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):