[prev in list] [next in list] [prev in thread] [next in thread]
List: ethereal-dev
Subject: [Ethereal-dev] packet-smb-pipe
From: "Pia Sahlberg" <piabar () hotmail ! com>
Date: 2001-07-29 13:37:29
[Download RAW message or body]
Hi list.
(different mailaddress, Im traveling)
3 patches are attached :
the patches must be applied in the order listed below. they depend on
eachother.
smb.patch.1 (tiny): changes to packet_info structure and smb dissector so
the smb dissector can pass important data to subdissector instead of using
hundreds of call parameters.
smb.patch.2 (tiny): one more parameter smb dissector needs to tell
subdissectors.
patch.smb.pipe.diff (54kb): this is the tvbuffified dissector for lanman
protocol.
It is different to the original dissector in several ways.
The patch now correctly matches a response to the Correct request and doesnt
just assume every response matches the last read request.
The patch correctly handles when lanman inserts an extra pad byte between
the parameters and the list of servers/shares in netshareenum-response and
netserverenum2-response.
All implemented calls have all parameters with hf_* fields.
The only calls implemented are netshareenum,netserverenum2.
The other calls in the original implementation could not be converted to
tvbuff and were removed. As soon as I, or anyone else, gets capture files
with any other calls, the remaining calls can be implemented.
I am currently travelling so I have no access to create any interesting
captures at the moment.
The only captures I had on my laptop contained only these two calls.
If anyone mails the list a capturefile with other calls not implemented, I
can implement and test those calls.
Lots of functionality was removed (all calls except netshareenum
netserverenum2) but I think it was nessesary, the other calls could not be
converted in their current implementation.
Use your own judgement for this patch.
_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp
["smb.patch.1" (application/octet-stream)]
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/epan/packet_info.h ethereal/epan/packet_info.h
--- ethereal-orig/epan/packet_info.h Mon Jun 4 17:27:50 2001
+++ ethereal/epan/packet_info.h Sat Jul 28 03:34:17 2001
@@ -119,6 +119,13 @@
guint32 callnumber;
guint32 seq;
} rx; /* fields specific for RX protocol */
+ struct {
+ gboolean request; /* is this a smb request ? */
+ guint16 tid;
+ guint16 pid;
+ guint16 uid;
+ guint16 mid;
+ } smb;
} ps; /* protocol specific data */
} packet_info;
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb.c ethereal/packet-smb.c
--- ethereal-orig/packet-smb.c Wed Jun 20 11:58:48 2001
+++ ethereal/packet-smb.c Sat Jul 28 03:34:12 2001
@@ -10804,6 +10804,7 @@
"Notify all",
"Notify open only"));
+ pi.ps.smb.request = !(flags&0x80);
proto_tree_add_text(flags_tree, NullTVB, offset, 1, "%s",
decode_boolean_bitfield(flags, SMB_FLAGS_DIRN,
8, "Response to client/redirector", "Request to server"));
@@ -10898,6 +10899,7 @@
tid = GSHORT(pd, offset);
si.tid = tid;
+ pi.ps.smb.tid = tid;
if (tree) {
@@ -10911,6 +10913,7 @@
pid = GSHORT(pd, offset);
si.pid = pid;
+ pi.ps.smb.pid = pid;
if (tree) {
@@ -10924,6 +10927,7 @@
uid = GSHORT(pd, offset);
si.uid = uid;
+ pi.ps.smb.uid = uid;
if (tree) {
@@ -10937,6 +10941,7 @@
mid = GSHORT(pd, offset);
si.mid = mid;
+ pi.ps.smb.mid = mid;
if (tree) {
["smb.patch.2" (application/octet-stream)]
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/epan/packet_info.h ethereal/epan/packet_info.h
--- ethereal-orig/epan/packet_info.h Sat Jul 28 03:57:55 2001
+++ ethereal/epan/packet_info.h Sat Jul 28 04:28:12 2001
@@ -125,6 +125,7 @@
guint16 pid;
guint16 uid;
guint16 mid;
+ guint16 ddisp; /* data displacement for trans commands */
} smb;
} ps; /* protocol specific data */
} packet_info;
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb.c ethereal/packet-smb.c
--- ethereal-orig/packet-smb.c Sat Jul 28 03:57:55 2001
+++ ethereal/packet-smb.c Sat Jul 28 04:30:11 2001
@@ -9405,6 +9405,7 @@
/* Build display for: Data Displacement */
DataDisplacement = GSHORT(pd, offset);
+ pi.ps.smb.ddisp = DataDisplacement;
if (tree) {
@@ -10148,6 +10149,7 @@
/* Build display for: Data Displacement */
DataDisplacement = GSHORT(pd, offset);
+ pi.ps.smb.ddisp = DataDisplacement;
if (tree) {
["patch.smb.pipe.diff" (application/octet-stream)]
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb-browse.c \
ethereal/packet-smb-browse.c
--- ethereal-orig/packet-smb-browse.c Fri Jul 20 17:11:57 2001
+++ ethereal/packet-smb-browse.c Sun Jul 29 23:05:38 2001
@@ -449,8 +449,8 @@
}
-static void
-dissect_server_type_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree \
*parent_tree, int offset) +void
+dissect_smb_server_type_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree \
*parent_tree, int offset, gboolean infoflag) {
proto_tree *tree = NULL;
proto_item *item = NULL;
@@ -464,13 +464,15 @@
tree = proto_item_add_subtree(item, ett_browse_flags);
}
- /* Append the type(s) of the system to the COL_INFO line ... */
- if (check_col(pinfo->fd, COL_INFO)) {
- for (i = 0; i < 32; i++) {
- if (flags & (1<<i)) {
- col_append_fstr(pinfo->fd, COL_INFO, ", %s",
- val_to_str(i, server_types,
- "Unknown server type:%d"));
+ if(infoflag){
+ /* Append the type(s) of the system to the COL_INFO line ... */
+ if (check_col(pinfo->fd, COL_INFO)) {
+ for (i = 0; i < 32; i++) {
+ if (flags & (1<<i)) {
+ col_append_fstr(pinfo->fd, COL_INFO, ", %s",
+ val_to_str(i, server_types,
+ "Unknown server type:%d"));
+ }
}
}
}
@@ -612,7 +614,7 @@
offset += 1;
/* server type flags */
- dissect_server_type_flags(tvb, pinfo, tree, offset);
+ dissect_smb_server_type_flags(tvb, pinfo, tree, offset, TRUE);
offset += 4;
if (cmd == BROWSE_DOMAIN_ANNOUNCEMENT) {
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb-browse.h \
ethereal/packet-smb-browse.h
--- ethereal-orig/packet-smb-browse.h Fri Jul 13 09:37:48 2001
+++ ethereal/packet-smb-browse.h Sun Jul 29 23:04:39 2001
@@ -29,4 +29,7 @@
gboolean
dissect_mailslot_browse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+void
+dissect_smb_server_type_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, \
int offset, gboolean infoflag); +
#endif
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb-mailslot.c \
ethereal/packet-smb-mailslot.c
--- ethereal-orig/packet-smb-mailslot.c Fri Jul 13 09:37:48 2001
+++ ethereal/packet-smb-mailslot.c Sat Jul 28 23:03:43 2001
@@ -131,10 +131,11 @@
}
else if (command != NULL && strcmp(command, "LANMAN") == 0) {
+ tvbuff_t *tvb;
+ packet_info *pinfo = π
+ tvb = tvb_create_from_top(DataOffset);
- return dissect_pipe_lanman(pd, offset, fd, parent, tree, si,
- max_data, SMB_offset, errcode, dirn, command,
- DataOffset, DataCount, ParameterOffset, ParameterCount);
+ return dissect_pipe_lanman(tvb, pinfo, parent);
}
/* NOTE: use TEMP\\NETLOGON and MSSP because they seems very common, */
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb-pipe.c \
ethereal/packet-smb-pipe.c
--- ethereal-orig/packet-smb-pipe.c Thu Mar 22 11:50:44 2001
+++ ethereal/packet-smb-pipe.c Sun Jul 29 23:15:04 2001
@@ -1,6 +1,12 @@
+/*
+XXX Fixme : continuation stuff removed, should be solved by smb reassembly
+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 2001
*
* $Id: packet-smb-pipe.c,v 1.21 2001/03/22 00:50:44 guy Exp $
*
@@ -46,18 +52,34 @@
#include "packet.h"
#include "conversation.h"
#include "smb.h"
-#include "alignment.h"
-#include "strutil.h"
#include "packet-smb-pipe.h"
+#include "packet-smb-browse.h"
static int proto_smb_lanman = -1;
+static int hf_command = -1;
+static int hf_param_desc = -1;
+static int hf_return_desc = -1;
+static int hf_not_implemented = -1;
+static int hf_detail_level = -1;
+static int hf_recv_buf_len = -1;
+static int hf_response_to = -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_server_name = -1;
+static int hf_server_major = -1;
+static int hf_server_minor = -1;
+static int hf_server_comment = -1;
static gint ett_lanman = -1;
static gint ett_lanman_servers = -1;
static gint ett_lanman_server = -1;
static gint ett_lanman_shares = -1;
static gint ett_lanman_share = -1;
-static gint ett_lanman_flags = -1;
/*
* See
@@ -67,1086 +89,537 @@
* 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 share_status_vals[] = {
+ {0, "Success"},
+ {5, "Access Denied"},
+ {65, "Network Access Denied"},
+ {234, "More Data Available"},
+ {2114, "Server Not Started"},
+ {2141, "Bad Transact Config"},
+ {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 */
-
- while (lmd[i].lanman_num != -1) {
-
- if (lmd[i].lanman_num == lanman_num) {
-
- return &lmd[i];
-
- }
-
- i++;
-
- }
-
- return NULL;
-
-}
-
-
-#define NETSHAREENUM 0x00 /* 00 */
-#define NETSERVERENUM2 0x68 /* 104 */
-
-static void
-dissect_server_flags(proto_tree *tree, int offset, int length, int flags)
-{
- 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"));
-
-}
-
-
-
-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)
-{
-
- 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);
-
-}
-
-int get_ent_count()
-{
-
- return lm_ent_count;
-
-}
-
-int get_act_count()
+static int
+not_implemented(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
{
+ proto_tree_add_item(tree, hf_not_implemented, tvb, offset, \
tvb_length_remaining(tvb, offset), TRUE);
- return lm_act_count;
-
+ return offset+tvb_length_remaining(tvb,offset);
}
-static int get_byte_count(const u_char *p_data)
-
+static int
+netshareenum_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int \
offset) {
- int count = 0, off = 0;
-
- while (p_data[off] && isdigit(p_data[off])) {
-
- count = (count * 10) + (int)p_data[off++] - (int)'0';
+ /* detail level */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, tvb_get_letohs(tvb, \
offset)); + offset += 2;
+
+ /* receiver buffer length */
+ proto_tree_add_uint(tree, hf_recv_buf_len, tvb, offset, 2, tvb_get_letohs(tvb, \
offset)); + offset += 2;
- }
-
- 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)
+netshareenum_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int \
offset) {
- /* 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;
-
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ guint16 acount,ecount;
+ int i;
+ guint16 convert;
+ int pad;
+ int totlen;
+
+ /* status */
+ proto_tree_add_uint(tree, hf_status, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* convert */
+ convert = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_convert, tvb, offset, 2, convert);
+ offset += 2;
+
+ /* entry count */
+ ecount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2, ecount);
+ offset += 2;
+
+ /* available count */
+ acount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_acount, tvb, offset, 2, acount);
+ offset += 2;
+
+ /* pad to guint16 */
+ pad = 0;
+ if (tvb_raw_offset(tvb)&0x01) {
+ offset += 1;
+ pad = 1;
}
- 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;
-
- lm_act_count = WParam;
-
- return 1;
-
- }
-
- break;
-
- case 'e': /* An ent count .. */
-
- if (dirn == 0) { /* Only relevant in a response */
-
- WParam = GSHORT(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: (%04X)", (Name) ? Name : \
"Entry Count", WParam);
-
- pd_p_current += 2;
-
- lm_ent_count = WParam; /* Save this for later retrieval */
-
- return 1;
-
- }
-
- 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 */
-
- }
-
- 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;
-
- }
-
- break;
-
- case 'D': /* Double Word parameter */
-
- if (dirn == 1) {
-
- LParam = GWORD(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u (0x%08X)", (Name) ? \
Name : "DWord Param", LParam, LParam);
-
- pd_p_current += 4;
-
- return 1; /* That's it here */
-
- }
-
- break;
-
- case 'g': /* A byte or series of bytes is returned */
-
- if (dirn == 0) {
-
- bc = get_byte_count(p_desc + p_offset);
-
- 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));
-
- pd_p_current += (bc) ? bc : 1;
-
- return 1;
-
- }
-
- break;
-
- case 'b': /* A byte or series of bytes */
-
- if (dirn == 1) {
-
- bc = get_byte_count(p_desc + p_offset); /* This is not clean */
-
- /*Bytes = g_malloc(bc + 1); / * Is this needed ? */
-
- 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));
-
- pd_p_current += (bc) ? bc : 1;
-
- return 1; /* That's it here ... */
-
- }
-
- break;
-
- case 'O': /* A null pointer */
-
- if (dirn == 1) {
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 0, "%s: Null Pointer", (Name) ? \
Name : "Unknown");
-
- return 1; /* That's it here */
-
- }
-
- break;
-
- case 'z': /* An AsciiZ string */
-
- if (dirn == 1) {
-
- AsciiZ = pd + pd_p_current;
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, strlen(AsciiZ) + 1, "%s: %s", \
(Name) ? Name : "AsciiZ", AsciiZ);
-
- pd_p_current += strlen(AsciiZ) + 1;
-
- return 1; /* That's it here ... */
-
- }
-
- break;
-
- case 'F': /* One or more pad bytes */
-
- if (dirn == 1) {
-
- bc = get_byte_count(pd);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, bc, "%s%u: %s", (Name) ? Name : \
"Pad", bc, format_text(pd + pd_p_current, bc));
-
- pd_p_current += bc;
-
- return 1; /* That's it here */
-
- }
-
- break;
-
- case 'L': /* Receive buffer len: Short */
-
- if (dirn == 1) {
-
- WParam = GSHORT(pd, pd_p_current);
-
- proto_tree_add_text(tree, NullTVB, pd_p_current, 2, "%s: %u (0x%04X)", (Name) ? \
Name : "Receive Buffer Len", WParam, WParam);
-
- pd_p_current += 2;
-
- return 1; /* That's it here ... */
-
+ /* create a subtree for all available shares */
+ if (tree) {
+ it = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), \
"Available Shares"); + tr = proto_item_add_subtree(it, ett_lanman_shares);
}
- break;
+ totlen = tvb_length(tvb);
+ for(i=0;i<ecount;i++){
+ proto_item *si = NULL;
+ proto_tree *st = NULL;
+ char *share;
+ int old_offset = offset;
+ int cptr;
- case 's': /* Send buf ... */
+ share = (char *)tvb_get_ptr(tvb, offset, 1);
- if (dirn == 1) {
+ if (tree) {
+ si = proto_tree_add_text(tr, tvb, offset, 0, "Share %s", share);
+ st = proto_item_add_subtree(si, ett_lanman_shares);
+ }
- need_data = 1;
+ /* share name */
+ proto_tree_add_item(st, hf_share_name, tvb, offset, 13, TRUE);
+ offset += 13;
- LParam = GWORD(pd, pd_p_current);
+ /* pad byte */
+ offset += 1;
- proto_tree_add_text(tree, NullTVB, pd_p_current, 4, "%s: %u", (Name) ? Name : \
"Send Buffer Ptr", LParam); + /* share type */
+ proto_tree_add_uint(st, hf_share_type, tvb, offset, 2, tvb_get_letohs(tvb, \
offset)); + offset += 2;
- pd_p_current += 4;
+ /* pointer to comment */
+ /* +8 is hte first 4 guint16s in the packet */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert+8+pad;
+ offset += 4;
- return 1; /* That's it here ... */
+ /* share comment */
+ if(cptr<totlen){
+ proto_tree_add_item(st, hf_share_comment, tvb, cptr, tvb_strsize(tvb, cptr), \
TRUE); + } else {
+ proto_tree_add_text(st, tvb, 0, 0, "Share Comment: <String goes past end of \
frame>"); + }
+ proto_item_set_len(si, offset-old_offset);
}
- 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;
-
- }
-
- break;
-
- default:
-
- break;
-
- }
-
- break;
-
- case 1: /* We are in the data area ... */
-
-
- break;
-
- }
- }
-
- return 0;
-
+ return offset;
}
-static const value_string share_type_vals[] = {
- {0, "Directory tree"},
- {1, "Printer queue"},
- {2, "Communications device"},
- {3, "IPC"},
- {0, NULL}
-};
-
-/*
- * Per-frame data needed to dissect replies.
- */
-typedef struct {
- guint16 FunctionCode;
- gboolean is_continuation;
-} response_data;
-
-static GMemChunk *lanman_proto_data;
-
-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 int
+netserverenum2_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int \
offset) {
- 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 = SMB_offset;
-
- }
- 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;
-
- lanman = find_lanman(FunctionCode);
-
- if (check_col(fd, COL_INFO)) {
-
- if (lanman) {
- col_add_fstr(fd, COL_INFO, "%s Request", lanman -> lanman_name);
- }
- else {
- col_add_fstr(fd, COL_INFO, "Unknown LANMAN Request: %u", FunctionCode);
- }
- }
-
- 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);
-
- if (lanman) {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Function Code: %s", \
lanman -> lanman_name);
- }
- else {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Function Code: Unknown \
LANMAN Request: %u", FunctionCode);
- }
-
- }
-
- loc_offset += 2;
+ /* detail level */
+ proto_tree_add_uint(tree, hf_detail_level, tvb, offset, 2, tvb_get_letohs(tvb, \
offset)); + offset += 2;
+
+ /* receiver buffer length */
+ proto_tree_add_uint(tree, hf_recv_buf_len, tvb, offset, 2, tvb_get_letohs(tvb, \
offset)); + offset += 2;
+
+ /* server type flags */
+ dissect_smb_server_type_flags(tvb, pinfo, tree, offset, TRUE);
+ offset += 4;
- 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;
-
- switch (FunctionCode) {
-
- case NETSHAREENUM: /* Never decode this at the moment ... */
-
- 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 */
-
- 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 ... */
-
- if (tree) {
-
- int i = 0; /* Counter for names below */
- char *name = NULL;
-
- dissect_transact_engine_init(pd, ParameterDescriptor, ReturnDescriptor,SMB_offset, \
loc_offset, ParameterCount, DataOffset, DataCount);
-
- if (lanman) name = lanman -> req[i]; /* Must be OK ... */
-
- while (dissect_transact_next(pd, name, dirn, lanman_tree))
- if (name) name = lanman -> req[++i];
- }
-
- break;
-
- }
- }
- else { /* dirn == 0, response */
- response_data *proto_data;
- guint16 Status;
- guint16 Convert;
- guint16 EntCount;
- guint16 AvailCount;
- int i;
- proto_tree *server_tree = NULL, *flags_tree = NULL, *share_tree = NULL;
-
- /* Is there any per-frame LANMAN data for this frame? */
- proto_data = p_get_proto_data(fd, proto_smb_lanman);
- if (proto_data == NULL) {
- /* No. Allocate some, and set it up. */
- proto_data = g_mem_chunk_alloc(lanman_proto_data);
- proto_data->FunctionCode = si.request_val -> last_lanman_cmd;
-
- /*
- * If we've already seen a response to the request, this must
- * be a continuation of that response.
- */
- proto_data->is_continuation = si.request_val -> trans_response_seen;
-
- /*
- * Attach it to the frame.
- */
- p_add_proto_data(fd, proto_smb_lanman, proto_data);
- }
-
- FunctionCode = proto_data->FunctionCode;
-
- /*
- * If we have already seen the response to this transact, simply
- * record it as a continuation ...
- */
- if (proto_data->is_continuation) {
-
- if (check_col(fd, COL_INFO)) {
- col_set_str(fd, COL_INFO, "Transact Continuation");
- }
-
- 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, loc_offset, END_OF_FRAME, "Payload: %s", \
format_text(pd + loc_offset, END_OF_FRAME));
-
- }
-
- return TRUE;
-
- }
-
- si.request_val -> trans_response_seen = 1;
-
- lanman = find_lanman(FunctionCode);
-
- 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);
- }
- }
-
- 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, loc_offset, 0, "Function Code: %s", \
lanman -> lanman_name);
- }
- else {
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 0, "Function Code: Unknown \
LANMAN Response: %u", FunctionCode);
- }
- }
-
- if (is_interim_response) {
-
- return TRUE; /* no data to dissect */
-
- }
-
- switch (FunctionCode) {
-
- case NETSHAREENUM:
-
- 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, AvailCount * 20, \
"Available Shares");
-
- share_tree = proto_item_add_subtree(ti, ett_lanman_shares);
-
- }
-
- 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;
-
- if (tree) {
-
- ti = proto_tree_add_text(share_tree, NullTVB, loc_offset, 20, "Share %s", Share);
- share = proto_item_add_subtree(ti, ett_lanman_share);
-
-
- }
-
- if (tree) {
-
- proto_tree_add_text(share, NullTVB, loc_offset, 13, "Share Name: %s", Share);
-
- }
-
- loc_offset += 13;
-
- loc_offset += 1; /* Pad byte ... */
-
- Flags = GSHORT(pd, loc_offset);
-
- if (tree) {
-
- proto_tree_add_text(share, NullTVB, loc_offset, 2, "Share Type: %s",
- val_to_str(Flags, share_type_vals, "Unknown (%u)"));
+ return offset;
+}
+static int
+netserverenum2_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int \
offset) +{
+ guint16 ecount,acount,convert;
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ int i,pad,totlen;
+
+ /* status */
+ proto_tree_add_uint(tree, hf_status, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* convert */
+ convert = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_convert, tvb, offset, 2, convert);
+ offset += 2;
+
+ /* entry count */
+ ecount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2, ecount);
+ offset += 2;
+
+ /* antry count */
+ acount = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_acount, tvb, offset, 2, acount);
+ offset += 2;
+
+ /* pad to guint16 */
+ pad = 0;
+ if (tvb_raw_offset(tvb)&0x01) {
+ offset += 1;
+ pad = 1;
}
- loc_offset += 2;
-
- /* 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(share, NullTVB, loc_offset, 4, "Share Comment: %s", Comment);
-
+ it = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), \
"Servers"); + tr = proto_item_add_subtree(it, ett_lanman_servers);
}
- loc_offset += 4;
-
- }
-
- break;
-
- case NETSERVERENUM2:
-
- 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);
-
- }
-
- server_tree = proto_item_add_subtree(ti, ett_lanman_servers);
-
- }
-
- /* Make sure we don't go past the end of the capture buffer */
-
- 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;
-
- if (tree) {
-
- 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);
-
+ totlen = tvb_length(tvb);
+ for(i=0;i<ecount;i++){
+ proto_item *si = NULL;
+ proto_tree *st = NULL;
+ char *server;
+ int cptr;
+ int old_offset = offset;
+
+ server = (char *)tvb_get_ptr(tvb, offset, 1);
+ if (tree) {
+ si = proto_tree_add_text(tr, tvb, offset,
+ 0,
+ "Server %s", server);
+ st = proto_item_add_subtree(si, ett_lanman_server);
+ }
+
+ /* server name */
+ proto_tree_add_item(st, hf_server_name, tvb, offset, 16, TRUE);
+ offset += 16;
+
+ if(tvb_length_remaining(tvb, offset)){
+ /* major version */
+ proto_tree_add_uint(st, hf_server_major, tvb, offset, 1, tvb_get_guint8(tvb, \
offset)); + offset += 1;
+
+ /* minor version */
+ proto_tree_add_uint(st, hf_server_minor, tvb, offset, 1, tvb_get_guint8(tvb, \
offset)); + offset += 1;
+
+ /* server type flags */
+ dissect_smb_server_type_flags(tvb, pinfo, st, offset, FALSE);
+ offset += 4;
+
+ /* pointer to comment */
+ /* +8 is hte first 4 guint16s in the packet */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert+8+pad;
+ offset += 4;
+
+ /* share comment */
+ if(cptr<totlen){
+ proto_tree_add_item(st, hf_server_comment, tvb, cptr, tvb_strsize(tvb, cptr), \
TRUE); + } else {
+ proto_tree_add_text(st, tvb, 0, 0, "Share Comment: <String goes past end of \
frame>"); + }
+
+ }
+
+ proto_item_set_len(si, offset-old_offset);
+ }
+
+ return offset;
+}
+
+#define LANMAN_NETSHAREENUM 0
+#define LANMAN_NETSHAREGETINFO 1
+#define LANMAN_NETSERVERGETINFO 13
+#define LANMAN_NETGROUPGETUSERS 52
+#define LANMAN_NETUSERGETINFO 56
+#define LANMAN_NETUSERGETGROUPS 59
+#define LANMAN_NETWKSTAGETINFO 63
+#define LANMAN_DOSPRINTQENUM 69
+#define LANMAN_DOSPRINTQGETINFO 70
+#define LANMAN_WPRINTQUEUEPAUSE 74
+#define LANMAN_WPRINTQUEUERESUME 75
+#define LANMAN_WPRINTJOBENUMERATE 76
+#define LANMAN_WPRINTJOBGETINFO 77
+#define LANMAN_RDOSPRINTJOBDEL 81
+#define LANMAN_RDOSPRINTJOBPAUSE 82
+#define LANMAN_RDOSPRINTJOBRESUME 83
+#define LANMAN_WPRINTDESTENUM 84
+#define LANMAN_WPRINTDESTGETINFO 85
+#define LANMAN_NETREMOTETOD 91
+#define LANMAN_WPRINTQUEUEPURGE 103
+#define LANMAN_NETSERVERENUM2 104
+#define LANMAN_WACCESSGETUSERPERMS 105
+#define LANMAN_SETUSERPASSWORD 115
+#define LANMAN_NETWKSTAUSERLOGON 132
+#define LANMAN_NETWKSTAUSERLOGOFF 133
+#define LANMAN_PRINTJOBINFO 147
+#define LANMAN_WPRINTDRIVERENUM 205
+#define LANMAN_WPRINTQPROCENUM 206
+#define LANMAN_WPRINTPORTENUM 207
+#define LANMAN_SAMOEMCHANGEPASSWORD 214
+
+static const value_string commands[] = {
+ {LANMAN_NETSHAREENUM, "NetShareEnum"},
+ {LANMAN_NETSHAREGETINFO, "NetShareGetInfo"},
+ {LANMAN_NETSERVERGETINFO, "NetServerGetInfo"},
+ {LANMAN_NETGROUPGETUSERS, "NetGroupGetUsers"},
+ {LANMAN_NETUSERGETINFO, "NetUserGetInfo"},
+ {LANMAN_NETUSERGETGROUPS, "NetUserGetGroups"},
+ {LANMAN_NETWKSTAGETINFO, "NetWkstaGetInfo"},
+ {LANMAN_DOSPRINTQENUM, "DOSPrintQEnum"},
+ {LANMAN_DOSPRINTQGETINFO, "DOSPrintQGetInfo"},
+ {LANMAN_WPRINTQUEUEPAUSE, "WPrintQueuePause"},
+ {LANMAN_WPRINTQUEUERESUME, "WPrintQueueResume"},
+ {LANMAN_WPRINTJOBENUMERATE, "WPrintJobEnumerate"},
+ {LANMAN_WPRINTJOBGETINFO, "WPrintJobGetInfo"},
+ {LANMAN_RDOSPRINTJOBDEL, "RDOSPrintJobDel"},
+ {LANMAN_RDOSPRINTJOBPAUSE, "RDOSPrintJobPause"},
+ {LANMAN_RDOSPRINTJOBRESUME, "RDOSPrintJobResume"},
+ {LANMAN_WPRINTDESTENUM, "WPrintDestEnum"},
+ {LANMAN_WPRINTDESTGETINFO, "WPrintDestGetInfo"},
+ {LANMAN_NETREMOTETOD, "NetRemoteTOD"},
+ {LANMAN_WPRINTQUEUEPURGE, "WPrintQueuePurge"},
+ {LANMAN_NETSERVERENUM2, "NetServerEnum2"},
+ {LANMAN_WACCESSGETUSERPERMS, "WAccessGetUserPerms"},
+ {LANMAN_SETUSERPASSWORD, "SetUserPassword"},
+ {LANMAN_NETWKSTAUSERLOGON, "NetWkstaUserLogon"},
+ {LANMAN_NETWKSTAUSERLOGOFF, "NetWkstaUserLogoff"},
+ {LANMAN_PRINTJOBINFO, "PrintJobInfo"},
+ {LANMAN_WPRINTDRIVERENUM, "WPrintDriverEnum"},
+ {LANMAN_WPRINTQPROCENUM, "WPrintQProcEnum"},
+ {LANMAN_WPRINTPORTENUM, "WPrintPortEnum"},
+ {LANMAN_SAMOEMCHANGEPASSWORD, "SamOEMChangePassword"},
+ {0, NULL}
+};
- }
+struct lanman_dissector {
+ int command;
+ int (*request)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+ int (*response)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+};
- if (tree) {
-
- proto_tree_add_text(server, NullTVB, loc_offset, 16, "Server Name: %s", Server);
+struct lanman_dissector lmd[] = {
+ {LANMAN_NETSHAREENUM, netshareenum_request, netshareenum_response},
+ {LANMAN_NETSERVERENUM2, netserverenum2_request, netserverenum2_response},
+ {-1, not_implemented, not_implemented}
+};
+struct lanman_dissector *find_lanman_dissector(int cmd)
+{
+ int i;
+ for(i=0;1;i++){
+ if(lmd[i].command==-1){
+ return(&lmd[i]);
+ }
+ if(lmd[i].command==cmd){
+ return(&lmd[i]);
+ }
}
+ return NULL; /*never reached, to keep the compiler happy*/
+}
- 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); +/*
+ * Functions to track and match responses with requests
+ */
- }
+GHashTable *lm_table;
+static GMemChunk *lm_key_chunk = NULL;
+static GMemChunk *lm_data_chunk = NULL;
+static int lm_init_count = 200;
+
+/* XXX FIXME should also check src/dst address which can be IP/IPX/etc */
+struct lm_key {
+ guint16 tid;
+ guint16 pid;
+ guint16 uid;
+ guint16 mid;
+};
+struct lm_data {
+ int command;
+ int frame;
+};
- loc_offset += 4;
+static gint
+lm_equal(gconstpointer k1, gconstpointer k2)
+{
+ struct lm_key *key1 = (struct lm_key *)k1;
+ struct lm_key *key2 = (struct lm_key *)k2;
+ if ( (key1->tid==key2->tid)
+ &&(key1->pid==key2->pid)
+ &&(key1->uid==key2->uid)
+ &&(key1->mid==key2->mid) ){
+ return TRUE;
}
- }
-
- break;
-
- default:
-
- 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) {
+ return FALSE;
+}
- proto_tree_add_text(lanman_tree, NullTVB, loc_offset, 2, "Convert: %u", Convert);
+static guint
+lm_hash(gconstpointer k)
+{
+ struct lm_key *key = (struct lm_key *)k;
+ guint hash_val;
- }
+ hash_val = (key->tid) | (key->pid)
+ | (key->uid) | (key->mid);
- loc_offset += 2;
+ return hash_val;
+}
- if (tree) {
+static gboolean
+lm_table_free_all(gpointer key_arg, gpointer value, gpointer user_data)
+{
+ /* key/data removed by g_mem_chunk_destroy */
- int i = 0;
- char *name = NULL;
+ return TRUE;
+}
- dissect_transact_engine_init(pd, si.request_val -> last_param_descrip, \
si.request_val -> last_data_descrip, SMB_offset, loc_offset, ParameterCount, \
DataOffset, DataCount); +static void
+lm_init_protocol(void)
+{
+ if(lm_table != NULL){
+ g_hash_table_foreach_remove(lm_table, lm_table_free_all, NULL);
+ } else {
+ lm_table = g_hash_table_new(lm_hash, lm_equal);
+ }
+
+ if(lm_key_chunk){
+ g_mem_chunk_destroy(lm_key_chunk);
+ }
+ lm_key_chunk = g_mem_chunk_new("lm_key_chunk",
+ sizeof(struct lm_key),
+ lm_init_count*sizeof(struct lm_key),
+ G_ALLOC_ONLY);
+
+ if(lm_data_chunk){
+ g_mem_chunk_destroy(lm_data_chunk);
+ }
+ lm_data_chunk = g_mem_chunk_new("lm_data_chunk",
+ sizeof(struct lm_data),
+ lm_init_count*sizeof(struct lm_data),
+ G_ALLOC_ONLY);
- if (lanman) name = lanman -> resp[i];
-
- while (dissect_transact_next(pd, name, dirn, lanman_tree))
- if (name) name = lanman -> resp[++i];
-
- }
+}
- return TRUE;
- break;
- }
- }
+gboolean
+dissect_pipe_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ int offset = 0;
+ guint16 cmd;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ struct lanman_dissector *dis;
+ struct lm_key key;
+ struct lm_data *dt;
+
+
+ if (check_col(pinfo->fd, COL_PROTOCOL)) {
+ col_set_str(pinfo->fd, COL_PROTOCOL, "LANMAN");
+ }
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb_lanman,
+ tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+ tree = proto_item_add_subtree(item, ett_lanman);
+ }
+
+ /* continuation messages, dont try to decode them */
+ if (pinfo->ps.smb.ddisp) {
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_set_str(pinfo->fd, COL_INFO, "Transact Continuation");
+ }
+ return TRUE;
+ }
+
+
+
+ if (pinfo->ps.smb.request) { /* this is a request */
+
+ /* function code */
+ cmd = tvb_get_letohs(tvb, offset);
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_add_fstr(pinfo->fd, COL_INFO, "%s Request", val_to_str(cmd, commands, \
"Unknown Command:0x%02x")); + }
+ proto_tree_add_uint(tree, hf_command, tvb, offset, 2, cmd);
+ offset += 2;
+
+ /* remember this request so we can match responses with it */
+ /* first just check if we have already added this one */
+ key.tid = pinfo->ps.smb.tid;
+ key.pid = pinfo->ps.smb.pid;
+ key.uid = pinfo->ps.smb.uid;
+ key.mid = pinfo->ps.smb.mid;
+ if (!g_hash_table_lookup(lm_table, &key)) {
+ /* we have not seen this request before
+ add it so we can match responses to it */
+ struct lm_key *new_key;
+ struct lm_data *new_data;
+
+ new_key = g_mem_chunk_alloc(lm_key_chunk);
+ new_key->tid = key.tid;
+ new_key->pid = key.pid;
+ new_key->uid = key.uid;
+ new_key->mid = key.mid;
+
+ new_data = g_mem_chunk_alloc(lm_data_chunk);
+ new_data->command = cmd;
+ new_data->frame = pinfo->fd->num;
+
+ g_hash_table_insert(lm_table, new_key, new_data);
+ };
+
+
+ /* parameter descriptor */
+ proto_tree_add_item(tree, hf_param_desc, tvb, offset, tvb_strsize(tvb, offset), \
TRUE); + offset += tvb_strsize(tvb, offset);
+
+ /* return descriptor */
+ proto_tree_add_item(tree, hf_return_desc, tvb, offset, tvb_strsize(tvb, offset), \
TRUE); + offset += tvb_strsize(tvb, offset);
+
+ /* command parameters */
+ dis = find_lanman_dissector(cmd);
+ if(dis->request){
+ offset = (*(dis->request))(tvb, pinfo, tree, offset);
+ }
+
+ } else { /* this is a response */
+ /* check if we know this one */
+ key.tid = pinfo->ps.smb.tid;
+ key.pid = pinfo->ps.smb.pid;
+ key.uid = pinfo->ps.smb.uid;
+ key.mid = pinfo->ps.smb.mid;
+ if ((dt = g_hash_table_lookup(lm_table, &key))) {
+ /* ok we have seen this one before */
+
+ /* response to the request in frame xx */
+ proto_tree_add_uint(tree, hf_response_to, tvb, 0, 0, dt->frame);
+ /* command */
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_add_fstr(pinfo->fd, COL_INFO, "%s Response", val_to_str(dt->command, \
commands, "Unknown Command:0x%02x")); + }
+ proto_tree_add_uint(tree, hf_command, tvb, 0, 0, dt->command);
+
+ /* command parameters */
+ dis = find_lanman_dissector(dt->command);
+ if(dis->response){
+ offset = (*(dis->response))(tvb, pinfo, tree, offset);
+ }
+ }
+ }
return FALSE;
}
+
+
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) +dissect_pipe_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree \
*tree, char *command) {
if (!proto_is_protocol_enabled(proto_smb_lanman))
@@ -1155,9 +628,7 @@
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 dissect_pipe_lanman(tvb, pinfo, tree);
}
@@ -1165,21 +636,84 @@
}
-static void
-pipe_lanman_init_protocol(void)
-{
- if (lanman_proto_data != NULL)
- g_mem_chunk_destroy(lanman_proto_data);
-
- lanman_proto_data = g_mem_chunk_new("lanman_proto_data",
- sizeof(response_data),
- 100 * sizeof(response_data),
- G_ALLOC_AND_FREE);
-}
void
register_proto_smb_pipe( void){
+ static hf_register_info hf[] = {
+ { &hf_command,
+ { "Command", "lanman.command", FT_UINT16, BASE_HEX,
+ VALS(commands), 0, "LANMAN Function Code/Command", HFILL }},
+
+ { &hf_param_desc,
+ { "Parameter Descriptor", "lanman.param_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Parameter Descriptor", HFILL }},
+
+ { &hf_return_desc,
+ { "Return Descriptor", "lanman.ret_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Return Descriptor", HFILL }},
+
+ { &hf_not_implemented,
+ { "Unknown Data", "lanman.not_implemented", FT_BYTES, BASE_HEX,
+ NULL, 0, "Decoding of this data is not implemented yet", HFILL }},
+
+ { &hf_detail_level,
+ { "Detail Level", "lanman.level", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Detail Level", HFILL }},
+
+ { &hf_recv_buf_len,
+ { "Recv Buf Len", "lanman.recv_buf_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Receive Buffer Length", HFILL }},
+
+ { &hf_response_to,
+ { "Response to request in frame", "lanman.response_to", FT_UINT32, BASE_DEC,
+ NULL, 0, "This is a LANMAN response to the request in frame", HFILL }},
+
+ { &hf_status,
+ { "Status", "lanman.status", FT_UINT16, BASE_DEC,
+ VALS(share_status_vals), 0, "LANMAN Return status", HFILL }},
+
+ { &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 }},
+
+ { &hf_acount,
+ { "Available Count", "lanman.available_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Available Entries", HFILL }},
+
+ { &hf_share_name,
+ { "Name", "lanman.share.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Share", HFILL }},
+
+ { &hf_share_type,
+ { "Type", "lanman.share.type", FT_UINT16, BASE_DEC,
+ VALS(share_type_vals), 0, "LANMAN Type of Share", HFILL }},
+
+ { &hf_share_comment,
+ { "Comment", "lanman.share.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Comment", HFILL }},
+
+ { &hf_server_name,
+ { "Name", "lanman.server.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Server", HFILL }},
+
+ { &hf_server_major,
+ { "Major", "lanman.server.major", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Major Version", HFILL }},
+
+ { &hf_server_minor,
+ { "Minor", "lanman.server.minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Minor Version", HFILL }},
+
+ { &hf_server_comment,
+ { "Comment", "lanman.server.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Server Comment", HFILL }},
+
+ };
static gint *ett[] = {
@@ -1188,13 +722,14 @@
&ett_lanman_server,
&ett_lanman_shares,
&ett_lanman_share,
- &ett_lanman_flags
};
proto_smb_lanman = proto_register_protocol(
"Microsoft Windows Lanman Protocol", "LANMAN", "lanman");
+ proto_register_field_array(proto_smb_lanman, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
- register_init_routine(&pipe_lanman_init_protocol);
+ register_init_routine(lm_init_protocol);
}
+
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb-pipe.h \
ethereal/packet-smb-pipe.h
--- ethereal-orig/packet-smb-pipe.h Sun Mar 18 14:23:30 2001
+++ ethereal/packet-smb-pipe.h Sat Jul 28 23:24:07 2001
@@ -23,15 +23,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#ifndef _PACKET_SMB_PIPE_H_
+#define _PACKET_SMB_PIPE_H_
+
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);
+dissect_pipe_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
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);
+dissect_pipe_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, char \
*command); +
+#endif
+
diff -u -r -x *.[^ch]|nmake|am ethereal-orig/packet-smb.c ethereal/packet-smb.c
--- ethereal-orig/packet-smb.c Sat Jul 28 04:53:58 2001
+++ ethereal/packet-smb.c Sun Jul 29 00:29:47 2001
@@ -9547,6 +9547,8 @@
char *trans_type = NULL, *trans_cmd, *loc_of_slash = NULL;
int index;
const gchar *Data;
+ tvbuff_t *newtvb;
+ packet_info *pinfo;
if (!TransactName)
return;
@@ -9569,6 +9571,13 @@
else
trans_cmd = NULL;
+ pinfo = π
+ if(DataOffset<0){
+ newtvb = tvb_create_from_top(SMB_offset);
+ } else {
+ newtvb = tvb_create_from_top(SMB_offset+ParameterOffset);
+ }
+
if ((trans_cmd == NULL) ||
(((trans_type == NULL || strcmp(trans_type, "MAILSLOT") != 0) ||
!dissect_mailslot_smb(pd, SetupAreaOffset, fd, parent, tree, si,
@@ -9576,9 +9585,7 @@
SMB_offset + DataOffset, DataCount,
SMB_offset + ParameterOffset, ParameterCount)) &&
((trans_type == NULL || strcmp(trans_type, "PIPE") != 0) ||
- !dissect_pipe_smb(pd, offset, fd, parent, tree, si, max_data,
- SMB_offset, errcode, dirn, trans_cmd, DataOffset,
- DataCount, ParameterOffset, ParameterCount)))) {
+ !dissect_pipe_smb(newtvb, pinfo, parent, trans_cmd)))) {
if (ParameterCount > 0) {
@@ -10673,6 +10680,8 @@
guint32 status;
int SMB_offset = offset;
struct smb_info si;
+
+ pi.ps.smb.ddisp = 0;
OLD_CHECK_DISPLAY_AS_DATA(proto_smb, pd, offset, fd, tree);
_______________________________________________
Ethereal-dev mailing list
Ethereal-dev@ethereal.com
http://www.ethereal.com/mailman/listinfo/ethereal-dev
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic