Ethereal-dev: [ethereal-dev] Packet-smb patch
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Mike Hancher <Hanchman@xxxxxxx>
Date: Thu, 18 Nov 1999 16:53:16 -0500
I patched Packet-smb.c to handle UNICODED data and UNICODE offset
padding, fixed a problem with the password length display in the hex
box, added ASCII text display fields for the PARAMETERS and DATA fields
and added a label to the SERVICE field identifying the type of service.
Can anyone provice me with a breakdown or documentation of the
PARAMETERS fields.
--
.---------------------------------------------------------------------------------------
Hear something and it will be forgotten
See something and it will be remembered
Mike Hancher
Email : Hanchman@xxxxxxx
Homepage: http://www.qis.net/~hanchman
----------------------------------------------------------------------------------------
? patchsmb3.txt
? my.patch
? smb-patch.txt
? patchsmb.txt
? patchsmb2.txt
Index: packet-smb.c
===================================================================
RCS file: /cvsroot/ethereal/packet-smb.c,v
retrieving revision 1.43
diff -u -r1.43 packet-smb.c
--- packet-smb.c 1999/11/18 07:32:46 1.43
+++ packet-smb.c 1999/11/18 17:57:11
@@ -48,7 +48,10 @@
#include "alignment.h"
static int proto_smb = -1;
+static int Cap_Offset = 113; /* offset into the packet of the Capabilities flags */
+static int Flags2_Offset=68; /* offset into the packet of the Flags2 settings */
+
static gint ett_smb = -1;
static gint ett_smb_fileattributes = -1;
static gint ett_smb_capabilities = -1;
@@ -432,7 +435,6 @@
void
dissect_unknown_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)
{
-
if (tree) {
proto_tree_add_text(tree, offset, END_OF_FRAME, "Data (%u bytes)",
@@ -550,6 +552,34 @@
return cur;
}
+
+ /* lookup the service requested. */
+static gchar *
+lookup_service_description(const guint8 *str) {
+
+ gchar *str2;
+
+ str2="";
+ if (strcmp(str,"A:")==0) {
+ str2 = "Disk Share";
+ }
+ else if (strcmp(str,"LPT1:")==0) {
+ str2 = "Printer";
+ }
+ else if (strcmp(str,"IPC")==0) {
+ str2 = "Named Pipe";
+ }
+ else if (strcmp(str,"COMM")==0) {
+ str2 = "Communications Device";
+ }
+ else if (strcmp(str,"?????")==0) {
+ str2 = "Any Type of Device";
+ }
+ return str2;
+}
+
+
+
/*
* Each dissect routine is passed an offset to wct and works from there
*/
@@ -1772,11 +1802,11 @@
if (tree) {
- proto_tree_add_text(tree, offset, strlen(Password) + 1, "Password: %s", Password);
+ proto_tree_add_text(tree, offset, strlen(Password), "Password: %s", Password);
}
- offset += strlen(Password) + 1; /* Skip Password */
+ offset += strlen(Password); /* Skip Password */
/* Build display for: BufferFormat3 */
@@ -1797,6 +1827,7 @@
if (tree) {
proto_tree_add_text(tree, offset, strlen(Service) + 1, "Service: %s", Service);
+ proto_tree_add_text(tree, offset, strlen(Service) + 1, "Service Description: %s",lookup_service_description(Service));
}
@@ -1870,6 +1901,7 @@
guint8 WordCount;
guint8 AndXReserved;
guint8 AndXCommand = 0xFF;
+ guint8 Pad1;
guint32 SessionKey;
guint32 Reserved;
guint32 Capabilities;
@@ -1891,6 +1923,15 @@
const char *AccountName;
const char *ANSIPassword;
+ guint16 Flags2;
+ char *passstr;
+ char *ustr;
+ int ustr_len;
+
+ /* obtain the Flags2 settings */
+ Flags2 = GSHORT(pd, Flags2_Offset);
+
+
if (dirn == 1) { /* Request(s) dissect code */
WordCount = GBYTE(pd, offset);
@@ -2039,9 +2080,11 @@
Password = pd + offset;
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(Password) + 1, "Password: %s", Password);
-
+ passstr=g_malloc(PasswordLen+1);
+ strncpy(passstr, Password, PasswordLen);
+ passstr[PasswordLen+1]='\0';
+ proto_tree_add_text(tree, offset, PasswordLen, "Password: %s", passstr);
+ g_free(passstr);
}
offset += PasswordLen;
@@ -2293,9 +2336,11 @@
ANSIPassword = pd + offset;
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(ANSIPassword) + 1, "ANSI Password: %s", ANSIPassword);
-
+ passstr=g_malloc(ANSIAccountPasswordLength+1);
+ strncpy(passstr, ANSIPassword, ANSIAccountPasswordLength);
+ passstr[ANSIAccountPasswordLength+1]='\0';
+ proto_tree_add_text(tree, offset, ANSIAccountPasswordLength, "ANSI Password: %s", passstr);
+ g_free(passstr);
}
offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
@@ -2308,62 +2353,112 @@
if (UNICODEAccountPasswordLength > 0) {
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(UNICODEPassword) + 1, "UNICODE Password: %s", UNICODEPassword);
-
+ passstr=g_malloc(UNICODEAccountPasswordLength+1);
+ strncpy(passstr, UNICODEPassword, UNICODEAccountPasswordLength);
+ passstr[UNICODEAccountPasswordLength+1]='\0';
+ proto_tree_add_text(tree, offset, UNICODEAccountPasswordLength, "UNICODE Password: %s", passstr);
+ g_free(passstr);
}
- offset += strlen(UNICODEPassword) + 1; /* Skip UNICODE Password */
+ offset += UNICODEAccountPasswordLength; /* Skip UNICODE Password */
}
-
- /* Build display for: Account Name */
-
- AccountName = pd + offset;
-
- if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(AccountName) + 1, "Account Name: %s", AccountName);
-
- }
-
- offset += strlen(AccountName) + 1; /* Skip Account Name */
-
- /* Build display for: Primary Domain */
-
- PrimaryDomain = pd + offset;
-
- if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "Primary Domain: %s", PrimaryDomain);
-
- }
-
- offset += strlen(PrimaryDomain) + 1; /* Skip Primary Domain */
-
- /* Build display for: Native OS */
-
- NativeOS = pd + offset;
-
- if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
-
- }
-
- offset += strlen(NativeOS) + 1; /* Skip Native OS */
-
- /* Build display for: Native LanMan Type */
-
- NativeLanManType = pd + offset;
-
- if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(NativeLanManType) + 1, "Native LanMan Type: %s", NativeLanManType);
- }
+ if (Capabilities & 0x0004) {
+ if (offset % 2) {
- offset += strlen(NativeLanManType) + 1; /* Skip Native LanMan Type */
+ /* Build display for: Pad1 */
+ /* Need to pad out because of Unicode strings start on a
+ even boundary */
+
+ Pad1 = GBYTE(pd, offset);
+ if (tree) {
+ proto_tree_add_text(tree, offset, 1, "Pad1: %u", Pad1);
+
+ }
+ offset += 1;
+ }
+ }
+
+ /* Build display for: Account Name */
+
+ /* The AccountName, a null terminated string; Unicode if "caps" has
+ the 0x0004 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+ AccountName = pd + offset;
+ if (tree) {
+ if (Capabilities & 0x0004) {
+ ustr = unicode_to_str(AccountName, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Account Name: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Account Name */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(AccountName) + 1, "Account Name: %s", AccountName);
+ offset += strlen(AccountName) + 1; /* Skip Account Name */
+ }
+ }
+
+
+ /* Build display for: Primary Domain */
+
+ /* The Primary Domain, a null terminated string; Unicode if "caps" has
+ the 0x0004 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+ PrimaryDomain = pd + offset;
+
+ if (tree) {
+ if (Capabilities & 0x0004) {
+ ustr = unicode_to_str(PrimaryDomain, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Primary Domain: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Primary Domain */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "Primary Domain: %s", PrimaryDomain);
+ offset += strlen(PrimaryDomain) + 1; /* Skip Primary Domain */
+ }
+ }
+
+
+ /* Build display for: Native OS */
+
+ /* The NativeOS, a null terminated string; Unicode if "caps" has
+ the 0x0004 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+ NativeOS = pd + offset;
+
+ if (tree) {
+ if (Capabilities & 0x0004) {
+ ustr = unicode_to_str(NativeOS, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Native OS: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Native OS */
+ offset += 2; /* Skip EXTRA bytes */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
+ offset += strlen(NativeOS) + 1; /* Skip Native OS */
+ }
+ }
+
+
+ /* Build display for: Native LanMan Type */
+
+ /* The NativeLanManType, a null terminated string; Unicode if "caps" has
+ the 0x0004 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+ NativeLanManType = pd + offset;
+
+ if (tree) {
+ if (Capabilities & 0x0004) {
+ ustr = unicode_to_str(NativeLanManType, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Native LanMan Type: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Native LanMan Type */
+ offset += 2; /* Skip EXTRA bytes */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(NativeLanManType) + 1, "Native LanMan Type: %s", NativeLanManType);
+ offset += strlen(NativeLanManType) + 1; /* Skip Native LanMan Type */
+ }
+ }
}
@@ -2463,43 +2558,69 @@
offset += 2; /* Skip Byte Count (BCC) */
if (ByteCount > 0) {
-
- /* Build display for: NativeOS */
- NativeOS = pd + offset;
+ /* Build display for: Native OS */
- if (tree) {
+ /* The NativeOS, a null terminated string; Unicode if "Flags" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+ if (Flags2 & 0x8000) {
+ offset += 1; /* Skip EXTRA Byte for unicode only */
+ }
+ NativeOS = pd + offset;
+
+ if (tree) {
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(NativeOS, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Native OS: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Native OS */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
+ offset += strlen(NativeOS) + 1; /* Skip Native OS */
+ }
+ }
- proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "NativeOS: %s", NativeOS);
- }
-
- offset += strlen(NativeOS) + 1; /* Skip NativeOS */
-
/* Build display for: NativeLanMan */
-
- NativeLanMan = pd + offset;
- if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(NativeLanMan) + 1, "NativeLanMan: %s", NativeLanMan);
-
- }
+ /* The NativeLanManType, a null terminated string; Unicode if "Flags" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+ NativeLanManType = pd + offset;
+
+ if (tree) {
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(NativeLanManType, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "NativeLanManType: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Native LanMan Type */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(NativeLanManType) + 1, "Native LanMan Type: %s", NativeLanManType);
+ offset += strlen(NativeLanManType) + 1; /* Skip Native LanMan Type */
+ }
+ }
- offset += strlen(NativeLanMan) + 1; /* Skip NativeLanMan */
/* Build display for: PrimaryDomain */
-
- PrimaryDomain = pd + offset;
-
- if (tree) {
- proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "PrimaryDomain: %s", PrimaryDomain);
+ /* The Primary Domain, a null terminated string; Unicode if "caps" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+ PrimaryDomain = pd + offset;
+
+ if (tree) {
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(PrimaryDomain, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Primary Domain: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Primary Domain */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "Primary Domain: %s", PrimaryDomain);
+ offset += strlen(PrimaryDomain) + 1; /* Skip Primary Domain */
+ }
+ }
- }
-
- offset += strlen(PrimaryDomain) + 1; /* Skip PrimaryDomain */
-
}
if (AndXCommand != 0xFF) {
@@ -2522,6 +2643,19 @@
proto_tree *flags_tree;
proto_item *ti;
+ char *passstr;
+ char *ustr;
+ int ustr_len;
+ guint32 Capabilities;
+ guint16 Flags2;
+
+ /* obtain the Flags2 settings */
+ Flags2 = GSHORT(pd, Flags2_Offset);
+
+ /* Obtain Capabilities flags */
+ Capabilities = GWORD(pd, Cap_Offset);
+
+
wct = pd[offset];
/* Now figure out what format we are talking about, 2, 3, or 4 response
@@ -2633,31 +2767,46 @@
str = pd + offset;
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(str) + 1, "Password: %s", format_text(str, passwdlen));
-
+ passstr=g_malloc(passwdlen+1);
+ strncpy(passstr, str, passwdlen);
+ passstr[passwdlen+1]='\0';
+ proto_tree_add_text(tree, offset, passwdlen, "Password: %s", passstr);
+ g_free(passstr);
}
offset += passwdlen;
- str = pd + offset;
+ /* Build display for: Path */
- if (tree) {
+ /* The Path, a null terminated string; Unicode if "caps" has
+ the 0x0004 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
- proto_tree_add_text(tree, offset, strlen(str) + 1, "Path: %s", str);
+ str = pd + offset;
- }
+ if (tree) {
+ if (Capabilities & 0x0004) {
+ ustr = unicode_to_str(str, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Path: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Path OS */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(str) + 1, "Path: %s", str);
+ offset += strlen(str) + 1; /* Skip Path */
+ }
+ }
- offset += strlen(str) + 1;
+ /* Build display for: Service */
+
str = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service: %s", str);
+ proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Description: %s",lookup_service_description(str));
}
-
+ offset += strlen(str) + 1; /* Skip Service */
break;
case 2:
@@ -2676,8 +2825,8 @@
if (tree) {
- proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Type: %s",
- str);
+ proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Type: %s",str);
+ proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Description: %s",lookup_service_description(str));
}
@@ -2713,22 +2862,31 @@
if (tree) {
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service: %s", str);
+ proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Description: %s",lookup_service_description(str));
}
offset += strlen(str) + 1;
- str = pd + offset;
+ /* Build display for: Native File System */
- if (tree) {
+ /* The Native File System, a null terminated string; Unicode if "caps" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
- proto_tree_add_text(tree, offset, strlen(str) + 1, "Native File System: %s", str);
+ str = pd + offset;
+ if (tree) {
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(str, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Native File System: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Native File System */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(str) + 1, "Native File System: %s", str);
+ offset += strlen(str) + 1;
+ }
}
- offset += strlen(str) + 1;
-
-
break;
default:
@@ -3260,6 +3418,15 @@
guint16 ByteCount;
const char *DirectoryName;
+ guint16 Flags2;
+ char *ustr;
+ int ustr_len;
+
+
+ /* obtain the Flags2 settings */
+ Flags2 = GSHORT(pd, Flags2_Offset);
+
+
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
@@ -3300,16 +3467,23 @@
/* Build display for: Directory Name */
+ /* The Directory Name, a null terminated string; Unicode if "Flags" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
DirectoryName = pd + offset;
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
-
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(DirectoryName, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
+ offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
+ }
}
- offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
-
}
if (dirn == 0) { /* Response(s) dissect code */
@@ -3351,6 +3525,15 @@
guint16 ByteCount;
const char *DirectoryName;
+ guint16 Flags2;
+ char *ustr;
+ int ustr_len;
+
+
+ /* obtain the Flags2 settings */
+ Flags2 = GSHORT(pd, Flags2_Offset);
+
+
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
@@ -3391,16 +3574,22 @@
/* Build display for: Directory Name */
+ /* The Directory Name, a null terminated string; Unicode if "Flags" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
DirectoryName = pd + offset;
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
-
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(DirectoryName, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
+ offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
+ }
}
-
- offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
-
}
if (dirn == 0) { /* Response(s) dissect code */
@@ -3442,6 +3631,15 @@
guint16 ByteCount;
const char *DirectoryName;
+ guint16 Flags2;
+ char *ustr;
+ int ustr_len;
+
+
+ /* obtain the Flags2 settings */
+ Flags2 = GSHORT(pd, Flags2_Offset);
+
+
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
@@ -3482,16 +3680,23 @@
/* Build display for: Directory Name */
+ /* The Directory Name, a null terminated string; Unicode if "Flags" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
DirectoryName = pd + offset;
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
-
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(DirectoryName, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
+ offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
+ }
}
- offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
-
}
if (dirn == 0) { /* Response(s) dissect code */
@@ -6831,6 +7036,15 @@
const char *FileName;
const char *DirectoryName;
+ guint16 Flags2;
+ char *ustr;
+ int ustr_len;
+
+
+ /* obtain the Flags2 settings */
+ Flags2 = GSHORT(pd, Flags2_Offset);
+
+
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
@@ -6907,16 +7121,23 @@
/* Build display for: Directory Name */
+ /* The Directory Name, a null terminated string; Unicode if "Flags" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
DirectoryName = pd + offset;
if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
-
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(DirectoryName, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
+ } else {
+ proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
+ offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
+ }
}
- offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
-
}
if (dirn == 0) { /* Response(s) dissect code */
@@ -8561,7 +8782,7 @@
if (tree) {
- proto_tree_add_text(tree, offset, 2, "Transact Name: %s", decode_trans2_name(Setup));
+ proto_tree_add_text(tree, offset, 2, "Transact Name 1: %s", decode_trans2_name(Setup));
}
@@ -8587,6 +8808,7 @@
if (tree) {
+ proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
}
@@ -8619,7 +8841,8 @@
if (tree) {
- proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(&pd[offset], DataCount));
+ proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
+ proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
@@ -8674,17 +8897,17 @@
offset += 2; /* Skip Total Data Count */
- /* Build display for: Reserved2 */
+ /* Build display for: Reserved1 */
- Reserved2 = GSHORT(pd, offset);
+ Reserved1 = GSHORT(pd, offset);
if (tree) {
- proto_tree_add_text(tree, offset, 2, "Reserved2: %u", Reserved2);
+ proto_tree_add_text(tree, offset, 2, "Reserved1: %u", Reserved1);
}
- offset += 2; /* Skip Reserved2 */
+ offset += 2; /* Skip Reserved */
/* Build display for: Parameter Count */
@@ -8770,17 +8993,17 @@
offset += 1; /* Skip Setup Count */
- /* Build display for: Reserved3 */
+ /* Build display for: Reserved2 */
- Reserved3 = GBYTE(pd, offset);
+ Reserved2 = GBYTE(pd, offset);
if (tree) {
- proto_tree_add_text(tree, offset, 1, "Reserved3: %u", Reserved3);
+ proto_tree_add_text(tree, offset, 1, "Reserved2: %u", Reserved2);
}
- offset += 1; /* Skip Reserved3 */
+ offset += 1; /* Skip Reserved2 */
/* Build display for: Setup */
@@ -8824,7 +9047,8 @@
if (tree) {
- proto_tree_add_text(tree, offset, ParameterCount, "Parameter: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
+ proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
+ proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
}
@@ -8832,25 +9056,25 @@
}
- /* Build display for: Pad2 */
-
- Pad2 = GBYTE(pd, offset);
-
- if (tree) {
-
- proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
+
+ if (offset % 2) {
+ /* Build display for: Pad2 */
+ Pad2 = GBYTE(pd, offset);
+ if (tree) {
+ proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
+ }
+ offset += 1; /* Skip Pad2 */
}
- offset += 1; /* Skip Pad2 */
-
/* Build display for: Data */
if (DataCount > 0) {
if (tree) {
- proto_tree_add_text(tree, offset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
+ proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
+ proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
@@ -8896,11 +9120,20 @@
char *TransactNameCopy;
char *trans_type;
char *trans_cmd, *loc_of_slash;
- guint32 index;
+ guint32 index=0;
conversation_t *conversation;
struct smb_request_key request_key, *new_request_key;
struct smb_request_val *request_val;
+ char *ustr;
+ int ustr_len;
+ guint8 Default_Path;
+ guint16 Flags2;
+
+ /* obtain the Flags2 settings */
+ Flags2 = GSHORT(pd, Flags2_Offset);
+
+
/*
* Find out what conversation this packet is part of
*/
@@ -8937,6 +9170,7 @@
}
+
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
@@ -9172,10 +9406,31 @@
offset += 2; /* Skip Byte Count (BCC) */
+
/* Build display for: Transact Name */
+ /* The Transact Name, a null terminated string; Unicode if "Flags" has
+ the 0x8000 bit set, ASCII (OEM character set) otherwise.
+ XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
+
+
+ if (Flags2 & 0x8000) {
+ offset +=1; /* skip EXTRA bit for unicode alignment */
+ }
TransactName = pd + offset;
+ if (tree) {
+ if (Flags2 & 0x8000) {
+ ustr = unicode_to_str(TransactName, &ustr_len);
+ proto_tree_add_text(tree, offset, ustr_len+2, "Transact Name 2: %s", ustr);
+ offset += (strlen(ustr)*2) + 2; /* Skip Transact Name */
+ TransactName=ustr;
+ } else {
+ proto_tree_add_text(tree, offset, strlen(TransactName) + 1, "Transact Name 2: %s", TransactName);
+ offset += strlen(TransactName) + 1; /* Skip Transact Name */
+ }
+ }
+
if (request_val -> last_transact_command) g_free(request_val -> last_transact_command);
request_val -> last_transact_command = g_malloc(strlen(TransactName) + 1);
@@ -9189,14 +9444,6 @@
}
- if (tree) {
-
- proto_tree_add_text(tree, offset, strlen(TransactName) + 1, "Transact Name: %s", TransactName);
-
- }
-
- offset += strlen(TransactName) + 1; /* Skip Transact Name */
-
if (offset % 2) {
/* Build display for: Pad1 */
@@ -9228,17 +9475,25 @@
trans_type[index] = '\0';
}
else
- trans_cmd = NULL;
+ trans_cmd = NULL;
+
- if (!strcmp(trans_type, "MAILSLOT") &&
- !dissect_mailslot_smb(pd, offset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn, trans_cmd, SMB_offset + DataOffset, DataCount)) {
+/* If trans type != MAILSLOT then process mailslot. if unsuccessful then default processing */
+
+ Default_Path = 1;
+ if (!strncmp(trans_type, "MAILSLOT",8))
+ Default_Path = !(dissect_mailslot_smb(pd, offset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn, trans_cmd, SMB_offset + DataOffset, DataCount));
+
+ if (Default_Path) {
+
if (ParameterCount > 0) {
/* Build display for: Parameters */
if (tree) {
+ proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
}
@@ -9271,6 +9526,7 @@
if (tree) {
+ proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
@@ -9475,37 +9731,40 @@
offset += 1; /* Skip Pad1 */
- /* Build display for: Parameter */
-
- Parameter = GBYTE(pd, offset);
-
- if (tree) {
+ if (ParameterCount > 0) {
- proto_tree_add_text(tree, offset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
+ /* Build display for: Parameter */
- }
+ Parameter = GBYTE(pd, offset);
- offset += 1; /* Skip Parameter */
+ if (tree) {
- /* Build display for: Pad2 */
+ proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
+ proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
- Pad2 = GBYTE(pd, offset);
+ }
- if (tree) {
+ offset += ParameterCount; /* Skip Parameter */
+ }
- proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
+ if (offset %2) {
+ /* Build display for: Pad2 */
+ Pad2 = GBYTE(pd, offset);
+ if (tree) {
+ proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
+ }
+ offset += 1; /* Skip Pad2 */
}
- offset += 1; /* Skip Pad2 */
-
/* Build display for: Data */
if (DataCount > 0) {
if (tree) {
- proto_tree_add_text(tree, offset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
+ proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
+ proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
Index: packet.c
===================================================================
RCS file: /cvsroot/ethereal/packet.c,v
retrieving revision 1.55
diff -u -r1.55 packet.c
--- packet.c 1999/11/17 21:58:32 1.55
+++ packet.c 1999/11/18 17:57:13
@@ -369,7 +369,7 @@
return lineend;
}
-#define MAX_COLUMNS_LINE_DETAIL 62
+#define MAX_COLUMNS_LINE_DETAIL 999
/*
* Get the length of the next token in a line, and the beginning of the
@@ -402,6 +402,112 @@
return token_len;
}
+
+
+
+/*
+ * Given a string, generate a string from it that shows non-printable
+ * characters as C-style escapes, and return a pointer to it.
+ */
+gchar *
+format_text_ASCII(const u_char *string, int len)
+{
+ static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
+ gchar *fmtbufp;
+ int column;
+ const u_char *stringend = string + len;
+ u_char c;
+
+ column = 0;
+ fmtbufp = &fmtbuf[0];
+ while (string < stringend) {
+ if (column >= MAX_COLUMNS_LINE_DETAIL) {
+ /*
+ * Put "..." and quit.
+ */
+ strcpy(fmtbufp, " ...");
+ break;
+ }
+ c = *string++;
+ if (isprint(c)) {
+ *fmtbufp++ = c;
+ column++;
+ } else {
+ switch (c) {
+
+ case '\\':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = '\\';
+ column++;
+ break;
+
+ case '\a':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = 'a';
+ column++;
+ break;
+
+ case '\b':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = 'b';
+ column++;
+ break;
+
+ case '\f':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = 'f';
+ column++;
+ break;
+
+ case '\n':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = 'n';
+ column++;
+ break;
+
+ case '\r':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = 'r';
+ column++;
+ break;
+
+ case '\t':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = 't';
+ column++;
+ break;
+
+ case '\v':
+ *fmtbufp++ = '\\';
+ column++;
+ *fmtbufp++ = 'v';
+ column++;
+ break;
+
+ default:
+ *fmtbufp++ = '.';
+ column++;
+ break;
+ }
+ }
+ }
+ *fmtbufp = '\0';
+
+ return fmtbuf;
+}
+
+
+
+
+
+
/*
* Given a string, generate a string from it that shows non-printable
Index: packet.h
===================================================================
RCS file: /cvsroot/ethereal/packet.h,v
retrieving revision 1.144
diff -u -r1.144 packet.h
--- packet.h 1999/11/17 21:58:32 1.144
+++ packet.h 1999/11/18 17:57:15
@@ -221,6 +221,7 @@
int get_token_len(const u_char *linep, const u_char *lineend,
const u_char **next_token);
gchar* format_text(const u_char *line, int len);
+gchar* format_text_ASCII(const u_char *line, int len);
gchar* val_to_str(guint32, const value_string *, const char *);
gchar* match_strval(guint32, const value_string*);
char * decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width);
/* packet.c
* Routines for packet disassembly
*
* $Id: packet.c,v 1.55 1999/11/17 21:58:32 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxx>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif
#include <glib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#ifdef NEED_SNPRINTF_H
# include "snprintf.h"
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#include <arpa/inet.h>
#ifdef NEED_INET_V6DEFS_H
# include "inet_v6defs.h"
#endif
#include "packet.h"
#include "print.h"
#include "file.h"
extern capture_file cf;
static int proto_frame = -1;
static int hf_frame_arrival_time = -1;
static int hf_frame_time_delta = -1;
static int hf_frame_number = -1;
static int hf_frame_packet_len = -1;
static int hf_frame_capture_len = -1;
static gint ett_frame = -1;
gchar *
ether_to_str(const guint8 *ad) {
static gchar str[3][18];
static gchar *cur;
gchar *p;
int i;
guint32 octet;
static const gchar hex_digits[16] = "0123456789abcdef";
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
p = &cur[18];
*--p = '\0';
i = 5;
for (;;) {
octet = ad[i];
*--p = hex_digits[octet&0xF];
octet >>= 4;
*--p = hex_digits[octet&0xF];
if (i == 0)
break;
*--p = ':';
i--;
}
return p;
}
gchar *
ip_to_str(const guint8 *ad) {
static gchar str[3][16];
static gchar *cur;
gchar *p;
int i;
guint32 octet;
guint32 digit;
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
p = &cur[16];
*--p = '\0';
i = 3;
for (;;) {
octet = ad[i];
*--p = (octet%10) + '0';
octet /= 10;
digit = octet%10;
octet /= 10;
if (digit != 0 || octet != 0)
*--p = digit + '0';
if (octet != 0)
*--p = octet + '0';
if (i == 0)
break;
*--p = '.';
i--;
}
return p;
}
gchar *
ip6_to_str(struct e_in6_addr *ad) {
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif
static gchar buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
return buf;
}
#define PLURALIZE(n) (((n) > 1) ? "s" : "")
#define COMMA(do_it) ((do_it) ? ", " : "")
gchar *
time_secs_to_str(guint32 time)
{
static gchar str[3][8+1+4+2+2+5+2+2+7+2+2+7+1];
static gchar *cur, *p;
int hours, mins, secs;
int do_comma;
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
secs = time % 60;
time /= 60;
mins = time % 60;
time /= 60;
hours = time % 24;
time /= 24;
p = cur;
if (time != 0) {
sprintf(p, "%u day%s", time, PLURALIZE(time));
p += strlen(p);
do_comma = 1;
} else
do_comma = 0;
if (hours != 0) {
sprintf(p, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
p += strlen(p);
do_comma = 1;
} else
do_comma = 0;
if (mins != 0) {
sprintf(p, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
p += strlen(p);
do_comma = 1;
} else
do_comma = 0;
if (secs != 0)
sprintf(p, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
return cur;
}
/* Max string length for displaying byte string. */
#define MAX_BYTE_STR_LEN 20
/* Turn an array of bytes into a string showing the bytes in hex. */
gchar *
bytes_to_str(const guint8 *bd, int bd_len) {
static gchar str[3][MAX_BYTE_STR_LEN+3+1];
static gchar *cur;
gchar *p;
int len;
static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
p = cur;
len = MAX_BYTE_STR_LEN;
while (bd_len > 0 && len > 0) {
*p++ = hex[(*bd) >> 4];
*p++ = hex[(*bd) & 0xF];
len -= 2;
bd++;
bd_len--;
}
if (bd_len != 0) {
/* Note that we're not showing the full string. */
*p++ = '.';
*p++ = '.';
*p++ = '.';
}
*p = '\0';
return cur;
}
static const char *mon_names[12] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
gchar *
abs_time_to_str(struct timeval *abs_time)
{
struct tm *tmp;
static gchar *cur;
static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
tmp = localtime(&abs_time->tv_sec);
sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
mon_names[tmp->tm_mon],
tmp->tm_mday,
tmp->tm_year + 1900,
tmp->tm_hour,
tmp->tm_min,
tmp->tm_sec,
(long)abs_time->tv_usec/100);
return cur;
}
gchar *
rel_time_to_str(struct timeval *rel_time)
{
static gchar *cur;
static char str[3][10+1+6+1];
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
(long)rel_time->tv_usec);
return cur;
}
/*
* Given a pointer into a data buffer, and to the end of the buffer,
* find the end of the (putative) line at that position in the data
* buffer.
* Return a pointer to the EOL character(s) in "*eol".
*/
const u_char *
find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
{
const u_char *lineend;
lineend = memchr(data, '\n', dataend - data);
if (lineend == NULL) {
/*
* No LF - line is probably continued in next TCP segment.
*/
lineend = dataend;
*eol = dataend;
} else {
/*
* Is the LF at the beginning of the line?
*/
if (lineend > data) {
/*
* No - is it preceded by a carriage return?
* (Perhaps it's supposed to be, but that's not guaranteed....)
*/
if (*(lineend - 1) == '\r') {
/*
* Yes. The EOL starts with the CR.
*/
*eol = lineend - 1;
} else {
/*
* No. The EOL starts with the LF.
*/
*eol = lineend;
/*
* I seem to remember that we once saw lines ending with LF-CR
* in an HTTP request or response, so check if it's *followed*
* by a carriage return.
*/
if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
/*
* It's <non-LF><LF><CR>; say it ends with the CR.
*/
lineend++;
}
}
}
/*
* Point to the character after the last character.
*/
lineend++;
}
return lineend;
}
#define MAX_COLUMNS_LINE_DETAIL 999
/*
* Get the length of the next token in a line, and the beginning of the
* next token after that (if any).
* Return 0 if there is no next token.
*/
int
get_token_len(const u_char *linep, const u_char *lineend,
const u_char **next_token)
{
const u_char *tokenp;
int token_len;
tokenp = linep;
/*
* Search for a blank, a CR or an LF, or the end of the buffer.
*/
while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
linep++;
token_len = linep - tokenp;
/*
* Skip trailing blanks.
*/
while (linep < lineend && *linep == ' ')
linep++;
*next_token = linep;
return token_len;
}
/*
* Given a string, generate a string from it that shows non-printable
* characters as C-style escapes, and return a pointer to it.
*/
gchar *
format_text_ASCII(const u_char *string, int len)
{
static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
gchar *fmtbufp;
int column;
const u_char *stringend = string + len;
u_char c;
column = 0;
fmtbufp = &fmtbuf[0];
while (string < stringend) {
if (column >= MAX_COLUMNS_LINE_DETAIL) {
/*
* Put "..." and quit.
*/
strcpy(fmtbufp, " ...");
break;
}
c = *string++;
if (isprint(c)) {
*fmtbufp++ = c;
column++;
} else {
switch (c) {
case '\\':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = '\\';
column++;
break;
case '\a':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = 'a';
column++;
break;
case '\b':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = 'b';
column++;
break;
case '\f':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = 'f';
column++;
break;
case '\n':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = 'n';
column++;
break;
case '\r':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = 'r';
column++;
break;
case '\t':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = 't';
column++;
break;
case '\v':
*fmtbufp++ = '\\';
column++;
*fmtbufp++ = 'v';
column++;
break;
default:
*fmtbufp++ = '.';
column++;
break;
}
}
}
*fmtbufp = '\0';
return fmtbuf;
}
/*
* Given a string, generate a string from it that shows non-printable
* characters as C-style escapes, and return a pointer to it.
*/
gchar *
format_text(const u_char *string, int len)
{
static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
gchar *fmtbufp;
int column;
const u_char *stringend = string + len;
u_char c;
int i;
column = 0;
fmtbufp = &fmtbuf[0];
while (string < stringend) {
if (column >= MAX_COLUMNS_LINE_DETAIL) {
/*
* Put "..." and quit.
*/
strcpy(fmtbufp, " ...");
break;
}
c = *string++;
if (isprint(c)) {
*fmtbufp++ = c;
column++;
} else {
*fmtbufp++ = '\\';
column++;
switch (c) {
case '\\':
*fmtbufp++ = '\\';
column++;
break;
case '\a':
*fmtbufp++ = 'a';
column++;
break;
case '\b':
*fmtbufp++ = 'b';
column++;
break;
case '\f':
*fmtbufp++ = 'f';
column++;
break;
case '\n':
*fmtbufp++ = 'n';
column++;
break;
case '\r':
*fmtbufp++ = 'r';
column++;
break;
case '\t':
*fmtbufp++ = 't';
column++;
break;
case '\v':
*fmtbufp++ = 'v';
column++;
break;
default:
i = (c>>6)&03;
*fmtbufp++ = i + '0';
column++;
i = (c>>3)&07;
*fmtbufp++ = i + '0';
column++;
i = (c>>0)&07;
*fmtbufp++ = i + '0';
column++;
break;
}
}
}
*fmtbufp = '\0';
return fmtbuf;
}
/* Tries to match val against each element in the value_string array vs.
Returns the associated string ptr on a match.
Formats val with fmt, and returns the resulting string, on failure. */
gchar*
val_to_str(guint32 val, const value_string *vs, const char *fmt) {
gchar *ret;
static gchar str[3][64];
static gchar *cur;
ret = match_strval(val, vs);
if (ret != NULL)
return ret;
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
snprintf(cur, 64, fmt, val);
return cur;
}
/* Tries to match val against each element in the value_string array vs.
Returns the associated string ptr on a match, or NULL on failure. */
gchar*
match_strval(guint32 val, const value_string *vs) {
gint i = 0;
while (vs[i].strptr) {
if (vs[i].value == val)
return(vs[i].strptr);
i++;
}
return(NULL);
}
/* Generate, into "buf", a string showing the bits of a bitfield.
Return a pointer to the character after that string. */
char *
decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
{
int i;
guint32 bit;
char *p;
i = 0;
p = buf;
bit = 1 << (width - 1);
for (;;) {
if (mask & bit) {
/* This bit is part of the field. Show its value. */
if (val & bit)
*p++ = '1';
else
*p++ = '0';
} else {
/* This bit is not part of the field. */
*p++ = '.';
}
bit >>= 1;
i++;
if (i >= width)
break;
if (i % 4 == 0)
*p++ = ' ';
}
strcpy(p, " = ");
p += 3;
return p;
}
/* Generate a string describing a Boolean bitfield (a one-bit field that
says something is either true of false). */
const char *
decode_boolean_bitfield(guint32 val, guint32 mask, int width,
const char *truedesc, const char *falsedesc)
{
static char buf[1025];
char *p;
p = decode_bitfield_value(buf, val, mask, width);
if (val & mask)
strcpy(p, truedesc);
else
strcpy(p, falsedesc);
return buf;
}
/* Generate a string describing an enumerated bitfield (an N-bit field
with various specific values having particular names). */
const char *
decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
const value_string *tab, const char *fmt)
{
static char buf[1025];
char *p;
p = decode_bitfield_value(buf, val, mask, width);
sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
return buf;
}
/* Generate a string describing a numeric bitfield (an N-bit field whose
value is just a number). */
const char *
decode_numeric_bitfield(guint32 val, guint32 mask, int width,
const char *fmt)
{
static char buf[1025];
char *p;
int shift = 0;
/* Compute the number of bits we have to shift the bitfield right
to extract its value. */
while ((mask & (1<<shift)) == 0)
shift++;
p = decode_bitfield_value(buf, val, mask, width);
sprintf(p, fmt, (val & mask) >> shift);
return buf;
}
/* Checks to see if a particular packet information element is needed for
the packet list */
gint
check_col(frame_data *fd, gint el) {
int i;
if (fd->cinfo) {
for (i = 0; i < fd->cinfo->num_cols; i++) {
if (fd->cinfo->fmt_matx[i][el])
return TRUE;
}
}
return FALSE;
}
/* Adds a vararg list to a packet info string. */
void
col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
va_list ap;
int i;
size_t max_len;
va_start(ap, format);
for (i = 0; i < fd->cinfo->num_cols; i++) {
if (fd->cinfo->fmt_matx[i][el]) {
if (el == COL_INFO)
max_len = COL_MAX_INFO_LEN;
else
max_len = COL_MAX_LEN;
vsnprintf(fd->cinfo->col_data[i], max_len, format, ap);
}
}
}
void
col_add_str(frame_data *fd, gint el, const gchar* str) {
int i;
size_t max_len;
for (i = 0; i < fd->cinfo->num_cols; i++) {
if (fd->cinfo->fmt_matx[i][el]) {
if (el == COL_INFO)
max_len = COL_MAX_INFO_LEN;
else
max_len = COL_MAX_LEN;
strncpy(fd->cinfo->col_data[i], str, max_len);
fd->cinfo->col_data[i][max_len - 1] = 0;
}
}
}
/* Appends a vararg list to a packet info string. */
void
col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
va_list ap;
int i;
size_t len, max_len;
va_start(ap, format);
for (i = 0; i < fd->cinfo->num_cols; i++) {
if (fd->cinfo->fmt_matx[i][el]) {
len = strlen(fd->cinfo->col_data[i]);
if (el == COL_INFO)
max_len = COL_MAX_INFO_LEN;
else
max_len = COL_MAX_LEN;
vsnprintf(&fd->cinfo->col_data[i][len], max_len - len, format, ap);
}
}
}
void
col_append_str(frame_data *fd, gint el, gchar* str) {
int i;
size_t len, max_len;
for (i = 0; i < fd->cinfo->num_cols; i++) {
if (fd->cinfo->fmt_matx[i][el]) {
len = strlen(fd->cinfo->col_data[i]);
if (el == COL_INFO)
max_len = COL_MAX_LEN;
else
max_len = COL_MAX_INFO_LEN;
strncat(fd->cinfo->col_data[i], str, max_len - len);
fd->cinfo->col_data[i][max_len - 1] = 0;
}
}
}
void blank_packetinfo(void)
{
pi.dl_src.type = AT_NONE;
pi.dl_dst.type = AT_NONE;
pi.net_src.type = AT_NONE;
pi.net_dst.type = AT_NONE;
pi.src.type = AT_NONE;
pi.dst.type = AT_NONE;
pi.ipproto = 0;
pi.ptype = PT_NONE;
pi.srcport = 0;
pi.destport = 0;
}
/* Allow protocols to register "init" routines, which are called before
we make a pass through a capture file and dissect all its packets
(e.g., when we read in a new capture file, or run a "filter packets"
or "colorize packets" pass over the current capture file). */
static GSList *init_routines;
void
register_init_routine(void (*func)(void))
{
init_routines = g_slist_append(init_routines, func);
}
/* Call all the registered "init" routines. */
static void
call_init_routine(gpointer routine, gpointer dummy)
{
void (*func)(void) = routine;
(*func)();
}
void
init_all_protocols(void)
{
g_slist_foreach(init_routines, &call_init_routine, NULL);
}
/* this routine checks the frame type from the cf structure */
void
dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
{
proto_tree *fh_tree;
proto_item *ti;
struct timeval tv;
/* Put in frame header information. */
if (tree) {
ti = proto_tree_add_item_format(tree, proto_frame, 0, fd->cap_len,
NULL, "Frame (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
fh_tree = proto_item_add_subtree(ti, ett_frame);
tv.tv_sec = fd->abs_secs;
tv.tv_usec = fd->abs_usecs;
proto_tree_add_item(fh_tree, hf_frame_arrival_time,
0, 0, &tv);
tv.tv_sec = fd->del_secs;
tv.tv_usec = fd->del_usecs;
proto_tree_add_item(fh_tree, hf_frame_time_delta,
0, 0, &tv);
proto_tree_add_item(fh_tree, hf_frame_number,
0, 0, fd->num);
proto_tree_add_item_format(fh_tree, hf_frame_packet_len,
0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
plurality(fd->pkt_len, "", "s"));
proto_tree_add_item_format(fh_tree, hf_frame_capture_len,
0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len,
plurality(fd->cap_len, "", "s"));
}
blank_packetinfo();
/* Set the initial payload to the packet length, and the initial
captured payload to the capture length (other protocols may
reduce them if their headers say they're less). */
pi.len = fd->pkt_len;
pi.captured_len = fd->cap_len;
switch (fd->lnk_t) {
case WTAP_ENCAP_ETHERNET :
dissect_eth(pd, 0, fd, tree);
break;
case WTAP_ENCAP_FDDI :
dissect_fddi(pd, fd, tree, FALSE);
break;
case WTAP_ENCAP_FDDI_BITSWAPPED :
dissect_fddi(pd, fd, tree, TRUE);
break;
case WTAP_ENCAP_TR :
dissect_tr(pd, 0, fd, tree);
break;
case WTAP_ENCAP_NULL :
dissect_null(pd, fd, tree);
break;
case WTAP_ENCAP_PPP :
dissect_ppp(pd, fd, tree);
break;
case WTAP_ENCAP_LAPB :
dissect_lapb(pd, fd, tree);
break;
case WTAP_ENCAP_RAW_IP :
dissect_raw(pd, fd, tree);
break;
case WTAP_ENCAP_LINUX_ATM_CLIP :
dissect_clip(pd, fd, tree);
break;
case WTAP_ENCAP_ATM_SNIFFER :
dissect_atm(pd, fd, tree);
break;
case WTAP_ENCAP_ASCEND :
dissect_ascend(pd, fd, tree);
break;
case WTAP_ENCAP_LAPD :
dissect_lapd(pd, fd, tree);
break;
}
}
void
proto_register_frame(void)
{
static hf_register_info hf[] = {
{ &hf_frame_arrival_time,
{ "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
""}},
{ &hf_frame_time_delta,
{ "Time delta from previous packet", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
0x0,
"" }},
{ &hf_frame_number,
{ "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
"" }},
{ &hf_frame_packet_len,
{ "Total Frame Length", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
"" }},
{ &hf_frame_capture_len,
{ "Capture Frame Length", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
"" }},
};
static gint *ett[] = {
&ett_frame,
};
proto_frame = proto_register_protocol("Frame", "frame");
proto_register_field_array(proto_frame, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
/* packet.h
* Definitions for packet disassembly structures and routines
*
* $Id: packet.h,v 1.144 1999/11/17 21:58:32 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxx>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PACKET_H__
#define __PACKET_H__
#ifndef __WTAP_H__
#include "wiretap/wtap.h"
#endif
#ifndef __PROTO_H__
#include "proto.h"
#endif
/* Pointer versions of ntohs and ntohl. Given a pointer to a member of a
* byte array, returns the value of the two or four bytes at the pointer.
* The pletoh[sl] versions return the little-endian representation.
*/
#define pntohs(p) ((guint16) \
((guint16)*((guint8 *)p+0)<<8| \
(guint16)*((guint8 *)p+1)<<0))
#define pntohl(p) ((guint32)*((guint8 *)p+0)<<24| \
(guint32)*((guint8 *)p+1)<<16| \
(guint32)*((guint8 *)p+2)<<8| \
(guint32)*((guint8 *)p+3)<<0)
#define pletohs(p) ((guint16) \
((guint16)*((guint8 *)p+1)<<8| \
(guint16)*((guint8 *)p+0)<<0))
#define pletohl(p) ((guint32)*((guint8 *)p+3)<<24| \
(guint32)*((guint8 *)p+2)<<16| \
(guint32)*((guint8 *)p+1)<<8| \
(guint32)*((guint8 *)p+0)<<0)
#define hi_nibble(b) ((b & 0xf0) >> 4)
#define lo_nibble(b) (b & 0x0f)
/* Useful when you have an array whose size you can tell at compile-time */
#define array_length(x) (sizeof x / sizeof x[0])
/* Useful when highlighting regions inside a dissect_*() function. With this
* macro, you can highlight from an arbitrary offset to the end of the
* packet (which may come before the end of the frame).
* See dissect_data() for an example.
*/
#define END_OF_FRAME (pi.captured_len - offset)
/* Check whether the "len" bytes of data starting at "offset" is
* entirely inside the captured data for this packet. */
#define BYTES_ARE_IN_FRAME(offset, len) ((offset) + (len) <= pi.captured_len)
/* Check whether there's any data at all starting at "offset". */
#define IS_DATA_IN_FRAME(offset) ((offset) < pi.captured_len)
/* To pass one of two strings, singular or plural */
#define plurality(d,s,p) ((d) == 1 ? (s) : (p))
typedef struct _column_info {
gint num_cols; /* Number of columns */
gint *col_fmt; /* Format of column */
gboolean **fmt_matx; /* Specifies which formats apply to a column */
gint *col_width; /* Column widths to use during a "-S" capture */
gchar **col_title; /* Column titles */
gchar **col_data; /* Column data */
} column_info;
#define COL_MAX_LEN 256
#define COL_MAX_INFO_LEN 4096
typedef struct _packet_counts {
gint tcp;
gint udp;
gint icmp;
gint ospf;
gint gre;
gint netbios;
gint other;
gint total;
} packet_counts;
/* XXX - some of this stuff is used only while a packet is being dissected;
should we keep around a separate data structure for that, to save
memory?
Also, should the pseudo-header be supplied by Wiretap when you do a
seek-and-read, so that we don't have to save it for all frames? */
typedef struct _frame_data {
struct _frame_data *next; /* Next element in list */
struct _frame_data *prev; /* Previous element in list */
guint32 num; /* Frame number */
guint32 pkt_len; /* Packet length */
guint32 cap_len; /* Amount actually captured */
guint32 rel_secs; /* Relative seconds */
guint32 rel_usecs; /* Relative microseconds */
guint32 abs_secs; /* Absolute seconds */
guint32 abs_usecs; /* Absolute microseconds */
guint32 del_secs; /* Delta seconds */
guint32 del_usecs; /* Delta microseconds */
long file_off; /* File offset */
column_info *cinfo; /* Column formatting information */
gint row; /* Row number for this packet in the display */
int lnk_t; /* Per-packet encapsulation/data-link type */
gboolean passed_dfilter; /* TRUE = display, FALSE = no display */
union pseudo_header pseudo_header; /* "pseudo-header" from wiretap */
} frame_data;
/* Types of addresses Ethereal knows about. */
typedef enum {
AT_NONE, /* no link-layer address */
AT_ETHER, /* MAC (Ethernet, 802.x, FDDI) address */
AT_IPv4, /* IPv4 */
AT_IPv6, /* IPv6 */
AT_IPX, /* IPX */
AT_SNA, /* SNA */
AT_ATALK, /* Appletalk DDP */
AT_VINES /* Banyan Vines */
} address_type;
typedef struct _address {
address_type type; /* type of address */
int len; /* length of address, in bytes */
const guint8 *data; /* bytes that constitute address */
} address;
#define SET_ADDRESS(addr, addr_type, addr_len, addr_data) { \
(addr)->type = (addr_type); \
(addr)->len = (addr_len); \
(addr)->data = (addr_data); \
}
/* Types of port numbers Ethereal knows about. */
typedef enum {
PT_NONE, /* no port number */
PT_TCP, /* TCP */
PT_UDP /* UDP */
} port_type;
typedef struct _packet_info {
int len;
int captured_len;
address dl_src; /* link-layer source address */
address dl_dst; /* link-layer destination address */
address net_src; /* network-layer source address */
address net_dst; /* network-layer destination address */
address src; /* source address (net if present, DL otherwise )*/
address dst; /* destination address (net if present, DL otherwise )*/
guint32 ipproto;
port_type ptype; /* type of the following two port numbers */
guint32 srcport; /* source port */
guint32 destport; /* destination port */
guint32 match_port;
int iplen;
int iphdrlen;
} packet_info;
extern packet_info pi;
/* Struct for the match_strval function */
typedef struct _value_string {
guint32 value;
gchar *strptr;
} value_string;
/* Struct for boolean enumerations */
typedef struct true_false_string {
char *true_string;
char *false_string;
} true_false_string;
/* Many of the structs and definitions below and in packet-*.c files
* were taken from include files in the Linux distribution. */
typedef struct tcp_extra_data {
int match_port;
int sport;
int dport;
} tcp_extra_data;
/* Utility routines used by packet*.c */
gchar* ether_to_str(const guint8 *);
gchar* ip_to_str(const guint8 *);
struct e_in6_addr;
gchar* ip6_to_str(struct e_in6_addr *);
gchar* ipx_addr_to_str(guint32, const guint8 *);
gchar* abs_time_to_str(struct timeval*);
gchar* rel_time_to_str(struct timeval*);
gchar* time_secs_to_str(guint32);
gchar* bytes_to_str(const guint8 *, int);
const u_char *find_line_end(const u_char *data, const u_char *dataend,
const u_char **eol);
int get_token_len(const u_char *linep, const u_char *lineend,
const u_char **next_token);
gchar* format_text(const u_char *line, int len);
gchar* format_text_ASCII(const u_char *line, int len);
gchar* val_to_str(guint32, const value_string *, const char *);
gchar* match_strval(guint32, const value_string*);
char * decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width);
const char *decode_boolean_bitfield(guint32 val, guint32 mask, int width,
const char *truedesc, const char *falsedesc);
const char *decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
const value_string *tab, const char *fmt);
const char *decode_numeric_bitfield(guint32 val, guint32 mask, int width,
const char *fmt);
gint check_col(frame_data *, gint);
#if __GNUC__ == 2
void col_add_fstr(frame_data *, gint, gchar *, ...)
__attribute__((format (printf, 3, 4)));
void col_append_fstr(frame_data *, gint, gchar *, ...)
__attribute__((format (printf, 3, 4)));
#else
void col_add_fstr(frame_data *, gint, gchar *, ...);
void col_append_fstr(frame_data *, gint, gchar *, ...);
#endif
void col_add_str(frame_data *, gint, const gchar *);
void col_append_str(frame_data *, gint, gchar *);
void blank_packetinfo(void);
/* Allow protocols to register "init" routines, which are called before
we make a pass through a capture file and dissect all its packets
(e.g., when we read in a new capture file, or run a "filter packets"
or "colorize packets" pass over the current capture file). */
void register_init_routine(void (*func)(void));
/* Call all the registered "init" routines. */
void init_all_protocols(void);
void dissect_packet(const u_char *, frame_data *, proto_tree *);
/*
* Routines in packet-*.c
* Routines should take three args: packet data *, cap_len, packet_counts *
* They should never modify the packet data.
*/
void capture_clip(const u_char *, guint32, packet_counts *);
void capture_eth(const u_char *, guint32, packet_counts *);
void capture_fddi(const u_char *, guint32, packet_counts *);
void capture_null(const u_char *, guint32, packet_counts *);
void capture_ppp(const u_char *, guint32, packet_counts *);
void capture_raw(const u_char *, guint32, packet_counts *);
void capture_tr(const u_char *, guint32, packet_counts *);
/*
* Routines in packet-*.c
* Routines should take four args: packet data *, offset, cap_len,
* packet_counts *
* They should never modify the packet data.
*/
void capture_netbios(const u_char *, int, guint32, packet_counts *);
void capture_llc(const u_char *, int, guint32, packet_counts *);
void capture_ip(const u_char *, int, guint32, packet_counts *);
/*
* Routines in packet-*.c
* Routines should take three args: packet data *, frame_data *, tree *
* They should never modify the packet data.
*/
void dissect_ascend(const u_char *, frame_data *, proto_tree *);
void dissect_atm(const u_char *, frame_data *, proto_tree *);
void dissect_clip(const u_char *, frame_data *, proto_tree *);
void dissect_lapb(const u_char *, frame_data *, proto_tree *);
void dissect_lapd(const u_char *, frame_data *, proto_tree *);
void dissect_null(const u_char *, frame_data *, proto_tree *);
void dissect_ppp(const u_char *, frame_data *, proto_tree *);
void dissect_raw(const u_char *, frame_data *, proto_tree *);
/*
* Routines in packet-*.c
* Routines should take four args: packet data *, frame_data *, tree *,
* gboolean
* They should never modify the packet data.
*/
void dissect_fddi(const u_char *, frame_data *, proto_tree *, gboolean);
typedef void (*DissectFunc) (const u_char*, int, frame_data*, proto_tree*);
/*
* Routines in packet-*.c
* Routines should take four args: packet data *, offset, frame_data *,
* tree *
* They should never modify the packet data.
*/
int dissect_ah(const u_char *, int, frame_data *, proto_tree *);
void dissect_aarp(const u_char *, int, frame_data *, proto_tree *);
void dissect_afs(const u_char *, int, frame_data *, proto_tree *);
void dissect_arp(const u_char *, int, frame_data *, proto_tree *);
void dissect_bgp(const u_char *, int, frame_data *, proto_tree *);
void dissect_bootp(const u_char *, int, frame_data *, proto_tree *);
void dissect_bpdu(const u_char *, int, frame_data *, proto_tree *);
void dissect_cdp(const u_char *, int, frame_data *, proto_tree *);
void dissect_cotp(const u_char *, int, frame_data *, proto_tree *);
void dissect_data(const u_char *, int, frame_data *, proto_tree *);
void dissect_ddp(const u_char *, int, frame_data *, proto_tree *);
void dissect_dns(const u_char *, int, frame_data *, proto_tree *);
void dissect_eigrp(const u_char *, int, frame_data *, proto_tree *);
void dissect_esp(const u_char *, int, frame_data *, proto_tree *);
void dissect_eth(const u_char *, int, frame_data *, proto_tree *);
void dissect_ftp(const u_char *, int, frame_data *, proto_tree *);
void dissect_ftpdata(const u_char *, int, frame_data *, proto_tree *);
void dissect_giop(const u_char *, int, frame_data *, proto_tree *);
void dissect_http(const u_char *, int, frame_data *, proto_tree *);
void dissect_icmp(const u_char *, int, frame_data *, proto_tree *);
void dissect_icmpv6(const u_char *, int, frame_data *, proto_tree *);
void dissect_igmp(const u_char *, int, frame_data *, proto_tree *);
void dissect_ip(const u_char *, int, frame_data *, proto_tree *);
void dissect_ipcomp(const u_char *, int, frame_data *, proto_tree *);
void dissect_ipp(const u_char *, int, frame_data *, proto_tree *);
void dissect_ipv6(const u_char *, int, frame_data *, proto_tree *);
void dissect_ipx(const u_char *, int, frame_data *, proto_tree *);
void dissect_llc(const u_char *, int, frame_data *, proto_tree *);
void dissect_lpd(const u_char *, int, frame_data *, proto_tree *);
void dissect_mapi(const u_char *, int, frame_data *, proto_tree *);
void dissect_nbdgm(const u_char *, int, frame_data *, proto_tree *);
void dissect_netbios(const u_char *, int, frame_data *, proto_tree *);
void dissect_nbipx(const u_char *, int, frame_data *, proto_tree *);
void dissect_nbns(const u_char *, int, frame_data *, proto_tree *);
void dissect_nbss(const u_char *, int, frame_data *, proto_tree *);
void dissect_ncp(const u_char *, int, frame_data *, proto_tree *);
void dissect_nntp(const u_char *, int, frame_data *, proto_tree *);
void dissect_ntp(const u_char *, int, frame_data *, proto_tree *);
void dissect_nwlink_dg(const u_char *, int, frame_data *, proto_tree *);
void dissect_osi(const u_char *, int, frame_data *, proto_tree *);
void dissect_ospf(const u_char *, int, frame_data *, proto_tree *);
void dissect_ospf_hello(const u_char *, int, frame_data *, proto_tree *);
void dissect_pim(const u_char *, int, frame_data *, proto_tree *);
void dissect_pop(const u_char *, int, frame_data *, proto_tree *);
void dissect_pppoed(const u_char *, int, frame_data *, proto_tree *);
void dissect_pppoes(const u_char *, int, frame_data *, proto_tree *);
void dissect_icp(const u_char *,int, frame_data *, proto_tree *);
void dissect_icq(const u_char *,int, frame_data *, proto_tree *);
void dissect_imap(const u_char *,int, frame_data *, proto_tree *);
void dissect_isakmp(const u_char *, int, frame_data *, proto_tree *);
void dissect_pim(const u_char *, int, frame_data *, proto_tree *);
void dissect_q931(const u_char *, int, frame_data *, proto_tree *);
void dissect_radius(const u_char *, int, frame_data *, proto_tree *);
void dissect_rip(const u_char *, int, frame_data *, proto_tree *);
void dissect_ripng(const u_char *, int, frame_data *, proto_tree *);
void dissect_rsvp(const u_char *, int, frame_data *, proto_tree *);
void dissect_rtsp(const u_char *, int, frame_data *, proto_tree *);
void dissect_rx(const u_char *, int, frame_data *, proto_tree *);
void dissect_sap(const u_char *, int, frame_data *, proto_tree *);
void dissect_sdp(const u_char *, int, frame_data *, proto_tree *);
void dissect_sna(const u_char *, int, frame_data *, proto_tree *);
void dissect_snmp(const u_char *, int, frame_data *, proto_tree *);
void dissect_tcp(const u_char *, int, frame_data *, proto_tree *);
void dissect_telnet(const u_char *, int, frame_data *, proto_tree *);
void dissect_tftp(const u_char *, int, frame_data *, proto_tree *);
void dissect_tr(const u_char *, int, frame_data *, proto_tree *);
void dissect_trmac(const u_char *, int, frame_data *, proto_tree *);
void dissect_udp(const u_char *, int, frame_data *, proto_tree *);
void dissect_vines(const u_char *, int, frame_data *, proto_tree *);
void dissect_vines_arp(const u_char *, int, frame_data *, proto_tree *);
void dissect_vines_frp(const u_char *, int, frame_data *, proto_tree *);
void dissect_vines_icp(const u_char *, int, frame_data *, proto_tree *);
void dissect_vines_ipc(const u_char *, int, frame_data *, proto_tree *);
void dissect_vines_rtp(const u_char *, int, frame_data *, proto_tree *);
void dissect_vines_spp(const u_char *, int, frame_data *, proto_tree *);
void dissect_vlan(const u_char *, int, frame_data *, proto_tree *);
void dissect_payload_ppp(const u_char *, int, frame_data *, proto_tree *);
void dissect_x25(const u_char *, int, frame_data *, proto_tree *);
void dissect_yhoo(const u_char *, int, frame_data *, proto_tree *);
void dissect_smb(const u_char *, int, frame_data *, proto_tree *, int);
void dissect_pptp(const u_char *, int, frame_data *, proto_tree *);
void dissect_gre(const u_char *, int, frame_data *, proto_tree *);
/*
* Routines in packet-*.c
* Routines should take four args: packet data *, offset, frame_data *,
* tree *
* They should never modify the packet data.
* They should return TRUE if the packet is of the type the routine would
* dissect, FALSE otherwise.
*/
gboolean dissect_rpc(const u_char *, int, frame_data *, proto_tree *);
void init_dissect_rpc(void);
void init_dissect_udp(void);
void init_dissect_x25(void);
/* These functions are in ethertype.c */
void capture_ethertype(guint16 etype, int offset,
const u_char *pd, guint32 cap_len, packet_counts *ld);
void ethertype(guint16 etype, int offset,
const u_char *pd, frame_data *fd, proto_tree *tree,
proto_tree *fh_tree, int item_id);
extern const value_string etype_vals[];
/* These functions are in packet-arp.c */
gchar *arphrdaddr_to_str(guint8 *ad, int ad_len, guint16 type);
gchar *arphrdtype_to_str(guint16 hwtype, const char *fmt);
/* ipproto.c */
extern const char *ipprotostr(int proto);
/*
* All of the possible columns in summary listing.
*
* NOTE: The SRC and DST entries MUST remain in this order, or else you
* need to fix the offset #defines before get_column_format!
*/
enum {
COL_NUMBER, /* Packet list item number */
COL_CLS_TIME, /* Command line-specified time (default relative) */
COL_REL_TIME, /* Relative time */
COL_ABS_TIME, /* Absolute time */
COL_DELTA_TIME, /* Delta time */
COL_DEF_SRC, /* Source address */
COL_RES_SRC, /* Resolved source */
COL_UNRES_SRC, /* Unresolved source */
COL_DEF_DL_SRC, /* Data link layer source address */
COL_RES_DL_SRC, /* Resolved DL source */
COL_UNRES_DL_SRC, /* Unresolved DL source */
COL_DEF_NET_SRC, /* Network layer source address */
COL_RES_NET_SRC, /* Resolved net source */
COL_UNRES_NET_SRC, /* Unresolved net source */
COL_DEF_DST, /* Destination address */
COL_RES_DST, /* Resolved dest */
COL_UNRES_DST, /* Unresolved dest */
COL_DEF_DL_DST, /* Data link layer dest address */
COL_RES_DL_DST, /* Resolved DL dest */
COL_UNRES_DL_DST, /* Unresolved DL dest */
COL_DEF_NET_DST, /* Network layer dest address */
COL_RES_NET_DST, /* Resolved net dest */
COL_UNRES_NET_DST, /* Unresolved net dest */
COL_DEF_SRC_PORT, /* Source port */
COL_RES_SRC_PORT, /* Resolved source port */
COL_UNRES_SRC_PORT, /* Unresolved source port */
COL_DEF_DST_PORT, /* Destination port */
COL_RES_DST_PORT, /* Resolved dest port */
COL_UNRES_DST_PORT, /* Unresolved dest port */
COL_PROTOCOL, /* Protocol */
COL_INFO, /* Description */
COL_PACKET_LENGTH, /* Packet length in bytes */
NUM_COL_FMTS /* Should always be last */
};
#endif /* packet.h */
/* packet-smb.c
* Routines for smb packet dissection
* Copyright 1999, Richard Sharpe <rsharpe@xxxxxxxxxx>
*
* $Id: packet-smb.c,v 1.43 1999/11/18 07:32:46 sharpe Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxxxx>
* Copyright 1998 Gerald Combs
*
* Copied from packet-pop.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#include <time.h>
#include <string.h>
#include <glib.h>
#include "packet.h"
#include "conversation.h"
#include "smb.h"
#include "alignment.h"
static int proto_smb = -1;
static int Cap_Offset = 113; /* offset into the packet of the Capabilities flags */
static int Flags2_Offset=68; /* offset into the packet of the Flags2 settings */
static gint ett_smb = -1;
static gint ett_smb_fileattributes = -1;
static gint ett_smb_capabilities = -1;
static gint ett_smb_aflags = -1;
static gint ett_smb_dialects = -1;
static gint ett_smb_mode = -1;
static gint ett_smb_rawmode = -1;
static gint ett_smb_flags = -1;
static gint ett_smb_flags2 = -1;
static gint ett_smb_desiredaccess = -1;
static gint ett_smb_search = -1;
static gint ett_smb_file = -1;
static gint ett_smb_openfunction = -1;
static gint ett_smb_filetype = -1;
static gint ett_smb_action = -1;
static gint ett_smb_writemode = -1;
static gint ett_smb_lock_type = -1;
static int proto_browse = -1;
static gint ett_browse = -1;
static gint ett_browse_flags = -1;
static gint ett_browse_election_criteria = -1;
static gint ett_browse_election_os = -1;
static gint ett_browse_election_desire = -1;
/*
* Struct passed to each SMB decode routine of info it may need
*/
struct smb_info {
int tid, uid, mid, pid; /* Any more? */
};
char *decode_smb_name(unsigned char);
int smb_packet_init_count = 200;
struct smb_request_key {
guint32 conversation;
guint16 mid;
};
struct smb_request_val {
guint16 last_transact2_command;
gchar *last_transact_command;
guint16 mid;
};
GHashTable *smb_request_hash = NULL;
GMemChunk *smb_request_keys = NULL;
GMemChunk *smb_request_vals = NULL;
/* Hash Functions */
gint
smb_equal(gconstpointer v, gconstpointer w)
{
struct smb_request_key *v1 = (struct smb_request_key *)v;
struct smb_request_key *v2 = (struct smb_request_key *)w;
#if defined(DEBUG_SMB_HASH)
printf("Comparing %08X:%u\n and %08X:%u\n",
v1 -> conversation, v1 -> mid,
v2 -> conversation, v2 -> mid);
#endif
if (v1 -> conversation == v2 -> conversation &&
v1 -> mid == v2 -> mid) {
return 1;
}
return 0;
}
guint
smb_hash (gconstpointer v)
{
struct smb_request_key *key = (struct smb_request_key *)v;
guint val;
val = key -> conversation + key -> mid;
#if defined(DEBUG_SMB_HASH)
printf("SMB Hash calculated as %u\n", val);
#endif
return val;
}
/*
* Free up any state information we've saved, and re-initialize the
* tables of state information.
*/
static void
smb_init_protocol(void)
{
#if defined(DEBUG_SMB_HASH)
printf("Initializing SMB hashtable area\n");
#endif
if (smb_request_hash)
g_hash_table_destroy(smb_request_hash);
if (smb_request_keys)
g_mem_chunk_destroy(smb_request_keys);
if (smb_request_vals)
g_mem_chunk_destroy(smb_request_vals);
smb_request_hash = g_hash_table_new(smb_hash, smb_equal);
smb_request_keys = g_mem_chunk_new("smb_request_keys",
sizeof(struct smb_request_key),
smb_packet_init_count * sizeof(struct smb_request_key), G_ALLOC_AND_FREE);
smb_request_vals = g_mem_chunk_new("smb_request_vals",
sizeof(struct smb_request_val),
smb_packet_init_count * sizeof(struct smb_request_val), G_ALLOC_AND_FREE);
}
void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info si, int, int, int, int);
char *SMB_names[256] = {
"SMBcreatedirectory",
"SMBdeletedirectory",
"SMBopen",
"SMBcreate",
"SMBclose",
"SMBflush",
"SMBunlink",
"SMBmv",
"SMBgetatr",
"SMBsetatr",
"SMBread",
"SMBwrite",
"SMBlock",
"SMBunlock",
"SMBctemp",
"SMBmknew",
"SMBchkpth",
"SMBexit",
"SMBlseek",
"SMBlockread",
"SMBwriteunlock",
"unknown-0x15",
"unknown-0x16",
"unknown-0x17",
"unknown-0x18",
"unknown-0x19",
"SMBreadBraw",
"SMBreadBmpx",
"SMBreadBs",
"SMBwriteBraw",
"SMBwriteBmpx",
"SMBwriteBs",
"SMBwriteC",
"unknown-0x21",
"SMBsetattrE",
"SMBgetattrE",
"SMBlockingX",
"SMBtrans",
"SMBtranss",
"SMBioctl",
"SMBioctls",
"SMBcopy",
"SMBmove",
"SMBecho",
"SMBwriteclose",
"SMBopenX",
"SMBreadX",
"SMBwriteX",
"unknown-0x30",
"SMBcloseandtreedisc",
"SMBtrans2",
"SMBtrans2secondary",
"SMBfindclose2",
"SMBfindnotifyclose",
"unknown-0x36",
"unknown-0x37",
"unknown-0x38",
"unknown-0x39",
"unknown-0x3A",
"unknown-0x3B",
"unknown-0x3C",
"unknown-0x3D",
"unknown-0x3E",
"unknown-0x3F",
"unknown-0x40",
"unknown-0x41",
"unknown-0x42",
"unknown-0x43",
"unknown-0x44",
"unknown-0x45",
"unknown-0x46",
"unknown-0x47",
"unknown-0x48",
"unknown-0x49",
"unknown-0x4A",
"unknown-0x4B",
"unknown-0x4C",
"unknown-0x4D",
"unknown-0x4E",
"unknown-0x4F",
"unknown-0x50",
"unknown-0x51",
"unknown-0x52",
"unknown-0x53",
"unknown-0x54",
"unknown-0x55",
"unknown-0x56",
"unknown-0x57",
"unknown-0x58",
"unknown-0x59",
"unknown-0x5A",
"unknown-0x5B",
"unknown-0x5C",
"unknown-0x5D",
"unknown-0x5E",
"unknown-0x5F",
"unknown-0x60",
"unknown-0x61",
"unknown-0x62",
"unknown-0x63",
"unknown-0x64",
"unknown-0x65",
"unknown-0x66",
"unknown-0x67",
"unknown-0x68",
"unknown-0x69",
"unknown-0x6A",
"unknown-0x6B",
"unknown-0x6C",
"unknown-0x6D",
"unknown-0x6E",
"unknown-0x6F",
"SMBtcon",
"SMBtdis",
"SMBnegprot",
"SMBsesssetupX",
"SMBlogoffX",
"SMBtconX",
"unknown-0x76",
"unknown-0x77",
"unknown-0x78",
"unknown-0x79",
"unknown-0x7A",
"unknown-0x7B",
"unknown-0x7C",
"unknown-0x7D",
"unknown-0x7E",
"unknown-0x7F",
"SMBdskattr",
"SMBsearch",
"SMBffirst",
"SMBfunique",
"SMBfclose",
"unknown-0x85",
"unknown-0x86",
"unknown-0x87",
"unknown-0x88",
"unknown-0x89",
"unknown-0x8A",
"unknown-0x8B",
"unknown-0x8C",
"unknown-0x8D",
"unknown-0x8E",
"unknown-0x8F",
"unknown-0x90",
"unknown-0x91",
"unknown-0x92",
"unknown-0x93",
"unknown-0x94",
"unknown-0x95",
"unknown-0x96",
"unknown-0x97",
"unknown-0x98",
"unknown-0x99",
"unknown-0x9A",
"unknown-0x9B",
"unknown-0x9C",
"unknown-0x9D",
"unknown-0x9E",
"unknown-0x9F",
"SMBnttransact",
"SMBnttransactsecondary",
"SMBntcreateX",
"unknown-0xA3",
"SMBntcancel",
"unknown-0xA5",
"unknown-0xA6",
"unknown-0xA7",
"unknown-0xA8",
"unknown-0xA9",
"unknown-0xAA",
"unknown-0xAB",
"unknown-0xAC",
"unknown-0xAD",
"unknown-0xAE",
"unknown-0xAF",
"unknown-0xB0",
"unknown-0xB1",
"unknown-0xB2",
"unknown-0xB3",
"unknown-0xB4",
"unknown-0xB5",
"unknown-0xB6",
"unknown-0xB7",
"unknown-0xB8",
"unknown-0xB9",
"unknown-0xBA",
"unknown-0xBB",
"unknown-0xBC",
"unknown-0xBD",
"unknown-0xBE",
"unknown-0xBF",
"SMBsplopen",
"SMBsplwr",
"SMBsplclose",
"SMBsplretq",
"unknown-0xC4",
"unknown-0xC5",
"unknown-0xC6",
"unknown-0xC7",
"unknown-0xC8",
"unknown-0xC9",
"unknown-0xCA",
"unknown-0xCB",
"unknown-0xCC",
"unknown-0xCD",
"unknown-0xCE",
"unknown-0xCF",
"SMBsends",
"SMBsendb",
"SMBfwdname",
"SMBcancelf",
"SMBgetmac",
"SMBsendstrt",
"SMBsendend",
"SMBsendtxt",
"SMBreadbulk",
"SMBwritebulk",
"SMBwritebulkdata",
"unknown-0xDB",
"unknown-0xDC",
"unknown-0xDD",
"unknown-0xDE",
"unknown-0xDF",
"unknown-0xE0",
"unknown-0xE1",
"unknown-0xE2",
"unknown-0xE3",
"unknown-0xE4",
"unknown-0xE5",
"unknown-0xE6",
"unknown-0xE7",
"unknown-0xE8",
"unknown-0xE9",
"unknown-0xEA",
"unknown-0xEB",
"unknown-0xEC",
"unknown-0xED",
"unknown-0xEE",
"unknown-0xEF",
"unknown-0xF0",
"unknown-0xF1",
"unknown-0xF2",
"unknown-0xF3",
"unknown-0xF4",
"unknown-0xF5",
"unknown-0xF6",
"unknown-0xF7",
"unknown-0xF8",
"unknown-0xF9",
"unknown-0xFA",
"unknown-0xFB",
"unknown-0xFC",
"unknown-0xFD",
"SMBinvalid",
"unknown-0xFF"
};
void
dissect_unknown_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)
{
if (tree) {
proto_tree_add_text(tree, offset, END_OF_FRAME, "Data (%u bytes)",
END_OF_FRAME);
}
}
/*
* Dissect a UNIX like date ...
*/
struct tm *gtime;
static char *
dissect_smbu_date(guint16 date, guint16 time)
{
static char datebuf[4+2+2+2+1];
time_t ltime = (date << 16) + time;
gtime = gmtime(<ime);
sprintf(datebuf, "%04d-%02d-%02d",
1900 + (gtime -> tm_year), gtime -> tm_mon, gtime -> tm_mday);
return datebuf;
}
/*
* Relies on time
*/
static char *
dissect_smbu_time(guint16 date, guint16 time)
{
static char timebuf[2+2+2+2+1];
sprintf(timebuf, "%02d:%02d:%02d",
gtime -> tm_hour, gtime -> tm_min, gtime -> tm_sec);
return timebuf;
}
/*
* Dissect a DOS-format date.
*/
static char *
dissect_dos_date(guint16 date)
{
static char datebuf[4+2+2+1];
sprintf(datebuf, "%04d-%02d-%02d",
((date>>9)&0x7F) + 1980, (date>>5)&0x0F, date&0x1F);
return datebuf;
}
/*
* Dissect a DOS-format time.
*/
static char *
dissect_dos_time(guint16 time)
{
static char timebuf[2+2+2+1];
sprintf(timebuf, "%02d:%02d:%02d",
(time>>11)&0x1F, (time>>5)&0x3F, (time&0x1F)*2);
return timebuf;
}
/* Max string length for displaying Unicode strings. */
#define MAX_UNICODE_STR_LEN 256
/* Turn a little-endian Unicode '\0'-terminated string into a string we
can display.
XXX - for now, we just handle the ISO 8859-1 characters. */
static gchar *
unicode_to_str(const guint8 *us, int *us_lenp) {
static gchar str[3][MAX_UNICODE_STR_LEN+3+1];
static gchar *cur;
gchar *p;
int len;
int us_len;
int overflow = 0;
if (cur == &str[0][0]) {
cur = &str[1][0];
} else if (cur == &str[1][0]) {
cur = &str[2][0];
} else {
cur = &str[0][0];
}
p = cur;
len = MAX_UNICODE_STR_LEN;
us_len = 0;
while (*us != 0 || *(us + 1) != 0) {
if (len > 0) {
*p++ = *us;
len--;
} else
overflow = 1;
us += 2;
us_len += 2;
}
if (overflow) {
/* Note that we're not showing the full string. */
*p++ = '.';
*p++ = '.';
*p++ = '.';
}
*p = '\0';
*us_lenp = us_len;
return cur;
}
/* lookup the service requested. */
static gchar *
lookup_service_description(const guint8 *str) {
gchar *str2;
str2="";
if (strcmp(str,"A:")==0) {
str2 = "Disk Share";
}
else if (strcmp(str,"LPT1:")==0) {
str2 = "Printer";
}
else if (strcmp(str,"IPC")==0) {
str2 = "Named Pipe";
}
else if (strcmp(str,"COMM")==0) {
str2 = "Communications Device";
}
else if (strcmp(str,"?????")==0) {
str2 = "Any Type of Device";
}
return str2;
}
/*
* Each dissect routine is passed an offset to wct and works from there
*/
void
dissect_flush_file_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)
{
guint8 WordCount;
guint16 FID;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_get_disk_attr_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)
{
guint8 WordCount;
guint16 TotalUnits;
guint16 Reserved;
guint16 FreeUnits;
guint16 ByteCount;
guint16 BlocksPerUnit;
guint16 BlockSize;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Total Units */
TotalUnits = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Units: %u", TotalUnits);
}
offset += 2; /* Skip Total Units */
/* Build display for: Blocks Per Unit */
BlocksPerUnit = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Blocks Per Unit: %u", BlocksPerUnit);
}
offset += 2; /* Skip Blocks Per Unit */
/* Build display for: Block Size */
BlockSize = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Block Size: %u", BlockSize);
}
offset += 2; /* Skip Block Size */
/* Build display for: Free Units */
FreeUnits = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Free Units: %u", FreeUnits);
}
offset += 2; /* Skip Free Units */
/* Build display for: Reserved */
Reserved = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
}
offset += 2; /* Skip Reserved */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_set_file_attr_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)
{
proto_tree *Attributes_tree;
proto_item *ti;
guint8 WordCount;
guint8 ByteCount;
guint8 BufferFormat;
guint16 Reserved5;
guint16 Reserved4;
guint16 Reserved3;
guint16 Reserved2;
guint16 Reserved1;
guint16 LastWriteTime;
guint16 LastWriteDate;
guint16 Attributes;
const char *FileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Attributes */
Attributes = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Attributes: 0x%02x", Attributes);
Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
}
offset += 2; /* Skip Attributes */
/* Build display for: Last Write Time */
LastWriteTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Time: %u", dissect_dos_time(LastWriteTime));
}
offset += 2; /* Skip Last Write Time */
/* Build display for: Last Write Date */
LastWriteDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Date: %u", dissect_dos_date(LastWriteDate));
}
offset += 2; /* Skip Last Write Date */
/* Build display for: Reserved 1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 1: %u", Reserved1);
}
offset += 2; /* Skip Reserved 1 */
/* Build display for: Reserved 2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 2: %u", Reserved2);
}
offset += 2; /* Skip Reserved 2 */
/* Build display for: Reserved 3 */
Reserved3 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 3: %u", Reserved3);
}
offset += 2; /* Skip Reserved 3 */
/* Build display for: Reserved 4 */
Reserved4 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 4: %u", Reserved4);
}
offset += 2; /* Skip Reserved 4 */
/* Build display for: Reserved 5 */
Reserved5 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 5: %u", Reserved5);
}
offset += 2; /* Skip Reserved 5 */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: File Name */
FileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
}
offset += strlen(FileName) + 1; /* Skip File Name */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Byte Count (BCC): %u", ByteCount);
}
offset += 1; /* Skip Byte Count (BCC) */
}
}
void
dissect_write_file_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint32 Offset;
guint16 Remaining;
guint16 FID;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Remaining */
Remaining = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Remaining: %u", Remaining);
}
offset += 2; /* Skip Remaining */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_read_mpx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *arent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset, int errcode, int dirn)
{
guint8 WordCount;
guint8 Pad;
guint32 Reserved1;
guint32 Offset;
guint16 Reserved2;
guint16 Reserved;
guint16 MinCount;
guint16 MaxCount;
guint16 FID;
guint16 DataOffset;
guint16 DataLength;
guint16 DataCompactionMode;
guint16 Count;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Max Count */
MaxCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Count: %u", MaxCount);
}
offset += 2; /* Skip Max Count */
/* Build display for: Min Count */
MinCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Min Count: %u", MinCount);
}
offset += 2; /* Skip Min Count */
/* Build display for: Reserved 1 */
Reserved1 = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Reserved 1: %u", Reserved1);
}
offset += 4; /* Skip Reserved 1 */
/* Build display for: Reserved 2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 2: %u", Reserved2);
}
offset += 2; /* Skip Reserved 2 */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count: %u", WordCount);
}
offset += 1; /* Skip Word Count */
if (WordCount > 0) {
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Reserved */
Reserved = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
}
offset += 2; /* Skip Reserved */
/* Build display for: Data Compaction Mode */
DataCompactionMode = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Compaction Mode: %u", DataCompactionMode);
}
offset += 2; /* Skip Data Compaction Mode */
/* Build display for: Reserved */
Reserved = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
}
offset += 2; /* Skip Reserved */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Pad */
Pad = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad: %u", Pad);
}
offset += 1; /* Skip Pad */
}
}
void
dissect_delete_file_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *paernt, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset, int errcode, int dirn)
{
guint8 WordCount;
guint8 BufferFormat;
guint16 ByteCount;
const char *FileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: File Name */
FileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
}
offset += strlen(FileName) + 1; /* Skip File Name */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_query_info2_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)
{
proto_tree *Attributes_tree;
proto_item *ti;
guint8 WordCount;
guint32 FileDataSize;
guint32 FileAllocationSize;
guint16 LastWriteTime;
guint16 LastWriteDate;
guint16 LastAccessTime;
guint16 LastAccessDate;
guint16 FID;
guint16 CreationTime;
guint16 CreationDate;
guint16 ByteCount;
guint16 Attributes;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Creation Date */
CreationDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Date: %u", dissect_dos_date(CreationDate));
}
offset += 2; /* Skip Creation Date */
/* Build display for: Creation Time */
CreationTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Time: %u", dissect_dos_time(CreationTime));
}
offset += 2; /* Skip Creation Time */
/* Build display for: Last Access Date */
LastAccessDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Access Date: %u", dissect_dos_date(LastAccessDate));
}
offset += 2; /* Skip Last Access Date */
/* Build display for: Last Access Time */
LastAccessTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Access Time: %u", dissect_dos_time(LastAccessTime));
}
offset += 2; /* Skip Last Access Time */
/* Build display for: Last Write Date */
LastWriteDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Date: %u", dissect_dos_date(LastWriteDate));
}
offset += 2; /* Skip Last Write Date */
/* Build display for: Last Write Time */
LastWriteTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Time: %u", dissect_dos_time(LastWriteTime));
}
offset += 2; /* Skip Last Write Time */
/* Build display for: File Data Size */
FileDataSize = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "File Data Size: %u", FileDataSize);
}
offset += 4; /* Skip File Data Size */
/* Build display for: File Allocation Size */
FileAllocationSize = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "File Allocation Size: %u", FileAllocationSize);
}
offset += 4; /* Skip File Allocation Size */
/* Build display for: Attributes */
Attributes = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Attributes: 0x%02x", Attributes);
Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
}
offset += 2; /* Skip Attributes */
}
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
}
}
void
dissect_treecon_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)
{
guint8 WordCount;
guint8 BufferFormat3;
guint8 BufferFormat2;
guint8 BufferFormat1;
guint16 TID;
guint16 MaxBufferSize;
guint16 ByteCount;
const char *SharePath;
const char *Service;
const char *Password;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: BufferFormat1 */
BufferFormat1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "BufferFormat1: %u", BufferFormat1);
}
offset += 1; /* Skip BufferFormat1 */
/* Build display for: Share Path */
SharePath = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(SharePath) + 1, "Share Path: %s", SharePath);
}
offset += strlen(SharePath) + 1; /* Skip Share Path */
/* Build display for: BufferFormat2 */
BufferFormat2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "BufferFormat2: %u", BufferFormat2);
}
offset += 1; /* Skip BufferFormat2 */
/* Build display for: Password */
Password = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(Password), "Password: %s", Password);
}
offset += strlen(Password); /* Skip Password */
/* Build display for: BufferFormat3 */
BufferFormat3 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "BufferFormat3: %u", BufferFormat3);
}
offset += 1; /* Skip BufferFormat3 */
/* Build display for: Service */
Service = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(Service) + 1, "Service: %s", Service);
proto_tree_add_text(tree, offset, strlen(Service) + 1, "Service Description: %s",lookup_service_description(Service));
}
offset += strlen(Service) + 1; /* Skip Service */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
if (errcode != 0) return;
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Max Buffer Size */
MaxBufferSize = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Buffer Size: %u", MaxBufferSize);
}
offset += 2; /* Skip Max Buffer Size */
/* Build display for: TID */
TID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "TID: %u", TID);
}
offset += 2; /* Skip TID */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
/* Generated by build-dissect.pl Vesion 0.6 27-Jun-1999, ACT */
void
dissect_ssetup_andx_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)
{
proto_tree *Capabilities_tree;
proto_item *ti;
guint8 WordCount;
guint8 AndXReserved;
guint8 AndXCommand = 0xFF;
guint8 Pad1;
guint32 SessionKey;
guint32 Reserved;
guint32 Capabilities;
guint16 VcNumber;
guint16 UNICODEAccountPasswordLength;
guint16 PasswordLen;
guint16 MaxMpxCount;
guint16 MaxBufferSize;
guint16 ByteCount;
guint16 AndXOffset = 0;
guint16 Action;
guint16 ANSIAccountPasswordLength;
const char *UNICODEPassword;
const char *Password;
const char *PrimaryDomain;
const char *NativeOS;
const char *NativeLanManType;
const char *NativeLanMan;
const char *AccountName;
const char *ANSIPassword;
guint16 Flags2;
char *passstr;
char *ustr;
int ustr_len;
/* obtain the Flags2 settings */
Flags2 = GSHORT(pd, Flags2_Offset);
if (dirn == 1) { /* Request(s) dissect code */
WordCount = GBYTE(pd, offset);
switch (WordCount) {
case 10:
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %s",
(AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: MaxBufferSize */
MaxBufferSize = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
}
offset += 2; /* Skip MaxBufferSize */
/* Build display for: MaxMpxCount */
MaxMpxCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
}
offset += 2; /* Skip MaxMpxCount */
/* Build display for: VcNumber */
VcNumber = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "VcNumber: %u", VcNumber);
}
offset += 2; /* Skip VcNumber */
/* Build display for: SessionKey */
SessionKey = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "SessionKey: %u", SessionKey);
}
offset += 4; /* Skip SessionKey */
/* Build display for: PasswordLen */
PasswordLen = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "PasswordLen: %u", PasswordLen);
}
offset += 2; /* Skip PasswordLen */
/* Build display for: Reserved */
Reserved = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Reserved: %u", Reserved);
}
offset += 4; /* Skip Reserved */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
if (ByteCount > 0) {
/* Build displat for: Password */
Password = pd + offset;
if (tree) {
passstr=g_malloc(PasswordLen+1);
strncpy(passstr, Password, PasswordLen);
passstr[PasswordLen+1]='\0';
proto_tree_add_text(tree, offset, PasswordLen, "Password: %s", passstr);
g_free(passstr);
}
offset += PasswordLen;
/* Build display for: AccountName */
AccountName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(AccountName) + 1, "AccountName: %s", AccountName);
}
offset += strlen(AccountName) + 1; /* Skip AccountName */
/* Build display for: PrimaryDomain */
PrimaryDomain = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "PrimaryDomain: %s", PrimaryDomain);
}
offset += strlen(PrimaryDomain) + 1; /* Skip PrimaryDomain */
/* Build display for: NativeOS */
NativeOS = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
}
offset += strlen(NativeOS) + 1; /* Skip NativeOS */
/* Build display for: NativeLanMan */
NativeLanMan = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(NativeLanMan) + 1, "Native Lan Manager: %s", NativeLanMan);
}
offset += strlen(NativeLanMan) + 1; /* Skip NativeLanMan */
}
break;
case 13:
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %s",
(AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: MaxBufferSize */
MaxBufferSize = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
}
offset += 2; /* Skip MaxBufferSize */
/* Build display for: MaxMpxCount */
MaxMpxCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
}
offset += 2; /* Skip MaxMpxCount */
/* Build display for: VcNumber */
VcNumber = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "VcNumber: %u", VcNumber);
}
offset += 2; /* Skip VcNumber */
/* Build display for: SessionKey */
SessionKey = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "SessionKey: %u", SessionKey);
}
offset += 4; /* Skip SessionKey */
/* Build display for: ANSI Account Password Length */
ANSIAccountPasswordLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "ANSI Account Password Length: %u", ANSIAccountPasswordLength);
}
offset += 2; /* Skip ANSI Account Password Length */
/* Build display for: UNICODE Account Password Length */
UNICODEAccountPasswordLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "UNICODE Account Password Length: %u", UNICODEAccountPasswordLength);
}
offset += 2; /* Skip UNICODE Account Password Length */
/* Build display for: Reserved */
Reserved = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Reserved: %u", Reserved);
}
offset += 4; /* Skip Reserved */
/* Build display for: Capabilities */
Capabilities = GWORD(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 4, "Capabilities: 0x%04x", Capabilities);
Capabilities_tree = proto_item_add_subtree(ti, ett_smb_capabilities);
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0001, 32, " Raw Mode supported", " Raw Mode not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0002, 32, " Raw Mode supported", " MPX Mode not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0004, 32," Unicode supported", " Unicode not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0008, 32, " Large Files supported", " Large Files not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0010, 32, " NT LM 0.12 SMBs supported", " NT LM 0.12 SMBs not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0020, 32, " RPC Remote APIs supported", " RPC Remote APIs not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0040, 32, " NT Status Codes supported", " NT Status Codes not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0080, 32, " Level 2 OpLocks supported", " Level 2 OpLocks not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0100, 32, " Lock&Read supported", " Lock&Read not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x0200, 32, " NT Find supported", " NT Find not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x1000, 32, " DFS supported", " DFS not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x4000, 32, " Large READX supported", " Large READX not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x8000, 32, " Large WRITEX supported", " Large WRITEX not supported"));
proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
decode_boolean_bitfield(Capabilities, 0x80000000, 32, " Extended Security Exchanges supported", " Extended Security Exchanges not supported"));
}
offset += 4; /* Skip Capabilities */
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
if (ByteCount > 0) {
/* Build display for: ANSI Password */
ANSIPassword = pd + offset;
if (tree) {
passstr=g_malloc(ANSIAccountPasswordLength+1);
strncpy(passstr, ANSIPassword, ANSIAccountPasswordLength);
passstr[ANSIAccountPasswordLength+1]='\0';
proto_tree_add_text(tree, offset, ANSIAccountPasswordLength, "ANSI Password: %s", passstr);
g_free(passstr);
}
offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
if (ANSIAccountPasswordLength == 0) offset++; /* Add 1 */
/* Build display for: UNICODE Password */
UNICODEPassword = pd + offset;
if (UNICODEAccountPasswordLength > 0) {
if (tree) {
passstr=g_malloc(UNICODEAccountPasswordLength+1);
strncpy(passstr, UNICODEPassword, UNICODEAccountPasswordLength);
passstr[UNICODEAccountPasswordLength+1]='\0';
proto_tree_add_text(tree, offset, UNICODEAccountPasswordLength, "UNICODE Password: %s", passstr);
g_free(passstr);
}
offset += UNICODEAccountPasswordLength; /* Skip UNICODE Password */
}
if (Capabilities & 0x0004) {
if (offset % 2) {
/* Build display for: Pad1 */
/* Need to pad out because of Unicode strings start on a
even boundary */
Pad1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad1: %u", Pad1);
}
offset += 1;
}
}
/* Build display for: Account Name */
/* The AccountName, a null terminated string; Unicode if "caps" has
the 0x0004 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
AccountName = pd + offset;
if (tree) {
if (Capabilities & 0x0004) {
ustr = unicode_to_str(AccountName, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Account Name: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Account Name */
} else {
proto_tree_add_text(tree, offset, strlen(AccountName) + 1, "Account Name: %s", AccountName);
offset += strlen(AccountName) + 1; /* Skip Account Name */
}
}
/* Build display for: Primary Domain */
/* The Primary Domain, a null terminated string; Unicode if "caps" has
the 0x0004 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
PrimaryDomain = pd + offset;
if (tree) {
if (Capabilities & 0x0004) {
ustr = unicode_to_str(PrimaryDomain, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Primary Domain: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Primary Domain */
} else {
proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "Primary Domain: %s", PrimaryDomain);
offset += strlen(PrimaryDomain) + 1; /* Skip Primary Domain */
}
}
/* Build display for: Native OS */
/* The NativeOS, a null terminated string; Unicode if "caps" has
the 0x0004 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
NativeOS = pd + offset;
if (tree) {
if (Capabilities & 0x0004) {
ustr = unicode_to_str(NativeOS, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Native OS: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Native OS */
offset += 2; /* Skip EXTRA bytes */
} else {
proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
offset += strlen(NativeOS) + 1; /* Skip Native OS */
}
}
/* Build display for: Native LanMan Type */
/* The NativeLanManType, a null terminated string; Unicode if "caps" has
the 0x0004 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
NativeLanManType = pd + offset;
if (tree) {
if (Capabilities & 0x0004) {
ustr = unicode_to_str(NativeLanManType, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Native LanMan Type: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Native LanMan Type */
offset += 2; /* Skip EXTRA bytes */
} else {
proto_tree_add_text(tree, offset, strlen(NativeLanManType) + 1, "Native LanMan Type: %s", NativeLanManType);
offset += strlen(NativeLanManType) + 1; /* Skip Native LanMan Type */
}
}
}
break;
}
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %s",
(AndXCommand == 0xFF ? "No futher commands" : decode_smb_name(AndXCommand)));
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: Action */
Action = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Action: %u", Action);
}
offset += 2; /* Skip Action */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
if (errcode != 0 && WordCount == 0xFF) return; /* No more here ... */
offset += 2; /* Skip Byte Count (BCC) */
if (ByteCount > 0) {
/* Build display for: Native OS */
/* The NativeOS, a null terminated string; Unicode if "Flags" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
if (Flags2 & 0x8000) {
offset += 1; /* Skip EXTRA Byte for unicode only */
}
NativeOS = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(NativeOS, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Native OS: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Native OS */
} else {
proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
offset += strlen(NativeOS) + 1; /* Skip Native OS */
}
}
/* Build display for: NativeLanMan */
/* The NativeLanManType, a null terminated string; Unicode if "Flags" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
NativeLanManType = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(NativeLanManType, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "NativeLanManType: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Native LanMan Type */
} else {
proto_tree_add_text(tree, offset, strlen(NativeLanManType) + 1, "Native LanMan Type: %s", NativeLanManType);
offset += strlen(NativeLanManType) + 1; /* Skip Native LanMan Type */
}
}
/* Build display for: PrimaryDomain */
/* The Primary Domain, a null terminated string; Unicode if "caps" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
PrimaryDomain = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(PrimaryDomain, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Primary Domain: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Primary Domain */
} else {
proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "Primary Domain: %s", PrimaryDomain);
offset += strlen(PrimaryDomain) + 1; /* Skip Primary Domain */
}
}
}
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
}
void
dissect_tcon_andx_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)
{
guint8 wct, andxcmd = 0xFF;
guint16 andxoffs = 0, flags, passwdlen, bcc, optionsup;
const char *str;
proto_tree *flags_tree;
proto_item *ti;
char *passstr;
char *ustr;
int ustr_len;
guint32 Capabilities;
guint16 Flags2;
/* obtain the Flags2 settings */
Flags2 = GSHORT(pd, Flags2_Offset);
/* Obtain Capabilities flags */
Capabilities = GWORD(pd, Cap_Offset);
wct = pd[offset];
/* Now figure out what format we are talking about, 2, 3, or 4 response
* words ...
*/
if (!((dirn == 1) && (wct == 4)) && !((dirn == 0) && (wct == 2)) &&
!((dirn == 0) && (wct == 3)) && !(wct == 0)) {
if (tree) {
proto_tree_add_text(tree, offset, 1, "Invalid TCON_ANDX format. WCT should be 0, 2, 3, or 4 ..., not %u", wct);
proto_tree_add_text(tree, offset, END_OF_FRAME, "Data");
return;
}
}
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", wct);
}
offset += 1;
if (wct > 0) {
andxcmd = pd[offset];
if (tree) {
proto_tree_add_text(tree, offset, 1, "Next Command: %s",
(andxcmd == 0xFF) ? "No further commands":
decode_smb_name(andxcmd));
proto_tree_add_text(tree, offset + 1, 1, "Reserved (MBZ): %u", pd[offset+1]);
}
offset += 2;
andxoffs = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Offset to next command: %u", andxoffs);
}
offset += 2;
}
switch (wct) {
case 0:
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
}
break;
case 4:
flags = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Additional Flags: 0x%02x", flags);
flags_tree = proto_item_add_subtree(ti, ett_smb_aflags);
proto_tree_add_text(flags_tree, offset, 2, "%s",
decode_boolean_bitfield(flags, 0x01, 16,
"Disconnect TID",
"Don't disconnect TID"));
}
offset += 2;
passwdlen = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Password Length: %u", passwdlen);
}
offset += 2;
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
}
offset += 2;
str = pd + offset;
if (tree) {
passstr=g_malloc(passwdlen+1);
strncpy(passstr, str, passwdlen);
passstr[passwdlen+1]='\0';
proto_tree_add_text(tree, offset, passwdlen, "Password: %s", passstr);
g_free(passstr);
}
offset += passwdlen;
/* Build display for: Path */
/* The Path, a null terminated string; Unicode if "caps" has
the 0x0004 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
str = pd + offset;
if (tree) {
if (Capabilities & 0x0004) {
ustr = unicode_to_str(str, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Path: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Path OS */
} else {
proto_tree_add_text(tree, offset, strlen(str) + 1, "Path: %s", str);
offset += strlen(str) + 1; /* Skip Path */
}
}
/* Build display for: Service */
str = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service: %s", str);
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Description: %s",lookup_service_description(str));
}
offset += strlen(str) + 1; /* Skip Service */
break;
case 2:
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
}
offset += 2;
str = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Type: %s",str);
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Description: %s",lookup_service_description(str));
}
offset += strlen(str) + 1;
break;
case 3:
optionsup = GSHORT(pd, offset);
if (tree) { /* Should break out the bits */
proto_tree_add_text(tree, offset, 2, "Optional Support: 0x%04x",
optionsup);
}
offset += 2;
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
}
offset += 2;
str = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service: %s", str);
proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Description: %s",lookup_service_description(str));
}
offset += strlen(str) + 1;
/* Build display for: Native File System */
/* The Native File System, a null terminated string; Unicode if "caps" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
str = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(str, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Native File System: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Native File System */
} else {
proto_tree_add_text(tree, offset, strlen(str) + 1, "Native File System: %s", str);
offset += strlen(str) + 1;
}
}
break;
default:
; /* nothing */
break;
}
if (andxcmd != 0xFF) /* Process that next command ... ??? */
(dissect[andxcmd])(pd, SMB_offset + andxoffs, fd, parent, tree, si, max_data - offset, SMB_offset, errcode, dirn);
}
void
dissect_negprot_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)
{
guint8 wct, enckeylen;
guint16 bcc, mode, rawmode, dialect;
guint32 caps;
proto_tree *dialects = NULL, *mode_tree, *caps_tree, *rawmode_tree;
proto_item *ti;
const char *str;
char *ustr;
int ustr_len;
wct = pd[offset]; /* Should be 0, 1 or 13 or 17, I think */
if (!((wct == 0) && (dirn == 1)) && !((wct == 1) && (dirn == 0)) &&
!((wct == 13) && (dirn == 0)) && !((wct == 17) && (dirn == 0))) {
if (tree) {
proto_tree_add_text(tree, offset, 1, "Invalid Negotiate Protocol format. WCT should be zero or 1 or 13 or 17 ..., not %u", wct);
proto_tree_add_text(tree, offset, END_OF_FRAME, "Data");
return;
}
}
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %d", wct);
}
if (dirn == 0 && errcode != 0) return; /* No more info ... */
offset += 1;
/* Now decode the various formats ... */
switch (wct) {
case 0: /* A request */
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
}
offset += 2;
if (tree) {
ti = proto_tree_add_text(tree, offset, END_OF_FRAME, "Dialects");
dialects = proto_item_add_subtree(ti, ett_smb_dialects);
}
while (IS_DATA_IN_FRAME(offset)) {
const char *str;
if (tree) {
proto_tree_add_text(dialects, offset, 1, "Dialect Marker: %d", pd[offset]);
}
offset += 1;
str = pd + offset;
if (tree) {
proto_tree_add_text(dialects, offset, strlen(str)+1, "Dialect: %s", str);
}
offset += strlen(str) + 1;
}
break;
case 1: /* PC NETWORK PROGRAM 1.0 */
dialect = GSHORT(pd, offset);
if (tree) { /* Hmmmm, what if none of the dialects is recognized */
if (dialect == 0xFFFF) { /* Server didn't like them dialects */
proto_tree_add_text(tree, offset, 2, "Supplied dialects not recognized");
}
else {
proto_tree_add_text(tree, offset, 2, "Dialect Index: %u, PC NETWORK PROTGRAM 1.0", dialect);
}
}
offset += 2;
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
}
break;
case 13: /* Greater than Core and up to and incl LANMAN2.1 */
if (tree) {
proto_tree_add_text(tree, offset, 2, "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", GSHORT(pd, offset));
}
/* Much of this is similar to response 17 below */
offset += 2;
mode = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Security Mode: 0x%04x", mode);
mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
proto_tree_add_text(mode_tree, offset, 2, "%s",
decode_boolean_bitfield(mode, 0x0001, 16,
"Security = User",
"Security = Share"));
proto_tree_add_text(mode_tree, offset, 2, "%s",
decode_boolean_bitfield(mode, 0x0002, 16,
"Passwords = Encrypted",
"Passwords = Plaintext"));
}
offset += 2;
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max buffer size: %u", GSHORT(pd, offset));
}
offset += 2;
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset));
}
offset += 2;
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max vcs: %u", GSHORT(pd, offset));
}
offset += 2;
rawmode = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Raw Mode: 0x%04x", rawmode);
rawmode_tree = proto_item_add_subtree(ti, ett_smb_rawmode);
proto_tree_add_text(rawmode_tree, offset, 2, "%s",
decode_boolean_bitfield(rawmode, 0x01, 16,
"Read Raw supported",
"Read Raw not supported"));
proto_tree_add_text(rawmode_tree, offset, 2, "%s",
decode_boolean_bitfield(rawmode, 0x02, 16,
"Write Raw supported",
"Write Raw not supported"));
}
offset += 2;
if (tree) {
proto_tree_add_text(tree, offset, 4, "Session key: %08x", GWORD(pd, offset));
}
offset += 4;
/* Now the server time, two short parameters ... */
if (tree) {
proto_tree_add_text(tree, offset, 2, "Server Time: %s",
dissect_dos_time(GSHORT(pd, offset)));
proto_tree_add_text(tree, offset + 2, 2, "Server Date: %s",
dissect_dos_date(GSHORT(pd, offset + 2)));
}
offset += 4;
/* Server Time Zone, SHORT */
if (tree) {
proto_tree_add_text(tree, offset, 2, "Server time zone: %i min from UTC",
(signed)GSSHORT(pd, offset));
}
offset += 2;
/* Challenge Length */
enckeylen = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Challenge Length: %u", enckeylen);
}
offset += 2;
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u (MBZ)", GSHORT(pd, offset));
}
offset += 2;
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
}
offset += 2;
if (enckeylen) { /* only if non-zero key len */
str = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, enckeylen, "Challenge: %s",
bytes_to_str(str, enckeylen));
}
offset += enckeylen;
}
/* Primary Domain ... */
str = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(str)+1, "Primary Domain: %s", str);
}
break;
case 17: /* Greater than LANMAN2.1 */
if (tree) {
proto_tree_add_text(tree, offset, 2, "Dialect Index: %u, Greater than LANMAN2.1", GSHORT(pd, offset));
}
offset += 2;
mode = GBYTE(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 1, "Security Mode: 0x%02x", mode);
mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
proto_tree_add_text(mode_tree, offset, 1, "%s",
decode_boolean_bitfield(mode, 0x01, 8,
"Security = User",
"Security = Share"));
proto_tree_add_text(mode_tree, offset, 1, "%s",
decode_boolean_bitfield(mode, 0x02, 8,
"Passwords = Encrypted",
"Passwords = Plaintext"));
proto_tree_add_text(mode_tree, offset, 1, "%s",
decode_boolean_bitfield(mode, 0x04, 8,
"Security signatures enabled",
"Security signatures not enabled"));
proto_tree_add_text(mode_tree, offset, 1, "%s",
decode_boolean_bitfield(mode, 0x08, 8,
"Security signatures required",
"Security signatures not required"));
}
offset += 1;
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset));
}
offset += 2;
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max vcs: %u", GSHORT(pd, offset));
}
offset += 2;
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max buffer size: %u", GWORD(pd, offset));
}
offset += 4;
if (tree) {
proto_tree_add_text(tree, offset, 4, "Max raw size: %u", GWORD(pd, offset));
}
offset += 4;
if (tree) {
proto_tree_add_text(tree, offset, 4, "Session key: %08x", GWORD(pd, offset));
}
offset += 4;
caps = GWORD(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 4, "Capabilities: 0x%04x", caps);
caps_tree = proto_item_add_subtree(ti, ett_smb_capabilities);
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0001, 32,
"Raw Mode supported",
"Raw Mode not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0002, 32,
"MPX Mode supported",
"MPX Mode not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0004, 32,
"Unicode supported",
"Unicode not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0008, 32,
"Large files supported",
"Large files not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0010, 32,
"NT LM 0.12 SMBs supported",
"NT LM 0.12 SMBs not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0020, 32,
"RPC remote APIs supported",
"RPC remote APIs not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0040, 32,
"NT status codes supported",
"NT status codes not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0080, 32,
"Level 2 OpLocks supported",
"Level 2 OpLocks not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0100, 32,
"Lock&Read supported",
"Lock&Read not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x0200, 32,
"NT Find supported",
"NT Find not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x1000, 32,
"DFS supported",
"DFS not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x4000, 32,
"Large READX supported",
"Large READX not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x8000, 32,
"Large WRITEX supported",
"Large WRITEX not supported"));
proto_tree_add_text(caps_tree, offset, 4, "%s",
decode_boolean_bitfield(caps, 0x80000000, 32,
"Extended security exchanges supported",
"Extended security exchanges not supported"));
}
offset += 4;
/* Server time, 2 WORDS */
if (tree) {
proto_tree_add_text(tree, offset, 4, "System Time Low: 0x%08x", GWORD(pd, offset));
proto_tree_add_text(tree, offset + 4, 4, "System Time High: 0x%08x", GWORD(pd, offset + 4));
}
offset += 8;
/* Server Time Zone, SHORT */
if (tree) {
proto_tree_add_text(tree, offset, 2, "Server time zone: %i min from UTC",
(signed)GSSHORT(pd, offset));
}
offset += 2;
/* Encryption key len */
enckeylen = pd[offset];
if (tree) {
proto_tree_add_text(tree, offset, 1, "Encryption key len: %u", enckeylen);
}
offset += 1;
bcc = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte count (BCC): %u", bcc);
}
offset += 2;
if (enckeylen) { /* only if non-zero key len */
/* Encryption challenge key */
str = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, enckeylen, "Challenge encryption key: %s",
bytes_to_str(str, enckeylen));
}
offset += enckeylen;
}
/* The domain, a null terminated string; Unicode if "caps" has
the 0x0004 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
str = pd + offset;
if (tree) {
if (caps & 0x0004) {
ustr = unicode_to_str(str, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "OEM domain name: %s", ustr);
} else {
proto_tree_add_text(tree, offset, strlen(str)+1, "OEM domain name: %s", str);
}
}
break;
default: /* Baddd */
if (tree)
proto_tree_add_text(tree, offset, 1, "Bad format, should never get here");
return;
}
}
void
dissect_deletedir_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint16 ByteCount;
const char *DirectoryName;
guint16 Flags2;
char *ustr;
int ustr_len;
/* obtain the Flags2 settings */
Flags2 = GSHORT(pd, Flags2_Offset);
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Directory Name */
/* The Directory Name, a null terminated string; Unicode if "Flags" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
DirectoryName = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(DirectoryName, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
} else {
proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
}
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_createdir_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint16 ByteCount;
const char *DirectoryName;
guint16 Flags2;
char *ustr;
int ustr_len;
/* obtain the Flags2 settings */
Flags2 = GSHORT(pd, Flags2_Offset);
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Directory Name */
/* The Directory Name, a null terminated string; Unicode if "Flags" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
DirectoryName = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(DirectoryName, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
} else {
proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
}
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_checkdir_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint16 ByteCount;
const char *DirectoryName;
guint16 Flags2;
char *ustr;
int ustr_len;
/* obtain the Flags2 settings */
Flags2 = GSHORT(pd, Flags2_Offset);
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Directory Name */
/* The Directory Name, a null terminated string; Unicode if "Flags" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
DirectoryName = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(DirectoryName, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
} else {
proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
}
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_open_andx_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)
{
static const value_string OpenFunction_0x10[] = {
{ 0, "Fail if file does not exist"},
{ 16, "Create file if it does not exist"},
{ 0, NULL}
};
static const value_string OpenFunction_0x03[] = {
{ 0, "Fail if file exists"},
{ 1, "Open file if it exists"},
{ 2, "Truncate File if it exists"},
{ 0, NULL}
};
static const value_string FileType_0xFFFF[] = {
{ 0, "Disk file or directory"},
{ 1, "Named pipe in byte mode"},
{ 2, "Named pipe in message mode"},
{ 3, "Spooled printer"},
{ 0, NULL}
};
static const value_string DesiredAccess_0x70[] = {
{ 00, "Compatibility mode"},
{ 16, "Deny read/write/execute (exclusive)"},
{ 32, "Deny write"},
{ 48, "Deny read/execute"},
{ 64, "Deny none"},
{ 0, NULL}
};
static const value_string DesiredAccess_0x700[] = {
{ 0, "Locality of reference unknown"},
{ 256, "Mainly sequential access"},
{ 512, "Mainly random access"},
{ 768, "Random access with some locality"},
{0, NULL}
};
static const value_string DesiredAccess_0x4000[] = {
{ 0, "Write through mode disabled"},
{ 16384, "Write through mode enabled"},
{0, NULL}
};
static const value_string DesiredAccess_0x1000[] = {
{ 0, "Normal file (caching permitted)"},
{ 4096, "Do not cache this file"},
{0, NULL}
};
static const value_string DesiredAccess_0x07[] = {
{ 0, "Open for reading"},
{ 1, "Open for writing"},
{ 2, "Open for reading and writing"},
{ 3, "Open for execute"},
{0, NULL}
};
static const value_string Action_0x8000[] = {
{ 0, "File opened by another user (or mode not supported by server)"},
{ 32768, "File is opened only by this user at present"},
{0, NULL}
};
static const value_string Action_0x0003[] = {
{ 0, "No action taken?"},
{ 1, "The file existed and was opened"},
{ 2, "The file did not exist but was created"},
{ 3, "The file existed and was truncated"},
{0, NULL}
};
proto_tree *Search_tree;
proto_tree *OpenFunction_tree;
proto_tree *Flags_tree;
proto_tree *File_tree;
proto_tree *FileType_tree;
proto_tree *FileAttributes_tree;
proto_tree *DesiredAccess_tree;
proto_tree *Action_tree;
proto_item *ti;
guint8 WordCount;
guint8 AndXReserved;
guint8 AndXCommand = 0xFF;
guint32 ServerFID;
guint32 Reserved2;
guint32 Reserved1;
guint32 DataSize;
guint32 AllocatedSize;
guint16 Search;
guint16 Reserved;
guint16 OpenFunction;
guint16 LastWriteTime;
guint16 LastWriteDate;
guint16 GrantedAccess;
guint16 Flags;
guint16 FileType;
guint16 FileAttributes;
guint16 File;
guint16 FID;
guint16 DeviceState;
guint16 DesiredAccess;
guint16 CreationTime;
guint16 CreationDate;
guint16 ByteCount;
guint16 AndXOffset = 0;
guint16 Action;
const char *FileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %s",
(AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: Flags */
Flags = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Flags: 0x%02x", Flags);
Flags_tree = proto_item_add_subtree(ti, ett_smb_flags);
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_boolean_bitfield(Flags, 0x01, 16, "Dont Return Additional Info", "Return Additional Info"));
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_boolean_bitfield(Flags, 0x02, 16, "Exclusive OpLock not Requested", "Exclusive OpLock Requested"));
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_boolean_bitfield(Flags, 0x04, 16, "Batch OpLock not Requested", "Batch OpLock Requested"));
}
offset += 2; /* Skip Flags */
/* Build display for: Desired Access */
DesiredAccess = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Desired Access: 0x%02x", DesiredAccess);
DesiredAccess_tree = proto_item_add_subtree(ti, ett_smb_desiredaccess);
proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
decode_enumerated_bitfield(DesiredAccess, 0x07, 16, DesiredAccess_0x07, "%s"));
proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
decode_enumerated_bitfield(DesiredAccess, 0x70, 16, DesiredAccess_0x70, "%s"));
proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
decode_enumerated_bitfield(DesiredAccess, 0x700, 16, DesiredAccess_0x700, "%s"));
proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
decode_enumerated_bitfield(DesiredAccess, 0x1000, 16, DesiredAccess_0x1000, "%s"));
proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
decode_enumerated_bitfield(DesiredAccess, 0x4000, 16, DesiredAccess_0x4000, "%s"));
}
offset += 2; /* Skip Desired Access */
/* Build display for: Search */
Search = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Search: 0x%02x", Search);
Search_tree = proto_item_add_subtree(ti, ett_smb_search);
proto_tree_add_text(Search_tree, offset, 2, "%s",
decode_boolean_bitfield(Search, 0x01, 16, "Read only file", "Not a read only file"));
proto_tree_add_text(Search_tree, offset, 2, "%s",
decode_boolean_bitfield(Search, 0x02, 16, "Hidden file", "Not a hidden file"));
proto_tree_add_text(Search_tree, offset, 2, "%s",
decode_boolean_bitfield(Search, 0x04, 16, "System file", "Not a system file"));
proto_tree_add_text(Search_tree, offset, 2, "%s",
decode_boolean_bitfield(Search, 0x08, 16, " Volume", "Not a volume"));
proto_tree_add_text(Search_tree, offset, 2, "%s",
decode_boolean_bitfield(Search, 0x10, 16, " Directory", "Not a directory"));
proto_tree_add_text(Search_tree, offset, 2, "%s",
decode_boolean_bitfield(Search, 0x20, 16, "Archive file", "Do not archive file"));
}
offset += 2; /* Skip Search */
/* Build display for: File */
File = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "File: 0x%02x", File);
File_tree = proto_item_add_subtree(ti, ett_smb_file);
proto_tree_add_text(File_tree, offset, 2, "%s",
decode_boolean_bitfield(File, 0x01, 16, "Read only file", "Not a read only file"));
proto_tree_add_text(File_tree, offset, 2, "%s",
decode_boolean_bitfield(File, 0x02, 16, "Hidden file", "Not a hidden file"));
proto_tree_add_text(File_tree, offset, 2, "%s",
decode_boolean_bitfield(File, 0x04, 16, "System file", "Not a system file"));
proto_tree_add_text(File_tree, offset, 2, "%s",
decode_boolean_bitfield(File, 0x08, 16, " Volume", "Not a volume"));
proto_tree_add_text(File_tree, offset, 2, "%s",
decode_boolean_bitfield(File, 0x10, 16, " Directory", "Not a directory"));
proto_tree_add_text(File_tree, offset, 2, "%s",
decode_boolean_bitfield(File, 0x20, 16, "Archive file", "Do not archive file"));
}
offset += 2; /* Skip File */
/* Build display for: Creation Time */
CreationTime = GSHORT(pd, offset);
if (tree) {
}
offset += 2; /* Skip Creation Time */
/* Build display for: Creation Date */
CreationDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Date: %s", dissect_smbu_date(CreationDate, CreationTime));
proto_tree_add_text(tree, offset, 2, "Creation Time: %s", dissect_smbu_time(CreationDate, CreationTime));
}
offset += 2; /* Skip Creation Date */
/* Build display for: Open Function */
OpenFunction = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Open Function: 0x%02x", OpenFunction);
OpenFunction_tree = proto_item_add_subtree(ti, ett_smb_openfunction);
proto_tree_add_text(OpenFunction_tree, offset, 2, "%s",
decode_enumerated_bitfield(OpenFunction, 0x10, 16, OpenFunction_0x10, "%s"));
proto_tree_add_text(OpenFunction_tree, offset, 2, "%s",
decode_enumerated_bitfield(OpenFunction, 0x03, 16, OpenFunction_0x03, "%s"));
}
offset += 2; /* Skip Open Function */
/* Build display for: Allocated Size */
AllocatedSize = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Allocated Size: %u", AllocatedSize);
}
offset += 4; /* Skip Allocated Size */
/* Build display for: Reserved1 */
Reserved1 = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Reserved1: %u", Reserved1);
}
offset += 4; /* Skip Reserved1 */
/* Build display for: Reserved2 */
Reserved2 = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Reserved2: %u", Reserved2);
}
offset += 4; /* Skip Reserved2 */
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
/* Build display for: File Name */
FileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
}
offset += strlen(FileName) + 1; /* Skip File Name */
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %s",
(AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: FileAttributes */
FileAttributes = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "FileAttributes: 0x%02x", FileAttributes);
FileAttributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
decode_boolean_bitfield(FileAttributes, 0x01, 16, "Read only file", "Not a read only file"));
proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
decode_boolean_bitfield(FileAttributes, 0x02, 16, "Hidden file", "Not a hidden file"));
proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
decode_boolean_bitfield(FileAttributes, 0x04, 16, "System file", "Not a system file"));
proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
decode_boolean_bitfield(FileAttributes, 0x08, 16, " Volume", "Not a volume"));
proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
decode_boolean_bitfield(FileAttributes, 0x10, 16, " Directory", "Not a directory"));
proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
decode_boolean_bitfield(FileAttributes, 0x20, 16, "Archive file", "Do not archive file"));
}
offset += 2; /* Skip FileAttributes */
/* Build display for: Last Write Time */
LastWriteTime = GSHORT(pd, offset);
if (tree) {
}
offset += 2; /* Skip Last Write Time */
/* Build display for: Last Write Date */
LastWriteDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Date: %s", dissect_smbu_date(LastWriteDate, LastWriteTime));
proto_tree_add_text(tree, offset, 2, "Last Write Time: %s", dissect_smbu_time(LastWriteDate, LastWriteTime));
}
offset += 2; /* Skip Last Write Date */
/* Build display for: Data Size */
DataSize = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Data Size: %u", DataSize);
}
offset += 4; /* Skip Data Size */
/* Build display for: Granted Access */
GrantedAccess = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Granted Access: %u", GrantedAccess);
}
offset += 2; /* Skip Granted Access */
/* Build display for: File Type */
FileType = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "File Type: 0x%02x", FileType);
FileType_tree = proto_item_add_subtree(ti, ett_smb_filetype);
proto_tree_add_text(FileType_tree, offset, 2, "%s",
decode_enumerated_bitfield(FileType, 0xFFFF, 16, FileType_0xFFFF, "%s"));
}
offset += 2; /* Skip File Type */
/* Build display for: Device State */
DeviceState = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Device State: %u", DeviceState);
}
offset += 2; /* Skip Device State */
/* Build display for: Action */
Action = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Action: 0x%02x", Action);
Action_tree = proto_item_add_subtree(ti, ett_smb_action);
proto_tree_add_text(Action_tree, offset, 2, "%s",
decode_enumerated_bitfield(Action, 0x8000, 16, Action_0x8000, "%s"));
proto_tree_add_text(Action_tree, offset, 2, "%s",
decode_enumerated_bitfield(Action, 0x0003, 16, Action_0x0003, "%s"));
}
offset += 2; /* Skip Action */
/* Build display for: Server FID */
ServerFID = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Server FID: %u", ServerFID);
}
offset += 4; /* Skip Server FID */
/* Build display for: Reserved */
Reserved = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
}
offset += 2; /* Skip Reserved */
}
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
}
void
dissect_write_raw_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)
{
proto_tree *WriteMode_tree;
proto_item *ti;
guint8 WordCount;
guint8 Pad;
guint32 Timeout;
guint32 Reserved2;
guint32 Offset;
guint16 WriteMode;
guint16 Reserved1;
guint16 Remaining;
guint16 FID;
guint16 DataOffset;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
WordCount = GBYTE(pd, offset);
switch (WordCount) {
case 12:
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Reserved 1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 1: %u", Reserved1);
}
offset += 2; /* Skip Reserved 1 */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: WriteMode */
WriteMode = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "WriteMode: 0x%02x", WriteMode);
WriteMode_tree = proto_item_add_subtree(ti, ett_smb_writemode);
proto_tree_add_text(WriteMode_tree, offset, 2, "%s",
decode_boolean_bitfield(WriteMode, 0x01, 16, "Write through requested", "Write through not requested"));
proto_tree_add_text(WriteMode_tree, offset, 2, "%s",
decode_boolean_bitfield(WriteMode, 0x02, 16, "Return Remaining (pipe/dev)", "Dont return Remaining (pipe/dev)"));
}
offset += 2; /* Skip WriteMode */
/* Build display for: Reserved 2 */
Reserved2 = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Reserved 2: %u", Reserved2);
}
offset += 4; /* Skip Reserved 2 */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Pad */
Pad = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad: %u", Pad);
}
offset += 1; /* Skip Pad */
break;
case 14:
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Reserved 1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 1: %u", Reserved1);
}
offset += 2; /* Skip Reserved 1 */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: WriteMode */
WriteMode = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "WriteMode: 0x%02x", WriteMode);
WriteMode_tree = proto_item_add_subtree(ti, ett_smb_writemode);
proto_tree_add_text(WriteMode_tree, offset, 2, "%s",
decode_boolean_bitfield(WriteMode, 0x01, 16, "Write through requested", "Write through not requested"));
proto_tree_add_text(WriteMode_tree, offset, 2, "%s",
decode_boolean_bitfield(WriteMode, 0x02, 16, "Return Remaining (pipe/dev)", "Dont return Remaining (pipe/dev)"));
}
offset += 2; /* Skip WriteMode */
/* Build display for: Reserved 2 */
Reserved2 = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Reserved 2: %u", Reserved2);
}
offset += 4; /* Skip Reserved 2 */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Pad */
Pad = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad: %u", Pad);
}
offset += 1; /* Skip Pad */
break;
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Remaining */
Remaining = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Remaining: %u", Remaining);
}
offset += 2; /* Skip Remaining */
}
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
}
}
void
dissect_tdis_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)
{
guint8 WordCount;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_move_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)
{
static const value_string Flags_0x03[] = {
{ 0, "Target must be a file"},
{ 1, "Target must be a directory"},
{ 2, "Reserved"},
{ 3, "Reserved"},
{ 4, "Verify all writes"},
{ 0, NULL}
};
proto_tree *Flags_tree;
proto_item *ti;
guint8 WordCount;
guint8 ErrorFileFormat;
guint16 TID2;
guint16 OpenFunction;
guint16 Flags;
guint16 Count;
guint16 ByteCount;
const char *ErrorFileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: TID2 */
TID2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "TID2: %u", TID2);
}
offset += 2; /* Skip TID2 */
/* Build display for: Open Function */
OpenFunction = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Open Function: %u", OpenFunction);
}
offset += 2; /* Skip Open Function */
/* Build display for: Flags */
Flags = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Flags: 0x%02x", Flags);
Flags_tree = proto_item_add_subtree(ti, ett_smb_flags);
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_enumerated_bitfield(Flags, 0x03, 16, Flags_0x03, "%s"));
}
offset += 2; /* Skip Flags */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
}
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
/* Build display for: Error File Format */
ErrorFileFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Error File Format: %u", ErrorFileFormat);
}
offset += 1; /* Skip Error File Format */
/* Build display for: Error File Name */
ErrorFileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(ErrorFileName) + 1, "Error File Name: %s", ErrorFileName);
}
offset += strlen(ErrorFileName) + 1; /* Skip Error File Name */
}
}
void
dissect_rename_file_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)
{
guint8 WordCount;
guint8 BufferFormat2;
guint8 BufferFormat1;
guint16 SearchAttributes;
guint16 ByteCount;
const char *OldFileName;
const char *NewFileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Search Attributes */
SearchAttributes = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Search Attributes: %u", SearchAttributes);
}
offset += 2; /* Skip Search Attributes */
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
/* Build display for: Buffer Format 1 */
BufferFormat1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format 1: %u", BufferFormat1);
}
offset += 1; /* Skip Buffer Format 1 */
/* Build display for: Old File Name */
OldFileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(OldFileName) + 1, "Old File Name: %s", OldFileName);
}
offset += strlen(OldFileName) + 1; /* Skip Old File Name */
/* Build display for: Buffer Format 2 */
BufferFormat2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format 2: %u", BufferFormat2);
}
offset += 1; /* Skip Buffer Format 2 */
/* Build display for: New File Name */
NewFileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(NewFileName) + 1, "New File Name: %s", NewFileName);
}
offset += strlen(NewFileName) + 1; /* Skip New File Name */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_open_print_file_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)
{
static const value_string Mode_0x03[] = {
{ 0, "Text mode (DOS expands TABs)"},
{ 1, "Graphics mode"},
{ 0, NULL}
};
proto_tree *Mode_tree;
proto_item *ti;
guint8 WordCount;
guint8 BufferFormat;
guint16 SetupLength;
guint16 Mode;
guint16 FID;
guint16 ByteCount;
const char *IdentifierString;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Setup Length */
SetupLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Setup Length: %u", SetupLength);
}
offset += 2; /* Skip Setup Length */
/* Build display for: Mode */
Mode = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Mode: 0x%02x", Mode);
Mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
proto_tree_add_text(Mode_tree, offset, 2, "%s",
decode_enumerated_bitfield(Mode, 0x03, 16, Mode_0x03, "%s"));
}
offset += 2; /* Skip Mode */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Identifier String */
IdentifierString = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(IdentifierString) + 1, "Identifier String: %s", IdentifierString);
}
offset += strlen(IdentifierString) + 1; /* Skip Identifier String */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_close_print_file_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)
{
guint8 WordCount;
guint16 FID;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count: %u", WordCount);
}
offset += 1; /* Skip Word Count */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_read_raw_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)
{
guint8 WordCount;
guint32 Timeout;
guint32 OffsetHigh;
guint32 Offset;
guint16 Reserved;
guint16 MinCount;
guint16 MaxCount;
guint16 FID;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
WordCount = GBYTE(pd, offset);
switch (WordCount) {
case 8:
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Max Count */
MaxCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Count: %u", MaxCount);
}
offset += 2; /* Skip Max Count */
/* Build display for: Min Count */
MinCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Min Count: %u", MinCount);
}
offset += 2; /* Skip Min Count */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: Reserved */
Reserved = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
}
offset += 2; /* Skip Reserved */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
break;
case 10:
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Max Count */
MaxCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Count: %u", MaxCount);
}
offset += 2; /* Skip Max Count */
/* Build display for: Min Count */
MinCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Min Count: %u", MinCount);
}
offset += 2; /* Skip Min Count */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: Reserved */
Reserved = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
}
offset += 2; /* Skip Reserved */
/* Build display for: Offset High */
OffsetHigh = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset High: %u", OffsetHigh);
}
offset += 4; /* Skip Offset High */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
break;
}
}
if (dirn == 0) { /* Response(s) dissect code */
}
}
void
dissect_logoff_andx_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)
{
guint8 WordCount;
guint8 AndXReserved;
guint8 AndXCommand = 0xFF;
guint16 ByteCount;
guint16 AndXOffset = 0;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
}
void
dissect_seek_file_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)
{
static const value_string Mode_0x03[] = {
{ 0, "Seek from start of file"},
{ 1, "Seek from current position"},
{ 2, "Seek from end of file"},
{ 0, NULL}
};
proto_tree *Mode_tree;
proto_item *ti;
guint8 WordCount;
guint32 Offset;
guint16 Mode;
guint16 FID;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Mode */
Mode = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Mode: 0x%02x", Mode);
Mode_tree = proto_item_add_subtree(ti, ett_smb_mode);
proto_tree_add_text(Mode_tree, offset, 2, "%s",
decode_enumerated_bitfield(Mode, 0x03, 16, Mode_0x03, "%s"));
}
offset += 2; /* Skip Mode */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_write_and_unlock_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint32 Offset;
guint16 Remaining;
guint16 FID;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Remaining */
Remaining = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Remaining: %u", Remaining);
}
offset += 2; /* Skip Remaining */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_set_info2_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)
{
guint8 WordCount;
guint16 LastWriteTime;
guint16 LastWriteDate;
guint16 LastAccessTime;
guint16 LastAccessDate;
guint16 FID;
guint16 CreationTime;
guint16 CreationDate;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count: %u", WordCount);
}
offset += 1; /* Skip Word Count */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Creation Date */
CreationDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Date: %u", dissect_dos_date(CreationDate));
}
offset += 2; /* Skip Creation Date */
/* Build display for: Creation Time */
CreationTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Time: %u", dissect_dos_time(CreationTime));
}
offset += 2; /* Skip Creation Time */
/* Build display for: Last Access Date */
LastAccessDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Access Date: %u", dissect_dos_date(LastAccessDate));
}
offset += 2; /* Skip Last Access Date */
/* Build display for: Last Access Time */
LastAccessTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Access Time: %u", dissect_dos_time(LastAccessTime));
}
offset += 2; /* Skip Last Access Time */
/* Build display for: Last Write Date */
LastWriteDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Date: %u", dissect_dos_date(LastWriteDate));
}
offset += 2; /* Skip Last Write Date */
/* Build display for: Last Write Time */
LastWriteTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Time: %u", dissect_dos_time(LastWriteTime));
}
offset += 2; /* Skip Last Write Time */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCC) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCC): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCC) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_lock_bytes_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)
{
guint8 WordCount;
guint32 Offset;
guint32 Count;
guint16 FID;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Count: %u", Count);
}
offset += 4; /* Skip Count */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_get_print_queue_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint16 StartIndex;
guint16 RestartIndex;
guint16 MaxCount;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count: %u", WordCount);
}
offset += 1; /* Skip Word Count */
/* Build display for: Max Count */
MaxCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Count: %u", MaxCount);
}
offset += 2; /* Skip Max Count */
/* Build display for: Start Index */
StartIndex = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Start Index: %u", StartIndex);
}
offset += 2; /* Skip Start Index */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Restart Index */
RestartIndex = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Restart Index: %u", RestartIndex);
}
offset += 2; /* Skip Restart Index */
/* Build display for: Byte Count (BCC) */
}
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
}
}
void
dissect_locking_andx_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)
{
proto_tree *LockType_tree;
proto_item *ti;
guint8 LockType;
guint8 WordCount;
guint8 OplockLevel;
guint8 AndXReserved;
guint8 AndXCommand = 0xFF;
guint32 Timeout;
guint16 NumberofLocks;
guint16 NumberOfUnlocks;
guint16 FID;
guint16 ByteCount;
guint16 AndXoffset;
guint16 AndXOffset = 0;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXOffset */
AndXOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
}
offset += 2; /* Skip AndXOffset */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Lock Type */
LockType = GBYTE(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 1, "Lock Type: 0x%01x", LockType);
LockType_tree = proto_item_add_subtree(ti, ett_smb_lock_type);
proto_tree_add_text(LockType_tree, offset, 1, "%s",
decode_boolean_bitfield(LockType, 0x01, 16, "Read-only lock", "Not a Read-only lock"));
proto_tree_add_text(LockType_tree, offset, 1, "%s",
decode_boolean_bitfield(LockType, 0x02, 16, "Oplock break notification", "Not an Oplock break notification"));
proto_tree_add_text(LockType_tree, offset, 1, "%s",
decode_boolean_bitfield(LockType, 0x04, 16, "Change lock type", "Not a lock type change"));
proto_tree_add_text(LockType_tree, offset, 1, "%s",
decode_boolean_bitfield(LockType, 0x08, 16, "Cancel outstanding request", "Dont cancel outstanding request"));
proto_tree_add_text(LockType_tree, offset, 1, "%s",
decode_boolean_bitfield(LockType, 0x10, 16, "Large file locking format", "Not a large file locking format"));
}
offset += 1; /* Skip Lock Type */
/* Build display for: OplockLevel */
OplockLevel = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "OplockLevel: %u", OplockLevel);
}
offset += 1; /* Skip OplockLevel */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: Number Of Unlocks */
NumberOfUnlocks = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Number Of Unlocks: %u", NumberOfUnlocks);
}
offset += 2; /* Skip Number Of Unlocks */
/* Build display for: Number of Locks */
NumberofLocks = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Number of Locks: %u", NumberofLocks);
}
offset += 2; /* Skip Number of Locks */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: AndXCommand */
AndXCommand = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXCommand: %s",
(AndXCommand == 0xFF ? "No further commands" : decode_smb_name(AndXCommand)));
}
offset += 1; /* Skip AndXCommand */
/* Build display for: AndXReserved */
AndXReserved = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
}
offset += 1; /* Skip AndXReserved */
/* Build display for: AndXoffset */
AndXoffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "AndXoffset: %u", AndXoffset);
}
offset += 2; /* Skip AndXoffset */
}
/* Build display for: Byte Count */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
}
offset += 2; /* Skip Byte Count */
if (AndXCommand != 0xFF) {
(dissect[AndXCommand])(pd, SMB_offset + AndXOffset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn);
}
}
}
void
dissect_unlock_bytes_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)
{
guint8 WordCount;
guint32 Offset;
guint32 Count;
guint16 FID;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Count: %u", Count);
}
offset += 4; /* Skip Count */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_create_file_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)
{
proto_tree *Attributes_tree;
proto_item *ti;
guint8 WordCount;
guint8 BufferFormat;
guint16 FID;
guint16 CreationTime;
guint16 ByteCount;
guint16 Attributes;
const char *FileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Attributes */
Attributes = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Attributes: 0x%02x", Attributes);
Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
}
offset += 2; /* Skip Attributes */
/* Build display for: Creation Time */
CreationTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Time: %u", dissect_dos_time(CreationTime));
}
offset += 2; /* Skip Creation Time */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: File Name */
FileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
}
offset += strlen(FileName) + 1; /* Skip File Name */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_search_dir_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)
{
guint8 WordCount;
guint8 BufferFormat2;
guint8 BufferFormat1;
guint8 BufferFormat;
guint16 SearchAttributes;
guint16 ResumeKeyLength;
guint16 MaxCount;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
const char *FileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Max Count */
MaxCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Count: %u", MaxCount);
}
offset += 2; /* Skip Max Count */
/* Build display for: Search Attributes */
SearchAttributes = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Search Attributes: %u", SearchAttributes);
}
offset += 2; /* Skip Search Attributes */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format 1 */
BufferFormat1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format 1: %u", BufferFormat1);
}
offset += 1; /* Skip Buffer Format 1 */
/* Build display for: File Name */
FileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
}
offset += strlen(FileName) + 1; /* Skip File Name */
/* Build display for: Buffer Format 2 */
BufferFormat2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format 2: %u", BufferFormat2);
}
offset += 1; /* Skip Buffer Format 2 */
/* Build display for: Resume Key Length */
ResumeKeyLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Resume Key Length: %u", ResumeKeyLength);
}
offset += 2; /* Skip Resume Key Length */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
}
}
void
dissect_create_temporary_file_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint16 Reserved;
guint16 FID;
guint16 CreationTime;
guint16 CreationDate;
guint16 ByteCount;
const char *FileName;
const char *DirectoryName;
guint16 Flags2;
char *ustr;
int ustr_len;
/* obtain the Flags2 settings */
Flags2 = GSHORT(pd, Flags2_Offset);
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Reserved */
Reserved = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
}
offset += 2; /* Skip Reserved */
/* Build display for: Creation Time */
CreationTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Time: %u", dissect_dos_time(CreationTime));
}
offset += 2; /* Skip Creation Time */
/* Build display for: Creation Date */
CreationDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Creation Date: %u", dissect_dos_date(CreationDate));
}
offset += 2; /* Skip Creation Date */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Directory Name */
/* The Directory Name, a null terminated string; Unicode if "Flags" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
DirectoryName = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(DirectoryName, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Directory Name: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Directory Name */
} else {
proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
}
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: File Name */
FileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
}
offset += strlen(FileName) + 1; /* Skip File Name */
}
}
void
dissect_close_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)
{
guint8 WordCount;
guint16 LastWriteTime;
guint16 LastWriteDate;
guint16 FID;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Last Write Time */
LastWriteTime = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Time: %u", dissect_dos_time(LastWriteTime));
}
offset += 2; /* Skip Last Write Time */
/* Build display for: Last Write Date */
LastWriteDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Date: %u", dissect_dos_date(LastWriteDate));
}
offset += 2; /* Skip Last Write Date */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_write_print_file_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint16 FID;
guint16 DataLength;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_lock_and_read_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)
{
guint8 WordCount;
guint8 BufferFormat;
guint32 Offset;
guint16 Reserved4;
guint16 Reserved3;
guint16 Reserved2;
guint16 Reserved1;
guint16 Remaining;
guint16 FID;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Remaining */
Remaining = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Remaining: %u", Remaining);
}
offset += 2; /* Skip Remaining */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Reserved 1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 1: %u", Reserved1);
}
offset += 2; /* Skip Reserved 1 */
/* Build display for: Reserved 2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 2: %u", Reserved2);
}
offset += 2; /* Skip Reserved 2 */
/* Build display for: Reserved 3 */
Reserved3 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 3: %u", Reserved3);
}
offset += 2; /* Skip Reserved 3 */
/* Build display for: Reserved 4 */
Reserved4 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 4: %u", Reserved4);
}
offset += 2; /* Skip Reserved 4 */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
}
}
void
dissect_process_exit_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)
{
guint8 WordCount;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_get_file_attr_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)
{
proto_tree *Attributes_tree;
proto_item *ti;
guint8 WordCount;
guint8 BufferFormat;
guint32 FileSize;
guint16 Reserved5;
guint16 Reserved4;
guint16 Reserved3;
guint16 Reserved2;
guint16 Reserved1;
guint16 LastWriteTime;
guint16 LastWriteDate;
guint16 ByteCount;
guint16 Attributes;
const char *FileName;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
}
offset += 1; /* Skip Buffer Format */
/* Build display for: File Name */
FileName = pd + offset;
if (tree) {
proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
}
offset += strlen(FileName) + 1; /* Skip File Name */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Attributes */
Attributes = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Attributes: 0x%02x", Attributes);
Attributes_tree = proto_item_add_subtree(ti, ett_smb_fileattributes);
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x01, 16, "Read-only file", "Not a read-only file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x02, 16, "Hidden file", "Not a hidden file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x04, 16, "System file", "Not a system file"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x08, 16, " Volume", "Not a volume"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x10, 16, " Directory", "Not a directory"));
proto_tree_add_text(Attributes_tree, offset, 2, "%s",
decode_boolean_bitfield(Attributes, 0x20, 16, " Archived", "Not archived"));
}
offset += 2; /* Skip Attributes */
/* Build display for: Last Write Time */
LastWriteTime = GSHORT(pd, offset);
if (tree) {
}
offset += 2; /* Skip Last Write Time */
/* Build display for: Last Write Date */
LastWriteDate = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Last Write Date: %s", dissect_smbu_date(LastWriteDate, LastWriteTime));
proto_tree_add_text(tree, offset, 2, "Last Write Time: %s", dissect_smbu_time(LastWriteDate, LastWriteTime));
}
offset += 2; /* Skip Last Write Date */
/* Build display for: File Size */
FileSize = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "File Size: %u", FileSize);
}
offset += 4; /* Skip File Size */
/* Build display for: Reserved 1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 1: %u", Reserved1);
}
offset += 2; /* Skip Reserved 1 */
/* Build display for: Reserved 2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 2: %u", Reserved2);
}
offset += 2; /* Skip Reserved 2 */
/* Build display for: Reserved 3 */
Reserved3 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 3: %u", Reserved3);
}
offset += 2; /* Skip Reserved 3 */
/* Build display for: Reserved 4 */
Reserved4 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 4: %u", Reserved4);
}
offset += 2; /* Skip Reserved 4 */
/* Build display for: Reserved 5 */
Reserved5 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 5: %u", Reserved5);
}
offset += 2; /* Skip Reserved 5 */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_read_file_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)
{
guint8 WordCount;
guint32 Offset;
guint16 Reserved4;
guint16 Reserved3;
guint16 Reserved2;
guint16 Reserved1;
guint16 Remaining;
guint16 FID;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
guint16 BufferFormat;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Offset */
Offset = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Offset: %u", Offset);
}
offset += 4; /* Skip Offset */
/* Build display for: Remaining */
Remaining = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Remaining: %u", Remaining);
}
offset += 2; /* Skip Remaining */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Reserved 1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 1: %u", Reserved1);
}
offset += 2; /* Skip Reserved 1 */
/* Build display for: Reserved 2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 2: %u", Reserved2);
}
offset += 2; /* Skip Reserved 2 */
/* Build display for: Reserved 3 */
Reserved3 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 3: %u", Reserved3);
}
offset += 2; /* Skip Reserved 3 */
/* Build display for: Reserved 4 */
Reserved4 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 4: %u", Reserved4);
}
offset += 2; /* Skip Reserved 4 */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Buffer Format */
BufferFormat = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Buffer Format: %u", BufferFormat);
}
offset += 2; /* Skip Buffer Format */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
}
}
void
dissect_write_mpx_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)
{
proto_tree *WriteMode_tree;
proto_item *ti;
guint8 WordCount;
guint8 Pad;
guint32 Timeout;
guint32 ResponseMask;
guint32 RequestMask;
guint16 WriteMode;
guint16 Reserved1;
guint16 FID;
guint16 DataOffset;
guint16 DataLength;
guint16 Count;
guint16 ByteCount;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Count */
Count = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Count: %u", Count);
}
offset += 2; /* Skip Count */
/* Build display for: Reserved 1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved 1: %u", Reserved1);
}
offset += 2; /* Skip Reserved 1 */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: WriteMode */
WriteMode = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "WriteMode: 0x%02x", WriteMode);
WriteMode_tree = proto_item_add_subtree(ti, ett_smb_writemode);
proto_tree_add_text(WriteMode_tree, offset, 2, "%s",
decode_boolean_bitfield(WriteMode, 0x01, 16, "Write through requested", "Write through not requested"));
proto_tree_add_text(WriteMode_tree, offset, 2, "%s",
decode_boolean_bitfield(WriteMode, 0x02, 16, "Return Remaining", "Dont return Remaining"));
proto_tree_add_text(WriteMode_tree, offset, 2, "%s",
decode_boolean_bitfield(WriteMode, 0x40, 16, "Connectionless mode requested", "Connectionless mode not requested"));
}
offset += 2; /* Skip WriteMode */
/* Build display for: Request Mask */
RequestMask = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Request Mask: %u", RequestMask);
}
offset += 4; /* Skip Request Mask */
/* Build display for: Data Length */
DataLength = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Length: %u", DataLength);
}
offset += 2; /* Skip Data Length */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Pad */
Pad = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad: %u", Pad);
}
offset += 1; /* Skip Pad */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
if (WordCount > 0) {
/* Build display for: Response Mask */
ResponseMask = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Response Mask: %u", ResponseMask);
}
offset += 4; /* Skip Response Mask */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
}
offset += 2; /* Skip Byte Count (BCC) */
}
}
void
dissect_find_close2_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)
{
guint8 WordCount;
guint8 ByteCount;
guint16 FID;
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WTC) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WTC): %u", WordCount);
}
offset += 1; /* Skip Word Count (WTC) */
/* Build display for: FID */
FID = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
}
offset += 2; /* Skip FID */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
}
if (dirn == 0) { /* Response(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Byte Count (BCC) */
ByteCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Byte Count (BCC): %u", ByteCount);
}
offset += 1; /* Skip Byte Count (BCC) */
}
}
char *trans2_cmd_names[] = {
"TRANS2_OPEN",
"TRANS2_FIND_FIRST2",
"TRANS2_FIND_NEXT2",
"TRANS2_QUERY_FS_INFORMATION",
"TRANS2_QUERY_PATH_INFORMATION",
"TRANS2_SET_PATH_INFORMATION",
"TRANS2_QUERY_FILE_INFORMATION",
"TRANS2_SET_FILE_INFORMATION",
"TRANS2_FSCTL",
"TRANS2_IOCTL2",
"TRANS2_FIND_NOTIFY_FIRST",
"TRANS2_FIND_NOTIFY_NEXT",
"TRANS2_CREATE_DIRECTORY",
"TRANS2_SESSION_SETUP",
"TRANS2_GET_DFS_REFERRAL",
"no such command",
"TRANS2_REPORT_DFS_INCONSISTENCY"};
char *decode_trans2_name(int code)
{
if (code > 17 || code < 0) {
return("no such command");
}
return trans2_cmd_names[code];
}
guint32 dissect_mailslot_smb(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info, int, int, int, int, const u_char *, int, int);
void
dissect_transact2_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)
{
proto_tree *Flags_tree;
proto_item *ti;
guint8 WordCount;
guint8 SetupCount;
guint8 Reserved3;
guint8 Reserved1;
guint8 Pad2;
guint8 Pad1;
guint8 MaxSetupCount;
guint8 Data;
guint32 Timeout;
guint16 TotalParameterCount;
guint16 TotalDataCount;
guint16 Setup = 0;
guint16 Reserved2;
guint16 ParameterOffset;
guint16 ParameterDisplacement;
guint16 ParameterCount;
guint16 MaxParameterCount;
guint16 MaxDataCount;
guint16 Flags;
guint16 DataOffset;
guint16 DataDisplacement;
guint16 DataCount;
guint16 ByteCount;
conversation_t *conversation;
struct smb_request_key request_key, *new_request_key;
struct smb_request_val *request_val;
/*
* Find out what conversation this packet is part of.
* XXX - this should really be done by the transport-layer protocol,
* although for connectionless transports, we may not want to do that
* unless we know some higher-level protocol will want it - or we
* may want to do it, so you can say e.g. "show only the packets in
* this UDP 'connection'".
*
* Note that we don't have to worry about the direction this packet
* was going - the conversation code handles that for us, treating
* packets from A:X to B:Y as being part of the same conversation as
* packets from B:Y to A:X.
*/
conversation = find_conversation(&pi.src, &pi.dst, pi.ptype,
pi.srcport, pi.destport);
if (conversation == NULL) {
/* It's not part of any conversation - create a new one. */
conversation = conversation_new(&pi.src, &pi.dst, pi.ptype,
pi.srcport, pi.destport, NULL);
}
/*
* Check for and insert entry in request hash table if does not exist
*/
request_key.conversation = conversation->index;
request_key.mid = si.mid;
request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key);
if (!request_val) { /* Create one */
new_request_key = g_mem_chunk_alloc(smb_request_keys);
new_request_key -> conversation = conversation->index;
new_request_key -> mid = si.mid;
request_val = g_mem_chunk_alloc(smb_request_vals);
request_val -> mid = si.mid;
request_val -> last_transact2_command = 0xFFFF;
g_hash_table_insert(smb_request_hash, new_request_key, request_val);
}
else { /* Update the transact request */
request_val -> mid = si.mid;
}
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Total Parameter Count */
TotalParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Parameter Count: %u", TotalParameterCount);
}
offset += 2; /* Skip Total Parameter Count */
/* Build display for: Total Data Count */
TotalDataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Data Count: %u", TotalDataCount);
}
offset += 2; /* Skip Total Data Count */
/* Build display for: Max Parameter Count */
MaxParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Parameter Count: %u", MaxParameterCount);
}
offset += 2; /* Skip Max Parameter Count */
/* Build display for: Max Data Count */
MaxDataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Data Count: %u", MaxDataCount);
}
offset += 2; /* Skip Max Data Count */
/* Build display for: Max Setup Count */
MaxSetupCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Max Setup Count: %u", MaxSetupCount);
}
offset += 1; /* Skip Max Setup Count */
/* Build display for: Reserved1 */
Reserved1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Reserved1: %u", Reserved1);
}
offset += 1; /* Skip Reserved1 */
/* Build display for: Flags */
Flags = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Flags: 0x%02x", Flags);
Flags_tree = proto_item_add_subtree(ti, ett_smb_flags);
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_boolean_bitfield(Flags, 0x01, 16, "Also disconnect TID", "Dont disconnect TID"));
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_boolean_bitfield(Flags, 0x02, 16, "One way transaction", "Two way transaction"));
}
offset += 2; /* Skip Flags */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: Reserved2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved2: %u", Reserved2);
}
offset += 2; /* Skip Reserved2 */
/* Build display for: Parameter Count */
ParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Count: %u", ParameterCount);
}
offset += 2; /* Skip Parameter Count */
/* Build display for: Parameter Offset */
ParameterOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Offset: %u", ParameterOffset);
}
offset += 2; /* Skip Parameter Offset */
/* Build display for: Data Count */
DataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Count: %u", DataCount);
}
offset += 2; /* Skip Data Count */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
/* Build display for: Setup Count */
SetupCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Setup Count: %u", SetupCount);
}
offset += 1; /* Skip Setup Count */
/* Build display for: Reserved3 */
Reserved3 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Reserved3: %u", Reserved3);
}
offset += 1; /* Skip Reserved3 */
/* Build display for: Setup */
if (SetupCount > 0) {
int i = SetupCount;
Setup = GSHORT(pd, offset);
request_val -> last_transact2_command = Setup; /* Save for later */
if (check_col(fd, COL_INFO)) {
col_add_fstr(fd, COL_INFO, "%s %s", decode_trans2_name(Setup), (dirn ? "Request" : "Response"));
}
for (i = 1; i <= SetupCount; i++) {
int Setup1;
Setup1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Setup%i: %u", i, Setup1);
}
offset += 2; /* Skip Setup */
}
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Transact Name */
if (tree) {
proto_tree_add_text(tree, offset, 2, "Transact Name 1: %s", decode_trans2_name(Setup));
}
if (offset % 2) {
/* Build display for: Pad1 */
Pad1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad1: %u", Pad1);
}
offset += 1; /* Skip Pad1 */
}
if (ParameterCount > 0) {
/* Build display for: Parameters */
if (tree) {
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
}
offset += ParameterCount; /* Skip Parameters */
}
if (offset % 2) {
/* Build display for: Pad2 */
Pad2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
}
offset += 1; /* Skip Pad2 */
}
if (DataCount > 0) {
/* Build display for: Data */
Data = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
offset += DataCount; /* Skip Data */
}
}
if (dirn == 0) { /* Response(s) dissect code */
/* Pick up the last transact2 command and put it in the right places */
if (check_col(fd, COL_INFO)) {
col_add_fstr(fd, COL_INFO, "%s %s", decode_trans2_name(request_val -> last_transact2_command), "response");
}
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Total Parameter Count */
TotalParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Parameter Count: %u", TotalParameterCount);
}
offset += 2; /* Skip Total Parameter Count */
/* Build display for: Total Data Count */
TotalDataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Data Count: %u", TotalDataCount);
}
offset += 2; /* Skip Total Data Count */
/* Build display for: Reserved1 */
Reserved1 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved1: %u", Reserved1);
}
offset += 2; /* Skip Reserved */
/* Build display for: Parameter Count */
ParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Count: %u", ParameterCount);
}
offset += 2; /* Skip Parameter Count */
/* Build display for: Parameter Offset */
ParameterOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Offset: %u", ParameterOffset);
}
offset += 2; /* Skip Parameter Offset */
/* Build display for: Parameter Displacement */
ParameterDisplacement = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Displacement: %u", ParameterDisplacement);
}
offset += 2; /* Skip Parameter Displacement */
/* Build display for: Data Count */
DataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Count: %u", DataCount);
}
offset += 2; /* Skip Data Count */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
/* Build display for: Data Displacement */
DataDisplacement = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Displacement: %u", DataDisplacement);
}
offset += 2; /* Skip Data Displacement */
/* Build display for: Setup Count */
SetupCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Setup Count: %u", SetupCount);
}
offset += 1; /* Skip Setup Count */
/* Build display for: Reserved2 */
Reserved2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Reserved2: %u", Reserved2);
}
offset += 1; /* Skip Reserved2 */
/* Build display for: Setup */
Setup = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Setup: %u", Setup);
}
offset += 2; /* Skip Setup */
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Pad1 */
Pad1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad1: %u", Pad1);
}
offset += 1; /* Skip Pad1 */
/* Build display for: Parameter */
if (ParameterCount > 0) {
if (tree) {
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
}
offset += ParameterCount; /* Skip Parameter */
}
if (offset % 2) {
/* Build display for: Pad2 */
Pad2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
}
offset += 1; /* Skip Pad2 */
}
/* Build display for: Data */
if (DataCount > 0) {
if (tree) {
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
offset += DataCount; /* Skip Data */
}
}
}
void
dissect_transact_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)
{
proto_tree *Flags_tree;
proto_item *ti;
guint8 WordCount;
guint8 SetupCount;
guint8 Reserved3;
guint8 Reserved1;
guint8 Parameter;
guint8 Pad2;
guint8 Pad1;
guint8 MaxSetupCount;
guint8 Data;
guint32 Timeout;
guint16 TotalParameterCount;
guint16 TotalDataCount;
guint16 Setup = 0;
guint16 Reserved2;
guint16 ParameterOffset;
guint16 ParameterDisplacement;
guint16 ParameterCount;
guint16 MaxParameterCount;
guint16 MaxDataCount;
guint16 Flags;
guint16 DataOffset;
guint16 DataDisplacement;
guint16 DataCount;
guint16 ByteCount;
const char *TransactName;
char *TransactNameCopy;
char *trans_type;
char *trans_cmd, *loc_of_slash;
guint32 index=0;
conversation_t *conversation;
struct smb_request_key request_key, *new_request_key;
struct smb_request_val *request_val;
char *ustr;
int ustr_len;
guint8 Default_Path;
guint16 Flags2;
/* obtain the Flags2 settings */
Flags2 = GSHORT(pd, Flags2_Offset);
/*
* Find out what conversation this packet is part of
*/
conversation = find_conversation(&pi.src, &pi.dst, pi.ptype,
pi.srcport, pi.destport);
if (conversation == NULL) { /* Create a new conversation */
conversation = conversation_new(&pi.src, &pi.dst, pi.ptype,
pi.srcport, pi.destport, NULL);
}
/*
* Check for and insert entry in request hash table if does not exist
*/
request_key.conversation = conversation->index;
request_key.mid = si.mid;
request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key);
if (!request_val) { /* Create one */
new_request_key = g_mem_chunk_alloc(smb_request_keys);
new_request_key -> conversation = conversation -> index;
new_request_key -> mid = si.mid;
request_val = g_mem_chunk_alloc(smb_request_vals);
request_val -> mid = si.mid;
request_val -> last_transact_command = NULL;
g_hash_table_insert(smb_request_hash, new_request_key, request_val);
}
if (dirn == 1) { /* Request(s) dissect code */
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Total Parameter Count */
TotalParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Parameter Count: %u", TotalParameterCount);
}
offset += 2; /* Skip Total Parameter Count */
/* Build display for: Total Data Count */
TotalDataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Data Count: %u", TotalDataCount);
}
offset += 2; /* Skip Total Data Count */
/* Build display for: Max Parameter Count */
MaxParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Parameter Count: %u", MaxParameterCount);
}
offset += 2; /* Skip Max Parameter Count */
/* Build display for: Max Data Count */
MaxDataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Max Data Count: %u", MaxDataCount);
}
offset += 2; /* Skip Max Data Count */
/* Build display for: Max Setup Count */
MaxSetupCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Max Setup Count: %u", MaxSetupCount);
}
offset += 1; /* Skip Max Setup Count */
/* Build display for: Reserved1 */
Reserved1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Reserved1: %u", Reserved1);
}
offset += 1; /* Skip Reserved1 */
/* Build display for: Flags */
Flags = GSHORT(pd, offset);
if (tree) {
ti = proto_tree_add_text(tree, offset, 2, "Flags: 0x%02x", Flags);
Flags_tree = proto_item_add_subtree(ti, ett_smb_flags);
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_boolean_bitfield(Flags, 0x01, 16, "Also disconnect TID", "Dont disconnect TID"));
proto_tree_add_text(Flags_tree, offset, 2, "%s",
decode_boolean_bitfield(Flags, 0x02, 16, "One way transaction", "Two way transaction"));
}
offset += 2; /* Skip Flags */
/* Build display for: Timeout */
Timeout = GWORD(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 4, "Timeout: %u", Timeout);
}
offset += 4; /* Skip Timeout */
/* Build display for: Reserved2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved2: %u", Reserved2);
}
offset += 2; /* Skip Reserved2 */
/* Build display for: Parameter Count */
ParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Count: %u", ParameterCount);
}
offset += 2; /* Skip Parameter Count */
/* Build display for: Parameter Offset */
ParameterOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Offset: %u", ParameterOffset);
}
offset += 2; /* Skip Parameter Offset */
/* Build display for: Data Count */
DataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Count: %u", DataCount);
}
offset += 2; /* Skip Data Count */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
/* Build display for: Setup Count */
SetupCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Setup Count: %u", SetupCount);
}
offset += 1; /* Skip Setup Count */
/* Build display for: Reserved3 */
Reserved3 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Reserved3: %u", Reserved3);
}
offset += 1; /* Skip Reserved3 */
/* Build display for: Setup */
if (SetupCount > 0) {
int i = SetupCount;
Setup = GSHORT(pd, offset);
for (i = 1; i <= SetupCount; i++) {
Setup = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Setup%i: %u", i, Setup);
}
offset += 2; /* Skip Setup */
}
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Transact Name */
/* The Transact Name, a null terminated string; Unicode if "Flags" has
the 0x8000 bit set, ASCII (OEM character set) otherwise.
XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
if (Flags2 & 0x8000) {
offset +=1; /* skip EXTRA bit for unicode alignment */
}
TransactName = pd + offset;
if (tree) {
if (Flags2 & 0x8000) {
ustr = unicode_to_str(TransactName, &ustr_len);
proto_tree_add_text(tree, offset, ustr_len+2, "Transact Name 2: %s", ustr);
offset += (strlen(ustr)*2) + 2; /* Skip Transact Name */
TransactName=ustr;
} else {
proto_tree_add_text(tree, offset, strlen(TransactName) + 1, "Transact Name 2: %s", TransactName);
offset += strlen(TransactName) + 1; /* Skip Transact Name */
}
}
if (request_val -> last_transact_command) g_free(request_val -> last_transact_command);
request_val -> last_transact_command = g_malloc(strlen(TransactName) + 1);
if (request_val -> last_transact_command)
strcpy(request_val -> last_transact_command, TransactName);
if (check_col(fd, COL_INFO)) {
col_add_fstr(fd, COL_INFO, "%s %s", TransactName, (dirn ? "Request" : "Response"));
}
if (offset % 2) {
/* Build display for: Pad1 */
Pad1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad1: %u", Pad1);
}
offset += 1; /* Skip Pad1 */
}
/* Let's see if we can decode this */
TransactNameCopy = g_malloc(strlen(TransactName) + 1);
/* Bad, check for error? */
strcpy(TransactNameCopy, TransactName);
trans_type = TransactNameCopy + 1; /* Skip the slash */
loc_of_slash = strchr(trans_type, '\\');
if (loc_of_slash) {
index = loc_of_slash - trans_type; /* Make it a real index */
trans_cmd = trans_type + index + 1;
trans_type[index] = '\0';
}
else
trans_cmd = NULL;
/* If trans type != MAILSLOT then process mailslot. if unsuccessful then default processing */
Default_Path = 1;
if (!strncmp(trans_type, "MAILSLOT",8))
Default_Path = !(dissect_mailslot_smb(pd, offset, fd, parent, tree, si, max_data, SMB_offset, errcode, dirn, trans_cmd, SMB_offset + DataOffset, DataCount));
if (Default_Path) {
if (ParameterCount > 0) {
/* Build display for: Parameters */
if (tree) {
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
}
offset += ParameterCount; /* Skip Parameters */
}
if (offset % 2) {
/* Build display for: Pad2 */
Pad2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
}
offset += 1; /* Skip Pad2 */
}
if (DataCount > 0) {
/* Build display for: Data */
Data = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
offset += DataCount; /* Skip Data */
}
}
}
if (dirn == 0) { /* Response(s) dissect code */
if (check_col(fd, COL_INFO)) {
col_add_fstr(fd, COL_INFO, "%s %s", request_val -> last_transact_command, "Response");
}
/* Build display for: Word Count (WCT) */
WordCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
}
offset += 1; /* Skip Word Count (WCT) */
/* Build display for: Total Parameter Count */
TotalParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Parameter Count: %u", TotalParameterCount);
}
offset += 2; /* Skip Total Parameter Count */
/* Build display for: Total Data Count */
TotalDataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Total Data Count: %u", TotalDataCount);
}
offset += 2; /* Skip Total Data Count */
/* Build display for: Reserved2 */
Reserved2 = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Reserved2: %u", Reserved2);
}
offset += 2; /* Skip Reserved2 */
/* Build display for: Parameter Count */
ParameterCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Count: %u", ParameterCount);
}
offset += 2; /* Skip Parameter Count */
/* Build display for: Parameter Offset */
ParameterOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Offset: %u", ParameterOffset);
}
offset += 2; /* Skip Parameter Offset */
/* Build display for: Parameter Displacement */
ParameterDisplacement = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Parameter Displacement: %u", ParameterDisplacement);
}
offset += 2; /* Skip Parameter Displacement */
/* Build display for: Data Count */
DataCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Count: %u", DataCount);
}
offset += 2; /* Skip Data Count */
/* Build display for: Data Offset */
DataOffset = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Offset: %u", DataOffset);
}
offset += 2; /* Skip Data Offset */
/* Build display for: Data Displacement */
DataDisplacement = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Data Displacement: %u", DataDisplacement);
}
offset += 2; /* Skip Data Displacement */
/* Build display for: Setup Count */
SetupCount = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Setup Count: %u", SetupCount);
}
offset += 1; /* Skip Setup Count */
/* Build display for: Reserved3 */
Reserved3 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Reserved3: %u", Reserved3);
}
offset += 1; /* Skip Reserved3 */
/* Build display for: Setup */
if (SetupCount > 0) {
/* Hmmm, should code for all setup words ... */
Setup = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Setup: %u", Setup);
}
offset += 2; /* Skip Setup */
}
/* Build display for: Byte Count (BCC) */
ByteCount = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
}
offset += 2; /* Skip Byte Count (BCC) */
/* Build display for: Pad1 */
Pad1 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad1: %u", Pad1);
}
offset += 1; /* Skip Pad1 */
if (ParameterCount > 0) {
/* Build display for: Parameter */
Parameter = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text_ASCII(pd + SMB_offset + ParameterOffset, ParameterCount));
proto_tree_add_text(tree, SMB_offset + ParameterOffset, ParameterCount, "Parameters: %s", format_text(pd + SMB_offset + ParameterOffset, ParameterCount));
}
offset += ParameterCount; /* Skip Parameter */
}
if (offset %2) {
/* Build display for: Pad2 */
Pad2 = GBYTE(pd, offset);
if (tree) {
proto_tree_add_text(tree, offset, 1, "Pad2: %u", Pad2);
}
offset += 1; /* Skip Pad2 */
}
/* Build display for: Data */
if (DataCount > 0) {
if (tree) {
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text_ASCII(&pd[offset], DataCount));
proto_tree_add_text(tree, SMB_offset + DataOffset, DataCount, "Data: %s", format_text(pd + SMB_offset + DataOffset, DataCount));
}
offset += DataCount; /* Skip Data */
}
}
}
/*
* The routines for mailslot and pipe dissecting should be migrated to another
* file soon?
*/
char *browse_commands[] =
{ "Error, No such command!", /* Value 0 */
"Host Announcement", /* Value 1 */
"Request Announcement", /* Value 2 */
"Error, No such command!", /* Value 3 */
"Error, No such command!", /* Value 4 */
"Error, No such command!", /* Value 5 */
"Error, No such command!", /* Value 6 */
"Error, No such command!", /* Value 7 */
"Browser Election Request", /* Value 8 */
"Get Backup List Request", /* Value 9 */
"Get Backup List Response", /* Value 10 */
"Become Backup Browser", /* Value 11 */
"Domain/Workgroup Announcement", /* Value 12 */
"Master Announcement", /* Value 13 */
"Error! No such command", /* Value 14 */
"Local Master Announcement" /* Value 15 */
};
#define HOST_ANNOUNCE 1
#define REQUEST_ANNOUNCE 2
#define BROWSER_ELECTION 8
#define GETBACKUPLISTREQ 9
#define GETBACKUPLISTRESP 10
#define BECOMEBACKUPBROWSER 11
#define DOMAINANNOUNCEMENT 12
#define MASTERANNOUNCEMENT 13
#define LOCALMASTERANNOUNC 15
char *svr_types[32] = {
"Workstation",
"Server",
"SQL Server",
"Domain Controller",
"Backup Controller",
"Time Source",
"Apple Server",
"Novell Server",
"Domain Member Server",
"Print Queue Server",
"Dialin Server",
"Xenix Server",
"NT Workstation",
"Windows for Workgroups",
"Unknown Server - FIXME",
"NT Server",
"Potential Browser",
"Backup Browser",
"Master Browser",
"Domain Master Browser",
"OSF",
"VMS",
"Windows 95 or above",
"Unused",
"Unused",
"Unused",
"Unused",
"Unused",
"Unused",
"Unused",
"Local List Only",
"Domain Enum"
};
guint32
dissect_mailslot_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)
{
guint8 OpCode;
guint8 UpdateCount;
guint8 VersionMajor;
guint8 VersionMinor;
guint32 Periodicity;
guint32 ServerType;
guint16 SigConstant;
guint32 Token;
guint8 BackupServerCount;
guint8 Flags;
guint32 MBZ;
guint8 ElectionVersion;
guint32 ElectionCriteria;
guint8 ElectionOS;
guint8 ElectionDesire;
guint16 ElectionRevision;
guint32 ServerUpTime;
const char *ServerName;
const char *ServerComment;
proto_tree *browse_tree = NULL, *flags_tree = NULL,
*OSflags = NULL, *DesireFlags = NULL;
proto_item *ti, *ec;
guint32 loc_offset = DataOffset, count = 0;
int i;
if (strcmp(command, "BROWSE") == 0) { /* Decode a browse */
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "BROWSER");
if (check_col(fd, COL_INFO)) /* Put in something, and replace it later */
col_add_str(fd, COL_INFO, "Browse Announcement");
/*
* Now, decode the browse request
*/
OpCode = GBYTE(pd, loc_offset);
if (check_col(fd, COL_INFO))
col_add_fstr(fd, COL_INFO, (OpCode > (sizeof(browse_commands)/sizeof(char *))) ? "Error, No Such Command:%u" : browse_commands[OpCode], OpCode);
if (tree) { /* Add the browse tree */
ti = proto_tree_add_item(parent, proto_browse, DataOffset, DataCount, NULL);
browse_tree = proto_item_add_subtree(ti, ett_browse);
proto_tree_add_text(browse_tree, loc_offset, 1, "OpCode: %s", (OpCode > (sizeof(browse_commands)/sizeof(char *))) ? "Error, No Such Command" : browse_commands[OpCode]);
}
loc_offset += 1; /* Skip the OpCode */
switch (OpCode) {
case DOMAINANNOUNCEMENT:
case LOCALMASTERANNOUNC:
case HOST_ANNOUNCE:
UpdateCount = GBYTE(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 1, "Update Count: %u", UpdateCount);
}
loc_offset += 1; /* Skip the Update Count */
Periodicity = GWORD(pd, loc_offset + 2);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 4, "Update Periodicity: %u mSec", Periodicity >> 16);
}
loc_offset += 4;
ServerName = pd + loc_offset;
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 16, (OpCode == DOMAINANNOUNCEMENT) ? "Domain/WorkGroup: %s": "Host Name: %s", ServerName);
}
loc_offset += 16;
VersionMajor = GBYTE(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 1, "Major Version: %u", VersionMajor);
}
loc_offset += 1;
VersionMinor = GBYTE(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 1, "Minor Version: %u", VersionMinor);
}
loc_offset += 1;
ServerType = GWORD(pd, loc_offset);
if (check_col(fd, COL_INFO)) {
/* Append the type(s) of the system to the COL_INFO line ... */
for (i = 1; i <= 32; i++) {
if (ServerType & (1 << (i - 1)) && (strcmp("Unused", svr_types[i]) != 0))
col_append_fstr(fd, COL_INFO, ", %s", svr_types[i - 1]);
}
}
if (tree) {
ti = proto_tree_add_text(browse_tree, loc_offset, 4, "Server Type: 0x%04x", ServerType);
flags_tree = proto_item_add_subtree(ti, ett_browse_flags);
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0001, 32, "Workstation", "Not Workstation"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0002, 32, "Server", "Not Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0004, 32, "SQL Server", "Not SQL Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0008, 32, "Domain Controller", "Not Domain Controller"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0010, 32, "Backup Controller", "Not Backup Controller"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0020, 32, "Time Source", "Not Time Source"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0040, 32, "Apple Server", "Not Apple Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0080, 32, "Novell Server", "Not Novell Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0100, 32, "Domain Member Server", "Not Domain Member Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0200, 32, "Print Queue Server", "Not Print Queue Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0400, 32, "Dialin Server", "Not Dialin Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x0800, 32, "Xenix Server", "Not Xenix Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x1000, 32, "NT Workstation", "Not NT Workstation"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x2000, 32, "Windows for Workgroups", "Not Windows for Workgroups"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x8000, 32, "NT Server", "Not NT Server"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x10000, 32, "Potential Browser", "Not Potential Browser"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x20000, 32, "Backup Browser", "Not Backup Browser"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x40000, 32, "Master Browser", "Not Master Browser"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x80000, 32, "Domain Master Browser", "Not Domain Master Browser"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x100000, 32, "OSF", "Not OSF"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x200000, 32, "VMS", "Not VMS"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x400000, 32, "Windows 95 or above", "Not Windows 95 or above"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x40000000, 32, "Local List Only", "Not Local List Only"));
proto_tree_add_text(flags_tree, loc_offset, 4, "%s",
decode_boolean_bitfield(ServerType, 0x80000000, 32, "Domain Enum", "Not Domain Enum"));
}
loc_offset += 4;
ElectionVersion = GSHORT(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 2, "Election Version: %u", ElectionVersion);
}
loc_offset += 2;
SigConstant = GSHORT(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 2, "Signature: %u (0x%04X)", SigConstant, SigConstant);
}
loc_offset += 2;
ServerComment = pd + loc_offset;
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, strlen(ServerComment) + 1, "Host Comment: %s", ServerComment);
}
break;
case REQUEST_ANNOUNCE:
Flags = GBYTE(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 1, "Unused Flags: %u", Flags);
}
loc_offset += 1;
ServerName = pd + loc_offset;
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, strlen(ServerName) + 1, "Send List To: %s", ServerName);
}
break;
case BROWSER_ELECTION:
ElectionVersion = GBYTE(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 1, "Election Version = %u", ElectionVersion);
}
loc_offset += 1;
ElectionCriteria = GWORD(pd, loc_offset);
ElectionOS = GBYTE(pd, loc_offset + 3);
ElectionRevision = GSHORT(pd, loc_offset + 1);
ElectionDesire = GBYTE(pd, loc_offset);
if (tree) {
ti = proto_tree_add_text(browse_tree, loc_offset, 4, "Election Criteria = %u (0x%08X)", ElectionCriteria, ElectionCriteria);
ec = proto_item_add_subtree(ti, ett_browse_election_criteria);
ti = proto_tree_add_text(ec, loc_offset + 3, 1, "Election OS Summary: %u (0x%02X)", ElectionOS, ElectionOS);
OSflags = proto_item_add_subtree(ti, ett_browse_election_os);
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x01, 8, "Windows for Workgroups", "Not Windows for Workgroups"));
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x02, 8, "Unknown", "Not used"));
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x04, 8, "Unknown", "Not used"));
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x08, 8, "Unknown", "Not used"));
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x10, 8, "Windows NT Workstation", "Not Windows NT Workstation"));
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x20, 8, "Windows NT Server", "Not Windows NT Server"));
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x40, 8, "Unknown", "Not used"));
proto_tree_add_text(OSflags, loc_offset + 3, 1, "%s",
decode_boolean_bitfield(ElectionOS, 0x80, 8, "Unknown", "Not used"));
proto_tree_add_text(ec, loc_offset + 1, 2, "Election Revision: %u (0x%04X)", ElectionRevision, ElectionRevision);
ti = proto_tree_add_text(ec, loc_offset, 1, "Election Desire Summary: %u (0x%02X)", ElectionDesire, ElectionDesire);
DesireFlags = proto_item_add_subtree(ti, ett_browse_election_desire);
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x01, 8, "Backup Browse Server", "Not Backup Browse Server"));
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x02, 8, "Standby Browse Server", "Not Standby Browse Server"));
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x04, 8, "Master Browser", "Not Master Browser"));
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x08, 8, "Domain Master Browse Server", "Not Domain Master Browse Server"));
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x10, 8, "Unknown", "Not used"));
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x20, 8, "WINS Client", "Not WINS Client"));
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x40, 8, "Unknown", "Not used"));
proto_tree_add_text(DesireFlags, loc_offset, 1, "%s",
decode_boolean_bitfield(ElectionDesire, 0x80, 8, "Windows NT Advanced Server", "Not Windows NT Advanced Server"));
}
loc_offset += 4;
ServerUpTime = GWORD(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 4, "Server Up Time: %u Sec", ServerUpTime);
}
loc_offset += 4;
MBZ = GWORD(pd, loc_offset);
loc_offset += 4;
ServerName = pd + loc_offset;
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, strlen(ServerName) + 1, "Election Server Name: %s", ServerName);
}
break;
case GETBACKUPLISTREQ:
BackupServerCount = GBYTE(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 1, "Backup List Requested Count: %u", BackupServerCount);
}
loc_offset += 1;
Token = GWORD(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 4, "Backup Request Token: %u", Token);
}
break;
case GETBACKUPLISTRESP:
BackupServerCount = GBYTE(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 1, "Backup Server Count: %u", BackupServerCount);
}
loc_offset += 1;
Token = GWORD(pd, loc_offset);
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, 4, "Backup Response Token: %u", Token);
}
loc_offset += 4;
ServerName = pd + loc_offset;
for (count = 1; count <= BackupServerCount; count++) {
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, strlen(ServerName) + 1, "Backup Server: %s", ServerName);
}
loc_offset += strlen(ServerName) + 1;
ServerName = pd + loc_offset;
}
break;
case BECOMEBACKUPBROWSER:
ServerName = pd + loc_offset;
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, strlen(ServerName) + 1, "Browser to Promote: %s", ServerName);
}
break;
case MASTERANNOUNCEMENT:
ServerName = pd + loc_offset;
if (tree) {
proto_tree_add_text(browse_tree, loc_offset, strlen(ServerName) + 1, "Server Name: %s", ServerName);
}
break;
default:
break;
}
return 1; /* Success */
}
return 0;
}
void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, proto_tree *, struct smb_info, int, int, int, int) = {
dissect_unknown_smb, /* unknown SMB 0x00 */
dissect_unknown_smb, /* unknown SMB 0x01 */
dissect_unknown_smb, /* SMBopen open a file */
dissect_create_file_smb, /* SMBcreate create a file */
dissect_close_smb, /* SMBclose close a file */
dissect_flush_file_smb, /* SMBflush flush a file */
dissect_delete_file_smb, /* SMBunlink delete a file */
dissect_rename_file_smb, /* SMBmv rename a file */
dissect_get_file_attr_smb,/* SMBgetatr get file attributes */
dissect_set_file_attr_smb,/* SMBsetatr set file attributes */
dissect_read_file_smb, /* SMBread read from a file */
dissect_write_file_smb, /* SMBwrite write to a file */
dissect_lock_bytes_smb, /* SMBlock lock a byte range */
dissect_unlock_bytes_smb, /* SMBunlock unlock a byte range */
dissect_create_temporary_file_smb,/* SMBctemp create a temporary file */
dissect_unknown_smb, /* SMBmknew make a new file */
dissect_checkdir_smb, /* SMBchkpth check a directory path */
dissect_process_exit_smb, /* SMBexit process exit */
dissect_unknown_smb, /* SMBlseek seek */
dissect_lock_and_read_smb,/* SMBlockread Lock a range and read it */
dissect_write_and_unlock_smb,/* SMBwriteunlock Unlock a range and then write */
dissect_unknown_smb, /* unknown SMB 0x15 */
dissect_unknown_smb, /* unknown SMB 0x16 */
dissect_unknown_smb, /* unknown SMB 0x17 */
dissect_unknown_smb, /* unknown SMB 0x18 */
dissect_unknown_smb, /* unknown SMB 0x19 */
dissect_read_raw_smb, /* SMBreadBraw read block raw */
dissect_read_mpx_smb, /* SMBreadBmpx read block multiplexed */
dissect_unknown_smb, /* SMBreadBs read block (secondary response) */
dissect_write_raw_smb, /* SMBwriteBraw write block raw */
dissect_write_mpx_smb, /* SMBwriteBmpx write block multiplexed */
dissect_unknown_smb, /* SMBwriteBs write block (secondary request) */
dissect_unknown_smb, /* SMBwriteC write complete response */
dissect_unknown_smb, /* unknown SMB 0x21 */
dissect_set_info2_smb, /* SMBsetattrE set file attributes expanded */
dissect_query_info2_smb, /* SMBgetattrE get file attributes expanded */
dissect_locking_andx_smb, /* SMBlockingX lock/unlock byte ranges and X */
dissect_transact_smb, /* SMBtrans transaction - name, bytes in/out */
dissect_unknown_smb, /* SMBtranss transaction (secondary request/response) */
dissect_unknown_smb, /* SMBioctl IOCTL */
dissect_unknown_smb, /* SMBioctls IOCTL (secondary request/response) */
dissect_unknown_smb, /* SMBcopy copy */
dissect_move_smb, /* SMBmove move */
dissect_unknown_smb, /* SMBecho echo */
dissect_unknown_smb, /* SMBwriteclose write a file and then close it */
dissect_open_andx_smb, /* SMBopenX open and X */
dissect_unknown_smb, /* SMBreadX read and X */
dissect_unknown_smb, /* SMBwriteX write and X */
dissect_unknown_smb, /* unknown SMB 0x30 */
dissect_unknown_smb, /* unknown SMB 0x31 */
dissect_transact2_smb, /* unknown SMB 0x32 */
dissect_unknown_smb, /* unknown SMB 0x33 */
dissect_find_close2_smb, /* unknown SMB 0x34 */
dissect_unknown_smb, /* unknown SMB 0x35 */
dissect_unknown_smb, /* unknown SMB 0x36 */
dissect_unknown_smb, /* unknown SMB 0x37 */
dissect_unknown_smb, /* unknown SMB 0x38 */
dissect_unknown_smb, /* unknown SMB 0x39 */
dissect_unknown_smb, /* unknown SMB 0x3a */
dissect_unknown_smb, /* unknown SMB 0x3b */
dissect_unknown_smb, /* unknown SMB 0x3c */
dissect_unknown_smb, /* unknown SMB 0x3d */
dissect_unknown_smb, /* unknown SMB 0x3e */
dissect_unknown_smb, /* unknown SMB 0x3f */
dissect_unknown_smb, /* unknown SMB 0x40 */
dissect_unknown_smb, /* unknown SMB 0x41 */
dissect_unknown_smb, /* unknown SMB 0x42 */
dissect_unknown_smb, /* unknown SMB 0x43 */
dissect_unknown_smb, /* unknown SMB 0x44 */
dissect_unknown_smb, /* unknown SMB 0x45 */
dissect_unknown_smb, /* unknown SMB 0x46 */
dissect_unknown_smb, /* unknown SMB 0x47 */
dissect_unknown_smb, /* unknown SMB 0x48 */
dissect_unknown_smb, /* unknown SMB 0x49 */
dissect_unknown_smb, /* unknown SMB 0x4a */
dissect_unknown_smb, /* unknown SMB 0x4b */
dissect_unknown_smb, /* unknown SMB 0x4c */
dissect_unknown_smb, /* unknown SMB 0x4d */
dissect_unknown_smb, /* unknown SMB 0x4e */
dissect_unknown_smb, /* unknown SMB 0x4f */
dissect_unknown_smb, /* unknown SMB 0x50 */
dissect_unknown_smb, /* unknown SMB 0x51 */
dissect_unknown_smb, /* unknown SMB 0x52 */
dissect_unknown_smb, /* unknown SMB 0x53 */
dissect_unknown_smb, /* unknown SMB 0x54 */
dissect_unknown_smb, /* unknown SMB 0x55 */
dissect_unknown_smb, /* unknown SMB 0x56 */
dissect_unknown_smb, /* unknown SMB 0x57 */
dissect_unknown_smb, /* unknown SMB 0x58 */
dissect_unknown_smb, /* unknown SMB 0x59 */
dissect_unknown_smb, /* unknown SMB 0x5a */
dissect_unknown_smb, /* unknown SMB 0x5b */
dissect_unknown_smb, /* unknown SMB 0x5c */
dissect_unknown_smb, /* unknown SMB 0x5d */
dissect_unknown_smb, /* unknown SMB 0x5e */
dissect_unknown_smb, /* unknown SMB 0x5f */
dissect_unknown_smb, /* unknown SMB 0x60 */
dissect_unknown_smb, /* unknown SMB 0x61 */
dissect_unknown_smb, /* unknown SMB 0x62 */
dissect_unknown_smb, /* unknown SMB 0x63 */
dissect_unknown_smb, /* unknown SMB 0x64 */
dissect_unknown_smb, /* unknown SMB 0x65 */
dissect_unknown_smb, /* unknown SMB 0x66 */
dissect_unknown_smb, /* unknown SMB 0x67 */
dissect_unknown_smb, /* unknown SMB 0x68 */
dissect_unknown_smb, /* unknown SMB 0x69 */
dissect_unknown_smb, /* unknown SMB 0x6a */
dissect_unknown_smb, /* unknown SMB 0x6b */
dissect_unknown_smb, /* unknown SMB 0x6c */
dissect_unknown_smb, /* unknown SMB 0x6d */
dissect_unknown_smb, /* unknown SMB 0x6e */
dissect_unknown_smb, /* unknown SMB 0x6f */
dissect_treecon_smb, /* SMBtcon tree connect */
dissect_tdis_smb, /* SMBtdis tree disconnect */
dissect_negprot_smb, /* SMBnegprot negotiate a protocol */
dissect_ssetup_andx_smb, /* SMBsesssetupX Session Set Up & X (including User Logon) */
dissect_logoff_andx_smb, /* SMBlogof Logoff & X */
dissect_tcon_andx_smb, /* SMBtconX tree connect and X */
dissect_unknown_smb, /* unknown SMB 0x76 */
dissect_unknown_smb, /* unknown SMB 0x77 */
dissect_unknown_smb, /* unknown SMB 0x78 */
dissect_unknown_smb, /* unknown SMB 0x79 */
dissect_unknown_smb, /* unknown SMB 0x7a */
dissect_unknown_smb, /* unknown SMB 0x7b */
dissect_unknown_smb, /* unknown SMB 0x7c */
dissect_unknown_smb, /* unknown SMB 0x7d */
dissect_unknown_smb, /* unknown SMB 0x7e */
dissect_unknown_smb, /* unknown SMB 0x7f */
dissect_get_disk_attr_smb,/* SMBdskattr get disk attributes */
dissect_search_dir_smb, /* SMBsearch search a directory */
dissect_unknown_smb, /* SMBffirst find first */
dissect_unknown_smb, /* SMBfunique find unique */
dissect_unknown_smb, /* SMBfclose find close */
dissect_unknown_smb, /* unknown SMB 0x85 */
dissect_unknown_smb, /* unknown SMB 0x86 */
dissect_unknown_smb, /* unknown SMB 0x87 */
dissect_unknown_smb, /* unknown SMB 0x88 */
dissect_unknown_smb, /* unknown SMB 0x89 */
dissect_unknown_smb, /* unknown SMB 0x8a */
dissect_unknown_smb, /* unknown SMB 0x8b */
dissect_unknown_smb, /* unknown SMB 0x8c */
dissect_unknown_smb, /* unknown SMB 0x8d */
dissect_unknown_smb, /* unknown SMB 0x8e */
dissect_unknown_smb, /* unknown SMB 0x8f */
dissect_unknown_smb, /* unknown SMB 0x90 */
dissect_unknown_smb, /* unknown SMB 0x91 */
dissect_unknown_smb, /* unknown SMB 0x92 */
dissect_unknown_smb, /* unknown SMB 0x93 */
dissect_unknown_smb, /* unknown SMB 0x94 */
dissect_unknown_smb, /* unknown SMB 0x95 */
dissect_unknown_smb, /* unknown SMB 0x96 */
dissect_unknown_smb, /* unknown SMB 0x97 */
dissect_unknown_smb, /* unknown SMB 0x98 */
dissect_unknown_smb, /* unknown SMB 0x99 */
dissect_unknown_smb, /* unknown SMB 0x9a */
dissect_unknown_smb, /* unknown SMB 0x9b */
dissect_unknown_smb, /* unknown SMB 0x9c */
dissect_unknown_smb, /* unknown SMB 0x9d */
dissect_unknown_smb, /* unknown SMB 0x9e */
dissect_unknown_smb, /* unknown SMB 0x9f */
dissect_unknown_smb, /* unknown SMB 0xa0 */
dissect_unknown_smb, /* unknown SMB 0xa1 */
dissect_unknown_smb, /* unknown SMB 0xa2 */
dissect_unknown_smb, /* unknown SMB 0xa3 */
dissect_unknown_smb, /* unknown SMB 0xa4 */
dissect_unknown_smb, /* unknown SMB 0xa5 */
dissect_unknown_smb, /* unknown SMB 0xa6 */
dissect_unknown_smb, /* unknown SMB 0xa7 */
dissect_unknown_smb, /* unknown SMB 0xa8 */
dissect_unknown_smb, /* unknown SMB 0xa9 */
dissect_unknown_smb, /* unknown SMB 0xaa */
dissect_unknown_smb, /* unknown SMB 0xab */
dissect_unknown_smb, /* unknown SMB 0xac */
dissect_unknown_smb, /* unknown SMB 0xad */
dissect_unknown_smb, /* unknown SMB 0xae */
dissect_unknown_smb, /* unknown SMB 0xaf */
dissect_unknown_smb, /* unknown SMB 0xb0 */
dissect_unknown_smb, /* unknown SMB 0xb1 */
dissect_unknown_smb, /* unknown SMB 0xb2 */
dissect_unknown_smb, /* unknown SMB 0xb3 */
dissect_unknown_smb, /* unknown SMB 0xb4 */
dissect_unknown_smb, /* unknown SMB 0xb5 */
dissect_unknown_smb, /* unknown SMB 0xb6 */
dissect_unknown_smb, /* unknown SMB 0xb7 */
dissect_unknown_smb, /* unknown SMB 0xb8 */
dissect_unknown_smb, /* unknown SMB 0xb9 */
dissect_unknown_smb, /* unknown SMB 0xba */
dissect_unknown_smb, /* unknown SMB 0xbb */
dissect_unknown_smb, /* unknown SMB 0xbc */
dissect_unknown_smb, /* unknown SMB 0xbd */
dissect_unknown_smb, /* unknown SMB 0xbe */
dissect_unknown_smb, /* unknown SMB 0xbf */
dissect_unknown_smb, /* SMBsplopen open a print spool file */
dissect_write_print_file_smb,/* SMBsplwr write to a print spool file */
dissect_close_print_file_smb,/* SMBsplclose close a print spool file */
dissect_get_print_queue_smb, /* SMBsplretq return print queue */
dissect_unknown_smb, /* unknown SMB 0xc4 */
dissect_unknown_smb, /* unknown SMB 0xc5 */
dissect_unknown_smb, /* unknown SMB 0xc6 */
dissect_unknown_smb, /* unknown SMB 0xc7 */
dissect_unknown_smb, /* unknown SMB 0xc8 */
dissect_unknown_smb, /* unknown SMB 0xc9 */
dissect_unknown_smb, /* unknown SMB 0xca */
dissect_unknown_smb, /* unknown SMB 0xcb */
dissect_unknown_smb, /* unknown SMB 0xcc */
dissect_unknown_smb, /* unknown SMB 0xcd */
dissect_unknown_smb, /* unknown SMB 0xce */
dissect_unknown_smb, /* unknown SMB 0xcf */
dissect_unknown_smb, /* SMBsends send a single block message */
dissect_unknown_smb, /* SMBsendb send a broadcast message */
dissect_unknown_smb, /* SMBfwdname forward user name */
dissect_unknown_smb, /* SMBcancelf cancel forward */
dissect_unknown_smb, /* SMBgetmac get a machine name */
dissect_unknown_smb, /* SMBsendstrt send start of multi-block message */
dissect_unknown_smb, /* SMBsendend send end of multi-block message */
dissect_unknown_smb, /* SMBsendtxt send text of multi-block message */
dissect_unknown_smb, /* unknown SMB 0xd8 */
dissect_unknown_smb, /* unknown SMB 0xd9 */
dissect_unknown_smb, /* unknown SMB 0xda */
dissect_unknown_smb, /* unknown SMB 0xdb */
dissect_unknown_smb, /* unknown SMB 0xdc */
dissect_unknown_smb, /* unknown SMB 0xdd */
dissect_unknown_smb, /* unknown SMB 0xde */
dissect_unknown_smb, /* unknown SMB 0xdf */
dissect_unknown_smb, /* unknown SMB 0xe0 */
dissect_unknown_smb, /* unknown SMB 0xe1 */
dissect_unknown_smb, /* unknown SMB 0xe2 */
dissect_unknown_smb, /* unknown SMB 0xe3 */
dissect_unknown_smb, /* unknown SMB 0xe4 */
dissect_unknown_smb, /* unknown SMB 0xe5 */
dissect_unknown_smb, /* unknown SMB 0xe6 */
dissect_unknown_smb, /* unknown SMB 0xe7 */
dissect_unknown_smb, /* unknown SMB 0xe8 */
dissect_unknown_smb, /* unknown SMB 0xe9 */
dissect_unknown_smb, /* unknown SMB 0xea */
dissect_unknown_smb, /* unknown SMB 0xeb */
dissect_unknown_smb, /* unknown SMB 0xec */
dissect_unknown_smb, /* unknown SMB 0xed */
dissect_unknown_smb, /* unknown SMB 0xee */
dissect_unknown_smb, /* unknown SMB 0xef */
dissect_unknown_smb, /* unknown SMB 0xf0 */
dissect_unknown_smb, /* unknown SMB 0xf1 */
dissect_unknown_smb, /* unknown SMB 0xf2 */
dissect_unknown_smb, /* unknown SMB 0xf3 */
dissect_unknown_smb, /* unknown SMB 0xf4 */
dissect_unknown_smb, /* unknown SMB 0xf5 */
dissect_unknown_smb, /* unknown SMB 0xf6 */
dissect_unknown_smb, /* unknown SMB 0xf7 */
dissect_unknown_smb, /* unknown SMB 0xf8 */
dissect_unknown_smb, /* unknown SMB 0xf9 */
dissect_unknown_smb, /* unknown SMB 0xfa */
dissect_unknown_smb, /* unknown SMB 0xfb */
dissect_unknown_smb, /* unknown SMB 0xfc */
dissect_unknown_smb, /* unknown SMB 0xfd */
dissect_unknown_smb, /* SMBinvalid invalid command */
dissect_unknown_smb /* unknown SMB 0xff */
};
static const value_string errcls_types[] = {
{ SMB_SUCCESS, "Success"},
{ SMB_ERRDOS, "DOS Error"},
{ SMB_ERRSRV, "Server Error"},
{ SMB_ERRHRD, "Hardware Error"},
{ SMB_ERRCMD, "Command Error - Not an SMB format command"},
{ 0, 0}
};
char *decode_smb_name(unsigned char cmd)
{
return(SMB_names[cmd]);
}
static const value_string DOS_errors[] = {
{SMBE_badfunc, "Invalid function (or system call)"},
{SMBE_badfile, "File not found (pathname error)"},
{SMBE_badpath, "Directory not found"},
{SMBE_nofids, "Too many open files"},
{SMBE_noaccess, "Access denied"},
{SMBE_badfid, "Invalid fid"},
{SMBE_nomem, "Out of memory"},
{SMBE_badmem, "Invalid memory block address"},
{SMBE_badenv, "Invalid environment"},
{SMBE_badaccess, "Invalid open mode"},
{SMBE_baddata, "Invalid data (only from ioctl call)"},
{SMBE_res, "Reserved error code?"},
{SMBE_baddrive, "Invalid drive"},
{SMBE_remcd, "Attempt to delete current directory"},
{SMBE_diffdevice, "Rename/move across different filesystems"},
{SMBE_nofiles, "no more files found in file search"},
{SMBE_badshare, "Share mode on file conflict with open mode"},
{SMBE_lock, "Lock request conflicts with existing lock"},
{SMBE_unsup, "Request unsupported, returned by Win 95"},
{SMBE_filexists, "File in operation already exists"},
{SMBE_cannotopen, "Cannot open the file specified"},
{SMBE_unknownlevel, "Unknown level??"},
{SMBE_badpipe, "Named pipe invalid"},
{SMBE_pipebusy, "All instances of pipe are busy"},
{SMBE_pipeclosing, "Named pipe close in progress"},
{SMBE_notconnected, "No process on other end of named pipe"},
{SMBE_moredata, "More data to be returned"},
{SMBE_baddirectory, "Invalid directory name in a path."},
{SMBE_eas_didnt_fit, "Extended attributes didn't fit"},
{SMBE_eas_nsup, "Extended attributes not supported"},
{SMBE_notify_buf_small, "Buffer too small to return change notify."},
{SMBE_unknownipc, "Unknown IPC Operation"},
{SMBE_noipc, "Don't support ipc"},
{0, 0}
};
/* Error codes for the ERRSRV class */
static const value_string SRV_errors[] = {
{SMBE_error, "Non specific error code"},
{SMBE_badpw, "Bad password"},
{SMBE_badtype, "Reserved"},
{SMBE_access, "No permissions to perform the requested operation"},
{SMBE_invnid, "TID invalid"},
{SMBE_invnetname, "Invalid network name. Service not found"},
{SMBE_invdevice, "Invalid device"},
{SMBE_unknownsmb, "Unknown SMB, from NT 3.5 response"},
{SMBE_qfull, "Print queue full"},
{SMBE_qtoobig, "Queued item too big"},
{SMBE_qeof, "EOF on print queue dump"},
{SMBE_invpfid, "Invalid print file in smb_fid"},
{SMBE_smbcmd, "Unrecognised command"},
{SMBE_srverror, "SMB server internal error"},
{SMBE_filespecs, "Fid and pathname invalid combination"},
{SMBE_badlink, "Bad link in request ???"},
{SMBE_badpermits, "Access specified for a file is not valid"},
{SMBE_badpid, "Bad process id in request"},
{SMBE_setattrmode, "Attribute mode invalid"},
{SMBE_paused, "Message server paused"},
{SMBE_msgoff, "Not receiving messages"},
{SMBE_noroom, "No room for message"},
{SMBE_rmuns, "Too many remote usernames"},
{SMBE_timeout, "Operation timed out"},
{SMBE_noresource, "No resources currently available for request."},
{SMBE_toomanyuids, "Too many userids"},
{SMBE_baduid, "Bad userid"},
{SMBE_useMPX, "Temporarily unable to use raw mode, use MPX mode"},
{SMBE_useSTD, "Temporarily unable to use raw mode, use standard mode"},
{SMBE_contMPX, "Resume MPX mode"},
{SMBE_badPW, "Bad Password???"},
{SMBE_nosupport, "Operation not supported???"},
{ 0, 0}
};
/* Error codes for the ERRHRD class */
static const value_string HRD_errors[] = {
{SMBE_nowrite, "read only media"},
{SMBE_badunit, "Unknown device"},
{SMBE_notready, "Drive not ready"},
{SMBE_badcmd, "Unknown command"},
{SMBE_data, "Data (CRC) error"},
{SMBE_badreq, "Bad request structure length"},
{SMBE_seek, "Seek error???"},
{SMBE_badmedia, "Bad media???"},
{SMBE_badsector, "Bad sector???"},
{SMBE_nopaper, "No paper in printer???"},
{SMBE_write, "Write error???"},
{SMBE_read, "Read error???"},
{SMBE_general, "General error???"},
{SMBE_badshare, "A open conflicts with an existing open"},
{SMBE_lock, "Lock/unlock error"},
{SMBE_wrongdisk, "Wrong disk???"},
{SMBE_FCBunavail, "FCB unavailable???"},
{SMBE_sharebufexc, "Share buffer excluded???"},
{SMBE_diskfull, "Disk full???"},
{0, 0}
};
char *decode_smb_error(guint8 errcls, guint8 errcode)
{
switch (errcls) {
case SMB_SUCCESS:
return("No Error"); /* No error ??? */
break;
case SMB_ERRDOS:
return(val_to_str(errcode, DOS_errors, "Unknown DOS error (%x)"));
break;
case SMB_ERRSRV:
return(val_to_str(errcode, SRV_errors, "Unknown SRV error (%x)"));
break;
case SMB_ERRHRD:
return(val_to_str(errcode, HRD_errors, "Unknown HRD error (%x)"));
break;
default:
return("Unknown error class!");
}
}
#define SMB_FLAGS_DIRN 0x80
void
dissect_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
{
proto_tree *smb_tree = tree, *flags_tree, *flags2_tree;
proto_item *ti, *tf;
guint8 cmd, errcls, errcode1, flags;
guint16 flags2, errcode, tid, pid, uid, mid;
int SMB_offset = offset;
struct smb_info si;
cmd = pd[offset + SMB_hdr_com_offset];
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "SMB");
/* Hmmm, poor coding here ... Also, should check the type */
if (check_col(fd, COL_INFO)) {
col_add_fstr(fd, COL_INFO, "%s %s", decode_smb_name(cmd), (pi.match_port == pi.destport)? "Request" : "Response");
}
if (tree) {
ti = proto_tree_add_item(tree, proto_smb, offset, END_OF_FRAME, NULL);
smb_tree = proto_item_add_subtree(ti, ett_smb);
/* 0xFFSMB is actually a 1 byte msg type and 3 byte server
* component ... SMB is only one used
*/
proto_tree_add_text(smb_tree, offset, 1, "Message Type: 0xFF");
proto_tree_add_text(smb_tree, offset+1, 3, "Server Component: SMB");
}
offset += 4; /* Skip the marker */
if (tree) {
proto_tree_add_text(smb_tree, offset, 1, "Command: %s", decode_smb_name(cmd));
}
offset += 1;
/* Next, look at the error class, SMB_RETCLASS */
errcls = pd[offset];
if (tree) {
proto_tree_add_text(smb_tree, offset, 1, "Error Class: %s",
val_to_str((guint8)pd[offset], errcls_types, "Unknown Error Class (%x)"));
}
offset += 1;
/* Error code, SMB_HEINFO ... */
errcode1 = pd[offset];
if (tree) {
proto_tree_add_text(smb_tree, offset, 1, "Reserved: %i", errcode1);
}
offset += 1;
errcode = GSHORT(pd, offset);
if (tree) {
proto_tree_add_text(smb_tree, offset, 2, "Error Code: %s",
decode_smb_error(errcls, errcode));
}
offset += 2;
/* Now for the flags: Bit 0 = 0 means cmd, 0 = 1 means resp */
flags = pd[offset];
if (tree) {
tf = proto_tree_add_text(smb_tree, offset, 1, "Flags: 0x%02x", flags);
flags_tree = proto_item_add_subtree(tf, ett_smb_flags);
proto_tree_add_text(flags_tree, offset, 1, "%s",
decode_boolean_bitfield(flags, 0x01, 8,
"Lock&Read, Write&Unlock supported",
"Lock&Read, Write&Unlock not supported"));
proto_tree_add_text(flags_tree, offset, 1, "%s",
decode_boolean_bitfield(flags, 0x02, 8,
"Receive buffer posted",
"Receive buffer not posted"));
proto_tree_add_text(flags_tree, offset, 1, "%s",
decode_boolean_bitfield(flags, 0x08, 8,
"Path names caseless",
"Path names case sensitive"));
proto_tree_add_text(flags_tree, offset, 1, "%s",
decode_boolean_bitfield(flags, 0x10, 8,
"Pathnames canonicalized",
"Pathnames not canonicalized"));
proto_tree_add_text(flags_tree, offset, 1, "%s",
decode_boolean_bitfield(flags, 0x20, 8,
"OpLocks requested/granted",
"OpLocks not requested/granted"));
proto_tree_add_text(flags_tree, offset, 1, "%s",
decode_boolean_bitfield(flags, 0x40, 8,
"Notify all",
"Notify open only"));
proto_tree_add_text(flags_tree, offset, 1, "%s",
decode_boolean_bitfield(flags, SMB_FLAGS_DIRN,
8, "Response to client/redirector", "Request to server"));
}
offset += 1;
flags2 = GSHORT(pd, offset);
if (tree) {
tf = proto_tree_add_text(smb_tree, offset, 1, "Flags2: 0x%04x", flags2);
flags2_tree = proto_item_add_subtree(tf, ett_smb_flags2);
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x0001, 16,
"Long file names supported",
"Long file names not supported"));
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x0002, 16,
"Extended attributes supported",
"Extended attributes not supported"));
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x0004, 16,
"Security signatures supported",
"Security signatures not supported"));
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x0800, 16,
"Extended security negotiation supported",
"Extended security negotiation not supported"));
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x1000, 16,
"Resolve pathnames with DFS",
"Don't resolve pathnames with DFS"));
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x2000, 16,
"Permit reads if execute-only",
"Don't permit reads if execute-only"));
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x4000, 16,
"Error codes are NT error codes",
"Error codes are DOS error codes"));
proto_tree_add_text(flags2_tree, offset, 1, "%s",
decode_boolean_bitfield(flags2, 0x8000, 16,
"Strings are Unicode",
"Strings are ASCII"));
}
offset += 2;
if (tree) {
proto_tree_add_text(smb_tree, offset, 12, "Reserved: 6 WORDS");
}
offset += 12;
/* Now the TID, tree ID */
tid = GSHORT(pd, offset);
si.tid = tid;
if (tree) {
proto_tree_add_text(smb_tree, offset, 2, "Network Path/Tree ID (TID): %i (%04x)", tid, tid);
}
offset += 2;
/* Now the PID, Process ID */
pid = GSHORT(pd, offset);
si.pid = pid;
if (tree) {
proto_tree_add_text(smb_tree, offset, 2, "Process ID (PID): %i (%04x)", pid, pid);
}
offset += 2;
/* Now the UID, User ID */
uid = GSHORT(pd, offset);
si.uid = uid;
if (tree) {
proto_tree_add_text(smb_tree, offset, 2, "User ID (UID): %i (%04x)", uid, uid);
}
offset += 2;
/* Now the MID, Multiplex ID */
mid = GSHORT(pd, offset);
si.mid = mid;
if (tree) {
proto_tree_add_text(smb_tree, offset, 2, "Multiplex ID (MID): %i (%04x)", mid, mid);
}
offset += 2;
/* Now vector through the table to dissect them */
(dissect[cmd])(pd, offset, fd, tree, smb_tree, si, max_data, SMB_offset, errcode,
((flags & 0x80) == 0));
}
void
proto_register_smb(void)
{
/* static hf_register_info hf[] = {
{ &variable,
{ "Name", "smb.abbreviation", TYPE, VALS_POINTER }},
};*/
static gint *ett[] = {
&ett_smb,
&ett_smb_fileattributes,
&ett_smb_capabilities,
&ett_smb_aflags,
&ett_smb_dialects,
&ett_smb_mode,
&ett_smb_rawmode,
&ett_smb_flags,
&ett_smb_flags2,
&ett_smb_desiredaccess,
&ett_smb_search,
&ett_smb_file,
&ett_smb_openfunction,
&ett_smb_filetype,
&ett_smb_action,
&ett_smb_writemode,
&ett_smb_lock_type,
&ett_browse,
&ett_browse_flags,
&ett_browse_election_criteria,
&ett_browse_election_os,
&ett_browse_election_desire
};
proto_smb = proto_register_protocol("Server Message Block Protocol", "smb");
proto_browse = proto_register_protocol("Microsoft Windows Browser Protocol", "browser");
/* proto_register_field_array(proto_smb, hf, array_length(hf));*/
proto_register_subtree_array(ett, array_length(ett));
register_init_routine(&smb_init_protocol);
}
- Follow-Ups:
- Re: [ethereal-dev] Packet-smb patch
- From: Richard Sharpe
- Re: [ethereal-dev] Packet-smb patch
- Prev by Date: Re: [ethereal-dev] Problem with packet-stat.c
- Next by Date: Re: [ethereal-dev] Problem with packet-stat.c
- Previous by thread: Re: [ethereal-dev] Problem with packet-stat.c
- Next by thread: Re: [ethereal-dev] Packet-smb patch
- Index(es):





