Clients exchange messages with a server to access resources on that server. These messages are called Server Message Blocks (SMBs), and every SMB message has a common format.
This section describes the entire set of SMB commands and responses exchanged between CIFS clients and servers. It also details which SMBs are introduced into the protocol as higher dialect levels are negotiated.
This specification makes use of "C"-like notation to describe the formats of messages. Unlike the "C" language, which allows implementation flexibility in laying out structures, this specification adopts the following rules. Multi-byte values are always transmitted least significant byte first. All fields, except "bit-fields," are aligned on the nearest byte boundary (even if longer than a byte), and there is no implicit padding. Fields using the "bit field" notation are defined to be laid out within the structure with the first-named field occupying the lowest order bits, the next named field the next lowest order bits, and so on.
Although each SMB command has specific encodings, some fields in the SMB header have meaning to all SMBs. These fields and considerations are described in the following sections:
typedef unsigned char UCHAR; // 8 unsigned bits
typedef unsigned short USHORT; // 16 unsigned bits
typedef unsigned long ULONG; // 32 unsigned bits
typedef struct {
ULONG LowPart;
LONG HighPart;
} LARGE_INTEGER; // 64 bits of data
typedef struct {
UCHAR Protocol[4]; // Contains 0xFF,'SMB'
UCHAR Command; // Command code
union {
struct {
UCHAR ErrorClass; // Error class
UCHAR Reserved; // Reserved for future use
USHORT Error; // Error code
} DosError;
ULONG Status; // 32-bit error code
} Status;
UCHAR Flags; // Flags
USHORT Flags2; // More flags
union {
USHORT Pad[6]; // Ensure section is 12 bytes long
struct {
USHORT PidHigh; // High part of PID
UCHAR SecuritySignature[8]; // reserved for security
} Extra;
};
USHORT Tid; // Tree identifier
USHORT Pid; // Caller's process id
USHORT Uid; // Unauthenticated user id
USHORT Mid; // multiplex id
UCHAR WordCount; // Count of parameter words
USHORT ParameterWords[ WordCount ]; // The parameter words
USHORT ByteCount; // Count of bytes
UCHAR Buffer[ ByteCount ]; // The bytes
} SMB_HEADER;
All SMBs in this specification have identical format up to the ParameterWords fields. (Some obsolescent ones do not.) Different SMBs have a different number and interpretation of ParameterWords and Buffer. All reserved fields in the SMB header must be zero.
Note Command is the operation code that this SMB is requesting or responding to.
This field contains eight individual flags, numbered from least significant to most significant, which have the following meanings:
Bit == |
Meaning ============================ |
Earliest Dialect ============== |
0 | Reserved for obsolescent requests. (LOCK_AND_READ, WRITE_AND_CLOSE) | LANMAN1.0 |
1 | Reserved (must be zero). | |
2 | Reserved (must be zero). | |
3 | When on, all pathnames in this SMB must be treated as case-less. When off, the pathnames are case-sensitive. | LANMAN1.0 |
4 | Reserved (clients must send as zero; servers must ignore). | |
5 | Reserved for obsolescent requests. (SMB_COM_OPEN, SMB_COM_CREATE and SMB_COM_CREATE_NEW) | LANMAN1.0 |
6 | Reserved for obsolescent requests. (SMB_COM_OPEN, SMB_COM_CREATE and SMB_COM_CREATE_NEW) | LANMAN1.0 |
7 | SMB_FLAGS_SERVER_TO_REDIR. When on, this SMB is being sent from the server in response to a client request. The Command field usually contains the same value in a protocol request from the client to the server as in the matching response from the server to the client. This bit unambiguously distinguishes the command request from the command response. | PC NETWORK PROGRAM 1.0 |
This field contains six individual flags that are defined below and numbered from least significant bit to most significant bit. Flags that are not defined must be set to zero.
Bit == |
Meaning ============================ |
Earliest Dialect ============= |
0 | If set in a request, the server may return long components in path names in the response. | |
1 | If set, the client is aware of extended attributes. | |
11 | If set, the client is aware of Extended Security | NT LM 0.12 |
12 | If set, any request pathnames in this SMB should be resolved in the Distributed File System. | NT LM 0.12 |
13 | If set, indicates that a read will be permitted if the client does not have read permission but does have execute permission. This flag is only useful on a read request. | |
14 | If set, specifies that the returned error code is a 32-bit error code in Status.Status. Otherwise, the Status.DosError.ErrorClass and Status.DosError.Error fields contain the DOS-style error information. When passing NT status codes is negotiated, this flag should be set for every SMB. | NT LM 0.12 |
15 | If set, any fields of datatype STRING in this SMB message are encoded as UNICODE. Otherwise, they are in ASCII. | NT LM 0.12 |
Tid represents an instance of an authenticated connection to a server resource. The server returns Tid to the client when the client successfully connects to a resource, and the client uses Tid in subsequent requests referring to the resource.
In most SMB requests, Tid must contain a valid value. Exceptions include prior to getting a Tid established, including SMB_COM_NEGOTIATE, SMB_COM_TREE_CONNECT, SMB_COM_ECHO,
and SMB_COM_SESSION_SETUP_ANDX. 0xFFFF
should be used for Tid for these situations. The server is always responsible for enforcing use of a valid Tid where appropriate.
Pid is the caller's process id, and is generated by the client to uniquely identify a process within the client computer. Concurrency control is associated with Pid (and PidHigh)—sharing modes, and locks are arbitrated using the Pid. For example, if a file is successfully opened for exclusive access, subsequent opens from other clients or from the same client with a different Pid will be refused.
Clients inform servers of the creation of a new process by simply introducing a new Pid value into the dialogue for new processes. The client operating system must ensure that the appropriate close and cleanup SMBs will be sent when the last process referencing a file closes it. From the server's point of view, there is no concept of Fids "belonging to" processes. A Fid returned by the server to one process may be used by any other process using the same transport connection and Tid.
It is up to the client operating system to ensure that only authorized client processes gain access to Fids (and Tids). On SMB_COM_TREE_DISCONNECT (or when the client and server session is terminated) with a given Tid, the server will invalidate any files opened by any process on that client.
Uid is a user ID assigned by the server after a user authenticates to it, and that will be associated with that user until the client requests the association be broken. After authentication to the server, the client should make sure that the Uid is not used for a different user than the one who authenticated. (It is permitted that a single user have more than one Uid.) Requests that do authorization, such as open requests, will perform access checks using the identity associated with the Uid.
The multiplex ID (Mid) is used along with Pid to allow multiplexing the single client and server connection among the client's multiple processes, threads, and requests per thread. Clients may have many outstanding requests (up to the negotiated number) at one time. Servers may respond to requests in any order, but a response message must always contain the same Mid and Pid values as the corresponding request message. The client must not have multiple outstanding requests to a server with the same Mid and Pid.
An SMB returns error information to the client in the Status field. Protocol dialects prior to NT LM 0.12
return status to the client using the combination of Status.DosError.ErrorClass and Status.DosError.Error. Beginning with NT LM 0.12,
CIFS servers can return 32-bit error information to clients using Status.Status, if the incoming client SMB has bit 14 set in the Flags2 field of the SMB header. Contents of response parameters are not guaranteed in the case of an error return and must be ignored. For write-behind activity, a subsequent write or close of the file may return the fact that a previous write failed. Normally, write-behind failures are limited to hard disk errors and device out of space.
In general, SMBs are not expected to block at the server; they should return "immediately." But some SMB requests do indicate timeout periods for the completion of the request on the server. If a server implementation cannot support timeouts, an error can be returned just as if a timeout had occurred—if the resource is not available immediately upon request.
The data portion of SMBs typically contains the data to be read or written, file paths, or directory paths. The format of the data portion depends on the message. All fields in the data portion have the same format, which in every case consists of an identifier byte followed by the data.
Identifier ============= |
Description ===================== |
Value ==== |
Data Block
Dialect Pathname ASCII Variable block |
See Below
Null terminated String Null terminated String Null terminated String See Below |
1
2 3 4 5 |
When the identifier indicates a data block or variable block then the format is a word indicating the length followed by the data.
In all dialects prior to NT LM 0.12
, all strings are encoded in ASCII. If the agreed dialect is NT LM 0.12
or later, Unicode strings may be exchanged. Unicode strings include file names, resource names, and user names. This applies to null-terminated strings, length specified strings, and the type-prefixed strings. In all cases where a string is passed in Unicode format, the Unicode string must be word-aligned with respect to the beginning of the SMB. Should the string not naturally fall on a two-byte boundary, a null byte of padding will be inserted, and the Unicode string will begin at the next address. In the description of the SMBs, items that may be encoded in Unicode or ASCII are labeled as STRING. If the encoding is ASCII, even if the negotiated string is Unicode, the quantity is labeled as UCHAR.
For type-prefixed Unicode strings, the padding byte is found after the type byte. The type byte is 4 (indicating SMB_FORMAT_ASCII), independent of whether the string is ASCII or Unicode. For strings whose start addresses are found using offsets within the fixed part of the SMB (as opposed to simply being found at the byte following the preceding field), it is guaranteed that the offset will be properly aligned.
Strings that are never passed in Unicode are:
When Unicode is negotiated, bit 15 should be set in the Flags2 field of every SMB header.
Despite the flexible encoding scheme, no field of a data portion may be omitted or included out of order. In addition, neither a WordCount nor ByteCount of value 0 at the end of a message may be omitted.
File names in the CIFS protocol consist of components separated by a backslash ('\'). Early clients of the CIFS protocol required that the name components adhere to an 8.3 format name. These names consist of two parts: a basename of no more than 8 characters, and an extension of no more than 3 characters. The basename and extension are separated by a '.'. All characters are legal in the basename and extension except the space character (0x20) and:
" . / \[]:+|<>=;,*?
If the client has indicated long name support by setting bit2 in the Flags2 field of the SMB header, this indicates that the client is not bound by the 8.3 convention. Specifically, this indicates that any SMB that returns file names to the client may return names that do not adhere to the 8.3 convention, and have a total length of up to 255 characters. This capability was introduced with the LM1.2X002
protocol dialect.
Some SMB requests allow wildcards to be given for the filename. The wildcard allows a number of files to be operated on as a unit without having to separately enumerate the files and individually operate on each one from the client.
If the client is using 8.3 names, each part of the name ( base (8) or extension (3) ) is treated separately. For long filenames, the . in the name is significant even though there is no longer a restriction on the size of each of the components.
The ? character is a wild card for a single character. If a filename part commences with one or more "?"s, then exactly that number of characters will be matched by the wildcards, e.g., "??x" equals "abx" but not "abcx" or "ax." When a filename part has trailing "?"s, then it matches the specified number of characters or less, e.g., "x??" matches "xab," "xa" and "x," but not "xabc." If only "?"s are present in the filename part, then it is handled as for trailing "?"s.
The * character matches an entire part of the name, as does an empty specification for that part. A part consisting of * means that the rest of the component should be filled with ?, and the search should be performed with this wildcard character. For example, "*.abc" or ".abc" match any file with an extension of "abc". "*.*," "*" or "null" match all files in a directory.
If the negotiated dialect is "NT LM 0.12"
or later, and the client requires MS-DOS wildcard matching semantics, UNICODE wildcards should be translated according to the following rules:
The translation can be performed in-place.
A Dfs pathname adheres to the standard described in the FileNames section. A Dfs-enabled client accessing a Dfs share should set the Flags2 bit 12 in all name-based SMB requests indicating to the server that the enclosed pathname should be resolved in the Distributed File System namespace. The pathname should always have the full file name, including the server name and share name. If the server can resolve the Dfs name to a piece of local storage, the local storage will be accessed. If the server determines that the Dfs name actually maps to a different server share, the access to the name will fail with the 32-bit status STATUS_PATH_NOT_COVERED (0xC0000257), or DOS error ERRsrv/ERRbadpath.
On receiving this error, the Dfs-enabled client should ask the server for a referral (see TRANS2_GET_DFS_REFERRAL). The referral request should contain the full file name.
The response to the request will contain a list of server and share names to try, and the part of the request file name that junctions to the list of server shares. If the ServerType field of the referral is set to 1 (SMB server), then the client should resubmit the request with the original file name to one of the server shares in the list, once again setting the Flags2 bit 12 bit in the SMB. If the ServerType field is not 1, then the client should strip off the part of the file name that junctions to the server share before resubmitting the request to one of servers in the list.
A response to a referral request may elicit a response that does not have the StorageServers bit set. In that case, the client should resubmit the referral request to one of the servers in the list, until it finally obtains a referral response that has the StorageServers bit set, at which point the client can resubmit the request SMB to one of the listed server shares.
If, after getting a referral with the StorageServers bit set and resubmitting the request to one of the server shares in the list, the server fails the request with STATUS_PATH_NOT_COVERED, there must be an inconsistency between the view of the Dfs namespace held by the server granting the referral and the server listed in that referral. In this case, the client may inform the server granting the referral of this inconsistency via the TRANS2_REPORT_DFS_INCONSISTENCY SMB.
When SMB requests or responses encode time values, the following describes the various encodings used.
struct {
USHORT Day : 5;
USHORT Month : 4;
USHORT Year : 7;
} SMB_DATE;
The Year field has a range of 0-119, which represents years 1980-2099. The Month is encoded as 1-12, and the day ranges from 1-31
struct {
USHORT TwoSeconds : 5;
USHORT Minutes : 6;
USHORT Hours : 5;
} SMB_TIME;
Hours ranges from 0-23, Minutes range from 0-59, and TwoSeconds ranges from 0-29 representing two-second increments within the minute.
typedef struct {
ULONG LowTime;
LONG HighTime;
} TIME;
TIME indicates a signed 64-bit integer representing either an absolute time or a time interval. Times are specified in units of 100ns. A positive value expresses an absolute time, where the base time (the 64-bit integer with value 0) is the beginning of the year 1601 AD in the Gregorian calendar. A negative value expresses a time interval relative to some base time, usually the current time.
typedef unsigned long UTIME;
UTIME is the number of seconds since Jan 1, 1970, 00:00:00.0.
Various client requests and server responses, such as SMB_COM_OPEN, pass file access modes encoded into a USHORT. The encoding of these is as follows:
1111 11
5432 1098 7654 3210
rWrC rLLL rSSS rAAA
where:
W—Write through mode. No read ahead or write behind allowed on
this file or device. When the response is returned, data is
expected to be on the disk or device.
S—Sharing mode:
0—Compatibility mode
1—Deny read/write/execute (exclusive)
2—Deny write
3—Deny read/execute
4—Deny none
A—Access mode
0—Open for reading
1—Open for writing
2—Open for reading and writing
3—Open for execute
rSSSrAAA = 11111111 (hex FF) indicates file control block (FCB) open (???)
C—Cache mode
0—Normal file
1—Do not cache this file
L—Locality of reference
0—Locality of reference is unknown
1—Mainly sequential access
2—Mainly random access
3—Random access with some locality
4 to 7—Currently undefined
The ACCESS_MASK structure is one 32-bit value containing standard, specific, and generic rights. These rights are used in access-control entries (ACEs) and are the primary means of specifying the requested or granted access to an object.
The bits in this value are allocated as follows:
Bits | Meaning |
0 -15 | Specific rights. Contains the access mask specific to the object type associated with the mask. |
16-23 | Standard rights. Contains the object's standard access rights and can be a combination of the following predefined flags: |
Bit | Flag | Meaning |
16 | DELETE | Delete access |
17 | READ_CONTROL | Read access to the owner, group, and discretionary access-control list (ACL) of the security descriptor |
18 | WRITE_DAC | Write access to the discretionary access-control list (ACL) |
19 | WRITE_OWNER | Write access to owner |
20 | SYNCHRONIZE | Microsoft® Windows NT®: Synchronize access |
Bits | Meaning |
24 | Access system security (ACCESS_SYSTEM_SECURITY). This flag is not a typical access type. It is used to indicate access to a system ACL. This type of access requires the calling process to have a specific privilege. |
25 | Maximum allowed (MAXIMUM_ALLOWED) |
26, 27 | Reserved |
28 | Generic all (GENERIC_ALL) |
29 | Generic execute (GENERIC_EXECUTE) |
30 | Generic write (GENERIC_WRITE) |
31 | Generic read (GENERIC_READ) |
OpenFunction specifies the action to be taken depending on whether or not the file exists. This word has the following format:
bits:
1111 11
5432 1098 7654 3210
rrrr rrrr rrrC rrOO
where:
C—Create (action to be taken if file does not exist).
0—Fail.
1—Create file.
r—reserved (must be zero).
O—Open (action to be taken if file exists).
0—Fail.
1—Open file.
2—Truncate file.
Action in the response to an open or create request describes the action taken as a result of the request. It has the following format:
bits:
1111 11
5432 1098 7654 3210
Lrrr rrrr rrrr rrOO
where:
L—Lock (single user total file lock status).
0—file opened by another user (or mode not supported by server).
1—file is opened only by this user at the present time.
r—reserved (must be zero).
O—Open (action taken on Open).
1—The file existed and was opened.
2—The file did not exist but was created.
3—The file existed and was truncated.
When SMB messages exchange file attribute information, it is encoded in 16 bits as:
Value ===== |
Description ================= |
0x01 | Read only file |
0x02 | Hidden file |
0x04 | System file |
0x08 | Volume |
0x10 | Directory |
0x20 | Archive file |
others | Reserved—must be 0 |
The extended file attributes is a 32-bit value composed of attributes and flags.
Any combination of the following attributes is acceptable, except all other file attributes override FILE_ATTR_NORMAL:
Name
=========== |
Value
=== |
Meaning
=============================== |
ATTR_ARCHIVE | 0x020 | The file has not been archived since it was last modified. Applications use this attribute to mark files for backup or removal. |
ATTR_COMPRESSED | 0x800 | The file or directory is compressed. For a file, this means that all of the data in the file is compressed. For a directory, this means that compression is the default for newly created files and subdirectories. |
ATTR_NORMAL | 0x080 | The file has no other attributes set. This attribute is valid only if used alone. |
ATTR_HIDDEN | 0x002 | The file is hidden. It is not to be included in an ordinary directory listing. |
ATTR_READONLY | 0x001 | The file is read only. Applications can read the file but cannot write to it or delete it. |
ATTR_TEMPORARY | 0x100 | The file is temporary |
ATTR_DIRECTORY | 0x010 | The file is a directory |
ATTR_SYSTEM | 0x004 | The file is part of or is used exclusively by the operating system. |
Any combination of the following flags is acceptable:
Name
============ |
Value
======= |
Meaning
=========================== |
WRITE_THROUGH | 0x80000000 | Instructs the operating system to write through any intermediate cache and go directly to the file. The operating system can still cache write operations, but cannot lazily flush them. |
NO_BUFFERING | 0x20000000 | Requests the server to open the file with no intermediate buffering or caching; the server is not obliged to honor the request. An application must meet certain requirements when working with files opened with FILE_FLAG_NO_BUFFERING. File access must begin at offsets within the file that are integer multiples of the volume's sector size, and must be for numbers of bytes that are integer multiples of the volume's sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes. |
RANDOM_ACCESS | 0x10000000 | Indicates that the application intends to access the file randomly. The server may use this flag to optimize file caching. |
SEQUENTIAL_SCAN | 0x08000000 | Indicates that the file is to be accessed sequentially from beginning to end. Windows uses this flag to optimize file caching. If an application moves the file pointer for random access, optimum caching may not occur; however, correct operation is still guaranteed. Specifying this flag can increase performance for applications that read large files using sequential access. Performance gains can be even more noticeable for applications that read large files mostly sequentially, but occasionally skip over small ranges of bytes. |
DELETE_ON_CLOSE | 0x04000000 | Requests that the server delete the file immediately after all its handles have been closed. |
BACKUP_SEMANTICS | 0x02000000 | Indicates that the file is being opened or created for a backup or restore operation. The server should allow the client to override normal file security checks, provided it has the necessary permission to do so. |
POSIX_SEMANTICS | 0x01000000 | Indicates that the file is to be accessed according to POSIX rules. This includes allowing multiple files with names differing only in case, for file systems that support such naming. (Use care when using this option because files created with this flag may not be accessible by applications written for MS-DOS, Windows 3.x, or Windows NT.) |
LANMAN1.0
and later dialects of the CIFS protocol allow multiple SMB requests to be sent in one message to the server. Messages of this type are called AndX SMBs, and they obey the following rules:
The "transaction" style subprotocols are used for commands that potentially need to transfer a large amount of data (greater than 64K bytes).
Primary Client Request ================= |
Description ============================= |
Command | SMB_COM_TRANSACTION2 |
UCHAR WordCount; | Count of parameter words; value = (14 + SetupCount) |
USHORT TotalParameterCount; | Total parameter bytes being sent |
USHORT TotalDataCount; | Total data bytes being sent |
USHORT MaxParameterCount; | Max parameter bytes to return |
USHORT MaxDataCount; | Max data bytes to return |
UCHAR MaxSetupCount; | Max setup words to return |
UCHAR Reserved; | |
USHORT Flags; | Additional information: |
bit 0—also disconnect TID in TID | |
ULONG Timeout; | |
USHORT Reserved2; | |
USHORT ParameterCount; | Parameter bytes sent this buffer |
USHORT ParameterOffset; | Offset (from header start) to Parameters |
USHORT DataCount; | Data bytes sent this buffer |
USHORT DataOffset; | Offset (from header start) to data |
UCHAR SetupCount; | Count of setup words |
UCHAR Reserved3; | Reserved (pad above to word) |
USHORT Setup[SetupCount]; | Setup words (# = SetupWordCount) |
USHORT ByteCount; | Count of data bytes |
STRING Name[]; | Must be NULL |
UCHAR Pad[]; | Pad to SHORT or LONG |
UCHAR Parameters[ ParameterCount]; | Parameter bytes (# = ParameterCount) |
UCHAR Pad1[]; | Pad to SHORT or LONG |
UCHAR Data[ DataCount ]; | Data bytes (# = DataCount) |
Interim Server Response ================= |
Description ============================= |
UCHAR WordCount; | Count of parameter words = 0 |
USHORT ByteCount; | Count of data bytes = 0 |
Secondary Client Request ================= |
Description ============================= |
Command | SMB_COM_TRANSACTION_SECONDARY |
UCHAR WordCount; | Count of parameter words = 8 |
USHORT TotalParameterCount; | Total parameter bytes being sent |
USHORT TotalDataCount; | Total data bytes being sent |
USHORT ParameterCount; | Parameter bytes sent this buffer |
USHORT ParameterOffset; | Offset (from header start) to Parameters |
USHORT ParameterDisplacement; | Displacement of these Parameter bytes |
USHORT DataCount; | Data bytes sent this buffer |
USHORT DataOffset; | Offset (from header start) to data |
USHORT DataDisplacement; | Displacement of these data bytes |
USHORT Fid; | FID for handle-based requests, else 0xFFFF . This field is present only if this is an SMB_COM_TRANSACTION2 request. |
USHORT ByteCount; | Count of data bytes |
UCHAR Pad[]; | Pad to SHORT or LONG |
UCHAR Parameters[ParameterCount]; | Parameter bytes (# = ParameterCount) |
UCHAR Pad1[]; | Pad to SHORT or LONG |
UCHAR Data[DataCount]; | Data bytes (# = DataCount) |
Server Response ================== |
Description ============================= |
UCHAR WordCount; | Count of data bytes; value = 10 + SetupCount |
USHORT TotalParameterCount; | Total parameter bytes being sent |
USHORT TotalDataCount; | Total data bytes being sent |
USHORT Reserved; | |
USHORT ParameterCount; | Parameter bytes sent this buffer |
USHORT ParameterOffset; | Offset (from header start) to Parameters |
USHORT ParameterDisplacement; | Displacement of these Parameter bytes |
USHORT DataCount; | Data bytes sent this buffer |
USHORT DataOffset; | Offset (from header start) to data |
USHORT DataDisplacement; | Displacement of these data bytes |
UCHAR SetupCount; | Count of setup words |
UCHAR Reserved2; | Reserved (pad above to word) |
USHORT Setup[SetupWordCount]; | Setup words (# = SetupWordCount) |
USHORT ByteCount; | Count of data bytes |
UCHAR Pad[]; | Pad to SHORT or LONG |
UCHAR Parameters[ParameterCount]; | Parameter bytes (# = ParameterCount) |
UCHAR Pad1[]; | Pad to SHORT or LONG |
UCHAR Data[DataCount]; | Data bytes (# = DataCount) |
Primary Client Request ================== |
Description ============================= |
UCHAR WordCount; | Count of parameter words; value = (19 + SetupCount) |
UCHAR MaxSetupCount; | Max setup words to return |
USHORT Reserved; | |
ULONG TotalParameterCount; | Total parameter bytes being sent |
ULONG TotalDataCount; | Total data bytes being sent |
ULONG MaxParameterCount; | Max parameter bytes to return |
ULONG MaxDataCount; | Max data bytes to return |
ULONG ParameterCount; | Parameter bytes sent this buffer |
ULONG ParameterOffset; | Offset (from header start) to Parameters |
ULONG DataCount; | Data bytes sent this buffer |
ULONG DataOffset; | Offset (from header start) to data |
UCHAR SetupCount; | Count of setup words |
USHORT Function; | The transaction function code |
UCHAR Buffer[1]; | |
USHORT Setup[SetupWordCount]; | Setup words |
USHORT ByteCount; | Count of data bytes |
UCHAR Pad1[]; | Pad to LONG |
UCHAR Parameters[ParameterCount]; | Parameter bytes |
UCHAR Pad2[]; | Pad to LONG |
UCHAR Data[DataCount]; Data bytes |
Interim Server Response ================== |
Description ============================ |
UCHAR WordCount; | Count of parameter words = 0 |
USHORT ByteCount; | Count of data bytes = 0 |
Secondary Client Request ================== |
Description ============================ |
UCHAR WordCount; | Count of parameter words = 18 |
UCHAR Reserved[3]; | MBZ |
ULONG TotalParameterCount; | Total parameter bytes being sent |
ULONG TotalDataCount; | Total data bytes being sent |
ULONG ParameterCount; | Parameter bytes sent this buffer |
ULONG ParameterOffset; | Offset (from header start) to Parameters |
ULONG ParameterDisplacement; | Specifies the offset from the start of the overall parameter block to the parameter bytes that are contained in this message |
ULONG DataCount; | Data bytes sent this buffer |
ULONG DataOffset; | Offset (from header start) to data |
ULONG DataDisplacement; | Specifies the offset from the start of the overall data block to the data bytes that are contained in this message. |
UCHAR Reserved1; | |
USHORT ByteCount; | Count of data bytes |
UCHAR Pad1[]; | Pad to LONG |
UCHAR Parameters[ParameterCount]; | Parameter bytes |
UCHAR Pad2[]; | Pad to LONG |
UCHAR Data[DataCount]; | Data bytes |
Server Response ================== |
Description ============================ |
UCHAR WordCount; | Count of data bytes; value = 18 + SetupCount |
UCHAR Reserved[3]; | |
ULONG TotalParameterCount; | Total parameter bytes being sent |
ULONG TotalDataCount; | Total data bytes being sent |
ULONG ParameterCount; | Parameter bytes sent this buffer |
ULONG ParameterOffset; | Offset (from header start) to Parameters |
ULONG ParameterDisplacement; | Specifies the offset from the start of the overall parameter block to the parameter bytes that are contained in this message |
ULONG DataCount; | Data bytes sent this buffer |
ULONG DataOffset; | Offset (from header start) to data |
ULONG DataDisplacement; | Specifies the offset from the start of the overall data block to the data bytes that are contained in this message. |
UCHAR SetupCount; | Count of setup words |
USHORT Setup[SetupWordCount]; | Setup words |
USHORT ByteCount; | Count of data bytes |
UCHAR Pad1[]; | Pad to LONG |
UCHAR Parameters[ParameterCount]; | Parameter bytes |
UCHAR Pad2[]; | Pad to SHORT or LONG |
UCHAR Data[DataCount]; | Data bytes |
The transaction Setup information and/or Parameters define functions specific to a particular resource on a particular server. Therefore, the functions supported are not defined by the transaction subprotocol. The transaction protocol simply provides a means of delivering them and retrieving the results.
The number of bytes needed in order to perform the transaction request may be more than will fit in a single buffer.
At the time of the request, the client knows the number of parameter and data bytes expected to be sent and passes this information to the server via the primary request (TotalParameterCount and TotalDataCount). This may be reduced by lowering the total number of bytes expected (TotalParameterCount and TotalDataCount) in each (if any) secondary request.
When the amount of parameter bytes received (total of each ParameterCount) equals the total amount of parameter bytes expected (smallest TotalParameterCount) received, the server has then received all the parameter bytes.
Likewise, when the amount of data bytes received (total of each DataCount) equals the total amount of data bytes expected (smallest TotalDataCount) received, the server has then received all the data bytes.
The parameter bytes should normally be sent first followed by the data bytes. However, the server knows where each begins and ends in each buffer by the offset fields (ParameterOffset and DataOffset) and the length fields (ParameterCount and DataCount). The displacement of the bytes (relative to start of each) is also known (ParameterDisplacement and DataDisplacement). Thus, the server is able to reassemble the parameter and data bytes should the individual requests be received out of sequence.
If all parameter bytes and data bytes fit into a single buffer, no interim response is expected, and no secondary request is sent.
The client knows the maximum amount of data bytes and parameter bytes that the server may return (from MaxParameterCount and MaxDataCount of the request). Thus, the client initializes its bytes expected variables to these values. The server then informs the client of the actual amounts being returned via each message of the server response (TotalParameterCount and TotalDataCount). The server may reduce the expected bytes by lowering the total number of bytes expected (TotalParameterCount and/or TotalDataCount) in each (any) response.
When the amount of parameter bytes received (total of each ParameterCount) equals the total amount of parameter bytes expected (smallest TotalParameterCount) received, the client has then received all the parameter bytes.
Likewise, when the amount of data bytes received (total of each DataCount) equals the total amount of data bytes expected (smallest TotalDataCount) received, the client has then received all the data bytes.
The parameter bytes should normally be returned first, followed by the data bytes. However, the client knows where each begins and ends in each buffer by the offset fields (ParameterOffset and DataOffset) and the length fields (ParameterCount and DataCount). The displacement of the bytes (relative to start of each) is also known (ParameterDisplacement and DataDisplacement). The client is able to reassemble the parameter and data bytes should the server responses be received out of sequence.
The flow for these transactions over a connection-oriented transport is:
The flow for the transaction protocol when the request parameters and data do not all fit in a single buffer is:
Client ===================== |
<-> == |
Server ====================== |
Primary TRANSACTION request |
-> |
|
|
<- |
Interim Server Response |
Secondary TRANSACTION request 1 |
-> |
|
Secondary TRANSACTION request 2 |
-> |
|
Secondary TRANSACTION request N |
-> |
|
<- |
TRANSACTION response 1 |
|
<- |
TRANSACTION response 2 |
|
<- |
TRANSACTION response m |
When the request parameters and data all fit in a single buffer, the flow for the transaction protocol is:
Client ===================== |
<-> == |
Server ====================== |
Primary TRANSACTION request |
-> |
|
|
<- |
TRANSACTION response 1 |
|
<- |
TRANSACTION response 2 |
|
<- |
TRANSACTION response m |
The primary transaction request through the final response makes up the complete transaction exchange; thus, the Tid, Pid, Uid and Mid must remain constant and can be used as appropriate by both the server and the client. Of course, other SMB requests may intervene as well.
There are (at least) three ways that actual server responses have been observed to differ from what might be expected. First, some servers will send Pad bytes to move the DataOffset to a 2- or 4-byte boundary, even if there are no data bytes. The point here is that the ByteCount must be used instead of ParameterOffset plus ParameterCount to infer the actual message length. Second, some servers always return MaxParameterCount bytes, even if the particular Transact2 has no parameter response. Finally, in case of an error, some servers send the "traditional WordCount==0/ByteCount==0" response while others generate a Transact response format.
CIFS clients and servers may exchange the following SMB messages if the "PC NETWORK PROGRAM 1.0
" dialect is negotiated:
SMB_COM_CREATE_DIRECTORY | SMB_COM_DELETE_DIRECTORY |
SMB_COM_OPEN | SMB_COM_CREATE |
SMB_COM_CLOSE | SMB_COM_FLUSH |
SMB_COM_DELETE | SMB_COM_RENAME |
SMB_COM_QUERY_INFORMATION | SMB_COM_SET_INFORMATION |
SMB_COM_READ | SMB_COM_WRITE |
SMB_COM_LOCK_BYTE_RANGE | SMB_COM_UNLOCK_BYTE_RANGE |
SMB_COM_CREATE_TEMPORARY | SMB_COM_CREATE_NEW |
SMB_COM_CHECK_DIRECTORY | SMB_COM_PROCESS_EXIT |
SMB_COM_SEEK | SMB_COM_TREE_CONNECT |
SMB_COM_TREE_DISCONNECT | SMB_COM_NEGOTIATE |
SMB_COM_QUERY_INFORMATION_DISK | SMB_COM_SEARCH |
SMB_COM_OPEN_PRINT_FILE | SMB_COM_WRITE_PRINT_FILE |
SMB_COM_CLOSE_PRINT_FILE | SMB_COM_GET_PRINT_QUEUE |
If the "LANMAN 1.0
" dialect is negotiated, all of the messages in the previous list must be supported. Clients negotiating LANMAN 1.0
and higher dialects will probably no longer send SMB_COM_PROCESS_EXIT, and the response format for SMB_COM_NEGOTIATE is modified as well. New messages introduced with the LANMAN 1.0
dialect are:
SMB_COM_LOCK_AND_READ | SMB_COM_WRITE_AND_UNLOCK |
SMB_COM_READ_RAW | SMB_COM_READ_MPX |
SMB_COM_WRITE_MPX | SMB_COM_WRITE_RAW |
SMB_COM_WRITE_COMPLETE | SMB_COM_WRITE_MPX_SECONDARY |
SMB_COM_SET_INFORMATION2 | SMB_COM_QUERY_INFORMATION2 |
SMB_COM_LOCKING_ANDX | SMB_COM_TRANSACTION |
SMB_COM_TRANSACTION_SECONDARY | SMB_COM_IOCTL |
SMB_COM_IOCTL_SECONDARY | SMB_COM_COPY |
SMB_COM_MOVE | SMB_COM_ECHO |
SMB_COM_WRITE_AND_CLOSE | SMB_COM_OPEN_ANDX |
SMB_COM_READ_ANDX | SMB_COM_WRITE_ANDX |
SMB_COM_SESSION_SETUP_ANDX | SMB_COM_TREE_CONNECT_ANDX |
SMB_COM_FIND | SMB_COM_FIND_UNIQUE |
SMB_COM_FIND_CLOSE |
The "LM1.2X002
" dialect introduces these new SMBs:
SMB_COM_TRANSACTION2 | SMB_COM_TRANSACTION2_SECONDARY |
SMB_COM_FIND_CLOSE2 | SMB_COM_LOGOFF_ANDX |
"NT LM 0.12
" dialect introduces:
SMB_COM_NT_TRANSACT | SMB_COM_NT_TRANSACT_SECONDARY |
SMB_COM_NT_CREATE_ANDX | SMB_COM_NT_CANCEL |
SMB_COM_NT_RENAME |