diff -Nru a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX --- a/Documentation/filesystems/00-INDEX Thu Oct 10 14:53:27 2002 +++ b/Documentation/filesystems/00-INDEX Thu Oct 10 14:53:27 2002 @@ -8,6 +8,8 @@ - info and mount options for the Amiga Fast File System. bfs.txt - info for the SCO UnixWare Boot Filesystem (BFS). +cifs.txt + - description of the CIFS filesystem coda.txt - description of the CODA filesystem. cramfs.txt diff -Nru a/Documentation/filesystems/cifs.txt b/Documentation/filesystems/cifs.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/filesystems/cifs.txt Thu Oct 10 14:53:27 2002 @@ -0,0 +1,26 @@ +This module, cifs, is a filesystem that implements the SMB/CIFS protocol, which is the +protocol used by Windows based operating systems (including Windows 2000 and its successors) +as well as Samba, OS/2 and many others operating systems and network file server appliances. +The Cifs VFS filesystem module is designed to work well with servers that implement the newer versions +(dialects) of the SMB/CIFS protocol such as Samba, the program written by Andrew Tridgell +that turns any Unix host into a file server for DOS or Windows clients, as well as Windows NT, +Windows 2000 and its successors. It is not designed to handle older smb servers well, those that +implement older versions of the dialect (such as OS/2 or Windows 95), for this purpose use smbfs. + +This module can support mounting without a mount helper program. The mount syntax is: + mount //server_ip_address/share_name /mnt -o user=username,password=your_password +where "username", "your_password" and "server_ip_address" and "share_name" should be replaced +with specific values (supplied by the user) e.g. + mount //9.53.216.16/public /mnt -o user=jsmith,password=openup + +This cifs implementation is designed to handle network caching (safely) as well as to implement locking, +large file (64 bit access), distributed file system ("dfs") and other advanced protocol features. It +also implements the SNIA standard for Unix extensions to CIFS (when communicating with servers such as +Samba 2.2.3 or later which support it). + +For more information contact sfrench@us.ibm.com + +Cifs is an SMB client (or gateway). For more info on the SMB/CIFS protocol and Samba, including +documentation, please go to http://www.samba.org/ and then on to your nearest mirror. For more +information about the cifs vfs, go to the project page at: + http://us1.samba.org/samba/Linux_CIFS_client.html diff -Nru a/fs/Config.help b/fs/Config.help --- a/fs/Config.help Thu Oct 10 14:53:27 2002 +++ b/fs/Config.help Thu Oct 10 14:53:27 2002 @@ -950,6 +950,33 @@ module, say M here and read . If unsure, say N. +CIFS (Common Internet File System) support +CONFIG_CIFS + This is the client VFS module for the Common Internet File System + (CIFS) protocol which is the successor to the Server Message Block + (SMB) protocol, the native file sharing mechanism for most early + PC operating systems. CIFS is fully supported by current network + file servers such as Windows 2000 (including Windows NT version 4 + and Windows XP) as well by Samba (which provides excellent CIFS + server support for Linux and many other operating systems). For + production systems the smbfs module may be used instead of this + cifs module since smbfs is currently more stable and provides + support for older servers. The intent of this module is to provide the + most advanced network file system function for CIFS compliant servers, + including support for dfs (heirarchical name space), secure per-user + session establishment, safe distributed caching (oplock), optional + packet signing, Unicode and other internationalization improvements, and + optional Winbind (nsswitch) integration. This module is in an early + development stage, so unless you are specifically interested in this + filesystem, just say N. + +CIFS Debugging +CONFIG_CIFS_DEBUG + If you are experiencing any problems with the CIFS filesystem, say + Y here. This will result in additional debugging messages to be + written to the system log. Under normal circumstances, this + results in very little overhead. + CONFIG_SMB_FS SMB (Server Message Block) is the protocol Windows for Workgroups (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share diff -Nru a/fs/Config.in b/fs/Config.in --- a/fs/Config.in Thu Oct 10 14:53:27 2002 +++ b/fs/Config.in Thu Oct 10 14:53:27 2002 @@ -140,6 +140,8 @@ fi define_tristate CONFIG_EXPORTFS $CONFIG_NFSD + dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)' CONFIG_CIFS $CONFIG_INET + dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET if [ "$CONFIG_SMB_FS" != "n" ]; then bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT diff -Nru a/fs/Makefile b/fs/Makefile --- a/fs/Makefile Thu Oct 10 14:53:27 2002 +++ b/fs/Makefile Thu Oct 10 14:53:27 2002 @@ -65,6 +65,7 @@ obj-$(CONFIG_NLS) += nls/ obj-$(CONFIG_SYSV_FS) += sysv/ obj-$(CONFIG_SMB_FS) += smbfs/ +obj-$(CONFIG_CIFS) += cifs/ obj-$(CONFIG_NCP_FS) += ncpfs/ obj-$(CONFIG_HPFS_FS) += hpfs/ obj-$(CONFIG_NTFS_FS) += ntfs/ diff -Nru a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/AUTHORS Thu Oct 10 14:53:27 2002 @@ -0,0 +1,16 @@ +Original Author +=============== +Steve French (sfrench@samba.org) + +The author wishes to express his appreciation and thanks to: +Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS +improvements. Thanks to IBM for allowing me the time and test resources to pursue +this project. Jim McDonough from IBM (and the Samba Team) for his help. +The IBM Linux JFS team for explaining many esoteric Linux filesystem features. +Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) +for proving years ago that a very good smb/cifs client could be done on a Unix like +operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin +and others for their work on the Linux smbfs module over the years. Thanks to +the other members of the Storage Network Industry Association CIFS Technical +Workgroup for their work specifying this highly complex protocol and finally +thanks to the Samba team for their technical advice and encouragement. diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/CHANGES Thu Oct 10 14:53:27 2002 @@ -0,0 +1,142 @@ +Version 0.54 +------------ +Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre +changes to superblock layout. Remove wasteful allocation of smb buffers (now the send +buffer is reused for responses). Add more oplock handling. Additional minor cleanup. + +Version 0.53 +------------ +More stylistic updates to better match kernel style. Add additional statistics +for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2 +and CIFS Packet Signing enablement. + +Version 0.52 +------------ +Replace call to sleep_on with safer wait_on_event. +Make stylistic changes to better match kernel style recommendations. +Remove most typedef usage (except for the PDUs themselves). + +Version 0.51 +------------ +Update mount so the -unc mount option is no longer required (the ip address can be specified +in a UNC style device name. Implementation of readpage/writepage started. + +Version 0.50 +------------ +Fix intermittent problem with incorrect smb header checking on badly +fragmented tcp responses + +Version 0.49 +------------ +Fixes to setting of allocation size and file size. + +Version 0.48 +------------ +Various 2.5.38 fixes. Now works on 2.5.38 + +Version 0.47 +------------ +Prepare for 2.5 kernel merge. Remove ifdefs. + +Version 0.46 +------------ +Socket buffer management fixes. Fix dual free. + +Version 0.45 +------------ +Various big endian fixes for hardlinks and symlinks and also for dfs. + +Version 0.44 +------------ +Various big endian fixes for servers with Unix extensions such as Samba + +Version 0.43 +------------ +Various FindNext fixes for incorrect filenames on large directory searches on big endian +clients. basic posix file i/o tests now work on big endian machines, not just le + +Version 0.42 +------------ +SessionSetup and NegotiateProtocol now work from Big Endian machines. +Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatability with older +versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7). + +Version 0.41 +------------ +Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked +files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked. + +Version 0.40 +------------ +Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate +session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP. +Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs +(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos). + +Version 0.38 +------------ +Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable +it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU). + +Version 0.37 +------------ +Rewrote much of connection and mount/unmount logic to handle bugs with +multiple uses to same share, multiple users to same server etc. + +Version 0.36 +------------ +Fixed major problem with dentry corruption (missing call to dput) + +Version 0.35 +------------ +Rewrite of readdir code to fix bug. Various fixes for bigendian machines. +Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs +although corresponding function not fully implemented in the vfs yet + +Version 0.34 +------------ +Fixed dentry caching bug, misc. cleanup + +Version 0.33 +------------ +Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build +on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels. +Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added. + +Version 0.32 +------------ +Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented +and tested against Samba 2.2.5 + + +Version 0.31 +------------ +1) Fixed lockrange to be correct (it was one byte too short) + +2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly +show range as locked when there is a conflict with an existing lock. + +3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories +in most cases. Eventually will offer optional ability to query server for the correct perms. + +3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded +but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb +session) + +4) Fixed error logging of valid mount options + +5) Removed logging of password field. + +6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c +and cleaned them up and made them more consistent with other cifs functions. + +7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways +(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed, +nor is the symlink support using the Unix extensions + +8) Started adding the readlink and follow_link code + +Version 0.3 +----------- +Initial drop + diff -Nru a/fs/cifs/Makefile b/fs/cifs/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/Makefile Thu Oct 10 14:53:27 2002 @@ -0,0 +1,8 @@ +# +# Makefile for Linux CIFS VFS client +# +obj-$(CONFIG_CIFS) += cifs.o + +cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o + +include $(TOPDIR)/Rules.make diff -Nru a/fs/cifs/README b/fs/cifs/README --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/README Thu Oct 10 14:53:27 2002 @@ -0,0 +1,94 @@ +This is the CIFS VFS support for Linux. It supports many advanced network filesystem +features such as heirarchical dfs like filesystem, hardlinks, locking and more. +It was designed to comply with the SNIA CIFS Technical Reference (which supersedes +the 1992 X/Open SMB Standard) as well as to perform best practice practical +interoperability with Windows 2000, Windows XP, Samba and equivalent +servers. + +For questions or bug reports please contact sfrench@samba.org (sfrench@us.ibm.com) + +Build instructions: +================== +extract the kernel from http://www.cifs.bkbits.net/linux-2.5 or +http://www.cifs.bkbits.net/linux-2.4 +make menuconfig (or make xconfig) +select cifs from within the network filesystem choices +save and exit +make dep +make modules (or "make" if you did not select CIFS VFS to be built as a module) + +Installation instructions: +========================= +If you have built the CIFS vfs as module (successfully)you +simply type "make modules_install" (or if you prefer manually copy the file to +the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o). + +If you have built the CIFS vfs into the kernel itself, follow the instructions +for your distribution on how to install a new kernel (usually you +would simply type "make install"). + +If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on the +CIFS VFS web site) copy it to the directory /sbin (or the same directory in which +mount.smbfs resides). Although no helper software is required, the installation +of mount.cifs is recommended. Eventually the Samba 3.0 utility program "net" +may also be helpful since it may someday provide easier mount syntax for users used +to Windows e.g. + net use +and there will likely be other helper programs available ala smbmount to provide +additional optional function in the future. Note that running Winbind on all +of your Linux clients is useful in mapping Uids and Gids consistently to the +proper network user. + +Samba Considerations +==================== +To get the maximum benefit from the CIFS VFS, we recommend using a server that +supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or Samba 3.0) +but the CIFS vfs works fine with a wide variety of CIFS servers. Note that the +uid, gid and file permissions will display default values if you do not have +a server that supports the Unix extensions for CIFS (such as Samba 2.2.3 or +later). To enable the Unix CIFS Extensions in the Samba server, add the line: + unix extensions = yes +to your smb.conf file on the server. Note that the following smb.conf settings are +also useful (on the Samba server) when the majority of clients are Unix +or Linux: + case sensitive = yes + delete readonly = yes +Some administrators also change the "map archive" and the "create mask" parameters +from their defaults. For more information on these see the manual pages +("man smb.conf") on the Samba server system. Note that the cifs vfs, unlike the +smbfs vfs, does not read the smb.conf on the client system (the few optional settings +are passed in on mount via -o parameters instead). + +Use instructions: +================ +Once the CIFS VFS support is built into the kernel or installed as a module (cifs.o), +you can use mount syntax like the following to access Samba or Windows servers: + mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword +after -o the following cifs vfs specific options are supported: + user= + pass= + domain= +TCP names (in addition to ip addresses) will be available when the mount helper +(mount.cifs) is complete + +Restrictions +============ +Servers must support the NTLM SMB dialect (which is the most recent, supported by Samba +and Windows NT, 2000 and XP and many other SMB/CIFS servers) and servers must support +either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC 1001/1002 support for +"Netbios-Over-TCP/IP." Neither of these is likely to be a problem as most servers +support this. IPv6 support is planned for the future. + +Misc /proc/fs/cifs Flags and Debug Info +======================================= +Various experimental features and tracing can be enabled by changing flags in /proc/fs/cifs (after +the cifs module has been installed or built into the kernel, e.g. insmod cifs). To enable +a feature you can set it to 1 e.g. to enable tracing to the kernel message log you can do +"echo 1 > /proc/fs/cifs/cifsFYI" and "echo 1 > /proc/fs/cifs/traceSMB" +Also note that "cat /proc/fs/cifs/DebugData" will display some information about the currently +active sessions and the shares that are mounted. Currently the ntlmv2 enablement and packet +signing will not work since they the implementation is not quite complete, so do not enable +these flags unless you are doing specific testing. Enabling extended security works to +Windows 2000 Workstations and XP but not to Windows 2000 server or Samba since it does not +usually send "raw NTLMSSP" (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which +support is not complete in the CIFS VFS yet). diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/TODO Thu Oct 10 14:53:27 2002 @@ -0,0 +1,55 @@ +version 0.5.3 October 8th, 2002 + +A Partial List of Known Problems and Missing Features +===================================================== + +Contributions are welcome. There are plenty of opportunities +for visible, important contributions to this module. Here +is a partial list of the known problems and missing features: + +a) Support for SecurityDescriptors for chmod/chgrp/chown + +b) Better pam/winbind integration + +c) multi-user mounts - multiplexed sessionsetups over single vc +(ie tcp session) - prettying up needed + +d) Kerberos/SPNEGO session setup support - (started) + +e)NTLMv2 authentication and MD5-HMAC signing of SMB PDUs - (mostly implemented) + +f) oplock support (ie safe CIFS distributed file caching) is not complete. +In addition Directory entry caching relies on a 1 second timer, rather than +using FindNotify or equivalent. - (started) + +g) There may be a few additional changes that could be done to take advantage +of recent 2.5 kernel improvements in byte-range locking + +h) quota support + +i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr + +j) finish off the mount helper, mount.cifs - (started) + +k) support for memory mapped files only partially works until support for +MS_INVALIDATE implemented. readpage and writepage code not finished (started) + +KNOWN BUGS (updated October 8nd, 2002) +==================================== +1) symbolic links (Windows reparse points) are recognized but +can not be created remotely. They are implemented for Samba and those that +support the CIFS Unix extensions but Samba has a bug currently handling +symlink text beginning with slash +2) delete of file with read-only attribute set will fail (may be ok) +3) autoreconnection logic is only partially complete. + +Misc testing to do +================= +1) check out max path names and max path name components against various server +types. + +2) Run POSIX bencharks against cifs + +3) Run dbench + +4) Finish FSX testing on SMP now that we workaround the Samba bug diff -Nru a/fs/cifs/asn1.c b/fs/cifs/asn1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/asn1.c Thu Oct 10 14:53:27 2002 @@ -0,0 +1,615 @@ +/* + * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in + * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich + * + * Copyright (c) 2000 RP Internet (www.rpi.net.au). + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include "cifspdu.h" +#include "cifsglob.h" +#include "cifs_debug.h" + +/***************************************************************************** + * + * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse) + * + *****************************************************************************/ + +/* Class */ +#define ASN1_UNI 0 /* Universal */ +#define ASN1_APL 1 /* Application */ +#define ASN1_CTX 2 /* Context */ +#define ASN1_PRV 3 /* Private */ + +/* Tag */ +#define ASN1_EOC 0 /* End Of Contents or N/A */ +#define ASN1_BOL 1 /* Boolean */ +#define ASN1_INT 2 /* Integer */ +#define ASN1_BTS 3 /* Bit String */ +#define ASN1_OTS 4 /* Octet String */ +#define ASN1_NUL 5 /* Null */ +#define ASN1_OJI 6 /* Object Identifier */ +#define ASN1_OJD 7 /* Object Description */ +#define ASN1_EXT 8 /* External */ +#define ASN1_SEQ 16 /* Sequence */ +#define ASN1_SET 17 /* Set */ +#define ASN1_NUMSTR 18 /* Numerical String */ +#define ASN1_PRNSTR 19 /* Printable String */ +#define ASN1_TEXSTR 20 /* Teletext String */ +#define ASN1_VIDSTR 21 /* Video String */ +#define ASN1_IA5STR 22 /* IA5 String */ +#define ASN1_UNITIM 23 /* Universal Time */ +#define ASN1_GENTIM 24 /* General Time */ +#define ASN1_GRASTR 25 /* Graphical String */ +#define ASN1_VISSTR 26 /* Visible String */ +#define ASN1_GENSTR 27 /* General String */ + +/* Primitive / Constructed methods*/ +#define ASN1_PRI 0 /* Primitive */ +#define ASN1_CON 1 /* Constructed */ + +/* + * Error codes. + */ +#define ASN1_ERR_NOERROR 0 +#define ASN1_ERR_DEC_EMPTY 2 +#define ASN1_ERR_DEC_EOC_MISMATCH 3 +#define ASN1_ERR_DEC_LENGTH_MISMATCH 4 +#define ASN1_ERR_DEC_BADVALUE 5 + +#define SPNEGO_OID_LEN 7 +#define NTLMSSP_OID_LEN 10 +unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; +unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; + +/* + * ASN.1 context. + */ +struct asn1_ctx { + int error; /* Error condition */ + unsigned char *pointer; /* Octet just to be decoded */ + unsigned char *begin; /* First octet */ + unsigned char *end; /* Octet after last octet */ +}; + +/* + * Octet string (not null terminated) + */ +struct asn1_octstr { + unsigned char *data; + unsigned int len; +}; + +static void +asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len) +{ + ctx->begin = buf; + ctx->end = buf + len; + ctx->pointer = buf; + ctx->error = ASN1_ERR_NOERROR; +} + +static unsigned char +asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) +{ + if (ctx->pointer >= ctx->end) { + ctx->error = ASN1_ERR_DEC_EMPTY; + return 0; + } + *ch = *(ctx->pointer)++; + return 1; +} + +static unsigned char +asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) +{ + unsigned char ch; + + *tag = 0; + + do { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + *tag <<= 7; + *tag |= ch & 0x7F; + } while ((ch & 0x80) == 0x80); + return 1; +} + +static unsigned char +asn1_id_decode(struct asn1_ctx *ctx, + unsigned int *cls, unsigned int *con, unsigned int *tag) +{ + unsigned char ch; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *cls = (ch & 0xC0) >> 6; + *con = (ch & 0x20) >> 5; + *tag = (ch & 0x1F); + + if (*tag == 0x1F) { + if (!asn1_tag_decode(ctx, tag)) + return 0; + } + return 1; +} + +static unsigned char +asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len) +{ + unsigned char ch, cnt; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + if (ch == 0x80) + *def = 0; + else { + *def = 1; + + if (ch < 0x80) + *len = ch; + else { + cnt = (unsigned char) (ch & 0x7F); + *len = 0; + + while (cnt > 0) { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + *len <<= 8; + *len |= ch; + cnt--; + } + } + } + return 1; +} + +static unsigned char +asn1_header_decode(struct asn1_ctx *ctx, + unsigned char **eoc, + unsigned int *cls, unsigned int *con, unsigned int *tag) +{ + unsigned int def, len; + + if (!asn1_id_decode(ctx, cls, con, tag)) + return 0; + + if (!asn1_length_decode(ctx, &def, &len)) + return 0; + + if (def) + *eoc = ctx->pointer + len; + else + *eoc = 0; + return 1; +} + +static unsigned char +asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc) +{ + unsigned char ch; + + if (eoc == 0) { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + if (ch != 0x00) { + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + if (ch != 0x00) { + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; + return 0; + } + return 1; + } else { + if (ctx->pointer != eoc) { + ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH; + return 0; + } + return 1; + } +} + +/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx, + unsigned char *eoc) +{ + ctx->pointer = eoc; + return 1; +} + +static unsigned char asn1_long_decode(struct asn1_ctx *ctx, + unsigned char *eoc, long *integer) +{ + unsigned char ch; + unsigned int len; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer = (signed char) ch; + len = 1; + + while (ctx->pointer < eoc) { + if (++len > sizeof(long)) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer <<= 8; + *integer |= ch; + } + return 1; +} + +static unsigned char asn1_uint_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + unsigned int *integer) +{ + unsigned char ch; + unsigned int len; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer = ch; + if (ch == 0) + len = 0; + else + len = 1; + + while (ctx->pointer < eoc) { + if (++len > sizeof(unsigned int)) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer <<= 8; + *integer |= ch; + } + return 1; +} + +static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + unsigned long *integer) +{ + unsigned char ch; + unsigned int len; + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer = ch; + if (ch == 0) + len = 0; + else + len = 1; + + while (ctx->pointer < eoc) { + if (++len > sizeof(unsigned long)) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + return 0; + } + + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *integer <<= 8; + *integer |= ch; + } + return 1; +} + +static unsigned char +asn1_octets_decode(struct asn1_ctx *ctx, + unsigned char *eoc, + unsigned char **octets, unsigned int *len) +{ + unsigned char *ptr; + + *len = 0; + + *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC); + if (*octets == NULL) { + return 0; + } + + ptr = *octets; + while (ctx->pointer < eoc) { + if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) { + kfree(*octets); + *octets = NULL; + return 0; + } + (*len)++; + } + return 1; +} */ + +static unsigned char +asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid) +{ + unsigned char ch; + + *subid = 0; + + do { + if (!asn1_octet_decode(ctx, &ch)) + return 0; + + *subid <<= 7; + *subid |= ch & 0x7F; + } while ((ch & 0x80) == 0x80); + return 1; +} + +static unsigned char +asn1_oid_decode(struct asn1_ctx *ctx, + unsigned char *eoc, unsigned long **oid, unsigned int *len) +{ + unsigned long subid; + unsigned int size; + unsigned long *optr; + + size = eoc - ctx->pointer + 1; + *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC); + if (*oid == NULL) { + return 0; + } + + optr = *oid; + + if (!asn1_subid_decode(ctx, &subid)) { + kfree(*oid); + *oid = NULL; + return 0; + } + + if (subid < 40) { + optr[0] = 0; + optr[1] = subid; + } else if (subid < 80) { + optr[0] = 1; + optr[1] = subid - 40; + } else { + optr[0] = 2; + optr[1] = subid - 80; + } + + *len = 2; + optr += 2; + + while (ctx->pointer < eoc) { + if (++(*len) > size) { + ctx->error = ASN1_ERR_DEC_BADVALUE; + kfree(*oid); + *oid = NULL; + return 0; + } + + if (!asn1_subid_decode(ctx, optr++)) { + kfree(*oid); + *oid = NULL; + return 0; + } + } + return 1; +} + +static int +compare_oid(unsigned long *oid1, unsigned int oid1len, + unsigned long *oid2, unsigned int oid2len) +{ + int i; + + if (oid1len != oid2len) + return 0; + else { + for (i = 0; i < oid1len; i++) { + if (oid1[i] != oid2[i]) + return 0; + } + return 1; + } +} + + /* BB check for endian conversion issues here */ + +int +decode_negTokenInit(unsigned char *security_blob, int length, + enum securityEnum *secType) +{ + struct asn1_ctx ctx; + unsigned char *end; + unsigned char *sequence_end; + unsigned long *oid; + unsigned int cls, con, tag, oidlen, rc; + int use_ntlmssp = FALSE; + + dump_mem(" Received SecBlob ", security_blob, length); + + asn1_open(&ctx, security_blob, length); + + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, ("\nError decoding negTokenInit header ")); + return 0; + } else if ((cls != ASN1_APL) || (con != ASN1_CON) + || (tag != ASN1_EOC)) { + cFYI(1, ("\ncls = %d con = %d tag = %d", cls, con, tag)); + return 0; + } else { + /* remember to free obj->oid */ + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); + if (rc) { + if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) { + rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); + if (rc) { + rc = compare_oid(oid, oidlen, + SPNEGO_OID, + SPNEGO_OID_LEN); + kfree(oid); + } + } else + rc = 0; + } + + if (!rc) { + cFYI(1, ("\nError decoding negTokenInit header")); + return 0; + } + + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, ("\nError decoding negTokenInit ")); + return 0; + } else if ((cls != ASN1_CTX) || (con != ASN1_CON) + || (tag != ASN1_EOC)) { + cFYI(1, + ("\ncls = %d con = %d tag = %d end = %p (%d) exit 0", + cls, con, tag, end, *end)); + return 0; + } + + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, ("\nError decoding negTokenInit ")); + return 0; + } else if ((cls != ASN1_UNI) || (con != ASN1_CON) + || (tag != ASN1_SEQ)) { + cFYI(1, + ("\ncls = %d con = %d tag = %d end = %p (%d) exit 1", + cls, con, tag, end, *end)); + return 0; + } + + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, ("\nError decoding 2nd part of negTokenInit ")); + return 0; + } else if ((cls != ASN1_CTX) || (con != ASN1_CON) + || (tag != ASN1_EOC)) { + cFYI(1, + ("\ncls = %d con = %d tag = %d end = %p (%d) exit 0", + cls, con, tag, end, *end)); + return 0; + } + + if (asn1_header_decode + (&ctx, &sequence_end, &cls, &con, &tag) == 0) { + cFYI(1, ("\nError decoding 2nd part of negTokenInit ")); + return 0; + } else if ((cls != ASN1_UNI) || (con != ASN1_CON) + || (tag != ASN1_SEQ)) { + cFYI(1, + ("\ncls = %d con = %d tag = %d end = %p (%d) exit 1", + cls, con, tag, end, *end)); + return 0; + } + + while (!asn1_eoc_decode(&ctx, sequence_end)) { + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); + if (!rc) { + cFYI(1, + ("\nError 1 decoding negTokenInit header exit 2")); + return 0; + } + if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { + asn1_oid_decode(&ctx, end, &oid, &oidlen); + cFYI(1, + ("\nOID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx", + oidlen, *oid, *(oid + 1), *(oid + 2), + *(oid + 3))); + rc = compare_oid(oid, oidlen, NTLMSSP_OID, + NTLMSSP_OID_LEN); + kfree(oid); + if (rc) + use_ntlmssp = TRUE; + } else { + cFYI(1, + ("\nThis should be an oid what is going on? ")); + } + } + + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, + ("\nError decoding last part of negTokenInit exit 3")); + return 0; + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */ + cFYI(1, + ("\nExit 4 cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end)); + return 0; + } + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, + ("\nError decoding last part of negTokenInit exit 5")); + return 0; + } else if ((cls != ASN1_UNI) || (con != ASN1_CON) + || (tag != ASN1_SEQ)) { + cFYI(1, + ("\nExit 6 cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end)); + } + + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, + ("\nError decoding last part of negTokenInit exit 7")); + return 0; + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { + cFYI(1, + ("\nExit 8 cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end)); + return 0; + } + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + cFYI(1, + ("\nError decoding last part of negTokenInit exit 9")); + return 0; + } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) + || (tag != ASN1_GENSTR)) { + cFYI(1, + ("\nExit 10 cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end)); + return 0; + } + cFYI(1, ("\nNeed to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */ + } + + /* if (use_kerberos) + *secType = Kerberos + else */ + if (use_ntlmssp) { + *secType = NTLMSSP; + } + + return 1; +} diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifs_debug.c Thu Oct 10 14:53:27 2002 @@ -0,0 +1,546 @@ +/* + * fs/cifs_debug.c + * + * Copyright (c) International Business Machines Corp., 2000,2002 + * + * Modified by Steve French (sfrench@us.ibm.com) + * + * 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 + */ +#include +#include +#include +#define __NO_VERSION__ +#include +#include +#include +#include "cifspdu.h" +#include "cifsglob.h" +#include "cifsproto.h" +#include "cifs_debug.h" + +void +dump_mem(char *label, void *data, int length) +{ + int i, j; + int *intptr = data; + char *charptr = data; + char buf[10], line[80]; + + printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length, data); + for (i = 0; i < length; i += 16) { + line[0] = 0; + for (j = 0; (j < 4) && (i + j * 4 < length); j++) { + sprintf(buf, " %08x", intptr[i / 4 + j]); + strcat(line, buf); + } + buf[0] = ' '; + buf[2] = 0; + for (j = 0; (j < 16) && (i + j < length); j++) { + buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.'; + strcat(line, buf); + } + printk("%s\n", line); + } +} + +#if CONFIG_PROC_FS +int +cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, + int count, int *eof, void *data) +{ + struct list_head *tmp; + struct cifsSesInfo *ses; + struct cifsTconInfo *tcon; + int i; + int length = 0; + char *buf_start = buf; + + printk("\n\nEntering cifs_debug_data_read: buf=0x%p, beginBuffer=0x%p, offset=%ld, count=%d, eof=%d, data=0x%p\n", buf, *beginBuffer, offset, count, *eof, data); /* BB remove */ + length = + sprintf(buf, + "Display Internal CIFS Data Structures for Debugging\n" + "---------------------------------------------------\n"); + buf += length; + + length = sprintf(buf, "Servers: \n"); + buf += length; + + i = 0; + list_for_each(tmp, &GlobalSMBSessionList) { + i++; + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); + length = + sprintf(buf, + "\n%d) Name: %s Domain: %s HowManyMounts: %d LocalUsersToSameServer: %d\n\t ServerOS: %s ServerNOS: %s Capabilities: 0x%x ", + i, ses->serverName, ses->serverDomain, + atomic_read(&ses->inUse), + atomic_read(&ses->server->socketUseCount), + ses->serverOS, ses->serverNOS, ses->capabilities); + buf += length; + } + sprintf(buf, "\n"); + buf++; + printk("\nTotal Buffer so far: %s\n", buf_start); + + length = sprintf(buf, "\nShares: \n"); + buf += length; + + i = 0; + list_for_each(tmp, &GlobalTreeConnectionList) { + i++; + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); + length = + sprintf(buf, + "\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x and PathComponentLengthMax: %d", + i, tcon->treeName, + atomic_read(&tcon->useCount), + tcon->nativeFileSystem, + tcon->fsDevInfo.DeviceCharacteristics, + tcon->fsAttrInfo.Attributes, + tcon->fsAttrInfo.MaxPathNameComponentLength); + buf += length; + if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK) + length = sprintf(buf, " type: DISK "); + else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM) + length = sprintf(buf, " type: CDROM "); + else + length = + sprintf(buf, " type: %d ", + tcon->fsDevInfo.DeviceType); + buf += length; + } + length = sprintf(buf, "\n"); + buf += length; + *eof = 1; + /* BB add code to dump additional info such as TCP session info now */ + /* + if (offset >= (buf - buf_start)) + { + *beginBuffer = buf; + return 0; + } + *beginBuffer = buf + offset; + if ((buf - buf_start - offset) > count) + return count; + else */ + return (buf - buf_start - offset); +} + +int +cifs_total_xid_read(char *buf, char **beginBuffer, off_t offset, + int length, int *eof, void *data) +{ + + length = + sprintf(buf, + "Total vfs operations: %d and maximum simultaneous serviced by this filesystem: %d\n", + GlobalCurrentXid,GlobalMaxActiveXid); + + return length; +} + +int +cifs_stats_read(char *buf, char **beginBuffer, off_t offset, + int length, int *eof, void *data) +{ + int item_length; + length = + sprintf(buf, + "Currently Allocated structures\nCIFS Sessions: %d\n",sesInfoAllocCount.counter); + buf += length; + item_length = + sprintf(buf,"Shares (unique mount targets): %d\n",tconInfoAllocCount.counter); + length += item_length; + buf += item_length; + item_length = + sprintf(buf,"Allocated SMB Request and Response Buffers: %d\n",bufAllocCount.counter); + length += item_length; + buf += item_length; + item_length = + sprintf(buf,"Active Operations (MIDs in use): %d\n",midCount.counter); + length += item_length; + + return length; +} + +struct proc_dir_entry *proc_fs_cifs; +read_proc_t cifs_txanchor_read; +static read_proc_t cifsFYI_read; +static write_proc_t cifsFYI_write; +static read_proc_t oplockEnabled_read; +static write_proc_t oplockEnabled_write; +static read_proc_t traceSMB_read; +static write_proc_t traceSMB_write; +static read_proc_t multiuser_mount_read; +static write_proc_t multiuser_mount_write; +static read_proc_t extended_security_read; +static write_proc_t extended_security_write; +static read_proc_t ntlmv2_enabled_read; +static write_proc_t ntlmv2_enabled_write; +static read_proc_t packet_signing_enabled_read; +static write_proc_t packet_signing_enabled_write; + +void +cifs_proc_init(void) +{ + struct proc_dir_entry *pde; + + proc_fs_cifs = proc_mkdir("cifs", proc_root_fs); + if (proc_fs_cifs == NULL) + return; + + proc_fs_cifs->owner = THIS_MODULE; + create_proc_read_entry("DebugData", 0, proc_fs_cifs, + cifs_debug_data_read, 0); + + create_proc_read_entry("SimultaneousOps", 0, proc_fs_cifs, + cifs_total_xid_read, 0); + + create_proc_read_entry("Stats", 0, proc_fs_cifs, + cifs_stats_read, 0); + + pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs, + cifsFYI_read, 0); + if (pde) + pde->write_proc = cifsFYI_write; + + pde = + create_proc_read_entry("traceSMB", 0, proc_fs_cifs, + traceSMB_read, 0); + if (pde) + pde->write_proc = traceSMB_write; + + pde = create_proc_read_entry("oplockEnabled", 0, proc_fs_cifs, + oplockEnabled_read, 0); + if (pde) + pde->write_proc = oplockEnabled_write; + + pde = + create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs, + multiuser_mount_read, 0); + if (pde) + pde->write_proc = multiuser_mount_write; + + pde = + create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs, + extended_security_read, 0); + if (pde) + pde->write_proc = extended_security_write; + + pde = + create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs, + ntlmv2_enabled_read, 0); + if (pde) + pde->write_proc = ntlmv2_enabled_write; + + pde = + create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs, + packet_signing_enabled_read, 0); + if (pde) + pde->write_proc = packet_signing_enabled_write; +} + +void +cifs_proc_clean(void) +{ + if (proc_fs_cifs == NULL) + return; + + remove_proc_entry("DebugData", proc_fs_cifs); + remove_proc_entry("cifsFYI", proc_fs_cifs); + remove_proc_entry("TraceSMB", proc_fs_cifs); + remove_proc_entry("MaxSimultaneousOps", proc_fs_cifs); + remove_proc_entry("TotalOps", proc_fs_cifs); + remove_proc_entry("MultiuserMount", proc_fs_cifs); + remove_proc_entry("oplockEnabled", proc_fs_cifs); + remove_proc_entry("cifs", proc_root_fs); +} + +static int +cifsFYI_read(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int len; + + len = sprintf(page, "%d\n", cifsFYI); + + len -= off; + *start = page + off; + + if (len > count) + len = count; + else + *eof = 1; + + if (len < 0) + len = 0; + + return len; +} +static int +cifsFYI_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + cifsFYI = 0; + else if (c == '1' || c == 'y' || c == 'Y') + cifsFYI = 1; + + return count; +} + +static int +oplockEnabled_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = sprintf(page, "%d\n", oplockEnabled); + + len -= off; + *start = page + off; + + if (len > count) + len = count; + else + *eof = 1; + + if (len < 0) + len = 0; + + return len; +} +static int +oplockEnabled_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + oplockEnabled = 0; + else if (c == '1' || c == 'y' || c == 'Y') + oplockEnabled = 1; + + return count; +} + +static int +traceSMB_read(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int len; + + len = sprintf(page, "%d\n", traceSMB); + + len -= off; + *start = page + off; + + if (len > count) + len = count; + else + *eof = 1; + + if (len < 0) + len = 0; + + return len; +} +static int +traceSMB_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + traceSMB = 0; + else if (c == '1' || c == 'y' || c == 'Y') + traceSMB = 1; + + return count; +} + +static int +multiuser_mount_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = sprintf(page, "%d\n", multiuser_mount); + + len -= off; + *start = page + off; + + if (len > count) + len = count; + else + *eof = 1; + + if (len < 0) + len = 0; + + return len; +} +static int +multiuser_mount_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + multiuser_mount = 0; + else if (c == '1' || c == 'y' || c == 'Y') + multiuser_mount = 1; + + return count; +} + +static int +extended_security_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = sprintf(page, "%d\n", extended_security); + + len -= off; + *start = page + off; + + if (len > count) + len = count; + else + *eof = 1; + + if (len < 0) + len = 0; + + return len; +} +static int +extended_security_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + extended_security = 0; + else if (c == '1' || c == 'y' || c == 'Y') + extended_security = 1; + + return count; +} + +static int +ntlmv2_enabled_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = sprintf(page, "%d\n", ntlmv2_support); + + len -= off; + *start = page + off; + + if (len > count) + len = count; + else + *eof = 1; + + if (len < 0) + len = 0; + + return len; +} +static int +ntlmv2_enabled_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + ntlmv2_support = 0; + else if (c == '1' || c == 'y' || c == 'Y') + ntlmv2_support = 1; + + return count; +} + +static int +packet_signing_enabled_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = sprintf(page, "%d\n", sign_CIFS_PDUs); + + len -= off; + *start = page + off; + + if (len > count) + len = count; + else + *eof = 1; + + if (len < 0) + len = 0; + + return len; +} +static int +packet_signing_enabled_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + sign_CIFS_PDUs = 0; + else if (c == '1' || c == 'y' || c == 'Y') + sign_CIFS_PDUs = 1; + + return count; +} + + +#endif diff -Nru a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifs_debug.h Thu Oct 10 14:53:27 2002 @@ -0,0 +1,74 @@ +/* + * + * Copyright (c) International Business Machines Corp., 2000,2002 + * Modified by Steve French (sfrench@us.ibm.com) + * + * 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 + * +*/ +#define CIFS_DEBUG /* BB temporary */ + +#ifndef _H_CIFS_DEBUG +#define _H_CIFS_DEBUG + +void dump_mem(char *label, void *data, int length); +extern int traceSMB; /* flag which enables the function below */ +void dump_smb(struct smb_hdr *, int); + +/* + * debug ON + * -------- + */ +#ifdef CIFS_DEBUG + +/* information message: e.g., configuration, major event */ +extern int cifsFYI; +#define cFYI(button,prspec)\ +{ if (button && cifsFYI) printk prspec; } + +/* debug event message: */ +#define cEVENT(button,prspec)\ +{ if (button) printk prspec; } + +/* error event message: e.g., i/o error */ +extern int cifsERROR; +#define cERROR(button, prspec)\ +{ if (button && cifsERROR) { printk prspec; if (button > 1) BUG(); } } + +/* + * debug OFF + * --------- + */ +#else /* _CIFS_DEBUG */ +#define cERROR(button,prspec) +#define cEVENT(button,prspec) +#define cFYI(button, prspec) +#endif /* _CIFS_DEBUG */ + +/* + * statistics + * ---------- + */ +#ifdef _CIFS_STATISTICS +#define INCREMENT(x) ((x)++) +#define DECREMENT(x) ((x)--) +#define HIGHWATERMARK(x,y) x = MAX((x), (y)) +#else +#define INCREMENT(x) +#define DECREMENT(x) +#define HIGHWATERMARK(x,y) +#endif /* _CIFS_STATISTICS */ + +#endif /* _H_CIFS_DEBUG */ diff -Nru a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifs_fs_sb.h Thu Oct 10 14:53:27 2002 @@ -0,0 +1,27 @@ +/* + * fs/cifs/cifs_fs_sb.h + * + * Copyright (c) International Business Machines Corp., 2002 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + */ +#ifndef _CIFS_FS_SB_H +#define _CIFS_FS_SB_H + +struct cifs_sb_info { + struct cifsTconInfo *tcon; /* primary mount */ + /* list of implicit mounts beneath this mount point - needed in dfs case */ + struct list_head nested_tcon_q; + struct nls_table *local_nls; +}; +#endif /* _CIFS_FS_SB_H */ diff -Nru a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifs_unicode.c Thu Oct 10 14:53:27 2002 @@ -0,0 +1,136 @@ +/* + * fs/cifs/cifs_unicode.c + * + * Copyright (c) International Business Machines Corp., 2000,2002 + * Modified by Steve French (sfrench@us.ibm.com) + * + * 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 + */ +#include +#include "cifs_unicode.h" +#include "cifs_uniupr.h" +#include "cifspdu.h" +#include "cifs_debug.h" + +/* + * NAME: toUpper() + * + * FUNCTION: Upper case ASCII string (in place) using the current codepage + * + */ + +void +toUpper(const struct nls_table *n, char *mixed_string) +{ + int i; + char temp; + + for (i = 0; i < strlen(mixed_string); i++) { + temp = mixed_string[i]; + mixed_string[i] = n->charset2upper[(int) temp]; + } +} + +/* + * NAME: cifs_strfromUCS() + * + * FUNCTION: Convert little-endian unicode string to character string + * + */ +int +cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */ + int len, const struct nls_table *codepage) +{ + int i; + int outlen = 0; + + for (i = 0; (i < len) && from[i]; i++) { + int charlen; + /* 2.4.0 kernel or greater */ + charlen = + codepage->uni2char(le16_to_cpu(from[i]), &to[outlen], + NLS_MAX_CHARSET_SIZE); + if (charlen > 0) { + outlen += charlen; + } else { + to[outlen++] = '?'; + } + } + to[outlen] = 0; + cEVENT(0, ("cifs_strfromUCS returning %d - '%s'\n", outlen, to)); + return outlen; +} + +/* + * NAME: cifs_strtoUCS() + * + * FUNCTION: Convert character string to unicode string + * + */ +int +cifs_strtoUCS(wchar_t * to, const char *from, int len, + const struct nls_table *codepage) +{ + int charlen; + int i; + + cEVENT(0, ("cifs_strtoUCS - '%s'\n", from)); + + for (i = 0; len && *from; i++, from += charlen, len -= charlen) { + + /* works for 2.4.0 kernel or later */ + charlen = codepage->char2uni(from, len, &to[i]); + if (charlen < 1) { + cERROR(1, + ("cifs_strtoUCS: char2uni returned %d.\n", + charlen)); + to[i] = cpu_to_le16(0x003f); /* a question mark */ + charlen = 1; + } + to[i] = cpu_to_le16(to[i]); + + } + + cEVENT(0, (" returning %d\n", i)); + + to[i] = 0; + return i; +} + +/* + * NAME: get_UCSname2() + * + * FUNCTION: Allocate and translate to unicode string + * + */ +/*int +get_UCSname2(struct component_name *uniName, struct dentry *dentry, + struct nls_table *nls_tab) +{ + int length = dentry->d_name.len; + + if (length > 255) + return ENAMETOOLONG; + + uniName->name = kmalloc((length + 1) * sizeof (wchar_t), GFP_KERNEL); + + if (uniName->name == NULL) + return ENOSPC; + + uniName->namlen = cifs_strtoUCS(uniName->name, dentry->d_name.name, + length, nls_tab); + + return 0; +} */ diff -Nru a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifs_unicode.h Thu Oct 10 14:53:27 2002 @@ -0,0 +1,368 @@ +/* + * cifs_unicode: Unicode kernel case support + * + * Function: + * Convert a unicode character to upper or lower case using + * compressed tables. + * + * Copyright (c) International Business Machines Corp., 2000,2002 + * + * 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 + * + * + * Notes: + * These APIs are based on the C library functions. The semantics + * should match the C functions but with expanded size operands. + * + * The upper/lower functions are based on a table created by mkupr. + * This is a compressed table of upper and lower case conversion. + * + */ + +#include +#include +#include + +#define UNIUPR_NOLOWER /* Example to not expand lower case tables */ + +/* Just define what we want from uniupr.h. We don't want to define the tables + * in each source file. + */ +#ifndef UNICASERANGE_DEFINED +struct UniCaseRange { + wchar_t start; + wchar_t end; + signed char *table; +}; +#endif /* UNICASERANGE_DEFINED */ + +#ifndef UNIUPR_NOUPPER +extern signed char CifsUniUpperTable[512]; +extern const struct UniCaseRange CifsUniUpperRange[]; +#endif /* UNIUPR_NOUPPER */ + +#ifndef UNIUPR_NOLOWER +extern signed char UniLowerTable[512]; +extern struct UniCaseRange UniLowerRange[]; +#endif /* UNIUPR_NOLOWER */ + +/* + * directory entry argument + */ +struct component_name { + int namlen; + wchar_t *name; +}; + +#ifdef __KERNEL__ +int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *); +int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *); + +int cifs_UCSname(struct component_name *, struct dentry *, + const struct nls_table *); + +void toUpper(const struct nls_table *, char *); +#endif + +#define free_UCSname(COMP) kfree((COMP)->name) + +/* + * UniStrcat: Concatenate the second string to the first + * + * Returns: + * Address of the first string + */ +static inline wchar_t * +UniStrcat(wchar_t * ucs1, const wchar_t * ucs2) +{ + wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ + + while (*ucs1++) ; /* To end of first string */ + ucs1--; /* Return to the null */ + while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */ + return anchor; +} + +/* + * UniStrchr: Find a character in a string + * + * Returns: + * Address of first occurance of character in string + * or NULL if the character is not in the string + */ +static inline wchar_t * +UniStrchr(const wchar_t * ucs, wchar_t uc) +{ + while ((*ucs != uc) && *ucs) + ucs++; + + if (*ucs == uc) + return (wchar_t *) ucs; + return NULL; +} + +/* + * UniStrcmp: Compare two strings + * + * Returns: + * < 0: First string is less than second + * = 0: Strings are equal + * > 0: First string is greater than second + */ +static inline int +UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2) +{ + while ((*ucs1 == *ucs2) && *ucs1) { + ucs1++; + ucs2++; + } + return (int) *ucs1 - (int) *ucs2; +} + +/* + * UniStrcpy: Copy a string + */ +static inline wchar_t * +UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2) +{ + wchar_t *anchor = ucs1; /* save the start of result string */ + + while ((*ucs1++ = *ucs2++)) ; + return anchor; +} + +/* + * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) + */ +static inline size_t +UniStrlen(const wchar_t * ucs1) +{ + int i = 0; + + while (*ucs1++) + i++; + return i; +} + +/* + * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited) + */ +static inline size_t +UniStrnlen(const wchar_t * ucs1, int maxlen) +{ + int i = 0; + + while (*ucs1++) { + i++; + if (i >= maxlen) + break; + } + return i; +} + +/* + * UniStrncat: Concatenate length limited string + */ +static inline wchar_t * +UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n) +{ + wchar_t *anchor = ucs1; /* save pointer to string 1 */ + + while (*ucs1++) ; + ucs1--; /* point to null terminator of s1 */ + while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ + ucs1++; + ucs2++; + } + *ucs1 = 0; /* Null terminate the result */ + return (anchor); +} + +/* + * UniStrncmp: Compare length limited string + */ +static inline int +UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n) +{ + if (!n) + return 0; /* Null strings are equal */ + while ((*ucs1 == *ucs2) && *ucs1 && --n) { + ucs1++; + ucs2++; + } + return (int) *ucs1 - (int) *ucs2; +} + +/* + * UniStrncmp_le: Compare length limited string - native to little-endian + */ +static inline int +UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n) +{ + if (!n) + return 0; /* Null strings are equal */ + while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { + ucs1++; + ucs2++; + } + return (int) *ucs1 - (int) __le16_to_cpu(*ucs2); +} + +/* + * UniStrncpy: Copy length limited string with pad + */ +static inline wchar_t * +UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n) +{ + wchar_t *anchor = ucs1; + + while (n-- && *ucs2) /* Copy the strings */ + *ucs1++ = *ucs2++; + + n++; + while (n--) /* Pad with nulls */ + *ucs1++ = 0; + return anchor; +} + +/* + * UniStrncpy_le: Copy length limited string with pad to little-endian + */ +static inline wchar_t * +UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n) +{ + wchar_t *anchor = ucs1; + + while (n-- && *ucs2) /* Copy the strings */ + *ucs1++ = __le16_to_cpu(*ucs2++); + + n++; + while (n--) /* Pad with nulls */ + *ucs1++ = 0; + return anchor; +} + +/* + * UniStrstr: Find a string in a string + * + * Returns: + * Address of first match found + * NULL if no matching string is found + */ +static inline wchar_t * +UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2) +{ + const wchar_t *anchor1 = ucs1; + const wchar_t *anchor2 = ucs2; + + while (*ucs1) { + if (*ucs1 == *ucs2) { /* Partial match found */ + ucs1++; + ucs2++; + } else { + if (!*ucs2) /* Match found */ + return (wchar_t *) anchor1; + ucs1 = ++anchor1; /* No match */ + ucs2 = anchor2; + } + } + + if (!*ucs2) /* Both end together */ + return (wchar_t *) anchor1; /* Match found */ + return NULL; /* No match */ +} + +#ifndef UNIUPR_NOUPPER +/* + * UniToupper: Convert a unicode character to upper case + */ +static inline wchar_t +UniToupper(register wchar_t uc) +{ + register const struct UniCaseRange *rp; + + if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */ + return uc + CifsUniUpperTable[uc]; /* Use base tables */ + } else { + rp = CifsUniUpperRange; /* Use range tables */ + while (rp->start) { + if (uc < rp->start) /* Before start of range */ + return uc; /* Uppercase = input */ + if (uc <= rp->end) /* In range */ + return uc + rp->table[uc - rp->start]; + rp++; /* Try next range */ + } + } + return uc; /* Past last range */ +} + +/* + * UniStrupr: Upper case a unicode string + */ +static inline wchar_t * +UniStrupr(register wchar_t * upin) +{ + register wchar_t *up; + + up = upin; + while (*up) { /* For all characters */ + *up = UniToupper(*up); + up++; + } + return upin; /* Return input pointer */ +} +#endif /* UNIUPR_NOUPPER */ + +#ifndef UNIUPR_NOLOWER +/* + * UniTolower: Convert a unicode character to lower case + */ +static inline wchar_t +UniTolower(wchar_t uc) +{ + register struct UniCaseRange *rp; + + if (uc < sizeof (UniLowerTable)) { /* Latin characters */ + return uc + UniLowerTable[uc]; /* Use base tables */ + } else { + rp = UniLowerRange; /* Use range tables */ + while (rp->start) { + if (uc < rp->start) /* Before start of range */ + return uc; /* Uppercase = input */ + if (uc <= rp->end) /* In range */ + return uc + rp->table[uc - rp->start]; + rp++; /* Try next range */ + } + } + return uc; /* Past last range */ +} + +/* + * UniStrlwr: Lower case a unicode string + */ +static inline wchar_t * +UniStrlwr(register wchar_t * upin) +{ + register wchar_t *up; + + up = upin; + while (*up) { /* For all characters */ + *up = UniTolower(*up); + up++; + } + return upin; /* Return input pointer */ +} + +#endif diff -Nru a/fs/cifs/cifs_uniupr.h b/fs/cifs/cifs_uniupr.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifs_uniupr.h Thu Oct 10 14:53:27 2002 @@ -0,0 +1,253 @@ +/* + * Copyright (c) International Business Machines Corp., 2000,2002 + * + * 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 + * + * uniupr.h - Unicode compressed case ranges + * +*/ + +#ifndef UNIUPR_NOUPPER +/* + * Latin upper case + */ +signed char CifsUniUpperTable[512] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */ + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */ + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */ + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */ + -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */ + 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */ + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */ + 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */ + 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */ + 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */ + -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */ + 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */ + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */ + 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */ +}; + +/* Upper case range - Greek */ +static signed char UniCaseRangeU03a0[47] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */ + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */ + -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64, + -63, -63, +}; + +/* Upper case range - Cyrillic */ +static signed char UniCaseRangeU0430[48] = { + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */ + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */ + 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */ +}; + +/* Upper case range - Extended cyrillic */ +static signed char UniCaseRangeU0490[61] = { + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */ + 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, +}; + +/* Upper case range - Extended latin and greek */ +static signed char UniCaseRangeU1e00[509] = { + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */ + 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */ + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */ + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */ + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */ + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */ + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */ + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */ + 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */ + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */ + 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */ + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */ + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */ + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */ + 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */ + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */ + 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */ + 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */ + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +/* Upper case range - Wide latin */ +static signed char UniCaseRangeUff40[27] = { + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */ + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, +}; + +/* + * Upper Case Range + */ +const struct UniCaseRange CifsUniUpperRange[] = { + {0x03a0, 0x03ce, UniCaseRangeU03a0}, + {0x0430, 0x045f, UniCaseRangeU0430}, + {0x0490, 0x04cc, UniCaseRangeU0490}, + {0x1e00, 0x1ffc, UniCaseRangeU1e00}, + {0xff40, 0xff5a, UniCaseRangeUff40}, + {0, 0, 0} +}; +#endif + +#ifndef UNIUPR_NOLOWER +/* + * Latin lower case + */ +static signed char CifsUniLowerTable[512] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */ + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */ + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */ + 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */ + 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */ + 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */ + 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */ + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */ + 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */ + 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */ + 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */ + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */ + 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */ +}; + +/* Lower case range - Greek */ +static signed char UniCaseRangeL0380[44] = { + 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */ + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */ + 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, +}; + +/* Lower case range - Cyrillic */ +static signed char UniCaseRangeL0400[48] = { + 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */ +}; + +/* Lower case range - Extended cyrillic */ +static signed char UniCaseRangeL0490[60] = { + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */ + 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, +}; + +/* Lower case range - Extended latin and greek */ +static signed char UniCaseRangeL1e00[504] = { + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */ + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */ + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */ + 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */ + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */ + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +/* Lower case range - Wide latin */ +static signed char UniCaseRangeLff20[27] = { + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, +}; + +/* + * Lower Case Range + */ +const static struct UniCaseRange CifsUniLowerRange[] = { + 0x0380, 0x03ab, UniCaseRangeL0380, + 0x0400, 0x042f, UniCaseRangeL0400, + 0x0490, 0x04cb, UniCaseRangeL0490, + 0x1e00, 0x1ff7, UniCaseRangeL1e00, + 0xff20, 0xff3a, UniCaseRangeLff20, + 0, 0, 0 +}; +#endif diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifsfs.c Thu Oct 10 14:53:27 2002 @@ -0,0 +1,433 @@ +/* + * fs/cifs/cifsfs.c + * + * Copyright (c) International Business Machines Corp., 2002 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * Common Internet FileSystem (CIFS) client + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Note that BB means BUGBUG (ie something to fix eventually) */ + +#include +#include +#include +#include +#include +#include +#include +#include "cifsfs.h" +#include "cifspdu.h" +#define DECLARE_GLOBALS_HERE +#include "cifsglob.h" +#include "cifsproto.h" +#include "cifs_debug.h" +#include "cifs_fs_sb.h" +#include +#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of all SMB PDUs */ + +extern struct file_system_type cifs_fs_type; + +int cifsFYI = 0; +int cifsERROR = 1; +int traceSMB = 0; +unsigned int oplockEnabled = 0; +unsigned int multiuser_mount = 0; +unsigned int extended_security = 0; +unsigned int ntlmv2_support = 0; +unsigned int sign_CIFS_PDUs = 0; + +extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, + char *); +extern int cifs_umount(struct super_block *, struct cifs_sb_info *); +void cifs_proc_init(void); +void cifs_proc_clean(void); + +static int +cifs_read_super(struct super_block *sb, void *data, char *devname, int silent) +{ + struct inode *inode; + struct cifs_sb_info *cifs_sb; + int rc = 0; + + sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); + cifs_sb = CIFS_SB(sb); + cifs_sb->local_nls = load_nls_default(); /* needed for ASCII cp to Unicode converts */ + rc = cifs_mount(sb, cifs_sb, data, devname); + + if (rc) { + if (!silent) + cERROR(1, + ("cifs_mount failed w/return code = %d\n", rc)); + goto out_mount_failed; + } + + sb->s_magic = CIFS_MAGIC_NUMBER; + sb->s_op = &cifs_super_ops; + sb->s_blocksize = CIFS_MAX_MSGSIZE; /* BB check SMBSessSetup negotiated size */ + sb->s_blocksize_bits = 10; /* 2**10 = CIFS_MAX_MSGSIZE */ + inode = iget(sb, ROOT_I); + + if (!inode) + goto out_no_root; + + sb->s_root = d_alloc_root(inode); + + if (!sb->s_root) + goto out_no_root; + + return 0; + +out_no_root: + cEVENT(1, ("cifs_read_super: get root inode failed\n")); + if (inode) + iput(inode); + +/* rc = cifs_umount(sb); BB is CIFS unmount routine needed? */ + if (rc) { + cERROR(1, ("cifs_umount failed with return code %d\n", rc)); + } +out_mount_failed: + if(cifs_sb) + kfree(cifs_sb); + return -EINVAL; +} + +void +cifs_put_super(struct super_block *sb) +{ + int rc = 0; + struct cifs_sb_info *cifs_sb; + + cFYI(1, ("In cifs_put_super\n")); + cifs_sb = CIFS_SB(sb); + rc = cifs_umount(sb, cifs_sb); + if (rc) { + cERROR(1, ("cifs_umount failed with return code %d\n", rc)); + } + if(cifs_sb) { + unload_nls(cifs_sb->local_nls); + kfree(cifs_sb); + } + return; +} + +int +cifs_statfs(struct super_block *sb, struct statfs *buf) +{ + int xid, rc; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *pTcon; + + xid = GetXid(); + + cifs_sb = CIFS_SB(sb); + pTcon = cifs_sb->tcon; + + buf->f_type = CIFS_MAGIC_NUMBER; + + /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ + buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably + be length of total path, note that some servers may be + able to support more than this, but best to be safe + since Win2k and others can not handle very long filenames */ + buf->f_files = 0; /* undefined */ + buf->f_ffree = -1; /* unlimited */ + + rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls); + + /* + int f_type; + __fsid_t f_fsid; + int f_namelen; */ + /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */ + + return 0; /* always return success? what if volume is no longer available? */ +} + +static kmem_cache_t *cifs_inode_cachep; +kmem_cache_t *cifs_req_cachep; +kmem_cache_t *cifs_mid_cachep; + +static struct inode * +cifs_alloc_inode(struct super_block *sb) +{ + struct cifsInodeInfo *cifs_inode; + cifs_inode = + (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep, + SLAB_KERNEL); + if (!cifs_inode) + return NULL; + cifs_inode->cifsAttrs = 0x20; /* default */ + atomic_set(&cifs_inode->inUse, 0); + cifs_inode->time = 0; + cifs_inode->clientCanCache = 0; + INIT_LIST_HEAD(&cifs_inode->openFileList); + return &cifs_inode->vfs_inode; +} + +static void +cifs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); +} + +/* + * cifs_show_options() is for displaying mount options in /proc/mounts. + * It tries to avoid showing settings that were not changed from their + * defaults. + */ +static int +cifs_show_options(struct seq_file *s, struct vfsmount *m) +{ + struct cifs_sb_info *cifs_sb; + + cifs_sb = CIFS_SB(m->mnt_sb); + + if (cifs_sb) + if (cifs_sb->tcon) { + seq_printf(s, ", TARGET: %s ", cifs_sb->tcon->treeName); + seq_printf(s, "FS TYPE: %s ", + cifs_sb->tcon->nativeFileSystem); + if (cifs_sb->tcon->ses->userName) + seq_printf(s, " USER: %s ", + cifs_sb->tcon->ses->userName); + } + return 0; +} + +struct super_operations cifs_super_ops = { + .read_inode = cifs_read_inode, + .put_super = cifs_put_super, + .statfs = cifs_statfs, + .alloc_inode = cifs_alloc_inode, + .destroy_inode = cifs_destroy_inode, +/* .drop_inode = generic_delete_inode, + .delete_inode = cifs_delete_inode, *//* Do not need the above two functions + unless later we add lazy close of inodes or unless the kernel forgets to call + us with the same number of releases (closes) as opens */ + .show_options = cifs_show_options, +/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */ +}; + +static struct super_block * +cifs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + int rc; + struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); + + cFYI(1, ("\nDevname: %s flags: %d ", dev_name, flags)); + + if (IS_ERR(sb)) + return sb; + + sb->s_flags = flags; + + rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0); + if (rc) { + up_write(&sb->s_umount); + deactivate_super(sb); + return ERR_PTR(rc); + } + sb->s_flags |= MS_ACTIVE; + return sb; +} + +static struct file_system_type cifs_fs_type = { + .owner = THIS_MODULE, + .name = "cifs", + .get_sb = cifs_get_sb, + .kill_sb = kill_anon_super, + /* .fs_flags */ +}; +struct inode_operations cifs_dir_inode_ops = { + .create = cifs_create, + .lookup = cifs_lookup, + .unlink = cifs_unlink, + .link = cifs_hardlink, + .mkdir = cifs_mkdir, + .rmdir = cifs_rmdir, + .rename = cifs_rename, +/* revalidate:cifs_revalidate, */ + .setattr = cifs_setattr, + .symlink = cifs_symlink, +}; + +struct inode_operations cifs_file_inode_ops = { +/* revalidate:cifs_revalidate, */ + .setattr = cifs_setattr, + .rename = cifs_rename, +}; + +struct inode_operations cifs_symlink_inode_ops = { + .readlink = cifs_readlink, + .follow_link = cifs_follow_link, + /* BB add the following two eventually */ + /* revalidate: cifs_revalidate, + setattr: cifs_notify_change, *//* BB do we need notify change */ +}; + +struct file_operations cifs_file_ops = { + .read = cifs_read, + .write = cifs_write, + .open = cifs_open, + .release = cifs_close, + .lock = cifs_lock, + .fsync = cifs_fsync, +}; + +struct file_operations cifs_dir_ops = { + .readdir = cifs_readdir, + .release = cifs_closedir, +}; + +static void +cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags) +{ + struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode; + + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) { + inode_init_once(&cifsi->vfs_inode); + INIT_LIST_HEAD(&cifsi->lockList); + } +} + +int +cifs_init_inodecache(void) +{ + cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", + sizeof (struct cifsInodeInfo), + 0, SLAB_HWCACHE_ALIGN, + cifs_init_once, NULL); + if (cifs_inode_cachep == NULL) + return -ENOMEM; + + return 0; +} + +void +cifs_destroy_inodecache(void) +{ + if (kmem_cache_destroy(cifs_inode_cachep)) + printk(KERN_INFO "cifs_inode_cache: error freeing\n"); +} + +int +cifs_init_request_bufs(void) +{ + cifs_req_cachep = kmem_cache_create("cifs_request", + CIFS_MAX_MSGSIZE + + MAX_CIFS_HDR_SIZE, 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (cifs_req_cachep == NULL) + return -ENOMEM; + + return 0; +} + +void +cifs_destroy_request_bufs(void) +{ + if (kmem_cache_destroy(cifs_req_cachep)) + printk(KERN_INFO + "cifs_destroy_request_cache: error not all structures were freed\n"); +} + +int +cifs_init_mids(void) +{ + cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", + sizeof (struct mid_q_entry), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (cifs_mid_cachep == NULL) + return -ENOMEM; + + return 0; +} + +void +cifs_destroy_mids(void) +{ + if (kmem_cache_destroy(cifs_mid_cachep)) + printk(KERN_INFO + "cifs_destroy_mids: error not all structures were freed\n"); +} + +static int __init +init_cifs(void) +{ + int rc = 0; +#if CONFIG_PROC_FS + cifs_proc_init(); +#endif + INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */ + INIT_LIST_HEAD(&GlobalSMBSessionList); + INIT_LIST_HEAD(&GlobalTreeConnectionList); + +/* + * Initialize Global counters + */ + atomic_set(&sesInfoAllocCount, 0); + atomic_set(&tconInfoAllocCount, 0); + atomic_set(&bufAllocCount, 0); + atomic_set(&midCount, 0); + GlobalTotalActiveXid = 0; + GlobalMaxActiveXid = 0; + + rc = cifs_init_inodecache(); + if (!rc) { + rc = cifs_init_mids(); + if (!rc) { + rc = cifs_init_request_bufs(); + if (!rc) { + rc = register_filesystem(&cifs_fs_type); + if (!rc) + return rc; /* Success */ + else + cifs_destroy_request_bufs(); + } + cifs_destroy_mids(); + } + cifs_destroy_inodecache(); + } +#if CONFIG_PROC_FS + cifs_proc_clean(); +#endif + return rc; +} + +static void __exit +exit_cifs(void) +{ + cFYI(0, ("\nIn unregister ie exit_cifs")); +#if CONFIG_PROC_FS + cifs_proc_clean(); +#endif + unregister_filesystem(&cifs_fs_type); + cifs_destroy_inodecache(); + cifs_destroy_mids(); + cifs_destroy_request_bufs(); +} + +MODULE_AUTHOR("Steve French "); +MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */ +MODULE_DESCRIPTION + ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows"); +module_init(init_cifs) +module_exit(exit_cifs) diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifsfs.h Thu Oct 10 14:53:27 2002 @@ -0,0 +1,90 @@ +/* + * fs/cifs/cifsfs.h + * + * Copyright (c) International Business Machines Corp., 2002 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CIFSFS_H +#define _CIFSFS_H + +#define ROOT_I 2 + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +extern int map_cifs_error(int error_class, int error_code, + int status_codes_negotiated); + +extern struct address_space_operations cifs_addr_ops; + +/* Functions related to super block operations */ +extern struct super_operations cifs_super_ops; +extern void cifs_put_inode(struct inode *); +extern void cifs_read_inode(struct inode *); +extern void cifs_delete_inode(struct inode *); +/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */ + +/* Functions related to inodes */ +extern struct inode_operations cifs_dir_inode_ops; +extern int cifs_create(struct inode *, struct dentry *, int); +extern struct dentry *cifs_lookup(struct inode *, struct dentry *); +extern int cifs_unlink(struct inode *, struct dentry *); +extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); +extern int cifs_mkdir(struct inode *, struct dentry *, int); +extern int cifs_rmdir(struct inode *, struct dentry *); +extern int cifs_rename(struct inode *, struct dentry *, struct inode *, + struct dentry *); +extern int cifs_revalidate(struct dentry *); +extern int cifs_setattr(struct dentry *, struct iattr *); + +extern struct inode_operations cifs_file_inode_ops; +extern void cifs_truncate_file(struct inode *); + +extern struct inode_operations cifs_symlink_inode_ops; + +/* Functions related to files and directories */ +extern struct file_operations cifs_file_ops; +extern int cifs_open(struct inode *inode, struct file *file); +extern int cifs_close(struct inode *inode, struct file *file); +extern int cifs_closedir(struct inode *inode, struct file *file); +extern ssize_t cifs_read(struct file *file, char *read_data, + size_t read_size, loff_t * poffset); +extern ssize_t cifs_write(struct file *file, const char *write_data, + size_t write_size, loff_t * poffset); +extern int cifs_lock(struct file *, int, struct file_lock *); +extern int cifs_fsync(struct file *, struct dentry *, int); + +extern struct file_operations cifs_dir_ops; +extern int cifs_dir_open(struct inode *inode, struct file *file); +extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); + +/* Functions related to dir entries */ +extern struct dentry_operations cifs_dentry_ops; + +/* Functions related to symlinks */ +extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd); +extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen); +extern int cifs_symlink(struct inode *inode, struct dentry *direntry, + const char *symname); + +#endif /* _CIFSSMB_H */ diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifsglob.h Thu Oct 10 14:53:27 2002 @@ -0,0 +1,333 @@ +/* + * fs/cifs/cifsglob.h + * + * Copyright (c) International Business Machines Corp., 2002 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + */ +#include +#include "cifs_fs_sb.h" +/* + * The sizes of various internal tables and strings + */ +#define MAX_UID_INFO 16 +#define MAX_SES_INFO 2 +#define MAX_TCON_INFO 4 + +#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1 +#define MAX_SERVER_SIZE 15 +#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */ +#define MAX_USERNAME_SIZE 32 /* 22 is to allow for 15 char names + null + termination then *2 for unicode versions */ +#define MAX_PASSWORD_SIZE 16 + +/* + * MAX_REQ is the maximum number of requests that WE will send + * on one NetBIOS handle concurently. + */ +#define MAX_REQ (10) + +#define SERVER_NAME_LENGTH 15 +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) + +/* used to define string lengths for reversing unicode strings */ +/* (256+1)*2 = 514 */ +/* (max path length + 1 for null) * 2 for unicode */ +#define MAX_NAME 514 + +#include "cifspdu.h" + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* + * This information is kept on every Server we know about. + * + * Some things to note: + * + */ +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) + +/* + * CIFS vfs client Status information (based on what we know.) + */ + + /* associated with each tcp and smb session */ +enum statusEnum { + CifsNew = 0, + CifsGood, + CifsExiting, + CifsNeedReconnect +}; + +enum securityEnum { + NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */ + NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ + RawNTLMSSP, /* NTLMSSP without SPNEGO */ + NTLMSSP, /* NTLMSSP via SPNEGO */ + Kerberos /* Kerberos via SPNEGO */ +}; + +/* + ***************************************************************** + * Except the CIFS PDUs themselves all the + * globally interesting structs should go here + ***************************************************************** + */ + +struct TCP_Server_Info { + char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */ + char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */ + struct socket *ssocket; + struct sockaddr_in sockAddr; + wait_queue_head_t response_q; + struct list_head pending_mid_q; + void *Server_NlsInfo; /* BB - placeholder for future NLS info */ + unsigned short server_codepage; /* codepage for the server */ + unsigned long ip_address; /* IP addr for the server if known */ + unsigned long svType; /* computer type */ + char versionMajor; + char versionMinor; + int svlocal:1; /* local server or remote */ + atomic_t socketUseCount; /* indicates if the server has any open cifs sessions */ + enum statusEnum tcpStatus; /* what we think the status is */ + struct semaphore tcpSem; + struct task_struct *tsk; + char server_GUID[16]; +}; + +/* + * The following is our shortcut to user information. We surface the uid, + * and name. We always get the password on the fly in case it + * has changed. We also hang a list of sessions owned by this user off here. + */ +struct cifsUidInfo { + struct cifsUidInfo *next1; /* BB replace with list and atomicize */ + struct cifsSesInfo *ses; /* list of sessions *//* BB replace with list and atomicize */ + struct srSesInfo *sesSR; /* Save/Restore session list */ + uid_t linux_uid; + char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */ + /* BB eventually need ptr into PAM or WinBind info */ +}; + +/* + * Session structure. One of these for each uid session with a particular host + */ +struct cifsSesInfo { + struct list_head cifsSessionList; + struct semaphore sesSem; + struct cifsUidInfo *uidInfo; /* pointer to user info */ + struct TCP_Server_Info *server; /* pointer to server info */ + atomic_t inUse; /* # of CURRENT users of this ses */ + enum statusEnum status; + int dialectIndex; /* the negotiated dialect index */ + char secMode; + enum securityEnum secType; + unsigned int maxReq; /* Clients should submit no more */ + /* than maxReq distinct unanswered SMBs to the server when using */ + /* multiplexed reads or writes */ + unsigned int maxBuf; /* maxBuf specifies the maximum */ + /* message size the server can send or receive for non-raw SMBs */ + unsigned int maxRw; /* maxRw specifies the maximum */ + /* message size the server can send or receive for */ + /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ + char sessid[4]; /* unique token id for this session */ + /* (returned on Negotiate */ + __u16 ipc_tid; /* special tid for connection to IPC share */ + int capabilities; + __u16 timeZone; + char *serverOS; /* name of operating system underlying the server */ + char *serverNOS; /* name of network operating system that the server is running */ + char *serverDomain; /* security realm of server */ + int Suid; /* needed for user level security */ + char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */ + char userName[MAX_USERNAME_SIZE + 1]; /* BB remove and replace with list of cifsUidInfo structures */ +}; + +/* + * there is one of these for each connection to a resource on a particular + * session + */ +struct cifsTconInfo { + struct list_head cifsConnectionList; + struct list_head openFileList; + struct semaphore tconSem; + struct cifsSesInfo *ses; /* pointer to session associated with */ + char treeName[MAX_TREE_SIZE + 1]; /* The ascii or unicode name of this resource depending on the ses->capabilities *//* BB fill in this field */ + char *nativeFileSystem; + __u16 tid; /* The 2 byte transaction id */ + __u16 Flags; /* optional support bits */ + atomic_t useCount; /* how many mounts (explicit or implicit refer to this share */ + FILE_SYSTEM_DEVICE_INFO fsDevInfo; + FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* note file system name may be truncated - but very unlikely */ + FILE_SYSTEM_UNIX_INFO fsUnixInfo; + /* BB add field for back pointer to sb struct? */ +}; + +/* + * This info hangs off the cifsFileInfo structure. This is used to track + * byte stream locks on the file + */ +struct cifsLockInfo { + struct cifsLockInfo *next; + int start; + int length; + int type; +}; + +/* + * One of these for each open instance of a file + */ +struct cifsFileInfo { + struct list_head tlist; /* pointer to next fid owned by tcon */ + struct list_head flist; /* next fid (file instance) for this inode */ + unsigned int uid; /* allows you to find which FileInfo structure */ + __u32 pid; /* process id who opened file */ + __u16 netfid; /* file id from remote */ + /* BB add lock scope info here if needed */ ; + /* lock scope id (0 if none) */ + int endOfSearch:1; /* we have reached end of search */ + int closePend:1; /* file is marked to close */ +}; + +/* + * One of these for each file inode + */ + +struct cifsInodeInfo { + struct list_head lockList; + /* BB add in lists for dirty pages - i.e. write caching info for oplock */ + struct list_head openFileList; + __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system etc. */ + atomic_t inUse; /* num concurrent users (local openers cifs) of file */ + unsigned long time; /* jiffies of last update/check of inode */ + int clientCanCache:1; /* oplocked. We need to extend cases beyond this i.e. what + if file read-only or if file locked? or if file on r/o vol? */ + struct inode vfs_inode; +}; + +static inline struct cifsInodeInfo * +CIFS_I(struct inode *inode) +{ + return container_of(inode, struct cifsInodeInfo, vfs_inode); +} + +static inline struct cifs_sb_info * +CIFS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + + +/* one of these for every pending CIFS request to the server */ +struct mid_q_entry { + struct list_head qhead; /* mids waiting on reply from this server */ + __u16 mid; /* multiplex id */ + __u16 pid; /* process id */ + __u16 command; /* smb command code */ + struct timeval when_sent; /* time when smb sent */ + struct cifsSesInfo *ses; /* smb was sent to this server */ + struct task_struct *tsk; /* task waiting for response */ + struct smb_hdr *resp_buf; /* response buffer */ + int midState; /* wish this could be an enum but can not pass that to wait_event */ +}; + +#define MID_FREE 0 +#define MID_REQUEST_ALLOCATED 1 +#define MID_REQUEST_SUBMITTED 2 +#define MID_RESPONSE_RECEIVED 4 + +struct servers_not_supported { /* @z4a */ + struct servers_not_supported *next1; /* @z4a */ + char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* @z4a */ + /* Server Names in SMB protocol are 15 chars + X'20' */ + /* in 16th byte... @z4a */ +}; + +/* + ***************************************************************** + * All constants go here + ***************************************************************** + */ + +#define UID_HASH (16) + +/* + * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the + * following to be declared. + */ + +/* BB Every global should have an associated mutex for safe update BB */ + +#ifdef DECLARE_GLOBALS_HERE +#define GLOBAL_EXTERN +#else +#define GLOBAL_EXTERN extern +#endif + +/* + * The list of servers that did not respond with NT LM 0.12. + * This list helps improve performance and eliminate the messages indicating + * that we had a communications error talking to the server in this list. + */ +GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */ + +/* + * The following is a hash table of all the users we know about. + */ +GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH]; + +GLOBAL_EXTERN struct list_head GlobalServerList; /* BB this one is not implemented yet */ +GLOBAL_EXTERN struct list_head GlobalSMBSessionList; +GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; +/* + * Global list of free SMB structures + */ +GLOBAL_EXTERN void *GlobalFreeSMB; + +/* + * Global transaction id (XID) information + */ +GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ +GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ +GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ + +GLOBAL_EXTERN char Local_System_Name[15]; + +/* + * Global counters, updated atomically + */ +GLOBAL_EXTERN atomic_t sesInfoAllocCount; +GLOBAL_EXTERN atomic_t tconInfoAllocCount; + +/* Various Debug counters to remove someday (BB) */ +GLOBAL_EXTERN atomic_t bufAllocCount; +GLOBAL_EXTERN atomic_t midCount; + +/* Misc globals */ +GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions + to be established on existing mount if we + have the uid/password or Kerberos credential + or equivalent for current user */ +GLOBAL_EXTERN unsigned int oplockEnabled; +GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent + with more secure ntlmssp2 challenge/resp */ +GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */ +GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ + + diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/cifs/cifspdu.h Thu Oct 10 14:53:27 2002 @@ -0,0 +1,1527 @@ +/* + * fs/cifs/cifspdu.h + * + * Copyright (c) International Business Machines Corp., 2002 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CIFSPDU_H +#define _CIFSPDU_H + +#include + +#define CIFS_PROT 0 +#define BAD_PROT CIFS_PROT+1 + +/* SMB command codes */ +#define SMB_COM_CREATE_DIRECTORY 0x00 +#define SMB_COM_DELETE_DIRECTORY 0x01 +#define SMB_COM_CLOSE 0x04 +#define SMB_COM_DELETE 0x06 +#define SMB_COM_RENAME 0x07 +#define SMB_COM_LOCKING_ANDX 0x24 +#define SMB_COM_READ_ANDX 0x2E +#define SMB_COM_WRITE_ANDX 0x2F +#define SMB_COM_TRANSACTION2 0x32 +#define SMB_COM_TRANSACTION2_SECONDARY 0x33 +#define SMB_COM_TREE_DISCONNECT 0x71 +#define SMB_COM_NEGOTIATE 0x72 +#define SMB_COM_SESSION_SETUP_ANDX 0x73 +#define SMB_COM_LOGOFF_ANDX 0x74 +#define SMB_COM_TREE_CONNECT_ANDX 0x75 +#define SMB_COM_NT_TRANSACT 0xA0 +#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1 +#define SMB_COM_NT_CREATE_ANDX 0xA2 +#define SMB_COM_NT_RENAME 0xA5 + +/* Transact2 subcommand codes */ +#define TRANS2_OPEN 0x00 +#define TRANS2_FIND_FIRST 0x01 +#define TRANS2_FIND_NEXT 0x02 +#define TRANS2_QUERY_FS_INFORMATION 0x03 +#define TRANS2_QUERY_PATH_INFORMATION 0x05 +#define TRANS2_SET_PATH_INFORMATION 0x06 +#define TRANS2_QUERY_FILE_INFORMATION 0x07 +#define TRANS2_SET_FILE_INFORMATION 0x08 +#define TRANS2_GET_DFS_REFERRAL 0x10 +#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 + +/* NT Transact subcommand codes */ +#define NT_TRANSACT_CREATE 0x01 +#define NT_TRANSACT_IOCTL 0x02 +#define NT_TRANSACT_SET_SECURITY_DESC 0x03 +#define NT_TRANSACT_NOTIFY_CHANGE 0x04 +#define NT_TRANSACT_RENAME 0x05 +#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06 + +#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */ + +/* internal cifs vfs structures */ +/***************************************************************** + * All constants go here + ***************************************************************** + */ + +/* + * Starting value for maximum SMB size negotiation + */ +#define CIFS_MAX_MSGSIZE (4*1024) + +/* + * Size of encrypted user password in bytes + */ +#define CIFS_ENCPWD_SIZE (16) + +/* + * Size of the crypto key returned on the negotiate SMB in bytes + */ +#define CIFS_CRYPTO_KEY_SIZE (8) + +/* + * Size of the session key (crypto key encrypted with the password + */ +#define CIFS_SESSION_KEY_SIZE (24) + +/* + * Maximum user name length + */ +#define CIFS_UNLEN (20) + +/* + * Flags on SMB open + */ +#define SMBOPEN_WRITE_THROUGH 0x4000 +#define SMBOPEN_DENY_ALL 0x0010 +#define SMBOPEN_DENY_WRITE 0x0020 +#define SMBOPEN_DENY_READ 0x0030 +#define SMBOPEN_DENY_NONE 0x0040 +#define SMBOPEN_READ 0x0000 +#define SMBOPEN_WRITE 0x0001 +#define SMBOPEN_READWRITE 0x0002 +#define SMBOPEN_EXECUTE 0x0003 + +#define SMBOPEN_OCREATE 0x0010 +#define SMBOPEN_OTRUNC 0x0002 +#define SMBOPEN_OAPPEND 0x0001 + +/* + * SMB flag definitions + */ +#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */ +#define SMBFLG_RCV_POSTED 0x02 /* obsolete */ +#define SMBFLG_RSVD 0x04 +#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */ +#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */ +#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */ +#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */ +#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */ + +/* + * SMB flag2 definitions + */ +#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */ +#define SMBFLG2_KNOWS_EAS 0x0002 +#define SMBFLG2_SECURITY_SIGNATURE 0x0004 +#define SMBFLG2_IS_LONG_NAME 0x0040 +#define SMBFLG2_EXT_SEC 0x0800 +#define SMBFLG2_DFS 0x1000 +#define SMBFLG2_PAGING_IO 0x2000 +#define SMBFLG2_ERR_STATUS 0x4000 +#define SMBFLG2_UNICODE 0x8000 + +/* + * These are the file access permission bits defined in CIFS for the + * NTCreateAndX as well as the level 0x107 + * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO + * responds with the AccessFlags. + * The AccessFlags specifies the access permissions a caller has to the + * file and can have any suitable combination of the following values: + */ + +#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */ +#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */ +#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */ +#define FILE_READ_EA 0x00000008 /* Extended attributes associated */ + /* with the file can be read */ +#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */ + /* with the file can be written */ +#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */ + /* the file using system paging I/O */ +#define FILE_DELETE_CHILD 0x00000040 +#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */ + /* file can be read */ +#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */ + /* file can be written */ +#define DELETE 0x00010000 /* The file can be deleted */ +#define READ_CONTROL 0x00020000 /* The access control list and */ + /* ownership associated with the */ + /* file can be read */ +#define WRITE_DAC 0x00040000 /* The access control list and */ + /* ownership associated with the */ + /* file can be written. */ +#define WRITE_OWNER 0x00080000 /* Ownership information associated */ + /* with the file can be written */ +#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */ + /* synchronize with the completion */ + /* of an input/output request */ +#define GENERIC_ALL 0x10000000 +#define GENERIC_EXECUTE 0x20000000 +#define GENERIC_WRITE 0x40000000 +#define GENERIC_READ 0x80000000 + /* In summary - Relevant file */ + /* access flags from CIFS are */ + /* file_read_data, file_write_data */ + /* file_execute, file_read_attributes */ + /* write_dac, and delete. */ + +/* + * Invalid readdir handle + */ +#define CIFS_NO_HANDLE 0xFFFF + +/* IPC$ in ASCII */ +#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24" + +/* IPC$ in Unicode */ +#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00" + +/* Unicode Null terminate 2 bytes of 0 */ +#define UNICODE_NULL "\x00\x00" +#define ASCII_NULL 0x00 + +/* + * Server type values (returned on EnumServer API + */ +#define CIFS_SV_TYPE_DC 0x00000008 +#define CIFS_SV_TYPE_BACKDC 0x00000010 + +/* + * Alias type flags (From EnumAlias API call + */ +#define CIFS_ALIAS_TYPE_FILE 0x0001 +#define CIFS_SHARE_TYPE_FILE 0x0000 + +/* + * File Attribute flags + */ +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_DIRECTORY 0x0010 +#define ATTR_ARCHIVE 0x0020 +#define ATTR_DEVICE 0x0040 +#define ATTR_NORMAL 0x0080 +#define ATTR_TEMPORARY 0x0100 +#define ATTR_SPARSE 0x0200 +#define ATTR_REPARSE 0x0400 +#define ATTR_COMPRESSED 0x0800 +#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */ +#define ATTR_NOT_CONTENT_INDEXED 0x2000 +#define ATTR_ENCRYPTED 0x4000 +#define ATTR_POSIX_SEMANTICS 0x01000000 +#define ATTR_SEQUENTIAL_SCAN 0x08000000 +#define ATTR_RANDOM_ACCESS 0x10000000 +#define ATTR_NO_BUFFERING 0x20000000 +#define ATTR_WRITE_THROUGH 0x80000000 + +/* ShareAccess flags */ +#define FILE_NO_SHARE 0x00000000 +#define FILE_SHARE_READ 0x00000001 +#define FILE_SHARE_WRITE 0x00000002 +#define FILE_SHARE_DELETE 0x00000004 +#define FILE_SHARE_ALL 0x00000007 + +/* CreateDisposition flags */ +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 + +/* CreateOptions */ +#define CREATE_NOT_FILE 0x00000001 /* if set, indicates must not be file */ +#define CREATE_NOT_DIR 0x00000040 /* if set, indicates must not be directory */ + +/* ImpersonationLevel flags */ +#define SECURITY_ANONYMOUS 0 +#define SECURITY_IDENTIFICATION 1 +#define SECURITY_IMPERSONATION 2 +#define SECURITY_DELEGATION 3 + +/* SecurityFlags */ +#define SECURITY_CONTEXT_TRACKING 0x01 +#define SECURITY_EFFECTIVE_ONLY 0x02 + +/* + * Default PID value, used in all SMBs where the PID is not important + */ +#define CIFS_DFT_PID 0x1234 + +/* + * We use the same routine for Copy and Move SMBs. This flag is used to + * distinguish + */ +#define CIFS_COPY_OP 1 +#define CIFS_RENAME_OP 2 + +#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */ +#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */ + +#pragma pack(1) + +struct smb_hdr { + __u32 smb_buf_length; /* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */ + __u8 Protocol[4]; + __u8 Command; + union { + struct { + __u8 ErrorClass; + __u8 Reserved; + __u16 Error; /* note: treated as little endian (le) on wire */ + } DosError; + __u32 CifsError; /* note: le */ + } Status; + __u8 Flags; + __u16 Flags2; /* note: le */ + __u16 PidHigh; /* note: le */ + __u8 SecuritySignature[8]; /* note le */ + __u8 pad[2]; + __u16 Tid; + __u16 Pid; /* note: le */ + __u16 Uid; + __u16 Mid; + __u8 WordCount; +}; +/* given a pointer to an smb_hdr retrieve the value of byte count */ +#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) + +/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ +#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) + +/* + * Computer Name Length + */ +#define CNLEN 15 + +/* + * Share Name Length @S8A + * Note: This length is limited by the SMB used to get @S8A + * the Share info. NetShareEnum only returns 13 @S8A + * chars, including the null termination. @S8A + */ +#define SNLEN 12 /*@S8A */ + +/* + * Comment Length + */ +#define MAXCOMMENTLEN 40 + +/* + * The OS/2 maximum path name + */ +#define MAX_PATHCONF 256 + +/* + * SMB frame definitions (following must be packed structs) + * See the SNIA CIFS Specification for details. + * + * The Naming convention is the lower case version of the + * smb command code name for the struct and this is typedef to the + * uppercase version of the same name with the prefix SMB_ removed + * for brevity. Although typedefs are not commonly used for + * structure definitions in the Linux kernel, their use in the + * CIFS standards document, which this code is based on, may + * make this one of the cases where typedefs for structures make + * sense to improve readability for readers of the standards doc. + * Typedefs can always be removed later if they are too distracting + * and they are only used for the CIFSs PDUs themselves, not + * internal cifs vfs structures + * + */ + +typedef struct negotiate_req { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; + unsigned char DialectsArray[1]; +} NEGOTIATE_REQ; + +typedef struct negotiate_rsp { + struct smb_hdr hdr; /* wct = 17 */ + __u16 DialectIndex; + __u8 SecurityMode; + __u16 MaxMpxCount; + __u16 MaxNumberVcs; + __u32 MaxBufferSize; + __u32 MaxRawSize; + __u32 SessionKey; + __u32 Capabilities; /* see below */ + __u32 SystemTimeLow; + __u32 SystemTimeHigh; + __u16 ServerTimeZone; + __u8 EncryptionKeyLength; + __u16 ByteCount; + union { + unsigned char EncryptionKey[1]; /* if cap extended security is off */ + /* followed by Domain name - if extended security is off */ + /* followed by 16 bytes of server GUID */ + /* followed by security blob if cap_extended_security negotiated */ + struct { + unsigned char GUID[16]; + unsigned char SecurityBlob[1]; + } extended_response; + } u; +} NEGOTIATE_RSP; + +/* SecurityMode bits */ +#define SECMODE_USER 0x01 /* off indicates share level security */ +#define SECMODE_PW_ENCRYPT 0x02 +#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */ +#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */ + +/* Negotiate response Capabilities */ +#define CAP_RAW_MODE 0x00000001 +#define CAP_MPX_MODE 0x00000002 +#define CAP_UNICODE 0x00000004 +#define CAP_LARGE_FILES 0x00000008 +#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */ +#define CAP_RPC_REMOTE_APIS 0x00000020 +#define CAP_STATUS32 0x00000040 +#define CAP_LEVEL_II_OPLOCKS 0x00000080 +#define CAP_LOCK_AND_READ 0x00000100 +#define CAP_NT_FIND 0x00000200 +#define CAP_DFS 0x00001000 +#define CAP_INFOLEVEL_PASSTHRU 0x00002000 +#define CAP_LARGE_READ_X 0x00004000 +#define CAP_LARGE_WRITE_X 0x00008000 +#define CAP_UNIX 0x00800000 +#define CAP_RESERVED 0x02000000 +#define CAP_BULK_TRANSFER 0x20000000 +#define CAP_COMPRESSED_DATA 0x40000000 +#define CAP_EXTENDED_SECURITY 0x80000000 + +typedef union smb_com_session_setup_andx { + struct { /* request format */ + struct smb_hdr hdr; /* wct = 12 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 MaxBufferSize; + __u16 MaxMpxCount; + __u16 VcNumber; + __u32 SessionKey; + __u16 SecurityBlobLength; + __u32 Reserved; + __u32 Capabilities; /* see below */ + __u16 ByteCount; + unsigned char SecurityBlob[1]; /* followed by */ + /* STRING NativeOS */ + /* STRING NativeLanMan */ + } req; /* NTLM request format (with extended security */ + + struct { /* request format */ + struct smb_hdr hdr; /* wct = 13 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 MaxBufferSize; + __u16 MaxMpxCount; + __u16 VcNumber; + __u32 SessionKey; + __u16 CaseInsensitivePasswordLength; /* ASCII password length */ + __u16 CaseSensitivePasswordLength; /* Unicode password length */ + __u32 Reserved; /* see below */ + __u32 Capabilities; + __u16 ByteCount; + unsigned char CaseInsensitivePassword[1]; /* followed by: */ + /* unsigned char * CaseSensitivePassword; */ + /* STRING AccountName */ + /* STRING PrimaryDomain */ + /* STRING NativeOS */ + /* STRING NativeLanMan */ + } req_no_secext; /* NTLM request format (without extended security */ + + struct { /* default (NTLM) response format */ + struct smb_hdr hdr; /* wct = 4 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Action; /* see below */ + __u16 SecurityBlobLength; + __u16 ByteCount; + unsigned char SecurityBlob[1]; /* followed by */ +/* unsigned char * NativeOS; */ +/* unsigned char * NativeLanMan; */ +/* unsigned char * PrimaryDomain; */ + } resp; /* NTLM response format (with or without extended security */ + + struct { /* request format */ + struct smb_hdr hdr; /* wct = 10 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 MaxBufferSize; + __u16 MaxMpxCount; + __u16 VcNumber; + __u32 SessionKey; + __u16 PassswordLength; + __u32 Reserved; + __u16 ByteCount; + unsigned char AccountPassword[1]; /* followed by */ + /* STRING AccountName */ + /* STRING PrimaryDomain */ + /* STRING NativeOS */ + /* STRING NativeLanMan */ + } old_req; /* pre-NTLM (LANMAN2.1) request format */ + + struct { /* default (NTLM) response format */ + struct smb_hdr hdr; /* wct = 3 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Action; /* see below */ + __u16 ByteCount; + unsigned char NativeOS[1]; /* followed by */ +/* unsigned char * NativeLanMan; */ +/* unsigned char * PrimaryDomain; */ + } old_resp; /* pre-NTLM (LANMAN2.1) response format */ +} SESSION_SETUP_ANDX; + +#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" + +/* Capabilities bits (for NTLM SessSetup request) */ +#define CAP_UNICODE 0x00000004 +#define CAP_LARGE_FILES 0x00000008 +#define CAP_NT_SMBS 0x00000010 +#define CAP_STATUS32 0x00000040 +#define CAP_LEVEL_II_OPLOCKS 0x00000080 +#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */ +#define CAP_BULK_TRANSFER 0x20000000 +#define CAP_EXTENDED_SECURITY 0x80000000 + +/* Action bits */ +#define GUEST_LOGIN 1 + +typedef struct smb_com_tconx_req { + struct smb_hdr hdr; /* wct = 4 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Flags; /* see below */ + __u16 PasswordLength; + __u16 ByteCount; + unsigned char Password[1]; /* followed by */ +/* STRING Path *//* \\server\share name */ + /* STRING Service */ +} TCONX_REQ; + +typedef struct smb_com_tconx_rsp { + struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 OptionalSupport; /* see below */ + __u16 ByteCount; + unsigned char Service[1]; /* always ASCII, not Unicode */ + /* STRING NativeFileSystem */ +} TCONX_RSP; + +/* tree connect Flags */ +#define DISCONNECT_TID 0x0001 +#define TCON_EXTENDED_SECINFO 0x0008 +/* OptionalSupport bits */ +#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */ +#define SMB_SHARE_IS_IN_DFS 0x0002 + +typedef struct smb_com_logoff_andx_req { + + struct smb_hdr hdr; /* wct = 2 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 ByteCount; +} LOGOFF_ANDX_REQ; + +typedef struct smb_com_logoff_andx_rsp { + struct smb_hdr hdr; /* wct = 2 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 ByteCount; +} LOGOFF_ANDX_RSP; + +typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */ + struct { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; /* bcc = 0 */ + } req; + struct { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; /* bcc = 0 */ + } resp; +} TREE_DISCONNECT; + +typedef struct smb_com_close_req { + struct smb_hdr hdr; /* wct = 3 */ + __u16 FileID; /* target file attributes */ + __u32 LastWriteTime; /* should be zero */ + __u16 ByteCount; /* 0 */ +} CLOSE_REQ; + +typedef struct smb_com_close_rsp { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; /* bct = 0 */ +} CLOSE_RSP; + +/* OpenFlags */ +#define REQ_OPLOCK 0x00000002 +#define REQ_BATCHOPLOCK 0x00000004 +#define REQ_OPENDIRONLY 0x00000008 + +typedef struct smb_com_open_req { /* also handles create */ + struct smb_hdr hdr; /* wct = 24 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u8 Reserved; /* Must Be Zero */ + __u16 NameLength; + __u32 OpenFlags; + __u32 RootDirectoryFid; + __u32 DesiredAccess; + __u64 AllocationSize; + __u32 FileAttributes; + __u32 ShareAccess; + __u32 CreateDisposition; + __u32 CreateOptions; + __u32 ImpersonationLevel; + __u8 SecurityFlags; + __u16 ByteCount; + char fileName[1]; +} OPEN_REQ; + +typedef struct smb_com_open_rsp { + struct smb_hdr hdr; /* wct = 34 BB */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u8 OplockLevel; + __u16 Fid; + __u32 CreateAction; + __u64 CreationTime; + __u64 LastAccessTime; + __u64 LastWriteTime; + __u64 ChangeTime; + __u32 FileAttributes; + __u64 AllocationSize; + __u64 EndOfFile; + __u16 FileType; + __u16 DeviceState; + __u8 DirectoryFlag; + __u16 ByteCount; /* bct = 0 */ +} OPEN_RSP; + +typedef struct smb_com_write_req { + struct smb_hdr hdr; /* wct = 14 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Fid; + __u32 OffsetLow; + __u32 Reserved; + __u16 WriteMode; + __u16 Remaining; + __u16 DataLengthHigh; + __u16 DataLengthLow; + __u16 DataOffset; + __u32 OffsetHigh; + __u16 ByteCount; + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ + char Data[1]; +} WRITE_REQ; + +typedef struct smb_com_write_rsp { + struct smb_hdr hdr; /* wct = 6 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Count; + __u16 Remaining; + __u32 Reserved; + __u16 ByteCount; +} WRITE_RSP; + +typedef struct smb_com_read_req { + struct smb_hdr hdr; /* wct = 12 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Fid; + __u32 OffsetLow; + __u16 MaxCount; + __u16 MinCount; /* obsolete */ + __u32 MaxCountHigh; + __u16 Remaining; + __u32 OffsetHigh; + __u16 ByteCount; +} READ_REQ; + +typedef struct smb_com_read_rsp { + struct smb_hdr hdr; /* wct = 12 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Remaining; + __u16 DataCompactionMode; + __u16 Reserved; + __u16 DataLength; + __u16 DataOffset; + __u16 DataLengthHigh; + __u64 Reserved2; + __u16 ByteCount; + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ + char Data[1]; +} READ_RSP; + +typedef struct locking_andx_range { + __u16 Pid; + __u16 Pad; + __u64 Offset; + __u64 Length; +} LOCKING_ANDX_RANGE; + +#define LOCKING_ANDX_SHARED_LOCK 0x01 +#define LOCKING_ANDX_OPLOCK_RELEASE 0x02 +#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 +#define LOCKING_ANDX_CANCEL_LOCK 0x08 +#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */ + +typedef struct smb_com_lock_req { + struct smb_hdr hdr; /* wct = 8 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 Fid; + __u8 LockType; + __u8 OplockLevel; + __u32 Timeout; + __u16 NumberOfUnlocks; + __u16 NumberOfLocks; + __u16 ByteCount; + LOCKING_ANDX_RANGE Locks[1]; +} LOCK_REQ; + +typedef struct smb_com_lock_rsp { + struct smb_hdr hdr; /* wct = 2 */ + __u8 AndXCommand; + __u8 AndXReserved; + __u16 AndXOffset; + __u16 ByteCount; +} LOCK_RSP; + +typedef struct smb_com_rename_req { + struct smb_hdr hdr; /* wct = 1 */ + __u16 SearchAttributes; /* target file attributes */ + __u16 ByteCount; + __u8 BufferFormat; /* 4 = ASCII or Unicode */ + unsigned char OldFileName[1]; + /* followed by __u8 BufferFormat2 */ + /* followed by NewFileName */ +} RENAME_REQ; + +#define CREATE_HARD_LINK 0x103 +typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */ + struct smb_hdr hdr; /* wct = 4 */ + __u16 SearchAttributes; /* target file attributes */ + __u16 Flags; /* spec says Information Level */ + __u32 ClusterCount; + __u16 ByteCount; + __u8 BufferFormat; /* 4 = ASCII or Unicode */ + unsigned char OldFileName[1]; + /* followed by __u8 BufferFormat2 */ + /* followed by NewFileName */ +} NT_RENAME_REQ; + +typedef struct smb_com_rename_rsp { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; /* bct = 0 */ +} RENAME_RSP; + +typedef struct smb_com_delete_file_req { + struct smb_hdr hdr; /* wct = 1 */ + __u16 SearchAttributes; + __u16 ByteCount; + __u8 BufferFormat; /* 4 = ASCII */ + unsigned char fileName[1]; +} DELETE_FILE_REQ; + +typedef struct smb_com_delete_file_rsp { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; /* bct = 0 */ +} DELETE_FILE_RSP; + +typedef struct smb_com_delete_directory_req { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; + __u8 BufferFormat; /* 4 = ASCII */ + unsigned char DirName[1]; +} DELETE_DIRECTORY_REQ; + +typedef struct smb_com_delete_directory_rsp { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; /* bct = 0 */ +} DELETE_DIRECTORY_RSP; + +typedef struct smb_com_create_directory_req { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; + __u8 BufferFormat; /* 4 = ASCII */ + unsigned char DirName[1]; +} CREATE_DIRECTORY_REQ; + +typedef struct smb_com_create_directory_rsp { + struct smb_hdr hdr; /* wct = 0 */ + __u16 ByteCount; /* bct = 0 */ +} CREATE_DIRECTORY_RSP; + +typedef struct smb_com_nt_transaction_ioctl_req { + struct smb_hdr hdr; /* wct = 23 */ + __u8 MaxSetupCount; + __u16 Reserved; + __u32 TotalParameterCount; + __u32 TotalDataCount; + __u32 MaxParameterCount; + __u32 MaxDataCount; + __u32 ParameterCount; + __u32 ParameterOffset; + __u32 DataCount; + __u32 DataOffset; + __u8 SetupCount; /* four setup words follow subcommand */ + /* SNIA spec incorrectly included spurious pad here */ + __u16 SubCommand; /* 2 = IOCTL/FSCTL */ + __u32 FunctionCode; + __u16 Fid; + __u8 IsFSCTLFlag; /* 1 = File System Control, 0 = device control (IOCTL) */ + __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share) */ + __u16 ByteCount; + __u8 Pad[3]; + __u8 Data[1]; +} TRANSACT_IOCTL_REQ; + +typedef struct smb_com_transaction_ioctl_rsp { + struct smb_hdr hdr; /* wct = 19 */ + __u8 Reserved[3]; + __u32 TotalParameterCount; + __u32 TotalDataCount; + __u32 ParameterCount; + __u32 ParameterOffset; + __u32 ParameterDisplacement; + __u32 DataCount; + __u32 DataOffset; + __u32 DataDisplacement; + __u8 SetupCount; /* 1 */ + __u16 ReturnedDataLen; + __u16 ByteCount; + __u8 Pad[3]; +} TRANSACT_IOCTL_RSP; + +typedef union smb_com_transaction2 { + struct { + struct smb_hdr hdr; /* wct = 14+ */ + __u16 TotalParameterCount; + __u16 TotalDataCount; + __u16 MaxParameterCount; + __u16 MaxDataCount; + __u8 MaxSetupCount; + __u8 Reserved; + __u16 Flags; + __u32 Timeout; + __u16 Reserved2; + __u16 ParameterCount; + __u16 ParameterOffset; + __u16 DataCount; + __u16 DataOffset; + __u8 SetupCount; + __u8 Reserved3; + __u16 SubCommand; /* 1st setup word