+/*
+XXX Fixme : shouldnt show [malformed frame] for long packets
+*/
+
/* packet-smb-pipe.c
* Routines for SMB named pipe packet dissection
* Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ * significant rewrite to tvbuffify the dissector, Ronnie Sahlberg and
+ * Guy Harris 2001
*
- * $Id: packet-smb-pipe.c,v 1.17 2001/03/21 22:57:26 guy Exp $
+ * $Id: packet-smb-pipe.c,v 1.72 2002/03/27 04:27:03 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from packet-pop.c
#include <string.h>
#include <glib.h>
#include <ctype.h>
-#include "packet.h"
-#include "conversation.h"
+#include <epan/packet.h>
+#include <epan/conversation.h>
#include "smb.h"
-#include "alignment.h"
-#include "strutil.h"
#include "packet-smb-pipe.h"
+#include "packet-smb-browse.h"
+#include "packet-dcerpc.h"
+#include "reassemble.h"
+
+static int proto_smb_pipe = -1;
+static int hf_pipe_function = -1;
+static int hf_pipe_priority = -1;
+static int hf_pipe_peek_available = -1;
+static int hf_pipe_peek_remaining = -1;
+static int hf_pipe_peek_status = -1;
+static int hf_pipe_getinfo_info_level = -1;
+static int hf_pipe_getinfo_output_buffer_size = -1;
+static int hf_pipe_getinfo_input_buffer_size = -1;
+static int hf_pipe_getinfo_maximum_instances = -1;
+static int hf_pipe_getinfo_current_instances = -1;
+static int hf_pipe_getinfo_pipe_name_length = -1;
+static int hf_pipe_getinfo_pipe_name = -1;
+static int hf_pipe_write_raw_bytes_written = -1;
+
+static gint ett_smb_pipe = -1;
+static gint ett_smb_pipe_fragments = -1;
static int proto_smb_lanman = -1;
+static int hf_function_code = -1;
+static int hf_param_desc = -1;
+static int hf_return_desc = -1;
+static int hf_aux_data_desc = -1;
+static int hf_detail_level = -1;
+static int hf_recv_buf_len = -1;
+static int hf_send_buf_len = -1;
+static int hf_continuation_from = -1;
+static int hf_status = -1;
+static int hf_convert = -1;
+static int hf_ecount = -1;
+static int hf_acount = -1;
+static int hf_share_name = -1;
+static int hf_share_type = -1;
+static int hf_share_comment = -1;
+static int hf_share_permissions = -1;
+static int hf_share_max_uses = -1;
+static int hf_share_current_uses = -1;
+static int hf_share_path = -1;
+static int hf_share_password = -1;
+static int hf_server_name = -1;
+static int hf_server_major = -1;
+static int hf_server_minor = -1;
+static int hf_server_comment = -1;
+static int hf_abytes = -1;
+static int hf_current_time = -1;
+static int hf_msecs = -1;
+static int hf_hour = -1;
+static int hf_minute = -1;
+static int hf_second = -1;
+static int hf_hundredths = -1;
+static int hf_tzoffset = -1;
+static int hf_timeinterval = -1;
+static int hf_day = -1;
+static int hf_month = -1;
+static int hf_year = -1;
+static int hf_weekday = -1;
+static int hf_enumeration_domain = -1;
+static int hf_computer_name = -1;
+static int hf_user_name = -1;
+static int hf_group_name = -1;
+static int hf_workstation_domain = -1;
+static int hf_workstation_major = -1;
+static int hf_workstation_minor = -1;
+static int hf_logon_domain = -1;
+static int hf_other_domains = -1;
+static int hf_password = -1;
+static int hf_workstation_name = -1;
+static int hf_ustruct_size = -1;
+static int hf_logon_code = -1;
+static int hf_privilege_level = -1;
+static int hf_operator_privileges = -1;
+static int hf_num_logons = -1;
+static int hf_bad_pw_count = -1;
+static int hf_last_logon = -1;
+static int hf_last_logoff = -1;
+static int hf_logoff_time = -1;
+static int hf_kickoff_time = -1;
+static int hf_password_age = -1;
+static int hf_password_can_change = -1;
+static int hf_password_must_change = -1;
+static int hf_script_path = -1;
+static int hf_logoff_code = -1;
+static int hf_duration = -1;
+static int hf_comment = -1;
+static int hf_user_comment = -1;
+static int hf_full_name = -1;
+static int hf_homedir = -1;
+static int hf_parameters = -1;
+static int hf_logon_server = -1;
+static int hf_country_code = -1;
+static int hf_workstations = -1;
+static int hf_max_storage = -1;
+static int hf_units_per_week = -1;
+static int hf_logon_hours = -1;
+static int hf_code_page = -1;
+static int hf_new_password = -1;
+static int hf_old_password = -1;
+static int hf_reserved = -1;
static gint ett_lanman = -1;
-static gint ett_lanman_servers = -1;
-static gint ett_lanman_server = -1;
+static gint ett_lanman_unknown_entries = -1;
+static gint ett_lanman_unknown_entry = -1;
static gint ett_lanman_shares = -1;
static gint ett_lanman_share = -1;
-static gint ett_lanman_flags = -1;
+static gint ett_lanman_groups = -1;
+static gint ett_lanman_servers = -1;
+static gint ett_lanman_server = -1;
+
+static dissector_handle_t data_handle;
/*
* See
* among other documents.
*/
-/*
- * The following data structure describes the LANMAN requests we understand
- *
- * Simply fill in the number, name, and parameter names if you know them
- * Try to keep them in order
- *
- * We will extend this data structure as we try to decode more ...
- */
-
-struct lanman_desc {
- int lanman_num;
- char *lanman_name;
- char **req;
- char **req_data; /* Hmmm, not flexible enough */
- char **resp;
- char **resp_data;
+static const value_string status_vals[] = {
+ {0, "Success"},
+ {5, "User has insufficient privilege"},
+ {65, "Network access is denied"},
+ {86, "The specified password is invalid"},
+ {SMBE_moredata, "Additional data is available"},
+ {2114, "Service is not running on the remote computer"},
+ {2123, "Supplied buffer is too small"},
+ {2141, "Server is not configured for transactions (IPC$ not shared)"},
+ {2212, "An error occurred while loading or running the logon script"},
+ {2214, "The logon was not validated by any server"},
+ {2217, "The logon server is running an older software version"},
+ {2221, "The user name was not found"},
+ {2240, "The user is not allowed to logon from this computer"},
+ {2241, "The user is not allowed to logon at this time"},
+ {2242, "The user password has expired"},
+ {2243, "The password cannot be changed"},
+ {2246, "The password is too short"},
+ {0, NULL}
};
-static char *lm_params_req_0[] = {"Detail Level", "Return Buffer Size", NULL};
-static char *lm_params_req_1[] = {"Share Name", "Detail Level", "Receive Buffer Size", NULL};
-static char *lm_params_resp_1[] = {"Returned Data Len", NULL};
-static char *lm_params_req_13[] = {"Detail Level", "Receive Buffer Size", NULL};
-static char *lm_params_req_56[] = {"User Name", "Detail Level", "Receive Buffer Size", NULL};
-static char *lm_params_req_104[] = {"Detail Level", "Return Buffer Size", "Server Type", "Domain", NULL};
-static char *lm_params_req_132[] = {"Reserved1", "Reserved2", "Detail Level", "UserInfoStruct?", "Length of UStruct", "Receive Buffer Size", NULL};
-static char *lm_params_req_133[] = {"Reserved1", "Reserved2", "Detail Level", "UserInfoStruct?", "Length of UStruct", "Receive Buffer Size", NULL};
-
-static char *lm_null_params[] = {NULL};
-
-struct lanman_desc lmd[] = {
- {0, "NetShareEnum", lm_params_req_0, lm_null_params, lm_null_params, lm_null_params},
- {1, "NetShareGetInfo", lm_params_req_1, lm_null_params, lm_params_resp_1, lm_null_params},
- {13, "NetServerGetInfo", lm_params_req_13, lm_null_params, lm_null_params, lm_null_params},
- {52, "NetGroupGetUsers", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {56, "NetUserGetInfo", lm_params_req_56, lm_null_params, lm_null_params, lm_null_params},
- {59, "NetUserGetGroups", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {63, "NetWkstaGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {69, "DOSPrintQEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {70, "DOSPrintQGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {74, "WPrintQueuePause", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {75, "WPrintQueueResume", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {76, "WPrintJobEnumerate", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {77, "WPrintJobGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {81, "RDOSPrintJobDel", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {82, "RDOSPrintJobPause", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {83, "RDOSPrintJobResume", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {84, "WPrintDestEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {85, "WPrintDestGetInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {91, "NetRemoteTOD", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {103, "WPrintQueuePurge", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {104, "NetServerEnum2", lm_params_req_104, lm_null_params, lm_null_params, lm_null_params},
- {105, "WAccessGetUserPerms", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {115, "SetUserPassword", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {132, "NetWkstaUserLogon", lm_params_req_132, lm_null_params, lm_null_params, lm_null_params},
- {133, "NetWkstaUserLogoff", lm_params_req_133, lm_null_params, lm_null_params, lm_null_params},
- {147, "PrintJobInfo", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {205, "WPrintDriverEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {206, "WPrintQProcEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {207, "WPrintPortEnum", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {214, "SamOEMChangePassword", lm_null_params, lm_null_params, lm_null_params, lm_null_params},
- {-1, NULL, NULL,NULL, NULL, NULL}
+static const value_string share_type_vals[] = {
+ {0, "Directory tree"},
+ {1, "Printer queue"},
+ {2, "Communications device"},
+ {3, "IPC"},
+ {0, NULL}
};
-static struct lanman_desc *
-find_lanman(int lanman_num)
-{
- int i = 0;
-
- /* FIXME, This could be more efficient */
+static const value_string privilege_vals[] = {
+ {0, "Guest"},
+ {1, "User"},
+ {2, "Administrator"},
+ {0, NULL}
+};
- while (lmd[i].lanman_num != -1) {
+static const value_string op_privilege_vals[] = {
+ {0, "Print operator"},
+ {1, "Communications operator"},
+ {2, "Server operator"},
+ {3, "Accounts operator"},
+ {0, NULL}
+};
- if (lmd[i].lanman_num == lanman_num) {
+static const value_string weekday_vals[] = {
+ {0, "Sunday"},
+ {1, "Monday"},
+ {2, "Tuesday"},
+ {3, "Wednesday"},
+ {4, "Thursday"},
+ {5, "Friday"},
+ {6, "Saturday"},
+ {0, NULL}
+};
- return &lmd[i];
+static int
+add_word_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ guint16 WParam;
- }
+ if (hf_index != -1)
+ proto_tree_add_item(tree, hf_index, tvb, offset, 2, TRUE);
+ else {
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Word Param: %u (0x%04X)", WParam, WParam);
+ }
+ offset += 2;
+ return offset;
+}
- i++;
+static int
+add_dword_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ guint32 LParam;
- }
+ if (hf_index != -1)
+ proto_tree_add_item(tree, hf_index, tvb, offset, 4, TRUE);
+ else {
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Doubleword Param: %u (0x%08X)", LParam, LParam);
+ }
+ offset += 4;
+ return offset;
+}
- return NULL;
+static int
+add_byte_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ guint8 BParam;
+ if (hf_index != -1)
+ proto_tree_add_item(tree, hf_index, tvb, offset, count, TRUE);
+ else {
+ if (count == 1) {
+ BParam = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, count,
+ "Byte Param: %u (0x%02X)",
+ BParam, BParam);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, count,
+ "Byte Param: %s",
+ tvb_bytes_to_str(tvb, offset, count));
+ }
+ }
+ offset += count;
+ return offset;
}
-
-#define NETSHAREENUM 0x00 /* 00 */
-#define NETSERVERENUM2 0x68 /* 104 */
+static int
+add_pad_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ /*
+ * This is for parameters that have descriptor entries but that
+ * are, in practice, just padding.
+ */
+ offset += count;
+ return offset;
+}
static void
-dissect_server_flags(proto_tree *tree, int offset, int length, int flags)
+add_null_pointer_param(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
{
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0001, length*8, "Workstation", "Not Workstation"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0002, length*8, "Server", "Not Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0004, length*8, "SQL Server", "Not SQL Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0008, length*8, "Domain Controller", "Not Domain Controller"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0010, length*8, "Backup Controller", "Not Backup Controller"));
- proto_tree_add_text(tree, NullTVB, offset, 4, "%s",
- decode_boolean_bitfield(flags, 0x0020, length*8, "Time Source", "Not Time Source"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0040, length*8, "Apple Server", "Not Apple Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0080, length*8, "Novell Server", "Not Novell Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0100, length*8, "Domain Member Server", "Not Domain Member Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0200, length*8, "Print Queue Server", "Not Print Queue Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0400, length*8, "Dialin Server", "Not Dialin Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x0800, length*8, "Xenix Server", "Not Xenix Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x1000, length*8, "NT Workstation", "Not NT Workstation"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x2000, length*8, "Windows for Workgroups", "Not Windows for Workgroups"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x8000, length*8, "NT Server", "Not NT Server"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x10000, length*8, "Potential Browser", "Not Potential Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x20000, length*8, "Backup Browser", "Not Backup Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x40000, length*8, "Master Browser", "Not Master Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x80000, length*8, "Domain Master Browser", "Not Domain Master Browser"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x100000, length*8, "OSF", "Not OSF"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x200000, length*8, "VMS", "Not VMS"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x400000, length*8, "Windows 95 or above", "Not Windows 95 or above"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x40000000, length*8, "Local List Only", "Not Local List Only"));
- proto_tree_add_text(tree, NullTVB, offset, length, "%s",
- decode_boolean_bitfield(flags, 0x80000000, length*8, "Domain Enum", "Not Domain Enum"));
-
+ if (hf_index != -1) {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "%s (Null pointer)",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "String Param (Null pointer)");
+ }
}
-
-
-static char *p_desc = NULL, *d_desc = NULL, *data = NULL, *params = NULL;
-static int p_count, d_count, p_offset, d_offset, d_current = 0, p_current = 0;
-static int pd_p_current = 0, pd_d_current = 0, in_params = 0, need_data = 0;
-static int lm_ent_count = 0, lm_act_count = 0;
-
-/* Initialize the various data structure */
-static void
-dissect_transact_engine_init(const u_char *pd, const char *param_desc,
- const char *data_desc, int SMB_offset, int ParameterOffset,
- int ParameterCount, int DataOffset, int DataCount)
+static int
+add_string_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
{
-
- d_count = DataCount;
- p_count = ParameterCount;
- d_offset = 0;
- p_offset = 0;
- d_current = 0;
- p_current = 0;
- lm_ent_count = lm_act_count = 0;
- pd_d_current = DataOffset;
- pd_p_current = ParameterOffset;
- in_params = need_data = 0;
-
- if (p_desc) g_free(p_desc);
- p_desc = g_malloc(strlen(param_desc) + 1);
- strcpy(p_desc, param_desc);
-
- if (d_desc) g_free(d_desc);
- d_desc= g_malloc(strlen(data_desc) + 1);
- strcpy(d_desc, data_desc);
-
- if (params) g_free(params);
- params = g_malloc(p_count);
- memcpy(params, pd + ParameterOffset, ParameterCount);
-
- if (data) g_free(data);
- data = g_malloc(d_count);
- memcpy(data, pd + DataOffset, DataCount);
-
+ guint string_len;
+
+ string_len = tvb_strsize(tvb, offset);
+ if (hf_index != -1) {
+ proto_tree_add_item(tree, hf_index, tvb, offset, string_len,
+ TRUE);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, string_len,
+ "String Param: %s",
+ tvb_format_text(tvb, offset, string_len));
+ }
+ offset += string_len;
+ return offset;
}
-int get_ent_count()
+static const char *
+get_stringz_pointer_value(tvbuff_t *tvb, int offset, int convert, int *cptrp,
+ int *lenp)
{
-
- return lm_ent_count;
-
+ int cptr;
+ gint string_len;
+
+ /* pointer to string */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ *cptrp = cptr;
+
+ /* string */
+ if (tvb_offset_exists(tvb, cptr) &&
+ (string_len = tvb_strnlen(tvb, cptr, -1)) != -1) {
+ string_len++; /* include the terminating '\0' */
+ *lenp = string_len;
+ return tvb_format_text(tvb, cptr, string_len - 1);
+ } else
+ return NULL;
}
-int get_act_count()
+static int
+add_stringz_pointer_param(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
{
+ int cptr;
+ const char *string;
+ gint string_len;
+
+ string = get_stringz_pointer_value(tvb, offset, convert, &cptr,
+ &string_len);
+ offset += 4;
+
+ /* string */
+ if (string != NULL) {
+ if (hf_index != -1) {
+ proto_tree_add_item(tree, hf_index, tvb, cptr,
+ string_len, TRUE);
+ } else {
+ proto_tree_add_text(tree, tvb, cptr, string_len,
+ "String Param: %s", string);
+ }
+ } else {
+ if (hf_index != -1) {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "%s: <String goes past end of frame>",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "String Param: <String goes past end of frame>");
+ }
+ }
- return lm_act_count;
-
+ return offset;
}
-static int get_byte_count(const u_char *p_data)
-
+static int
+add_bytes_pointer_param(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
{
- int count = 0, off = 0;
-
- while (p_data[off] && isdigit(p_data[off])) {
-
- count = (count * 10) + (int)p_data[off++] - (int)'0';
-
- }
+ int cptr;
+
+ /* pointer to byte array */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+
+ /* bytes */
+ if (tvb_bytes_exist(tvb, cptr, count)) {
+ if (hf_index != -1) {
+ proto_tree_add_item(tree, hf_index, tvb, cptr,
+ count, TRUE);
+ } else {
+ proto_tree_add_text(tree, tvb, cptr, count,
+ "Byte Param: %s",
+ tvb_bytes_to_str(tvb, cptr, count));
+ }
+ } else {
+ if (hf_index != -1) {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "%s: <Bytes go past end of frame>",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "Byte Param: <Bytes goes past end of frame>");
+ }
+ }
- return count;
+ return offset;
}
-
-/* Dissect the next item, if Name is null, call it by its data type */
-/* We pull out the next item in the appropriate place and display it */
-/* We display the parameters first, then the data, then any auxilliary data */
-
static int
-dissect_transact_next(const u_char *pd, char *Name, int dirn, proto_tree *tree)
+add_detail_level(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
{
- /* guint8 BParam; */
- guint16 WParam = 0;
- guint32 LParam = 0;
- const char /**Bytes,*/ *AsciiZ = NULL;
- int bc;
-
- while (1) {
-
- if (p_desc[p_offset] == 0) return 0; /* No more ... */
-
- switch (in_params) {
-
- case 0: /* We are in the params area ... */
-
- switch (p_desc[p_offset++]) {
-
- case 'r':
-
- if (dirn == 0) { /* We need to process the data ... */
-
- need_data = 1;
+ struct smb_info *smb_info = pinfo->private_data;
+ smb_transact_info_t *trp = smb_info->sip->extra_info;
+ guint16 level;
+
+ level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ trp->info_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_index, tvb, offset, 2, level);
+ offset += 2;
+ return offset;
+}
+static int
+add_max_uses(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ guint16 WParam;
+
+ WParam = tvb_get_letohs(tvb, offset);
+ if (WParam == 0xffff) { /* -1 */
+ proto_tree_add_uint_format(tree, hf_index, tvb,
+ offset, 2, WParam,
+ "%s: No limit",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_uint(tree, hf_index, tvb,
+ offset, 2, WParam);
}
+ offset += 2;
+ return offset;
+}
- break;
-
- case 'h': /* A WORD parameter received */
-
- if (dirn == 0) {
-
- WParam = GSHORT(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u (%04X)", (Name) ? Name : "Returned Word", WParam, WParam);
-
- pd_p_current += 2;
+static int
+add_server_type(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
+{
+ dissect_smb_server_type_flags(tvb, pinfo, tree, offset, FALSE);
+ offset += 4;
+ return offset;
+}
- lm_act_count = WParam;
+static int
+add_server_type_info(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
+{
+ dissect_smb_server_type_flags(tvb, pinfo, tree, offset, TRUE);
+ offset += 4;
+ return offset;
+}
- return 1;
+static int
+add_reltime(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ nstime_t nstime;
+
+ nstime.secs = tvb_get_letohl(tvb, offset);
+ nstime.nsecs = 0;
+ proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
+ &nstime, "%s: %s", proto_registrar_get_name(hf_index),
+ time_secs_to_str(nstime.secs));
+ offset += 4;
+ return offset;
+}
+/*
+ * Sigh. These are for handling Microsoft's annoying almost-UNIX-time-but-
+ * it's-local-time-not-UTC time.
+ */
+static int
+add_abstime_common(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index,
+ const char *absent_name)
+{
+ nstime_t nstime;
+ struct tm *tmp;
+
+ nstime.secs = tvb_get_letohl(tvb, offset);
+ nstime.nsecs = 0;
+ /*
+ * Sigh. Sometimes it appears that -1 means "unknown", and
+ * sometimes it appears that 0 means "unknown", for the last
+ * logoff date/time.
+ */
+ if (nstime.secs == -1 || nstime.secs == 0) {
+ proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
+ &nstime, "%s: %s", proto_registrar_get_name(hf_index),
+ absent_name);
+ } else {
+ /*
+ * Run it through "gmtime()" to break it down, and then
+ * run it through "mktime()" to put it back together
+ * as UTC.
+ */
+ tmp = gmtime(&nstime.secs);
+ tmp->tm_isdst = -1; /* we don't know if it's DST or not */
+ nstime.secs = mktime(tmp);
+ proto_tree_add_time(tree, hf_index, tvb, offset, 4,
+ &nstime);
}
+ offset += 4;
+ return offset;
+}
- break;
-
- case 'e': /* An ent count .. */
-
- if (dirn == 0) { /* Only relevant in a response */
+static int
+add_abstime_absent_never(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
+{
+ return add_abstime_common(tvb, offset, count, pinfo, tree,
+ convert, hf_index, "Never");
+}
- WParam = GSHORT(pd, pd_p_current);
+static int
+add_abstime_absent_unknown(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo, proto_tree *tree, int convert, int hf_index)
+{
+ return add_abstime_common(tvb, offset, count, pinfo, tree,
+ convert, hf_index, "Unknown");
+}
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: (%04X)", (Name) ? Name : "Entry Count", WParam);
+static int
+add_nlogons(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ guint16 nlogons;
- pd_p_current += 2;
+ nlogons = tvb_get_letohs(tvb, offset);
+ if (nlogons == 0xffff) /* -1 */
+ proto_tree_add_uint_format(tree, hf_index, tvb, offset, 2,
+ nlogons, "%s: Unknown",
+ proto_registrar_get_name(hf_index));
+ else
+ proto_tree_add_uint(tree, hf_index, tvb, offset, 2,
+ nlogons);
+ offset += 2;
+ return offset;
+}
- lm_ent_count = WParam; /* Save this for later retrieval */
+static int
+add_max_storage(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ guint32 max_storage;
- return 1;
+ max_storage = tvb_get_letohl(tvb, offset);
+ if (max_storage == 0xffffffff)
+ proto_tree_add_uint_format(tree, hf_index, tvb, offset, 4,
+ max_storage, "%s: No limit",
+ proto_registrar_get_name(hf_index));
+ else
+ proto_tree_add_uint(tree, hf_index, tvb, offset, 4,
+ max_storage);
+ offset += 4;
+ return offset;
+}
+static int
+add_logon_hours(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ int cptr;
+
+ /* pointer to byte array */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+
+ /* bytes */
+ if (tvb_bytes_exist(tvb, cptr, count)) {
+ if (count == 21) {
+ /*
+ * The logon hours should be exactly 21 bytes long.
+ *
+ * XXX - should actually carve up the bits;
+ * we need the units per week to do that, though.
+ */
+ proto_tree_add_item(tree, hf_index, tvb, cptr, count,
+ TRUE);
+ } else {
+ proto_tree_add_bytes_format(tree, hf_index, tvb,
+ cptr, count, tvb_get_ptr(tvb, cptr, count),
+ "%s: %s (wrong length, should be 21, is %d",
+ proto_registrar_get_name(hf_index),
+ tvb_bytes_to_str(tvb, cptr, count), count);
+ }
+ } else {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "%s: <Bytes go past end of frame>",
+ proto_registrar_get_name(hf_index));
}
- break;
-
- case 'W': /* Word Parameter */
-
- if (dirn == 1) { /* A request ... */
-
- /* Insert a word param */
-
- WParam = GSHORT(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u (%04X)", (Name) ? Name : "Word Param", WParam, WParam);
-
- pd_p_current += 2;
-
- return 1; /* That's it here ... we have dissected a param */
+ return offset;
+}
+static int
+add_tzoffset(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ gint16 tzoffset;
+
+ tzoffset = tvb_get_letohs(tvb, offset);
+ if (tzoffset < 0) {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "%s: %s east of UTC",
+ proto_registrar_get_name(hf_index),
+ time_secs_to_str(-tzoffset*60));
+ } else if (tzoffset > 0) {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "%s: %s west of UTC",
+ proto_registrar_get_name(hf_index),
+ time_secs_to_str(tzoffset*60));
+ } else {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "%s: at UTC",
+ proto_registrar_get_name(hf_index));
}
+ offset += 2;
+ return offset;
+}
- break;
-
- case 'i': /* A long word is returned */
-
- if (dirn == 0) {
-
- LParam = GWORD(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u (0x%08X)", (Name) ? Name : "Returned Long Word", LParam, LParam);
-
- pd_p_current += 2;
-
- return 1;
+static int
+add_timeinterval(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ guint16 timeinterval;
+
+ timeinterval = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_timeinterval, tvb, offset, 2,
+ timeinterval, "%s: %f seconds", proto_registrar_get_name(hf_index),
+ timeinterval*.0001);
+ offset += 2;
+ return offset;
+}
+static int
+add_logon_args(tvbuff_t *tvb, int offset, int count, packet_info *pinfo,
+ proto_tree *tree, int convert, int hf_index)
+{
+ if (count != 54) {
+ proto_tree_add_text(tree, tvb, offset, count,
+ "Bogus NetWkstaUserLogon parameters: length is %d, should be 54",
+ count);
+ offset += count;
+ return offset;
}
- break;
-
- case 'D': /* Double Word parameter */
+ /* user name */
+ proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
+ offset += 21;
- if (dirn == 1) {
+ /* pad1 */
+ offset += 1;
- LParam = GWORD(pd, pd_p_current);
+ /* password */
+ proto_tree_add_item(tree, hf_password, tvb, offset, 15, TRUE);
+ offset += 15;
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u (0x%08X)", (Name) ? Name : "DWord Param", LParam, LParam);
+ /* pad2 */
+ offset += 1;
- pd_p_current += 4;
-
- return 1; /* That's it here */
+ /* workstation name */
+ proto_tree_add_item(tree, hf_workstation_name, tvb, offset, 16, TRUE);
+ offset += 16;
+ return offset;
+}
- }
+/*
+ * The following data structure describes the Remote API requests we
+ * understand.
+ *
+ * Simply fill in the number and parameter information.
+ * Try to keep them in order.
+ *
+ * We will extend this data structure as we try to decode more.
+ */
- break;
+/*
+ * This is a pointer to a function to process an item.
+ */
+typedef int (*item_func)(tvbuff_t *, int, int, packet_info *, proto_tree *,
+ int, int);
- case 'g': /* A byte or series of bytes is returned */
+/*
+ * Type of an item; determines what parameter strings are valid for
+ * the item.
+ */
+typedef enum {
+ PARAM_NONE, /* for the end-of-list stopper */
+ PARAM_WORD, /* 'W' or 'h' - 16-bit word */
+ PARAM_DWORD, /* 'D' or 'i' - 32-bit word */
+ PARAM_BYTES, /* 'B' or 'b' or 'g' or 'O' - one or more bytes */
+ PARAM_STRINGZ, /* 'z' or 'O' - null-terminated string */
+} param_type_t;
- if (dirn == 0) {
-
- bc = get_byte_count(p_desc + p_offset);
+/*
+ * This structure describes an item; "hf_index" points to the index
+ * for the field corresponding to that item, "func" points to the
+ * function to use to add that item to the tree, and "type" is the
+ * type that the item is supposed to have.
+ */
+typedef struct {
+ int *hf_index;
+ item_func func;
+ param_type_t type;
+} item_t;
- proto_tree_add_text(tree, NullTVB, pd_p_current, bc, "%s%u: %s", (Name) ? Name : "B", (bc) ? bc : 1, format_text( pd + pd_p_current, (bc) ? bc : 1));
+/*
+ * This structure describes a list of items; each list of items
+ * has a corresponding detail level.
+ */
+typedef struct {
+ int level;
+ const item_t *item_list;
+} item_list_t;
- pd_p_current += (bc) ? bc : 1;
+struct lanman_desc {
+ int lanman_num;
+ const item_t *req;
+ proto_item *(*req_data_item)(tvbuff_t *, packet_info *,
+ proto_tree *, int);
+ gint *ett_req_data;
+ const item_t *req_data;
+ const item_t *req_aux_data;
+ const item_t *resp;
+ const gchar *resp_data_entry_list_label;
+ gint *ett_data_entry_list;
+ proto_item *(*resp_data_element_item)(tvbuff_t *, packet_info *,
+ proto_tree *, int);
+ gint *ett_resp_data_element_item;
+ const item_list_t *resp_data_list;
+ const item_t *resp_aux_data;
+};
- return 1;
+static int no_hf = -1; /* for padding crap */
- }
+static const item_t lm_params_req_netshareenum[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { &hf_recv_buf_len, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- break;
+static const item_t lm_params_resp_netshareenum[] = {
+ { &hf_acount, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- case 'b': /* A byte or series of bytes */
+/*
+ * Create a subtree for a share.
+ */
+static proto_item *
+netshareenum_share_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset)
+{
+ if (tree) {
+ return proto_tree_add_text(tree, tvb, offset, -1,
+ "Share %.13s", tvb_get_ptr(tvb, offset, 13));
+ } else
+ return NULL;
+}
- if (dirn == 1) {
+static const item_t lm_null[] = {
+ { NULL, NULL, PARAM_NONE }
+};
- bc = get_byte_count(p_desc + p_offset); /* This is not clean */
+static const item_list_t lm_null_list[] = {
+ { -1, lm_null }
+};
- /*Bytes = g_malloc(bc + 1); / * Is this needed ? */
+static const item_t lm_data_resp_netshareenum_1[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_share_type, add_word_param, PARAM_WORD },
+ { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
- proto_tree_add_text(tree, NullTVB, pd_p_current, bc, "%s%u: %s", (Name) ? Name : "B", (bc) ? bc : 1, format_text(pd + pd_p_current, (bc) ? bc : 1));
+static const item_list_t lm_data_resp_netshareenum[] = {
+ { 1, lm_data_resp_netshareenum_1 },
+ { -1, lm_null }
+};
- pd_p_current += (bc) ? bc : 1;
+static const item_t lm_params_req_netsharegetinfo[] = {
+ { &hf_share_name, add_string_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- return 1; /* That's it here ... */
+static const item_t lm_params_resp_netsharegetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- }
+static const item_t lm_data_resp_netsharegetinfo_0[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
- break;
+static const item_t lm_data_resp_netsharegetinfo_1[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_share_type, add_word_param, PARAM_WORD },
+ { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
- case 'O': /* A null pointer */
+static const item_t lm_data_resp_netsharegetinfo_2[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_share_type, add_word_param, PARAM_WORD },
+ { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_share_permissions, add_word_param, PARAM_WORD }, /* XXX - do as bit fields */
+ { &hf_share_max_uses, add_max_uses, PARAM_WORD },
+ { &hf_share_current_uses, add_word_param, PARAM_WORD },
+ { &hf_share_path, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_share_password, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
- if (dirn == 1) {
+static const item_list_t lm_data_resp_netsharegetinfo[] = {
+ { 0, lm_data_resp_netsharegetinfo_0 },
+ { 1, lm_data_resp_netsharegetinfo_1 },
+ { 2, lm_data_resp_netsharegetinfo_2 },
+ { -1, lm_null }
+};
- proto_tree_add_text(tree, NullTVB, pd_p_current, 0, "%s: Null Pointer", (Name) ? Name : "Unknown");
+static const item_t lm_params_req_netservergetinfo[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- return 1; /* That's it here */
+static const item_t lm_params_resp_netservergetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- }
+static const item_t lm_data_serverinfo_0[] = {
+ { &hf_server_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
- break;
+static const item_t lm_data_serverinfo_1[] = {
+ { &hf_server_name, add_byte_param, PARAM_BYTES },
+ { &hf_server_major, add_byte_param, PARAM_BYTES },
+ { &hf_server_minor, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_server_type, PARAM_DWORD },
+ { &hf_server_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
- case 'z': /* An AsciiZ string */
+static const item_list_t lm_data_serverinfo[] = {
+ { 0, lm_data_serverinfo_0 },
+ { 1, lm_data_serverinfo_1 },
+ { -1, lm_null }
+};
- if (dirn == 1) {
+static const item_t lm_params_req_netusergetinfo[] = {
+ { &hf_user_name, add_string_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- AsciiZ = pd + pd_p_current;
+static const item_t lm_params_resp_netusergetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- proto_tree_add_text(tree, NullTVB, pd_p_current, strlen(AsciiZ) + 1, "%s: %s", (Name) ? Name : "AsciiZ", AsciiZ);
+static const item_t lm_data_resp_netusergetinfo_11[] = {
+ { &hf_user_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_user_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_full_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_privilege_level, add_word_param, PARAM_WORD },
+ { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
+ { &hf_password_age, add_reltime, PARAM_DWORD },
+ { &hf_homedir, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_parameters, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_bad_pw_count, add_word_param, PARAM_WORD },
+ { &hf_num_logons, add_nlogons, PARAM_WORD },
+ { &hf_logon_server, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_country_code, add_word_param, PARAM_WORD },
+ { &hf_workstations, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_max_storage, add_max_storage, PARAM_DWORD },
+ { &hf_units_per_week, add_word_param, PARAM_WORD },
+ { &hf_logon_hours, add_logon_hours, PARAM_BYTES },
+ { &hf_code_page, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- pd_p_current += strlen(AsciiZ) + 1;
+static const item_list_t lm_data_resp_netusergetinfo[] = {
+ { 11, lm_data_resp_netusergetinfo_11 },
+ { -1, lm_null }
+};
- return 1; /* That's it here ... */
+static const item_t lm_params_req_netusergetgroups[] = {
+ { &hf_user_name, add_string_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- }
+static const item_t lm_params_resp_netusergetgroups[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- break;
+static const item_t lm_data_resp_netusergetgroups_0[] = {
+ { &hf_group_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
- case 'F': /* One or more pad bytes */
+static const item_list_t lm_data_resp_netusergetgroups[] = {
+ { 0, lm_data_resp_netusergetgroups_0 },
+ { -1, lm_null }
+};
- if (dirn == 1) {
+/*
+ * Has no detail level; make it the default.
+ */
+static const item_t lm_data_resp_netremotetod_nolevel[] = {
+ { &hf_current_time, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_msecs, add_dword_param, PARAM_DWORD },
+ { &hf_hour, add_byte_param, PARAM_BYTES },
+ { &hf_minute, add_byte_param, PARAM_BYTES },
+ { &hf_second, add_byte_param, PARAM_BYTES },
+ { &hf_hundredths, add_byte_param, PARAM_BYTES },
+ { &hf_tzoffset, add_tzoffset, PARAM_WORD },
+ { &hf_timeinterval, add_timeinterval, PARAM_WORD },
+ { &hf_day, add_byte_param, PARAM_BYTES },
+ { &hf_month, add_byte_param, PARAM_BYTES },
+ { &hf_year, add_word_param, PARAM_WORD },
+ { &hf_weekday, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
- bc = get_byte_count(pd);
+static const item_list_t lm_data_resp_netremotetod[] = {
+ { -1, lm_data_resp_netremotetod_nolevel },
+};
- proto_tree_add_text(tree, NullTVB, pd_p_current, bc, "%s%u: %s", (Name) ? Name : "Pad", bc, format_text(pd + pd_p_current, bc));
+static const item_t lm_params_req_netserverenum2[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { &no_hf, add_server_type_info, PARAM_DWORD },
+ { &hf_enumeration_domain, add_string_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
- pd_p_current += bc;
+/*
+ * Create a subtree for a server.
+ */
+static proto_item *
+netserverenum2_server_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset)
+{
+ if (tree) {
+ return proto_tree_add_text(tree, tvb, offset, -1,
+ "Server %.16s", tvb_get_ptr(tvb, offset, 16));
+ } else
+ return NULL;
+}
- return 1; /* That's it here */
+static const item_t lm_params_resp_netserverenum2[] = {
+ { &hf_acount, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- }
+static const item_t lm_params_req_netwkstagetinfo[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- break;
+static const item_t lm_params_resp_netwkstagetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- case 'L': /* Receive buffer len: Short */
+static const item_t lm_data_resp_netwkstagetinfo_10[] = {
+ { &hf_computer_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_user_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_workstation_domain, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_workstation_major, add_byte_param, PARAM_BYTES },
+ { &hf_workstation_minor, add_byte_param, PARAM_BYTES },
+ { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_other_domains, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
- if (dirn == 1) {
+static const item_list_t lm_data_resp_netwkstagetinfo[] = {
+ { 10, lm_data_resp_netwkstagetinfo_10 },
+ { -1, lm_null }
+};
- WParam = GSHORT(pd, pd_p_current);
+static const item_t lm_params_req_netwkstauserlogon[] = {
+ { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { &no_hf, add_logon_args, PARAM_BYTES },
+ { &hf_ustruct_size, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u (0x%04X)", (Name) ? Name : "Receive Buffer Len", WParam, WParam);
+static const item_t lm_params_resp_netwkstauserlogon[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- pd_p_current += 2;
+static const item_t lm_data_resp_netwkstauserlogon_1[] = {
+ { &hf_logon_code, add_word_param, PARAM_WORD },
+ { &hf_user_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_privilege_level, add_word_param, PARAM_WORD },
+ { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
+ { &hf_num_logons, add_nlogons, PARAM_WORD },
+ { &hf_bad_pw_count, add_word_param, PARAM_WORD },
+ { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_logoff_time, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_kickoff_time, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_password_age, add_reltime, PARAM_DWORD },
+ { &hf_password_can_change, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_password_must_change, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_server_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_script_path, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_reserved, add_dword_param, PARAM_DWORD },
+ { NULL, NULL, PARAM_NONE }
+};
- return 1; /* That's it here ... */
+static const item_list_t lm_data_resp_netwkstauserlogon[] = {
+ { 1, lm_data_resp_netwkstauserlogon_1 },
+ { -1, lm_null }
+};
- }
+static const item_t lm_params_req_netwkstauserlogoff[] = {
+ { &hf_user_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_workstation_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
- break;
+static const item_t lm_params_resp_netwkstauserlogoff[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- case 's': /* Send buf ... */
+static const item_t lm_data_resp_netwkstauserlogoff_1[] = {
+ { &hf_logoff_code, add_word_param, PARAM_WORD },
+ { &hf_duration, add_reltime, PARAM_DWORD },
+ { &hf_num_logons, add_nlogons, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
- if (dirn == 1) {
+static const item_list_t lm_data_resp_netwkstauserlogoff[] = {
+ { 1, lm_data_resp_netwkstauserlogoff_1 },
+ { -1, lm_null }
+};
- need_data = 1;
+static const item_t lm_params_req_samoemchangepassword[] = {
+ { &hf_user_name, add_string_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
- LParam = GWORD(pd, pd_p_current);
+static const item_t lm_data_req_samoemchangepassword[] = {
+ { &hf_new_password, add_byte_param, PARAM_BYTES },
+ { &hf_old_password, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u", (Name) ? Name : "Send Buffer Ptr", LParam);
+/*
+ * Create a subtree for an entry we don't yet know how to dissect.
+ */
+static proto_item *
+unknown_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset)
+{
+ if (tree) {
+ return proto_tree_add_text(tree, tvb, offset, -1,
+ "Unknown entry");
+ } else
+ return NULL;
+}
- pd_p_current += 4;
+#define API_NetShareEnum 0
+#define API_NetShareGetInfo 1
+#define API_NetShareSetInfo 2
+#define API_NetShareAdd 3
+#define API_NetShareDel 4
+#define API_NetShareCheck 5
+#define API_NetSessionEnum 6
+#define API_NetSessionGetInfo 7
+#define API_NetSessionDel 8
+#define API_WconnectionEnum 9
+#define API_NetFileEnum 10
+#define API_NetFileGetInfo 11
+#define API_NetFileClose 12
+#define API_NetServerGetInfo 13
+#define API_NetServerSetInfo 14
+#define API_NetServerDiskEnum 15
+#define API_NetServerAdminCommand 16
+#define API_NetAuditOpen 17
+#define API_NetAuditClear 18
+#define API_NetErrorLogOpen 19
+#define API_NetErrorLogClear 20
+#define API_NetCharDevEnum 21
+#define API_NetCharDevGetInfo 22
+#define API_NetCharDevControl 23
+#define API_NetCharDevQEnum 24
+#define API_NetCharDevQGetInfo 25
+#define API_NetCharDevQSetInfo 26
+#define API_NetCharDevQPurge 27
+#define API_NetCharDevQPurgeSelf 28
+#define API_NetMessageNameEnum 29
+#define API_NetMessageNameGetInfo 30
+#define API_NetMessageNameAdd 31
+#define API_NetMessageNameDel 32
+#define API_NetMessageNameFwd 33
+#define API_NetMessageNameUnFwd 34
+#define API_NetMessageBufferSend 35
+#define API_NetMessageFileSend 36
+#define API_NetMessageLogFileSet 37
+#define API_NetMessageLogFileGet 38
+#define API_NetServiceEnum 39
+#define API_NetServiceInstall 40
+#define API_NetServiceControl 41
+#define API_NetAccessEnum 42
+#define API_NetAccessGetInfo 43
+#define API_NetAccessSetInfo 44
+#define API_NetAccessAdd 45
+#define API_NetAccessDel 46
+#define API_NetGroupEnum 47
+#define API_NetGroupAdd 48
+#define API_NetGroupDel 49
+#define API_NetGroupAddUser 50
+#define API_NetGroupDelUser 51
+#define API_NetGroupGetUsers 52
+#define API_NetUserEnum 53
+#define API_NetUserAdd 54
+#define API_NetUserDel 55
+#define API_NetUserGetInfo 56
+#define API_NetUserSetInfo 57
+#define API_NetUserPasswordSet 58
+#define API_NetUserGetGroups 59
+/*This line and number replaced a Dead Entry for 60 */
+/*This line and number replaced a Dead Entry for 61 */
+#define API_NetWkstaSetUID 62
+#define API_NetWkstaGetInfo 63
+#define API_NetWkstaSetInfo 64
+#define API_NetUseEnum 65
+#define API_NetUseAdd 66
+#define API_NetUseDel 67
+#define API_NetUseGetInfo 68
+#define API_WPrintQEnum 69
+#define API_WPrintQGetInfo 70
+#define API_WPrintQSetInfo 71
+#define API_WPrintQAdd 72
+#define API_WPrintQDel 73
+#define API_WPrintQPause 74
+#define API_WPrintQContinue 75
+#define API_WPrintJobEnum 76
+#define API_WPrintJobGetInfo 77
+#define API_WPrintJobSetInfo_OLD 78
+/* This line and number replaced a Dead Entry for 79 */
+/* This line and number replaced a Dead Entry for 80 */
+#define API_WPrintJobDel 81
+#define API_WPrintJobPause 82
+#define API_WPrintJobContinue 83
+#define API_WPrintDestEnum 84
+#define API_WPrintDestGetInfo 85
+#define API_WPrintDestControl 86
+#define API_NetProfileSave 87
+#define API_NetProfileLoad 88
+#define API_NetStatisticsGet 89
+#define API_NetStatisticsClear 90
+#define API_NetRemoteTOD 91
+#define API_WNetBiosEnum 92
+#define API_WNetBiosGetInfo 93
+#define API_NetServerEnum 94
+#define API_I_NetServerEnum 95
+#define API_NetServiceGetInfo 96
+/* This line and number replaced a Dead Entry for 97 */
+/* This line and number replaced a Dead Entry for 98 */
+/* This line and number replaced a Dead Entry for 99 */
+/* This line and number replaced a Dead Entry for 100 */
+/* This line and number replaced a Dead Entry for 101 */
+/* This line and number replaced a Dead Entry for 102 */
+#define API_WPrintQPurge 103
+#define API_NetServerEnum2 104
+#define API_NetAccessGetUserPerms 105
+#define API_NetGroupGetInfo 106
+#define API_NetGroupSetInfo 107
+#define API_NetGroupSetUsers 108
+#define API_NetUserSetGroups 109
+#define API_NetUserModalsGet 110
+#define API_NetUserModalsSet 111
+#define API_NetFileEnum2 112
+#define API_NetUserAdd2 113
+#define API_NetUserSetInfo2 114
+#define API_NetUserPasswordSet2 115
+#define API_I_NetServerEnum2 116
+#define API_NetConfigGet2 117
+#define API_NetConfigGetAll2 118
+#define API_NetGetDCName 119
+#define API_NetHandleGetInfo 120
+#define API_NetHandleSetInfo 121
+#define API_NetStatisticsGet2 122
+#define API_WBuildGetInfo 123
+#define API_NetFileGetInfo2 124
+#define API_NetFileClose2 125
+#define API_NetServerReqChallenge 126
+#define API_NetServerAuthenticate 127
+#define API_NetServerPasswordSet 128
+#define API_WNetAccountDeltas 129
+#define API_WNetAccountSync 130
+#define API_NetUserEnum2 131
+#define API_NetWkstaUserLogon 132
+#define API_NetWkstaUserLogoff 133
+#define API_NetLogonEnum 134
+#define API_NetErrorLogRead 135
+#define API_I_NetPathType 136
+#define API_I_NetPathCanonicalize 137
+#define API_I_NetPathCompare 138
+#define API_I_NetNameValidate 139
+#define API_I_NetNameCanonicalize 140
+#define API_I_NetNameCompare 141
+#define API_NetAuditRead 142
+#define API_WPrintDestAdd 143
+#define API_WPrintDestSetInfo 144
+#define API_WPrintDestDel 145
+#define API_NetUserValidate2 146
+#define API_WPrintJobSetInfo 147
+#define API_TI_NetServerDiskEnum 148
+#define API_TI_NetServerDiskGetInfo 149
+#define API_TI_FTVerifyMirror 150
+#define API_TI_FTAbortVerify 151
+#define API_TI_FTGetInfo 152
+#define API_TI_FTSetInfo 153
+#define API_TI_FTLockDisk 154
+#define API_TI_FTFixError 155
+#define API_TI_FTAbortFix 156
+#define API_TI_FTDiagnoseError 157
+#define API_TI_FTGetDriveStats 158
+/* This line and number replaced a Dead Entry for 159 */
+#define API_TI_FTErrorGetInfo 160
+/* This line and number replaced a Dead Entry for 161 */
+/* This line and number replaced a Dead Entry for 162 */
+#define API_NetAccessCheck 163
+#define API_NetAlertRaise 164
+#define API_NetAlertStart 165
+#define API_NetAlertStop 166
+#define API_NetAuditWrite 167
+#define API_NetIRemoteAPI 168
+#define API_NetServiceStatus 169
+#define API_I_NetServerRegister 170
+#define API_I_NetServerDeregister 171
+#define API_I_NetSessionEntryMake 172
+#define API_I_NetSessionEntryClear 173
+#define API_I_NetSessionEntryGetInfo 174
+#define API_I_NetSessionEntrySetInfo 175
+#define API_I_NetConnectionEntryMake 176
+#define API_I_NetConnectionEntryClear 177
+#define API_I_NetConnectionEntrySetInfo 178
+#define API_I_NetConnectionEntryGetInfo 179
+#define API_I_NetFileEntryMake 180
+#define API_I_NetFileEntryClear 181
+#define API_I_NetFileEntrySetInfo 182
+#define API_I_NetFileEntryGetInfo 183
+#define API_AltSrvMessageBufferSend 184
+#define API_AltSrvMessageFileSend 185
+#define API_wI_NetRplWkstaEnum 186
+#define API_wI_NetRplWkstaGetInfo 187
+#define API_wI_NetRplWkstaSetInfo 188
+#define API_wI_NetRplWkstaAdd 189
+#define API_wI_NetRplWkstaDel 190
+#define API_wI_NetRplProfileEnum 191
+#define API_wI_NetRplProfileGetInfo 192
+#define API_wI_NetRplProfileSetInfo 193
+#define API_wI_NetRplProfileAdd 194
+#define API_wI_NetRplProfileDel 195
+#define API_wI_NetRplProfileClone 196
+#define API_wI_NetRplBaseProfileEnum 197
+/* This line and number replaced a Dead Entry for 198 */
+/* This line and number replaced a Dead Entry for 199 */
+/* This line and number replaced a Dead Entry for 200 */
+#define API_WIServerSetInfo 201
+/* This line and number replaced a Dead Entry for 202 */
+/* This line and number replaced a Dead Entry for 203 */
+/* This line and number replaced a Dead Entry for 204 */
+#define API_WPrintDriverEnum 205
+#define API_WPrintQProcessorEnum 206
+#define API_WPrintPortEnum 207
+#define API_WNetWriteUpdateLog 208
+#define API_WNetAccountUpdate 209
+#define API_WNetAccountConfirmUpdate 210
+#define API_NetConfigSet 211
+#define API_WAccountsReplicate 212
+/* 213 is used by WfW */
+#define API_SamOEMChgPasswordUser2_P 214
+#define API_NetServerEnum3 215
+/* XXX - what about 216 through 249? */
+#define API_WPrintDriverGetInfo 250
+#define API_WPrintDriverSetInfo 251
+#define API_NetAliasAdd 252
+#define API_NetAliasDel 253
+#define API_NetAliasGetInfo 254
+#define API_NetAliasSetInfo 255
+#define API_NetAliasEnum 256
+#define API_NetUserGetLogonAsn 257
+#define API_NetUserSetLogonAsn 258
+#define API_NetUserGetAppSel 259
+#define API_NetUserSetAppSel 260
+#define API_NetAppAdd 261
+#define API_NetAppDel 262
+#define API_NetAppGetInfo 263
+#define API_NetAppSetInfo 264
+#define API_NetAppEnum 265
+#define API_NetUserDCDBInit 266
+#define API_NetDASDAdd 267
+#define API_NetDASDDel 268
+#define API_NetDASDGetInfo 269
+#define API_NetDASDSetInfo 270
+#define API_NetDASDEnum 271
+#define API_NetDASDCheck 272
+#define API_NetDASDCtl 273
+#define API_NetUserRemoteLogonCheck 274
+#define API_NetUserPasswordSet3 275
+#define API_NetCreateRIPLMachine 276
+#define API_NetDeleteRIPLMachine 277
+#define API_NetGetRIPLMachineInfo 278
+#define API_NetSetRIPLMachineInfo 279
+#define API_NetEnumRIPLMachine 280
+#define API_I_ShareAdd 281
+#define API_I_AliasEnum 282
+#define API_NetAccessApply 283
+#define API_WPrt16Query 284
+#define API_WPrt16Set 285
+#define API_NetUserDel100 286
+#define API_NetUserRemoteLogonCheck2 287
+#define API_WRemoteTODSet 294
+#define API_WPrintJobMoveAll 295
+#define API_W16AppParmAdd 296
+#define API_W16AppParmDel 297
+#define API_W16AppParmGet 298
+#define API_W16AppParmSet 299
+#define API_W16RIPLMachineCreate 300
+#define API_W16RIPLMachineGetInfo 301
+#define API_W16RIPLMachineSetInfo 302
+#define API_W16RIPLMachineEnum 303
+#define API_W16RIPLMachineListParmEnum 304
+#define API_W16RIPLMachClassGetInfo 305
+#define API_W16RIPLMachClassEnum 306
+#define API_W16RIPLMachClassCreate 307
+#define API_W16RIPLMachClassSetInfo 308
+#define API_W16RIPLMachClassDelete 309
+#define API_W16RIPLMachClassLPEnum 310
+#define API_W16RIPLMachineDelete 311
+#define API_W16WSLevelGetInfo 312
+#define API_NetServerNameAdd 313
+#define API_NetServerNameDel 314
+#define API_NetServerNameEnum 315
+#define API_I_WDASDEnum 316
+#define API_I_WDASDEnumTerminate 317
+#define API_I_WDASDSetInfo2 318
+
+static const struct lanman_desc lmd[] = {
+ { API_NetShareEnum,
+ lm_params_req_netshareenum,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netshareenum,
+ "Available Shares",
+ &ett_lanman_shares,
+ netshareenum_share_entry,
+ &ett_lanman_share,
+ lm_data_resp_netshareenum,
+ lm_null },
+
+ { API_NetShareGetInfo,
+ lm_params_req_netsharegetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netsharegetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netsharegetinfo,
+ lm_null },
+
+ { API_NetServerGetInfo,
+ lm_params_req_netservergetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netservergetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_serverinfo,
+ lm_null },
+
+ { API_NetUserGetInfo,
+ lm_params_req_netusergetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netusergetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netusergetinfo,
+ lm_null },
+
+ { API_NetUserGetGroups,
+ lm_params_req_netusergetgroups,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netusergetgroups,
+ "Groups",
+ &ett_lanman_groups,
+ NULL,
+ NULL,
+ lm_data_resp_netusergetgroups,
+ lm_null },
+
+ { API_NetRemoteTOD,
+ lm_null,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_null,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netremotetod,
+ lm_null },
+
+ { API_NetServerEnum2,
+ lm_params_req_netserverenum2,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netserverenum2,
+ "Servers",
+ &ett_lanman_servers,
+ netserverenum2_server_entry,
+ &ett_lanman_server,
+ lm_data_serverinfo,
+ lm_null },
+
+ { API_NetWkstaGetInfo,
+ lm_params_req_netwkstagetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netwkstagetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netwkstagetinfo,
+ lm_null },
+
+ { API_NetWkstaUserLogon,
+ lm_params_req_netwkstauserlogon,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netwkstauserlogon,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netwkstauserlogon,
+ lm_null },
+
+ { API_NetWkstaUserLogoff,
+ lm_params_req_netwkstauserlogoff,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netwkstauserlogoff,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netwkstauserlogoff,
+ lm_null },
+
+ { API_SamOEMChgPasswordUser2_P,
+ lm_params_req_samoemchangepassword,
+ NULL,
+ NULL,
+ lm_data_req_samoemchangepassword,
+ lm_null,
+ lm_null,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_null_list,
+ lm_null },
+
+ { -1,
+ lm_null,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_null,
+ NULL,
+ NULL,
+ NULL,
+ &ett_lanman_unknown_entry,
+ lm_null_list,
+ lm_null }
+};
- return 1; /* That's it here ... */
+static const struct lanman_desc *
+find_lanman(int lanman_num)
+{
+ int i;
+ for (i = 0; lmd[i].lanman_num != -1; i++) {
+ if (lmd[i].lanman_num == lanman_num)
+ break;
}
+ return &lmd[i];
+}
- break;
-
- case 'T':
-
- if (dirn == 1) {
-
- WParam = GSHORT(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u", (Name) ? Name : "Send Buffer Len", WParam);
-
- pd_p_current += 2;
-
- return 1;
+static const guchar *
+get_count(const guchar *desc, int *countp)
+{
+ int count = 0;
+ guchar c;
+ if (!isdigit(*desc)) {
+ *countp = 1; /* no count was supplied */
+ return desc;
}
- break;
-
- default:
-
- break;
-
- }
-
- break;
+ while ((c = *desc) != '\0' && isdigit(c)) {
+ count = (count * 10) + c - '0';
+ desc++;
+ }
- case 1: /* We are in the data area ... */
+ *countp = count; /* XXX - what if it's 0? */
+ return desc;
+}
-
- break;
-
- }
- }
+static int
+dissect_request_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const guchar *desc, const item_t *items,
+ gboolean *has_data_p)
+{
+ guint c;
+ guint16 WParam;
+ guint32 LParam;
+ guint string_len;
+ int count;
+
+ *has_data_p = FALSE;
+ while ((c = *desc++) != '\0') {
+ switch (c) {
+
+ case 'W':
+ /*
+ * A 16-bit word value in the request.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_word_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_WORD) {
+ /*
+ * Descriptor character is 'W', but this
+ * isn't a word parameter.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%04X), type is wrong (W)",
+ (*items->hf_index == -1) ?
+ "Word Param" :
+ proto_registrar_get_name(*items->hf_index),
+ WParam, WParam);
+ offset += 2;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'D':
+ /*
+ * A 32-bit doubleword value in the request.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_dword_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_DWORD) {
+ /*
+ * Descriptor character is 'D', but this
+ * isn't a doubleword parameter.
+ */
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%08X), type is wrong (D)",
+ (*items->hf_index == -1) ?
+ "Doubleword Param" :
+ proto_registrar_get_name(*items->hf_index),
+ LParam, LParam);
+ offset += 4;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'b':
+ /*
+ * A byte or multi-byte value in the request.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_byte_param(tvb, offset, count,
+ pinfo, tree, 0, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'b', but this
+ * isn't a byte/bytes parameter.
+ */
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (b)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, offset, count));
+ offset += count;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'O':
+ /*
+ * A null pointer.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ add_null_pointer_param(tvb, offset, 0,
+ pinfo, tree, 0, -1);
+ } else {
+ /*
+ * If "*items->hf_index" is -1, this is
+ * a reserved must-be-null field; don't
+ * clutter the protocol tree by putting
+ * it in.
+ */
+ if (*items->hf_index != -1) {
+ add_null_pointer_param(tvb,
+ offset, 0, pinfo, tree, 0,
+ *items->hf_index);
+ }
+ items++;
+ }
+ break;
+
+ case 'z':
+ /*
+ * A null-terminated ASCII string.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_string_param(tvb, offset, 0,
+ pinfo, tree, 0, -1);
+ } else if (items->type != PARAM_STRINGZ) {
+ /*
+ * Descriptor character is 'z', but this
+ * isn't a string parameter.
+ */
+ string_len = tvb_strsize(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, string_len,
+ "%s: Value is %s, type is wrong (z)",
+ (*items->hf_index == -1) ?
+ "String Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_format_text(tvb, offset, string_len));
+ offset += string_len;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0,
+ pinfo, tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'F':
+ /*
+ * One or more pad bytes.
+ */
+ desc = get_count(desc, &count);
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s", "Padding");
+ offset += count;
+ break;
+
+ case 'L':
+ /*
+ * 16-bit receive buffer length.
+ */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb,
+ offset, 2, TRUE);
+ offset += 2;
+ break;
+
+ case 's':
+ /*
+ * 32-bit send buffer offset.
+ * This appears not to be sent over the wire.
+ */
+ *has_data_p = TRUE;
+ break;
+
+ case 'T':
+ /*
+ * 16-bit send buffer length.
+ * This also appears not to be sent over the wire.
+ */
+ break;
+
+ default:
+ break;
+ }
+ }
+ return offset;
+}
- return 0;
+static int
+dissect_response_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const guchar *desc, const item_t *items,
+ gboolean *has_data_p, gboolean *has_ent_count_p, guint16 *ent_count_p)
+{
+ guint c;
+ guint16 WParam;
+ guint32 LParam;
+ int count;
+
+ *has_data_p = FALSE;
+ *has_ent_count_p = FALSE;
+ while ((c = *desc++) != '\0') {
+ switch (c) {
+
+ case 'r':
+ /*
+ * 32-bit receive buffer offset.
+ */
+ *has_data_p = TRUE;
+ break;
+
+ case 'g':
+ /*
+ * A byte or series of bytes is returned.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_byte_param(tvb, offset, count,
+ pinfo, tree, 0, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'b', but this
+ * isn't a byte/bytes parameter.
+ */
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (g)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, offset, count));
+ offset += count;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'h':
+ /*
+ * A 16-bit word is received.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_word_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_WORD) {
+ /*
+ * Descriptor character is 'h', but this
+ * isn't a word parameter.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%04X), type is wrong (W)",
+ (*items->hf_index == -1) ?
+ "Word Param" :
+ proto_registrar_get_name(*items->hf_index),
+ WParam, WParam);
+ offset += 2;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'i':
+ /*
+ * A 32-bit doubleword is received.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_dword_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_DWORD) {
+ /*
+ * Descriptor character is 'i', but this
+ * isn't a doubleword parameter.
+ */
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%08X), type is wrong (i)",
+ (*items->hf_index == -1) ?
+ "Doubleword Param" :
+ proto_registrar_get_name(*items->hf_index),
+ LParam, LParam);
+ offset += 4;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'e':
+ /*
+ * A 16-bit entry count is returned.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2,
+ WParam);
+ offset += 2;
+ *has_ent_count_p = TRUE;
+ *ent_count_p = WParam; /* Save this for later retrieval */
+ break;
+
+ default:
+ break;
+ }
+ }
+ return offset;
+}
+static int
+dissect_transact_data(tvbuff_t *tvb, int offset, int convert,
+ packet_info *pinfo, proto_tree *tree, const guchar *desc,
+ const item_t *items, guint16 *aux_count_p)
+{
+ guint c;
+ guint16 WParam;
+ guint32 LParam;
+ int count;
+ int cptr;
+ const char *string;
+ gint string_len;
+ const guint8 *bytes;
+
+ if (aux_count_p != NULL)
+ *aux_count_p = 0;
+
+ while ((c = *desc++) != '\0') {
+ switch (c) {
+
+ case 'W':
+ /*
+ * A 16-bit word value.
+ * XXX - handle the count?
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_word_param(tvb, offset, 0, pinfo,
+ tree, convert, -1);
+ } else if (items->type != PARAM_WORD) {
+ /*
+ * Descriptor character is 'W', but this
+ * isn't a word parameter.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%04X), type is wrong (W)",
+ (*items->hf_index == -1) ?
+ "Word Param" :
+ proto_registrar_get_name(*items->hf_index),
+ WParam, WParam);
+ offset += 2;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'D':
+ /*
+ * A 32-bit doubleword value.
+ * XXX - handle the count?
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_dword_param(tvb, offset, 0, pinfo,
+ tree, convert, -1);
+ } else if (items->type != PARAM_DWORD) {
+ /*
+ * Descriptor character is 'D', but this
+ * isn't a doubleword parameter.
+ */
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%08X), type is wrong (D)",
+ (*items->hf_index == -1) ?
+ "Doubleword Param" :
+ proto_registrar_get_name(*items->hf_index),
+ LParam, LParam);
+ offset += 4;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'B':
+ /*
+ * A byte or multi-byte value.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_byte_param(tvb, offset, count,
+ pinfo, tree, convert, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'B', but this
+ * isn't a byte/bytes parameter.
+ */
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (B)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, offset, count));
+ offset += count;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'O':
+ /*
+ * A null pointer.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ add_null_pointer_param(tvb, offset, 0,
+ pinfo, tree, convert, -1);
+ } else {
+ /*
+ * If "*items->hf_index" is -1, this is
+ * a reserved must-be-null field; don't
+ * clutter the protocol tree by putting
+ * it in.
+ */
+ if (*items->hf_index != -1) {
+ add_null_pointer_param(tvb,
+ offset, 0, pinfo, tree, convert,
+ *items->hf_index);
+ }
+ items++;
+ }
+ break;
+
+ case 'z':
+ /*
+ * A pointer to a null-terminated ASCII string.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_stringz_pointer_param(tvb, offset,
+ 0, pinfo, tree, convert, -1);
+ } else if (items->type != PARAM_STRINGZ) {
+ /*
+ * Descriptor character is 'z', but this
+ * isn't a string parameter.
+ */
+ string = get_stringz_pointer_value(tvb, offset,
+ convert, &cptr, &string_len);
+ offset += 4;
+ proto_tree_add_text(tree, tvb, cptr, string_len,
+ "%s: Value is %s, type is wrong (z)",
+ (*items->hf_index == -1) ?
+ "String Param" :
+ proto_registrar_get_name(*items->hf_index),
+ string);
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0,
+ pinfo, tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'b':
+ /*
+ * A pointer to a byte or multi-byte value.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_bytes_pointer_param(tvb, offset,
+ count, pinfo, tree, convert, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'b', but this
+ * isn't a byte/bytes parameter.
+ */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (b)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, cptr, count));
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'N':
+ /*
+ * 16-bit auxiliary data structure count.
+ * XXX - hf_acount?
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: %u (0x%04X)",
+ "Auxiliary data structure count",
+ WParam, WParam);
+ offset += 2;
+ if (aux_count_p != NULL)
+ *aux_count_p = WParam; /* Save this for later retrieval */
+ break;
+
+ default:
+ break;
+ }
+ }
+ return offset;
}
-static const value_string share_type_vals[] = {
- {0, "Directory tree"},
- {1, "Printer queue"},
- {2, "Communications device"},
- {3, "IPC"},
- {0, NULL}
+static const value_string commands[] = {
+ {API_NetShareEnum, "NetShareEnum"},
+ {API_NetShareGetInfo, "NetShareGetInfo"},
+ {API_NetShareSetInfo, "NetShareSetInfo"},
+ {API_NetShareAdd, "NetShareAdd"},
+ {API_NetShareDel, "NetShareDel"},
+ {API_NetShareCheck, "NetShareCheck"},
+ {API_NetSessionEnum, "NetSessionEnum"},
+ {API_NetSessionGetInfo, "NetSessionGetInfo"},
+ {API_NetSessionDel, "NetSessionDel"},
+ {API_WconnectionEnum, "NetConnectionEnum"},
+ {API_NetFileEnum, "NetFileEnum"},
+ {API_NetFileGetInfo, "NetFileGetInfo"},
+ {API_NetFileClose, "NetFileClose"},
+ {API_NetServerGetInfo, "NetServerGetInfo"},
+ {API_NetServerSetInfo, "NetServerSetInfo"},
+ {API_NetServerDiskEnum, "NetServerDiskEnum"},
+ {API_NetServerAdminCommand, "NetServerAdminCommand"},
+ {API_NetAuditOpen, "NetAuditOpen"},
+ {API_NetAuditClear, "NetAuditClear"},
+ {API_NetErrorLogOpen, "NetErrorLogOpen"},
+ {API_NetErrorLogClear, "NetErrorLogClear"},
+ {API_NetCharDevEnum, "NetCharDevEnum"},
+ {API_NetCharDevGetInfo, "NetCharDevGetInfo"},
+ {API_NetCharDevControl, "NetCharDevControl"},
+ {API_NetCharDevQEnum, "NetCharDevQEnum"},
+ {API_NetCharDevQGetInfo, "NetCharDevQGetInfo"},
+ {API_NetCharDevQSetInfo, "NetCharDevQSetInfo"},
+ {API_NetCharDevQPurge, "NetCharDevQPurge"},
+ {API_NetCharDevQPurgeSelf, "NetCharDevQPurgeSelf"},
+ {API_NetMessageNameEnum, "NetMessageNameEnum"},
+ {API_NetMessageNameGetInfo, "NetMessageNameGetInfo"},
+ {API_NetMessageNameAdd, "NetMessageNameAdd"},
+ {API_NetMessageNameDel, "NetMessageNameDel"},
+ {API_NetMessageNameFwd, "NetMessageNameFwd"},
+ {API_NetMessageNameUnFwd, "NetMessageNameUnFwd"},
+ {API_NetMessageBufferSend, "NetMessageBufferSend"},
+ {API_NetMessageFileSend, "NetMessageFileSend"},
+ {API_NetMessageLogFileSet, "NetMessageLogFileSet"},
+ {API_NetMessageLogFileGet, "NetMessageLogFileGet"},
+ {API_NetServiceEnum, "NetServiceEnum"},
+ {API_NetServiceInstall, "NetServiceInstall"},
+ {API_NetServiceControl, "NetServiceControl"},
+ {API_NetAccessEnum, "NetAccessEnum"},
+ {API_NetAccessGetInfo, "NetAccessGetInfo"},
+ {API_NetAccessSetInfo, "NetAccessSetInfo"},
+ {API_NetAccessAdd, "NetAccessAdd"},
+ {API_NetAccessDel, "NetAccessDel"},
+ {API_NetGroupEnum, "NetGroupEnum"},
+ {API_NetGroupAdd, "NetGroupAdd"},
+ {API_NetGroupDel, "NetGroupDel"},
+ {API_NetGroupAddUser, "NetGroupAddUser"},
+ {API_NetGroupDelUser, "NetGroupDelUser"},
+ {API_NetGroupGetUsers, "NetGroupGetUsers"},
+ {API_NetUserEnum, "NetUserEnum"},
+ {API_NetUserAdd, "NetUserAdd"},
+ {API_NetUserDel, "NetUserDel"},
+ {API_NetUserGetInfo, "NetUserGetInfo"},
+ {API_NetUserSetInfo, "NetUserSetInfo"},
+ {API_NetUserPasswordSet, "NetUserPasswordSet"},
+ {API_NetUserGetGroups, "NetUserGetGroups"},
+ {API_NetWkstaSetUID, "NetWkstaSetUID"},
+ {API_NetWkstaGetInfo, "NetWkstaGetInfo"},
+ {API_NetWkstaSetInfo, "NetWkstaSetInfo"},
+ {API_NetUseEnum, "NetUseEnum"},
+ {API_NetUseAdd, "NetUseAdd"},
+ {API_NetUseDel, "NetUseDel"},
+ {API_NetUseGetInfo, "NetUseGetInfo"},
+ {API_WPrintQEnum, "WPrintQEnum"},
+ {API_WPrintQGetInfo, "WPrintQGetInfo"},
+ {API_WPrintQSetInfo, "WPrintQSetInfo"},
+ {API_WPrintQAdd, "WPrintQAdd"},
+ {API_WPrintQDel, "WPrintQDel"},
+ {API_WPrintQPause, "WPrintQPause"},
+ {API_WPrintQContinue, "WPrintQContinue"},
+ {API_WPrintJobEnum, "WPrintJobEnum"},
+ {API_WPrintJobGetInfo, "WPrintJobGetInfo"},
+ {API_WPrintJobSetInfo_OLD, "WPrintJobSetInfo_OLD"},
+ {API_WPrintJobDel, "WPrintJobDel"},
+ {API_WPrintJobPause, "WPrintJobPause"},
+ {API_WPrintJobContinue, "WPrintJobContinue"},
+ {API_WPrintDestEnum, "WPrintDestEnum"},
+ {API_WPrintDestGetInfo, "WPrintDestGetInfo"},
+ {API_WPrintDestControl, "WPrintDestControl"},
+ {API_NetProfileSave, "NetProfileSave"},
+ {API_NetProfileLoad, "NetProfileLoad"},
+ {API_NetStatisticsGet, "NetStatisticsGet"},
+ {API_NetStatisticsClear, "NetStatisticsClear"},
+ {API_NetRemoteTOD, "NetRemoteTOD"},
+ {API_WNetBiosEnum, "WNetBiosEnum"},
+ {API_WNetBiosGetInfo, "WNetBiosGetInfo"},
+ {API_NetServerEnum, "NetServerEnum"},
+ {API_I_NetServerEnum, "I_NetServerEnum"},
+ {API_NetServiceGetInfo, "NetServiceGetInfo"},
+ {API_WPrintQPurge, "WPrintQPurge"},
+ {API_NetServerEnum2, "NetServerEnum2"},
+ {API_NetAccessGetUserPerms, "NetAccessGetUserPerms"},
+ {API_NetGroupGetInfo, "NetGroupGetInfo"},
+ {API_NetGroupSetInfo, "NetGroupSetInfo"},
+ {API_NetGroupSetUsers, "NetGroupSetUsers"},
+ {API_NetUserSetGroups, "NetUserSetGroups"},
+ {API_NetUserModalsGet, "NetUserModalsGet"},
+ {API_NetUserModalsSet, "NetUserModalsSet"},
+ {API_NetFileEnum2, "NetFileEnum2"},
+ {API_NetUserAdd2, "NetUserAdd2"},
+ {API_NetUserSetInfo2, "NetUserSetInfo2"},
+ {API_NetUserPasswordSet2, "SetUserPassword"},
+ {API_I_NetServerEnum2, "I_NetServerEnum2"},
+ {API_NetConfigGet2, "NetConfigGet2"},
+ {API_NetConfigGetAll2, "NetConfigGetAll2"},
+ {API_NetGetDCName, "NetGetDCName"},
+ {API_NetHandleGetInfo, "NetHandleGetInfo"},
+ {API_NetHandleSetInfo, "NetHandleSetInfo"},
+ {API_NetStatisticsGet2, "NetStatisticsGet2"},
+ {API_WBuildGetInfo, "WBuildGetInfo"},
+ {API_NetFileGetInfo2, "NetFileGetInfo2"},
+ {API_NetFileClose2, "NetFileClose2"},
+ {API_NetServerReqChallenge, "NetServerReqChallenge"},
+ {API_NetServerAuthenticate, "NetServerAuthenticate"},
+ {API_NetServerPasswordSet, "NetServerPasswordSet"},
+ {API_WNetAccountDeltas, "WNetAccountDeltas"},
+ {API_WNetAccountSync, "WNetAccountSync"},
+ {API_NetUserEnum2, "NetUserEnum2"},
+ {API_NetWkstaUserLogon, "NetWkstaUserLogon"},
+ {API_NetWkstaUserLogoff, "NetWkstaUserLogoff"},
+ {API_NetLogonEnum, "NetLogonEnum"},
+ {API_NetErrorLogRead, "NetErrorLogRead"},
+ {API_I_NetPathType, "I_NetPathType"},
+ {API_I_NetPathCanonicalize, "I_NetPathCanonicalize"},
+ {API_I_NetPathCompare, "I_NetPathCompare"},
+ {API_I_NetNameValidate, "I_NetNameValidate"},
+ {API_I_NetNameCanonicalize, "I_NetNameCanonicalize"},
+ {API_I_NetNameCompare, "I_NetNameCompare"},
+ {API_NetAuditRead, "NetAuditRead"},
+ {API_WPrintDestAdd, "WPrintDestAdd"},
+ {API_WPrintDestSetInfo, "WPrintDestSetInfo"},
+ {API_WPrintDestDel, "WPrintDestDel"},
+ {API_NetUserValidate2, "NetUserValidate2"},
+ {API_WPrintJobSetInfo, "WPrintJobSetInfo"},
+ {API_TI_NetServerDiskEnum, "TI_NetServerDiskEnum"},
+ {API_TI_NetServerDiskGetInfo, "TI_NetServerDiskGetInfo"},
+ {API_TI_FTVerifyMirror, "TI_FTVerifyMirror"},
+ {API_TI_FTAbortVerify, "TI_FTAbortVerify"},
+ {API_TI_FTGetInfo, "TI_FTGetInfo"},
+ {API_TI_FTSetInfo, "TI_FTSetInfo"},
+ {API_TI_FTLockDisk, "TI_FTLockDisk"},
+ {API_TI_FTFixError, "TI_FTFixError"},
+ {API_TI_FTAbortFix, "TI_FTAbortFix"},
+ {API_TI_FTDiagnoseError, "TI_FTDiagnoseError"},
+ {API_TI_FTGetDriveStats, "TI_FTGetDriveStats"},
+ {API_TI_FTErrorGetInfo, "TI_FTErrorGetInfo"},
+ {API_NetAccessCheck, "NetAccessCheck"},
+ {API_NetAlertRaise, "NetAlertRaise"},
+ {API_NetAlertStart, "NetAlertStart"},
+ {API_NetAlertStop, "NetAlertStop"},
+ {API_NetAuditWrite, "NetAuditWrite"},
+ {API_NetIRemoteAPI, "NetIRemoteAPI"},
+ {API_NetServiceStatus, "NetServiceStatus"},
+ {API_I_NetServerRegister, "I_NetServerRegister"},
+ {API_I_NetServerDeregister, "I_NetServerDeregister"},
+ {API_I_NetSessionEntryMake, "I_NetSessionEntryMake"},
+ {API_I_NetSessionEntryClear, "I_NetSessionEntryClear"},
+ {API_I_NetSessionEntryGetInfo, "I_NetSessionEntryGetInfo"},
+ {API_I_NetSessionEntrySetInfo, "I_NetSessionEntrySetInfo"},
+ {API_I_NetConnectionEntryMake, "I_NetConnectionEntryMake"},
+ {API_I_NetConnectionEntryClear, "I_NetConnectionEntryClear"},
+ {API_I_NetConnectionEntrySetInfo, "I_NetConnectionEntrySetInfo"},
+ {API_I_NetConnectionEntryGetInfo, "I_NetConnectionEntryGetInfo"},
+ {API_I_NetFileEntryMake, "I_NetFileEntryMake"},
+ {API_I_NetFileEntryClear, "I_NetFileEntryClear"},
+ {API_I_NetFileEntrySetInfo, "I_NetFileEntrySetInfo"},
+ {API_I_NetFileEntryGetInfo, "I_NetFileEntryGetInfo"},
+ {API_AltSrvMessageBufferSend, "AltSrvMessageBufferSend"},
+ {API_AltSrvMessageFileSend, "AltSrvMessageFileSend"},
+ {API_wI_NetRplWkstaEnum, "wI_NetRplWkstaEnum"},
+ {API_wI_NetRplWkstaGetInfo, "wI_NetRplWkstaGetInfo"},
+ {API_wI_NetRplWkstaSetInfo, "wI_NetRplWkstaSetInfo"},
+ {API_wI_NetRplWkstaAdd, "wI_NetRplWkstaAdd"},
+ {API_wI_NetRplWkstaDel, "wI_NetRplWkstaDel"},
+ {API_wI_NetRplProfileEnum, "wI_NetRplProfileEnum"},
+ {API_wI_NetRplProfileGetInfo, "wI_NetRplProfileGetInfo"},
+ {API_wI_NetRplProfileSetInfo, "wI_NetRplProfileSetInfo"},
+ {API_wI_NetRplProfileAdd, "wI_NetRplProfileAdd"},
+ {API_wI_NetRplProfileDel, "wI_NetRplProfileDel"},
+ {API_wI_NetRplProfileClone, "wI_NetRplProfileClone"},
+ {API_wI_NetRplBaseProfileEnum, "wI_NetRplBaseProfileEnum"},
+ {API_WIServerSetInfo, "WIServerSetInfo"},
+ {API_WPrintDriverEnum, "WPrintDriverEnum"},
+ {API_WPrintQProcessorEnum, "WPrintQProcessorEnum"},
+ {API_WPrintPortEnum, "WPrintPortEnum"},
+ {API_WNetWriteUpdateLog, "WNetWriteUpdateLog"},
+ {API_WNetAccountUpdate, "WNetAccountUpdate"},
+ {API_WNetAccountConfirmUpdate, "WNetAccountConfirmUpdate"},
+ {API_NetConfigSet, "NetConfigSet"},
+ {API_WAccountsReplicate, "WAccountsReplicate"},
+ {API_SamOEMChgPasswordUser2_P, "SamOEMChangePassword"},
+ {API_NetServerEnum3, "NetServerEnum3"},
+ {API_WPrintDriverGetInfo, "WPrintDriverGetInfo"},
+ {API_WPrintDriverSetInfo, "WPrintDriverSetInfo"},
+ {API_NetAliasAdd, "NetAliasAdd"},
+ {API_NetAliasDel, "NetAliasDel"},
+ {API_NetAliasGetInfo, "NetAliasGetInfo"},
+ {API_NetAliasSetInfo, "NetAliasSetInfo"},
+ {API_NetAliasEnum, "NetAliasEnum"},
+ {API_NetUserGetLogonAsn, "NetUserGetLogonAsn"},
+ {API_NetUserSetLogonAsn, "NetUserSetLogonAsn"},
+ {API_NetUserGetAppSel, "NetUserGetAppSel"},
+ {API_NetUserSetAppSel, "NetUserSetAppSel"},
+ {API_NetAppAdd, "NetAppAdd"},
+ {API_NetAppDel, "NetAppDel"},
+ {API_NetAppGetInfo, "NetAppGetInfo"},
+ {API_NetAppSetInfo, "NetAppSetInfo"},
+ {API_NetAppEnum, "NetAppEnum"},
+ {API_NetUserDCDBInit, "NetUserDCDBInit"},
+ {API_NetDASDAdd, "NetDASDAdd"},
+ {API_NetDASDDel, "NetDASDDel"},
+ {API_NetDASDGetInfo, "NetDASDGetInfo"},
+ {API_NetDASDSetInfo, "NetDASDSetInfo"},
+ {API_NetDASDEnum, "NetDASDEnum"},
+ {API_NetDASDCheck, "NetDASDCheck"},
+ {API_NetDASDCtl, "NetDASDCtl"},
+ {API_NetUserRemoteLogonCheck, "NetUserRemoteLogonCheck"},
+ {API_NetUserPasswordSet3, "NetUserPasswordSet3"},
+ {API_NetCreateRIPLMachine, "NetCreateRIPLMachine"},
+ {API_NetDeleteRIPLMachine, "NetDeleteRIPLMachine"},
+ {API_NetGetRIPLMachineInfo, "NetGetRIPLMachineInfo"},
+ {API_NetSetRIPLMachineInfo, "NetSetRIPLMachineInfo"},
+ {API_NetEnumRIPLMachine, "NetEnumRIPLMachine"},
+ {API_I_ShareAdd, "I_ShareAdd"},
+ {API_I_AliasEnum, "I_AliasEnum"},
+ {API_NetAccessApply, "NetAccessApply"},
+ {API_WPrt16Query, "WPrt16Query"},
+ {API_WPrt16Set, "WPrt16Set"},
+ {API_NetUserDel100, "NetUserDel100"},
+ {API_NetUserRemoteLogonCheck2, "NetUserRemoteLogonCheck2"},
+ {API_WRemoteTODSet, "WRemoteTODSet"},
+ {API_WPrintJobMoveAll, "WPrintJobMoveAll"},
+ {API_W16AppParmAdd, "W16AppParmAdd"},
+ {API_W16AppParmDel, "W16AppParmDel"},
+ {API_W16AppParmGet, "W16AppParmGet"},
+ {API_W16AppParmSet, "W16AppParmSet"},
+ {API_W16RIPLMachineCreate, "W16RIPLMachineCreate"},
+ {API_W16RIPLMachineGetInfo, "W16RIPLMachineGetInfo"},
+ {API_W16RIPLMachineSetInfo, "W16RIPLMachineSetInfo"},
+ {API_W16RIPLMachineEnum, "W16RIPLMachineEnum"},
+ {API_W16RIPLMachineListParmEnum, "W16RIPLMachineListParmEnum"},
+ {API_W16RIPLMachClassGetInfo, "W16RIPLMachClassGetInfo"},
+ {API_W16RIPLMachClassEnum, "W16RIPLMachClassEnum"},
+ {API_W16RIPLMachClassCreate, "W16RIPLMachClassCreate"},
+ {API_W16RIPLMachClassSetInfo, "W16RIPLMachClassSetInfo"},
+ {API_W16RIPLMachClassDelete, "W16RIPLMachClassDelete"},
+ {API_W16RIPLMachClassLPEnum, "W16RIPLMachClassLPEnum"},
+ {API_W16RIPLMachineDelete, "W16RIPLMachineDelete"},
+ {API_W16WSLevelGetInfo, "W16WSLevelGetInfo"},
+ {API_NetServerNameAdd, "NetServerNameAdd"},
+ {API_NetServerNameDel, "NetServerNameDel"},
+ {API_NetServerNameEnum, "NetServerNameEnum"},
+ {API_I_WDASDEnum, "I_WDASDEnum"},
+ {API_I_WDASDEnumTerminate, "I_WDASDEnumTerminate"},
+ {API_I_WDASDSetInfo2, "I_WDASDSetInfo2"},
+ {0, NULL}
};
-gboolean
-dissect_pipe_lanman(const u_char *pd, int offset, frame_data *fd,
- proto_tree *parent, proto_tree *tree, struct smb_info si,
- int max_data, int SMB_offset, int errcode, int dirn,
- const u_char *command, int DataOffset, int DataCount,
- int ParameterOffset, int ParameterCount)
+static void
+dissect_response_data(tvbuff_t *tvb, packet_info *pinfo, int convert,
+ proto_tree *tree, struct smb_info *smb_info,
+ const struct lanman_desc *lanman, gboolean has_ent_count,
+ guint16 ent_count)
{
- gboolean is_interim_response;
- guint32 loc_offset;
- guint16 FunctionCode;
- guint16 Level;
- guint16 RecvBufLen;
- guint32 Flags;
- const char *ParameterDescriptor;
- const char *ReturnDescriptor;
- proto_tree *lanman_tree = NULL, *flags_tree = NULL;
- proto_item *ti;
- struct lanman_desc *lanman;
- guint32 string_offset;
-
- if (DataOffset < 0) {
-
- /* Interim response; we weren't given any data. */
-
- is_interim_response = TRUE;
- loc_offset = 0;
-
- }
- else {
-
- /* Offset of the data we should dissect. */
-
- is_interim_response = FALSE;
- loc_offset = SMB_offset + ParameterOffset;
-
- }
-
- if (check_col(fd, COL_PROTOCOL))
- col_set_str(fd, COL_PROTOCOL, "LANMAN");
-
- if (dirn == 1) { /* The request side */
-
- FunctionCode = GSHORT(pd, loc_offset);
-
- si.request_val -> last_lanman_cmd = FunctionCode;
-
- switch (FunctionCode) {
-
- case NETSHAREENUM: /* Never decode this at the moment ... */
-
- if (check_col(fd, COL_INFO)) {
-
- col_set_str(fd, COL_INFO, "NetShareEnum Request");
-
- }
-
- if (tree) {
-
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, ParameterCount, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Function Code: NetShareEnum");
-
- }
-
- loc_offset += 2;
-
- ParameterDescriptor = pd + loc_offset;
-
- si.request_val -> trans_response_seen = 0;
-
- if (si.request_val -> last_param_descrip) g_free(si.request_val -> last_param_descrip);
- si.request_val -> last_param_descrip = g_malloc(strlen(ParameterDescriptor) + 1);
- if (si.request_val -> last_param_descrip)
- strcpy(si.request_val -> last_param_descrip, ParameterDescriptor);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ParameterDescriptor) + 1, "Parameter Descriptor: %s", ParameterDescriptor);
-
- }
-
- loc_offset += strlen(ParameterDescriptor) + 1;
-
- ReturnDescriptor = pd + loc_offset;
-
- if (si.request_val -> last_data_descrip) g_free(si.request_val -> last_data_descrip);
- si.request_val -> last_data_descrip = g_malloc(strlen(ReturnDescriptor) + 1);
- if (si.request_val -> last_data_descrip)
- strcpy(si.request_val -> last_data_descrip, ReturnDescriptor);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ReturnDescriptor) + 1, "Return Descriptor: %s", ReturnDescriptor);
-
- }
-
- loc_offset += strlen(ReturnDescriptor) + 1;
-
- Level = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Detail Level: %u", Level);
-
- }
-
- loc_offset += 2;
-
- RecvBufLen = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Receive Buffer Length: %u", RecvBufLen);
-
- }
-
- loc_offset += 2;
-
- break;
-
- case NETSERVERENUM2: /* Process a NetServerEnum2 */
-
- if (check_col(fd, COL_INFO)) {
-
- col_set_str(fd, COL_INFO, "NetServerEnum2 Request");
-
- }
-
- if (tree) {
-
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, ParameterCount, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Function Code: NetServerEnum2");
-
- }
-
- loc_offset += 2;
-
- ParameterDescriptor = pd + loc_offset;
-
- /* Now, save these for later */
-
- si.request_val -> trans_response_seen = 0;
-
- if (si.request_val -> last_param_descrip) g_free(si.request_val -> last_param_descrip);
- si.request_val -> last_param_descrip = g_malloc(strlen(ParameterDescriptor) + 1);
- if (si.request_val -> last_param_descrip)
- strcpy(si.request_val -> last_param_descrip, ParameterDescriptor);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ParameterDescriptor) + 1, "Parameter Descriptor: %s", ParameterDescriptor);
-
- }
-
- loc_offset += strlen(ParameterDescriptor) + 1;
-
- ReturnDescriptor = pd + loc_offset;
-
- if (si.request_val -> last_data_descrip) g_free(si.request_val -> last_data_descrip);
-
- si.request_val -> last_data_descrip = g_malloc(strlen(ReturnDescriptor) + 1);
- if (si.request_val -> last_data_descrip)
- strcpy(si.request_val -> last_data_descrip, ReturnDescriptor);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ReturnDescriptor) + 1, "Return Descriptor: %s", ReturnDescriptor);
-
- }
-
- loc_offset += strlen(ReturnDescriptor) + 1;
-
- Level = GSHORT(pd, loc_offset);
- si.request_val -> last_level = Level;
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Info Detail Level: %u", Level);
-
- }
-
- loc_offset += 2;
-
- RecvBufLen = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Receive Buffer Length: %u", RecvBufLen);
-
- }
-
- loc_offset += 2;
-
- Flags = GWORD(pd, loc_offset);
-
- if (tree) {
-
- ti = proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 4, "Server Types Required: 0x%08X", Flags);
- flags_tree = proto_item_add_subtree(ti, ett_lanman_flags);
- dissect_server_flags(flags_tree, loc_offset, 4, Flags);
-
- }
-
- loc_offset += 4;
-
- return TRUE;
- break;
-
- default: /* Just try to handle what is there ... */
-
- lanman = find_lanman(FunctionCode);
-
- if (check_col(fd, COL_INFO)) {
-
- if (lanman) {
- col_add_fstr(fd, COL_INFO, "%s Request", lanman -> lanman_name);
+ smb_transact_info_t *trp = smb_info->sip->extra_info;
+ const item_list_t *resp_data_list;
+ int offset, start_offset;
+ const char *label;
+ gint ett;
+ const item_t *resp_data;
+ proto_item *data_item;
+ proto_tree *data_tree;
+ proto_item *entry_item;
+ proto_tree *entry_tree;
+ guint i, j;
+ guint16 aux_count;
+
+ /*
+ * Find the item table for the matching request's detail level.
+ */
+ for (resp_data_list = lanman->resp_data_list;
+ resp_data_list->level != -1; resp_data_list++) {
+ if (resp_data_list->level == trp->info_level)
+ break;
}
- else {
- col_add_fstr(fd, COL_INFO, "Unknown LANMAN Request: %u", FunctionCode);
+ resp_data = resp_data_list->item_list;
+
+ offset = 0;
+ if (has_ent_count) {
+ /*
+ * The data is a list of entries; create a protocol tree item
+ * for it.
+ */
+ if (tree) {
+ label = lanman->resp_data_entry_list_label;
+ if (label == NULL)
+ label = "Entries";
+ if (lanman->ett_data_entry_list != NULL)
+ ett = *lanman->ett_data_entry_list;
+ else
+ ett = ett_lanman_unknown_entries;
+ data_item = proto_tree_add_text(tree, tvb, offset, -1,
+ label);
+ data_tree = proto_item_add_subtree(data_item, ett);
+ } else {
+ data_item = NULL;
+ data_tree = NULL;
+ }
+ } else {
+ /*
+ * Just leave it at the top level.
+ */
+ data_item = NULL;
+ data_tree = tree;
}
- }
- if (tree) {
+ if (trp->data_descrip == NULL) {
+ /*
+ * This could happen if we only dissected
+ * part of the request to which this is a
+ * reply, e.g. if the request was split
+ * across TCP segments and we weren't doing
+ * TCP desegmentation, or if we had a snapshot
+ * length that was too short.
+ *
+ * We can't dissect the data; just show it
+ * as raw data.
+ */
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Data (no descriptor available)");
+ offset += tvb_length_remaining(tvb, offset);
+ } else {
+ /*
+ * If we have an entry count, show all the entries,
+ * with each one having a protocol tree item.
+ *
+ * Otherwise, we just show one returned item, with
+ * no protocol tree item.
+ */
+ if (!has_ent_count)
+ ent_count = 1;
+ for (i = 0; i < ent_count; i++) {
+ start_offset = offset;
+ if (has_ent_count &&
+ lanman->resp_data_element_item != NULL) {
+ /*
+ * Create a protocol tree item for the
+ * entry.
+ */
+ entry_item =
+ (*lanman->resp_data_element_item)
+ (tvb, pinfo, data_tree, offset);
+ entry_tree = proto_item_add_subtree(
+ entry_item,
+ *lanman->ett_resp_data_element_item);
+ } else {
+ /*
+ * Just leave it at the current
+ * level.
+ */
+ entry_item = NULL;
+ entry_tree = data_tree;
+ }
+
+ offset = dissect_transact_data(tvb, offset,
+ convert, pinfo, entry_tree,
+ trp->data_descrip, resp_data, &aux_count);
+
+ /* auxiliary data */
+ if (trp->aux_data_descrip != NULL) {
+ for (j = 0; j < aux_count; j++) {
+ offset = dissect_transact_data(
+ tvb, offset, convert,
+ pinfo, entry_tree,
+ trp->data_descrip,
+ lanman->resp_aux_data, NULL);
+ }
+ }
+
+ if (entry_item != NULL) {
+ /*
+ * Set the length of the protocol tree
+ * item for the entry.
+ */
+ proto_item_set_len(entry_item,
+ offset - start_offset);
+ }
+ }
+ }
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, ParameterCount, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
+ if (data_item != NULL) {
+ /*
+ * Set the length of the protocol tree item
+ * for the data.
+ */
+ proto_item_set_len(data_item, offset);
+ }
+}
- if (lanman) {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "%s Request", lanman -> lanman_name);
+static gboolean
+dissect_pipe_lanman(tvbuff_t *pd_tvb, tvbuff_t *p_tvb, tvbuff_t *d_tvb,
+ packet_info *pinfo, proto_tree *parent_tree)
+{
+ smb_info_t *smb_info = pinfo->private_data;
+ smb_transact_info_t *trp = smb_info->sip->extra_info;
+ int offset = 0, start_offset;
+ guint16 cmd;
+ guint16 status;
+ int convert;
+ const struct lanman_desc *lanman;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ guint descriptor_len;
+ const gchar *param_descrip, *data_descrip, *aux_data_descrip = NULL;
+ gboolean has_data;
+ gboolean has_ent_count;
+ guint16 ent_count, aux_count;
+ guint i;
+ proto_item *data_item;
+ proto_tree *data_tree;
+
+ if (!proto_is_protocol_enabled(proto_smb_lanman))
+ return FALSE;
+ if (smb_info->request && p_tvb == NULL) {
+ /*
+ * Requests must have parameters.
+ */
+ return FALSE;
}
- else {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Function Code: Unknown LANMAN Request: %u", FunctionCode);
+ pinfo->current_proto = "LANMAN";
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LANMAN");
}
- }
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb_lanman,
+ pd_tvb, 0, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_lanman);
+ }
- loc_offset += 2;
+ if (smb_info->request) { /* this is a request */
+ /* function code */
+ cmd = tvb_get_letohs(p_tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request", val_to_str(cmd, commands, "Unknown Command (%u)"));
+ }
+ proto_tree_add_uint(tree, hf_function_code, p_tvb, offset, 2,
+ cmd);
+ offset += 2;
+
+ /*
+ * If we haven't already done so, save the function code in
+ * the structure we were handed, so that it's available to
+ * the code parsing the reply, and initialize the detail
+ * level to -1, meaning "unknown".
+ */
+ if (!pinfo->fd->flags.visited) {
+ trp->lanman_cmd = cmd;
+ trp->info_level = -1;
+ trp->param_descrip=NULL;
+ trp->data_descrip=NULL;
+ trp->aux_data_descrip=NULL;
+ }
+
+ /* parameter descriptor */
+ descriptor_len = tvb_strsize(p_tvb, offset);
+ proto_tree_add_item(tree, hf_param_desc, p_tvb, offset,
+ descriptor_len, TRUE);
+ param_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * Save the parameter descriptor for future use.
+ */
+ g_assert(trp->param_descrip == NULL);
+ trp->param_descrip = g_strdup(param_descrip);
+ }
+ offset += descriptor_len;
+
+ /* return descriptor */
+ descriptor_len = tvb_strsize(p_tvb, offset);
+ proto_tree_add_item(tree, hf_return_desc, p_tvb, offset,
+ descriptor_len, TRUE);
+ data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * Save the return descriptor for future use.
+ */
+ g_assert(trp->data_descrip == NULL);
+ trp->data_descrip = g_strdup(data_descrip);
+ }
+ offset += descriptor_len;
+
+ lanman = find_lanman(cmd);
+
+ /* request parameters */
+ start_offset = offset;
+ offset = dissect_request_parameters(p_tvb, offset, pinfo, tree,
+ param_descrip, lanman->req, &has_data);
+
+ /* auxiliary data descriptor */
+ if (tvb_reported_length_remaining(p_tvb, offset) > 0){
+ /*
+ * There are more parameters left, so the next
+ * item is the auxiliary data descriptor.
+ */
+ descriptor_len = tvb_strsize(p_tvb, offset);
+ proto_tree_add_item(tree, hf_aux_data_desc, p_tvb, offset,
+ descriptor_len, TRUE);
+ aux_data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * Save the auxiliary data descriptor for
+ * future use.
+ */
+ g_assert(trp->aux_data_descrip == NULL);
+ trp->aux_data_descrip =
+ g_strdup(aux_data_descrip);
+ }
+ offset += descriptor_len;
+ }
+
+ /* reset offset, we now start dissecting the data area */
+ offset = 0;
+ if (has_data && d_tvb && tvb_reported_length(d_tvb) != 0) {
+ /*
+ * There's a send buffer item in the descriptor
+ * string, and the data count in the transaction
+ * is non-zero, so there's data to dissect.
+ */
+
+ if (lanman->req_data_item != NULL) {
+ /*
+ * Create a protocol tree item for the data.
+ */
+ data_item = (*lanman->req_data_item)(d_tvb,
+ pinfo, tree, offset);
+ data_tree = proto_item_add_subtree(data_item,
+ *lanman->ett_req_data);
+ } else {
+ /*
+ * Just leave it at the top level.
+ */
+ data_item = NULL;
+ data_tree = tree;
+ }
+
+ /* data */
+ offset = dissect_transact_data(d_tvb, offset, -1,
+ pinfo, data_tree, data_descrip, lanman->req_data,
+ &aux_count); /* XXX - what about strings? */
+
+ /* auxiliary data */
+ if (aux_data_descrip != NULL) {
+ for (i = 0; i < aux_count; i++) {
+ offset = dissect_transact_data(d_tvb,
+ offset, -1, pinfo, data_tree,
+ aux_data_descrip,
+ lanman->req_aux_data, NULL);
+ }
+ }
+
+ if (data_item != NULL) {
+ /*
+ * Set the length of the protocol tree item
+ * for the data.
+ */
+ proto_item_set_len(data_item, offset);
+ }
+ }
+ } else {
+ /*
+ * This is a response.
+ * Have we seen the request to which it's a response?
+ */
+ if (trp == NULL)
+ return FALSE; /* no - can't dissect it */
+
+ /* ok we have seen this one before */
+
+ /* if it looks like an interim response, update COL_INFO and return */
+ if( ( (p_tvb==NULL) || (tvb_reported_length(p_tvb)==0) )
+ && ( (d_tvb==NULL) || (tvb_reported_length(d_tvb)==0) ) ){
+ /* command */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Interim Response",
+ val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
+ }
+ proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0, trp->lanman_cmd);
+ return TRUE;
+ }
+
+ /* command */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Response",
+ val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
+ }
+ proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0,
+ trp->lanman_cmd);
+
+ lanman = find_lanman(trp->lanman_cmd);
+
+ /* response parameters */
+
+ /* status */
+ status = tvb_get_letohs(p_tvb, offset);
+ proto_tree_add_uint(tree, hf_status, p_tvb, offset, 2, status);
+ offset += 2;
+
+ /* convert */
+ convert = tvb_get_letohs(p_tvb, offset);
+ proto_tree_add_uint(tree, hf_convert, p_tvb, offset, 2, convert);
+ offset += 2;
+
+ /* rest of the parameters */
+ offset = dissect_response_parameters(p_tvb, offset, pinfo, tree,
+ trp->param_descrip, lanman->resp, &has_data,
+ &has_ent_count, &ent_count);
+
+ /* reset offset, we now start dissecting the data area */
+ offset = 0;
+ /* data */
+ if (has_data && d_tvb && tvb_reported_length(d_tvb) > 0) {
+ /*
+ * There's a receive buffer item in the descriptor
+ * string, and the data count in the transaction
+ * is non-zero, so there's data to dissect.
+ */
+ dissect_response_data(d_tvb, pinfo, convert, tree,
+ smb_info, lanman, has_ent_count, ent_count);
+ }
+ }
- ParameterDescriptor = pd + loc_offset;
+ return TRUE;
+}
- si.request_val -> trans_response_seen = 0;
+void
+proto_register_pipe_lanman(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_function_code,
+ { "Function Code", "lanman.function_code", FT_UINT16, BASE_DEC,
+ VALS(commands), 0, "LANMAN Function Code/Command", HFILL }},
- if (si.request_val -> last_param_descrip) g_free(si.request_val -> last_param_descrip);
- si.request_val -> last_param_descrip = g_malloc(strlen(ParameterDescriptor) + 1);
- if (si.request_val -> last_param_descrip)
- strcpy(si.request_val -> last_param_descrip, ParameterDescriptor);
+ { &hf_param_desc,
+ { "Parameter Descriptor", "lanman.param_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Parameter Descriptor", HFILL }},
- if (tree) {
+ { &hf_return_desc,
+ { "Return Descriptor", "lanman.ret_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Return Descriptor", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ParameterDescriptor) + 1, "Parameter Descriptor: %s", ParameterDescriptor);
+ { &hf_aux_data_desc,
+ { "Auxiliary Data Descriptor", "lanman.aux_data_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Auxiliary Data Descriptor", HFILL }},
- }
+ { &hf_detail_level,
+ { "Detail Level", "lanman.level", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Detail Level", HFILL }},
- loc_offset += strlen(ParameterDescriptor) + 1;
+ { &hf_recv_buf_len,
+ { "Receive Buffer Length", "lanman.recv_buf_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Receive Buffer Length", HFILL }},
- ReturnDescriptor = pd + loc_offset;
+ { &hf_send_buf_len,
+ { "Send Buffer Length", "lanman.send_buf_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Send Buffer Length", HFILL }},
- if (si.request_val -> last_data_descrip) g_free(si.request_val -> last_data_descrip);
- si.request_val -> last_data_descrip = g_malloc(strlen(ReturnDescriptor) + 1);
- if (si.request_val -> last_data_descrip)
- strcpy(si.request_val -> last_data_descrip, ReturnDescriptor);
+ { &hf_continuation_from,
+ { "Continuation from message in frame", "lanman.continuation_from", FT_UINT32, BASE_DEC,
+ NULL, 0, "This is a LANMAN continuation from the message in the frame in question", HFILL }},
- if (tree) {
+ { &hf_status,
+ { "Status", "lanman.status", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Return status", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, strlen(ReturnDescriptor) + 1, "Return Descriptor: %s", ReturnDescriptor);
+ { &hf_convert,
+ { "Convert", "lanman.convert", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Convert", HFILL }},
- }
+ { &hf_ecount,
+ { "Entry Count", "lanman.entry_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Entries", HFILL }},
- loc_offset += strlen(ReturnDescriptor) + 1;
+ { &hf_acount,
+ { "Available Entries", "lanman.available_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Available Entries", HFILL }},
- if (tree) {
+ { &hf_share_name,
+ { "Share Name", "lanman.share.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Share", HFILL }},
- int i = 0; /* Counter for names below */
- char *name = NULL;
+ { &hf_share_type,
+ { "Share Type", "lanman.share.type", FT_UINT16, BASE_DEC,
+ VALS(share_type_vals), 0, "LANMAN Type of Share", HFILL }},
- dissect_transact_engine_init(pd, ParameterDescriptor, ReturnDescriptor,SMB_offset, loc_offset, ParameterCount, DataOffset, DataCount);
+ { &hf_share_comment,
+ { "Share Comment", "lanman.share.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Comment", HFILL }},
- if (lanman) name = lanman -> req[i]; /* Must be OK ... */
+ { &hf_share_permissions,
+ { "Share Permissions", "lanman.share.permissions", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Permissions on share", HFILL }},
- while (dissect_transact_next(pd, name, dirn, lanman_tree))
- if (name) name = lanman -> req[++i];
- }
+ { &hf_share_max_uses,
+ { "Share Max Uses", "lanman.share.max_uses", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Max connections allowed to share", HFILL }},
- break;
-
- }
- }
- else { /* Dirn == 0, response */
- guint16 Status;
- guint16 Convert;
- guint16 EntCount;
- guint16 AvailCount;
- int i;
- proto_tree *server_tree = NULL, *flags_tree = NULL, *share_tree = NULL;
+ { &hf_share_current_uses,
+ { "Share Current Uses", "lanman.share.current_uses", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Current connections to share", HFILL }},
- FunctionCode = si.request_val -> last_lanman_cmd;
+ { &hf_share_path,
+ { "Share Path", "lanman.share.path", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Path", HFILL }},
- /*
- * If we have already seen the response to this transact, simply
- * record it as a continuation ...
- */
+ { &hf_share_password,
+ { "Share Password", "lanman.share.password", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Password", HFILL }},
-/*$$ printf("TransResponseSeen = %u\n", si.request_val -> trans_response_seen);
-*/
- if (si.request_val -> trans_response_seen == 1) {
+ { &hf_server_name,
+ { "Server Name", "lanman.server.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Server", HFILL }},
- if (check_col(fd, COL_INFO)) {
- col_set_str(fd, COL_INFO, "Transact Continuation");
- }
-
- if (tree) {
+ { &hf_server_major,
+ { "Major Version", "lanman.server.major", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Major Version", HFILL }},
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, SMB_offset + DataOffset, END_OF_FRAME, FALSE);
+ { &hf_server_minor,
+ { "Minor Version", "lanman.server.minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Minor Version", HFILL }},
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
+ { &hf_server_comment,
+ { "Server Comment", "lanman.server.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Server Comment", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, END_OF_FRAME, "Payload: %s", format_text(pd + SMB_offset + DataOffset, END_OF_FRAME));
+ { &hf_abytes,
+ { "Available Bytes", "lanman.available_bytes", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Available Bytes", HFILL }},
- }
+ { &hf_current_time,
+ { "Current Date/Time", "lanman.current_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Current date and time, in seconds since 00:00:00, January 1, 1970", HFILL }},
- return TRUE;
+ { &hf_msecs,
+ { "Milliseconds", "lanman.msecs", FT_UINT32, BASE_DEC,
+ NULL, 0, "LANMAN Milliseconds since arbitrary time in the past (typically boot time)", HFILL }},
+ { &hf_hour,
+ { "Hour", "lanman.hour", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current hour", HFILL }},
- }
+ { &hf_minute,
+ { "Minute", "lanman.minute", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current minute", HFILL }},
- si.request_val -> trans_response_seen = 1;
+ { &hf_second,
+ { "Second", "lanman.second", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current second", HFILL }},
- switch (FunctionCode) {
+ { &hf_hundredths,
+ { "Hundredths of a second", "lanman.hundredths", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current hundredths of a second", HFILL }},
- case NETSHAREENUM:
+ { &hf_tzoffset,
+ { "Time Zone Offset", "lanman.tzoffset", FT_INT16, BASE_DEC,
+ NULL, 0, "LANMAN Offset of time zone from GMT, in minutes", HFILL }},
- if (check_col(fd, COL_INFO)) {
+ { &hf_timeinterval,
+ { "Time Interval", "lanman.timeinterval", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN .0001 second units per clock tick", HFILL }},
- col_set_str(fd, COL_INFO,
- is_interim_response ? "NetShareEnum Interim Response" :
- "NetShareEnum Response");
+ { &hf_day,
+ { "Day", "lanman.day", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current day", HFILL }},
- }
+ { &hf_month,
+ { "Month", "lanman.month", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current month", HFILL }},
- if (tree) {
+ { &hf_year,
+ { "Year", "lanman.year", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Current year", HFILL }},
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, END_OF_FRAME, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
-
- proto_tree_add_text(lanman_tree, NullTVB, 0, 0, "Function Code: NetShareEnum");
+ { &hf_weekday,
+ { "Weekday", "lanman.weekday", FT_UINT8, BASE_DEC,
+ VALS(weekday_vals), 0, "LANMAN Current day of the week", HFILL }},
- }
+ { &hf_enumeration_domain,
+ { "Enumeration Domain", "lanman.enumeration_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Domain in which to enumerate servers", HFILL }},
- if (is_interim_response) {
+ { &hf_computer_name,
+ { "Computer Name", "lanman.computer_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Computer Name", HFILL }},
- return TRUE; /* no data to dissect */
+ { &hf_user_name,
+ { "User Name", "lanman.user_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN User Name", HFILL }},
- }
+ { &hf_group_name,
+ { "Group Name", "lanman.group_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Group Name", HFILL }},
- si.request_val -> trans_response_seen = 1;
+ { &hf_workstation_domain,
+ { "Workstation Domain", "lanman.workstation_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstation Domain", HFILL }},
- Status = GSHORT(pd, loc_offset);
+ { &hf_workstation_major,
+ { "Workstation Major Version", "lanman.workstation_major", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Workstation Major Version", HFILL }},
- if (tree) {
+ { &hf_workstation_minor,
+ { "Workstation Minor Version", "lanman.workstation_minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Workstation Minor Version", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Status: %u", Status);
+ { &hf_logon_domain,
+ { "Logon Domain", "lanman.logon_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Logon Domain", HFILL }},
- }
+ { &hf_other_domains,
+ { "Other Domains", "lanman.other_domains", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Other Domains", HFILL }},
- loc_offset += 2;
+ { &hf_password,
+ { "Password", "lanman.password", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Password", HFILL }},
- Convert = GSHORT(pd, loc_offset);
+ { &hf_workstation_name,
+ { "Workstation Name", "lanman.workstation_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstation Name", HFILL }},
- if (tree) {
+ { &hf_ustruct_size,
+ { "Length of UStruct", "lanman.ustruct_size", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN UStruct Length", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Convert: %u", Convert);
+ { &hf_logon_code,
+ { "Logon Code", "lanman.logon_code", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Logon Code", HFILL }},
- }
+ { &hf_privilege_level,
+ { "Privilege Level", "lanman.privilege_level", FT_UINT16, BASE_DEC,
+ VALS(privilege_vals), 0, "LANMAN Privilege Level", HFILL }},
- loc_offset += 2;
+ { &hf_operator_privileges,
+ { "Operator Privileges", "lanman.operator_privileges", FT_UINT32, BASE_DEC,
+ VALS(op_privilege_vals), 0, "LANMAN Operator Privileges", HFILL }},
- EntCount = GSHORT(pd, loc_offset);
+ { &hf_num_logons,
+ { "Number of Logons", "lanman.num_logons", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Logons", HFILL }},
- if (tree) {
+ { &hf_bad_pw_count,
+ { "Bad Password Count", "lanman.bad_pw_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of incorrect passwords entered since last successful login", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Entry Count: %u", EntCount);
+ { &hf_last_logon,
+ { "Last Logon Date/Time", "lanman.last_logon", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time of last logon", HFILL }},
- }
+ { &hf_last_logoff,
+ { "Last Logoff Date/Time", "lanman.last_logoff", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time of last logoff", HFILL }},
- loc_offset += 2;
+ { &hf_logoff_time,
+ { "Logoff Date/Time", "lanman.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user should log off", HFILL }},
- AvailCount = GSHORT(pd, loc_offset);
+ { &hf_kickoff_time,
+ { "Kickoff Date/Time", "lanman.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user will be logged off", HFILL }},
- if (tree) {
+ { &hf_password_age,
+ { "Password Age", "lanman.password_age", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Time since user last changed his/her password", HFILL }},
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Available Entries: %u", AvailCount);
+ { &hf_password_can_change,
+ { "Password Can Change", "lanman.password_can_change", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user can change their password", HFILL }},
- }
+ { &hf_password_must_change,
+ { "Password Must Change", "lanman.password_must_change", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user must change their password", HFILL }},
- loc_offset += 2;
+ { &hf_script_path,
+ { "Script Path", "lanman.script_path", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Pathname of user's logon script", HFILL }},
- if (tree) {
+ { &hf_logoff_code,
+ { "Logoff Code", "lanman.logoff_code", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Logoff Code", HFILL }},
- ti = proto_tree_add_text(lanman_tree, NullTVB, loc_offset, AvailCount * 20, "Available Shares");
+ { &hf_duration,
+ { "Duration of Session", "lanman.duration", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Number of seconds the user was logged on", HFILL }},
- share_tree = proto_item_add_subtree(ti, ett_lanman_shares);
+ { &hf_comment,
+ { "Comment", "lanman.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Comment", HFILL }},
- }
+ { &hf_user_comment,
+ { "User Comment", "lanman.user_comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN User Comment", HFILL }},
- for (i = 1; i <= EntCount; i++) {
- const gchar *Share = pd + loc_offset;
- guint32 Flags;
- const gchar *Comment;
- proto_tree *share = NULL;
- proto_item *ti = NULL;
+ { &hf_full_name,
+ { "Full Name", "lanman.full_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Full Name", HFILL }},
- if (tree) {
+ { &hf_homedir,
+ { "Home Directory", "lanman.homedir", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Home Directory", HFILL }},
- ti = proto_tree_add_text(share_tree, NullTVB, loc_offset, 20, "Share %s", Share);
- share = proto_item_add_subtree(ti, ett_lanman_share);
+ { &hf_parameters,
+ { "Parameters", "lanman.parameters", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Parameters", HFILL }},
+ { &hf_logon_server,
+ { "Logon Server", "lanman.logon_server", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Logon Server", HFILL }},
- }
-
- if (tree) {
-
- proto_tree_add_text(share, NullTVB, loc_offset, 13, "Share Name: %s", Share);
+ /* XXX - we should have a value_string table for this */
+ { &hf_country_code,
+ { "Country Code", "lanman.country_code", FT_UINT16, BASE_DEC,
+ VALS(ms_country_codes), 0, "LANMAN Country Code", HFILL }},
- }
+ { &hf_workstations,
+ { "Workstations", "lanman.workstations", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstations", HFILL }},
- loc_offset += 13;
+ { &hf_max_storage,
+ { "Max Storage", "lanman.max_storage", FT_UINT32, BASE_DEC,
+ NULL, 0, "LANMAN Max Storage", HFILL }},
- loc_offset += 1; /* Pad byte ... */
+ { &hf_units_per_week,
+ { "Units Per Week", "lanman.units_per_week", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Units Per Week", HFILL }},
- Flags = GSHORT(pd, loc_offset);
+ { &hf_logon_hours,
+ { "Logon Hours", "lanman.logon_hours", FT_BYTES, BASE_NONE,
+ NULL, 0, "LANMAN Logon Hours", HFILL }},
- if (tree) {
+ /* XXX - we should have a value_string table for this */
+ { &hf_code_page,
+ { "Code Page", "lanman.code_page", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Code Page", HFILL }},
- proto_tree_add_text(share, NullTVB, loc_offset, 2, "Share Type: %s",
- val_to_str(Flags, share_type_vals, "Unknown (%u)"));
+ { &hf_new_password,
+ { "New Password", "lanman.new_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "LANMAN New Password (encrypted)", HFILL }},
- }
+ { &hf_old_password,
+ { "Old Password", "lanman.old_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "LANMAN Old Password (encrypted)", HFILL }},
- loc_offset += 2;
+ { &hf_reserved,
+ { "Reserved", "lanman.reserved", FT_UINT32, BASE_HEX,
+ NULL, 0, "LANMAN Reserved", HFILL }},
- /* XXX - should check whether all of the string is within the
- frame. */
- string_offset = SMB_offset + DataOffset + (GWORD(pd, loc_offset) & 0xFFFF) - Convert;
- if (IS_DATA_IN_FRAME(string_offset))
- Comment = pd + string_offset;
- else
- Comment = "<String goes past end of frame>";
+ };
+ static gint *ett[] = {
+ &ett_lanman,
+ &ett_lanman_unknown_entries,
+ &ett_lanman_unknown_entry,
+ &ett_lanman_servers,
+ &ett_lanman_server,
+ &ett_lanman_groups,
+ &ett_lanman_shares,
+ &ett_lanman_share,
+ };
- if (tree) {
+ proto_smb_lanman = proto_register_protocol(
+ "Microsoft Windows Lanman Remote API Protocol", "LANMAN", "lanman");
+ proto_register_field_array(proto_smb_lanman, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
- proto_tree_add_text(share, NullTVB, loc_offset, 4, "Share Comment: %s", Comment);
+static heur_dissector_list_t smb_transact_heur_subdissector_list;
+gboolean
+dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree,
+ proto_tree *tree, guint32 fid)
+{
+ dcerpc_private_info dcerpc_priv;
+ smb_info_t *smb_priv = (smb_info_t *)pinfo->private_data;
+ gboolean result;
+ gboolean save_fragmented;
+
+ dcerpc_priv.transport_type = DCERPC_TRANSPORT_SMB;
+ dcerpc_priv.data.smb.fid = fid;
+
+ pinfo->private_data = &dcerpc_priv;
+
+ /* offer desegmentation service to DCERPC */
+ pinfo->can_desegment=0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
+ if(smb_dcerpc_reassembly){
+ pinfo->can_desegment=2;
}
- loc_offset += 4;
-
- }
-
- break;
-
- case NETSERVERENUM2:
-
- if (check_col(fd, COL_INFO)) {
-
- col_set_str(fd, COL_INFO,
- is_interim_response ? "NetServerEnum2 Interim Response" :
- "NetServerEnum2 Response");
- }
-
- if (tree) {
-
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, END_OF_FRAME, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
-
- proto_tree_add_text(lanman_tree, NullTVB, 0, 0, "Function Code: NetServerEnum2");
-
- }
-
- if (is_interim_response) {
-
- return TRUE; /* no data to dissect */
-
- }
-
- Status = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Status: %u", Status);
-
- }
-
- loc_offset += 2;
-
- Convert = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Convert: %u", Convert);
-
- }
-
- loc_offset += 2;
-
- EntCount = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Entry Count: %u", EntCount);
-
- }
-
- loc_offset += 2;
-
- AvailCount = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Available Entries: %u", AvailCount);
-
- }
-
- loc_offset += 2;
-
- if (tree) {
-
- ti = proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 26 * AvailCount, "Servers");
- if (ti == NULL) {
-
- printf("Null value returned from proto_tree_add_text\n");
- exit(1);
-
+ save_fragmented = pinfo->fragmented;
+
+ /* see if this packet is already desegmented */
+ if(smb_dcerpc_reassembly && pinfo->fd->flags.visited){
+ fragment_data *fd_head;
+ tvbuff_t *new_tvb;
+
+ fd_head=fragment_get(pinfo, pinfo->fd->num ,
+ dcerpc_fragment_table);
+ if(fd_head && fd_head->flags&FD_DEFRAGMENTED){
+ proto_tree *tr;
+ proto_item *it;
+ fragment_data *fd;
+
+ new_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->datalen, fd_head->datalen);
+ tvb_set_child_real_data_tvbuff(d_tvb, new_tvb);
+ add_new_data_source(pinfo->fd, new_tvb,
+ "DCERPC over SMB");
+ pinfo->fragmented=FALSE;
+
+ d_tvb=new_tvb;
+
+ /* list what segments we have */
+ it = proto_tree_add_text(tree, d_tvb, 0, -1, "Fragments");
+ tr = proto_item_add_subtree(it, ett_smb_pipe_fragments);
+ for(fd=fd_head->next;fd;fd=fd->next){
+ proto_tree_add_text(tr, d_tvb, fd->offset, fd->len,
+ "Frame:%u Data:%u-%u",
+ fd->frame, fd->offset,
+ fd->offset+fd->len-1);
+ }
+ }
}
- server_tree = proto_item_add_subtree(ti, ett_lanman_servers);
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb,
+ pinfo, parent_tree);
+ pinfo->private_data = smb_priv;
+
+ /* check if dissector wanted us to desegment the data */
+ if(smb_dcerpc_reassembly && !pinfo->fd->flags.visited && pinfo->desegment_len){
+ fragment_add(d_tvb, 0, pinfo, pinfo->fd->num,
+ dcerpc_fragment_table,
+ 0, tvb_length(d_tvb), TRUE);
+ fragment_set_tot_len(pinfo, pinfo->fd->num,
+ dcerpc_fragment_table,
+ pinfo->desegment_len+tvb_length(d_tvb));
+ /* since the other fragments are in normal ReadAndX and WriteAndX calls
+ we must make sure we can map FID values to this defragmentation
+ session */
+ /* first remove any old mappings */
+ if(g_hash_table_lookup(smb_priv->ct->dcerpc_fid_to_frame, (void *)fid)){
+ g_hash_table_remove(smb_priv->ct->dcerpc_fid_to_frame, (void *)fid);
+ }
+ g_hash_table_insert(smb_priv->ct->dcerpc_fid_to_frame, (void *)fid,
+ (void *)pinfo->fd->num);
+ }
+ /* clear out the variables */
+ pinfo->can_desegment=0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
- }
+ if (!result)
+ call_dissector(data_handle, d_tvb, pinfo, parent_tree);
- /* Make sure we don't go past the end of the capture buffer */
+ pinfo->fragmented = save_fragmented;
+ return TRUE;
+}
- for (i = 1; (i <= EntCount) && ((pi.captured_len - loc_offset) >= 16); i++) {
- const gchar *Server = pd + loc_offset;
- gint8 ServerMajor;
- guint ServerMinor;
- guint32 ServerFlags;
- const gchar *Comment;
- proto_tree *server = NULL;
- proto_item *ti;
+void
+proto_register_pipe_dcerpc(void)
+{
+ register_heur_dissector_list("smb_transact", &smb_transact_heur_subdissector_list);
+}
- if (tree) {
+#define CALL_NAMED_PIPE 0x54
+#define WAIT_NAMED_PIPE 0x53
+#define PEEK_NAMED_PIPE 0x23
+#define Q_NM_P_HAND_STATE 0x21
+#define SET_NM_P_HAND_STATE 0x01
+#define Q_NM_PIPE_INFO 0x22
+#define TRANSACT_NM_PIPE 0x26
+#define RAW_READ_NM_PIPE 0x11
+#define RAW_WRITE_NM_PIPE 0x31
+
+static const value_string functions[] = {
+ {CALL_NAMED_PIPE, "CallNamedPipe"},
+ {WAIT_NAMED_PIPE, "WaitNamedPipe"},
+ {PEEK_NAMED_PIPE, "PeekNamedPipe"},
+ {Q_NM_P_HAND_STATE, "QNmPHandState"},
+ {SET_NM_P_HAND_STATE, "SetNmPHandState"},
+ {Q_NM_PIPE_INFO, "QNmPipeInfo"},
+ {TRANSACT_NM_PIPE, "TransactNmPipe"},
+ {RAW_READ_NM_PIPE, "RawReadNmPipe"},
+ {RAW_WRITE_NM_PIPE, "RawWriteNmPipe"},
+ {0, NULL}
+};
- ti = proto_tree_add_text(server_tree, NullTVB, loc_offset,
- (si.request_val -> last_level) ? 26 : 16,
- "Server %s", Server);
- server = proto_item_add_subtree(ti, ett_lanman_server);
+static const value_string pipe_status[] = {
+ {1, "Disconnected by server"},
+ {2, "Listening"},
+ {3, "Connection to server is OK"},
+ {4, "Server end of pipe is closed"},
+ {0, NULL}
+};
+#define PIPE_LANMAN 1
+#define PIPE_DCERPC 2
+/* decode the SMB pipe protocol
+ for requests
+ pipe is the name of the pipe, e.g. LANMAN
+ smb_info->trans_subcmd is set to the symbolic constant matching the mailslot name
+ for responses
+ pipe is NULL
+ smb_info->trans_subcmd gives us which pipe this response is for
+*/
+gboolean
+dissect_pipe_smb(tvbuff_t *sp_tvb, tvbuff_t *s_tvb, tvbuff_t *pd_tvb,
+ tvbuff_t *p_tvb, tvbuff_t *d_tvb, const char *pipe,
+ packet_info *pinfo, proto_tree *tree)
+{
+ smb_info_t *smb_info;
+ smb_transact_info_t *tri;
+ guint sp_len;
+ proto_item *pipe_item = NULL;
+ proto_tree *pipe_tree = NULL;
+ int offset;
+ int trans_subcmd;
+ int function;
+ int fid = -1;
+ guint16 info_level;
+
+ if (!proto_is_protocol_enabled(proto_smb_pipe))
+ return FALSE;
+ pinfo->current_proto = "SMB Pipe";
+
+ smb_info = pinfo->private_data;
+
+ /*
+ * Set the columns.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB Pipe");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ smb_info->request ? "Request" : "Response");
}
+ if (smb_info->sip != NULL)
+ tri = smb_info->sip->extra_info;
+ else
+ tri = NULL;
+
+ /*
+ * Set up a subtree for the pipe protocol. (It might not contain
+ * anything.)
+ */
+ if (sp_tvb != NULL)
+ sp_len = tvb_length(sp_tvb);
+ else
+ sp_len = 0;
if (tree) {
-
- proto_tree_add_text(server, NullTVB, loc_offset, 16, "Server Name: %s", Server);
-
+ pipe_item = proto_tree_add_item(tree, proto_smb_pipe,
+ sp_tvb, 0, sp_len, FALSE);
+ pipe_tree = proto_item_add_subtree(pipe_item, ett_smb_pipe);
}
-
- loc_offset += 16;
-
- if (si.request_val -> last_level) { /* Print out the rest of the info */
-
- ServerMajor = GBYTE(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(server, NullTVB, loc_offset, 1, "Major Version: %u", ServerMajor);
-
- }
-
- loc_offset += 1;
-
- ServerMinor = GBYTE(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(server, NullTVB, loc_offset, 1, "Minor Version: %u", ServerMinor);
-
- }
-
- loc_offset += 1;
-
- ServerFlags = GWORD(pd, loc_offset);
-
- if (tree) {
-
- ti = proto_tree_add_text(server, NullTVB, loc_offset, 4, "Server Type: 0x%08X", ServerFlags);
- flags_tree = proto_item_add_subtree(ti, ett_lanman_flags);
- dissect_server_flags(flags_tree, loc_offset, 4, ServerFlags);
-
- }
-
- loc_offset += 4;
-
- /* XXX - should check whether all of the string is within the
- frame. */
- string_offset = SMB_offset + DataOffset + (GWORD(pd, loc_offset) & 0xFFFF) - Convert;
- if (IS_DATA_IN_FRAME(string_offset))
- Comment = pd + string_offset;
- else
- Comment = "<String goes past end of frame>";
-
- if (tree) {
-
- proto_tree_add_text(server, NullTVB, loc_offset, 4, "Server Comment: %s", Comment);
-
- }
-
- loc_offset += 4;
-
+ offset = 0;
+
+ /*
+ * Do we have any setup words at all?
+ */
+ if (s_tvb != NULL && tvb_length(s_tvb) != 0) {
+ /*
+ * Yes. The first of them is the function.
+ */
+ function = tvb_get_letohs(s_tvb, offset);
+ proto_tree_add_uint(pipe_tree, hf_pipe_function, s_tvb,
+ offset, 2, function);
+ offset += 2;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ val_to_str(function, functions, "Unknown function (0x%04x)"),
+ smb_info->request ? "Request" : "Response");
+ }
+ if (tri != NULL)
+ tri->function = function;
+
+ /*
+ * The second of them depends on the function.
+ */
+ switch (function) {
+
+ case CALL_NAMED_PIPE:
+ case WAIT_NAMED_PIPE:
+ /*
+ * It's a priority.
+ */
+ proto_tree_add_item(pipe_tree, hf_pipe_priority, s_tvb,
+ offset, 2, TRUE);
+ break;
+
+ case PEEK_NAMED_PIPE:
+ case Q_NM_P_HAND_STATE:
+ case SET_NM_P_HAND_STATE:
+ case Q_NM_PIPE_INFO:
+ case TRANSACT_NM_PIPE:
+ case RAW_READ_NM_PIPE:
+ case RAW_WRITE_NM_PIPE:
+ /*
+ * It's a FID.
+ */
+ fid = tvb_get_letohs(s_tvb, 2);
+ add_fid(s_tvb, pinfo, pipe_tree, offset, 2, fid);
+ if (tri != NULL)
+ tri->fid = fid;
+ break;
+
+ default:
+ /*
+ * It's something unknown.
+ * XXX - put it into the tree?
+ */
+ break;
+ }
+ offset += 2;
+ } else {
+ /*
+ * This is either a response or a pipe transaction with
+ * no setup information.
+ *
+ * In the former case, we can get that information from
+ * the matching request, if we saw it.
+ *
+ * In the latter case, there is no function or FID.
+ */
+ if (tri != NULL && tri->function != -1) {
+ function = tri->function;
+ proto_tree_add_uint(pipe_tree, hf_pipe_function, NULL,
+ 0, 0, function);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ val_to_str(function, functions, "Unknown function (0x%04x)"),
+ smb_info->request ? "Request" : "Response");
+ }
+ fid = tri->fid;
+ if (fid != -1)
+ add_fid(NULL, pinfo, pipe_tree, 0, 0, fid);
+ } else {
+ function = -1;
+ fid = -1;
+ }
}
- }
-
- break;
-
- default:
-
- lanman = find_lanman(si.request_val -> last_lanman_cmd);
-
- if (check_col(fd, COL_INFO)) {
-
- if (lanman) {
- col_add_fstr(fd, COL_INFO, "%s %sResponse", lanman -> lanman_name,
- is_interim_response ? "Interim " : "");
- }
- else {
- col_add_fstr(fd, COL_INFO, "Unknown LANMAN %sResponse: %u",
- is_interim_response ? "Interim " : "", FunctionCode);
+ /*
+ * XXX - put the byte count and the pipe name into the tree as well;
+ * that requires us to fetch a possibly-Unicode string.
+ */
+
+ if(smb_info->request){
+ if(strncmp(pipe,"LANMAN",6) == 0){
+ trans_subcmd=PIPE_LANMAN;
+ } else {
+ /* assume it is DCERPC */
+ trans_subcmd=PIPE_DCERPC;
+ }
+
+ if (!pinfo->fd->flags.visited)
+ tri->trans_subcmd = trans_subcmd;
+ } else
+ trans_subcmd = tri->trans_subcmd;
+
+ if (tri == NULL) {
+ /*
+ * We don't know what type of pipe transaction this
+ * was, so indicate that we didn't dissect it.
+ */
+ return FALSE;
}
- }
- if (tree) {
-
- ti = proto_tree_add_item(parent, proto_smb_lanman, NullTVB, loc_offset, END_OF_FRAME, FALSE);
- lanman_tree = proto_item_add_subtree(ti, ett_lanman);
- if (lanman) {
- proto_tree_add_text(lanman_tree, NullTVB, 0, 0, "%s Response", lanman -> lanman_name);
- }
- else {
- proto_tree_add_text(lanman_tree, NullTVB, 0, 0, "Function Code: Unknown LANMAN Response: %u", FunctionCode);
+ switch (function) {
+
+ case CALL_NAMED_PIPE:
+ case TRANSACT_NM_PIPE:
+ switch(trans_subcmd){
+
+ case PIPE_LANMAN:
+ return dissect_pipe_lanman(pd_tvb, p_tvb, d_tvb, pinfo,
+ tree);
+ break;
+
+ case PIPE_DCERPC:
+ /*
+ * Only dissect this if we know the FID.
+ */
+ if (fid != -1) {
+ if (d_tvb == NULL)
+ return FALSE;
+ return dissect_pipe_dcerpc(d_tvb, pinfo, tree,
+ pipe_tree, fid);
+ }
+ break;
+ }
+ break;
+
+ case -1:
+ /*
+ * We don't know the function; we dissect only LANMAN
+ * pipe messages, not RPC pipe messages, in that case.
+ */
+ switch(trans_subcmd){
+ case PIPE_LANMAN:
+ return dissect_pipe_lanman(pd_tvb, p_tvb, d_tvb, pinfo,
+ tree);
+ break;
+ }
+ break;
+
+ case WAIT_NAMED_PIPE:
+ break;
+
+ case PEEK_NAMED_PIPE:
+ /*
+ * Request contains no parameters or data.
+ */
+ if (!smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+ offset = 0;
+ proto_tree_add_item(pipe_tree, hf_pipe_peek_available,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree, hf_pipe_peek_remaining,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree, hf_pipe_peek_status,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ }
+ break;
+
+ case Q_NM_P_HAND_STATE:
+ /*
+ * Request contains no parameters or data.
+ */
+ if (!smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+ offset = dissect_ipc_state(p_tvb, pinfo, pipe_tree, 0,
+ FALSE);
+ }
+ break;
+
+ case SET_NM_P_HAND_STATE:
+ /*
+ * Response contains no parameters or data.
+ */
+ if (smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+ offset = dissect_ipc_state(p_tvb, pinfo, pipe_tree, 0,
+ TRUE);
+ }
+ break;
+
+ case Q_NM_PIPE_INFO:
+ offset = 0;
+ if (smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+
+ /*
+ * Request contains an information level.
+ */
+ info_level = tvb_get_letohs(p_tvb, offset);
+ proto_tree_add_uint(pipe_tree, hf_pipe_getinfo_info_level,
+ p_tvb, offset, 2, info_level);
+ offset += 2;
+ if (!pinfo->fd->flags.visited)
+ tri->info_level = info_level;
+ } else {
+ guint8 pipe_namelen;
+
+ if (d_tvb == NULL)
+ return FALSE;
+
+ switch (tri->info_level) {
+
+ case 1:
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_output_buffer_size,
+ d_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_input_buffer_size,
+ d_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_maximum_instances,
+ d_tvb, offset, 1, TRUE);
+ offset += 1;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_current_instances,
+ d_tvb, offset, 1, TRUE);
+ offset += 1;
+ pipe_namelen = tvb_get_guint8(d_tvb, offset);
+ proto_tree_add_uint(pipe_tree,
+ hf_pipe_getinfo_pipe_name_length,
+ d_tvb, offset, 1, pipe_namelen);
+ offset += 1;
+ /* XXX - can this be Unicode? */
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_pipe_name,
+ d_tvb, offset, pipe_namelen, TRUE);
+ break;
+ }
+ }
+ break;
+
+ case RAW_READ_NM_PIPE:
+ /*
+ * Request contains no parameters or data.
+ */
+ if (!smb_info->request) {
+ if (d_tvb == NULL)
+ return FALSE;
+
+ offset = dissect_file_data(d_tvb, pinfo, pipe_tree, 0,
+ tvb_reported_length(d_tvb),
+ tvb_reported_length(d_tvb));
+ }
+ break;
+
+ case RAW_WRITE_NM_PIPE:
+ offset = 0;
+ if (smb_info->request) {
+ if (d_tvb == NULL)
+ return FALSE;
+
+ offset = dissect_file_data(d_tvb, pinfo, pipe_tree,
+ offset, tvb_reported_length(d_tvb),
+ tvb_reported_length(d_tvb));
+ } else {
+ if (p_tvb == NULL)
+ return FALSE;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_write_raw_bytes_written,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ }
+ break;
}
- }
-
- if (is_interim_response) {
-
- return TRUE; /* no data to dissect */
-
- }
-
- Status = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Status: %u", Status);
-
- }
-
- loc_offset += 2;
-
- Convert = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Convert: %u", Convert);
-
- }
-
- loc_offset += 2;
-
- if (tree) {
-
- int i = 0;
- char *name = NULL;
-
- dissect_transact_engine_init(pd, si.request_val -> last_param_descrip, si.request_val -> last_data_descrip, SMB_offset, loc_offset, ParameterCount, DataOffset, DataCount);
-
- if (lanman) name = lanman -> resp[i];
-
- while (dissect_transact_next(pd, name, dirn, lanman_tree))
- if (name) name = lanman -> resp[++i];
-
- }
-
- return TRUE;
- break;
-
- }
-
- }
-
- return FALSE;
-
+ return TRUE;
}
-gboolean
-dissect_pipe_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset, int errcode, int dirn, const u_char *command, int DataOffset, int DataCount, int ParameterOffset, int ParameterCount)
-{
-
- if (!proto_is_protocol_enabled(proto_smb_lanman))
- return FALSE;
-
- if (command != NULL && strcmp(command, "LANMAN") == 0) {
- /* Try to decode a LANMAN */
-
- return dissect_pipe_lanman(pd, offset, fd, parent, tree, si, max_data,
- SMB_offset, errcode, dirn, command, DataOffset,
- DataCount, ParameterOffset, ParameterCount);
-
- }
-
- return FALSE;
-
-}
-
-
-
-
void
-register_proto_smb_pipe( void){
-
-
+proto_register_smb_pipe(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pipe_function,
+ { "Function", "pipe.function", FT_UINT16, BASE_HEX,
+ VALS(functions), 0, "SMB Pipe Function Code", HFILL }},
+ { &hf_pipe_priority,
+ { "Priority", "pipe.priority", FT_UINT16, BASE_DEC,
+ NULL, 0, "SMB Pipe Priority", HFILL }},
+ { &hf_pipe_peek_available,
+ { "Available Bytes", "pipe.peek.available_bytes", FT_UINT16, BASE_DEC,
+ NULL, 0, "Total number of bytes available to be read from the pipe", HFILL }},
+ { &hf_pipe_peek_remaining,
+ { "Bytes Remaining", "pipe.peek.remaining_bytes", FT_UINT16, BASE_DEC,
+ NULL, 0, "Total number of bytes remaining in the message at the head of the pipe", HFILL }},
+ { &hf_pipe_peek_status,
+ { "Pipe Status", "pipe.peek.status", FT_UINT16, BASE_DEC,
+ VALS(pipe_status), 0, "Pipe status", HFILL }},
+ { &hf_pipe_getinfo_info_level,
+ { "Information Level", "pipe.getinfo.info_level", FT_UINT16, BASE_DEC,
+ NULL, 0, "Information level of information to return", HFILL }},
+ { &hf_pipe_getinfo_output_buffer_size,
+ { "Output Buffer Size", "pipe.getinfo.output_buffer_size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Actual size of buffer for outgoing (server) I/O", HFILL }},
+ { &hf_pipe_getinfo_input_buffer_size,
+ { "Input Buffer Size", "pipe.getinfo.input_buffer_size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Actual size of buffer for incoming (client) I/O", HFILL }},
+ { &hf_pipe_getinfo_maximum_instances,
+ { "Maximum Instances", "pipe.getinfo.maximum_instances", FT_UINT8, BASE_DEC,
+ NULL, 0, "Maximum allowed number of instances", HFILL }},
+ { &hf_pipe_getinfo_current_instances,
+ { "Current Instances", "pipe.getinfo.current_instances", FT_UINT8, BASE_DEC,
+ NULL, 0, "Current number of instances", HFILL }},
+ { &hf_pipe_getinfo_pipe_name_length,
+ { "Pipe Name Length", "pipe.getinfo.pipe_name_length", FT_UINT8, BASE_DEC,
+ NULL, 0, "Length of pipe name", HFILL }},
+ { &hf_pipe_getinfo_pipe_name,
+ { "Pipe Name", "pipe.getinfo.pipe_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of pipe", HFILL }},
+ { &hf_pipe_write_raw_bytes_written,
+ { "Bytes Written", "pipe.write_raw.bytes_written", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of bytes written to the pipe", HFILL }},
+ };
static gint *ett[] = {
-
- &ett_lanman,
- &ett_lanman_servers,
- &ett_lanman_server,
- &ett_lanman_shares,
- &ett_lanman_share,
- &ett_lanman_flags
+ &ett_smb_pipe,
+ &ett_smb_pipe_fragments,
};
+ proto_smb_pipe = proto_register_protocol(
+ "SMB Pipe Protocol", "SMB Pipe", "pipe");
- proto_smb_lanman = proto_register_protocol(
- "Microsoft Windows Lanman Protocol", "LANMAN", "lanman");
-
+ proto_register_field_array(proto_smb_pipe, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
+
+void
+proto_reg_handoff_smb_pipe(void)
+{
+ data_handle = find_dissector("data");
+}