Implementing CIFS: The Common Internet File System
12.1 The SMB_HEADER.STATUS Field Exposed
Things get interesting starting at the STATUS field. It wouldn't be so bad except for the fact that there are two possible error code formats to consider. There is the DOS and OS/2 format, and then there is the NT_STATUS format. In C language terms, the STATUS field looks something like this: typedef union { ulong NT_Status; struct { uchar ErrorClass; uchar reserved; ushort ErrorCode; } DosError; } Status; From the client side, one way to deal with the split personality problem is to use the DOS codes exclusively. [1] These are fairly well documented (by SMB standards), and should be supported by all SMB servers. Using DOS codes is probably a good choice, but there is a catch... there are some advanced features which simply don't work unless the client negotiates NT_STATUS codes. [1] This is exactly what jCIFS does (up through release 0.6.6 and the 0.7.0beta series). There has been a small amount of discussion about supporting the NT_STATUS codes, but it's not clear whether there is any need to change.
Strange Behavior Alert
Another reason to support NT_STATUS codes is that they provide finergrained diagnostics, simply because there are more of them defined than there are DOS codes. Samba has a fairly complete list of the known NT_STATUS codes, which can be found in the samba/source/include/nterr.h file in the Samba distribution. The list of DOS codes is in doserr.h in the same directory. We have already described the structure of the DOS error codes. NT_STATUS codes also have a structure, and it looks like this: In testing, it appears as though the Facility field is always set to zero ( FACILITY_NULL ) for SMB errors. That leaves us with the Level and ErrorCode fields to provide variety... and, as we have suggested, there is quite a bit of variety. Samba's nterr.h file lists over 500 NT_STATUS codes, while doserr.h lists only 99 (and some of those are repeats). Level is one of the following: 00 == Success 01 == Information 10 == Warning 11 == Error Since the next two bits (the <reserved> bits) are always zero, the highestorder nibble will have one of the following values: 0x0 , 0x4 , 0x8 , or 0xC . At the other end of the longword, the ErrorCode is read as an unsigned short (just like the DOS ErrorCode field). The availability of Samba's list of NT_STATUS codes makes things easy. It took a bit of effort to generate that list, however, as most of the codes are not documented in an accessible form. Andrew Tridgell described the method below, which he used to generate a list of valid NT_STATUS codes. His results were used to create the nterr.h file used in Samba.
Tridge's Trick
Okay, now for the next conundrum ... Servers have it tougher than clients. Consider a server that needs to respond to one client using DOS error codes, and to another client using NT_STATUS codes. That's bad enough, but consider what happens when that server needs to query yet another server in order to complete some operation. For example, a file server might need to contact a Domain Controller in order to authenticate the user . The problem is that, no matter which STATUS format the Domain Controller uses when responding to the file server, it will be the wrong format for one of the clients. To solve this problem the server needs to provide a consistent mapping between DOS and NT_STATUS codes. Windows NT and Windows 2000 both have such mappings built-in but, of course, the details are not published (a partial list is given in Section 6 of the SNIA doc). Andrew Bartlett used a trick similar to Tridge's in order to generate the required mappings. His setup uses a Samba server running as a Primary Domain Controller (PDC), and a Windows 2000 system providing SMB file services. A third system, running Samba's smbtorture testing utility, acts as the client. When the client system tries to log on to the Windows server, Windows passes the login request to the Samba PDC. The test works like this:
Andrew Bartlett's Trick
Andrew's test must be rerun periodically. The mappings have been known to change when Windows service packs are installed. See the file samba/source/libsmb/errormap.c in the Samba distribution for more fun and adventure. [2] [2] After all that work... Sometime around August of 2002, Microsoft posted a bit of documentation listing the DOS error codes that they have defined. Not all are used in CIFS, but it's a nice list to have. In addition, they have documented an NTDLL.DLL function that converts DOS error codes into NT_STATUS codes. (Thanks to Jeremy for finding these.) |