2 XXX Fixme : shouldnt show [malformed frame] for long packets
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
11 * $Id: packet-smb-pipe.c,v 1.35 2001/09/14 07:10:05 guy Exp $
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@ethereal.com>
15 * Copyright 1998 Gerald Combs
17 * Copied from packet-pop.c
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.
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.
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.
40 #ifdef HAVE_SYS_TYPES_H
41 # include <sys/types.h>
44 #ifdef HAVE_NETINET_IN_H
45 # include <netinet/in.h>
53 #include "conversation.h"
55 #include "packet-smb-pipe.h"
56 #include "packet-smb-browse.h"
58 static int proto_smb_lanman = -1;
59 static int hf_function_code = -1;
60 static int hf_param_desc = -1;
61 static int hf_return_desc = -1;
62 static int hf_aux_data_desc = -1;
63 static int hf_detail_level = -1;
64 static int hf_recv_buf_len = -1;
65 static int hf_send_buf_len = -1;
66 static int hf_response_to = -1;
67 static int hf_continuation_from = -1;
68 static int hf_status = -1;
69 static int hf_convert = -1;
70 static int hf_ecount = -1;
71 static int hf_acount = -1;
72 static int hf_share_name = -1;
73 static int hf_share_type = -1;
74 static int hf_share_comment = -1;
75 static int hf_share_permissions = -1;
76 static int hf_share_max_uses = -1;
77 static int hf_share_current_uses = -1;
78 static int hf_share_path = -1;
79 static int hf_share_password = -1;
80 static int hf_server_name = -1;
81 static int hf_server_major = -1;
82 static int hf_server_minor = -1;
83 static int hf_server_comment = -1;
84 static int hf_abytes = -1;
85 static int hf_current_time = -1;
86 static int hf_msecs = -1;
87 static int hf_hour = -1;
88 static int hf_minute = -1;
89 static int hf_second = -1;
90 static int hf_hundredths = -1;
91 static int hf_tzoffset = -1;
92 static int hf_timeinterval = -1;
93 static int hf_day = -1;
94 static int hf_month = -1;
95 static int hf_year = -1;
96 static int hf_weekday = -1;
97 static int hf_enumeration_domain = -1;
98 static int hf_computer_name = -1;
99 static int hf_user_name = -1;
100 static int hf_workstation_domain = -1;
101 static int hf_workstation_major = -1;
102 static int hf_workstation_minor = -1;
103 static int hf_logon_domain = -1;
104 static int hf_other_domains = -1;
105 static int hf_password = -1;
106 static int hf_workstation_name = -1;
107 static int hf_ustruct_size = -1;
108 static int hf_logon_code = -1;
109 static int hf_privilege_level = -1;
110 static int hf_operator_privileges = -1;
111 static int hf_num_logons = -1;
112 static int hf_bad_pw_count = -1;
113 static int hf_last_logon = -1;
114 static int hf_last_logoff = -1;
115 static int hf_logoff_time = -1;
116 static int hf_kickoff_time = -1;
117 static int hf_password_age = -1;
118 static int hf_password_can_change = -1;
119 static int hf_password_must_change = -1;
120 static int hf_script_path = -1;
121 static int hf_logoff_code = -1;
122 static int hf_duration = -1;
123 static int hf_user_comment = -1;
124 static int hf_full_name = -1;
125 static int hf_homedir = -1;
126 static int hf_parameters = -1;
127 static int hf_logon_server = -1;
128 static int hf_country_code = -1;
129 static int hf_workstations = -1;
130 static int hf_max_storage = -1;
131 static int hf_units_per_week = -1;
132 static int hf_logon_hours = -1;
133 static int hf_code_page = -1;
134 static int hf_new_password = -1;
135 static int hf_old_password = -1;
136 static int hf_reserved = -1;
138 static gint ett_lanman = -1;
139 static gint ett_lanman_shares = -1;
140 static gint ett_lanman_share = -1;
141 static gint ett_lanman_servers = -1;
142 static gint ett_lanman_server = -1;
147 * ftp://ftp.microsoft.com/developr/drg/CIFS/cifsrap2.txt
149 * among other documents.
152 static const value_string status_vals[] = {
154 {5, "User has insufficient privilege"},
155 {65, "Network access is denied"},
156 {86, "The specified password is invalid"},
157 {SMBE_moredata, "Additional data is available"},
158 {2114, "Service is not running on the remote computer"},
159 {2123, "Supplied buffer is too small"},
160 {2141, "Server is not configured for transactions (IPC$ not shared)"},
161 {2212, "An error occurred while loading or running the logon script"},
162 {2214, "The logon was not validated by any server"},
163 {2217, "The logon server is running an older software version"},
164 {2221, "The user name was not found"},
165 {2240, "The user is not allowed to logon from this computer"},
166 {2241, "The user is not allowed to logon at this time"},
167 {2242, "The user password has expired"},
168 {2243, "The password cannot be changed"},
169 {2246, "The password is too short"},
173 static const value_string share_type_vals[] = {
174 {0, "Directory tree"},
175 {1, "Printer queue"},
176 {2, "Communications device"},
181 static const value_string privilege_vals[] = {
184 {2, "Administrator"},
188 static const value_string op_privilege_vals[] = {
189 {0, "Print operator"},
190 {1, "Communications operator"},
191 {2, "Server operator"},
192 {3, "Accounts operator"},
196 static const value_string weekday_vals[] = {
208 add_word_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
209 proto_tree *tree, int convert, int hf_index)
214 proto_tree_add_item(tree, hf_index, tvb, offset, 2, TRUE);
216 WParam = tvb_get_letohs(tvb, offset);
217 proto_tree_add_text(tree, tvb, offset, 2,
218 "Word Param: %u (0x%04X)", WParam, WParam);
225 add_dword_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
226 proto_tree *tree, int convert, int hf_index)
231 proto_tree_add_item(tree, hf_index, tvb, offset, 4, TRUE);
233 LParam = tvb_get_letohl(tvb, offset);
234 proto_tree_add_text(tree, tvb, offset, 4,
235 "Doubleword Param: %u (0x%08X)", LParam, LParam);
242 add_byte_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
243 proto_tree *tree, int convert, int hf_index)
248 proto_tree_add_item(tree, hf_index, tvb, offset, count, TRUE);
251 BParam = tvb_get_guint8(tvb, offset);
252 proto_tree_add_text(tree, tvb, offset, count,
253 "Byte Param: %u (0x%02X)",
256 proto_tree_add_text(tree, tvb, offset, count,
257 "Bytes Param: %s, type is wrong",
258 tvb_bytes_to_str(tvb, offset, count));
266 add_pad_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
267 proto_tree *tree, int convert, int hf_index)
270 * This is for parameters that have descriptor entries but that
271 * are, in practice, just padding.
278 add_null_pointer_param(tvbuff_t *tvb, int offset, int count,
279 packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
281 if (hf_index != -1) {
282 proto_tree_add_text(tree, tvb, offset, 0,
284 proto_registrar_get_name(hf_index));
286 proto_tree_add_text(tree, tvb, offset, 0,
287 "String Param (Null pointer)");
292 add_string_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
293 proto_tree *tree, int convert, int hf_index)
297 string_len = tvb_strsize(tvb, offset);
298 if (hf_index != -1) {
299 proto_tree_add_item(tree, hf_index, tvb, offset, string_len,
302 proto_tree_add_text(tree, tvb, offset, string_len,
304 tvb_format_text(tvb, offset, string_len));
306 offset += string_len;
311 get_pointer_value(tvbuff_t *tvb, int offset, int convert, int *cptrp, int *lenp)
316 /* pointer to string */
317 cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
321 if (tvb_offset_exists(tvb, cptr) &&
322 (string_len = tvb_strnlen(tvb, cptr, -1)) != -1) {
323 string_len++; /* include the terminating '\0' */
325 return tvb_format_text(tvb, offset, string_len);
331 add_pointer_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
332 proto_tree *tree, int convert, int hf_index)
338 string = get_pointer_value(tvb, offset, convert, &cptr, &string_len);
342 if (string != NULL) {
343 if (hf_index != -1) {
344 proto_tree_add_item(tree, hf_index, tvb, cptr,
347 proto_tree_add_text(tree, tvb, offset, string_len,
348 "String Param: %s", string);
351 if (hf_index != -1) {
352 proto_tree_add_text(tree, tvb, 0, 0,
353 "%s: <String goes past end of frame>",
354 proto_registrar_get_name(hf_index));
356 proto_tree_add_text(tree, tvb, 0, 0,
357 "String Param: <String goes past end of frame>");
365 add_detail_level(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
366 proto_tree *tree, int convert, int hf_index)
368 struct smb_info *smb_info = pinfo->private;
369 struct smb_request_val *request_val = smb_info->request_val;
372 level = tvb_get_letohs(tvb, offset);
373 if (!pinfo->fd->flags.visited)
374 request_val->last_level = level; /* remember this for the response */
375 proto_tree_add_uint(tree, hf_index, tvb, offset, 2, level);
381 add_max_uses(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
382 proto_tree *tree, int convert, int hf_index)
386 WParam = tvb_get_letohs(tvb, offset);
387 if (WParam == 0xffff) { /* -1 */
388 proto_tree_add_uint_format(tree, hf_index, tvb,
391 proto_registrar_get_name(hf_index));
393 proto_tree_add_uint(tree, hf_index, tvb,
401 add_server_type(tvbuff_t *tvb, int offset, int count,
402 packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
404 dissect_smb_server_type_flags(tvb, pinfo, tree, offset, FALSE);
410 add_server_type_info(tvbuff_t *tvb, int offset, int count,
411 packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
413 dissect_smb_server_type_flags(tvb, pinfo, tree, offset, TRUE);
419 add_reltime(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
420 proto_tree *tree, int convert, int hf_index)
424 nstime.secs = tvb_get_letohl(tvb, offset);
426 proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
427 &nstime, "%s: %s", proto_registrar_get_name(hf_index),
428 time_secs_to_str(nstime.secs));
434 * Sigh. These are for handling Microsoft's annoying almost-UNIX-time-but-
435 * it's-local-time-not-UTC time.
438 add_abstime_common(tvbuff_t *tvb, int offset, int count,
439 packet_info *pinfo, proto_tree *tree, int convert, int hf_index,
440 const char *absent_name)
445 nstime.secs = tvb_get_letohl(tvb, offset);
447 if (nstime.secs == -1) {
448 proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
449 &nstime, "%s: %s", proto_registrar_get_name(hf_index),
453 * Run it through "gmtime()" to break it down, and then
454 * run it through "mktime()" to put it back together
457 tmp = gmtime(&nstime.secs);
458 tmp->tm_isdst = -1; /* we don't know if it's DST or not */
459 nstime.secs = mktime(tmp);
460 proto_tree_add_time(tree, hf_index, tvb, offset, 4,
468 add_abstime_absent_never(tvbuff_t *tvb, int offset, int count,
469 packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
471 return add_abstime_common(tvb, offset, count, pinfo, tree,
472 convert, hf_index, "Never");
476 add_abstime_absent_unknown(tvbuff_t *tvb, int offset, int count,
477 packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
479 return add_abstime_common(tvb, offset, count, pinfo, tree,
480 convert, hf_index, "Unknown");
484 add_nlogons(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
485 proto_tree *tree, int convert, int hf_index)
489 nlogons = tvb_get_letohs(tvb, offset);
490 if (nlogons == 0xffff) /* -1 */
491 proto_tree_add_uint_format(tree, hf_index, tvb, offset, 2,
492 nlogons, "%s: Unknown",
493 proto_registrar_get_name(hf_index));
495 proto_tree_add_uint(tree, hf_index, tvb, offset, 2,
502 add_max_storage(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
503 proto_tree *tree, int convert, int hf_index)
507 max_storage = tvb_get_letohl(tvb, offset);
508 if (max_storage == 0xffffffff)
509 proto_tree_add_uint_format(tree, hf_index, tvb, offset, 4,
510 max_storage, "%s: No limit",
511 proto_registrar_get_name(hf_index));
513 proto_tree_add_uint(tree, hf_index, tvb, offset, 4,
520 add_logon_hours(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
521 proto_tree *tree, int convert, int hf_index)
525 /* pointer to string */
526 cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
530 /* XXX - should actually carve up the bits */
531 proto_tree_add_item(tree, hf_index, tvb, cptr, 21, TRUE);
537 add_tzoffset(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
538 proto_tree *tree, int convert, int hf_index)
542 tzoffset = tvb_get_letohs(tvb, offset);
544 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
545 tzoffset, "%s: %s east of UTC",
546 proto_registrar_get_name(hf_index),
547 time_secs_to_str(-tzoffset*60));
548 } else if (tzoffset > 0) {
549 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
550 tzoffset, "%s: %s west of UTC",
551 proto_registrar_get_name(hf_index),
552 time_secs_to_str(tzoffset*60));
554 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
555 tzoffset, "%s: at UTC",
556 proto_registrar_get_name(hf_index));
563 add_timeinterval(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
564 proto_tree *tree, int convert, int hf_index)
566 guint16 timeinterval;
568 timeinterval = tvb_get_letohs(tvb, offset);
569 proto_tree_add_uint_format(tree, hf_timeinterval, tvb, offset, 2,
570 timeinterval, "%s: %f seconds", proto_registrar_get_name(hf_index),
577 add_logon_args(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
578 proto_tree *tree, int convert, int hf_index)
581 proto_tree_add_text(tree, tvb, offset, count,
582 "Bogus NetWkstaUserLogon parameters: length is %d, should be 54",
589 proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
596 proto_tree_add_item(tree, hf_password, tvb, offset, 15, TRUE);
602 /* workstation name */
603 proto_tree_add_item(tree, hf_workstation_name, tvb, offset, 16, TRUE);
609 * The following data structure describes the Remote API requests we
612 * Simply fill in the number and parameter information.
613 * Try to keep them in order.
615 * We will extend this data structure as we try to decode more.
619 * This is a pointer to a function to process an item.
621 typedef int (*item_func)(tvbuff_t *, int, int, packet_info *, proto_tree *,
625 * Type of an item; determines what parameter strings are valid for
629 PARAM_NONE, /* for the end-of-list stopper */
630 PARAM_WORD, /* 'W' or 'h' - 16-bit word */
631 PARAM_DWORD, /* 'D' or 'i' - 32-bit word */
632 PARAM_BYTES, /* 'B' or 'b' or 'g' or 'O' - one or more bytes */
633 PARAM_STRINGZ, /* 'z' or 'O' - null-terminated string */
637 * This structure describes an item; "hf_index" points to the index
638 * for the field corresponding to that item, "func" points to the
639 * function to use to add that item to the tree, and "type" is the
640 * type that the item is supposed to have.
649 * This structure describes a list of items; each list of items
650 * has a corresponding detail level.
654 const item_t *item_list;
660 proto_item *(*req_data_item)(tvbuff_t *, packet_info *,
663 const item_t *req_data;
664 const item_t *req_aux_data;
666 proto_item *(*resp_data_item)(tvbuff_t *, packet_info *,
669 proto_item *(*resp_data_element_item)(tvbuff_t *, packet_info *,
671 gint *ett_resp_data_element_item;
672 const item_list_t *resp_data_list;
673 const item_t *resp_aux_data;
676 static int no_hf = -1; /* for padding crap */
678 static const item_t lm_params_req_netshareenum[] = {
679 { &hf_detail_level, add_detail_level, PARAM_WORD },
680 { &hf_recv_buf_len, add_word_param, PARAM_WORD },
681 { NULL, NULL, PARAM_NONE }
684 static const item_t lm_params_resp_netshareenum[] = {
685 { &hf_acount, add_word_param, PARAM_WORD },
686 { NULL, NULL, PARAM_NONE }
690 * Create a subtree for all available shares.
693 netshareenum_shares_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
697 return proto_tree_add_text(tree, tvb, offset,
698 tvb_length_remaining(tvb, offset),
705 * Create a subtree for a share.
708 netshareenum_share_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
712 return proto_tree_add_text(tree, tvb, offset,
713 tvb_length_remaining(tvb, offset),
714 "Share %.13s", tvb_get_ptr(tvb, offset, 13));
719 static const item_t lm_null[] = {
720 { NULL, NULL, PARAM_NONE }
723 static const item_list_t lm_null_list[] = {
727 static const item_t lm_data_resp_netshareenum_1[] = {
728 { &hf_share_name, add_byte_param, PARAM_BYTES },
729 { &no_hf, add_pad_param, PARAM_BYTES },
730 { &hf_share_type, add_word_param, PARAM_WORD },
731 { &hf_share_comment, add_pointer_param, PARAM_STRINGZ },
732 { NULL, NULL, PARAM_NONE }
735 static const item_list_t lm_data_resp_netshareenum[] = {
736 { 1, lm_data_resp_netshareenum_1 },
740 static const item_t lm_params_req_netsharegetinfo[] = {
741 { &hf_share_name, add_string_param, PARAM_STRINGZ },
742 { &hf_detail_level, add_detail_level, PARAM_WORD },
743 { NULL, NULL, PARAM_NONE }
746 static const item_t lm_params_resp_netsharegetinfo[] = {
747 { &hf_abytes, add_word_param, PARAM_WORD },
748 { NULL, NULL, PARAM_NONE }
751 static const item_t lm_data_resp_netsharegetinfo_0[] = {
752 { &hf_share_name, add_byte_param, PARAM_BYTES },
753 { NULL, NULL, PARAM_NONE }
756 static const item_t lm_data_resp_netsharegetinfo_1[] = {
757 { &hf_share_name, add_byte_param, PARAM_BYTES },
758 { &no_hf, add_pad_param, PARAM_BYTES },
759 { &hf_share_type, add_word_param, PARAM_WORD },
760 { &hf_share_comment, add_pointer_param, PARAM_STRINGZ },
761 { NULL, NULL, PARAM_NONE }
764 static const item_t lm_data_resp_netsharegetinfo_2[] = {
765 { &hf_share_name, add_byte_param, PARAM_BYTES },
766 { &no_hf, add_pad_param, PARAM_BYTES },
767 { &hf_share_type, add_word_param, PARAM_WORD },
768 { &hf_share_comment, add_pointer_param, PARAM_STRINGZ },
769 { &hf_share_permissions, add_word_param, PARAM_WORD }, /* XXX - do as bit fields */
770 { &hf_share_max_uses, add_max_uses, PARAM_WORD },
771 { &hf_share_current_uses, add_word_param, PARAM_WORD },
772 { &hf_share_path, add_pointer_param, PARAM_STRINGZ },
773 { &hf_share_password, add_byte_param, PARAM_BYTES },
774 { NULL, NULL, PARAM_NONE }
777 static const item_list_t lm_data_resp_netsharegetinfo[] = {
778 { 0, lm_data_resp_netsharegetinfo_0 },
779 { 1, lm_data_resp_netsharegetinfo_1 },
780 { 2, lm_data_resp_netsharegetinfo_2 },
784 static const item_t lm_params_req_netservergetinfo[] = {
785 { &hf_detail_level, add_detail_level, PARAM_WORD },
786 { NULL, NULL, PARAM_NONE }
789 static const item_t lm_params_resp_netservergetinfo[] = {
790 { &hf_abytes, add_word_param, PARAM_WORD },
791 { NULL, NULL, PARAM_NONE }
794 static const item_t lm_data_serverinfo_0[] = {
795 { &hf_server_name, add_byte_param, PARAM_BYTES },
796 { NULL, NULL, PARAM_NONE }
799 static const item_t lm_data_serverinfo_1[] = {
800 { &hf_server_name, add_byte_param, PARAM_BYTES },
801 { &hf_server_major, add_byte_param, PARAM_BYTES },
802 { &hf_server_minor, add_byte_param, PARAM_BYTES },
803 { &no_hf, add_server_type, PARAM_DWORD },
804 { &hf_server_comment, add_pointer_param, PARAM_STRINGZ },
805 { NULL, NULL, PARAM_NONE }
808 static const item_list_t lm_data_serverinfo[] = {
809 { 0, lm_data_serverinfo_0 },
810 { 1, lm_data_serverinfo_1 },
814 static const item_t lm_params_req_netusergetinfo[] = {
815 { &hf_detail_level, add_detail_level, PARAM_WORD },
816 { NULL, NULL, PARAM_NONE }
819 static const item_t lm_params_resp_netusergetinfo[] = {
820 { &hf_abytes, add_word_param, PARAM_WORD },
821 { NULL, NULL, PARAM_NONE }
824 static const item_t lm_data_resp_netusergetinfo_11[] = {
825 { &hf_user_name, add_byte_param, PARAM_BYTES },
826 { &no_hf, add_pad_param, PARAM_BYTES },
827 { &hf_user_comment, add_pointer_param, PARAM_STRINGZ },
828 { &hf_full_name, add_pointer_param, PARAM_STRINGZ },
829 { &hf_privilege_level, add_word_param, PARAM_WORD },
830 { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
831 { &hf_password_age, add_reltime, PARAM_DWORD },
832 { &hf_homedir, add_pointer_param, PARAM_STRINGZ },
833 { &hf_parameters, add_pointer_param, PARAM_STRINGZ },
834 { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
835 { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
836 { &hf_bad_pw_count, add_word_param, PARAM_WORD },
837 { &hf_num_logons, add_nlogons, PARAM_WORD },
838 { &hf_logon_server, add_pointer_param, PARAM_STRINGZ },
839 { &hf_country_code, add_word_param, PARAM_WORD },
840 { &hf_workstations, add_pointer_param, PARAM_STRINGZ },
841 { &hf_max_storage, add_max_storage, PARAM_DWORD },
842 { &hf_logon_hours, add_logon_hours, PARAM_DWORD },
843 { &hf_code_page, add_word_param, PARAM_WORD },
844 { NULL, NULL, PARAM_NONE }
847 static const item_list_t lm_data_resp_netusergetinfo[] = {
848 { 11, lm_data_resp_netusergetinfo_11 },
853 * Has no detail level; make it the default.
855 static const item_t lm_data_resp_netremotetod_nolevel[] = {
856 { &hf_current_time, add_abstime_absent_unknown, PARAM_DWORD },
857 { &hf_msecs, add_dword_param, PARAM_DWORD },
858 { &hf_hour, add_byte_param, PARAM_BYTES },
859 { &hf_minute, add_byte_param, PARAM_BYTES },
860 { &hf_second, add_byte_param, PARAM_BYTES },
861 { &hf_hundredths, add_byte_param, PARAM_BYTES },
862 { &hf_tzoffset, add_tzoffset, PARAM_WORD },
863 { &hf_timeinterval, add_timeinterval, PARAM_WORD },
864 { &hf_day, add_byte_param, PARAM_BYTES },
865 { &hf_month, add_byte_param, PARAM_BYTES },
866 { &hf_year, add_word_param, PARAM_WORD },
867 { &hf_weekday, add_byte_param, PARAM_BYTES },
868 { NULL, NULL, PARAM_NONE }
871 static const item_list_t lm_data_resp_netremotetod[] = {
872 { -1, lm_data_resp_netremotetod_nolevel },
875 static const item_t lm_params_req_netserverenum2[] = {
876 { &hf_detail_level, add_detail_level, PARAM_WORD },
877 { &no_hf, add_server_type_info, PARAM_DWORD },
878 { &hf_enumeration_domain, add_string_param, PARAM_STRINGZ },
879 { NULL, NULL, PARAM_NONE }
883 * Create a subtree for all servers.
886 netserverenum2_servers_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
890 return proto_tree_add_text(tree, tvb, offset,
891 tvb_length_remaining(tvb, offset), "Servers");
897 * Create a subtree for a share.
900 netserverenum2_server_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
904 return proto_tree_add_text(tree, tvb, offset,
905 tvb_length_remaining(tvb, offset),
906 "Server %.16s", tvb_get_ptr(tvb, offset, 16));
910 static const item_t lm_params_resp_netserverenum2[] = {
911 { &hf_acount, add_word_param, PARAM_WORD },
912 { NULL, NULL, PARAM_NONE }
915 static const item_t lm_params_req_netwkstagetinfo[] = {
916 { &hf_detail_level, add_detail_level, PARAM_WORD },
917 { NULL, NULL, PARAM_NONE }
920 static const item_t lm_params_resp_netwkstagetinfo[] = {
921 { &hf_abytes, add_word_param, PARAM_WORD },
922 { NULL, NULL, PARAM_NONE }
925 static const item_t lm_data_resp_netwkstagetinfo_10[] = {
926 { &hf_computer_name, add_pointer_param, PARAM_STRINGZ },
927 { &hf_user_name, add_pointer_param, PARAM_STRINGZ },
928 { &hf_workstation_domain, add_pointer_param, PARAM_STRINGZ },
929 { &hf_workstation_major, add_byte_param, PARAM_BYTES },
930 { &hf_workstation_minor, add_byte_param, PARAM_BYTES },
931 { &hf_logon_domain, add_pointer_param, PARAM_STRINGZ },
932 { &hf_other_domains, add_pointer_param, PARAM_STRINGZ },
933 { NULL, NULL, PARAM_NONE }
936 static const item_list_t lm_data_resp_netwkstagetinfo[] = {
937 { 10, lm_data_resp_netwkstagetinfo_10 },
941 static const item_t lm_params_req_netwkstauserlogon[] = {
942 { &no_hf, add_pointer_param, PARAM_STRINGZ },
943 { &no_hf, add_pointer_param, PARAM_STRINGZ },
944 { &hf_detail_level, add_detail_level, PARAM_WORD },
945 { &no_hf, add_logon_args, PARAM_BYTES },
946 { &hf_ustruct_size, add_word_param, PARAM_WORD },
947 { NULL, NULL, PARAM_NONE }
950 static const item_t lm_params_resp_netwkstauserlogon[] = {
951 { &hf_abytes, add_word_param, PARAM_WORD },
952 { NULL, NULL, PARAM_NONE }
955 static const item_t lm_data_resp_netwkstauserlogon_1[] = {
956 { &hf_logon_code, add_word_param, PARAM_WORD },
957 { &hf_user_name, add_byte_param, PARAM_BYTES },
958 { &no_hf, add_pad_param, PARAM_BYTES },
959 { &hf_privilege_level, add_word_param, PARAM_WORD },
960 { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
961 { &hf_num_logons, add_nlogons, PARAM_WORD },
962 { &hf_bad_pw_count, add_word_param, PARAM_WORD },
963 { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
964 { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
965 { &hf_logoff_time, add_abstime_absent_never, PARAM_DWORD },
966 { &hf_kickoff_time, add_abstime_absent_never, PARAM_DWORD },
967 { &hf_password_age, add_reltime, PARAM_DWORD },
968 { &hf_password_can_change, add_abstime_absent_never, PARAM_DWORD },
969 { &hf_password_must_change, add_abstime_absent_never, PARAM_DWORD },
970 { &hf_server_name, add_pointer_param, PARAM_STRINGZ },
971 { &hf_logon_domain, add_pointer_param, PARAM_STRINGZ },
972 { &hf_script_path, add_pointer_param, PARAM_STRINGZ },
973 { &hf_reserved, add_dword_param, PARAM_DWORD },
974 { NULL, NULL, PARAM_NONE }
977 static const item_list_t lm_data_resp_netwkstauserlogon[] = {
978 { 1, lm_data_resp_netwkstauserlogon_1 },
982 static const item_t lm_params_req_netwkstauserlogoff[] = {
983 { &hf_user_name, add_byte_param, PARAM_BYTES },
984 { &no_hf, add_pad_param, PARAM_BYTES },
985 { &hf_workstation_name, add_byte_param, PARAM_BYTES },
986 { NULL, NULL, PARAM_NONE }
989 static const item_t lm_params_resp_netwkstauserlogoff[] = {
990 { &hf_abytes, add_word_param, PARAM_WORD },
991 { NULL, NULL, PARAM_NONE }
994 static const item_t lm_data_resp_netwkstauserlogoff_1[] = {
995 { &hf_logoff_code, add_word_param, PARAM_WORD },
996 { &hf_duration, add_reltime, PARAM_DWORD },
997 { &hf_num_logons, add_nlogons, PARAM_WORD },
998 { NULL, NULL, PARAM_NONE }
1001 static const item_list_t lm_data_resp_netwkstauserlogoff[] = {
1002 { 1, lm_data_resp_netwkstauserlogoff_1 },
1006 static const item_t lm_params_req_samoemchangepassword[] = {
1007 { &hf_user_name, add_string_param, PARAM_STRINGZ },
1008 { NULL, NULL, PARAM_NONE }
1011 static const item_t lm_data_req_samoemchangepassword[] = {
1012 { &hf_new_password, add_byte_param, PARAM_BYTES },
1013 { &hf_old_password, add_byte_param, PARAM_BYTES },
1014 { NULL, NULL, PARAM_NONE }
1017 #define LANMAN_NETSHAREENUM 0
1018 #define LANMAN_NETSHAREGETINFO 1
1019 #define LANMAN_NETSERVERGETINFO 13
1020 #define LANMAN_NETGROUPGETUSERS 52
1021 #define LANMAN_NETUSERGETINFO 56
1022 #define LANMAN_NETUSERGETGROUPS 59
1023 #define LANMAN_NETWKSTAGETINFO 63
1024 #define LANMAN_DOSPRINTQENUM 69
1025 #define LANMAN_DOSPRINTQGETINFO 70
1026 #define LANMAN_WPRINTQUEUEPAUSE 74
1027 #define LANMAN_WPRINTQUEUERESUME 75
1028 #define LANMAN_WPRINTJOBENUMERATE 76
1029 #define LANMAN_WPRINTJOBGETINFO 77
1030 #define LANMAN_RDOSPRINTJOBDEL 81
1031 #define LANMAN_RDOSPRINTJOBPAUSE 82
1032 #define LANMAN_RDOSPRINTJOBRESUME 83
1033 #define LANMAN_WPRINTDESTENUM 84
1034 #define LANMAN_WPRINTDESTGETINFO 85
1035 #define LANMAN_NETREMOTETOD 91
1036 #define LANMAN_WPRINTQUEUEPURGE 103
1037 #define LANMAN_NETSERVERENUM2 104
1038 #define LANMAN_WACCESSGETUSERPERMS 105
1039 #define LANMAN_SETUSERPASSWORD 115
1040 #define LANMAN_NETWKSTAUSERLOGON 132
1041 #define LANMAN_NETWKSTAUSERLOGOFF 133
1042 #define LANMAN_PRINTJOBINFO 147
1043 #define LANMAN_WPRINTDRIVERENUM 205
1044 #define LANMAN_WPRINTQPROCENUM 206
1045 #define LANMAN_WPRINTPORTENUM 207
1046 #define LANMAN_SAMOEMCHANGEPASSWORD 214
1048 static const struct lanman_desc lmd[] = {
1049 { LANMAN_NETSHAREENUM,
1050 lm_params_req_netshareenum,
1055 lm_params_resp_netshareenum,
1056 netshareenum_shares_list,
1058 netshareenum_share_entry,
1060 lm_data_resp_netshareenum,
1063 { LANMAN_NETSHAREGETINFO,
1064 lm_params_req_netsharegetinfo,
1069 lm_params_resp_netsharegetinfo,
1074 lm_data_resp_netsharegetinfo,
1077 { LANMAN_NETSERVERGETINFO,
1078 lm_params_req_netservergetinfo,
1083 lm_params_resp_netservergetinfo,
1091 { LANMAN_NETUSERGETINFO,
1092 lm_params_req_netusergetinfo,
1097 lm_params_resp_netusergetinfo,
1102 lm_data_resp_netusergetinfo,
1105 { LANMAN_NETREMOTETOD,
1116 lm_data_resp_netremotetod,
1119 { LANMAN_NETSERVERENUM2,
1120 lm_params_req_netserverenum2,
1125 lm_params_resp_netserverenum2,
1126 netserverenum2_servers_list,
1127 &ett_lanman_servers,
1128 netserverenum2_server_entry,
1133 { LANMAN_NETWKSTAGETINFO,
1134 lm_params_req_netwkstagetinfo,
1139 lm_params_resp_netwkstagetinfo,
1144 lm_data_resp_netwkstagetinfo,
1147 { LANMAN_NETWKSTAUSERLOGON,
1148 lm_params_req_netwkstauserlogon,
1153 lm_params_resp_netwkstauserlogon,
1158 lm_data_resp_netwkstauserlogon,
1161 { LANMAN_NETWKSTAUSERLOGOFF,
1162 lm_params_req_netwkstauserlogoff,
1167 lm_params_resp_netwkstauserlogoff,
1172 lm_data_resp_netwkstauserlogoff,
1175 { LANMAN_SAMOEMCHANGEPASSWORD,
1176 lm_params_req_samoemchangepassword,
1179 lm_data_req_samoemchangepassword,
1204 static const struct lanman_desc *
1205 find_lanman(int lanman_num)
1209 for (i = 0; lmd[i].lanman_num != -1; i++) {
1210 if (lmd[i].lanman_num == lanman_num)
1216 static const guchar *
1217 get_count(const guchar *desc, int *countp)
1219 int count = 0, off = 0;
1222 if (!isdigit(*desc)) {
1223 *countp = 1; /* no count was supplied */
1227 while ((c = *desc) != '\0' && isdigit(c)) {
1228 count = (count * 10) + c - '0';
1232 *countp = count; /* XXX - what if it's 0? */
1237 dissect_request_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
1238 proto_tree *tree, const guchar *desc, const item_t *items,
1239 gboolean *has_data_p)
1247 *has_data_p = FALSE;
1248 while ((c = *desc++) != '\0') {
1253 * A 16-bit word value in the request.
1255 if (items->func == NULL) {
1257 * We've run out of items in the table;
1258 * fall back on the default.
1260 offset = add_word_param(tvb, offset, 0, pinfo,
1262 } else if (items->type != PARAM_WORD) {
1264 * Descriptor character is 'W', but this
1265 * isn't a word parameter.
1267 WParam = tvb_get_letohs(tvb, offset);
1268 proto_tree_add_text(tree, tvb, offset, 2,
1269 "%s: Value is %u (0x%04X), type is wrong (W)",
1270 (*items->hf_index == -1) ?
1272 proto_registrar_get_name(*items->hf_index),
1277 offset = (*items->func)(tvb, offset, 0, pinfo,
1278 tree, 0, *items->hf_index);
1285 * A 32-bit doubleword value in the request.
1287 if (items->func == NULL) {
1289 * We've run out of items in the table;
1290 * fall back on the default.
1292 offset = add_dword_param(tvb, offset, 0, pinfo,
1294 } else if (items->type != PARAM_DWORD) {
1296 * Descriptor character is 'D', but this
1297 * isn't a doubleword parameter.
1299 LParam = tvb_get_letohl(tvb, offset);
1300 proto_tree_add_text(tree, tvb, offset, 2,
1301 "%s: Value is %u (0x%08X), type is wrong (D)",
1302 (*items->hf_index == -1) ?
1303 "Doubleword Param" :
1304 proto_registrar_get_name(*items->hf_index),
1309 offset = (*items->func)(tvb, offset, 0, pinfo,
1310 tree, 0, *items->hf_index);
1317 * A byte or multi-byte value in the request.
1319 desc = get_count(desc, &count);
1320 if (items->func == NULL) {
1322 * We've run out of items in the table;
1323 * fall back on the default.
1325 offset = add_byte_param(tvb, offset, count,
1326 pinfo, tree, 0, -1);
1327 } else if (items->type != PARAM_BYTES) {
1329 * Descriptor character is 'b', but this
1330 * isn't a byte/bytes parameter.
1332 proto_tree_add_text(tree, tvb, offset, count,
1333 "%s: Value is %s, type is wrong (b)",
1334 (*items->hf_index == -1) ?
1336 proto_registrar_get_name(*items->hf_index),
1337 tvb_bytes_to_str(tvb, offset, count));
1341 offset = (*items->func)(tvb, offset, count,
1342 pinfo, tree, 0, *items->hf_index);
1351 if (items->func == NULL) {
1353 * We've run out of items in the table;
1354 * fall back on the default.
1356 add_null_pointer_param(tvb, offset, 0,
1357 pinfo, tree, 0, -1);
1360 * If "*items->hf_index" is -1, this is
1361 * a reserved must-be-null field; don't
1362 * clutter the protocol tree by putting
1365 if (*items->hf_index != -1) {
1366 add_null_pointer_param(tvb,
1367 offset, 0, pinfo, tree, 0,
1376 * A null-terminated ASCII string.
1378 if (items->func == NULL) {
1380 * We've run out of items in the table;
1381 * fall back on the default.
1383 offset = add_string_param(tvb, offset, 0,
1384 pinfo, tree, 0, -1);
1385 } else if (items->type != PARAM_STRINGZ) {
1387 * Descriptor character is 'z', but this
1388 * isn't a string parameter.
1390 string_len = tvb_strsize(tvb, offset);
1391 proto_tree_add_text(tree, tvb, offset, string_len,
1392 "%s: Value is %s, type is wrong (z)",
1393 (*items->hf_index == -1) ?
1395 proto_registrar_get_name(*items->hf_index),
1396 tvb_format_text(tvb, offset, string_len));
1397 offset += string_len;
1400 offset = (*items->func)(tvb, offset, 0,
1401 pinfo, tree, 0, *items->hf_index);
1408 * One or more pad bytes.
1410 desc = get_count(desc, &count);
1411 proto_tree_add_text(tree, tvb, offset, count,
1418 * 16-bit receive buffer length.
1420 proto_tree_add_item(tree, hf_recv_buf_len, tvb,
1427 * 32-bit send buffer offset.
1428 * XXX - is there actually a pointer here?
1429 * I suspect not. It looks like junk.
1432 LParam = tvb_get_letohl(tvb, offset);
1433 proto_tree_add_text(tree, tvb, offset, 4,
1434 "%s: %u", "Send Buffer Ptr", LParam);
1440 * 16-bit send buffer length.
1442 proto_tree_add_item(tree, hf_send_buf_len, tvb,
1455 dissect_response_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
1456 proto_tree *tree, const guchar *desc, const item_t *items,
1457 gboolean *has_data_p, gboolean *has_ent_count_p, guint16 *ent_count_p)
1464 *has_data_p = FALSE;
1465 *has_ent_count_p = FALSE;
1466 while ((c = *desc++) != '\0') {
1471 * 32-bit receive buffer offset.
1478 * A byte or series of bytes is returned.
1480 desc = get_count(desc, &count);
1481 if (items->func == NULL) {
1483 * We've run out of items in the table;
1484 * fall back on the default.
1486 offset = add_byte_param(tvb, offset, count,
1487 pinfo, tree, 0, -1);
1488 } else if (items->type != PARAM_BYTES) {
1490 * Descriptor character is 'b', but this
1491 * isn't a byte/bytes parameter.
1493 proto_tree_add_text(tree, tvb, offset, count,
1494 "%s: Value is %s, type is wrong (g)",
1495 (*items->hf_index == -1) ?
1497 proto_registrar_get_name(*items->hf_index),
1498 tvb_bytes_to_str(tvb, offset, count));
1502 offset = (*items->func)(tvb, offset, count,
1503 pinfo, tree, 0, *items->hf_index);
1510 * A 16-bit word is received.
1512 if (items->func == NULL) {
1514 * We've run out of items in the table;
1515 * fall back on the default.
1517 offset = add_word_param(tvb, offset, 0, pinfo,
1519 } else if (items->type != PARAM_WORD) {
1521 * Descriptor character is 'h', but this
1522 * isn't a word parameter.
1524 WParam = tvb_get_letohs(tvb, offset);
1525 proto_tree_add_text(tree, tvb, offset, 2,
1526 "%s: Value is %u (0x%04X), type is wrong (W)",
1527 (*items->hf_index == -1) ?
1529 proto_registrar_get_name(*items->hf_index),
1534 offset = (*items->func)(tvb, offset, 0, pinfo,
1535 tree, 0, *items->hf_index);
1542 * A 32-bit doubleword is received.
1544 if (items->func == NULL) {
1546 * We've run out of items in the table;
1547 * fall back on the default.
1549 offset = add_dword_param(tvb, offset, 0, pinfo,
1551 } else if (items->type != PARAM_DWORD) {
1553 * Descriptor character is 'i', but this
1554 * isn't a doubleword parameter.
1556 LParam = tvb_get_letohl(tvb, offset);
1557 proto_tree_add_text(tree, tvb, offset, 2,
1558 "%s: Value is %u (0x%08X), type is wrong (i)",
1559 (*items->hf_index == -1) ?
1560 "Doubleword Param" :
1561 proto_registrar_get_name(*items->hf_index),
1566 offset = (*items->func)(tvb, offset, 0, pinfo,
1567 tree, 0, *items->hf_index);
1574 * A 16-bit entry count is returned.
1576 WParam = tvb_get_letohs(tvb, offset);
1577 proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2,
1580 *has_ent_count_p = TRUE;
1581 *ent_count_p = WParam; /* Save this for later retrieval */
1592 dissect_transact_data(tvbuff_t *tvb, int offset, int convert,
1593 packet_info *pinfo, proto_tree *tree, const guchar *desc,
1594 const item_t *items, guint16 *aux_count_p)
1605 while ((c = *desc++) != '\0') {
1610 * A 16-bit word value.
1611 * XXX - handle the count?
1613 desc = get_count(desc, &count);
1614 if (items->func == NULL) {
1616 * We've run out of items in the table;
1617 * fall back on the default.
1619 offset = add_word_param(tvb, offset, 0, pinfo,
1621 } else if (items->type != PARAM_WORD) {
1623 * Descriptor character is 'W', but this
1624 * isn't a word parameter.
1626 WParam = tvb_get_letohs(tvb, offset);
1627 proto_tree_add_text(tree, tvb, offset, 2,
1628 "%s: Value is %u (0x%04X), type is wrong (W)",
1629 (*items->hf_index == -1) ?
1631 proto_registrar_get_name(*items->hf_index),
1636 offset = (*items->func)(tvb, offset, 0, pinfo,
1637 tree, convert, *items->hf_index);
1644 * A 32-bit doubleword value.
1645 * XXX - handle the count?
1647 desc = get_count(desc, &count);
1648 if (items->func == NULL) {
1650 * We've run out of items in the table;
1651 * fall back on the default.
1653 offset = add_dword_param(tvb, offset, 0, pinfo,
1655 } else if (items->type != PARAM_DWORD) {
1657 * Descriptor character is 'D', but this
1658 * isn't a doubleword parameter.
1660 LParam = tvb_get_letohl(tvb, offset);
1661 proto_tree_add_text(tree, tvb, offset, 2,
1662 "%s: Value is %u (0x%08X), type is wrong (D)",
1663 (*items->hf_index == -1) ?
1664 "Doubleword Param" :
1665 proto_registrar_get_name(*items->hf_index),
1670 offset = (*items->func)(tvb, offset, 0, pinfo,
1671 tree, convert, *items->hf_index);
1678 * A byte or multi-byte value.
1680 desc = get_count(desc, &count);
1681 if (items->func == NULL) {
1683 * We've run out of items in the table;
1684 * fall back on the default.
1686 offset = add_byte_param(tvb, offset, count,
1687 pinfo, tree, convert, -1);
1688 } else if (items->type != PARAM_BYTES) {
1690 * Descriptor character is 'B', but this
1691 * isn't a byte/bytes parameter.
1693 proto_tree_add_text(tree, tvb, offset, count,
1694 "%s: Value is %s, type is wrong (B)",
1695 (*items->hf_index == -1) ?
1697 proto_registrar_get_name(*items->hf_index),
1698 tvb_bytes_to_str(tvb, offset, count));
1702 offset = (*items->func)(tvb, offset, count,
1703 pinfo, tree, convert, *items->hf_index);
1712 if (items->func == NULL) {
1714 * We've run out of items in the table;
1715 * fall back on the default.
1717 add_null_pointer_param(tvb, offset, 0,
1718 pinfo, tree, convert, -1);
1721 * If "*items->hf_index" is -1, this is
1722 * a reserved must-be-null field; don't
1723 * clutter the protocol tree by putting
1726 if (*items->hf_index != -1) {
1727 add_null_pointer_param(tvb,
1728 offset, 0, pinfo, tree, convert,
1737 * A pointer to a null-terminated ASCII string.
1739 if (items->func == NULL) {
1741 * We've run out of items in the table;
1742 * fall back on the default.
1744 offset = add_pointer_param(tvb, offset, 0,
1745 pinfo, tree, convert, -1);
1746 } else if (items->type != PARAM_STRINGZ) {
1748 * Descriptor character is 'z', but this
1749 * isn't a string parameter.
1751 string = get_pointer_value(tvb, offset,
1752 convert, &cptr, &string_len);
1754 proto_tree_add_text(tree, tvb, cptr, string_len,
1755 "%s: Value is %s, type is wrong (z)",
1756 (*items->hf_index == -1) ?
1758 proto_registrar_get_name(*items->hf_index),
1762 offset = (*items->func)(tvb, offset, 0,
1763 pinfo, tree, convert, *items->hf_index);
1770 * 16-bit auxiliary data structure count.
1773 WParam = tvb_get_letohs(tvb, offset);
1774 proto_tree_add_text(tree, tvb, offset, 2,
1776 "Auxiliary data structure count",
1779 if (aux_count_p != NULL)
1780 *aux_count_p = WParam; /* Save this for later retrieval */
1790 static const value_string commands[] = {
1791 {LANMAN_NETSHAREENUM, "NetShareEnum"},
1792 {LANMAN_NETSHAREGETINFO, "NetShareGetInfo"},
1793 {LANMAN_NETSERVERGETINFO, "NetServerGetInfo"},
1794 {LANMAN_NETGROUPGETUSERS, "NetGroupGetUsers"},
1795 {LANMAN_NETUSERGETINFO, "NetUserGetInfo"},
1796 {LANMAN_NETUSERGETGROUPS, "NetUserGetGroups"},
1797 {LANMAN_NETWKSTAGETINFO, "NetWkstaGetInfo"},
1798 {LANMAN_DOSPRINTQENUM, "DOSPrintQEnum"},
1799 {LANMAN_DOSPRINTQGETINFO, "DOSPrintQGetInfo"},
1800 {LANMAN_WPRINTQUEUEPAUSE, "WPrintQueuePause"},
1801 {LANMAN_WPRINTQUEUERESUME, "WPrintQueueResume"},
1802 {LANMAN_WPRINTJOBENUMERATE, "WPrintJobEnumerate"},
1803 {LANMAN_WPRINTJOBGETINFO, "WPrintJobGetInfo"},
1804 {LANMAN_RDOSPRINTJOBDEL, "RDOSPrintJobDel"},
1805 {LANMAN_RDOSPRINTJOBPAUSE, "RDOSPrintJobPause"},
1806 {LANMAN_RDOSPRINTJOBRESUME, "RDOSPrintJobResume"},
1807 {LANMAN_WPRINTDESTENUM, "WPrintDestEnum"},
1808 {LANMAN_WPRINTDESTGETINFO, "WPrintDestGetInfo"},
1809 {LANMAN_NETREMOTETOD, "NetRemoteTOD"},
1810 {LANMAN_WPRINTQUEUEPURGE, "WPrintQueuePurge"},
1811 {LANMAN_NETSERVERENUM2, "NetServerEnum2"},
1812 {LANMAN_WACCESSGETUSERPERMS, "WAccessGetUserPerms"},
1813 {LANMAN_SETUSERPASSWORD, "SetUserPassword"},
1814 {LANMAN_NETWKSTAUSERLOGON, "NetWkstaUserLogon"},
1815 {LANMAN_NETWKSTAUSERLOGOFF, "NetWkstaUserLogoff"},
1816 {LANMAN_PRINTJOBINFO, "PrintJobInfo"},
1817 {LANMAN_WPRINTDRIVERENUM, "WPrintDriverEnum"},
1818 {LANMAN_WPRINTQPROCENUM, "WPrintQProcEnum"},
1819 {LANMAN_WPRINTPORTENUM, "WPrintPortEnum"},
1820 {LANMAN_SAMOEMCHANGEPASSWORD, "SamOEMChangePassword"},
1825 dissect_pipe_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1827 struct smb_info *smb_info = pinfo->private;
1828 struct smb_request_val *request_val = smb_info->request_val;
1829 int parameter_count = smb_info->parameter_count;
1830 int offset = 0, start_offset;
1834 const struct lanman_desc *lanman;
1835 proto_item *item = NULL;
1836 proto_tree *tree = NULL;
1837 guint descriptor_len;
1838 const gchar *param_descrip, *data_descrip, *aux_data_descrip = NULL;
1840 gboolean has_ent_count;
1841 guint16 ent_count, aux_count;
1843 const item_list_t *resp_data_list;
1844 const item_t *resp_data;
1845 proto_item *data_item;
1846 proto_tree *data_tree;
1847 proto_item *entry_item;
1848 proto_tree *entry_tree;
1850 if (check_col(pinfo->fd, COL_PROTOCOL)) {
1851 col_set_str(pinfo->fd, COL_PROTOCOL, "LANMAN");
1855 item = proto_tree_add_item(parent_tree, proto_smb_lanman,
1856 tvb, 0, tvb_length(tvb), FALSE);
1857 tree = proto_item_add_subtree(item, ett_lanman);
1861 * Don't try to decode continuation messages.
1863 * XXX - at some point, we will probably be handed tvbuffs
1864 * for the parameters of the first message and for the
1865 * reassembled contents of the data of the first message
1866 * and all the continuations, and should dissect it.
1868 * Transaction reassembly may, however, be an option, so that if
1869 * we don't *have* all the reply messages, you at least can
1870 * see what you have, by turning the option off. (We don't know
1871 * that we don't have them until we get to the end of the capture,
1872 * but, by that time, it may be too late to dissect what we have;
1873 * in Tethereal, for example, there's no going back....)
1875 if (smb_info->ddisp) {
1876 if (check_col(pinfo->fd, COL_INFO)) {
1877 col_set_str(pinfo->fd, COL_INFO, "Transact Continuation");
1879 if (smb_info->continuation_val != NULL) {
1880 /* continuation from the message in frame xx */
1881 proto_tree_add_uint(tree, hf_continuation_from, tvb,
1882 0, 0, smb_info->continuation_val->frame);
1884 proto_tree_add_text(tree, tvb, 0, tvb_length(tvb),
1885 "Continuation data");
1889 if (smb_info->request) { /* this is a request */
1891 cmd = tvb_get_letohs(tvb, offset);
1892 if (check_col(pinfo->fd, COL_INFO)) {
1893 col_add_fstr(pinfo->fd, COL_INFO, "%s Request", val_to_str(cmd, commands, "Unknown Command:0x%02x"));
1895 proto_tree_add_uint(tree, hf_function_code, tvb, offset, 2,
1898 parameter_count -= 2;
1901 * If we haven't already done so, save the function code in
1902 * the structure we were handed, so that it's available to
1903 * the code parsing the reply, and initialize the detail
1904 * level to -1, meaning "unknown".
1906 if (!pinfo->fd->flags.visited) {
1907 request_val->last_lanman_cmd = cmd;
1908 request_val->last_level = -1;
1911 /* parameter descriptor */
1912 descriptor_len = tvb_strsize(tvb, offset);
1913 proto_tree_add_item(tree, hf_param_desc, tvb, offset,
1914 descriptor_len, TRUE);
1915 param_descrip = tvb_get_ptr(tvb, offset, descriptor_len);
1916 if (!pinfo->fd->flags.visited) {
1918 * Save the parameter descriptor for future use.
1920 g_assert(request_val->last_param_descrip == NULL);
1921 request_val->last_param_descrip = g_strdup(param_descrip);
1923 offset += descriptor_len;
1924 parameter_count -= descriptor_len;
1926 /* return descriptor */
1927 descriptor_len = tvb_strsize(tvb, offset);
1928 proto_tree_add_item(tree, hf_return_desc, tvb, offset,
1929 descriptor_len, TRUE);
1930 data_descrip = tvb_get_ptr(tvb, offset, descriptor_len);
1931 if (!pinfo->fd->flags.visited) {
1933 * Save the return descriptor for future use.
1935 g_assert(request_val->last_data_descrip == NULL);
1936 request_val->last_data_descrip = g_strdup(data_descrip);
1938 offset += descriptor_len;
1939 parameter_count -= descriptor_len;
1941 lanman = find_lanman(cmd);
1943 /* request parameters */
1944 start_offset = offset;
1945 offset = dissect_request_parameters(tvb, offset, pinfo, tree,
1946 param_descrip, lanman->req, &has_data);
1947 parameter_count -= offset - start_offset;
1949 /* auxiliary data descriptor */
1950 if (parameter_count > 0) {
1952 * There are more parameters left, so the next
1953 * item is the auxiliary data descriptor.
1955 descriptor_len = tvb_strsize(tvb, offset);
1956 proto_tree_add_item(tree, hf_return_desc, tvb, offset,
1957 descriptor_len, TRUE);
1958 aux_data_descrip = tvb_get_ptr(tvb, offset, descriptor_len);
1959 if (!pinfo->fd->flags.visited) {
1961 * Save the auxiliary data descriptor for
1964 g_assert(request_val->last_aux_data_descrip == NULL);
1965 request_val->last_aux_data_descrip =
1966 g_strdup(aux_data_descrip);
1968 offset += descriptor_len;
1971 if (has_data && smb_info->data_count != 0) {
1973 * There's a send buffer item in the descriptor
1974 * string, and the data count in the transaction
1975 * is non-zero, so there's data to dissect.
1977 * XXX - should we just check "smb_info->data_count"?
1980 offset = smb_info->data_offset;
1981 if (lanman->req_data_item != NULL) {
1983 * Create a protocol tree item for the data.
1985 data_item = (*lanman->req_data_item)(tvb,
1986 pinfo, tree, offset);
1987 data_tree = proto_item_add_subtree(data_item,
1988 *lanman->ett_req_data);
1991 * Just leave it at the top level.
1998 offset = dissect_transact_data(tvb, offset, -1,
1999 pinfo, data_tree, data_descrip, lanman->req_data,
2000 &aux_count); /* XXX - what about strings? */
2002 /* auxiliary data */
2003 if (aux_data_descrip != NULL) {
2004 for (i = 0; i < aux_count; i++) {
2005 offset = dissect_transact_data(tvb,
2006 offset, -1, pinfo, data_tree,
2008 lanman->req_aux_data, NULL);
2012 if (data_item != NULL) {
2014 * Set the length of the protocol tree item
2017 proto_item_set_len(data_item,
2018 offset - smb_info->data_offset);
2023 * This is a response.
2024 * Have we seen the request to which it's a response?
2026 if (request_val == NULL)
2027 return FALSE; /* no - can't dissect it */
2029 /* ok we have seen this one before */
2031 /* response to the request in frame xx */
2032 proto_tree_add_uint(tree, hf_response_to, tvb, 0, 0,
2033 request_val->frame);
2035 if (check_col(pinfo->fd, COL_INFO)) {
2036 col_add_fstr(pinfo->fd, COL_INFO, "%s %sResponse",
2037 val_to_str(request_val->last_lanman_cmd, commands, "Unknown Command (0x%02x)"),
2038 smb_info->is_interim_response ? "Interim " : "");
2040 proto_tree_add_uint(tree, hf_function_code, tvb, 0, 0,
2041 request_val->last_lanman_cmd);
2043 if (smb_info->is_interim_response)
2044 return TRUE; /* no data to dissect */
2046 lanman = find_lanman(request_val->last_lanman_cmd);
2048 /* response parameters */
2051 status = tvb_get_letohs(tvb, offset);
2052 proto_tree_add_uint(tree, hf_status, tvb, offset, 2, status);
2056 convert = tvb_get_letohs(tvb, offset);
2057 proto_tree_add_uint(tree, hf_convert, tvb, offset, 2, convert);
2061 * "convert" is relative to the beginning of the data
2062 * area, but we're handed a tvbuff that starts at the
2063 * beginning of the parameter area, so we need to
2064 * add "smb_info->data_offset" to offsets after
2065 * subtracting "convert"; subtract it from "convert"
2066 * so that it gets added in for free.
2068 convert -= smb_info->data_offset;
2070 /* rest of the parameters */
2071 offset = dissect_response_parameters(tvb, offset, pinfo, tree,
2072 request_val->last_param_descrip, lanman->resp, &has_data,
2073 &has_ent_count, &ent_count);
2076 if (has_data && smb_info->data_count != 0) {
2078 * There's a receive buffer item in the descriptor
2079 * string, and the data count in the transaction
2080 * is non-zero, so there's data to dissect.
2082 * XXX - should we just check "smb_info->data_count"?
2086 * Find the item table for the matching request's
2089 for (resp_data_list = lanman->resp_data_list;
2090 resp_data_list->level != -1; resp_data_list++) {
2091 if (resp_data_list->level == request_val->last_level)
2094 resp_data = resp_data_list->item_list;
2096 offset = smb_info->data_offset;
2097 if (lanman->resp_data_item != NULL) {
2099 * Create a protocol tree item for the data.
2101 data_item = (*lanman->resp_data_item)(tvb,
2102 pinfo, tree, offset);
2103 data_tree = proto_item_add_subtree(data_item,
2104 *lanman->ett_resp_data);
2107 * Just leave it at the top level.
2114 * If we have an entry count, show all the entries,
2115 * with each one having a protocol tree item.
2117 * Otherwise, we just show one returned item, with
2118 * no protocol tree item.
2122 for (i = 0; i < ent_count; i++) {
2123 start_offset = offset;
2124 if (has_ent_count) {
2126 * Create a protocol tree item for the
2130 (*lanman->resp_data_element_item)
2131 (tvb, pinfo, data_tree, offset);
2132 entry_tree = proto_item_add_subtree(
2134 *lanman->ett_resp_data_element_item);
2137 * Just leave it at the current
2141 entry_tree = data_tree;
2144 offset = dissect_transact_data(tvb, offset,
2145 convert, pinfo, entry_tree,
2146 request_val->last_data_descrip,
2147 resp_data, &aux_count);
2149 /* auxiliary data */
2150 if (request_val->last_aux_data_descrip != NULL) {
2151 for (j = 0; j < aux_count; j++) {
2152 offset = dissect_transact_data(
2153 tvb, offset, convert,
2155 request_val->last_data_descrip,
2156 lanman->resp_aux_data, NULL);
2160 if (entry_item != NULL) {
2162 * Set the length of the protocol tree
2163 * item for the entry.
2165 proto_item_set_len(entry_item,
2166 offset - start_offset);
2170 if (data_item != NULL) {
2172 * Set the length of the protocol tree item
2175 proto_item_set_len(data_item,
2176 offset - smb_info->data_offset);
2187 dissect_pipe_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2189 struct smb_info *smb_info = pinfo->private;
2191 if (!proto_is_protocol_enabled(proto_smb_lanman))
2193 pinfo->current_proto = "LANMAN";
2195 if (smb_info->trans_cmd && strcmp(smb_info->trans_cmd, "LANMAN") == 0) {
2196 /* Try to decode a LANMAN */
2198 return dissect_pipe_lanman(tvb, pinfo, tree);
2205 register_proto_smb_pipe(void)
2207 static hf_register_info hf[] = {
2208 { &hf_function_code,
2209 { "Function Code", "lanman.function_code", FT_UINT16, BASE_DEC,
2210 VALS(commands), 0, "LANMAN Function Code/Command", HFILL }},
2213 { "Parameter Descriptor", "lanman.param_desc", FT_STRING, BASE_NONE,
2214 NULL, 0, "LANMAN Parameter Descriptor", HFILL }},
2217 { "Return Descriptor", "lanman.ret_desc", FT_STRING, BASE_NONE,
2218 NULL, 0, "LANMAN Return Descriptor", HFILL }},
2220 { &hf_aux_data_desc,
2221 { "Auxiliary Data Descriptor", "lanman.aux_data_desc", FT_STRING, BASE_NONE,
2222 NULL, 0, "LANMAN Auxiliary Data Descriptor", HFILL }},
2225 { "Detail Level", "lanman.level", FT_UINT16, BASE_DEC,
2226 NULL, 0, "LANMAN Detail Level", HFILL }},
2229 { "Receive Buffer Length", "lanman.recv_buf_len", FT_UINT16, BASE_DEC,
2230 NULL, 0, "LANMAN Receive Buffer Length", HFILL }},
2233 { "Send Buffer Length", "lanman.send_buf_len", FT_UINT16, BASE_DEC,
2234 NULL, 0, "LANMAN Send Buffer Length", HFILL }},
2237 { "Response to request in frame", "lanman.response_to", FT_UINT32, BASE_DEC,
2238 NULL, 0, "This is a LANMAN response to the request in the frame in question", HFILL }},
2240 { &hf_continuation_from,
2241 { "Continuation from message in frame", "lanman.continuation_from", FT_UINT32, BASE_DEC,
2242 NULL, 0, "This is a LANMAN continuation from the message in the frame in question", HFILL }},
2245 { "Status", "lanman.status", FT_UINT16, BASE_DEC,
2246 VALS(status_vals), 0, "LANMAN Return status", HFILL }},
2249 { "Convert", "lanman.convert", FT_UINT16, BASE_DEC,
2250 NULL, 0, "LANMAN Convert", HFILL }},
2253 { "Entry Count", "lanman.entry_count", FT_UINT16, BASE_DEC,
2254 NULL, 0, "LANMAN Number of Entries", HFILL }},
2257 { "Available Entries", "lanman.available_count", FT_UINT16, BASE_DEC,
2258 NULL, 0, "LANMAN Number of Available Entries", HFILL }},
2261 { "Share Name", "lanman.share.name", FT_STRING, BASE_NONE,
2262 NULL, 0, "LANMAN Name of Share", HFILL }},
2265 { "Share Type", "lanman.share.type", FT_UINT16, BASE_DEC,
2266 VALS(share_type_vals), 0, "LANMAN Type of Share", HFILL }},
2268 { &hf_share_comment,
2269 { "Share Comment", "lanman.share.comment", FT_STRING, BASE_NONE,
2270 NULL, 0, "LANMAN Share Comment", HFILL }},
2272 { &hf_share_permissions,
2273 { "Share Permissions", "lanman.share.permissions", FT_UINT16, BASE_DEC,
2274 NULL, 0, "LANMAN Permissions on share", HFILL }},
2276 { &hf_share_max_uses,
2277 { "Share Max Uses", "lanman.share.max_uses", FT_UINT16, BASE_DEC,
2278 NULL, 0, "LANMAN Max connections allowed to share", HFILL }},
2280 { &hf_share_current_uses,
2281 { "Share Current Uses", "lanman.share.current_uses", FT_UINT16, BASE_DEC,
2282 NULL, 0, "LANMAN Current connections to share", HFILL }},
2285 { "Share Path", "lanman.share.path", FT_STRING, BASE_NONE,
2286 NULL, 0, "LANMAN Share Path", HFILL }},
2288 { &hf_share_password,
2289 { "Share Password", "lanman.share.password", FT_STRING, BASE_NONE,
2290 NULL, 0, "LANMAN Share Password", HFILL }},
2293 { "Server Name", "lanman.server.name", FT_STRING, BASE_NONE,
2294 NULL, 0, "LANMAN Name of Server", HFILL }},
2297 { "Major Version", "lanman.server.major", FT_UINT8, BASE_DEC,
2298 NULL, 0, "LANMAN Server Major Version", HFILL }},
2301 { "Minor Version", "lanman.server.minor", FT_UINT8, BASE_DEC,
2302 NULL, 0, "LANMAN Server Minor Version", HFILL }},
2304 { &hf_server_comment,
2305 { "Server Comment", "lanman.server.comment", FT_STRING, BASE_NONE,
2306 NULL, 0, "LANMAN Server Comment", HFILL }},
2309 { "Available Bytes", "lanman.available_bytes", FT_UINT16, BASE_DEC,
2310 NULL, 0, "LANMAN Number of Available Bytes", HFILL }},
2313 { "Current Date/Time", "lanman.current_time", FT_ABSOLUTE_TIME, BASE_NONE,
2314 NULL, 0, "LANMAN Current date and time, in seconds since 00:00:00, January 1, 1970", HFILL }},
2317 { "Milliseconds", "lanman.msecs", FT_UINT32, BASE_DEC,
2318 NULL, 0, "LANMAN Milliseconds since arbitrary time in the past (typically boot time)", HFILL }},
2321 { "Hour", "lanman.hour", FT_UINT8, BASE_DEC,
2322 NULL, 0, "LANMAN Current hour", HFILL }},
2325 { "Minute", "lanman.minute", FT_UINT8, BASE_DEC,
2326 NULL, 0, "LANMAN Current minute", HFILL }},
2329 { "Second", "lanman.second", FT_UINT8, BASE_DEC,
2330 NULL, 0, "LANMAN Current second", HFILL }},
2333 { "Hundredths of a second", "lanman.hundredths", FT_UINT8, BASE_DEC,
2334 NULL, 0, "LANMAN Current hundredths of a second", HFILL }},
2337 { "Time Zone Offset", "lanman.tzoffset", FT_INT16, BASE_DEC,
2338 NULL, 0, "LANMAN Offset of time zone from GMT, in minutes", HFILL }},
2341 { "Time Interval", "lanman.timeinterval", FT_UINT16, BASE_DEC,
2342 NULL, 0, "LANMAN .0001 second units per clock tick", HFILL }},
2345 { "Day", "lanman.day", FT_UINT8, BASE_DEC,
2346 NULL, 0, "LANMAN Current day", HFILL }},
2349 { "Month", "lanman.month", FT_UINT8, BASE_DEC,
2350 NULL, 0, "LANMAN Current month", HFILL }},
2353 { "Year", "lanman.year", FT_UINT16, BASE_DEC,
2354 NULL, 0, "LANMAN Current year", HFILL }},
2357 { "Weekday", "lanman.weekday", FT_UINT8, BASE_DEC,
2358 VALS(weekday_vals), 0, "LANMAN Current day of the week", HFILL }},
2360 { &hf_enumeration_domain,
2361 { "Enumeration Domain", "lanman.enumeration_domain", FT_STRING, BASE_NONE,
2362 NULL, 0, "LANMAN Domain in which to enumerate servers", HFILL }},
2364 { &hf_computer_name,
2365 { "Computer Name", "lanman.computer_name", FT_STRING, BASE_NONE,
2366 NULL, 0, "LANMAN Computer Name", HFILL }},
2369 { "User Name", "lanman.user_name", FT_STRING, BASE_NONE,
2370 NULL, 0, "LANMAN User Name", HFILL }},
2372 { &hf_workstation_domain,
2373 { "Workstation Domain", "lanman.workstation_domain", FT_STRING, BASE_NONE,
2374 NULL, 0, "LANMAN Workstation Domain", HFILL }},
2376 { &hf_workstation_major,
2377 { "Workstation Major Version", "lanman.workstation_major", FT_UINT8, BASE_DEC,
2378 NULL, 0, "LANMAN Workstation Major Version", HFILL }},
2380 { &hf_workstation_minor,
2381 { "Workstation Minor Version", "lanman.workstation_minor", FT_UINT8, BASE_DEC,
2382 NULL, 0, "LANMAN Workstation Minor Version", HFILL }},
2385 { "Logon Domain", "lanman.logon_domain", FT_STRING, BASE_NONE,
2386 NULL, 0, "LANMAN Logon Domain", HFILL }},
2388 { &hf_other_domains,
2389 { "Other Domains", "lanman.other_domains", FT_STRING, BASE_NONE,
2390 NULL, 0, "LANMAN Other Domains", HFILL }},
2393 { "Password", "lanman.password", FT_STRING, BASE_NONE,
2394 NULL, 0, "LANMAN Password", HFILL }},
2396 { &hf_workstation_name,
2397 { "Workstation Name", "lanman.workstation_name", FT_STRING, BASE_NONE,
2398 NULL, 0, "LANMAN Workstation Name", HFILL }},
2401 { "Length of UStruct", "lanman.ustruct_size", FT_UINT16, BASE_DEC,
2402 NULL, 0, "LANMAN UStruct Length", HFILL }},
2405 { "Logon Code", "lanman.logon_code", FT_UINT16, BASE_DEC,
2406 VALS(status_vals), 0, "LANMAN Logon Code", HFILL }},
2408 { &hf_privilege_level,
2409 { "Privilege Level", "lanman.privilege_level", FT_UINT16, BASE_DEC,
2410 VALS(privilege_vals), 0, "LANMAN Privilege Level", HFILL }},
2412 { &hf_operator_privileges,
2413 { "Operator Privileges", "lanman.operator_privileges", FT_UINT32, BASE_DEC,
2414 VALS(op_privilege_vals), 0, "LANMAN Operator Privileges", HFILL }},
2417 { "Number of Logons", "lanman.num_logons", FT_UINT16, BASE_DEC,
2418 NULL, 0, "LANMAN Number of Logons", HFILL }},
2421 { "Bad Password Count", "lanman.bad_pw_count", FT_UINT16, BASE_DEC,
2422 NULL, 0, "LANMAN Number of incorrect passwords entered since last successful login", HFILL }},
2425 { "Last Logon Date/Time", "lanman.last_logon", FT_ABSOLUTE_TIME, BASE_NONE,
2426 NULL, 0, "LANMAN Date and time of last logon", HFILL }},
2429 { "Last Logoff Date/Time", "lanman.last_logoff", FT_ABSOLUTE_TIME, BASE_NONE,
2430 NULL, 0, "LANMAN Date and time of last logoff", HFILL }},
2433 { "Logoff Date/Time", "lanman.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
2434 NULL, 0, "LANMAN Date and time when user should log off", HFILL }},
2437 { "Kickoff Date/Time", "lanman.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
2438 NULL, 0, "LANMAN Date and time when user will be logged off", HFILL }},
2441 { "Password Age", "lanman.password_age", FT_RELATIVE_TIME, BASE_NONE,
2442 NULL, 0, "LANMAN Time since user last changed his/her password", HFILL }},
2444 { &hf_password_can_change,
2445 { "Password Can Change", "lanman.password_can_change", FT_ABSOLUTE_TIME, BASE_NONE,
2446 NULL, 0, "LANMAN Date and time when user can change their password", HFILL }},
2448 { &hf_password_must_change,
2449 { "Password Must Change", "lanman.password_must_change", FT_ABSOLUTE_TIME, BASE_NONE,
2450 NULL, 0, "LANMAN Date and time when user must change their password", HFILL }},
2453 { "Script Path", "lanman.script_path", FT_STRING, BASE_NONE,
2454 NULL, 0, "LANMAN Pathname of user's logon script", HFILL }},
2457 { "Logoff Code", "lanman.logoff_code", FT_UINT16, BASE_DEC,
2458 VALS(status_vals), 0, "LANMAN Logoff Code", HFILL }},
2461 { "Duration of Session", "lanman.duration", FT_RELATIVE_TIME, BASE_NONE,
2462 NULL, 0, "LANMAN Number of seconds the user was logged on", HFILL }},
2465 { "User Comment", "lanman.user_comment", FT_STRING, BASE_NONE,
2466 NULL, 0, "LANMAN User Comment", HFILL }},
2469 { "Full Name", "lanman.full_name", FT_STRING, BASE_NONE,
2470 NULL, 0, "LANMAN Full Name", HFILL }},
2473 { "Home Directory", "lanman.homedir", FT_STRING, BASE_NONE,
2474 NULL, 0, "LANMAN Home Directory", HFILL }},
2477 { "Parameters", "lanman.parameters", FT_STRING, BASE_NONE,
2478 NULL, 0, "LANMAN Parameters", HFILL }},
2481 { "Logon Server", "lanman.logon_server", FT_STRING, BASE_NONE,
2482 NULL, 0, "LANMAN Logon Server", HFILL }},
2484 /* XXX - we should have a value_string table for this */
2486 { "Country Code", "lanman.country_code", FT_UINT16, BASE_DEC,
2487 NULL, 0, "LANMAN Country Code", HFILL }},
2490 { "Workstations", "lanman.workstations", FT_STRING, BASE_NONE,
2491 NULL, 0, "LANMAN Workstations", HFILL }},
2494 { "Max Storage", "lanman.max_storage", FT_UINT32, BASE_DEC,
2495 NULL, 0, "LANMAN Max Storage", HFILL }},
2497 { &hf_units_per_week,
2498 { "Units Per Week", "lanman.units_per_week", FT_UINT16, BASE_DEC,
2499 NULL, 0, "LANMAN Units Per Week", HFILL }},
2502 { "Logon Hours", "lanman.logon_hours", FT_BYTES, BASE_NONE,
2503 NULL, 0, "LANMAN Logon Hours", HFILL }},
2505 /* XXX - we should have a value_string table for this */
2507 { "Code Page", "lanman.code_page", FT_UINT16, BASE_DEC,
2508 NULL, 0, "LANMAN Code Page", HFILL }},
2511 { "New Password", "lanman.new_password", FT_BYTES, BASE_HEX,
2512 NULL, 0, "LANMAN New Password (encrypted)", HFILL }},
2515 { "Old Password", "lanman.old_password", FT_BYTES, BASE_HEX,
2516 NULL, 0, "LANMAN Old Password (encrypted)", HFILL }},
2519 { "Reserved", "lanman.reserved", FT_UINT32, BASE_HEX,
2520 NULL, 0, "LANMAN Reserved", HFILL }},
2523 static gint *ett[] = {
2525 &ett_lanman_servers,
2531 proto_smb_lanman = proto_register_protocol(
2532 "Microsoft Windows Lanman Remote API Protocol", "LANMAN", "lanman");
2533 proto_register_field_array(proto_smb_lanman, hf, array_length(hf));
2534 proto_register_subtree_array(ett, array_length(ett));