diff options
Diffstat (limited to 'target/linux/generic-2.4/patches/107-cifs.patch')
-rw-r--r-- | target/linux/generic-2.4/patches/107-cifs.patch | 21977 |
1 files changed, 0 insertions, 21977 deletions
diff --git a/target/linux/generic-2.4/patches/107-cifs.patch b/target/linux/generic-2.4/patches/107-cifs.patch deleted file mode 100644 index e2ff33d..0000000 --- a/target/linux/generic-2.4/patches/107-cifs.patch +++ /dev/null @@ -1,21977 +0,0 @@ ---- a/Documentation/Configure.help -+++ b/Documentation/Configure.help -@@ -18007,6 +18007,34 @@ CONFIG_UNIXWARE_DISKLABEL - - If you don't know what all this is about, 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, Windows 2003 (including -+ Windows XP) as well by Samba (which provides excellent CIFS -+ server support for Linux and many other operating systems). -+ The smbfs module should be used instead of this cifs module for -+ mounting to older SMB servers such as OS/2. The smbfs and cifs -+ modules can coexist and do not conflict. -+ -+ The intent of this module is to provide the most advanced network -+ file system function for CIFS compliant servers, including better -+ POSIX compliance, secure per-user session establishment, high -+ performance safe distributed caching (oplock), optional packet -+ signing, Unicode support and other internationalization improvements -+ For more information see the project page at -+ http://us1.samba.org/samba/Linux_CIFS_client.html -+ -+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. -+ - SMB file system support (to mount Windows shares etc.) - CONFIG_SMB_FS - SMB (Server Message Block) is the protocol Windows for Workgroups ---- a/Documentation/filesystems/00-INDEX -+++ b/Documentation/filesystems/00-INDEX -@@ -10,6 +10,8 @@ befs.txt - - info for the BeOS file system (BFS) - bfs.txt - - info for the SCO UnixWare Boot Filesystem (BFS). -+cifs.txt -+ - info on the Common Internet File System (CIFS) - coda.txt - - description of the CODA filesystem. - cramfs.txt ---- /dev/null -+++ b/Documentation/filesystems/cifs.txt -@@ -0,0 +1,51 @@ -+ 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, Windows 2003 (including -+ Windows XP) as well by Samba (which provides excellent CIFS -+ server support for Linux and many other operating systems), so -+ this network filesystem client can mount to a wide variety of -+ servers. The smbfs module should be used instead of this cifs module -+ for mounting to older SMB servers such as OS/2. The smbfs and cifs -+ modules can coexist and do not conflict. 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 SMB/CIFS file server. -+ -+ The intent of this module is to provide the most advanced network -+ file system function for CIFS compliant servers, including better -+ POSIX compliance, secure per-user session establishment, high -+ performance safe distributed caching (oplock), optional packet -+ signing, large files, Unicode support and other internationalization -+ improvements. Since both Samba server and this filesystem client support -+ the CIFS Unix extensions, the combination can provide a reasonable -+ alternative to NFSv4 for fileserving in some Linux to Linux environments, -+ not just in Linux to Windows environments. -+ -+ This filesystem has an optional mount utility (mount.cifs) that can -+ be obtained from the project page and installed in the path in the same -+ directory with the other mount helpers (such as mount.smbfs). -+ Mounting using the cifs filesystem without installing the mount helper -+ requires specifying the server's ip address. -+ -+ For Linux 2.4: -+ mount //anything/here /mnt_target -o -+ user=username,pass=password,unc=//ip_address_of_server/sharename -+ -+ For Linux 2.5: -+ mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password -+ -+ -+ For more information on the module see the project page at -+ -+ http://us1.samba.org/samba/Linux_CIFS_client.html -+ -+ For more information on CIFS see: -+ -+ http://www.snia.org/tech_activities/CIFS -+ -+ or the Samba site: -+ -+ http://www.samba.org ---- /dev/null -+++ b/fs/cifs/asn1.c -@@ -0,0 +1,614 @@ -+/* -+ * 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 <linux/config.h> -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/kernel.h> -+#include <linux/mm.h> -+#include <linux/slab.h> -+#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 = NULL; -+ 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) -+{ -+ unsigned 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; -+ -+ *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */ -+ -+ /* cifs_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, ("Error decoding negTokenInit header ")); -+ return 0; -+ } else if ((cls != ASN1_APL) || (con != ASN1_CON) -+ || (tag != ASN1_EOC)) { -+ cFYI(1, ("cls = %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, ("Error decoding negTokenInit header")); -+ return 0; -+ } -+ -+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { -+ cFYI(1, ("Error decoding negTokenInit ")); -+ return 0; -+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON) -+ || (tag != ASN1_EOC)) { -+ cFYI(1,("cls = %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, ("Error decoding negTokenInit ")); -+ return 0; -+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON) -+ || (tag != ASN1_SEQ)) { -+ cFYI(1,("cls = %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, ("Error decoding 2nd part of negTokenInit ")); -+ return 0; -+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON) -+ || (tag != ASN1_EOC)) { -+ cFYI(1, -+ ("cls = %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, ("Error decoding 2nd part of negTokenInit ")); -+ return 0; -+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON) -+ || (tag != ASN1_SEQ)) { -+ cFYI(1, -+ ("cls = %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, -+ ("Error 1 decoding negTokenInit header exit 2")); -+ return 0; -+ } -+ if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { -+ asn1_oid_decode(&ctx, end, &oid, &oidlen); -+ cFYI(1, -+ ("OID 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,("This should be an oid what is going on? ")); -+ } -+ } -+ -+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { -+ cFYI(1, -+ ("Error decoding last part of negTokenInit exit 3")); -+ return 0; -+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */ -+ cFYI(1, -+ ("Exit 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, -+ ("Error decoding last part of negTokenInit exit 5")); -+ return 0; -+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON) -+ || (tag != ASN1_SEQ)) { -+ cFYI(1, -+ ("Exit 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, -+ ("Error decoding last part of negTokenInit exit 7")); -+ return 0; -+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { -+ cFYI(1, -+ ("Exit 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, -+ ("Error decoding last part of negTokenInit exit 9")); -+ return 0; -+ } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) -+ || (tag != ASN1_GENSTR)) { -+ cFYI(1, -+ ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)", -+ cls, con, tag, end, *end)); -+ return 0; -+ } -+ cFYI(1, ("Need 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; -+} ---- /dev/null -+++ b/fs/cifs/AUTHORS -@@ -0,0 +1,37 @@ -+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. -+ -+Patch Contributors -+------------------ -+Zwane Mwaikambo -+Andi Kleen -+Amrut Joshi -+Shobhit Dayal -+Sergey Vlasov -+Richard Hughes -+Yury Umanets -+ -+Test case and Bug Report contributors -+------------------------------------- -+Thanks to those in the community who have submitted detailed bug reports -+and debug of problems they have found: Jochen Dolze, David Blaine, -+Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, -+Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, -+Olaf Kirch, Kieron Briggs, Nick Millington and others. -+ -+And thanks to the IBM LTC and Power test teams and SuSE testers for -+finding multiple bugs during excellent stress test runs. ---- /dev/null -+++ b/fs/cifs/CHANGES -@@ -0,0 +1,572 @@ -+Version 1.20 -+------------ -+Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps -+info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir -+(in build_wildcard_path_from_dentry). Fix mknod to pass type field -+(block/char/fifo) properly. Remove spurious mount warning log entry when -+credentials passed as mount argument. Set major/minor device number in -+inode for block and char devices when unix extensions enabled. -+ -+Version 1.19 -+------------ -+Fix /proc/fs/cifs/Stats and DebugData display to handle larger -+amounts of return data. Properly limit requests to MAX_REQ (50 -+is the usual maximum active multiplex SMB/CIFS requests per server). -+Do not kill cifsd (and thus hurt the other SMB session) when more than one -+session to the same server (but with different userids) exists and one -+of the two user's smb sessions is being removed while leaving the other. -+Do not loop reconnecting in cifsd demultiplex thread when admin -+kills the thread without going through unmount. -+ -+Version 1.18 -+------------ -+Do not rename hardlinked files (since that should be a noop). Flush -+cached write behind data when reopening a file after session abend, -+except when already in write. Grab per socket sem during reconnect -+to avoid oops in sendmsg if overlapping with reconnect. Do not -+reset cached inode file size on readdir for files open for write on -+client. -+ -+ -+Version 1.17 -+------------ -+Update number of blocks in file so du command is happier (in Linux a fake -+blocksize of 512 is required for calculating number of blocks in inode). -+Fix prepare write of partial pages to read in data from server if possible. -+Fix race on tcpStatus field between unmount and reconnection code, causing -+cifsd process sometimes to hang around forever. Improve out of memory -+checks in cifs_filldir -+ -+Version 1.16 -+------------ -+Fix incorrect file size in file handle based setattr on big endian hardware. -+Fix oops in build_path_from_dentry when out of memory. Add checks for invalid -+and closing file structs in writepage/partialpagewrite. Add statistics -+for each mounted share (new menuconfig option). Fix endianness problem in -+volume information displayed in /proc/fs/cifs/DebugData (only affects -+affects big endian architectures). Prevent renames while constructing -+path names for open, mkdir and rmdir. -+ -+Version 1.15 -+------------ -+Change to mempools for alloc smb request buffers and multiplex structs -+to better handle low memory problems (and potential deadlocks). -+ -+Version 1.14 -+------------ -+Fix incomplete listings of large directories on Samba servers when Unix -+extensions enabled. Fix oops when smb_buffer can not be allocated. Fix -+rename deadlock when writing out dirty pages at same time. -+ -+Version 1.13 -+------------ -+Fix open of files in which O_CREATE can cause the mode to change in -+some cases. Fix case in which retry of write overlaps file close. -+Fix PPC64 build error. Reduce excessive stack usage in smb password -+hashing. Fix overwrite of Linux user's view of file mode to Windows servers. -+ -+Version 1.12 -+------------ -+Fixes for large file copy, signal handling, socket retry, buffer -+allocation and low memory situations. -+ -+Version 1.11 -+------------ -+Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize) -+also now allowing support for specifying client netbiosname. NT4 support added. -+ -+Version 1.10 -+------------ -+Fix reconnection (and certain failed mounts) to properly wake up the -+blocked users thread so it does not seem hung (in some cases was blocked -+until the cifs receive timeout expired). Fix spurious error logging -+to kernel log when application with open network files killed. -+ -+Version 1.09 -+------------ -+Fix /proc/fs module unload warning message (that could be logged -+to the kernel log). Fix intermittent failure in connectathon -+test7 (hardlink count not immediately refreshed in case in which -+inode metadata can be incorrectly kept cached when time near zero) -+ -+Version 1.08 -+------------ -+Allow file_mode and dir_mode (specified at mount time) to be enforced -+locally (the server already enforced its own ACLs too) for servers -+that do not report the correct mode (do not support the -+CIFS Unix Extensions). -+ -+Version 1.07 -+------------ -+Fix some small memory leaks in some unmount error paths. Fix major leak -+of cache pages in readpages causing multiple read oriented stress -+testcases (including fsx, and even large file copy) to fail over time. -+ -+Version 1.06 -+------------ -+Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server. -+This allows files that differ only in case and improves performance of file -+creation and file open to such servers. Fix semaphore conflict which causes -+slow delete of open file to Samba (which unfortunately can cause an oplock -+break to self while vfs_unlink held i_sem) which can hang for 20 seconds. -+ -+Version 1.05 -+------------ -+fixes to cifs_readpages for fsx test case -+ -+Version 1.04 -+------------ -+Fix caching data integrity bug when extending file size especially when no -+oplock on file. Fix spurious logging of valid already parsed mount options -+that are parsed outside of the cifs vfs such as nosuid. -+ -+ -+Version 1.03 -+------------ -+Connect to server when port number override not specified, and tcp port -+unitialized. Reset search to restart at correct file when kernel routine -+filldir returns error during large directory searches (readdir). -+ -+Version 1.02 -+------------ -+Fix caching problem when files opened by multiple clients in which -+page cache could contain stale data, and write through did -+not occur often enough while file was still open when read ahead -+(read oplock) not allowed. Treat "sep=" when first mount option -+as an overrride of comma as the default separator between mount -+options. -+ -+Version 1.01 -+------------ -+Allow passwords longer than 16 bytes. Allow null password string. -+ -+Version 1.00 -+------------ -+Gracefully clean up failed mounts when attempting to mount to servers such as -+Windows 98 that terminate tcp sessions during prototocol negotiation. Handle -+embedded commas in mount parsing of passwords. -+ -+Version 0.99 -+------------ -+Invalidate local inode cached pages on oplock break and when last file -+instance is closed so that the client does not continue using stale local -+copy rather than later modified server copy of file. Do not reconnect -+when server drops the tcp session prematurely before negotiate -+protocol response. Fix oops in roepen_file when dentry freed. Allow -+the support for CIFS Unix Extensions to be disabled via proc interface. -+ -+Version 0.98 -+------------ -+Fix hang in commit_write during reconnection of open files under heavy load. -+Fix unload_nls oops in a mount failure path. Serialize writes to same socket -+which also fixes any possible races when cifs signatures are enabled in SMBs -+being sent out of signature sequence number order. -+ -+Version 0.97 -+------------ -+Fix byte range locking bug (endian problem) causing bad offset and -+length. -+ -+Version 0.96 -+------------ -+Fix oops (in send_sig) caused by CIFS unmount code trying to -+wake up the demultiplex thread after it had exited. Do not log -+error on harmless oplock release of closed handle. -+ -+Version 0.95 -+------------ -+Fix unsafe global variable usage and password hash failure on gcc 3.3.1 -+Fix problem reconnecting secondary mounts to same server after session -+failure. Fix invalid dentry - race in mkdir when directory gets created -+by another client between the lookup and mkdir. -+ -+Version 0.94 -+------------ -+Fix to list processing in reopen_files. Fix reconnection when server hung -+but tcpip session still alive. Set proper timeout on socket read. -+ -+Version 0.93 -+------------ -+Add missing mount options including iocharset. SMP fixes in write and open. -+Fix errors in reconnecting after TCP session failure. Fix module unloading -+of default nls codepage -+ -+Version 0.92 -+------------ -+Active smb transactions should never go negative (fix double FreeXid). Fix -+list processing in file routines. Check return code on kmalloc in open. -+Fix spinlock usage for SMP. -+ -+Version 0.91 -+------------ -+Fix oops in reopen_files when invalid dentry. drop dentry on server rename -+and on revalidate errors. Fix cases where pid is now tgid. Fix return code -+on create hard link when server does not support them. -+ -+Version 0.90 -+------------ -+Fix scheduling while atomic error in getting inode info on newly created file. -+Fix truncate of existing files opened with O_CREAT but not O_TRUNC set. -+ -+Version 0.89 -+------------ -+Fix oops on write to dead tcp session. Remove error log write for case when file open -+O_CREAT but not O_EXCL -+ -+Version 0.88 -+------------ -+Fix non-POSIX behavior on rename of open file and delete of open file by taking -+advantage of trans2 SetFileInfo rename facility if available on target server. -+Retry on ENOSPC and EAGAIN socket errors. -+ -+Version 0.87 -+------------ -+Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix -+allocation size miscalculation. After oplock token lost do not read through -+cache. -+ -+Version 0.86 -+------------ -+Fix oops on empty file readahead. Fix for file size handling for locally cached files. -+ -+Version 0.85 -+------------ -+Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files -+during auto reconnection to server after server recovered from failure. -+ -+Version 0.84 -+------------ -+Finish support for Linux 2.5 open/create changes, which removes the -+redundant NTCreate/QPathInfo/close that was sent during file create. -+Enable oplock by default. Enable packet signing by default (needed to -+access many recent Windows servers) -+ -+Version 0.83 -+------------ -+Fix oops when mounting to long server names caused by inverted parms to kmalloc. -+Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled -+we will choose a cifs user session (smb uid) that better matches the local -+uid if a) the mount uid does not match the current uid and b) we have another -+session to the same server (ip address) for a different mount which -+matches the current local uid. -+ -+Version 0.82 -+------------ -+Add support for mknod of block or character devices. Fix oplock -+code (distributed caching) to properly send response to oplock -+break from server. -+ -+Version 0.81 -+------------ -+Finish up CIFS packet digital signing for the default -+NTLM security case. This should help Windows 2003 -+network interoperability since it is common for -+packet signing to be required now. Fix statfs (stat -f) -+which recently started returning errors due to -+invalid value (-1 instead of 0) being set in the -+struct kstatfs f_ffiles field. -+ -+Version 0.80 -+----------- -+Fix oops on stopping oplock thread when removing cifs when -+built as module. -+ -+Version 0.79 -+------------ -+Fix mount options for ro (readonly), uid, gid and file and directory mode. -+ -+Version 0.78 -+------------ -+Fix errors displayed on failed mounts to be more understandable. -+Fixed various incorrect or misleading smb to posix error code mappings. -+ -+Version 0.77 -+------------ -+Fix display of NTFS DFS junctions to display as symlinks. -+They are the network equivalent. Fix oops in -+cifs_partialpagewrite caused by missing spinlock protection -+of openfile linked list. Allow writebehind caching errors to -+be returned to the application at file close. -+ -+Version 0.76 -+------------ -+Clean up options displayed in /proc/mounts by show_options to -+be more consistent with other filesystems. -+ -+Version 0.75 -+------------ -+Fix delete of readonly file to Windows servers. Reflect -+presence or absence of read only dos attribute in mode -+bits for servers that do not support CIFS Unix extensions. -+Fix shortened results on readdir of large directories to -+servers supporting CIFS Unix extensions (caused by -+incorrect resume key). -+ -+Version 0.74 -+------------ -+Fix truncate bug (set file size) that could cause hangs e.g. running fsx -+ -+Version 0.73 -+------------ -+unload nls if mount fails. -+ -+Version 0.72 -+------------ -+Add resume key support to search (readdir) code to workaround -+Windows bug. Add /proc/fs/cifs/LookupCacheEnable which -+allows disabling caching of attribute information for -+lookups. -+ -+Version 0.71 -+------------ -+Add more oplock handling (distributed caching code). Remove -+dead code. Remove excessive stack space utilization from -+symlink routines. -+ -+Version 0.70 -+------------ -+Fix oops in get dfs referral (triggered when null path sent in to -+mount). Add support for overriding rsize at mount time. -+ -+Version 0.69 -+------------ -+Fix buffer overrun in readdir which caused intermittent kernel oopses. -+Fix writepage code to release kmap on write data. Allow "-ip=" new -+mount option to be passed in on parameter distinct from the first part -+(server name portion of) the UNC name. Allow override of the -+tcp port of the target server via new mount option "-port=" -+ -+Version 0.68 -+------------ -+Fix search handle leak on rewind. Fix setuid and gid so that they are -+reflected in the local inode immediately. Cleanup of whitespace -+to make 2.4 and 2.5 versions more consistent. -+ -+ -+Version 0.67 -+------------ -+Fix signal sending so that captive thread (cifsd) exits on umount -+(which was causing the warning in kmem_cache_free of the request buffers -+at rmmod time). This had broken as a sideeffect of the recent global -+kernel change to daemonize. Fix memory leak in readdir code which -+showed up in "ls -R" (and applications that did search rewinding). -+ -+Version 0.66 -+------------ -+Reconnect tids and fids after session reconnection (still do not -+reconnect byte range locks though). Fix problem caching -+lookup information for directory inodes, improving performance, -+especially in deep directory trees. Fix various build warnings. -+ -+Version 0.65 -+------------ -+Finish fixes to commit write for caching/readahead consistency. fsx -+now works to Samba servers. Fix oops caused when readahead -+was interrupted by a signal. -+ -+Version 0.64 -+------------ -+Fix data corruption (in partial page after truncate) that caused fsx to -+fail to Windows servers. Cleaned up some extraneous error logging in -+common error paths. Add generic sendfile support. -+ -+Version 0.63 -+------------ -+Fix memory leak in AllocMidQEntry. -+Finish reconnection logic, so connection with server can be dropped -+(or server rebooted) and the cifs client will reconnect. -+ -+Version 0.62 -+------------ -+Fix temporary socket leak when bad userid or password specified -+(or other SMBSessSetup failure). Increase maximum buffer size to slightly -+over 16K to allow negotiation of up to Samba and Windows server default read -+sizes. Add support for readpages -+ -+Version 0.61 -+------------ -+Fix oops when username not passed in on mount. Extensive fixes and improvements -+to error logging (strip redundant newlines, change debug macros to ensure newline -+passed in and to be more consistent). Fix writepage wrong file handle problem, -+a readonly file handle could be incorrectly used to attempt to write out -+file updates through the page cache to multiply open files. This could cause -+the iozone benchmark to fail on the fwrite test. Fix bug mounting two different -+shares to the same Windows server when using different usernames -+(doing this to Samba servers worked but Windows was rejecting it) - now it is -+possible to use different userids when connecting to the same server from a -+Linux client. Fix oops when treeDisconnect called during unmount on -+previously freed socket. -+ -+Version 0.60 -+------------ -+Fix oops in readpages caused by not setting address space operations in inode in -+rare code path. -+ -+Version 0.59 -+------------ -+Includes support for deleting of open files and renaming over existing files (per POSIX -+requirement). Add readlink support for Windows junction points (directory symlinks). -+ -+Version 0.58 -+------------ -+Changed read and write to go through pagecache. Added additional address space operations. -+Memory mapped operations now working. -+ -+Version 0.57 -+------------ -+Added writepage code for additional memory mapping support. Fixed leak in xids causing -+the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on -+every stat call. Additional formatting cleanup. -+ -+Version 0.56 -+------------ -+Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup. -+ -+Version 0.55 -+------------ -+Fixes from Zwane Mwaikambo for adding missing return code checking in a few places. -+Also included a modified version of his fix to protect global list manipulation of -+the smb session and tree connection and mid related global variables. -+ -+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 compatibility 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 -+ ---- /dev/null -+++ b/fs/cifs/cifs_debug.c -@@ -0,0 +1,797 @@ -+/* -+ * fs/cifs_debug.c -+ * -+ * Copyright (C) International Business Machines Corp., 2000,2003 -+ * -+ * 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 <linux/fs.h> -+#include <linux/string.h> -+#include <linux/ctype.h> -+#include <linux/module.h> -+#include <linux/proc_fs.h> -+#include <asm/uaccess.h> -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_debug.h" -+ -+void -+cifs_dump_mem(char *label, void *data, int length) -+{ -+ int i, j; -+ int *intptr = data; -+ char *charptr = data; -+ char buf[10], line[80]; -+ -+ printk(KERN_DEBUG "%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(KERN_DEBUG "%s\n", line); -+ } -+} -+ -+#ifdef 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 list_head *tmp1; -+ struct mid_q_entry * mid_entry; -+ struct cifsSesInfo *ses; -+ struct cifsTconInfo *tcon; -+ int i; -+ int length = 0; -+ char * original_buf = buf; -+ -+ *beginBuffer = buf + offset; -+ -+ -+ length = -+ sprintf(buf, -+ "Display Internal CIFS Data Structures for Debugging\n" -+ "---------------------------------------------------\n"); -+ buf += length; -+ -+ length = sprintf(buf, "Servers:\n"); -+ buf += length; -+ -+ i = 0; -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(tmp, &GlobalSMBSessionList) { -+ i++; -+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); -+ length = -+ sprintf(buf, -+ "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d", -+ i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), -+ ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus); -+ buf += length; -+ if(ses->server) { -+ buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d", -+ atomic_read(&ses->server->socketUseCount), -+ ses->server->secMode, -+ atomic_read(&ses->server->inFlight)); -+ -+ length = sprintf(buf, "\nMIDs: \n"); -+ buf += length; -+ -+ spin_lock(&GlobalMid_Lock); -+ list_for_each(tmp1, &ses->server->pending_mid_q) { -+ mid_entry = list_entry(tmp1, struct -+ mid_q_entry, -+ qhead); -+ if(mid_entry) { -+ length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid); -+ buf += length; -+ } -+ } -+ spin_unlock(&GlobalMid_Lock); -+ } -+ -+ } -+ read_unlock(&GlobalSMBSeslock); -+ sprintf(buf, "\n"); -+ buf++; -+ -+ length = sprintf(buf, "\nShares:\n"); -+ buf += length; -+ -+ i = 0; -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(tmp, &GlobalTreeConnectionList) { -+ i++; -+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); -+ length = -+ sprintf(buf, -+ "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d", -+ i, tcon->treeName, -+ atomic_read(&tcon->useCount), -+ tcon->nativeFileSystem, -+ tcon->fsDevInfo.DeviceCharacteristics, -+ tcon->fsAttrInfo.Attributes, -+ tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus); -+ 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; -+ if(tcon->tidStatus == CifsNeedReconnect) { -+ buf += sprintf(buf, "\tDISCONNECTED "); -+ length += 14; -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ -+ length = sprintf(buf, "\n"); -+ buf += length; -+ -+ /* BB add code to dump additional info such as TCP session info now */ -+ /* Now calculate total size of returned data */ -+ length = buf - original_buf; -+ -+ if(offset + count >= length) -+ *eof = 1; -+ if(length < offset) { -+ *eof = 1; -+ return 0; -+ } else { -+ length = length - offset; -+ } -+ if (length > count) -+ length = count; -+ -+ return length; -+} -+ -+#ifdef CONFIG_CIFS_STATS -+int -+cifs_stats_read(char *buf, char **beginBuffer, off_t offset, -+ int count, int *eof, void *data) -+{ -+ int item_length,i,length; -+ struct list_head *tmp; -+ struct cifsTconInfo *tcon; -+ -+ *beginBuffer = buf + offset; -+ -+ length = sprintf(buf, -+ "Resources in use\nCIFS Session: %d\n", -+ sesInfoAllocCount.counter); -+ buf += length; -+ item_length = -+ sprintf(buf,"Share (unique mount targets): %d\n", -+ tconInfoAllocCount.counter); -+ length += item_length; -+ buf += item_length; -+ item_length = -+ sprintf(buf,"SMB Request/Response Buffer: %d\n", -+ bufAllocCount.counter); -+ length += item_length; -+ buf += item_length; -+ item_length = -+ sprintf(buf,"Operations (MIDs): %d\n", -+ midCount.counter); -+ length += item_length; -+ buf += item_length; -+ item_length = sprintf(buf, -+ "\n%d session %d share reconnects\n", -+ tcpSesReconnectCount.counter,tconInfoReconnectCount.counter); -+ length += item_length; -+ buf += item_length; -+ -+ item_length = sprintf(buf, -+ "Total vfs operations: %d maximum at one time: %d\n", -+ GlobalCurrentXid,GlobalMaxActiveXid); -+ length += item_length; -+ buf += item_length; -+ -+ i = 0; -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(tmp, &GlobalTreeConnectionList) { -+ i++; -+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); -+ item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName); -+ buf += item_length; -+ length += item_length; -+ if(tcon->tidStatus == CifsNeedReconnect) { -+ buf += sprintf(buf, "\tDISCONNECTED "); -+ length += 14; -+ } -+ item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d", -+ atomic_read(&tcon->num_smbs_sent), -+ atomic_read(&tcon->num_oplock_brks)); -+ buf += item_length; -+ length += item_length; -+ item_length = sprintf(buf,"\nReads: %d Bytes %lld", -+ atomic_read(&tcon->num_reads), -+ (long long)(tcon->bytes_read)); -+ buf += item_length; -+ length += item_length; -+ item_length = sprintf(buf,"\nWrites: %d Bytes: %lld", -+ atomic_read(&tcon->num_writes), -+ (long long)(tcon->bytes_written)); -+ buf += item_length; -+ length += item_length; -+ item_length = sprintf(buf, -+ "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d", -+ atomic_read(&tcon->num_opens), -+ atomic_read(&tcon->num_deletes), -+ atomic_read(&tcon->num_mkdirs), -+ atomic_read(&tcon->num_rmdirs)); -+ buf += item_length; -+ length += item_length; -+ item_length = sprintf(buf, -+ "\nRenames: %d T2 Renames %d", -+ atomic_read(&tcon->num_renames), -+ atomic_read(&tcon->num_t2renames)); -+ buf += item_length; -+ length += item_length; -+ } -+ read_unlock(&GlobalSMBSeslock); -+ -+ buf += sprintf(buf,"\n"); -+ length++; -+ -+ if(offset + count >= length) -+ *eof = 1; -+ if(length < offset) { -+ *eof = 1; -+ return 0; -+ } else { -+ length = length - offset; -+ } -+ if (length > count) -+ length = count; -+ -+ return length; -+} -+#endif -+ -+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 lookupFlag_read; -+static write_proc_t lookupFlag_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; -+static read_proc_t quotaEnabled_read; -+static write_proc_t quotaEnabled_write; -+static read_proc_t linuxExtensionsEnabled_read; -+static write_proc_t linuxExtensionsEnabled_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, NULL); -+ -+#ifdef CONFIG_CIFS_STATS -+ create_proc_read_entry("Stats", 0, proc_fs_cifs, -+ cifs_stats_read, NULL); -+#endif -+ pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs, -+ cifsFYI_read, NULL); -+ if (pde) -+ pde->write_proc = cifsFYI_write; -+ -+ pde = -+ create_proc_read_entry("traceSMB", 0, proc_fs_cifs, -+ traceSMB_read, NULL); -+ if (pde) -+ pde->write_proc = traceSMB_write; -+ -+ pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs, -+ oplockEnabled_read, NULL); -+ if (pde) -+ pde->write_proc = oplockEnabled_write; -+ -+ pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs, -+ quotaEnabled_read, NULL); -+ if (pde) -+ pde->write_proc = quotaEnabled_write; -+ -+ pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs, -+ linuxExtensionsEnabled_read, NULL); -+ if (pde) -+ pde->write_proc = linuxExtensionsEnabled_write; -+ -+ pde = -+ create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs, -+ multiuser_mount_read, NULL); -+ if (pde) -+ pde->write_proc = multiuser_mount_write; -+ -+ pde = -+ create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs, -+ extended_security_read, NULL); -+ if (pde) -+ pde->write_proc = extended_security_write; -+ -+ pde = -+ create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs, -+ lookupFlag_read, NULL); -+ if (pde) -+ pde->write_proc = lookupFlag_write; -+ -+ pde = -+ create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs, -+ ntlmv2_enabled_read, NULL); -+ if (pde) -+ pde->write_proc = ntlmv2_enabled_write; -+ -+ pde = -+ create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs, -+ packet_signing_enabled_read, NULL); -+ 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); -+#ifdef CONFIG_CIFS_STATS -+ remove_proc_entry("Stats", proc_fs_cifs); -+#endif -+ remove_proc_entry("MultiuserMount", proc_fs_cifs); -+ remove_proc_entry("OplockEnabled", proc_fs_cifs); -+ remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); -+ remove_proc_entry("ExtendedSecurity",proc_fs_cifs); -+ remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); -+ remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); -+ remove_proc_entry("QuotaEnabled",proc_fs_cifs); -+ remove_proc_entry("LookupCacheEnabled",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 -+quotaEnabled_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len; -+ -+ len = sprintf(page, "%d\n", quotaEnabled); -+/* could also check if quotas are enabled in kernel -+ as a whole first */ -+ len -= off; -+ *start = page + off; -+ -+ if (len > count) -+ len = count; -+ else -+ *eof = 1; -+ -+ if (len < 0) -+ len = 0; -+ -+ return len; -+} -+static int -+quotaEnabled_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') -+ quotaEnabled = 0; -+ else if (c == '1' || c == 'y' || c == 'Y') -+ quotaEnabled = 1; -+ -+ return count; -+} -+ -+static int -+linuxExtensionsEnabled_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len; -+ -+ len = sprintf(page, "%d\n", linuxExtEnabled); -+/* could also check if quotas are enabled in kernel -+ as a whole first */ -+ len -= off; -+ *start = page + off; -+ -+ if (len > count) -+ len = count; -+ else -+ *eof = 1; -+ -+ if (len < 0) -+ len = 0; -+ -+ return len; -+} -+static int -+linuxExtensionsEnabled_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') -+ linuxExtEnabled = 0; -+ else if (c == '1' || c == 'y' || c == 'Y') -+ linuxExtEnabled = 1; -+ -+ return count; -+} -+ -+ -+static int -+lookupFlag_read(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len; -+ -+ len = sprintf(page, "%d\n", lookupCacheEnabled); -+ -+ len -= off; -+ *start = page + off; -+ -+ if (len > count) -+ len = count; -+ else -+ *eof = 1; -+ -+ if (len < 0) -+ len = 0; -+ -+ return len; -+} -+static int -+lookupFlag_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') -+ lookupCacheEnabled = 0; -+ else if (c == '1' || c == 'y' || c == 'Y') -+ lookupCacheEnabled = 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; -+ else if (c == '2') -+ sign_CIFS_PDUs = 2; -+ -+ return count; -+} -+ -+ -+#endif ---- /dev/null -+++ b/fs/cifs/cifs_debug.h -@@ -0,0 +1,66 @@ -+/* -+ * -+ * 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 cifs_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 cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg) -+ -+#define cFYI(button,prspec) if (button) cifsfyi prspec -+ -+#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg) -+ -+/* debug event message: */ -+extern int cifsERROR; -+ -+#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg) -+ -+/* error event message: e.g., i/o error */ -+#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg) -+ -+#define cERROR(button, prspec) if (button) cifserror prspec -+ -+/* -+ * debug OFF -+ * --------- -+ */ -+#else /* _CIFS_DEBUG */ -+#define cERROR(button,prspec) -+#define cEVENT(format,arg...) -+#define cFYI(button, prspec) -+#define cifserror(format,arg...) -+#endif /* _CIFS_DEBUG */ -+ -+#endif /* _H_CIFS_DEBUG */ ---- /dev/null -+++ b/fs/cifs/cifsencrypt.c -@@ -0,0 +1,204 @@ -+/* -+ * fs/cifs/cifsencrypt.c -+ * -+ * Copyright (C) International Business Machines Corp., 2003 -+ * 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 -+ */ -+ -+#include <linux/fs.h> -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifs_debug.h" -+#include "md5.h" -+#include "cifs_unicode.h" -+ -+/* Calculate and return the CIFS signature based on the mac key and the smb pdu */ -+/* the 16 byte signature must be allocated by the caller */ -+/* Note we only use the 1st eight bytes */ -+/* Note that the smb header signature field on input contains the -+ sequence number before this function is called */ -+ -+extern void mdfour(unsigned char *out, unsigned char *in, int n); -+extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); -+ -+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature) -+{ -+ struct MD5Context context; -+ -+ if((cifs_pdu == NULL) || (signature == NULL)) -+ return -EINVAL; -+ -+ MD5Init(&context); -+ MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); -+ MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); -+ MD5Final(signature,&context); -+ return 0; -+} -+ -+int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, -+ __u32 * pexpected_response_sequence_number) -+{ -+ int rc = 0; -+ char smb_signature[20]; -+ -+ /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */ -+ /* BB remember to add code to save expected sequence number in midQ entry BB */ -+ -+ if((cifs_pdu == NULL) || (ses == NULL)) -+ return -EINVAL; -+ -+ if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0) -+ return rc; -+ -+ spin_lock(&GlobalMid_Lock); -+ cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number); -+ cifs_pdu->Signature.Sequence.Reserved = 0; -+ -+ *pexpected_response_sequence_number = ses->sequence_number++; -+ ses->sequence_number++; -+ spin_unlock(&GlobalMid_Lock); -+ -+ rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature); -+ if(rc) -+ memset(cifs_pdu->Signature.SecuritySignature, 0, 8); -+ else -+ memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8); -+ -+ return rc; -+} -+ -+int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, -+ __u32 expected_sequence_number) -+{ -+ unsigned int rc; -+ char server_response_sig[8]; -+ char what_we_think_sig_should_be[20]; -+ -+ if((cifs_pdu == NULL) || (mac_key == NULL)) -+ return -EINVAL; -+ -+ if (cifs_pdu->Command == SMB_COM_NEGOTIATE) -+ return 0; -+ -+ if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) { -+ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu; -+ if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE) -+ return 0; -+ } -+ -+ /* BB what if signatures are supposed to be on for session but server does not -+ send one? BB */ -+ -+ /* Do not need to verify session setups with signature "BSRSPYL " */ -+ if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0) -+ cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command)); -+ -+ expected_sequence_number = cpu_to_le32(expected_sequence_number); -+ -+ /* save off the origiginal signature so we can modify the smb and check -+ its signature against what the server sent */ -+ memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8); -+ -+ cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number; -+ cifs_pdu->Signature.Sequence.Reserved = 0; -+ -+ rc = cifs_calculate_signature(cifs_pdu, mac_key, -+ what_we_think_sig_should_be); -+ -+ if(rc) -+ return rc; -+ -+ -+/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */ -+ -+ if(memcmp(server_response_sig, what_we_think_sig_should_be, 8)) -+ return -EACCES; -+ else -+ return 0; -+ -+} -+ -+/* We fill in key by putting in 40 byte array which was allocated by caller */ -+int cifs_calculate_mac_key(char * key, const char * rn, const char * password) -+{ -+ char temp_key[16]; -+ if ((key == NULL) || (rn == NULL)) -+ return -EINVAL; -+ -+ E_md4hash(password, temp_key); -+ mdfour(key,temp_key,16); -+ memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE); -+ return 0; -+} -+ -+int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info) -+{ -+ char temp_hash[16]; -+ struct HMACMD5Context ctx; -+ char * ucase_buf; -+ wchar_t * unicode_buf; -+ unsigned int i,user_name_len,dom_name_len; -+ -+ if(ses) -+ return -EINVAL; -+ -+ E_md4hash(ses->password, temp_hash); -+ -+ hmac_md5_init_limK_to_64(temp_hash, 16, &ctx); -+ user_name_len = strlen(ses->userName); -+ if(user_name_len > MAX_USERNAME_SIZE) -+ return -EINVAL; -+ dom_name_len = strlen(ses->domainName); -+ if(dom_name_len > MAX_USERNAME_SIZE) -+ return -EINVAL; -+ -+ ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL); -+ unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL); -+ -+ for(i=0;i<user_name_len;i++) -+ ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]]; -+ ucase_buf[i] = 0; -+ user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info); -+ unicode_buf[user_name_len] = 0; -+ user_name_len++; -+ -+ for(i=0;i<dom_name_len;i++) -+ ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]]; -+ ucase_buf[i] = 0; -+ dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info); -+ -+ unicode_buf[user_name_len + dom_name_len] = 0; -+ hmac_md5_update((const unsigned char *) unicode_buf, -+ (user_name_len+dom_name_len)*2,&ctx); -+ -+ hmac_md5_final(ses->mac_signing_key,&ctx); -+ kfree(ucase_buf); -+ kfree(unicode_buf); -+ return 0; -+} -+void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) -+{ -+ struct HMACMD5Context context; -+ memcpy(v2_session_response + 8, ses->server->cryptKey,8); -+ /* gen_blob(v2_session_response + 16); */ -+ hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context); -+ -+ hmac_md5_update(ses->server->cryptKey,8,&context); -+/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ -+ -+ hmac_md5_final(v2_session_response,&context); -+} ---- /dev/null -+++ b/fs/cifs/cifserr.c -@@ -0,0 +1,70 @@ -+/* -+ * fs/cifserr.c -+ * -+ * 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 -+ */ -+ -+#include <linux/errno.h> -+#include <linux/fs.h> -+#include <linux/smbno.h> -+#include "cifsfs.h" -+ -+int map_cifs_error(int error_class, int error_code, -+ int status_codes_negotiated) -+{ -+ -+ -+ if (status_codes_negotiated) { -+ switch (error_code) { -+ default: -+ return EIO; -+ } -+ } else -+ switch (error_class) { -+ case SUCCESS: -+ return 0; -+ -+ case ERRDOS: -+ switch (error_code) { -+ case ERRbadfunc: -+ return EINVAL; -+ default: -+ return EIO; -+ } -+ -+ case ERRSRV: -+ switch (error_code) { -+ default: -+ return EIO; -+ } -+ -+ case ERRHRD: -+ switch (error_code) { -+ default: -+ return EIO; -+ } -+ default: -+ return EIO; -+ } -+ return 0; -+} -+ -+int map_smb_error(int error_class, int error_code) -+{ -+ return map_cifs_error(error_class, error_code, FALSE); -+} ---- /dev/null -+++ b/fs/cifs/cifsfs.c -@@ -0,0 +1,769 @@ -+/* -+ * fs/cifs/cifsfs.c -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2004 -+ * 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 <linux/module.h> -+#include <linux/fs.h> -+#include <linux/mount.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <linux/version.h> -+#include <linux/list.h> -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15)) -+#include <linux/seq_file.h> -+#endif -+#include <linux/vfs.h> -+#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 <linux/mm.h> -+#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ -+/* BB when mempool_resize is added back in, we will resize pool on new mount */ -+#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */ -+ -+#ifdef CONFIG_CIFS_QUOTA -+static struct quotactl_ops cifs_quotactl_ops; -+#endif -+ -+extern struct file_system_type cifs_fs_type; -+ -+int cifsFYI = 0; -+int cifsERROR = 1; -+int traceSMB = 0; -+unsigned int oplockEnabled = 1; -+unsigned int quotaEnabled = 0; -+unsigned int linuxExtEnabled = 1; -+unsigned int lookupCacheEnabled = 1; -+unsigned int multiuser_mount = 0; -+unsigned int extended_security = 0; -+unsigned int ntlmv2_support = 0; -+unsigned int sign_CIFS_PDUs = 1; -+unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE; -+struct task_struct * oplockThread = NULL; -+ -+extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, -+ const char *); -+extern int cifs_umount(struct super_block *, struct cifs_sb_info *); -+void cifs_proc_init(void); -+void cifs_proc_clean(void); -+ -+static DECLARE_COMPLETION(cifs_oplock_exited); -+ -+ -+struct super_block * -+cifs_read_super(struct super_block *sb, void *data, int silent) -+{ -+ struct inode *inode; -+ struct cifs_sb_info *cifs_sb; -+ int rc = 0; -+ -+ sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ -+ cifs_sb = CIFS_SB(sb); -+ if(cifs_sb == NULL) -+ return 0; -+ else -+ memset(cifs_sb,0,sizeof(struct cifs_sb_info)); -+ -+ -+ rc = cifs_mount(sb, cifs_sb, data, NULL); -+ -+ if (rc) { -+ if (!silent) -+ cERROR(1, -+ ("cifs_mount failed w/return code = %d", rc)); -+ goto out_mount_failed; -+ } -+ -+ sb->s_magic = CIFS_MAGIC_NUMBER; -+ sb->s_op = &cifs_super_ops; -+/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) -+ sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ -+#ifdef CONFIG_CIFS_QUOTA -+ sb->s_qcop = &cifs_quotactl_ops; -+#endif -+ sb->s_blocksize = CIFS_MAX_MSGSIZE; -+ sb->s_blocksize_bits = 14; /* default 2**14 = 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 sb; -+ -+out_no_root: -+ cERROR(1, ("cifs_read_super: get root inode failed")); -+ if (inode) -+ iput(inode); -+ -+out_mount_failed: -+ if(cifs_sb->local_nls) -+ unload_nls(cifs_sb->local_nls); -+ sb->s_dev = 0; -+ return 0; -+} -+ -+static void -+cifs_put_super(struct super_block *sb) -+{ -+ int rc = 0; -+ struct cifs_sb_info *cifs_sb; -+ -+ cFYI(1, ("In cifs_put_super")); -+ cifs_sb = CIFS_SB(sb); -+ if(cifs_sb == NULL) { -+ cFYI(1,("Empty cifs superblock info passed to unmount")); -+ return; -+ } -+ rc = cifs_umount(sb, cifs_sb); -+ if (rc) { -+ cERROR(1, ("cifs_umount failed with return code %d", rc)); -+ } -+ unload_nls(cifs_sb->local_nls); -+ return; -+} -+ -+static 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 = 0; /* 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 */ -+ FreeXid(xid); -+ return 0; /* always return success? what if volume is no longer available? */ -+} -+ -+static int cifs_permission(struct inode * inode, int mask) -+{ -+ /* the server does permission checks, we do not need to do it here */ -+ return 0; -+} -+ -+kmem_cache_t *cifs_req_cachep; -+kmem_cache_t *cifs_mid_cachep; -+kmem_cache_t *cifs_oplock_cachep; -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+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; -+ /* Until the file is open and we have gotten oplock -+ info back from the server, can not assume caching of -+ file data or metadata */ -+ cifs_inode->clientCanCacheRead = FALSE; -+ cifs_inode->clientCanCacheAll = FALSE; -+ 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)); -+} -+#endif -+ -+/* -+ * cifs_show_options() is for displaying mount options in /proc/mounts. -+ * Not all settable options are displayed but most of the important -+ * ones are. -+ */ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15)) -+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, ",unc=%s", cifs_sb->tcon->treeName); -+ if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName)) -+ seq_printf(s, ",username=%s", -+ cifs_sb->tcon->ses->userName); -+ if(cifs_sb->tcon->ses->domainName) -+ seq_printf(s, ",domain=%s", -+ cifs_sb->tcon->ses->domainName); -+ } -+ seq_printf(s, ",rsize=%d",cifs_sb->rsize); -+ seq_printf(s, ",wsize=%d",cifs_sb->wsize); -+ } -+ return 0; -+} -+#endif -+ -+#ifdef CONFIG_CIFS_QUOTA -+int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid, -+ struct fs_disk_quota * pdquota) -+{ -+ int xid; -+ int rc = 0; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -+ struct cifsTconInfo *pTcon; -+ -+ if(cifs_sb) -+ pTcon = cifs_sb->tcon; -+ else -+ return -EIO; -+ -+ -+ xid = GetXid(); -+ if(pTcon) { -+ cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); -+ } else { -+ return -EIO; -+ } -+ -+ FreeXid(xid); -+ return rc; -+} -+ -+int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid, -+ struct fs_disk_quota * pdquota) -+{ -+ int xid; -+ int rc = 0; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -+ struct cifsTconInfo *pTcon; -+ -+ if(cifs_sb) -+ pTcon = cifs_sb->tcon; -+ else -+ return -EIO; -+ -+ xid = GetXid(); -+ if(pTcon) { -+ cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); -+ } else { -+ rc = -EIO; -+ } -+ -+ FreeXid(xid); -+ return rc; -+} -+ -+int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation) -+{ -+ int xid; -+ int rc = 0; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -+ struct cifsTconInfo *pTcon; -+ -+ if(cifs_sb) -+ pTcon = cifs_sb->tcon; -+ else -+ return -EIO; -+ -+ xid = GetXid(); -+ if(pTcon) { -+ cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation)); -+ } else { -+ rc = -EIO; -+ } -+ -+ FreeXid(xid); -+ return rc; -+} -+ -+int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats) -+{ -+ int xid; -+ int rc = 0; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -+ struct cifsTconInfo *pTcon; -+ -+ if(cifs_sb) { -+ pTcon = cifs_sb->tcon; -+ } else { -+ return -EIO; -+ } -+ xid = GetXid(); -+ if(pTcon) { -+ cFYI(1,("pqstats %p",qstats)); -+ } else { -+ rc = -EIO; -+ } -+ -+ FreeXid(xid); -+ return rc; -+} -+ -+static struct quotactl_ops cifs_quotactl_ops = { -+ .set_xquota = cifs_xquota_set, -+ .get_xquota = cifs_xquota_set, -+ .set_xstate = cifs_xstate_set, -+ .get_xstate = cifs_xstate_get, -+}; -+#endif -+ -+static int cifs_remount(struct super_block *sb, int *flags, char *data) -+{ -+ *flags |= MS_NODIRATIME; -+ 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 */ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15)) -+ .show_options = cifs_show_options, -+#endif -+/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */ -+}; -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+static struct super_block * -+cifs_get_sb(struct file_system_type *fs_type, -+ int flags, const char *dev_name, void *data) -+{ -+ int rc; -+ struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); -+ -+ cFYI(1, ("Devname: %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; -+} -+#endif -+ -+static ssize_t -+cifs_read_wrapper(struct file * file, char *read_data, size_t read_size, -+ loff_t * poffset) -+{ -+ if(file == NULL) -+ return -EIO; -+ else if(file->f_dentry == NULL) -+ return -EIO; -+ else if(file->f_dentry->d_inode == NULL) -+ return -EIO; -+ -+ if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) { -+ return generic_file_read(file,read_data,read_size,poffset); -+ } else { -+ /* BB do we need to lock inode from here until after invalidate? */ -+/* if(file->f_dentry->d_inode->i_mapping) { -+ filemap_fdatawrite(file->f_dentry->d_inode->i_mapping); -+ filemap_fdatawait(file->f_dentry->d_inode->i_mapping); -+ }*/ -+/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */ -+ -+ /* BB we should make timer configurable - perhaps -+ by simply calling cifs_revalidate here */ -+ /* invalidate_remote_inode(file->f_dentry->d_inode);*/ -+ return generic_file_read(file,read_data,read_size,poffset); -+ } -+} -+ -+static ssize_t -+cifs_write_wrapper(struct file * file, const char *write_data, -+ size_t write_size, loff_t * poffset) -+{ -+ ssize_t written; -+ -+ if(file == NULL) -+ return -EIO; -+ else if(file->f_dentry == NULL) -+ return -EIO; -+ else if(file->f_dentry->d_inode == NULL) -+ return -EIO; -+ -+ /* check whether we can cache writes locally */ -+ written = generic_file_write(file,write_data,write_size,poffset); -+ if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) { -+ if(file->f_dentry->d_inode->i_mapping) { -+ filemap_fdatasync(file->f_dentry->d_inode->i_mapping); -+ } -+ } -+ return written; -+} -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+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 */ -+}; -+#endif -+ -+static DECLARE_FSTYPE(cifs_fs_type, "cifs", cifs_read_super,0); -+ -+ -+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, -+ .permission = cifs_permission, -+ .revalidate = cifs_revalidate, -+ .setattr = cifs_setattr, -+ .symlink = cifs_symlink, -+ .mknod = cifs_mknod, -+}; -+ -+struct inode_operations cifs_file_inode_ops = { -+ .revalidate = cifs_revalidate, -+ .setattr = cifs_setattr, -+/* .getattr = cifs_getattr,*/ -+ .rename = cifs_rename, -+ .permission = cifs_permission, -+#ifdef CONFIG_CIFS_XATTR -+ .setxattr = cifs_setxattr, -+ .getxattr = cifs_getxattr, -+ .listxattr = cifs_listxattr, -+ .removexattr = cifs_removexattr, -+#endif -+}; -+ -+struct inode_operations cifs_symlink_inode_ops = { -+ .readlink = cifs_readlink, -+ .follow_link = cifs_follow_link, -+ .permission = cifs_permission, -+ /* BB add the following two eventually */ -+ /* revalidate: cifs_revalidate, -+ setattr: cifs_notify_change, *//* BB do we need notify change */ -+#ifdef CONFIG_CIFS_XATTR -+ .setxattr = cifs_setxattr, -+ .getxattr = cifs_getxattr, -+ .listxattr = cifs_listxattr, -+ .removexattr = cifs_removexattr, -+#endif -+}; -+ -+struct file_operations cifs_file_ops = { -+ .read = cifs_read_wrapper, -+ .write = cifs_write_wrapper, -+ .open = cifs_open, -+ .release = cifs_close, -+ .lock = cifs_lock, -+ .fsync = cifs_fsync, -+ .flush = cifs_flush, -+ .mmap = cifs_file_mmap, -+/* .sendfile = generic_file_sendfile,*/ -+#ifdef CONFIG_CIFS_FCNTL -+ .fcntl = cifs_fcntl, -+#endif -+}; -+ -+struct file_operations cifs_dir_ops = { -+ .readdir = cifs_readdir, -+ .release = cifs_closedir, -+ .read = generic_read_dir, -+#ifdef CONFIG_CIFS_FCNTL -+ .fcntl = cifs_fcntl, -+#endif -+}; -+/* -+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); -+ } -+} -+ -+static 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; -+} -+ -+static void -+cifs_destroy_inodecache(void) -+{ -+ if (kmem_cache_destroy(cifs_inode_cachep)) -+ printk(KERN_WARNING "cifs_inode_cache: error freeing\n"); -+} */ -+ -+static 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; -+} -+ -+static void -+cifs_destroy_request_bufs(void) -+{ -+ if (kmem_cache_destroy(cifs_req_cachep)) -+ printk(KERN_WARNING -+ "cifs_destroy_request_cache: error not all structures were freed\n"); -+} -+ -+static 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; -+ cifs_oplock_cachep = kmem_cache_create("cifs_oplock_struct", -+ sizeof (struct oplock_q_entry), 0, -+ SLAB_HWCACHE_ALIGN, NULL, NULL); -+ if (cifs_oplock_cachep == NULL) { -+ kmem_cache_destroy(cifs_mid_cachep); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void -+cifs_destroy_mids(void) -+{ -+ if (kmem_cache_destroy(cifs_mid_cachep)) -+ printk(KERN_WARNING -+ "cifs_destroy_mids: error not all structures were freed\n"); -+ if (kmem_cache_destroy(cifs_oplock_cachep)) -+ printk(KERN_WARNING -+ "error not all oplock structures were freed\n"); -+} -+ -+static int cifs_oplock_thread(void * dummyarg) -+{ -+ struct oplock_q_entry * oplock_item; -+ struct cifsTconInfo *pTcon; -+ struct inode * inode; -+ __u16 netfid; -+ int rc = 0; -+ -+ daemonize(); -+ sprintf(current->comm,"cifsoplockd"); -+ -+ oplockThread = current; -+ do { -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ schedule_timeout(1*HZ); -+ spin_lock(&GlobalMid_Lock); -+ if(list_empty(&GlobalOplock_Q)) { -+ spin_unlock(&GlobalMid_Lock); -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(39*HZ); -+ } else { -+ oplock_item = list_entry(GlobalOplock_Q.next, -+ struct oplock_q_entry, qhead); -+ if(oplock_item) { -+ cFYI(1,("found oplock item to write out")); -+ pTcon = oplock_item->tcon; -+ inode = oplock_item->pinode; -+ netfid = oplock_item->netfid; -+ spin_unlock(&GlobalMid_Lock); -+ DeleteOplockQEntry(oplock_item); -+ /* can not grab inode sem here since it would -+ deadlock when oplock received on delete -+ since vfs_unlink holds the i_sem across -+ the call */ -+ /* down(&inode->i_sem);*/ -+ if (S_ISREG(inode->i_mode)) { -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17)) -+ rc = filemap_fdatasync(inode->i_mapping); -+ if(rc) -+ CIFS_I(inode)->write_behind_rc = rc; -+#else -+ filemap_fdatasync(inode->i_mapping); -+#endif -+ if(CIFS_I(inode)->clientCanCacheRead == 0) -+ invalidate_inode_pages(inode); -+ } else -+ rc = 0; -+ /* releasing a stale oplock after recent reconnection -+ of smb session using a now incorrect file -+ handle is not a data integrity issue but do -+ not bother sending an oplock release if session -+ to server still is disconnected since oplock -+ already released by the server in that case */ -+ if(pTcon->tidStatus != CifsNeedReconnect) { -+ rc = CIFSSMBLock(0, pTcon, -+ netfid, -+ 0 /* len */ , 0 /* offset */, 0, -+ 0, LOCKING_ANDX_OPLOCK_RELEASE, -+ 0 /* wait flag */); -+ cFYI(1,("Oplock release rc = %d ",rc)); -+ } -+ } else -+ spin_unlock(&GlobalMid_Lock); -+ } -+ } while(!signal_pending(current)); -+ complete_and_exit (&cifs_oplock_exited, 0); -+} -+ -+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); -+ INIT_LIST_HEAD(&GlobalOplock_Q); -+/* -+ * Initialize Global counters -+ */ -+ atomic_set(&sesInfoAllocCount, 0); -+ atomic_set(&tconInfoAllocCount, 0); -+ atomic_set(&tcpSesReconnectCount, 0); -+ atomic_set(&tconInfoReconnectCount, 0); -+ -+ atomic_set(&bufAllocCount, 0); -+ atomic_set(&midCount, 0); -+ GlobalCurrentXid = 0; -+ GlobalTotalActiveXid = 0; -+ GlobalMaxActiveXid = 0; -+ GlobalSMBSeslock = RW_LOCK_UNLOCKED; -+ GlobalMid_Lock = SPIN_LOCK_UNLOCKED; -+ -+/* 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) { -+ kernel_thread(cifs_oplock_thread, NULL, -+ CLONE_FS | CLONE_FILES | CLONE_VM); -+ 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, ("In 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(); -+ if(oplockThread) { -+ send_sig(SIGTERM, oplockThread, 1); -+ wait_for_completion(&cifs_oplock_exited); -+ } -+} -+ -+MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); -+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) ---- /dev/null -+++ b/fs/cifs/cifsfs.h -@@ -0,0 +1,97 @@ -+/* -+ * 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_mknod(struct inode *, struct dentry *, int, int); -+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 int cifs_flush(struct file *); -+extern int cifs_file_mmap(struct file * , struct vm_area_struct *); -+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); -+extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *); -+ -+/* 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); -+extern int cifs_removexattr(struct dentry *, const char *); -+extern int cifs_setxattr(struct dentry *, const char *, const void *, -+ size_t, int); -+extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -+#define CIFS_VERSION "1.20" -+#endif /* _CIFSFS_H */ ---- /dev/null -+++ b/fs/cifs/cifs_fs_sb.h -@@ -0,0 +1,32 @@ -+/* -+ * 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 */ -+ struct list_head nested_tcon_q; -+ struct nls_table *local_nls; -+ unsigned int rsize; -+ unsigned int wsize; -+ uid_t mnt_uid; -+ gid_t mnt_gid; -+ mode_t mnt_file_mode; -+ mode_t mnt_dir_mode; -+}; -+#endif /* _CIFS_FS_SB_H */ ---- /dev/null -+++ b/fs/cifs/cifsglob.h -@@ -0,0 +1,413 @@ -+/* -+ * fs/cifs/cifsglob.h -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2003 -+ * 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 <linux/in.h> -+#include <linux/in6.h> -+#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 /* 32 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 socket concurently. It also matches the most common -+ * value of max multiplex returned by servers. We may -+ * eventually want to use the negotiated value (in case -+ * future servers can handle more) when we are more confident that -+ * we will not have problems oveloading the socket with pending -+ * write data. -+ */ -+#define CIFS_MAX_REQ 50 -+ -+#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 -+ -+#ifndef XATTR_DOS_ATTRIB -+#define XATTR_DOS_ATTRIB "user.DOSATTRIB" -+#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 */ -+}; -+ -+enum protocolEnum { -+ IPV4 = 0, -+ IPV6, -+ SCTP -+ /* Netbios frames protocol not supported at this time */ -+}; -+ -+/* -+ ***************************************************************** -+ * 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; -+ union { -+ struct sockaddr_in sockAddr; -+ struct sockaddr_in6 sockAddr6; -+ } addr; -+ wait_queue_head_t response_q; -+ wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ -+ 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 */ -+ enum protocolEnum protocolType; -+ char versionMajor; -+ char versionMinor; -+ int svlocal:1; /* local server or remote */ -+ atomic_t socketUseCount; /* number of open cifs sessions on socket */ -+ atomic_t inFlight; /* number of requests on the wire to server */ -+ enum statusEnum tcpStatus; /* what we think the status is */ -+ struct semaphore tcpSem; -+ struct task_struct *tsk; -+ char server_GUID[16]; -+ 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 */ -+ int capabilities; /* allow selective disabling of caps by smb sess */ -+ __u16 timeZone; -+ char cryptKey[CIFS_CRYPTO_KEY_SIZE]; -+ char workstation_RFC1001_name[16]; /* 16th byte is always zero */ -+}; -+ -+/* -+ * 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 list_head userList; -+ struct list_head sessionList; /* SMB sessions for this user */ -+ uid_t linux_uid; -+ char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */ -+ /* BB may need ptr or callback for 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 mounts (tree connections) on this ses */ -+ enum statusEnum status; -+ __u32 sequence_number; /* needed for CIFS PDU signature */ -+ __u16 ipc_tid; /* special tid for connection to IPC share */ -+ char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; -+ 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; /* remote smb uid */ -+ uid_t linux_uid; /* local Linux uid */ -+ int capabilities; -+ 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]; -+ char domainName[MAX_USERNAME_SIZE + 1]; -+ char * password; -+}; -+ -+/* -+ * 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]; /* UNC name of resource (in ASCII not UTF) */ -+ char *nativeFileSystem; -+ __u16 tid; /* The 2 byte tree id */ -+ __u16 Flags; /* optional support bits */ -+ enum statusEnum tidStatus; -+ atomic_t useCount; /* how many mounts (explicit or implicit) to this share */ -+#ifdef CONFIG_CIFS_STATS -+ atomic_t num_smbs_sent; -+ atomic_t num_writes; -+ atomic_t num_reads; -+ atomic_t num_oplock_brks; -+ atomic_t num_opens; -+ atomic_t num_deletes; -+ atomic_t num_mkdirs; -+ atomic_t num_rmdirs; -+ atomic_t num_renames; -+ atomic_t num_t2renames; -+ __u64 bytes_read; -+ __u64 bytes_written; -+ spinlock_t stat_lock; -+#endif -+ FILE_SYSTEM_DEVICE_INFO fsDevInfo; -+ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ -+ FILE_SYSTEM_UNIX_INFO fsUnixInfo; -+ int retry:1; -+ /* 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 finding 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) */ -+ struct file * pfile; /* needed for writepage */ -+ struct inode * pInode; /* needed for oplock break */ -+ int endOfSearch:1; /* we have reached end of search */ -+ int closePend:1; /* file is marked to close */ -+ int emptyDir:1; -+ int invalidHandle:1; /* file closed via session abend */ -+ struct semaphore fh_sem; /* prevents reopen race after dead ses*/ -+ char * search_resume_name; -+ unsigned int resume_name_length; -+ __u32 resume_key; -+}; -+ -+/* -+ * 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; -+ int write_behind_rc; -+ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ -+ atomic_t inUse; /* num concurrent users (local openers cifs) of file*/ -+ unsigned long time; /* jiffies of last update/check of inode */ -+ int clientCanCacheRead:1; /* read oplock */ -+ int clientCanCacheAll:1; /* read and writebehind oplock */ -+ int oplockPending:1; -+ struct inode vfs_inode; -+}; -+ -+static inline struct cifsInodeInfo * CIFS_I(struct inode *inode) -+{ -+ return (struct cifsInodeInfo *)&(inode->u); -+} -+ -+static inline struct cifs_sb_info * CIFS_SB(struct super_block *sb) -+{ -+ return (struct cifs_sb_info *) &(sb->u); -+} -+ -+ -+/* 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 */ -+ __u32 sequence_number; /* for CIFS signing */ -+ __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 were enum but can not pass to wait_event */ -+}; -+ -+struct oplock_q_entry { -+ struct list_head qhead; -+ struct inode * pinode; -+ struct cifsTconInfo * tcon; -+ __u16 netfid; -+}; -+ -+#define MID_FREE 0 -+#define MID_REQUEST_ALLOCATED 1 -+#define MID_REQUEST_SUBMITTED 2 -+#define MID_RESPONSE_RECEIVED 4 -+#define MID_RETRY_NEEDED 8 /* session closed while this request out */ -+ -+/* -+ ***************************************************************** -+ * All constants go here -+ ***************************************************************** -+ */ -+ -+#define UID_HASH (16) -+ -+/* -+ * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the -+ * following to be declared. -+ */ -+ -+/**************************************************************************** -+ * Locking notes. All updates to global variables and lists should be -+ * protected by spinlocks or semaphores. -+ * -+ * Spinlocks -+ * --------- -+ * GlobalMid_Lock protects: -+ * list operations on pending_mid_q and oplockQ -+ * updates to XID counters, multiplex id and SMB sequence numbers -+ * GlobalSMBSesLock protects: -+ * list operations on tcp and SMB session lists and tCon lists -+ * f_owner.lock protects certain per file struct operations -+ * mapping->page_lock protects certain per page operations -+ * -+ * Semaphores -+ * ---------- -+ * sesSem operations on smb session -+ * tconSem operations on tree connection -+ * fh_sem file handle reconnection operations -+ * -+ ****************************************************************************/ -+ -+#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 not implemented yet */ -+GLOBAL_EXTERN struct list_head GlobalSMBSessionList; -+GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; -+GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ -+ -+GLOBAL_EXTERN struct list_head GlobalOplock_Q; -+ -+/* -+ * 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 spinlock_t GlobalMid_Lock; /* protects above and list operations */ -+ /* on midQ entries */ -+GLOBAL_EXTERN char Local_System_Name[15]; -+ -+/* -+ * Global counters, updated atomically -+ */ -+GLOBAL_EXTERN atomic_t sesInfoAllocCount; -+GLOBAL_EXTERN atomic_t tconInfoAllocCount; -+ -+GLOBAL_EXTERN atomic_t tcpSesReconnectCount; -+GLOBAL_EXTERN atomic_t tconInfoReconnectCount; -+ -+/* 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 quotaEnabled; -+GLOBAL_EXTERN unsigned int lookupCacheEnabled; -+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 */ -+GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */ -+ ---- /dev/null -+++ b/fs/cifs/cifspdu.h -@@ -0,0 +1,1793 @@ -+/* -+ * 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 <net/sock.h> -+ -+#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_COPY 0x29 -+#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_FIND_CLOSE2 0x34 -+#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 NT_TRANSACT_GET_USER_QUOTA 0x07 -+#define NT_TRANSACT_SET_USER_QUOTA 0x08 -+ -+#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*4096) -+ -+/* -+ * 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_BACKUP_SEMANTICS 0x02000000 -+#define ATTR_DELETE_ON_CLOSE 0x04000000 -+#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 must not be file */ -+#define CREATE_WRITE_THROUGH 0x00000002 -+#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ -+#define CREATE_RANDOM_ACCESS 0x00000800 -+#define CREATE_DELETE_ON_CLOSE 0x00001000 -+#define OPEN_REPARSE_POINT 0x00200000 -+ -+/* 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 */ -+ union { -+ struct { -+ __u32 SequenceNumber; /* le */ -+ __u32 Reserved; /* zero */ -+ } Sequence; -+ __u8 SecuritySignature[8]; /* le */ -+ } Signature; -+ __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; -+ __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; -+ -+typedef struct smb_com_findclose_req { -+ struct smb_hdr hdr; /* wct = 1 */ -+ __u16 FileID; -+ __u16 ByteCount; /* 0 */ -+} FINDCLOSE_REQ; -+ -+/* 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; -+ -+/* open response: oplock levels */ -+#define OPLOCK_NONE 0 -+#define OPLOCK_EXCLUSIVE 1 -+#define OPLOCK_BATCH 2 -+#define OPLOCK_READ 3 /* level 2 oplock */ -+ -+/* open response for CreateAction shifted left */ -+#define CIFS_CREATE_ACTION 0x20000 /* file created */ -+ -+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; -+ __u32 OffsetHigh; -+ __u32 OffsetLow; -+ __u32 LengthHigh; -+ __u32 LengthLow; -+} 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; -+ -+ /* copy request flags */ -+#define COPY_MUST_BE_FILE 0x0001 -+#define COPY_MUST_BE_DIR 0x0002 -+#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */ -+#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */ -+#define COPY_VERIFY_WRITES 0x0010 -+#define COPY_TREE 0x0020 -+ -+typedef struct smb_com_copy_req { -+ struct smb_hdr hdr; /* wct = 3 */ -+ __u16 Tid2; -+ __u16 OpenFunction; -+ __u16 Flags; -+ __u16 ByteCount; -+ __u8 BufferFormat; /* 4 = ASCII or Unicode */ -+ unsigned char OldFileName[1]; -+ /* followed by __u8 BufferFormat2 */ -+ /* followed by NewFileName string */ -+} COPY_REQ; -+ -+typedef struct smb_com_copy_rsp { -+ struct smb_hdr hdr; /* wct = 1 */ -+ __u16 CopyCount; /* number of files copied */ -+ __u16 ByteCount; /* may be zero */ -+ __u8 BufferFormat; /* 0x04 - only present if errored file follows */ -+ unsigned char ErrorFileName[1]; /* only present if error in copy */ -+} COPY_RSP; -+ -+#define CREATE_HARD_LINK 0x103 -+#define MOVEFILE_COPY_ALLOWED 0x0002 -+#define MOVEFILE_REPLACE_EXISTING 0x0001 -+ -+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; -+ -+/***************************************************/ -+/* NT Transact structure defintions follow */ -+/* Currently only ioctl and notify are implemented */ -+/***************************************************/ -+typedef struct smb_com_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 IsFsctl; /* 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 struct smb_com_transaction_change_notify_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;/* 4 = Change Notify */ -+ __u32 CompletionFilter; /* operation to monitor */ -+ __u16 Fid; -+ __u8 WatchTree; /* 1 = Monitor subdirectories */ -+ __u8 Reserved2; -+ __u16 ByteCount; -+/* __u8 Pad[3];*/ -+/* __u8 Data[1];*/ -+} TRANSACT_CHANGE_NOTIFY_REQ; -+ -+typedef struct smb_com_transaction_change_notify_rsp { -+ struct smb_hdr hdr; /* wct = 18 */ -+ __u8 Reserved[3]; -+ __u32 TotalParameterCount; -+ __u32 TotalDataCount; -+ __u32 ParameterCount; -+ __u32 ParameterOffset; -+ __u32 ParameterDisplacement; -+ __u32 DataCount; -+ __u32 DataOffset; -+ __u32 DataDisplacement; -+ __u8 SetupCount; /* 0 */ -+ __u16 ByteCount; -+ /* __u8 Pad[3]; */ -+} TRANSACT_CHANGE_NOTIFY_RSP; -+/* Completion Filter flags for Notify */ -+#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001 -+#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002 -+#define FILE_NOTIFY_CHANGE_NAME 0x00000003 -+#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004 -+#define FILE_NOTIFY_CHANGE_SIZE 0x00000008 -+#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 -+#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020 -+#define FILE_NOTIFY_CHANGE_CREATION 0x00000040 -+#define FILE_NOTIFY_CHANGE_EA 0x00000080 -+#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100 -+#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200 -+#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400 -+#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800 -+ -+#define FILE_ACTION_ADDED 0x00000001 -+#define FILE_ACTION_REMOVED 0x00000002 -+#define FILE_ACTION_MODIFIED 0x00000003 -+#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004 -+#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005 -+#define FILE_ACTION_ADDED_STREAM 0x00000006 -+#define FILE_ACTION_REMOVED_STREAM 0x00000007 -+#define FILE_ACTION_MODIFIED_STREAM 0x00000008 -+ -+/* response contains array of the following structures */ -+struct file_notify_information { -+ __u32 NextEntryOffset; -+ __u32 Action; -+ __u32 FileNameLength; -+ __u8 FileName[1]; -+}; -+ -+struct reparse_data { -+ __u32 ReparseTag; -+ __u16 ReparseDataLength; -+ __u16 Reserved; -+ __u16 AltNameOffset; -+ __u16 AltNameLen; -+ __u16 TargetNameOffset; -+ __u16 TargetNameLen; -+ char LinkNamesBuf[1]; -+}; -+ -+struct cifs_quota_data { -+ __u32 rsrvd1; /* 0 */ -+ __u32 sid_size; -+ __u64 rsrvd2; /* 0 */ -+ __u64 space_used; -+ __u64 soft_limit; -+ __u64 hard_limit; -+ char sid[1]; /* variable size? */ -+}; -+ -+/* quota sub commands */ -+#define QUOTA_LIST_CONTINUE 0 -+#define QUOTA_LIST_START 0x100 -+#define QUOTA_FOR_SID 0x101 -+ -+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 - can be followed by SetupCount words */ -+ __u16 ByteCount; /* careful - setupcount is not always one */ -+ } req; -+ struct { -+ struct smb_hdr hdr; /* wct = 0 */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParamterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* should be zero setup words following */ -+ __u16 ByteCount; -+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ -+ /* data area follows */ -+ } resp; -+} TRANSACTION2; -+ -+/* PathInfo/FileInfo infolevels */ -+#define SMB_INFO_STANDARD 1 -+#define SMB_INFO_QUERY_EAS_FROM_LIST 3 -+#define SMB_INFO_QUERY_ALL_EAS 4 -+#define SMB_INFO_IS_NAME_VALID 6 -+#define SMB_QUERY_FILE_BASIC_INFO 0x101 -+#define SMB_QUERY_FILE_STANDARD_INFO 0x102 -+#define SMB_QUERY_FILE_EA_INFO 0x103 -+#define SMB_QUERY_FILE_NAME_INFO 0x104 -+#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105 -+#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106 -+#define SMB_QUERY_FILE_ALL_INFO 0x107 -+#define SMB_QUERY_ALT_NAME_INFO 0x108 -+#define SMB_QUERY_FILE_STREAM_INFO 0x109 -+#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B -+#define SMB_QUERY_FILE_UNIX_BASIC 0x200 -+#define SMB_QUERY_FILE_UNIX_LINK 0x201 -+ -+#define SMB_SET_FILE_BASIC_INFO 0x101 -+#define SMB_SET_FILE_DISPOSITION_INFO 0x102 -+#define SMB_SET_FILE_ALLOCATION_INFO 0x103 -+#define SMB_SET_FILE_END_OF_FILE_INFO 0x104 -+#define SMB_SET_FILE_UNIX_BASIC 0x200 -+#define SMB_SET_FILE_UNIX_LINK 0x201 -+#define SMB_SET_FILE_UNIX_HLINK 0x203 -+#define SMB_SET_FILE_BASIC_INFO2 0x3ec -+#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 -+#define SMB_FILE_ALL_INFO2 0x3fa -+#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb -+#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc -+#define SMB_FILE_MOVE_CLUSTER_INFO 0x407 -+#define SMB_FILE_QUOTA_INFO 0x408 -+#define SMB_FILE_REPARSEPOINT_INFO 0x409 -+#define SMB_FILE_MAXIMUM_INFO 0x40d -+ -+/* Find File infolevels */ -+#define SMB_FIND_FILE_DIRECTORY_INFO 0x101 -+#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 -+#define SMB_FIND_FILE_NAMES_INFO 0x103 -+#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 -+#define SMB_FIND_FILE_UNIX 0x202 -+ -+typedef struct smb_com_transaction2_qpi_req { -+ 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; /* one setup word */ -+ __u16 ByteCount; -+ __u8 Pad; -+ __u16 InformationLevel; -+ __u32 Reserved4; -+ char FileName[1]; -+} TRANSACTION2_QPI_REQ; -+ -+typedef struct smb_com_transaction2_qpi_rsp { -+ struct smb_hdr hdr; /* wct = 10 + SetupCount */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParameterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* should be zero setup words following */ -+ __u16 ByteCount; -+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ -+} TRANSACTION2_QPI_RSP; -+ -+typedef struct smb_com_transaction2_spi_req { -+ struct smb_hdr hdr; /* wct = 15 */ -+ __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; /* one setup word */ -+ __u16 ByteCount; -+ __u8 Pad; -+ __u16 Pad1; -+ __u16 InformationLevel; -+ __u32 Reserved4; -+ char FileName[1]; -+} TRANSACTION2_SPI_REQ; -+ -+typedef struct smb_com_transaction2_spi_rsp { -+ struct smb_hdr hdr; /* wct = 10 + SetupCount */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParameterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* should be zero setup words following */ -+ __u16 ByteCount; -+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ -+} TRANSACTION2_SPI_RSP; -+ -+struct set_file_rename { -+ __u32 overwrite; /* 1 = overwrite dest */ -+ __u32 root_fid; /* zero */ -+ __u32 target_name_len; -+ char target_name[0]; /* Must be unicode */ -+}; -+ -+struct smb_com_transaction2_sfi_req { -+ struct smb_hdr hdr; /* wct = 15 */ -+ __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; /* one setup word */ -+ __u16 ByteCount; -+ __u8 Pad; -+ __u16 Pad1; -+ __u16 Fid; -+ __u16 InformationLevel; -+ __u16 Reserved4; -+}; -+ -+struct smb_com_transaction2_sfi_rsp { -+ struct smb_hdr hdr; /* wct = 10 + SetupCount */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParameterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* should be zero setup words following */ -+ __u16 ByteCount; -+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ -+}; -+ -+ -+/* -+ * Flags on T2 FINDFIRST and FINDNEXT -+ */ -+#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001 -+#define CIFS_SEARCH_CLOSE_AT_END 0x0002 -+#define CIFS_SEARCH_RETURN_RESUME 0x0004 -+#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008 -+#define CIFS_SEARCH_BACKUP_SEARCH 0x0010 -+ -+/* -+ * Size of the resume key on FINDFIRST and FINDNEXT calls -+ */ -+#define CIFS_SMB_RESUME_KEY_SIZE 4 -+ -+typedef struct smb_com_transaction2_ffirst_req { -+ struct smb_hdr hdr; /* wct = 15 */ -+ __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; /* one */ -+ __u8 Reserved3; -+ __u16 SubCommand; /* TRANS2_FIND_FIRST */ -+ __u16 ByteCount; -+ __u8 Pad; -+ __u16 SearchAttributes; -+ __u16 SearchCount; -+ __u16 SearchFlags; -+ __u16 InformationLevel; -+ __u32 SearchStorageType; -+ char FileName[1]; -+} TRANSACTION2_FFIRST_REQ; -+ -+typedef struct smb_com_transaction2_ffirst_rsp { -+ struct smb_hdr hdr; /* wct = 10 */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParameterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* should be zero setup words following */ -+ __u16 ByteCount; -+} TRANSACTION2_FFIRST_RSP; -+ -+typedef struct smb_com_transaction2_ffirst_rsp_parms { -+ __u16 SearchHandle; -+ __u16 SearchCount; -+ __u16 EndofSearch; -+ __u16 EAErrorOffset; -+ __u16 LastNameOffset; -+} T2_FFIRST_RSP_PARMS; -+ -+typedef struct smb_com_transaction2_fnext_req { -+ struct smb_hdr hdr; /* wct = 15 */ -+ __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; /* one */ -+ __u8 Reserved3; -+ __u16 SubCommand; /* TRANS2_FIND_NEXT */ -+ __u16 ByteCount; -+ __u8 Pad; -+ __u16 SearchHandle; -+ __u16 SearchCount; -+ __u16 InformationLevel; -+ __u32 ResumeKey; -+ __u16 SearchFlags; -+ char ResumeFileName[1]; -+} TRANSACTION2_FNEXT_REQ; -+ -+typedef struct smb_com_transaction2_fnext_rsp { -+ struct smb_hdr hdr; /* wct = 10 */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParameterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* should be zero setup words following */ -+ __u16 ByteCount; -+} TRANSACTION2_FNEXT_RSP; -+ -+typedef struct smb_com_transaction2_fnext_rsp_parms { -+ __u16 SearchCount; -+ __u16 EndofSearch; -+ __u16 EAErrorOffset; -+ __u16 LastNameOffset; -+} T2_FNEXT_RSP_PARMS; -+ -+/* QFSInfo Levels */ -+#define SMB_INFO_ALLOCATION 1 -+#define SMB_INFO_VOLUME 2 -+#define SMB_QUERY_FS_VOLUME_INFO 0x102 -+#define SMB_QUERY_FS_SIZE_INFO 0x103 -+#define SMB_QUERY_FS_DEVICE_INFO 0x104 -+#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 -+#define SMB_QUERY_CIFS_UNIX_INFO 0x200 -+#define SMB_QUERY_LABEL_INFO 0x3ea -+#define SMB_QUERY_FS_QUOTA_INFO 0x3ee -+ -+typedef struct smb_com_transaction2_qfsi_req { -+ 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; /* one setup word */ -+ __u16 ByteCount; -+ __u8 Pad; -+ __u16 InformationLevel; -+} TRANSACTION2_QFSI_REQ; -+ -+typedef struct smb_com_transaction_qfsi_rsp { -+ struct smb_hdr hdr; /* wct = 10 + SetupCount */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParameterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* should be zero setup words following */ -+ __u16 ByteCount; -+ __u8 Pad; /* may be three bytes *//* followed by data area */ -+} TRANSACTION2_QFSI_RSP; -+ -+typedef struct smb_com_transaction2_get_dfs_refer_req { -+ struct smb_hdr hdr; /* wct = 15 */ -+ __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; /* one setup word */ -+ __u16 ByteCount; -+ __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */ -+ __u16 MaxReferralLevel; -+ char RequestFileName[1]; -+} TRANSACTION2_GET_DFS_REFER_REQ; -+ -+typedef struct dfs_referral_level_3 { -+ __u16 VersionNumber; -+ __u16 ReferralSize; -+ __u16 ServerType; /* 0x0001 = CIFS server */ -+ __u16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */ -+ __u16 TimeToLive; -+ __u16 Proximity; -+ __u16 DfsPathOffset; -+ __u16 DfsAlternatePathOffset; -+ __u16 NetworkAddressOffset; -+} REFERRAL3; -+ -+typedef struct smb_com_transaction_get_dfs_refer_rsp { -+ struct smb_hdr hdr; /* wct = 10 */ -+ __u16 TotalParameterCount; -+ __u16 TotalDataCount; -+ __u16 Reserved; -+ __u16 ParameterCount; -+ __u16 ParameterOffset; -+ __u16 ParameterDisplacement; -+ __u16 DataCount; -+ __u16 DataOffset; -+ __u16 DataDisplacement; -+ __u8 SetupCount; -+ __u8 Reserved1; /* zero setup words following */ -+ __u16 ByteCount; -+ __u8 Pad; -+ __u16 PathConsumed; -+ __u16 NumberOfReferrals; -+ __u16 DFSFlags; -+ __u16 Pad2; -+ REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */ -+ /* followed by the strings pointed to by the referral structures */ -+} TRANSACTION2_GET_DFS_REFER_RSP; -+ -+/* DFS Flags */ -+#define DFSREF_REFERRAL_SERVER 0x0001 -+#define DFSREF_STORAGE_SERVER 0x0002 -+ -+/* IOCTL information */ -+/* List of ioctl function codes that look to be of interest to remote clients like this. */ -+/* Need to do some experimentation to make sure they all work remotely. */ -+/* Some of the following such as the encryption/compression ones would be */ -+/* invoked from tools via a specialized hook into the VFS rather than via the */ -+/* standard vfs entry points */ -+#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 -+#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 -+#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 -+#define FSCTL_LOCK_VOLUME 0x00090018 -+#define FSCTL_UNLOCK_VOLUME 0x0009001C -+#define FSCTL_GET_COMPRESSION 0x0009003C -+#define FSCTL_SET_COMPRESSION 0x0009C040 -+#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C -+#define FSCTL_FILESYS_GET_STATISTICS 0x00090090 -+#define FSCTL_SET_REPARSE_POINT 0x000900A4 -+#define FSCTL_GET_REPARSE_POINT 0x000900A8 -+#define FSCTL_DELETE_REPARSE_POINT 0x000900AC -+#define FSCTL_SET_SPARSE 0x000900C4 -+#define FSCTL_SET_ZERO_DATA 0x000900C8 -+#define FSCTL_SET_ENCRYPTION 0x000900D7 -+#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB -+#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF -+#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 -+#define FSCTL_SIS_COPYFILE 0x00090100 -+#define FSCTL_SIS_LINK_FILES 0x0009C104 -+ -+#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 -+#define IO_REPARSE_TAG_HSM 0xC0000004 -+#define IO_REPARSE_TAG_SIS 0x80000007 -+ -+/* -+ ************************************************************************ -+ * All structs for everything above the SMB PDUs themselves -+ * (such as the T2 level specific data) go here -+ ************************************************************************ -+ */ -+ -+/* -+ * Information on a server -+ */ -+ -+struct serverInfo { -+ char name[16]; -+ unsigned char versionMajor; -+ unsigned char versionMinor; -+ unsigned long type; -+ unsigned int commentOffset; -+}; -+ -+/* -+ * The following structure is the format of the data returned on a NetShareEnum -+ * with level "90" (x5A) -+ */ -+ -+struct shareInfo { -+ char shareName[13]; -+ char pad; -+ unsigned short type; -+ unsigned int commentOffset; -+}; -+ -+struct aliasInfo { -+ char aliasName[9]; -+ char pad; -+ unsigned int commentOffset; -+ unsigned char type[2]; -+}; -+ -+struct aliasInfo92 { -+ int aliasNameOffset; -+ int serverNameOffset; -+ int shareNameOffset; -+}; -+ -+typedef struct { -+ __u64 TotalAllocationUnits; -+ __u64 FreeAllocationUnits; -+ __u32 SectorsPerAllocationUnit; -+ __u32 BytesPerSector; -+} FILE_SYSTEM_INFO; /* size info, level 0x103 */ -+ -+typedef struct { -+ __u16 MajorVersionNumber; -+ __u16 MinorVersionNumber; -+ __u64 Capability; -+} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ -+/* Linux/Unix extensions capability flags */ -+#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ -+#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 -+ -+/* DeviceType Flags */ -+#define FILE_DEVICE_CD_ROM 0x00000002 -+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 -+#define FILE_DEVICE_DFS 0x00000006 -+#define FILE_DEVICE_DISK 0x00000007 -+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 -+#define FILE_DEVICE_FILE_SYSTEM 0x00000009 -+#define FILE_DEVICE_NAMED_PIPE 0x00000011 -+#define FILE_DEVICE_NETWORK 0x00000012 -+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 -+#define FILE_DEVICE_NULL 0x00000015 -+#define FILE_DEVICE_PARALLEL_PORT 0x00000016 -+#define FILE_DEVICE_PRINTER 0x00000018 -+#define FILE_DEVICE_SERIAL_PORT 0x0000001b -+#define FILE_DEVICE_STREAMS 0x0000001e -+#define FILE_DEVICE_TAPE 0x0000001f -+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 -+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 -+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 -+ -+typedef struct { -+ __u32 DeviceType; -+ __u32 DeviceCharacteristics; -+} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */ -+ -+typedef struct { -+ __u32 Attributes; -+ __u32 MaxPathNameComponentLength; -+ __u32 FileSystemNameLen; -+ char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ -+} FILE_SYSTEM_ATTRIBUTE_INFO; -+ -+typedef struct { /* data block encoding of response to level 263 QPathInfo */ -+ __u64 CreationTime; -+ __u64 LastAccessTime; -+ __u64 LastWriteTime; -+ __u64 ChangeTime; -+ __u32 Attributes; -+ __u32 Pad1; -+ __u64 AllocationSize; -+ __u64 EndOfFile; /* size ie offset to first free byte in file */ -+ __u32 NumberOfLinks; /* hard links */ -+ __u8 DeletePending; -+ __u8 Directory; -+ __u16 Pad2; -+ __u64 IndexNumber; -+ __u32 EASize; -+ __u32 AccessFlags; -+ __u64 IndexNumber1; -+ __u64 CurrentByteOffset; -+ __u32 Mode; -+ __u32 AlignmentRequirement; -+ __u32 FileNameLength; -+ char FileName[1]; -+} FILE_ALL_INFO; /* level 263 QPathInfo */ -+ -+typedef struct { -+ __u64 EndOfFile; -+ __u64 NumOfBytes; -+ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */ -+ __u64 LastAccessTime; -+ __u64 LastModificationTime; -+ __u64 Uid; -+ __u64 Gid; -+ __u32 Type; -+ __u64 DevMajor; -+ __u64 DevMinor; -+ __u64 UniqueId; -+ __u64 Permissions; -+ __u64 Nlinks; -+} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */ -+ -+typedef struct { -+ char LinkDest[1]; -+} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */ -+ -+/* defines for enumerating possible values of the Unix type field below */ -+#define UNIX_FILE 0 -+#define UNIX_DIR 1 -+#define UNIX_SYMLINK 2 -+#define UNIX_CHARDEV 3 -+#define UNIX_BLOCKDEV 4 -+#define UNIX_FIFO 5 -+#define UNIX_SOCKET 6 -+ -+typedef struct { -+ __u32 NextEntryOffset; -+ __u32 ResumeKey; -+ __u64 EndOfFile; -+ __u64 NumOfBytes; -+ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */ -+ __u64 LastAccessTime; -+ __u64 LastModificationTime; -+ __u64 Uid; -+ __u64 Gid; -+ __u32 Type; -+ __u64 DevMajor; -+ __u64 DevMinor; -+ __u64 UniqueId; -+ __u64 Permissions; -+ __u64 Nlinks; -+ char FileName[1]; -+} FILE_UNIX_INFO; -+ -+typedef struct { -+ __u64 CreationTime; -+ __u64 LastAccessTime; -+ __u64 LastWriteTime; -+ __u64 ChangeTime; -+ __u32 Attributes; -+ __u32 Pad; -+} FILE_BASIC_INFO; /* size info, level 0x101 */ -+ -+struct file_allocation_info { -+ __u64 AllocationSize; -+}; /* size info, level 0x103 */ -+ -+struct file_end_of_file_info { -+ __u64 FileSize; /* offset to end of file */ -+}; /* size info, level 0x104 */ -+ -+typedef struct { -+ __u32 NextEntryOffset; -+ __u32 FileIndex; -+ __u64 CreationTime; -+ __u64 LastAccessTime; -+ __u64 LastWriteTime; -+ __u64 ChangeTime; -+ __u64 EndOfFile; -+ __u64 AllocationSize; -+ __u32 ExtFileAttributes; -+ __u32 FileNameLength; -+ char FileName[1]; -+} FILE_DIRECTORY_INFO; /* level 257 FF response data area */ -+ -+struct gea { -+ unsigned char cbName; -+ char szName[1]; -+}; -+ -+struct gealist { -+ unsigned long cbList; -+ struct gea list[1]; -+}; -+ -+struct fea { -+ unsigned char EA_flags; -+ __u8 name_len; -+ __u16 value_len; -+ char szName[1]; -+ /* optionally followed by value */ -+}; -+/* flags for _FEA.fEA */ -+#define FEA_NEEDEA 0x80 /* need EA bit */ -+ -+struct fealist { -+ __u32 list_len; -+ struct fea list[1]; -+}; -+ -+/* used to hold an arbitrary blob of data */ -+struct data_blob { -+ __u8 *data; -+ size_t length; -+ void (*free) (struct data_blob * data_blob); -+}; -+ -+#ifdef CONFIG_CIFS_POSIX -+/* -+ For better POSIX semantics from Linux client, (even better -+ than the existing CIFS Unix Extensions) we need updated PDUs for: -+ -+ 1) PosixCreateX - to set and return the mode, inode#, device info and -+ perhaps add a CreateDevice - to create Pipes and other special .inodes -+ Also note POSIX open flags -+ 2) Close - to return the last write time to do cache across close more safely -+ 3) PosixQFSInfo - to return statfs info -+ 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes) -+ 5) Mkdir - set mode -+ -+ And under consideration: -+ 6) FindClose2 (return nanosecond timestamp ??) -+ 7) Use nanosecond timestamps throughout all time fields if -+ corresponding attribute flag is set -+ 8) sendfile - handle based copy -+ 9) Direct i/o -+ 10) "POSIX ACL" support -+ 11) Misc fcntls? -+ -+ what about fixing 64 bit alignment -+ -+ There are also various legacy SMB/CIFS requests used as is -+ -+ From existing Lanman and NTLM dialects: -+ -------------------------------------- -+ NEGOTIATE -+ SESSION_SETUP_ANDX (BB which?) -+ TREE_CONNECT_ANDX (BB which wct?) -+ TREE_DISCONNECT (BB add volume timestamp on response) -+ LOGOFF_ANDX -+ DELETE (note delete open file behavior) -+ DELETE_DIRECTORY -+ READ_AND_X -+ WRITE_AND_X -+ LOCKING_AND_X (note posix lock semantics) -+ RENAME (note rename across dirs and open file rename posix behaviors) -+ NT_RENAME (for hardlinks) Is this good enough for all features? -+ FIND_CLOSE2 -+ TRANSACTION2 (18 cases) -+ SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2 -+ (BB verify that never need to set allocation size) -+ SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?) -+ -+ COPY (note support for copy across directories) - FUTURE, OPTIONAL -+ setting/getting OS/2 EAs - FUTURE (BB can this handle -+ setting Linux xattrs perfectly) - OPTIONAL -+ dnotify - FUTURE, OPTIONAL -+ quota - FUTURE, OPTIONAL -+ -+ Note that various requests implemented for NT interop such as -+ NT_TRANSACT (IOCTL) QueryReparseInfo -+ are unneeded to servers compliant with the CIFS POSIX extensions -+ -+ From CIFS Unix Extensions: -+ ------------------------- -+ T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks -+ T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2) -+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK) -+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields -+ Actually need QUERY_FILE_UNIX_INFO since has inode num -+ BB what about a) blksize/blkbits/blocks -+ b) i_version -+ c) i_rdev -+ d) notify mask? -+ e) generation -+ f) size_seqcount -+ T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX -+ TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended -+ T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL -+ -+ -+ */ -+#endif -+ -+#pragma pack() /* resume default structure packing */ -+ -+#endif /* _CIFSPDU_H */ ---- /dev/null -+++ b/fs/cifs/cifsproto.h -@@ -0,0 +1,254 @@ -+/* -+ * fs/cifs/cifsproto.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 _CIFSPROTO_H -+#define _CIFSPROTO_H -+#include <linux/nls.h> -+ -+struct statfs; -+ -+/* -+ ***************************************************************** -+ * All Prototypes -+ ***************************************************************** -+ */ -+ -+extern struct smb_hdr *cifs_buf_get(void); -+extern void cifs_buf_release(void *); -+extern int smb_send(struct socket *, struct smb_hdr *, -+ unsigned int /* length */ , struct sockaddr *); -+extern unsigned int _GetXid(void); -+extern void _FreeXid(unsigned int); -+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); -+#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));} -+extern char *build_path_from_dentry(struct dentry *); -+extern char *build_wildcard_path_from_dentry(struct dentry *direntry); -+extern void renew_parental_timestamps(struct dentry *direntry); -+extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, -+ struct smb_hdr * /* input */ , -+ struct smb_hdr * /* out */ , -+ int * /* bytes returned */ , const int long_op); -+extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); -+extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); -+extern int is_valid_oplock_break(struct smb_hdr *smb); -+extern unsigned int smbCalcSize(struct smb_hdr *ptr); -+extern int decode_negTokenInit(unsigned char *security_blob, int length, -+ enum securityEnum *secType); -+extern int map_smb_to_linux_error(struct smb_hdr *smb); -+extern void header_assemble(struct smb_hdr *, char /* command */ , -+ const struct cifsTconInfo *, int -+ /* length of fixed section (word count) in two byte units */ -+ ); -+struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); -+void DeleteOplockQEntry(struct oplock_q_entry *); -+extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); -+extern u64 cifs_UnixTimeToNT(time_t); -+extern int cifs_get_inode_info(struct inode **pinode, -+ const unsigned char *search_path, -+ FILE_ALL_INFO * pfile_info, -+ struct super_block *sb, int xid); -+extern int cifs_get_inode_info_unix(struct inode **pinode, -+ const unsigned char *search_path, -+ struct super_block *sb,int xid); -+ -+extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, -+ struct nls_table * nls_info); -+extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses); -+ -+extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, -+ const char *tree, struct cifsTconInfo *tcon, -+ const struct nls_table *); -+ -+extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, -+ const char *searchName, -+ FILE_DIRECTORY_INFO * findData, -+ T2_FFIRST_RSP_PARMS * findParms, -+ const struct nls_table *nls_codepage, -+ int *pUnicodeFlag, -+ int *pUnixFlag /* if Unix extensions used */ ); -+extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, -+ FILE_DIRECTORY_INFO * findData, -+ T2_FNEXT_RSP_PARMS * findParms, -+ const __u16 searchHandle, char * resume_name, -+ int name_length, __u32 resume_key, -+ int *UnicodeFlag, int *pUnixFlag); -+ -+extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, -+ const __u16 search_handle); -+ -+extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ FILE_ALL_INFO * findData, -+ const struct nls_table *nls_codepage); -+ -+extern int CIFSSMBUnixQPathInfo(const int xid, -+ struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ FILE_UNIX_BASIC_INFO * pFindData, -+ const struct nls_table *nls_codepage); -+ -+extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, -+ const unsigned char *searchName, -+ unsigned char **targetUNCs, -+ unsigned int *number_of_UNC_in_array, -+ const struct nls_table *nls_codepage); -+ -+extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, -+ const char *old_path, -+ const struct nls_table *nls_codepage); -+extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, -+ const char *old_path, const struct nls_table *nls_codepage, -+ unsigned int *pnum_referrals, unsigned char ** preferrals); -+extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, -+ struct statfs *FSData, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBQFSAttributeInfo(const int xid, -+ struct cifsTconInfo *tcon, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, -+ const struct nls_table *nls_codepage); -+ -+extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, -+ char *fileName, FILE_BASIC_INFO * data, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, -+ char *fileName, __u64 size,int setAllocationSizeFlag, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, -+ __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag); -+extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, -+ char *full_path, __u64 mode, __u64 uid, -+ __u64 gid, dev_t dev, const struct nls_table *nls_codepage); -+ -+extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, -+ const char *newName, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, -+ const char *name, const struct nls_table *nls_codepage); -+ -+extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, -+ const char *name, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, -+ int netfid, char * target_name, const struct nls_table *nls_codepage); -+extern int CIFSCreateHardLink(const int xid, -+ struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage); -+extern int CIFSUnixCreateHardLink(const int xid, -+ struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage); -+extern int CIFSUnixCreateSymLink(const int xid, -+ struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBUnixQuerySymLink(const int xid, -+ struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ char *syminfo, const int buflen, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBQueryReparseLinkInfo(const int xid, -+ struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ char *symlinkinfo, const int buflen, __u16 fid, -+ const struct nls_table *nls_codepage); -+ -+extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, -+ const char *fileName, const int disposition, -+ const int access_flags, const int omode, -+ __u16 * netfid, int *pOplock, FILE_ALL_INFO *, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, -+ const int smb_file_id); -+ -+extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, -+ const int netfid, unsigned int count, -+ const __u64 lseek, unsigned int *nbytes, char **buf); -+extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, -+ const int netfid, const unsigned int count, -+ const __u64 lseek, unsigned int *nbytes, -+ const char *buf, const int long_op); -+extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, -+ const __u16 netfid, const __u64 len, -+ const __u64 offset, const __u32 numUnlock, -+ const __u32 numLock, const __u8 lockType, -+ const int waitFlag); -+ -+extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); -+extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); -+ -+extern struct cifsSesInfo *sesInfoAlloc(void); -+extern void sesInfoFree(struct cifsSesInfo *); -+extern struct cifsTconInfo *tconInfoAlloc(void); -+extern void tconInfoFree(struct cifsTconInfo *); -+ -+extern int cifs_reconnect(struct TCP_Server_Info *server); -+ -+extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); -+extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key, -+ __u32 expected_sequence_number); -+extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); -+extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); -+extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); -+ -+extern int CIFSBuildServerList(int xid, char *serverBufferList, -+ int recordlength, int *entries, -+ int *totalEntries, int *topoChangedFlag); -+extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon, -+ struct shareInfo *shareList, int bufferLen, -+ int *entries, int *totalEntries); -+extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon, -+ struct aliasInfo *aliasList, int bufferLen, -+ int *entries, int *totalEntries); -+extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon, -+ char *aliasName, char *serverName, -+ char *shareName, char *comment); -+extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon, -+ char *share, char *comment); -+extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon, -+ char *userName, char *searchName, int *perms); -+extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid); -+ -+extern int CIFSSMBSeek(int xid, -+ struct cifsTconInfo *tcon, -+ int netfid, -+ int pid, -+ int whence, unsigned long offset, long long *newoffset); -+ -+extern int CIFSSMBCopy(int xid, -+ struct cifsTconInfo *source_tcon, -+ const char *fromName, -+ const __u16 target_tid, -+ const char *toName, const int flags, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, -+ const int notify_subdirs,const __u16 netfid,__u32 filter, -+ const struct nls_table *nls_codepage); -+extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ char * EAData, size_t size, -+ const struct nls_table *nls_codepage); -+#endif /* _CIFSPROTO_H */ ---- /dev/null -+++ b/fs/cifs/cifssmb.c -@@ -0,0 +1,3016 @@ -+/* -+ * fs/cifs/cifssmb.c -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2003 -+ * Author(s): Steve French (sfrench@us.ibm.com) -+ * -+ * Contains the routines for constructing the SMB PDUs themselves -+ * -+ * 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 -+ */ -+ -+ /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */ -+ /* These are mostly routines that operate on a pathname, or on a tree id */ -+ /* (mounted volume), but there are eight handle based routines which must be */ -+ /* treated slightly different for reconnection purposes since we never want */ -+ /* to reuse a stale file handle and the caller knows the file handle */ -+ -+#include <linux/fs.h> -+#include <linux/kernel.h> -+#include <linux/vfs.h> -+#include <asm/uaccess.h> -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_unicode.h" -+#include "cifs_debug.h" -+ -+#ifdef CONFIG_CIFS_POSIX -+static struct { -+ int index; -+ char *name; -+} protocols[] = { -+ {CIFS_PROT, "\2NT LM 0.12"}, -+ {CIFS_PROT, "\2POSIX 2"}, -+ {BAD_PROT, "\2"} -+}; -+#else -+static struct { -+ int index; -+ char *name; -+} protocols[] = { -+ {CIFS_PROT, "\2NT LM 0.12"}, -+ {BAD_PROT, "\2"} -+}; -+#endif -+ -+ -+/* Mark as invalid, all open files on tree connections since they -+ were closed when session to server was lost */ -+static void mark_open_files_invalid(struct cifsTconInfo * pTcon) -+{ -+ struct cifsFileInfo *open_file = NULL; -+ struct list_head * tmp; -+ struct list_head * tmp1; -+ -+/* list all files open on tree connection and mark them invalid */ -+ write_lock(&GlobalSMBSeslock); -+ list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { -+ open_file = list_entry(tmp,struct cifsFileInfo, tlist); -+ if(open_file) { -+ open_file->invalidHandle = TRUE; -+ } -+ } -+ write_unlock(&GlobalSMBSeslock); -+ /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */ -+} -+ -+static int -+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, -+ void **request_buf /* returned */ , -+ void **response_buf /* returned */ ) -+{ -+ int rc = 0; -+ int timeout = 10 * HZ; -+ -+ /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so -+ check for tcp and smb session status done differently -+ for those three - in the calling routine */ -+ if(tcon) { -+ if((tcon->ses) && (tcon->ses->server)){ -+ struct nls_table *nls_codepage; -+ /* Give Demultiplex thread up to 10 seconds to -+ reconnect, should be greater than cifs socket -+ timeout which is 7 seconds */ -+ while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { -+ while ((tcon->ses->server->tcpStatus != CifsGood) && (timeout > 0)){ -+ timeout = interruptible_sleep_on_timeout(&tcon->ses->server->response_q,timeout); -+ } -+ if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { -+ /* on "soft" mounts we wait once */ -+ if((tcon->retry == FALSE) || -+ (tcon->ses->status == CifsExiting)) { -+ cFYI(1,("gave up waiting on reconnect in smb_init")); -+ return -EHOSTDOWN; -+ } /* else "hard" mount - keep retrying until -+ process is killed or server comes back up */ -+ } else /* TCP session is reestablished now */ -+ break; -+ -+ } -+ -+ nls_codepage = load_nls_default(); -+ /* need to prevent multiple threads trying to -+ simultaneously reconnect the same SMB session */ -+ down(&tcon->ses->sesSem); -+ if(tcon->ses->status == CifsNeedReconnect) -+ rc = cifs_setup_session(0, tcon->ses, nls_codepage); -+ if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { -+ mark_open_files_invalid(tcon); -+ rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, -+ nls_codepage); -+ up(&tcon->ses->sesSem); -+ if(rc == 0) -+ atomic_inc(&tconInfoReconnectCount); -+ -+ cFYI(1, ("reconnect tcon rc = %d", rc)); -+ /* Removed call to reopen open files here - -+ it is safer (and faster) to reopen files -+ one at a time as needed in read and write */ -+ -+ /* Check if handle based operation so we -+ know whether we can continue or not without -+ returning to caller to reset file handle */ -+ switch(smb_command) { -+ case SMB_COM_READ_ANDX: -+ case SMB_COM_WRITE_ANDX: -+ case SMB_COM_CLOSE: -+ case SMB_COM_FIND_CLOSE2: -+ case SMB_COM_LOCKING_ANDX: { -+ unload_nls(nls_codepage); -+ return -EAGAIN; -+ } -+ } -+ } else { -+ up(&tcon->ses->sesSem); -+ } -+ unload_nls(nls_codepage); -+ -+ } else { -+ return -EIO; -+ } -+ } -+ if(rc) -+ return rc; -+ -+ *request_buf = cifs_buf_get(); -+ if (*request_buf == 0) { -+ /* BB should we add a retry in here if not a writepage? */ -+ return -ENOMEM; -+ } -+ /* Although the original thought was we needed the response buf for */ -+ /* potential retries of smb operations it turns out we can determine */ -+ /* from the mid flags when the request buffer can be resent without */ -+ /* having to use a second distinct buffer for the response */ -+ *response_buf = *request_buf; -+ -+ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, -+ wct /*wct */ ); -+ -+#ifdef CONFIG_CIFS_STATS -+ if(tcon != NULL) { -+ atomic_inc(&tcon->num_smbs_sent); -+ } -+#endif -+ return rc; -+} -+ -+int -+CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) -+{ -+ NEGOTIATE_REQ *pSMB; -+ NEGOTIATE_RSP *pSMBr; -+ int rc = 0; -+ int bytes_returned; -+ struct TCP_Server_Info * server; -+ -+ if(ses->server) -+ server = ses->server; -+ else { -+ rc = -EIO; -+ return rc; -+ } -+ rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ , -+ (void **) &pSMB, (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; -+ if (extended_security) -+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; -+ -+ pSMB->ByteCount = strlen(protocols[0].name) + 1; -+ strncpy(pSMB->DialectsArray, protocols[0].name, 30); -+ /* null guaranteed to be at end of source and target buffers anyway */ -+ -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc == 0) { -+ server->secMode = pSMBr->SecurityMode; -+ server->secType = NTLM; /* BB override default for NTLMv2 or krb*/ -+ /* one byte - no need to convert this or EncryptionKeyLen from le,*/ -+ server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); -+ /* probably no need to store and check maxvcs */ -+ server->maxBuf = -+ min(le32_to_cpu(pSMBr->MaxBufferSize), -+ (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE); -+ server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); -+ cFYI(0, ("Max buf = %d ", ses->server->maxBuf)); -+ GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); -+ server->capabilities = le32_to_cpu(pSMBr->Capabilities); -+ server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); -+ /* BB with UTC do we ever need to be using srvr timezone? */ -+ if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { -+ memcpy(server->cryptKey, pSMBr->u.EncryptionKey, -+ CIFS_CRYPTO_KEY_SIZE); -+ } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) -+ && (pSMBr->EncryptionKeyLength == 0)) { -+ /* decode security blob */ -+ } else -+ rc = -EIO; -+ -+ /* BB might be helpful to save off the domain of server here */ -+ -+ if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) { -+ if (pSMBr->ByteCount < 16) -+ rc = -EIO; -+ else if (pSMBr->ByteCount == 16) { -+ server->secType = RawNTLMSSP; -+ if (server->socketUseCount.counter > 1) { -+ if (memcmp -+ (server->server_GUID, -+ pSMBr->u.extended_response. -+ GUID, 16) != 0) { -+ cFYI(1, -+ ("UID of server does not match previous connection to same ip address")); -+ memcpy(server-> -+ server_GUID, -+ pSMBr->u. -+ extended_response. -+ GUID, 16); -+ } -+ } else -+ memcpy(server->server_GUID, -+ pSMBr->u.extended_response. -+ GUID, 16); -+ } else { -+ rc = decode_negTokenInit(pSMBr->u. -+ extended_response. -+ SecurityBlob, -+ pSMBr->ByteCount - -+ 16, &server->secType); -+ } -+ } else -+ server->capabilities &= ~CAP_EXTENDED_SECURITY; -+ if(sign_CIFS_PDUs == FALSE) { -+ if(server->secMode & SECMODE_SIGN_REQUIRED) -+ cERROR(1, -+ ("Server requires /proc/fs/cifs/PacketSigningEnabled")); -+ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); -+ } else if(sign_CIFS_PDUs == 1) { -+ if((server->secMode & SECMODE_SIGN_REQUIRED) == 0) -+ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); -+ } -+ -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ return rc; -+} -+ -+int -+CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) -+{ -+ struct smb_hdr *smb_buffer; -+ struct smb_hdr *smb_buffer_response; -+ int rc = 0; -+ int length; -+ -+ cFYI(1, ("In tree disconnect")); -+ /* -+ * If last user of the connection and -+ * connection alive - disconnect it -+ * If this is the last connection on the server session disconnect it -+ * (and inside session disconnect we should check if tcp socket needs -+ * to be freed and kernel thread woken up). -+ */ -+ if (tcon) -+ down(&tcon->tconSem); -+ else -+ return -EIO; -+ -+ atomic_dec(&tcon->useCount); -+ if (atomic_read(&tcon->useCount) > 0) { -+ up(&tcon->tconSem); -+ return -EBUSY; -+ } -+ -+ /* No need to return error on this operation if tid invalidated and -+ closed on server already e.g. due to tcp session crashing */ -+ if(tcon->tidStatus == CifsNeedReconnect) { -+ up(&tcon->tconSem); -+ return 0; -+ } -+ -+ if((tcon->ses == 0) || (tcon->ses->server == 0)) { -+ up(&tcon->tconSem); -+ return -EIO; -+ } -+ -+ rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, -+ (void **) &smb_buffer, (void **) &smb_buffer_response); -+ if (rc) { -+ up(&tcon->tconSem); -+ return rc; -+ } -+ rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, -+ &length, 0); -+ if (rc) -+ cFYI(1, (" Tree disconnect failed %d", rc)); -+ -+ if (smb_buffer) -+ cifs_buf_release(smb_buffer); -+ up(&tcon->tconSem); -+ -+ /* No need to return error on this operation if tid invalidated and -+ closed on server already e.g. due to tcp session crashing */ -+ if (rc == -EAGAIN) -+ rc = 0; -+ -+ return rc; -+} -+ -+int -+CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) -+{ -+ struct smb_hdr *smb_buffer_response; -+ LOGOFF_ANDX_REQ *pSMB; -+ int rc = 0; -+ int length; -+ -+ cFYI(1, ("In SMBLogoff for session disconnect")); -+ if (ses) -+ down(&ses->sesSem); -+ else -+ return -EIO; -+ -+ atomic_dec(&ses->inUse); -+ if (atomic_read(&ses->inUse) > 0) { -+ up(&ses->sesSem); -+ return -EBUSY; -+ } -+ -+ rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */, -+ (void **) &pSMB, (void **) &smb_buffer_response); -+ -+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) -+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; -+ -+ if (rc) { -+ up(&ses->sesSem); -+ return rc; -+ } -+ -+ pSMB->hdr.Uid = ses->Suid; -+ -+ pSMB->AndXCommand = 0xFF; -+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, -+ smb_buffer_response, &length, 0); -+ if (ses->server) { -+ atomic_dec(&ses->server->socketUseCount); -+ if (atomic_read(&ses->server->socketUseCount) == 0) { -+ spin_lock(&GlobalMid_Lock); -+ ses->server->tcpStatus = CifsExiting; -+ spin_unlock(&GlobalMid_Lock); -+ rc = -ESHUTDOWN; -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ up(&ses->sesSem); -+ -+ /* if session dead then we do not need to do ulogoff, -+ since server closed smb session, no sense reporting -+ error */ -+ if (rc == -EAGAIN) -+ rc = 0; -+ return rc; -+} -+ -+int -+CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, -+ const char *fileName, const struct nls_table *nls_codepage) -+{ -+ DELETE_FILE_REQ *pSMB = NULL; -+ DELETE_FILE_RSP *pSMBr = NULL; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ -+DelFileRetry: -+ rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fileName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->fileName, fileName, name_len); -+ } -+ pSMB->SearchAttributes = -+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); -+ pSMB->ByteCount = name_len + 1; -+ pSMB->BufferFormat = 0x04; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Error in RMFile = %d", rc)); -+ } -+#ifdef CONFIG_CIFS_STATS -+ else { -+ atomic_inc(&tcon->num_deletes); -+ } -+#endif -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto DelFileRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, -+ const char *dirName, const struct nls_table *nls_codepage) -+{ -+ DELETE_DIRECTORY_REQ *pSMB = NULL; -+ DELETE_DIRECTORY_RSP *pSMBr = NULL; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ -+ cFYI(1, ("In CIFSSMBRmDir")); -+RmDirRetry: -+ rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(dirName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->DirName, dirName, name_len); -+ } -+ -+ pSMB->ByteCount = name_len + 1; -+ pSMB->BufferFormat = 0x04; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Error in RMDir = %d", rc)); -+ } -+#ifdef CONFIG_CIFS_STATS -+ else { -+ atomic_inc(&tcon->num_rmdirs); -+ } -+#endif -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto RmDirRetry; -+ return rc; -+} -+ -+int -+CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, -+ const char *name, const struct nls_table *nls_codepage) -+{ -+ int rc = 0; -+ CREATE_DIRECTORY_REQ *pSMB = NULL; -+ CREATE_DIRECTORY_RSP *pSMBr = NULL; -+ int bytes_returned; -+ int name_len; -+ -+ cFYI(1, ("In CIFSSMBMkDir")); -+MkDirRetry: -+ rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(name, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->DirName, name, name_len); -+ } -+ -+ pSMB->ByteCount = name_len + 1 /* for buf format */ ; -+ pSMB->BufferFormat = 0x04; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Error in Mkdir = %d", rc)); -+ } -+#ifdef CONFIG_CIFS_STATS -+ else { -+ atomic_inc(&tcon->num_mkdirs); -+ } -+#endif -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto MkDirRetry; -+ return rc; -+} -+ -+int -+CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, -+ const char *fileName, const int openDisposition, -+ const int access_flags, const int create_options, __u16 * netfid, -+ int *pOplock, FILE_ALL_INFO * pfile_info, -+ const struct nls_table *nls_codepage) -+{ -+ int rc = -EACCES; -+ OPEN_REQ *pSMB = NULL; -+ OPEN_RSP *pSMBr = NULL; -+ int bytes_returned; -+ int name_len; -+ -+openRetry: -+ rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->AndXCommand = 0xFF; /* none */ -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ pSMB->ByteCount = 1; /* account for one byte pad to word boundary */ -+ name_len = -+ cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1), -+ fileName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ pSMB->NameLength = cpu_to_le16(name_len); -+ } else { /* BB improve the check for buffer overruns BB */ -+ pSMB->ByteCount = 0; /* no pad */ -+ name_len = strnlen(fileName, 530); -+ name_len++; /* trailing null */ -+ pSMB->NameLength = cpu_to_le16(name_len); -+ strncpy(pSMB->fileName, fileName, name_len); -+ } -+ if (*pOplock & REQ_OPLOCK) -+ pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); -+ else if (*pOplock & REQ_BATCHOPLOCK) { -+ pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); -+ } -+ pSMB->DesiredAccess = cpu_to_le32(access_flags); -+ pSMB->AllocationSize = 0; -+ pSMB->FileAttributes = ATTR_NORMAL; -+ /* XP does not handle ATTR_POSIX_SEMANTICS */ -+ /* but it helps speed up case sensitive checks for other -+ servers such as Samba */ -+ if (tcon->ses->capabilities & CAP_UNIX) -+ pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS; -+ -+ /* if ((omode & S_IWUGO) == 0) -+ pSMB->FileAttributes |= ATTR_READONLY;*/ -+ /* Above line causes problems due to vfs splitting create into two -+ pieces - need to set mode after file created not while it is -+ being created */ -+ pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes); -+ pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); -+ pSMB->CreateDisposition = cpu_to_le32(openDisposition); -+ pSMB->CreateOptions = cpu_to_le32(create_options); -+ pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/ -+ pSMB->SecurityFlags = -+ cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY); -+ -+ pSMB->ByteCount += name_len; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ /* long_op set to 1 to allow for oplock break timeouts */ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 1); -+ if (rc) { -+ cFYI(1, ("Error in Open = %d", rc)); -+ } else { -+ *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ -+ *netfid = pSMBr->Fid; /* cifs fid stays in le */ -+ /* Let caller know file was created so we can set the mode. */ -+ /* Do we care about the CreateAction in any other cases? */ -+ if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) -+ *pOplock |= CIFS_CREATE_ACTION; -+ if(pfile_info) { -+ memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime, -+ 36 /* CreationTime to Attributes */); -+ /* the file_info buf is endian converted by caller */ -+ pfile_info->AllocationSize = pSMBr->AllocationSize; -+ pfile_info->EndOfFile = pSMBr->EndOfFile; -+ pfile_info->NumberOfLinks = cpu_to_le32(1); -+ } -+ -+#ifdef CONFIG_CIFS_STATS -+ atomic_inc(&tcon->num_opens); -+#endif -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto openRetry; -+ return rc; -+} -+ -+/* If no buffer passed in, then caller wants to do the copy -+ as in the case of readpages so the SMB buffer must be -+ freed by the caller */ -+ -+int -+CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, -+ const int netfid, const unsigned int count, -+ const __u64 lseek, unsigned int *nbytes, char **buf) -+{ -+ int rc = -EACCES; -+ READ_REQ *pSMB = NULL; -+ READ_RSP *pSMBr = NULL; -+ char *pReadData = NULL; -+ int bytes_returned; -+ -+ *nbytes = 0; -+ rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ /* tcon and ses pointer are checked in smb_init */ -+ if (tcon->ses->server == NULL) -+ return -ECONNABORTED; -+ -+ pSMB->AndXCommand = 0xFF; /* none */ -+ pSMB->Fid = netfid; -+ pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); -+ pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); -+ pSMB->Remaining = 0; -+ pSMB->MaxCount = cpu_to_le16(count); -+ pSMB->MaxCountHigh = 0; -+ pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cERROR(1, ("Send error in read = %d", rc)); -+ } else { -+ pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength); -+ *nbytes = pSMBr->DataLength; -+ /*check that DataLength would not go beyond end of SMB */ -+ if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE) -+ || (pSMBr->DataLength > count)) { -+ cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count)); -+ rc = -EIO; -+ *nbytes = 0; -+ } else { -+ pReadData = -+ (char *) (&pSMBr->hdr.Protocol) + -+ le16_to_cpu(pSMBr->DataOffset); -+/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) { -+ cERROR(1,("Faulting on read rc = %d",rc)); -+ rc = -EFAULT; -+ }*/ /* can not use copy_to_user when using page cache*/ -+ if(*buf) -+ memcpy(*buf,pReadData,pSMBr->DataLength); -+ } -+ } -+ if (pSMB) { -+ if(*buf) -+ cifs_buf_release(pSMB); -+ else -+ *buf = (char *)pSMB; -+ } -+ -+ /* Note: On -EAGAIN error only caller can retry on handle based calls -+ since file handle passed in no longer valid */ -+ return rc; -+} -+ -+int -+CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, -+ const int netfid, const unsigned int count, -+ const __u64 offset, unsigned int *nbytes, const char *buf, -+ const int long_op) -+{ -+ int rc = -EACCES; -+ WRITE_REQ *pSMB = NULL; -+ WRITE_RSP *pSMBr = NULL; -+ int bytes_returned; -+ -+ rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ /* tcon and ses pointer are checked in smb_init */ -+ if (tcon->ses->server == NULL) -+ return -ECONNABORTED; -+ -+ pSMB->AndXCommand = 0xFF; /* none */ -+ pSMB->Fid = netfid; -+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); -+ pSMB->OffsetHigh = cpu_to_le32(offset >> 32); -+ pSMB->Remaining = 0; -+ if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00)) -+ pSMB->DataLengthLow = -+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00; -+ else -+ pSMB->DataLengthLow = count; -+ pSMB->DataLengthHigh = 0; -+ pSMB->DataOffset = -+ cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); -+ -+ memcpy(pSMB->Data,buf,pSMB->DataLengthLow); -+ -+ pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ; -+ pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow); -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, long_op); -+ if (rc) { -+ cFYI(1, ("Send error in write = %d", rc)); -+ *nbytes = 0; -+ } else -+ *nbytes = le16_to_cpu(pSMBr->Count); -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Note: On -EAGAIN error only caller can retry on handle based calls -+ since file handle passed in no longer valid */ -+ -+ return rc; -+} -+ -+int -+CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, -+ const __u16 smb_file_id, const __u64 len, -+ const __u64 offset, const __u32 numUnlock, -+ const __u32 numLock, const __u8 lockType, const int waitFlag) -+{ -+ int rc = 0; -+ LOCK_REQ *pSMB = NULL; -+ LOCK_RSP *pSMBr = NULL; -+ int bytes_returned; -+ int timeout = 0; -+ __u64 temp; -+ -+ cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock)); -+ rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) { -+ timeout = -1; /* no response expected */ -+ pSMB->Timeout = 0; -+ } else if (waitFlag == TRUE) { -+ timeout = 3; /* blocking operation, no timeout */ -+ pSMB->Timeout = -1; /* blocking - do not time out */ -+ } else { -+ pSMB->Timeout = 0; -+ } -+ -+ pSMB->NumberOfLocks = cpu_to_le32(numLock); -+ pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock); -+ pSMB->LockType = lockType; -+ pSMB->AndXCommand = 0xFF; /* none */ -+ pSMB->Fid = smb_file_id; /* netfid stays le */ -+ -+ if(numLock != 0) { -+ pSMB->Locks[0].Pid = cpu_to_le16(current->tgid); -+ /* BB where to store pid high? */ -+ temp = cpu_to_le64(len); -+ pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF); -+ pSMB->Locks[0].LengthHigh = (__u32)(temp>>32); -+ temp = cpu_to_le64(offset); -+ pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF); -+ pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32); -+ pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE); -+ } else { -+ /* oplock break */ -+ pSMB->ByteCount = 0; -+ } -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, timeout); -+ -+ if (rc) { -+ cFYI(1, ("Send error in Lock = %d", rc)); -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Note: On -EAGAIN error only caller can retry on handle based calls -+ since file handle passed in no longer valid */ -+ return rc; -+} -+ -+int -+CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) -+{ -+ int rc = 0; -+ CLOSE_REQ *pSMB = NULL; -+ CLOSE_RSP *pSMBr = NULL; -+ int bytes_returned; -+ cFYI(1, ("In CIFSSMBClose")); -+ -+/* do not retry on dead session on close */ -+ rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if(rc == -EAGAIN) -+ return 0; -+ if (rc) -+ return rc; -+ -+ pSMB->FileID = (__u16) smb_file_id; -+ pSMB->LastWriteTime = 0; -+ pSMB->ByteCount = 0; -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ if(rc!=-EINTR) { -+ /* EINTR is expected when user ctl-c to kill app */ -+ cERROR(1, ("Send error in Close = %d", rc)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Since session is dead, file will be closed on server already */ -+ if(rc == -EAGAIN) -+ rc = 0; -+ -+ return rc; -+} -+ -+int -+CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage) -+{ -+ int rc = 0; -+ RENAME_REQ *pSMB = NULL; -+ RENAME_RSP *pSMBr = NULL; -+ int bytes_returned; -+ int name_len, name_len2; -+ -+ cFYI(1, ("In CIFSSMBRename")); -+renameRetry: -+ rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->BufferFormat = 0x04; -+ pSMB->SearchAttributes = -+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | -+ ATTR_DIRECTORY); -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ pSMB->OldFileName[name_len] = 0x04; /* pad */ -+ /* protocol requires ASCII signature byte on Unicode string */ -+ pSMB->OldFileName[name_len + 1] = 0x00; -+ name_len2 = -+ cifs_strtoUCS((wchar_t *) & pSMB-> -+ OldFileName[name_len + 2], toName, 530, -+ nls_codepage); -+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; -+ name_len2 *= 2; /* convert to bytes */ -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fromName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->OldFileName, fromName, name_len); -+ name_len2 = strnlen(toName, 530); -+ name_len2++; /* trailing null */ -+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ -+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); -+ name_len2++; /* trailing null */ -+ name_len2++; /* signature byte */ -+ } -+ -+ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in rename = %d", rc)); -+ } -+ -+#ifdef CONFIG_CIFS_STATS -+ else { -+ atomic_inc(&tcon->num_renames); -+ } -+#endif -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto renameRetry; -+ -+ return rc; -+} -+ -+int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, -+ int netfid, char * target_name, const struct nls_table * nls_codepage) -+{ -+ struct smb_com_transaction2_sfi_req *pSMB = NULL; -+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; -+ struct set_file_rename * rename_info; -+ char *data_offset; -+ char dummy_string[30]; -+ int rc = 0; -+ int bytes_returned = 0; -+ int len_of_str; -+ -+ cFYI(1, ("Rename to File by handle")); -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->ParameterCount = 6; -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req, -+ Fid) - 4; -+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; -+ -+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset; -+ rename_info = (struct set_file_rename *) data_offset; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); -+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount; -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); -+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); -+ /* construct random name ".cifs_tmp<inodenum><mid>" */ -+ rename_info->overwrite = cpu_to_le32(1); -+ rename_info->root_fid = 0; -+ /* unicode only call */ -+ if(target_name == NULL) { -+ sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); -+ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage); -+ } else { -+ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage); -+ } -+ rename_info->target_name_len = cpu_to_le32(2 * len_of_str); -+ pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2; -+ pSMB->ByteCount += pSMB->DataCount; -+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount); -+ pSMB->TotalDataCount = pSMB->DataCount; -+ pSMB->Fid = netfid; -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1,("Send error in Rename (by file handle) = %d", rc)); -+ } -+#ifdef CONFIG_CIFS_STATS -+ else { -+ atomic_inc(&pTcon->num_t2renames); -+ } -+#endif -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Note: On -EAGAIN error only caller can retry on handle based calls -+ since file handle passed in no longer valid */ -+ -+ return rc; -+} -+ -+int -+CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, -+ const __u16 target_tid, const char *toName, const int flags, -+ const struct nls_table *nls_codepage) -+{ -+ int rc = 0; -+ COPY_REQ *pSMB = NULL; -+ COPY_RSP *pSMBr = NULL; -+ int bytes_returned; -+ int name_len, name_len2; -+ -+ cFYI(1, ("In CIFSSMBCopy")); -+copyRetry: -+ rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->BufferFormat = 0x04; -+ pSMB->Tid2 = target_tid; -+ -+ if(flags & COPY_TREE) -+ pSMB->Flags |= COPY_TREE; -+ pSMB->Flags = cpu_to_le16(pSMB->Flags); -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, -+ fromName, -+ 530 /* find define for this maxpathcomponent */, -+ nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ pSMB->OldFileName[name_len] = 0x04; /* pad */ -+ /* protocol requires ASCII signature byte on Unicode string */ -+ pSMB->OldFileName[name_len + 1] = 0x00; -+ name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> -+ OldFileName[name_len + 2], toName, 530, -+ nls_codepage); -+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; -+ name_len2 *= 2; /* convert to bytes */ -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fromName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->OldFileName, fromName, name_len); -+ name_len2 = strnlen(toName, 530); -+ name_len2++; /* trailing null */ -+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ -+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); -+ name_len2++; /* trailing null */ -+ name_len2++; /* signature byte */ -+ } -+ -+ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in copy = %d with %d files copied", -+ rc, pSMBr->CopyCount)); -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto copyRetry; -+ -+ return rc; -+} -+ -+int -+CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage) -+{ -+ TRANSACTION2_SPI_REQ *pSMB = NULL; -+ TRANSACTION2_SPI_RSP *pSMBr = NULL; -+ char *data_offset; -+ int name_len; -+ int name_len_target; -+ int rc = 0; -+ int bytes_returned = 0; -+ -+ cFYI(1, ("In Symlink Unix style")); -+createSymLinkRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fromName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, fromName, name_len); -+ } -+ pSMB->ParameterCount = 6 + name_len; -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req, -+ InformationLevel) - 4; -+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; -+ -+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset; -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len_target = -+ cifs_strtoUCS((wchar_t *) data_offset, toName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len_target++; /* trailing null */ -+ name_len_target *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len_target = strnlen(toName, 530); -+ name_len_target++; /* trailing null */ -+ strncpy(data_offset, toName, name_len_target); -+ } -+ -+ pSMB->DataCount = name_len_target; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ /* BB find exact max on data count below from sess */ -+ pSMB->MaxDataCount = cpu_to_le16(1000); -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); -+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount; -+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount); -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalDataCount = pSMB->DataCount; -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); -+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); -+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, -+ ("Send error in SetPathInfo (create symlink) = %d", -+ rc)); -+ } -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto createSymLinkRetry; -+ -+ return rc; -+} -+ -+int -+CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage) -+{ -+ TRANSACTION2_SPI_REQ *pSMB = NULL; -+ TRANSACTION2_SPI_RSP *pSMBr = NULL; -+ char *data_offset; -+ int name_len; -+ int name_len_target; -+ int rc = 0; -+ int bytes_returned = 0; -+ -+ cFYI(1, ("In Create Hard link Unix style")); -+createHardLinkRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(toName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, toName, name_len); -+ } -+ pSMB->ParameterCount = 6 + name_len; -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req, -+ InformationLevel) - 4; -+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; -+ -+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset; -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len_target = -+ cifs_strtoUCS((wchar_t *) data_offset, fromName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len_target++; /* trailing null */ -+ name_len_target *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len_target = strnlen(fromName, 530); -+ name_len_target++; /* trailing null */ -+ strncpy(data_offset, fromName, name_len_target); -+ } -+ -+ pSMB->DataCount = name_len_target; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ /* BB find exact max on data count below from sess*/ -+ pSMB->MaxDataCount = cpu_to_le16(1000); -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); -+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount; -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount); -+ pSMB->TotalDataCount = pSMB->DataCount; -+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); -+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); -+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); -+ } -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto createHardLinkRetry; -+ -+ return rc; -+} -+ -+int -+CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, -+ const char *fromName, const char *toName, -+ const struct nls_table *nls_codepage) -+{ -+ int rc = 0; -+ NT_RENAME_REQ *pSMB = NULL; -+ RENAME_RSP *pSMBr = NULL; -+ int bytes_returned; -+ int name_len, name_len2; -+ -+ cFYI(1, ("In CIFSCreateHardLink")); -+winCreateHardLinkRetry: -+ -+ rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->SearchAttributes = -+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | -+ ATTR_DIRECTORY); -+ pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK); -+ pSMB->ClusterCount = 0; -+ -+ pSMB->BufferFormat = 0x04; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ pSMB->OldFileName[name_len] = 0; /* pad */ -+ pSMB->OldFileName[name_len + 1] = 0x04; -+ name_len2 = -+ cifs_strtoUCS((wchar_t *) & pSMB-> -+ OldFileName[name_len + 2], toName, 530, -+ nls_codepage); -+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; -+ name_len2 *= 2; /* convert to bytes */ -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fromName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->OldFileName, fromName, name_len); -+ name_len2 = strnlen(toName, 530); -+ name_len2++; /* trailing null */ -+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ -+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); -+ name_len2++; /* trailing null */ -+ name_len2++; /* signature byte */ -+ } -+ -+ pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto winCreateHardLinkRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ char *symlinkinfo, const int buflen, -+ const struct nls_table *nls_codepage) -+{ -+/* SMB_QUERY_FILE_UNIX_LINK */ -+ TRANSACTION2_QPI_REQ *pSMB = NULL; -+ TRANSACTION2_QPI_RSP *pSMBr = NULL; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ -+ cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName)); -+ -+querySymLinkRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(searchName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, searchName, name_len); -+ } -+ -+ pSMB->TotalParameterCount = -+ 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ /* BB find exact max data count below from sess structure BB */ -+ pSMB->MaxDataCount = cpu_to_le16(4000); -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount); -+ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512)) -+ /* BB also check enough total bytes returned */ -+ rc = -EIO; /* bad smb */ -+ else { -+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = UniStrnlen((wchar_t *) ((char *) -+ &pSMBr->hdr.Protocol +pSMBr->DataOffset), -+ min_t(const int, buflen,pSMBr->DataCount) / 2); -+ cifs_strfromUCS_le(symlinkinfo, -+ (wchar_t *) ((char *)&pSMBr->hdr.Protocol + -+ pSMBr->DataOffset), -+ name_len, nls_codepage); -+ } else { -+ strncpy(symlinkinfo, -+ (char *) &pSMBr->hdr.Protocol + -+ pSMBr->DataOffset, -+ min_t(const int, buflen, pSMBr->DataCount)); -+ } -+ symlinkinfo[buflen] = 0; -+ /* just in case so calling code does not go off the end of buffer */ -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto querySymLinkRetry; -+ return rc; -+} -+ -+ -+ -+int -+CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ char *symlinkinfo, const int buflen,__u16 fid, -+ const struct nls_table *nls_codepage) -+{ -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ struct smb_com_transaction_ioctl_req * pSMB; -+ struct smb_com_transaction_ioctl_rsp * pSMBr; -+ -+ cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName)); -+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->TotalParameterCount = 0 ; -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le32(2); -+ /* BB find exact data count max from sess structure BB */ -+ pSMB->MaxDataCount = cpu_to_le32(4000); -+ pSMB->MaxSetupCount = 4; -+ pSMB->Reserved = 0; -+ pSMB->ParameterOffset = 0; -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 4; -+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT); -+ pSMB->IsFsctl = 1; /* FSCTL */ -+ pSMB->IsRootFlag = 0; -+ pSMB->Fid = fid; /* file handle always le */ -+ pSMB->ByteCount = 0; -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount); -+ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512)) -+ /* BB also check enough total bytes returned */ -+ rc = -EIO; /* bad smb */ -+ else { -+ if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) { -+ /* could also validate reparse tag && better check name length */ -+ struct reparse_data * reparse_buf = (struct reparse_data *) -+ ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset); -+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = UniStrnlen((wchar_t *) -+ (reparse_buf->LinkNamesBuf + -+ reparse_buf->TargetNameOffset), -+ min(buflen/2, reparse_buf->TargetNameLen / 2)); -+ cifs_strfromUCS_le(symlinkinfo, -+ (wchar_t *) (reparse_buf->LinkNamesBuf + -+ reparse_buf->TargetNameOffset), -+ name_len, nls_codepage); -+ } else { /* ASCII names */ -+ strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + -+ reparse_buf->TargetNameOffset, -+ min_t(const int, buflen, reparse_buf->TargetNameLen)); -+ } -+ } else { -+ rc = -EIO; -+ cFYI(1,("Invalid return data count on get reparse info ioctl")); -+ } -+ symlinkinfo[buflen] = 0; /* just in case so the caller -+ does not go off the end of the buffer */ -+ cFYI(1,("readlink result - %s ",symlinkinfo)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Note: On -EAGAIN error only caller can retry on handle based calls -+ since file handle passed in no longer valid */ -+ -+ return rc; -+} -+ -+int -+CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ FILE_ALL_INFO * pFindData, -+ const struct nls_table *nls_codepage) -+{ -+/* level 263 SMB_QUERY_FILE_ALL_INFO */ -+ TRANSACTION2_QPI_REQ *pSMB = NULL; -+ TRANSACTION2_QPI_RSP *pSMBr = NULL; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ -+ cFYI(1, ("In QPathInfo path %s", searchName)); -+QPathInfoRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(searchName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, searchName, name_len); -+ } -+ -+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ + -+ name_len /* includes null */ ; -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in QPathInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ /* BB also check enough total bytes returned */ -+ /* BB we need to improve the validity checking -+ of these trans2 responses */ -+ if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) -+ rc = -EIO; /* bad smb */ -+ else if (pFindData){ -+ memcpy((char *) pFindData, -+ (char *) &pSMBr->hdr.Protocol + -+ pSMBr->DataOffset, sizeof (FILE_ALL_INFO)); -+ } else -+ rc = -ENOMEM; -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto QPathInfoRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ FILE_UNIX_BASIC_INFO * pFindData, -+ const struct nls_table *nls_codepage) -+{ -+/* SMB_QUERY_FILE_UNIX_BASIC */ -+ TRANSACTION2_QPI_REQ *pSMB = NULL; -+ TRANSACTION2_QPI_RSP *pSMBr = NULL; -+ int rc = 0; -+ int bytes_returned = 0; -+ int name_len; -+ -+ cFYI(1, ("In QPathInfo (Unix) the path %s", searchName)); -+UnixQPathInfoRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(searchName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, searchName, name_len); -+ } -+ -+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ + -+ name_len /* includes null */ ; -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxDataCount = cpu_to_le16(4000); -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in QPathInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ /* BB also check if enough total bytes returned */ -+ if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || -+ (pSMBr->DataOffset > 512) || -+ (pSMBr->DataOffset < sizeof(struct smb_hdr))) { -+ cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d", -+ (int)pSMBr->DataOffset,bytes_returned)); -+ rc = -EIO; /* bad smb */ -+ } else { -+ memcpy((char *) pFindData, -+ (char *) &pSMBr->hdr.Protocol + -+ pSMBr->DataOffset, -+ sizeof (FILE_UNIX_BASIC_INFO)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto UnixQPathInfoRetry; -+ -+ return rc; -+} -+ -+int -+CIFSFindSingle(const int xid, struct cifsTconInfo *tcon, -+ const char *searchName, FILE_ALL_INFO * findData, -+ const struct nls_table *nls_codepage) -+{ -+/* level 257 SMB_ */ -+ TRANSACTION2_FFIRST_REQ *pSMB = NULL; -+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ -+ cFYI(1, ("In FindUnique")); -+findUniqueRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(searchName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, searchName, name_len); -+ } -+ -+ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ; -+ pSMB->TotalDataCount = 0; /* no EAs */ -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = cpu_to_le16( -+ offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; /* one byte, no need to le convert */ -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->SearchAttributes = -+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | -+ ATTR_DIRECTORY); -+ pSMB->SearchCount = cpu_to_le16(16); /* BB increase */ -+ pSMB->SearchFlags = cpu_to_le16(1); -+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); -+ pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */ -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ -+ if (rc) { -+ cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); -+ } else { /* decode response */ -+ -+ /* BB fill in */ -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto findUniqueRetry; -+ -+ return rc; -+} -+ -+int -+CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, -+ const char *searchName, FILE_DIRECTORY_INFO * findData, -+ T2_FFIRST_RSP_PARMS * findParms, -+ const struct nls_table *nls_codepage, int *pUnicodeFlag, -+ int *pUnixFlag) -+{ -+/* level 257 SMB_ */ -+ TRANSACTION2_FFIRST_REQ *pSMB = NULL; -+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL; -+ char *response_data; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ -+ cFYI(1, ("In FindFirst")); -+findFirstRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(searchName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, searchName, name_len); -+ } -+ -+ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ; -+ pSMB->TotalDataCount = 0; /* no EAs */ -+ pSMB->MaxParameterCount = cpu_to_le16(10); -+ pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf - -+ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct -+ smb_com_transaction2_ffirst_req, SearchAttributes) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; /* one byte no need to make endian neutral */ -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); -+ pSMB->SearchAttributes = -+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | -+ ATTR_DIRECTORY); -+ pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */ -+ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); -+ -+ /* test for Unix extensions */ -+ if (tcon->ses->capabilities & CAP_UNIX) { -+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); -+ *pUnixFlag = TRUE; -+ } else { -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); -+ *pUnixFlag = FALSE; -+ } -+ pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */ -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ -+ if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ -+ cFYI(1, ("Error in FindFirst = %d", rc)); -+ } else { /* decode response */ -+ /* BB add safety checks for these memcpys */ -+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) -+ *pUnicodeFlag = TRUE; -+ else -+ *pUnicodeFlag = FALSE; -+ memcpy(findParms, -+ (char *) &pSMBr->hdr.Protocol + -+ le16_to_cpu(pSMBr->ParameterOffset), -+ sizeof (T2_FFIRST_RSP_PARMS)); -+ /* search handle can stay LE and EAoffset not needed so not converted */ -+ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch); -+ findParms->LastNameOffset = -+ le16_to_cpu(findParms->LastNameOffset); -+ findParms->SearchCount = le16_to_cpu(findParms->SearchCount); -+ response_data = -+ (char *) &pSMBr->hdr.Protocol + -+ le16_to_cpu(pSMBr->DataOffset); -+ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto findFirstRetry; -+ -+ return rc; -+} -+ -+int -+CIFSFindNext(const int xid, struct cifsTconInfo *tcon, -+ FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms, -+ const __u16 searchHandle, char * resume_file_name, int name_len, -+ __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag) -+{ -+/* level 257 SMB_ */ -+ TRANSACTION2_FNEXT_REQ *pSMB = NULL; -+ TRANSACTION2_FNEXT_RSP *pSMBr = NULL; -+ char *response_data; -+ int rc = 0; -+ int bytes_returned; -+ -+ cFYI(1, ("In FindNext")); -+ -+ if(resume_file_name == NULL) { -+ return -EIO; -+ } -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */ -+ pSMB->TotalDataCount = 0; /* no EAs */ -+ pSMB->MaxParameterCount = cpu_to_le16(8); -+ pSMB->MaxDataCount = -+ cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_fnext_req,SearchHandle) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); -+ pSMB->SearchHandle = searchHandle; /* always kept as le */ -+ findParms->SearchCount = 0; /* set to zero in case of error */ -+ pSMB->SearchCount = -+ cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); -+ /* test for Unix extensions */ -+ if (tcon->ses->capabilities & CAP_UNIX) { -+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); -+ *pUnixFlag = TRUE; -+ } else { -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); -+ *pUnixFlag = FALSE; -+ } -+ pSMB->ResumeKey = resume_key; -+ pSMB->SearchFlags = -+ cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); -+ /* BB add check to make sure we do not cross end of smb */ -+ if(name_len < CIFS_MAX_MSGSIZE) { -+ memcpy(pSMB->ResumeFileName, resume_file_name, name_len); -+ pSMB->ByteCount += name_len; -+ } -+ pSMB->TotalParameterCount += name_len; -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ /* BB improve error handling here */ -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ -+ if (rc) { -+ if (rc == -EBADF) -+ rc = 0; /* search probably was closed at end of search above */ -+ else -+ cFYI(1, ("FindNext returned = %d", rc)); -+ } else { /* decode response */ -+ /* BB add safety checks for these memcpys */ -+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) -+ *pUnicodeFlag = TRUE; -+ else -+ *pUnicodeFlag = FALSE; -+ memcpy(findParms, -+ (char *) &pSMBr->hdr.Protocol + -+ le16_to_cpu(pSMBr->ParameterOffset), -+ sizeof (T2_FNEXT_RSP_PARMS)); -+ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch); -+ findParms->LastNameOffset = -+ le16_to_cpu(findParms->LastNameOffset); -+ findParms->SearchCount = le16_to_cpu(findParms->SearchCount); -+ response_data = -+ (char *) &pSMBr->hdr.Protocol + -+ le16_to_cpu(pSMBr->DataOffset); -+ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Note: On -EAGAIN error only caller can retry on handle based calls -+ since file handle passed in no longer valid */ -+ -+ return rc; -+} -+ -+int -+CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle) -+{ -+ int rc = 0; -+ FINDCLOSE_REQ *pSMB = NULL; -+ CLOSE_RSP *pSMBr = NULL; -+ int bytes_returned; -+ -+ cFYI(1, ("In CIFSSMBFindClose")); -+ rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ /* no sense returning error if session restarted -+ file handle has been closed */ -+ if(rc == -EAGAIN) -+ return 0; -+ if (rc) -+ return rc; -+ -+ pSMB->FileID = searchHandle; -+ pSMB->ByteCount = 0; -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cERROR(1, ("Send error in FindClose = %d", rc)); -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Since session is dead, search handle closed on server already */ -+ if (rc == -EAGAIN) -+ rc = 0; -+ -+ return rc; -+} -+ -+int -+CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, -+ const unsigned char *searchName, -+ unsigned char **targetUNCs, -+ unsigned int *number_of_UNC_in_array, -+ const struct nls_table *nls_codepage) -+{ -+/* TRANS2_GET_DFS_REFERRAL */ -+ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; -+ TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; -+ struct dfs_referral_level_3 * referrals = NULL; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ unsigned int i; -+ char * temp; -+ *number_of_UNC_in_array = 0; -+ *targetUNCs = NULL; -+ -+ cFYI(1, ("In GetDFSRefer the path %s", searchName)); -+ if (ses == NULL) -+ return -ENODEV; -+getDFSRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->hdr.Tid = ses->ipc_tid; -+ pSMB->hdr.Uid = ses->Suid; -+ if (ses->capabilities & CAP_STATUS32) { -+ pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; -+ } -+ if (ses->capabilities & CAP_DFS) { -+ pSMB->hdr.Flags2 |= SMBFLG2_DFS; -+ } -+ -+ if (ses->capabilities & CAP_UNICODE) { -+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->RequestFileName, -+ searchName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(searchName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->RequestFileName, searchName, name_len); -+ } -+ -+ pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ; -+ pSMB->TotalDataCount = 0; -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->MaxParameterCount = 0; -+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4); -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL); -+ pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ; -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->MaxReferralLevel = cpu_to_le16(3); -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in GetDFSRefer = %d", rc)); -+ } else { /* decode response */ -+/* BB Add logic to parse referrals here */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount); -+ cFYI(1, -+ ("Decoding GetDFSRefer response. BCC: %d Offset %d", -+ pSMBr->ByteCount, pSMBr->DataOffset)); -+ if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */ -+ rc = -EIO; /* bad smb */ -+ else { -+ referrals = -+ (struct dfs_referral_level_3 *) -+ (8 /* sizeof start of data block */ + -+ pSMBr->DataOffset + -+ (char *) &pSMBr->hdr.Protocol); -+ cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive)); -+ /* BB This field is actually two bytes in from start of -+ data block so we could do safety check that DataBlock -+ begins at address of pSMBr->NumberOfReferrals */ -+ *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals); -+ -+ /* BB Fix below so can return more than one referral */ -+ if(*number_of_UNC_in_array > 1) -+ *number_of_UNC_in_array = 1; -+ -+ /* get the length of the strings describing refs */ -+ name_len = 0; -+ for(i=0;i<*number_of_UNC_in_array;i++) { -+ /* make sure that DfsPathOffset not past end */ -+ referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset); -+ if(referrals->DfsPathOffset > pSMBr->DataCount) { -+ /* if invalid referral, stop here and do -+ not try to copy any more */ -+ *number_of_UNC_in_array = i; -+ break; -+ } -+ temp = ((char *)referrals) + referrals->DfsPathOffset; -+ -+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount); -+ } else { -+ name_len += strnlen(temp,pSMBr->DataCount); -+ } -+ referrals++; -+ /* BB add check that referral pointer does not fall off end PDU */ -+ -+ } -+ /* BB add check for name_len bigger than bcc */ -+ *targetUNCs = -+ kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL); -+ /* copy the ref strings */ -+ referrals = -+ (struct dfs_referral_level_3 *) -+ (8 /* sizeof data hdr */ + -+ pSMBr->DataOffset + -+ (char *) &pSMBr->hdr.Protocol); -+ -+ for(i=0;i<*number_of_UNC_in_array;i++) { -+ temp = ((char *)referrals) + referrals->DfsPathOffset; -+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { -+ cifs_strfromUCS_le(*targetUNCs, -+ (wchar_t *) temp, name_len, nls_codepage); -+ } else { -+ strncpy(*targetUNCs,temp,name_len); -+ } -+ /* BB update target_uncs pointers */ -+ referrals++; -+ } -+ temp = *targetUNCs; -+ temp[name_len] = 0; -+ } -+ -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto getDFSRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, -+ struct statfs *FSData, const struct nls_table *nls_codepage) -+{ -+/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ -+ TRANSACTION2_QFSI_REQ *pSMB = NULL; -+ TRANSACTION2_QFSI_RSP *pSMBr = NULL; -+ FILE_SYSTEM_INFO *response_data; -+ int rc = 0; -+ int bytes_returned = 0; -+ -+ cFYI(1, ("In QFSInfo")); -+QFSInfoRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->TotalParameterCount = 2; /* level */ -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); -+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cERROR(1, ("Send error in QFSInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ cFYI(1, -+ ("Decoding qfsinfo response. BCC: %d Offset %d", -+ pSMBr->ByteCount, pSMBr->DataOffset)); -+ if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */ -+ rc = -EIO; /* bad smb */ -+ else { -+ response_data = -+ (FILE_SYSTEM_INFO -+ *) (((char *) &pSMBr->hdr.Protocol) + -+ pSMBr->DataOffset); -+ FSData->f_bsize = -+ le32_to_cpu(response_data->BytesPerSector) * -+ le32_to_cpu(response_data-> -+ SectorsPerAllocationUnit); -+ FSData->f_blocks = -+ le64_to_cpu(response_data->TotalAllocationUnits); -+ FSData->f_bfree = FSData->f_bavail = -+ le64_to_cpu(response_data->FreeAllocationUnits); -+ cFYI(1, -+ ("Blocks: %lld Free: %lld Block size %ld", -+ (unsigned long long)FSData->f_blocks, -+ (unsigned long long)FSData->f_bfree, -+ FSData->f_bsize)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto QFSInfoRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon, -+ const struct nls_table *nls_codepage) -+{ -+/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */ -+ TRANSACTION2_QFSI_REQ *pSMB = NULL; -+ TRANSACTION2_QFSI_RSP *pSMBr = NULL; -+ FILE_SYSTEM_ATTRIBUTE_INFO *response_data; -+ int rc = 0; -+ int bytes_returned = 0; -+ -+ cFYI(1, ("In QFSAttributeInfo")); -+QFSAttributeRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->TotalParameterCount = 2; /* level */ -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); -+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cERROR(1, ("Send error in QFSAttributeInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */ -+ rc = -EIO; /* bad smb */ -+ } else { -+ response_data = -+ (FILE_SYSTEM_ATTRIBUTE_INFO -+ *) (((char *) &pSMBr->hdr.Protocol) + -+ pSMBr->DataOffset); -+ response_data->Attributes = le32_to_cpu(response_data->Attributes); -+ response_data->MaxPathNameComponentLength = -+ le32_to_cpu(response_data->MaxPathNameComponentLength); -+ response_data->FileSystemNameLen = -+ le32_to_cpu(response_data->FileSystemNameLen); -+ memcpy(&tcon->fsAttrInfo, response_data, -+ sizeof (FILE_SYSTEM_ATTRIBUTE_INFO)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto QFSAttributeRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon, -+ const struct nls_table *nls_codepage) -+{ -+/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */ -+ TRANSACTION2_QFSI_REQ *pSMB = NULL; -+ TRANSACTION2_QFSI_RSP *pSMBr = NULL; -+ FILE_SYSTEM_DEVICE_INFO *response_data; -+ int rc = 0; -+ int bytes_returned = 0; -+ -+ cFYI(1, ("In QFSDeviceInfo")); -+QFSDeviceRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->TotalParameterCount = 2; /* level */ -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); -+ -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); -+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in QFSDeviceInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)) -+ || (pSMBr->DataOffset > 512)) -+ rc = -EIO; /* bad smb */ -+ else { -+ response_data = -+ (FILE_SYSTEM_DEVICE_INFO -+ *) (((char *) &pSMBr->hdr.Protocol) + -+ pSMBr->DataOffset); -+ response_data->DeviceType = -+ le32_to_cpu(response_data->DeviceType); -+ response_data->DeviceCharacteristics = -+ le32_to_cpu(response_data->DeviceCharacteristics); -+ memcpy(&tcon->fsDevInfo, response_data, -+ sizeof (FILE_SYSTEM_DEVICE_INFO)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto QFSDeviceRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon, -+ const struct nls_table *nls_codepage) -+{ -+/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */ -+ TRANSACTION2_QFSI_REQ *pSMB = NULL; -+ TRANSACTION2_QFSI_RSP *pSMBr = NULL; -+ FILE_SYSTEM_UNIX_INFO *response_data; -+ int rc = 0; -+ int bytes_returned = 0; -+ -+ cFYI(1, ("In QFSUnixInfo")); -+QFSUnixRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->ParameterCount = 2; /* level */ -+ pSMB->TotalDataCount = 0; -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ; -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct -+ smb_com_transaction2_qfsi_req, InformationLevel) - 4); -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); -+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cERROR(1, ("Send error in QFSUnixInfo = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset); -+ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { -+ rc = -EIO; /* bad smb */ -+ } else { -+ response_data = -+ (FILE_SYSTEM_UNIX_INFO -+ *) (((char *) &pSMBr->hdr.Protocol) + -+ pSMBr->DataOffset); -+ response_data->MajorVersionNumber = -+ le16_to_cpu(response_data->MajorVersionNumber); -+ response_data->MinorVersionNumber = -+ le16_to_cpu(response_data->MinorVersionNumber); -+ response_data->Capability = -+ le64_to_cpu(response_data->Capability); -+ memcpy(&tcon->fsUnixInfo, response_data, -+ sizeof (FILE_SYSTEM_UNIX_INFO)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto QFSUnixRetry; -+ -+ -+ return rc; -+} -+ -+/* We can not use write of zero bytes trick to -+ set file size due to need for large file support. Also note that -+ this SetPathInfo is preferred to SetFileInfo based method in next -+ routine which is only needed to work around a sharing violation bug -+ in Samba which this routine can run into */ -+ -+int -+CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName, -+ __u64 size, int SetAllocation, const struct nls_table *nls_codepage) -+{ -+ struct smb_com_transaction2_spi_req *pSMB = NULL; -+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL; -+ struct file_end_of_file_info *parm_data; -+ int name_len; -+ int rc = 0; -+ int bytes_returned = 0; -+ -+ cFYI(1, ("In SetEOF")); -+SetEOFRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fileName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, fileName, name_len); -+ } -+ pSMB->ParameterCount = 6 + name_len; -+ pSMB->DataCount = sizeof (struct file_end_of_file_info); -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req, -+ InformationLevel) - 4; -+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; -+ if(SetAllocation) { -+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); -+ else -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO); -+ } else /* Set File Size */ { -+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2); -+ else -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); -+ } -+ -+ parm_data = -+ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) + -+ pSMB->DataOffset); -+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); -+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); -+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount; -+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount); -+ pSMB->TotalDataCount = pSMB->DataCount; -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ parm_data->FileSize = cpu_to_le64(size); -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("SetPathInfo (file size) returned %d", rc)); -+ } -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto SetEOFRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, -+ __u16 fid, __u32 pid_of_opener, int SetAllocation) -+{ -+ struct smb_com_transaction2_sfi_req *pSMB = NULL; -+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; -+ char *data_offset; -+ struct file_end_of_file_info *parm_data; -+ int rc = 0; -+ int bytes_returned = 0; -+ __u32 tmp; -+ -+ cFYI(1, ("SetFileSize (via SetFileInfo) %lld", -+ (long long)size)); -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ tmp = cpu_to_le32(pid_of_opener); /* override pid of current process -+ so network fid will be valid */ -+ pSMB->hdr.Pid = tmp & 0xFFFF; -+ tmp >>= 16; -+ pSMB->hdr.PidHigh = tmp & 0xFFFF; -+ -+ pSMB->ParameterCount = 6; -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req, -+ Fid) - 4; -+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; -+ -+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset; -+ -+ pSMB->DataCount = sizeof(struct file_end_of_file_info); -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); -+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount; -+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount); -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalDataCount = pSMB->DataCount; -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); -+ parm_data = -+ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) + -+ pSMB->DataOffset); -+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */ -+ parm_data->FileSize = cpu_to_le64(size); -+ pSMB->Fid = fid; -+ if(SetAllocation) { -+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); -+ else -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO); -+ } else /* Set File Size */ { -+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2); -+ else -+ pSMB->InformationLevel = -+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); -+ } -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, -+ ("Send error in SetFileInfo (SetFileSize) = %d", -+ rc)); -+ } -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ /* Note: On -EAGAIN error only caller can retry on handle based calls -+ since file handle passed in no longer valid */ -+ -+ return rc; -+} -+ -+int -+CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName, -+ FILE_BASIC_INFO * data, const struct nls_table *nls_codepage) -+{ -+ TRANSACTION2_SPI_REQ *pSMB = NULL; -+ TRANSACTION2_SPI_RSP *pSMBr = NULL; -+ int name_len; -+ int rc = 0; -+ int bytes_returned = 0; -+ char *data_offset; -+ -+ cFYI(1, ("In SetTimes")); -+ -+SetTimesRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fileName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, fileName, name_len); -+ } -+ -+ pSMB->ParameterCount = 6 + name_len; -+ pSMB->DataCount = sizeof (FILE_BASIC_INFO); -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req, -+ InformationLevel) - 4; -+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; -+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset; -+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); -+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); -+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount; -+ -+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount); -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->TotalDataCount = pSMB->DataCount; -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) -+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2); -+ else -+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ memcpy(data_offset, data, sizeof (FILE_BASIC_INFO)); -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("SetPathInfo (times) returned %d", rc)); -+ } -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ -+ if (rc == -EAGAIN) -+ goto SetTimesRetry; -+ -+ return rc; -+} -+ -+int -+CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, -+ char *fileName, __u64 mode, __u64 uid, __u64 gid, -+ dev_t device, const struct nls_table *nls_codepage) -+{ -+ TRANSACTION2_SPI_REQ *pSMB = NULL; -+ TRANSACTION2_SPI_RSP *pSMBr = NULL; -+ int name_len; -+ int rc = 0; -+ int bytes_returned = 0; -+ FILE_UNIX_BASIC_INFO *data_offset; -+ -+ cFYI(1, ("In SetUID/GID/Mode")); -+setPermsRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(fileName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, fileName, name_len); -+ } -+ -+ pSMB->ParameterCount = 6 + name_len; -+ pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO); -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req, -+ InformationLevel) - 4; -+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; -+ data_offset = -+ (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol + -+ pSMB->DataOffset); -+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); -+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); -+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount; -+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); -+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount); -+ pSMB->TotalParameterCount = pSMB->ParameterCount; -+ pSMB->TotalDataCount = pSMB->DataCount; -+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ data_offset->Uid = cpu_to_le64(uid); -+ data_offset->Gid = cpu_to_le64(gid); -+ /* better to leave device as zero when it is */ -+ data_offset->DevMajor = cpu_to_le64(MAJOR(device)); -+ data_offset->DevMinor = cpu_to_le64(MINOR(device)); -+ data_offset->Permissions = cpu_to_le64(mode); -+ -+ if(S_ISREG(mode)) -+ data_offset->Type = cpu_to_le32(UNIX_FILE); -+ else if(S_ISDIR(mode)) -+ data_offset->Type = cpu_to_le32(UNIX_DIR); -+ else if(S_ISLNK(mode)) -+ data_offset->Type = cpu_to_le32(UNIX_SYMLINK); -+ else if(S_ISCHR(mode)) -+ data_offset->Type = cpu_to_le32(UNIX_CHARDEV); -+ else if(S_ISBLK(mode)) -+ data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); -+ else if(S_ISFIFO(mode)) -+ data_offset->Type = cpu_to_le32(UNIX_FIFO); -+ else if(S_ISSOCK(mode)) -+ data_offset->Type = cpu_to_le32(UNIX_SOCKET); -+ -+ -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("SetPathInfo (perms) returned %d", rc)); -+ } -+ -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto setPermsRetry; -+ return rc; -+} -+ -+int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, -+ const int notify_subdirs, const __u16 netfid, -+ __u32 filter, const struct nls_table *nls_codepage) -+{ -+ int rc = 0; -+ struct smb_com_transaction_change_notify_req * pSMB = NULL; -+ struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; -+ int bytes_returned; -+ -+ cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); -+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ pSMB->TotalParameterCount = 0 ; -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le32(2); -+ /* BB find exact data count max from sess structure BB */ -+ pSMB->MaxDataCount = 0; /* same in little endian or be */ -+ pSMB->MaxSetupCount = 4; -+ pSMB->Reserved = 0; -+ pSMB->ParameterOffset = 0; -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 4; /* single byte does not need le conversion */ -+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ if(notify_subdirs) -+ pSMB->WatchTree = 1; /* one byte - no le conversion needed */ -+ pSMB->Reserved2 = 0; -+ pSMB->CompletionFilter = cpu_to_le32(filter); -+ pSMB->Fid = netfid; /* file handle always le */ -+ pSMB->ByteCount = 0; -+ -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Error in Notify = %d", rc)); -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+/* if (rc == -EAGAIN) -+ goto NotifyRetry; */ -+ return rc; -+} -+#ifdef CONFIG_CIFS_XATTR -+int -+CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, -+ const unsigned char *searchName, -+ char * EAData, size_t size, -+ const struct nls_table *nls_codepage) -+{ -+ /* BB assumes one setup word */ -+ TRANSACTION2_QPI_REQ *pSMB = NULL; -+ TRANSACTION2_QPI_RSP *pSMBr = NULL; -+ int rc = 0; -+ int bytes_returned; -+ int name_len; -+ -+ cFYI(1, ("In Query All EAs path %s", searchName)); -+QAllEAsRetry: -+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, -+ (void **) &pSMBr); -+ if (rc) -+ return rc; -+ -+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { -+ name_len = -+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 -+ /* find define for this maxpathcomponent */ -+ , nls_codepage); -+ name_len++; /* trailing null */ -+ name_len *= 2; -+ } else { /* BB improve the check for buffer overruns BB */ -+ name_len = strnlen(searchName, 530); -+ name_len++; /* trailing null */ -+ strncpy(pSMB->FileName, searchName, name_len); -+ } -+ -+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ + -+ name_len /* includes null */ ; -+ pSMB->TotalDataCount = 0; -+ pSMB->MaxParameterCount = cpu_to_le16(2); -+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ -+ pSMB->MaxSetupCount = 0; -+ pSMB->Reserved = 0; -+ pSMB->Flags = 0; -+ pSMB->Timeout = 0; -+ pSMB->Reserved2 = 0; -+ pSMB->ParameterOffset = cpu_to_le16(offsetof( -+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); -+ pSMB->DataCount = 0; -+ pSMB->DataOffset = 0; -+ pSMB->SetupCount = 1; -+ pSMB->Reserved3 = 0; -+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); -+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ; -+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount); -+ pSMB->ParameterCount = pSMB->TotalParameterCount; -+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); -+ pSMB->Reserved4 = 0; -+ pSMB->hdr.smb_buf_length += pSMB->ByteCount; -+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); -+ -+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -+ (struct smb_hdr *) pSMBr, &bytes_returned, 0); -+ if (rc) { -+ cFYI(1, ("Send error in QueryAllEAs = %d", rc)); -+ } else { /* decode response */ -+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); -+ /* BB also check enough total bytes returned */ -+ /* BB we need to improve the validity checking -+ of these trans2 responses */ -+ if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) -+ rc = -EIO; /* bad smb */ -+ /* else if (pFindData){ -+ memcpy((char *) pFindData, -+ (char *) &pSMBr->hdr.Protocol + -+ pSMBr->DataOffset, kl); -+ }*/ else { -+ /* check that length of list is not more than bcc */ -+ /* check that each entry does not go beyond length -+ of list */ -+ /* check that each element of each entry does not -+ go beyond end of list */ -+ struct fealist * ea_response_data; -+ rc = 0; -+ /* validate_trans2_offsets() */ -+ /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/ -+ ea_response_data = (struct fealist *) -+ (((char *) &pSMBr->hdr.Protocol) + -+ pSMBr->DataOffset); -+ cFYI(1,("ea length %d",ea_response_data->list_len)); -+ } -+ } -+ if (pSMB) -+ cifs_buf_release(pSMB); -+ if (rc == -EAGAIN) -+ goto QAllEAsRetry; -+ -+ return rc; -+} -+#endif ---- /dev/null -+++ b/fs/cifs/cifs_unicode.c -@@ -0,0 +1,87 @@ -+/* -+ * 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 <linux/fs.h> -+#include "cifs_unicode.h" -+#include "cifs_uniupr.h" -+#include "cifspdu.h" -+#include "cifs_debug.h" -+ -+/* -+ * 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; -+ 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; -+ -+ 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", -+ charlen)); -+ to[i] = cpu_to_le16(0x003f); /* a question mark */ -+ charlen = 1; -+ } -+ to[i] = cpu_to_le16(to[i]); -+ -+ } -+ -+ to[i] = 0; -+ return i; -+} -+ ---- /dev/null -+++ b/fs/cifs/cifs_unicode.h -@@ -0,0 +1,353 @@ -+/* -+ * 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 <asm/byteorder.h> -+#include <linux/types.h> -+#include <linux/nls.h> -+ -+#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 */ -+ -+#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 *); -+#endif -+ -+/* -+ * 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 occurrence 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 ---- /dev/null -+++ b/fs/cifs/cifs_uniupr.h -@@ -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, NULL} -+}; -+#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 ---- /dev/null -+++ b/fs/cifs/connect.c -@@ -0,0 +1,2924 @@ -+/* -+ * fs/cifs/connect.c -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2004 -+ * 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 -+ */ -+#include <linux/fs.h> -+#include <linux/net.h> -+#include <linux/string.h> -+#include <linux/list.h> -+#include <linux/wait.h> -+#include <linux/version.h> -+#include <linux/ipv6.h> -+#include <linux/pagemap.h> -+#include <linux/ctype.h> -+#include <linux/utsname.h> -+#include <asm/uaccess.h> -+#include <asm/processor.h> -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_unicode.h" -+#include "cifs_debug.h" -+#include "cifs_fs_sb.h" -+#include "ntlmssp.h" -+#include "nterr.h" -+#include "rfc1002pdu.h" -+ -+#define CIFS_PORT 445 -+#define RFC1001_PORT 139 -+ -+extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, -+ unsigned char *p24); -+extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, -+ unsigned char *p24); -+extern int cifs_inet_pton(int, const char *, void *dst); -+ -+struct smb_vol { -+ char *username; -+ char *password; -+ char *domainname; -+ char *UNC; -+ char *UNCip; -+ char *iocharset; /* local code page for mapping to and from Unicode */ -+ char source_rfc1001_name[16]; /* netbios name of client */ -+ uid_t linux_uid; -+ gid_t linux_gid; -+ mode_t file_mode; -+ mode_t dir_mode; -+ int rw:1; -+ int retry:1; -+ int intr:1; -+ unsigned int rsize; -+ unsigned int wsize; -+ unsigned int sockopt; -+ unsigned short int port; -+}; -+ -+static int ipv4_connect(struct sockaddr_in *psin_server, -+ struct socket **csocket, -+ char * netb_name); -+static int ipv6_connect(struct sockaddr_in6 *psin_server, -+ struct socket **csocket); -+ -+ -+ /* -+ * cifs tcp session reconnection -+ * -+ * mark tcp session as reconnecting so temporarily locked -+ * mark all smb sessions as reconnecting for tcp session -+ * reconnect tcp session -+ * wake up waiters on reconnection? - (not needed currently) -+ */ -+ -+int -+cifs_reconnect(struct TCP_Server_Info *server) -+{ -+ int rc = 0; -+ struct list_head *tmp; -+ struct cifsSesInfo *ses; -+ struct cifsTconInfo *tcon; -+ struct mid_q_entry * mid_entry; -+ -+ spin_lock(&GlobalMid_Lock); -+ if(server->tcpStatus == CifsExiting) { -+ /* the demux thread will exit normally -+ next time through the loop */ -+ spin_unlock(&GlobalMid_Lock); -+ return rc; -+ } else -+ server->tcpStatus = CifsNeedReconnect; -+ spin_unlock(&GlobalMid_Lock); -+ server->maxBuf = 0; -+ -+ cFYI(1, ("Reconnecting tcp session ")); -+ -+ /* before reconnecting the tcp session, mark the smb session (uid) -+ and the tid bad so they are not used until reconnected */ -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(tmp, &GlobalSMBSessionList) { -+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); -+ if (ses->server) { -+ if (ses->server == server) { -+ ses->status = CifsNeedReconnect; -+ ses->ipc_tid = 0; -+ } -+ } -+ /* else tcp and smb sessions need reconnection */ -+ } -+ list_for_each(tmp, &GlobalTreeConnectionList) { -+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); -+ if((tcon) && (tcon->ses) && (tcon->ses->server == server)) { -+ tcon->tidStatus = CifsNeedReconnect; -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ /* do not want to be sending data on a socket we are freeing */ -+ down(&server->tcpSem); -+ if(server->ssocket) { -+ cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state, -+ server->ssocket->flags)); -+ server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN); -+ cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state, -+ server->ssocket->flags)); -+ sock_release(server->ssocket); -+ server->ssocket = NULL; -+ } -+ -+ spin_lock(&GlobalMid_Lock); -+ list_for_each(tmp, &server->pending_mid_q) { -+ mid_entry = list_entry(tmp, struct -+ mid_q_entry, -+ qhead); -+ if(mid_entry) { -+ if(mid_entry->midState == MID_REQUEST_SUBMITTED) { -+ /* Mark other intransit requests as needing retry so -+ we do not immediately mark the session bad again -+ (ie after we reconnect below) as they timeout too */ -+ mid_entry->midState = MID_RETRY_NEEDED; -+ } -+ } -+ } -+ spin_unlock(&GlobalMid_Lock); -+ up(&server->tcpSem); -+ -+ while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood)) -+ { -+ if(server->protocolType == IPV6) { -+ rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket); -+ } else { -+ rc = ipv4_connect(&server->addr.sockAddr, -+ &server->ssocket, -+ server->workstation_RFC1001_name); -+ } -+ if(rc) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(3 * HZ); -+ } else { -+ atomic_inc(&tcpSesReconnectCount); -+ spin_lock(&GlobalMid_Lock); -+ if(server->tcpStatus != CifsExiting) -+ server->tcpStatus = CifsGood; -+ spin_unlock(&GlobalMid_Lock); -+ /* atomic_set(&server->inFlight,0);*/ -+ wake_up(&server->response_q); -+ } -+ } -+ return rc; -+} -+ -+static int -+cifs_demultiplex_thread(struct TCP_Server_Info *server) -+{ -+ int length; -+ unsigned int pdu_length, total_read; -+ struct smb_hdr *smb_buffer = NULL; -+ struct msghdr smb_msg; -+ mm_segment_t temp_fs; -+ struct iovec iov; -+ struct socket *csocket = server->ssocket; -+ struct list_head *tmp; -+ struct cifsSesInfo *ses; -+ struct task_struct *task_to_wake = NULL; -+ struct mid_q_entry *mid_entry; -+ char *temp; -+ -+ daemonize(); -+ sprintf(current->comm,"cifsd"); -+ /* allow_signal(SIGKILL);*/ -+ current->flags |= PF_MEMALLOC; -+ server->tsk = current; /* save process info to wake at shutdown */ -+ cFYI(1, ("Demultiplex PID: %d", current->pid)); -+ -+ temp_fs = get_fs(); /* we must turn off socket api parm checking */ -+ set_fs(get_ds()); -+ -+ while (server->tcpStatus != CifsExiting) { -+ if (smb_buffer == NULL) -+ smb_buffer = cifs_buf_get(); -+ else -+ memset(smb_buffer, 0, sizeof (struct smb_hdr)); -+ -+ if (smb_buffer == NULL) { -+ cERROR(1,("Can not get memory for SMB response")); -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ * 3); /* give system time to free memory */ -+ continue; -+ } -+ iov.iov_base = smb_buffer; -+ iov.iov_len = sizeof (struct smb_hdr) - 1; -+ /* 1 byte less above since wct is not always returned in error cases */ -+ smb_msg.msg_iov = &iov; -+ smb_msg.msg_iovlen = 1; -+ smb_msg.msg_control = NULL; -+ smb_msg.msg_controllen = 0; -+ -+ length = -+ sock_recvmsg(csocket, &smb_msg, -+ sizeof (struct smb_hdr) - -+ 1 /* RFC1001 header and SMB header */ , -+ MSG_PEEK /* flags see socket.h */ ); -+ -+ if(server->tcpStatus == CifsExiting) { -+ break; -+ } else if (server->tcpStatus == CifsNeedReconnect) { -+ cFYI(1,("Reconnecting after server stopped responding")); -+ cifs_reconnect(server); -+ cFYI(1,("call to reconnect done")); -+ csocket = server->ssocket; -+ continue; -+ } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); /* minimum sleep to prevent looping -+ allowing socket to clear and app threads to set -+ tcpStatus CifsNeedReconnect if server hung */ -+ continue; -+ } else if (length <= 0) { -+ if(server->tcpStatus == CifsNew) { -+ cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); -+ /* some servers kill tcp session rather than returning -+ smb negprot error in which case reconnecting here is -+ not going to help - return error to mount */ -+ break; -+ } -+ if(length == -EINTR) { -+ cFYI(1,("cifsd thread killed")); -+ break; -+ } -+ cFYI(1,("Reconnecting after unexpected peek error %d",length)); -+ cifs_reconnect(server); -+ csocket = server->ssocket; -+ wake_up(&server->response_q); -+ continue; -+ } -+ -+ pdu_length = 4 + ntohl(smb_buffer->smb_buf_length); -+ /* Ony read pdu_length after below checks for too short (due -+ to e.g. int overflow) and too long ie beyond end of buf */ -+ cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length)); -+ -+ temp = (char *) smb_buffer; -+ if (length > 3) { -+ if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { -+ iov.iov_base = smb_buffer; -+ iov.iov_len = 4; -+ length = sock_recvmsg(csocket, &smb_msg, 4, 0); -+ cFYI(0,("Received 4 byte keep alive packet")); -+ } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) { -+ iov.iov_base = smb_buffer; -+ iov.iov_len = 4; -+ length = sock_recvmsg(csocket, &smb_msg, 4, 0); -+ cFYI(1,("Good RFC 1002 session rsp")); -+ } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) -+ && (length == 5)) { -+ /* we get this from Windows 98 instead of error on SMB negprot response */ -+ cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); -+ if(server->tcpStatus == CifsNew) { -+ /* if nack on negprot (rather than -+ ret of smb negprot error) reconnecting -+ not going to help, ret error to mount */ -+ break; -+ } else { -+ /* give server a second to -+ clean up before reconnect attempt */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ); -+ /* always try 445 first on reconnect -+ since we get NACK on some if we ever -+ connected to port 139 (the NACK is -+ since we do not begin with RFC1001 -+ session initialize frame) */ -+ server->addr.sockAddr.sin_port = CIFS_PORT; -+ cifs_reconnect(server); -+ csocket = server->ssocket; -+ wake_up(&server->response_q); -+ continue; -+ } -+ } else if (temp[0] != (char) 0) { -+ cERROR(1,("Unknown RFC 1002 frame")); -+ cifs_dump_mem(" Received Data: ", temp, length); -+ cifs_reconnect(server); -+ csocket = server->ssocket; -+ continue; -+ } else { -+ if ((length != sizeof (struct smb_hdr) - 1) -+ || (pdu_length > -+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) -+ || (pdu_length < -+ sizeof (struct smb_hdr) - 1) -+ || -+ (checkSMBhdr -+ (smb_buffer, smb_buffer->Mid))) { -+ cERROR(1, -+ ("Invalid size or format for SMB found with length %d and pdu_lenght %d", -+ length, pdu_length)); -+ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); -+ /* could we fix this network corruption by finding next -+ smb header (instead of killing the session) and -+ restart reading from next valid SMB found? */ -+ cifs_reconnect(server); -+ csocket = server->ssocket; -+ continue; -+ } else { /* length ok */ -+ -+ length = 0; -+ iov.iov_base = smb_buffer; -+ iov.iov_len = pdu_length; -+ for (total_read = 0; -+ total_read < pdu_length; -+ total_read += length) { -+ length = sock_recvmsg(csocket, &smb_msg, -+ pdu_length - total_read, 0); -+ if (length == 0) { -+ cERROR(1, -+ ("Zero length receive when expecting %d ", -+ pdu_length - total_read)); -+ cifs_reconnect(server); -+ csocket = server->ssocket; -+ continue; -+ } -+ } -+ } -+ -+ dump_smb(smb_buffer, length); -+ if (checkSMB -+ (smb_buffer, smb_buffer->Mid, total_read)) { -+ cERROR(1, ("Bad SMB Received ")); -+ continue; -+ } -+ -+ task_to_wake = NULL; -+ spin_lock(&GlobalMid_Lock); -+ list_for_each(tmp, &server->pending_mid_q) { -+ mid_entry = list_entry(tmp, struct -+ mid_q_entry, -+ qhead); -+ -+ if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) { -+ cFYI(1, -+ (" Mid 0x%x matched - waking up ",mid_entry->mid)); -+ task_to_wake = mid_entry->tsk; -+ mid_entry->resp_buf = -+ smb_buffer; -+ mid_entry->midState = -+ MID_RESPONSE_RECEIVED; -+ } -+ } -+ spin_unlock(&GlobalMid_Lock); -+ if (task_to_wake) { -+ smb_buffer = NULL; /* will be freed by users thread after he is done */ -+ wake_up_process(task_to_wake); -+ } else if (is_valid_oplock_break(smb_buffer) == FALSE) { -+ cERROR(1, ("No task to wake, unknown frame rcvd!")); -+ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); -+ } -+ } -+ } else { -+ cFYI(0, -+ ("Frame less than four bytes received %d bytes long.", -+ length)); -+ if (length > 0) { -+ length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */ -+ cFYI(1, -+ (" with junk 0x%x in it ", -+ *(__u32 *) smb_buffer)); -+ } -+ } -+ } -+ spin_lock(&GlobalMid_Lock); -+ server->tcpStatus = CifsExiting; -+ server->tsk = NULL; -+ atomic_set(&server->inFlight, 0); -+ spin_unlock(&GlobalMid_Lock); -+ /* Although there should not be any requests blocked on -+ this queue it can not hurt to be paranoid and try to wake up requests -+ that may haven been blocked when more than 50 at time were on the wire -+ to the same server - they now will see the session is in exit state -+ and get out of SendReceive. */ -+ wake_up_all(&server->request_q); -+ /* give those requests time to exit */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ/8); -+ -+ if(server->ssocket) { -+ sock_release(csocket); -+ server->ssocket = NULL; -+ } -+ set_fs(temp_fs); -+ if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */ -+ cifs_buf_release(smb_buffer); -+ -+ read_lock(&GlobalSMBSeslock); -+ if (list_empty(&server->pending_mid_q)) { -+ /* loop through server session structures attached to this and mark them dead */ -+ list_for_each(tmp, &GlobalSMBSessionList) { -+ ses = -+ list_entry(tmp, struct cifsSesInfo, -+ cifsSessionList); -+ if (ses->server == server) { -+ ses->status = CifsExiting; -+ ses->server = NULL; -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ } else { -+ spin_lock(&GlobalMid_Lock); -+ list_for_each(tmp, &server->pending_mid_q) { -+ mid_entry = list_entry(tmp, struct mid_q_entry, qhead); -+ if (mid_entry->midState == MID_REQUEST_SUBMITTED) { -+ cFYI(1, -+ (" Clearing Mid 0x%x - waking up ",mid_entry->mid)); -+ task_to_wake = mid_entry->tsk; -+ if(task_to_wake) { -+ wake_up_process(task_to_wake); -+ } -+ } -+ } -+ spin_unlock(&GlobalMid_Lock); -+ read_unlock(&GlobalSMBSeslock); -+ set_current_state(TASK_INTERRUPTIBLE); -+ /* 1/8th of sec is more than enough time for them to exit */ -+ schedule_timeout(HZ/8); -+ } -+ -+ if (list_empty(&server->pending_mid_q)) { -+ /* mpx threads have not exited yet give them -+ at least the smb send timeout time for long ops */ -+ cFYI(1, ("Wait for exit from demultiplex thread")); -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(46 * HZ); -+ /* if threads still have not exited they are probably never -+ coming home not much else we can do but free the memory */ -+ } -+ kfree(server); -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ/4); -+ return 0; -+} -+ -+static void * -+cifs_kcalloc(size_t size, int type) -+{ -+ void *addr; -+ addr = kmalloc(size, type); -+ if (addr) -+ memset(addr, 0, size); -+ return addr; -+} -+ -+static int -+cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol) -+{ -+ char *value; -+ char *data; -+ unsigned int temp_len, i, j; -+ char separator[2]; -+ -+ separator[0] = ','; -+ separator[1] = 0; -+ -+ memset(vol->source_rfc1001_name,0x20,15); -+ for(i=0;i < strnlen(system_utsname.nodename,15);i++) { -+ /* does not have to be a perfect mapping since the field is -+ informational, only used for servers that do not support -+ port 445 and it can be overridden at mount time */ -+ vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); -+ } -+ vol->source_rfc1001_name[15] = 0; -+ -+ vol->linux_uid = current->uid; /* current->euid instead? */ -+ vol->linux_gid = current->gid; -+ vol->dir_mode = S_IRWXUGO; -+ /* 2767 perms indicate mandatory locking support */ -+ vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); -+ -+ /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ -+ vol->rw = TRUE; -+ -+ if (!options) -+ return 1; -+ -+ if(strncmp(options,"sep=",4) == 0) { -+ if(options[4] != 0) { -+ separator[0] = options[4]; -+ options += 5; -+ } else { -+ cFYI(1,("Null separator not allowed")); -+ } -+ } -+ -+ while ((data = strsep(&options, separator)) != NULL) { -+ if (!*data) -+ continue; -+ if ((value = strchr(data, '=')) != NULL) -+ *value++ = '\0'; -+ if (strnicmp(data, "user", 4) == 0) { -+ if (!value || !*value) { -+ printk(KERN_WARNING -+ "CIFS: invalid or missing username\n"); -+ return 1; /* needs_arg; */ -+ } -+ if (strnlen(value, 200) < 200) { -+ vol->username = value; -+ } else { -+ printk(KERN_WARNING "CIFS: username too long\n"); -+ return 1; -+ } -+ } else if (strnicmp(data, "pass", 4) == 0) { -+ if (!value || !*value) { -+ vol->password = NULL; -+ continue; -+ } -+ temp_len = strlen(value); -+ /* removed password length check, NTLM passwords -+ can be arbitrarily long */ -+ -+ /* if comma in password, the string will be -+ prematurely null terminated. Commas in password are -+ specified across the cifs mount interface by a double -+ comma ie ,, and a comma used as in other cases ie ',' -+ as a parameter delimiter/separator is single and due -+ to the strsep above is temporarily zeroed. */ -+ -+ /* NB: password legally can have multiple commas and -+ the only illegal character in a password is null */ -+ -+ if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { -+ /* reinsert comma */ -+ value[temp_len] = separator[0]; -+ temp_len+=2; /* move after the second comma */ -+ while(value[temp_len] != 0) { -+ if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) { -+ /* single comma indicating start of next parm */ -+ break; -+ } -+ temp_len++; -+ } -+ if(value[temp_len] == 0) { -+ options = NULL; -+ } else { -+ value[temp_len] = 0; -+ /* move options to point to start of next parm */ -+ options = value + temp_len + 1; -+ } -+ /* go from value to (value + temp_len) condensing double commas to singles */ -+ vol->password = cifs_kcalloc(temp_len, GFP_KERNEL); -+ for(i=0,j=0;i<temp_len;i++,j++) { -+ vol->password[j] = value[i]; -+ if(value[i] == separator[0] && value[i+1] == separator[0]) { -+ /* skip second comma */ -+ i++; -+ } -+ } -+ /* value[temp_len] is zeroed above so -+ vol->password[temp_len] guaranteed to be null */ -+ } else { -+ vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL); -+ strcpy(vol->password, value); -+ } -+ } else if (strnicmp(data, "ip", 2) == 0) { -+ if (!value || !*value) { -+ vol->UNCip = NULL; -+ } else if (strnlen(value, 35) < 35) { -+ vol->UNCip = value; -+ } else { -+ printk(KERN_WARNING "CIFS: ip address too long\n"); -+ return 1; -+ } -+ } else if ((strnicmp(data, "unc", 3) == 0) -+ || (strnicmp(data, "target", 6) == 0) -+ || (strnicmp(data, "path", 4) == 0)) { -+ if (!value || !*value) { -+ printk(KERN_WARNING -+ "CIFS: invalid path to network resource\n"); -+ return 1; /* needs_arg; */ -+ } -+ if ((temp_len = strnlen(value, 300)) < 300) { -+ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL); -+ if(vol->UNC == NULL) -+ return 1; -+ strcpy(vol->UNC,value); -+ if (strncmp(vol->UNC, "//", 2) == 0) { -+ vol->UNC[0] = '\\'; -+ vol->UNC[1] = '\\'; -+ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { -+ printk(KERN_WARNING -+ "CIFS: UNC Path does not begin with // or \\\\ \n"); -+ return 1; -+ } -+ } else { -+ printk(KERN_WARNING "CIFS: UNC name too long\n"); -+ return 1; -+ } -+ } else if ((strnicmp(data, "domain", 3) == 0) -+ || (strnicmp(data, "workgroup", 5) == 0)) { -+ if (!value || !*value) { -+ printk(KERN_WARNING "CIFS: invalid domain name\n"); -+ return 1; /* needs_arg; */ -+ } -+ /* BB are there cases in which a comma can be valid in -+ a domain name and need special handling? */ -+ if (strnlen(value, 65) < 65) { -+ vol->domainname = value; -+ cFYI(1, ("Domain name set")); -+ } else { -+ printk(KERN_WARNING "CIFS: domain name too long\n"); -+ return 1; -+ } -+ } else if (strnicmp(data, "iocharset", 9) == 0) { -+ if (!value || !*value) { -+ printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); -+ return 1; /* needs_arg; */ -+ } -+ if (strnlen(value, 65) < 65) { -+ if(strnicmp(value,"default",7)) -+ vol->iocharset = value; -+ /* if iocharset not set load_nls_default used by caller */ -+ cFYI(1, ("iocharset set to %s",value)); -+ } else { -+ printk(KERN_WARNING "CIFS: iocharset name too long.\n"); -+ return 1; -+ } -+ } else if (strnicmp(data, "uid", 3) == 0) { -+ if (value && *value) { -+ vol->linux_uid = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "gid", 3) == 0) { -+ if (value && *value) { -+ vol->linux_gid = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "file_mode", 4) == 0) { -+ if (value && *value) { -+ vol->file_mode = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "dir_mode", 3) == 0) { -+ if (value && *value) { -+ vol->dir_mode = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "port", 4) == 0) { -+ if (value && *value) { -+ vol->port = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "rsize", 5) == 0) { -+ if (value && *value) { -+ vol->rsize = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "wsize", 5) == 0) { -+ if (value && *value) { -+ vol->wsize = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "sockopt", 5) == 0) { -+ if (value && *value) { -+ vol->sockopt = -+ simple_strtoul(value, &value, 0); -+ } -+ } else if (strnicmp(data, "netbiosname", 4) == 0) { -+ if (!value || !*value || (*value == ' ')) { -+ cFYI(1,("invalid (empty) netbiosname specified")); -+ } else { -+ memset(vol->source_rfc1001_name,0x20,15); -+ for(i=0;i<15;i++) { -+ /* BB are there cases in which a comma can be -+ valid in this workstation netbios name (and need -+ special handling)? */ -+ -+ /* We do not uppercase netbiosname for user */ -+ if (value[i]==0) -+ break; -+ else -+ vol->source_rfc1001_name[i] = value[i]; -+ } -+ /* The string has 16th byte zero still from -+ set at top of the function */ -+ if((i==15) && (value[i] != 0)) -+ printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); -+ } -+ } else if (strnicmp(data, "credentials", 4) == 0) { -+ /* ignore */ -+ } else if (strnicmp(data, "version", 3) == 0) { -+ /* ignore */ -+ } else if (strnicmp(data, "rw", 2) == 0) { -+ vol->rw = TRUE; -+ } else if ((strnicmp(data, "suid", 4) == 0) || -+ (strnicmp(data, "nosuid", 6) == 0) || -+ (strnicmp(data, "exec", 4) == 0) || -+ (strnicmp(data, "noexec", 6) == 0) || -+ (strnicmp(data, "nodev", 5) == 0) || -+ (strnicmp(data, "noauto", 6) == 0) || -+ (strnicmp(data, "dev", 3) == 0)) { -+ /* The mount tool or mount.cifs helper (if present) -+ uses these opts to set flags, and the flags are read -+ by the kernel vfs layer before we get here (ie -+ before read super) so there is no point trying to -+ parse these options again and set anything and it -+ is ok to just ignore them */ -+ continue; -+ } else if (strnicmp(data, "ro", 2) == 0) { -+ vol->rw = FALSE; -+ } else if (strnicmp(data, "hard", 4) == 0) { -+ vol->retry = 1; -+ } else if (strnicmp(data, "soft", 4) == 0) { -+ vol->retry = 0; -+ } else if (strnicmp(data, "nohard", 6) == 0) { -+ vol->retry = 0; -+ } else if (strnicmp(data, "nosoft", 6) == 0) { -+ vol->retry = 1; -+ } else if (strnicmp(data, "nointr", 6) == 0) { -+ vol->intr = 0; -+ } else if (strnicmp(data, "intr", 4) == 0) { -+ vol->intr = 1; -+ } else if (strnicmp(data, "noac", 4) == 0) { -+ printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); -+ } else -+ printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data); -+ } -+ if (vol->UNC == NULL) { -+ if(devname == NULL) { -+ printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n"); -+ return 1; -+ } -+ if ((temp_len = strnlen(devname, 300)) < 300) { -+ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL); -+ if(vol->UNC == NULL) -+ return 1; -+ strcpy(vol->UNC,devname); -+ if (strncmp(vol->UNC, "//", 2) == 0) { -+ vol->UNC[0] = '\\'; -+ vol->UNC[1] = '\\'; -+ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { -+ printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n"); -+ return 1; -+ } -+ } else { -+ printk(KERN_WARNING "CIFS: UNC name too long\n"); -+ return 1; -+ } -+ } -+ if(vol->UNCip == 0) -+ vol->UNCip = &vol->UNC[2]; -+ -+ return 0; -+} -+ -+static struct cifsSesInfo * -+cifs_find_tcp_session(__u32 new_target_ip_addr, -+ char *userName, struct TCP_Server_Info **psrvTcp) -+{ -+ struct list_head *tmp; -+ struct cifsSesInfo *ses; -+ -+ *psrvTcp = NULL; -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(tmp, &GlobalSMBSessionList) { -+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); -+ if (ses->server) { -+ if (ses->server->addr.sockAddr.sin_addr.s_addr == -+ new_target_ip_addr) { -+ /* BB lock server and tcp session and increment use count here?? */ -+ *psrvTcp = ses->server; /* found a match on the TCP session */ -+ /* BB check if reconnection needed */ -+ if (strncmp -+ (ses->userName, userName, -+ MAX_USERNAME_SIZE) == 0){ -+ read_unlock(&GlobalSMBSeslock); -+ return ses; /* found exact match on both tcp and SMB sessions */ -+ } -+ } -+ } -+ /* else tcp and smb sessions need reconnection */ -+ } -+ read_unlock(&GlobalSMBSeslock); -+ return NULL; -+} -+ -+static struct cifsTconInfo * -+find_unc(__u32 new_target_ip_addr, char *uncName, char *userName) -+{ -+ struct list_head *tmp; -+ struct cifsTconInfo *tcon; -+ -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(tmp, &GlobalTreeConnectionList) { -+ cFYI(1, ("Next tcon - ")); -+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); -+ if (tcon->ses) { -+ if (tcon->ses->server) { -+ cFYI(1, -+ (" old ip addr: %x == new ip %x ?", -+ tcon->ses->server->addr.sockAddr.sin_addr. -+ s_addr, new_target_ip_addr)); -+ if (tcon->ses->server->addr.sockAddr.sin_addr. -+ s_addr == new_target_ip_addr) { -+ /* BB lock tcon and server and tcp session and increment use count here? */ -+ /* found a match on the TCP session */ -+ /* BB check if reconnection needed */ -+ cFYI(1,("Matched ip, old UNC: %s == new: %s ?", -+ tcon->treeName, uncName)); -+ if (strncmp -+ (tcon->treeName, uncName, -+ MAX_TREE_SIZE) == 0) { -+ cFYI(1, -+ ("Matched UNC, old user: %s == new: %s ?", -+ tcon->treeName, uncName)); -+ if (strncmp -+ (tcon->ses->userName, -+ userName, -+ MAX_USERNAME_SIZE) == 0) { -+ read_unlock(&GlobalSMBSeslock); -+ return tcon;/* also matched user (smb session)*/ -+ } -+ } -+ } -+ } -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ return NULL; -+} -+ -+int -+connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, -+ const char *old_path, const struct nls_table *nls_codepage) -+{ -+ unsigned char *referrals = NULL; -+ unsigned int num_referrals; -+ int rc = 0; -+ -+ rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, -+ &num_referrals, &referrals); -+ -+ /* BB Add in code to: if valid refrl, if not ip address contact -+ the helper that resolves tcp names, mount to it, try to -+ tcon to it unmount it if fail */ -+ -+ if(referrals) -+ kfree(referrals); -+ -+ return rc; -+} -+ -+int -+get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, -+ const char *old_path, const struct nls_table *nls_codepage, -+ unsigned int *pnum_referrals, unsigned char ** preferrals) -+{ -+ char *temp_unc; -+ int rc = 0; -+ -+ *pnum_referrals = 0; -+ -+ if (pSesInfo->ipc_tid == 0) { -+ temp_unc = kmalloc(2 /* for slashes */ + -+ strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2) -+ + 1 + 4 /* slash IPC$ */ + 2, -+ GFP_KERNEL); -+ if (temp_unc == NULL) -+ return -ENOMEM; -+ temp_unc[0] = '\\'; -+ temp_unc[1] = '\\'; -+ strcpy(temp_unc + 2, pSesInfo->serverName); -+ strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$"); -+ rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage); -+ cFYI(1, -+ ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid)); -+ kfree(temp_unc); -+ } -+ if (rc == 0) -+ rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, -+ pnum_referrals, nls_codepage); -+ -+ return rc; -+} -+ -+/* See RFC1001 section 14 on representation of Netbios names */ -+static void rfc1002mangle(char * target,char * source, unsigned int length) -+{ -+ unsigned int i,j; -+ -+ for(i=0,j=0;i<(length);i++) { -+ /* mask a nibble at a time and encode */ -+ target[j] = 'A' + (0x0F & (source[i] >> 4)); -+ target[j+1] = 'A' + (0x0F & source[i]); -+ j+=2; -+ } -+ -+} -+ -+ -+static int -+ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, -+ char * netbios_name) -+{ -+ int rc = 0; -+ int connected = 0; -+ unsigned short int orig_port = 0; -+ -+ if(*csocket == NULL) { -+ rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket); -+ if (rc < 0) { -+ cERROR(1, ("Error %d creating socket",rc)); -+ *csocket = NULL; -+ return rc; -+ } else { -+ /* BB other socket options to set KEEPALIVE, NODELAY? */ -+ cFYI(1,("Socket created")); -+ (*csocket)->sk->allocation = GFP_NOFS; -+ } -+ } -+ -+ psin_server->sin_family = AF_INET; -+ if(psin_server->sin_port) { /* user overrode default port */ -+ rc = (*csocket)->ops->connect(*csocket, -+ (struct sockaddr *) psin_server, -+ sizeof (struct sockaddr_in),0); -+ if (rc >= 0) -+ connected = 1; -+ } -+ -+ if(!connected) { -+ /* save original port so we can retry user specified port -+ later if fall back ports fail this time */ -+ orig_port = psin_server->sin_port; -+ -+ /* do not retry on the same port we just failed on */ -+ if(psin_server->sin_port != htons(CIFS_PORT)) { -+ psin_server->sin_port = htons(CIFS_PORT); -+ -+ rc = (*csocket)->ops->connect(*csocket, -+ (struct sockaddr *) psin_server, -+ sizeof (struct sockaddr_in),0); -+ if (rc >= 0) -+ connected = 1; -+ } -+ } -+ if (!connected) { -+ psin_server->sin_port = htons(RFC1001_PORT); -+ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) -+ psin_server, sizeof (struct sockaddr_in),0); -+ if (rc >= 0) -+ connected = 1; -+ } -+ -+ /* give up here - unless we want to retry on different -+ protocol families some day */ -+ if (!connected) { -+ if(orig_port) -+ psin_server->sin_port = orig_port; -+ cFYI(1,("Error %d connecting to server via ipv4",rc)); -+ sock_release(*csocket); -+ *csocket = NULL; -+ return rc; -+ } -+ /* Eventually check for other socket options to change from -+ the default. sock_setsockopt not used because it expects -+ user space buffer */ -+ (*csocket)->sk->rcvtimeo = 7 * HZ; -+ -+ /* send RFC1001 sessinit */ -+ -+ if(psin_server->sin_port == htons(139)) { -+ /* some servers require RFC1001 sessinit before sending -+ negprot - BB check reconnection in case where second -+ sessinit is sent but no second negprot */ -+ struct rfc1002_session_packet * ses_init_buf; -+ struct smb_hdr * smb_buf; -+ ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); -+ if(ses_init_buf) { -+ ses_init_buf->trailer.session_req.called_len = 32; -+ rfc1002mangle(ses_init_buf->trailer.session_req.called_name, -+ DEFAULT_CIFS_CALLED_NAME,16); -+ ses_init_buf->trailer.session_req.calling_len = 32; -+ /* calling name ends in null (byte 16) from old smb -+ convention. */ -+ if(netbios_name && (netbios_name[0] !=0)) { -+ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name, -+ netbios_name,16); -+ } else { -+ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name, -+ "LINUX_CIFS_CLNT",16); -+ } -+ ses_init_buf->trailer.session_req.scope1 = 0; -+ ses_init_buf->trailer.session_req.scope2 = 0; -+ smb_buf = (struct smb_hdr *)ses_init_buf; -+ /* sizeof RFC1002_SESSION_REQUEST with no scope */ -+ smb_buf->smb_buf_length = 0x81000044; -+ rc = smb_send(*csocket, smb_buf, 0x44, -+ (struct sockaddr *)psin_server); -+ kfree(ses_init_buf); -+ } -+ /* else the negprot may still work without this -+ even though malloc failed */ -+ -+ } -+ -+ return rc; -+} -+ -+static int -+ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) -+{ -+ int rc = 0; -+ int connected = 0; -+ -+ if(*csocket == NULL) { -+ rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket); -+ if (rc < 0) { -+ cERROR(1, ("Error %d creating ipv6 socket",rc)); -+ *csocket = NULL; -+ return rc; -+ } else { -+ /* BB other socket options to set KEEPALIVE, NODELAY? */ -+ cFYI(1,("ipv6 Socket created")); -+ (*csocket)->sk->allocation = GFP_NOFS; -+ } -+ } -+ -+ psin_server->sin6_family = AF_INET6; -+ -+ if(psin_server->sin6_port) { /* user overrode default port */ -+ rc = (*csocket)->ops->connect(*csocket, -+ (struct sockaddr *) psin_server, -+ sizeof (struct sockaddr_in6),0); -+ if (rc >= 0) -+ connected = 1; -+ } -+ -+ if(!connected) { -+ /* do not retry on the same port we just failed on */ -+ if(psin_server->sin6_port != htons(CIFS_PORT)) { -+ psin_server->sin6_port = htons(CIFS_PORT); -+ -+ rc = (*csocket)->ops->connect(*csocket, -+ (struct sockaddr *) psin_server, -+ sizeof (struct sockaddr_in6),0); -+ if (rc >= 0) -+ connected = 1; -+ } -+ } -+ if (!connected) { -+ psin_server->sin6_port = htons(RFC1001_PORT); -+ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) -+ psin_server, sizeof (struct sockaddr_in6),0); -+ if (rc >= 0) -+ connected = 1; -+ } -+ -+ /* give up here - unless we want to retry on different -+ protocol families some day */ -+ if (!connected) { -+ cFYI(1,("Error %d connecting to server via ipv6",rc)); -+ sock_release(*csocket); -+ *csocket = NULL; -+ return rc; -+ } -+ /* Eventually check for other socket options to change from -+ the default. sock_setsockopt not used because it expects -+ user space buffer */ -+ (*csocket)->sk->rcvtimeo = 7 * HZ; -+ -+ return rc; -+} -+ -+int -+cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, -+ char *mount_data, const char *devname) -+{ -+ int rc = 0; -+ int xid; -+ struct socket *csocket = NULL; -+ struct sockaddr_in sin_server; -+ struct sockaddr_in6 sin_server6; -+ struct smb_vol volume_info; -+ struct cifsSesInfo *pSesInfo = NULL; -+ struct cifsSesInfo *existingCifsSes = NULL; -+ struct cifsTconInfo *tcon = NULL; -+ struct TCP_Server_Info *srvTcp = NULL; -+ -+ xid = GetXid(); -+ -+ cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); /* BB removeme BB fixme */ -+ -+ memset(&volume_info,0,sizeof(struct smb_vol)); -+ if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return -EINVAL; -+ } -+ -+ if (volume_info.username) { -+ cFYI(1, ("Username: %s ", volume_info.username)); -+ -+ } else { -+ cifserror("No username specified "); -+ /* In userspace mount helper we can get user name from alternate -+ locations such as env variables and files on disk */ -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return -EINVAL; -+ } -+ -+ if (volume_info.UNCip && volume_info.UNC) { -+ rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr); -+ -+ if(rc == 0) { -+ /* not ipv4 address, try ipv6 */ -+ rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u); -+ } -+ -+ if(rc != 1) { -+ /* we failed translating address */ -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return -EINVAL; -+ } -+ -+ cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); -+ /* success */ -+ rc = 0; -+ } else if (volume_info.UNCip){ -+ /* BB using ip addr as server name connect to the DFS root below */ -+ cERROR(1,("Connecting to DFS root not implemented yet")); -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return -EINVAL; -+ } else /* which servers DFS root would we conect to */ { -+ cERROR(1, -+ ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return -EINVAL; -+ } -+ -+ /* this is needed for ASCII cp to Unicode converts */ -+ if(volume_info.iocharset == NULL) { -+ cifs_sb->local_nls = load_nls_default(); -+ /* load_nls_default can not return null */ -+ } else { -+ cifs_sb->local_nls = load_nls(volume_info.iocharset); -+ if(cifs_sb->local_nls == NULL) { -+ cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return -ELIBACC; -+ } -+ } -+ -+ existingCifsSes = -+ cifs_find_tcp_session(sin_server.sin_addr.s_addr, -+ volume_info.username, &srvTcp); -+ if (srvTcp) { -+ cFYI(1, ("Existing tcp session with server found ")); -+ } else { /* create socket */ -+ if(volume_info.port) -+ sin_server.sin_port = htons(volume_info.port); -+ else -+ sin_server.sin_port = 0; -+ rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); -+ if (rc < 0) { -+ cERROR(1, -+ ("Error connecting to IPv4 socket. Aborting operation")); -+ if(csocket != NULL) -+ sock_release(csocket); -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return rc; -+ } -+ -+ srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL); -+ if (srvTcp == NULL) { -+ rc = -ENOMEM; -+ sock_release(csocket); -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ FreeXid(xid); -+ return rc; -+ } else { -+ memset(srvTcp, 0, sizeof (struct TCP_Server_Info)); -+ memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in)); -+ atomic_set(&srvTcp->inFlight,0); -+ /* BB Add code for ipv6 case too */ -+ srvTcp->ssocket = csocket; -+ srvTcp->protocolType = IPV4; -+ init_waitqueue_head(&srvTcp->response_q); -+ init_waitqueue_head(&srvTcp->request_q); -+ INIT_LIST_HEAD(&srvTcp->pending_mid_q); -+ /* at this point we are the only ones with the pointer -+ to the struct since the kernel thread not created yet -+ so no need to spinlock this init of tcpStatus */ -+ srvTcp->tcpStatus = CifsNew; -+ init_MUTEX(&srvTcp->tcpSem); -+ kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp, -+ CLONE_FS | CLONE_FILES | CLONE_VM); -+ memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); -+ } -+ } -+ -+ if (existingCifsSes) { -+ pSesInfo = existingCifsSes; -+ cFYI(1, ("Existing smb sess found ")); -+ if(volume_info.password) -+ kfree(volume_info.password); -+ /* volume_info.UNC freed at end of function */ -+ } else if (!rc) { -+ cFYI(1, ("Existing smb sess not found ")); -+ pSesInfo = sesInfoAlloc(); -+ if (pSesInfo == NULL) -+ rc = -ENOMEM; -+ else { -+ pSesInfo->server = srvTcp; -+ sprintf(pSesInfo->serverName, "%u.%u.%u.%u", -+ NIPQUAD(sin_server.sin_addr.s_addr)); -+ } -+ -+ if (!rc){ -+ /* volume_info.password freed at unmount */ -+ if (volume_info.password) -+ pSesInfo->password = volume_info.password; -+ if (volume_info.username) -+ strncpy(pSesInfo->userName, -+ volume_info.username,MAX_USERNAME_SIZE); -+ if (volume_info.domainname) -+ strncpy(pSesInfo->domainName, -+ volume_info.domainname,MAX_USERNAME_SIZE); -+ pSesInfo->linux_uid = volume_info.linux_uid; -+ down(&pSesInfo->sesSem); -+ rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); -+ up(&pSesInfo->sesSem); -+ if(!rc) -+ atomic_inc(&srvTcp->socketUseCount); -+ } else -+ if(volume_info.password) -+ kfree(volume_info.password); -+ } -+ -+ /* search for existing tcon to this server share */ -+ if (!rc) { -+ if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf)) -+ cifs_sb->rsize = volume_info.rsize; -+ else -+ cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ -+ if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf)) -+ cifs_sb->wsize = volume_info.wsize; -+ else -+ cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ -+ if(cifs_sb->rsize < PAGE_CACHE_SIZE) { -+ cifs_sb->rsize = PAGE_CACHE_SIZE; -+ cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); -+ } -+ cifs_sb->mnt_uid = volume_info.linux_uid; -+ cifs_sb->mnt_gid = volume_info.linux_gid; -+ cifs_sb->mnt_file_mode = volume_info.file_mode; -+ cifs_sb->mnt_dir_mode = volume_info.dir_mode; -+ cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); -+ tcon = -+ find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, -+ volume_info.username); -+ if (tcon) { -+ cFYI(1, ("Found match on UNC path ")); -+ /* we can have only one retry value for a connection -+ to a share so for resources mounted more than once -+ to the same server share the last value passed in -+ for the retry flag is used */ -+ tcon->retry = volume_info.retry; -+ } else { -+ tcon = tconInfoAlloc(); -+ if (tcon == NULL) -+ rc = -ENOMEM; -+ else { -+ /* check for null share name ie connect to dfs root */ -+ -+ /* BB check if this works for exactly length three strings */ -+ if ((strchr(volume_info.UNC + 3, '\\') == NULL) -+ && (strchr(volume_info.UNC + 3, '/') == -+ NULL)) { -+ rc = connect_to_dfs_path(xid, -+ pSesInfo, -+ "", -+ cifs_sb-> -+ local_nls); -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ FreeXid(xid); -+ return -ENODEV; -+ } else { -+ rc = CIFSTCon(xid, pSesInfo, -+ volume_info.UNC, -+ tcon, cifs_sb->local_nls); -+ cFYI(1, ("CIFS Tcon rc = %d", rc)); -+ } -+ if (!rc) { -+ atomic_inc(&pSesInfo->inUse); -+ tcon->retry = volume_info.retry; -+ } -+ } -+ } -+ } -+ if(pSesInfo) { -+ if (pSesInfo->capabilities & CAP_LARGE_FILES) { -+ sb->s_maxbytes = (u64) 1 << 63; -+ } else -+ sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ -+ } -+ -+/* on error free sesinfo and tcon struct if needed */ -+ if (rc) { -+ /* if session setup failed, use count is zero but -+ we still need to free cifsd thread */ -+ if(atomic_read(&srvTcp->socketUseCount) == 0) { -+ spin_lock(&GlobalMid_Lock); -+ srvTcp->tcpStatus = CifsExiting; -+ spin_unlock(&GlobalMid_Lock); -+ if(srvTcp->tsk) -+ send_sig(SIGKILL,srvTcp->tsk,1); -+ } -+ /* If find_unc succeeded then rc == 0 so we can not end */ -+ if (tcon) /* up accidently freeing someone elses tcon struct */ -+ tconInfoFree(tcon); -+ if (existingCifsSes == 0) { -+ if (pSesInfo) { -+ if ((pSesInfo->server) && -+ (pSesInfo->status == CifsGood)) { -+ int temp_rc; -+ temp_rc = CIFSSMBLogoff(xid, pSesInfo); -+ /* if the socketUseCount is now zero */ -+ if((temp_rc == -ESHUTDOWN) && -+ (pSesInfo->server->tsk)) -+ send_sig(SIGKILL,pSesInfo->server->tsk,1); -+ } else -+ cFYI(1, ("No session or bad tcon")); -+ sesInfoFree(pSesInfo); -+ /* pSesInfo = NULL; */ -+ } -+ } -+ } else { -+ atomic_inc(&tcon->useCount); -+ cifs_sb->tcon = tcon; -+ tcon->ses = pSesInfo; -+ -+ /* do not care if following two calls succeed - informational only */ -+ CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls); -+ CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls); -+ if (tcon->ses->capabilities & CAP_UNIX) -+ CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls); -+ } -+ -+ /* volume_info.password is freed above when existing session found -+ (in which case it is not needed anymore) but when new sesion is created -+ the password ptr is put in the new session structure (in which case the -+ password will be freed at unmount time) */ -+ if(volume_info.UNC) -+ kfree(volume_info.UNC); -+ FreeXid(xid); -+ return rc; -+} -+ -+static int -+CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, -+ char session_key[CIFS_SESSION_KEY_SIZE], -+ const struct nls_table *nls_codepage) -+{ -+ struct smb_hdr *smb_buffer; -+ struct smb_hdr *smb_buffer_response; -+ SESSION_SETUP_ANDX *pSMB; -+ SESSION_SETUP_ANDX *pSMBr; -+ char *bcc_ptr; -+ char *user = ses->userName; -+ char *domain = ses->domainName; -+ int rc = 0; -+ int remaining_words = 0; -+ int bytes_returned = 0; -+ int len; -+ -+ cFYI(1, ("In sesssetup ")); -+ -+ smb_buffer = cifs_buf_get(); -+ if (smb_buffer == 0) { -+ return -ENOMEM; -+ } -+ smb_buffer_response = smb_buffer; -+ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; -+ -+ /* send SMBsessionSetup here */ -+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, -+ NULL /* no tCon exists yet */ , 13 /* wct */ ); -+ -+ pSMB->req_no_secext.AndXCommand = 0xFF; -+ pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); -+ pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); -+ -+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) -+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; -+ -+ pSMB->req_no_secext.Capabilities = -+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS; -+ if (ses->capabilities & CAP_UNICODE) { -+ smb_buffer->Flags2 |= SMBFLG2_UNICODE; -+ pSMB->req_no_secext.Capabilities |= CAP_UNICODE; -+ } -+ if (ses->capabilities & CAP_STATUS32) { -+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; -+ pSMB->req_no_secext.Capabilities |= CAP_STATUS32; -+ } -+ if (ses->capabilities & CAP_DFS) { -+ smb_buffer->Flags2 |= SMBFLG2_DFS; -+ pSMB->req_no_secext.Capabilities |= CAP_DFS; -+ } -+ pSMB->req_no_secext.Capabilities = -+ cpu_to_le32(pSMB->req_no_secext.Capabilities); -+ /* pSMB->req_no_secext.CaseInsensitivePasswordLength = -+ CIFS_SESSION_KEY_SIZE; */ -+ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; -+ pSMB->req_no_secext.CaseSensitivePasswordLength = -+ cpu_to_le16(CIFS_SESSION_KEY_SIZE); -+ bcc_ptr = pByteArea(smb_buffer); -+ /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE); -+ bcc_ptr += CIFS_SESSION_KEY_SIZE; */ -+ memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); -+ bcc_ptr += CIFS_SESSION_KEY_SIZE; -+ -+ if (ses->capabilities & CAP_UNICODE) { -+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ } -+ if(user == NULL) -+ bytes_returned = 0; /* skill null user */ -+ else -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, -+ nls_codepage); -+ bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */ -+ bcc_ptr += 2; /* trailing null */ -+ if (domain == NULL) -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, -+ "CIFS_LINUX_DOM", 32, nls_codepage); -+ else -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, -+ nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", -+ 32, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32, -+ nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, -+ 64, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; -+ } else { -+ if(user != NULL) { -+ strncpy(bcc_ptr, user, 200); -+ bcc_ptr += strnlen(user, 200); -+ } -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ if (domain == NULL) { -+ strcpy(bcc_ptr, "CIFS_LINUX_DOM"); -+ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1; -+ } else { -+ strncpy(bcc_ptr, domain, 64); -+ bcc_ptr += strnlen(domain, 64); -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ } -+ strcpy(bcc_ptr, "Linux version "); -+ bcc_ptr += strlen("Linux version "); -+ strcpy(bcc_ptr, UTS_RELEASE); -+ bcc_ptr += strlen(UTS_RELEASE) + 1; -+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); -+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; -+ } -+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); -+ smb_buffer->smb_buf_length += BCC(smb_buffer); -+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); -+ -+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, -+ &bytes_returned, 1); -+ if (rc) { -+/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ -+ } else if ((smb_buffer_response->WordCount == 3) -+ || (smb_buffer_response->WordCount == 4)) { -+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); -+ if (pSMBr->resp.Action & GUEST_LOGIN) -+ cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */ -+ if (ses) { -+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */ -+ cFYI(1, ("UID = %d ", ses->Suid)); -+ /* response can have either 3 or 4 word count - Samba sends 3 */ -+ bcc_ptr = pByteArea(smb_buffer_response); -+ if ((pSMBr->resp.hdr.WordCount == 3) -+ || ((pSMBr->resp.hdr.WordCount == 4) -+ && (pSMBr->resp.SecurityBlobLength < -+ pSMBr->resp.ByteCount))) { -+ if (pSMBr->resp.hdr.WordCount == 4) -+ bcc_ptr += -+ pSMBr->resp.SecurityBlobLength; -+ -+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { -+ if ((long) (bcc_ptr) % 2) { -+ remaining_words = -+ (BCC(smb_buffer_response) -+ - 1) / 2; -+ bcc_ptr++; /* Unicode strings must be word aligned */ -+ } else { -+ remaining_words = -+ BCC -+ (smb_buffer_response) / 2; -+ } -+ len = -+ UniStrnlen((wchar_t *) bcc_ptr, -+ remaining_words - 1); -+/* We look for obvious messed up bcc or strings in response so we do not go off -+ the end since (at least) WIN2K and Windows XP have a major bug in not null -+ terminating last Unicode string in response */ -+ ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverOS, -+ (wchar_t *)bcc_ptr, len,nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ remaining_words -= len + 1; -+ ses->serverOS[2 * len] = 0; -+ ses->serverOS[1 + (2 * len)] = 0; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *)bcc_ptr, -+ remaining_words -+ - 1); -+ ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverNOS, -+ (wchar_t *)bcc_ptr,len,nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ ses->serverNOS[2 * len] = 0; -+ ses->serverNOS[1 + (2 * len)] = 0; -+ remaining_words -= len + 1; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); -+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ -+ ses->serverDomain = -+ cifs_kcalloc(2*(len+1),GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverDomain, -+ (wchar_t *)bcc_ptr,len,nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ ses->serverDomain[2*len] = 0; -+ ses->serverDomain[1+(2*len)] = 0; -+ } /* else no more room so create dummy domain string */ -+ else -+ ses->serverDomain = -+ cifs_kcalloc(2, -+ GFP_KERNEL); -+ } else { /* no room so create dummy domain and NOS string */ -+ ses->serverDomain = -+ cifs_kcalloc(2, GFP_KERNEL); -+ ses->serverNOS = -+ cifs_kcalloc(2, GFP_KERNEL); -+ } -+ } else { /* ASCII */ -+ len = strnlen(bcc_ptr, 1024); -+ if (((long) bcc_ptr + len) - (long) -+ pByteArea(smb_buffer_response) -+ <= BCC(smb_buffer_response)) { -+ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); -+ strncpy(ses->serverOS,bcc_ptr, len); -+ -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; /* null terminate the string */ -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); -+ strncpy(ses->serverNOS, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL); -+ strncpy(ses->serverDomain, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ } else -+ cFYI(1, -+ ("Variable field of length %d extends beyond end of smb ", -+ len)); -+ } -+ } else { -+ cERROR(1, -+ (" Security Blob Length extends beyond end of SMB")); -+ } -+ } else { -+ cERROR(1, ("No session structure passed in.")); -+ } -+ } else { -+ cERROR(1, -+ (" Invalid Word count %d: ", -+ smb_buffer_response->WordCount)); -+ rc = -EIO; -+ } -+ -+ if (smb_buffer) -+ cifs_buf_release(smb_buffer); -+ -+ return rc; -+} -+ -+static int -+CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, -+ char *SecurityBlob,int SecurityBlobLength, -+ const struct nls_table *nls_codepage) -+{ -+ struct smb_hdr *smb_buffer; -+ struct smb_hdr *smb_buffer_response; -+ SESSION_SETUP_ANDX *pSMB; -+ SESSION_SETUP_ANDX *pSMBr; -+ char *bcc_ptr; -+ char *user = ses->userName; -+ char *domain = ses->domainName; -+ int rc = 0; -+ int remaining_words = 0; -+ int bytes_returned = 0; -+ int len; -+ -+ cFYI(1, ("In spnego sesssetup ")); -+ -+ smb_buffer = cifs_buf_get(); -+ if (smb_buffer == 0) { -+ return -ENOMEM; -+ } -+ smb_buffer_response = smb_buffer; -+ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; -+ -+ /* send SMBsessionSetup here */ -+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, -+ NULL /* no tCon exists yet */ , 12 /* wct */ ); -+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; -+ pSMB->req.AndXCommand = 0xFF; -+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); -+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); -+ -+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) -+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; -+ -+ pSMB->req.Capabilities = -+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | -+ CAP_EXTENDED_SECURITY; -+ if (ses->capabilities & CAP_UNICODE) { -+ smb_buffer->Flags2 |= SMBFLG2_UNICODE; -+ pSMB->req.Capabilities |= CAP_UNICODE; -+ } -+ if (ses->capabilities & CAP_STATUS32) { -+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; -+ pSMB->req.Capabilities |= CAP_STATUS32; -+ } -+ if (ses->capabilities & CAP_DFS) { -+ smb_buffer->Flags2 |= SMBFLG2_DFS; -+ pSMB->req.Capabilities |= CAP_DFS; -+ } -+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities); -+ -+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); -+ bcc_ptr = pByteArea(smb_buffer); -+ memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength); -+ bcc_ptr += SecurityBlobLength; -+ -+ if (ses->capabilities & CAP_UNICODE) { -+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */ -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ } -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */ -+ bcc_ptr += 2; /* trailing null */ -+ if (domain == NULL) -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, -+ "CIFS_LINUX_DOM", 32, nls_codepage); -+ else -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, -+ nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", -+ 32, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32, -+ nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, -+ 64, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; -+ } else { -+ strncpy(bcc_ptr, user, 200); -+ bcc_ptr += strnlen(user, 200); -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ if (domain == NULL) { -+ strcpy(bcc_ptr, "CIFS_LINUX_DOM"); -+ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1; -+ } else { -+ strncpy(bcc_ptr, domain, 64); -+ bcc_ptr += strnlen(domain, 64); -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ } -+ strcpy(bcc_ptr, "Linux version "); -+ bcc_ptr += strlen("Linux version "); -+ strcpy(bcc_ptr, UTS_RELEASE); -+ bcc_ptr += strlen(UTS_RELEASE) + 1; -+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); -+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; -+ } -+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); -+ smb_buffer->smb_buf_length += BCC(smb_buffer); -+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); -+ -+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, -+ &bytes_returned, 1); -+ if (rc) { -+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ -+ } else if ((smb_buffer_response->WordCount == 3) -+ || (smb_buffer_response->WordCount == 4)) { -+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); -+ pSMBr->resp.SecurityBlobLength = -+ le16_to_cpu(pSMBr->resp.SecurityBlobLength); -+ if (pSMBr->resp.Action & GUEST_LOGIN) -+ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */ -+ if (ses) { -+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */ -+ cFYI(1, ("UID = %d ", ses->Suid)); -+ bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */ -+ -+ /* BB Fix below to make endian neutral !! */ -+ -+ if ((pSMBr->resp.hdr.WordCount == 3) -+ || ((pSMBr->resp.hdr.WordCount == 4) -+ && (pSMBr->resp.SecurityBlobLength < -+ pSMBr->resp.ByteCount))) { -+ if (pSMBr->resp.hdr.WordCount == 4) { -+ bcc_ptr += -+ pSMBr->resp.SecurityBlobLength; -+ cFYI(1, -+ ("Security Blob Length %d ", -+ pSMBr->resp.SecurityBlobLength)); -+ } -+ -+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { -+ if ((long) (bcc_ptr) % 2) { -+ remaining_words = -+ (BCC(smb_buffer_response) -+ - 1) / 2; -+ bcc_ptr++; /* Unicode strings must be word aligned */ -+ } else { -+ remaining_words = -+ BCC -+ (smb_buffer_response) / 2; -+ } -+ len = -+ UniStrnlen((wchar_t *) bcc_ptr, -+ remaining_words - 1); -+/* We look for obvious messed up bcc or strings in response so we do not go off -+ the end since (at least) WIN2K and Windows XP have a major bug in not null -+ terminating last Unicode string in response */ -+ ses->serverOS = -+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverOS, -+ (wchar_t *) -+ bcc_ptr, len, -+ nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ remaining_words -= len + 1; -+ ses->serverOS[2 * len] = 0; -+ ses->serverOS[1 + (2 * len)] = 0; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *)bcc_ptr, -+ remaining_words -+ - 1); -+ ses->serverNOS = -+ cifs_kcalloc(2 * (len + 1), -+ GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverNOS, -+ (wchar_t *)bcc_ptr, -+ len, -+ nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ ses->serverNOS[2 * len] = 0; -+ ses->serverNOS[1 + (2 * len)] = 0; -+ remaining_words -= len + 1; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); -+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ -+ ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverDomain, -+ (wchar_t *)bcc_ptr, -+ len, -+ nls_codepage); -+ bcc_ptr += 2*(len+1); -+ ses->serverDomain[2*len] = 0; -+ ses->serverDomain[1+(2*len)] = 0; -+ } /* else no more room so create dummy domain string */ -+ else -+ ses->serverDomain = -+ cifs_kcalloc(2,GFP_KERNEL); -+ } else { /* no room so create dummy domain and NOS string */ -+ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); -+ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); -+ } -+ } else { /* ASCII */ -+ -+ len = strnlen(bcc_ptr, 1024); -+ if (((long) bcc_ptr + len) - (long) -+ pByteArea(smb_buffer_response) -+ <= BCC(smb_buffer_response)) { -+ ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL); -+ strncpy(ses->serverOS, bcc_ptr, len); -+ -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; /* null terminate the string */ -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); -+ strncpy(ses->serverNOS, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL); -+ strncpy(ses->serverDomain, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ } else -+ cFYI(1, -+ ("Variable field of length %d extends beyond end of smb ", -+ len)); -+ } -+ } else { -+ cERROR(1, -+ (" Security Blob Length extends beyond end of SMB")); -+ } -+ } else { -+ cERROR(1, ("No session structure passed in.")); -+ } -+ } else { -+ cERROR(1, -+ (" Invalid Word count %d: ", -+ smb_buffer_response->WordCount)); -+ rc = -EIO; -+ } -+ -+ if (smb_buffer) -+ cifs_buf_release(smb_buffer); -+ -+ return rc; -+} -+ -+static int -+CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, -+ struct cifsSesInfo *ses, int * pNTLMv2_flag, -+ const struct nls_table *nls_codepage) -+{ -+ struct smb_hdr *smb_buffer; -+ struct smb_hdr *smb_buffer_response; -+ SESSION_SETUP_ANDX *pSMB; -+ SESSION_SETUP_ANDX *pSMBr; -+ char *bcc_ptr; -+ char *domain = ses->domainName; -+ int rc = 0; -+ int remaining_words = 0; -+ int bytes_returned = 0; -+ int len; -+ int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE); -+ PNEGOTIATE_MESSAGE SecurityBlob; -+ PCHALLENGE_MESSAGE SecurityBlob2; -+ -+ cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); -+ *pNTLMv2_flag = FALSE; -+ smb_buffer = cifs_buf_get(); -+ if (smb_buffer == 0) { -+ return -ENOMEM; -+ } -+ smb_buffer_response = smb_buffer; -+ pSMB = (SESSION_SETUP_ANDX *) smb_buffer; -+ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; -+ -+ /* send SMBsessionSetup here */ -+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, -+ NULL /* no tCon exists yet */ , 12 /* wct */ ); -+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; -+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); -+ -+ pSMB->req.AndXCommand = 0xFF; -+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); -+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); -+ -+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) -+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; -+ -+ pSMB->req.Capabilities = -+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | -+ CAP_EXTENDED_SECURITY; -+ if (ses->capabilities & CAP_UNICODE) { -+ smb_buffer->Flags2 |= SMBFLG2_UNICODE; -+ pSMB->req.Capabilities |= CAP_UNICODE; -+ } -+ if (ses->capabilities & CAP_STATUS32) { -+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; -+ pSMB->req.Capabilities |= CAP_STATUS32; -+ } -+ if (ses->capabilities & CAP_DFS) { -+ smb_buffer->Flags2 |= SMBFLG2_DFS; -+ pSMB->req.Capabilities |= CAP_DFS; -+ } -+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities); -+ -+ bcc_ptr = (char *) &pSMB->req.SecurityBlob; -+ SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr; -+ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); -+ SecurityBlob->MessageType = NtLmNegotiate; -+ SecurityBlob->NegotiateFlags = -+ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | -+ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | -+ /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; -+ if(sign_CIFS_PDUs) -+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; -+ if(ntlmv2_support) -+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2; -+ /* setup pointers to domain name and workstation name */ -+ bcc_ptr += SecurityBlobLength; -+ -+ SecurityBlob->WorkstationName.Buffer = 0; -+ SecurityBlob->WorkstationName.Length = 0; -+ SecurityBlob->WorkstationName.MaximumLength = 0; -+ -+ if (domain == NULL) { -+ SecurityBlob->DomainName.Buffer = 0; -+ SecurityBlob->DomainName.Length = 0; -+ SecurityBlob->DomainName.MaximumLength = 0; -+ } else { -+ SecurityBlob->NegotiateFlags |= -+ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; -+ strncpy(bcc_ptr, domain, 63); -+ SecurityBlob->DomainName.Length = strnlen(domain, 64); -+ SecurityBlob->DomainName.MaximumLength = -+ cpu_to_le16(SecurityBlob->DomainName.Length); -+ SecurityBlob->DomainName.Buffer = -+ cpu_to_le32((long) &SecurityBlob-> -+ DomainString - -+ (long) &SecurityBlob->Signature); -+ bcc_ptr += SecurityBlob->DomainName.Length; -+ SecurityBlobLength += SecurityBlob->DomainName.Length; -+ SecurityBlob->DomainName.Length = -+ cpu_to_le16(SecurityBlob->DomainName.Length); -+ } -+ if (ses->capabilities & CAP_UNICODE) { -+ if ((long) bcc_ptr % 2) { -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ } -+ -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", -+ 32, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32, -+ nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; /* null terminate Linux version */ -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, -+ 64, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ *(bcc_ptr + 1) = 0; -+ *(bcc_ptr + 2) = 0; -+ bcc_ptr += 2; /* null terminate network opsys string */ -+ *(bcc_ptr + 1) = 0; -+ *(bcc_ptr + 2) = 0; -+ bcc_ptr += 2; /* null domain */ -+ } else { /* ASCII */ -+ strcpy(bcc_ptr, "Linux version "); -+ bcc_ptr += strlen("Linux version "); -+ strcpy(bcc_ptr, UTS_RELEASE); -+ bcc_ptr += strlen(UTS_RELEASE) + 1; -+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); -+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; -+ bcc_ptr++; /* empty domain field */ -+ *bcc_ptr = 0; -+ } -+ SecurityBlob->NegotiateFlags = -+ cpu_to_le32(SecurityBlob->NegotiateFlags); -+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); -+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); -+ smb_buffer->smb_buf_length += BCC(smb_buffer); -+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); -+ -+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, -+ &bytes_returned, 1); -+ -+ if (smb_buffer_response->Status.CifsError == -+ (NT_STATUS_MORE_PROCESSING_REQUIRED)) -+ rc = 0; -+ -+ if (rc) { -+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ -+ } else if ((smb_buffer_response->WordCount == 3) -+ || (smb_buffer_response->WordCount == 4)) { -+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); -+ pSMBr->resp.SecurityBlobLength = -+ le16_to_cpu(pSMBr->resp.SecurityBlobLength); -+ if (pSMBr->resp.Action & GUEST_LOGIN) -+ cFYI(1, (" Guest login")); -+ /* Do we want to set anything in SesInfo struct when guest login? */ -+ -+ bcc_ptr = pByteArea(smb_buffer_response); -+ /* response can have either 3 or 4 word count - Samba sends 3 */ -+ -+ SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr; -+ if (SecurityBlob2->MessageType != NtLmChallenge) { -+ cFYI(1, -+ ("Unexpected NTLMSSP message type received %d", -+ SecurityBlob2->MessageType)); -+ } else if (ses) { -+ ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ -+ cFYI(1, ("UID = %d ", ses->Suid)); -+ if ((pSMBr->resp.hdr.WordCount == 3) -+ || ((pSMBr->resp.hdr.WordCount == 4) -+ && (pSMBr->resp.SecurityBlobLength < -+ pSMBr->resp.ByteCount))) { -+ if (pSMBr->resp.hdr.WordCount == 4) { -+ bcc_ptr += -+ pSMBr->resp.SecurityBlobLength; -+ cFYI(1, -+ ("Security Blob Length %d ", -+ pSMBr->resp.SecurityBlobLength)); -+ } -+ -+ cFYI(1, ("NTLMSSP Challenge rcvd ")); -+ -+ memcpy(ses->server->cryptKey, -+ SecurityBlob2->Challenge, -+ CIFS_CRYPTO_KEY_SIZE); -+ if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2) -+ *pNTLMv2_flag = TRUE; -+ -+ if((SecurityBlob2->NegotiateFlags & -+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN) -+ || (sign_CIFS_PDUs > 1)) -+ ses->server->secMode |= -+ SECMODE_SIGN_REQUIRED; -+ if ((SecurityBlob2->NegotiateFlags & -+ NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs)) -+ ses->server->secMode |= -+ SECMODE_SIGN_ENABLED; -+ -+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { -+ if ((long) (bcc_ptr) % 2) { -+ remaining_words = -+ (BCC(smb_buffer_response) -+ - 1) / 2; -+ bcc_ptr++; /* Unicode strings must be word aligned */ -+ } else { -+ remaining_words = -+ BCC -+ (smb_buffer_response) / 2; -+ } -+ len = -+ UniStrnlen((wchar_t *) bcc_ptr, -+ remaining_words - 1); -+/* We look for obvious messed up bcc or strings in response so we do not go off -+ the end since (at least) WIN2K and Windows XP have a major bug in not null -+ terminating last Unicode string in response */ -+ ses->serverOS = -+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverOS, -+ (wchar_t *) -+ bcc_ptr, len, -+ nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ remaining_words -= len + 1; -+ ses->serverOS[2 * len] = 0; -+ ses->serverOS[1 + (2 * len)] = 0; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *) -+ bcc_ptr, -+ remaining_words -+ - 1); -+ ses->serverNOS = -+ cifs_kcalloc(2 * (len + 1), -+ GFP_KERNEL); -+ cifs_strfromUCS_le(ses-> -+ serverNOS, -+ (wchar_t *) -+ bcc_ptr, -+ len, -+ nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ ses->serverNOS[2 * len] = 0; -+ ses->serverNOS[1 + -+ (2 * len)] = 0; -+ remaining_words -= len + 1; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); -+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ -+ ses->serverDomain = -+ cifs_kcalloc(2 * -+ (len + -+ 1), -+ GFP_KERNEL); -+ cifs_strfromUCS_le -+ (ses-> -+ serverDomain, -+ (wchar_t *) -+ bcc_ptr, len, -+ nls_codepage); -+ bcc_ptr += -+ 2 * (len + 1); -+ ses-> -+ serverDomain[2 -+ * len] -+ = 0; -+ ses-> -+ serverDomain[1 -+ + -+ (2 -+ * -+ len)] -+ = 0; -+ } /* else no more room so create dummy domain string */ -+ else -+ ses->serverDomain = -+ cifs_kcalloc(2, -+ GFP_KERNEL); -+ } else { /* no room so create dummy domain and NOS string */ -+ ses->serverDomain = -+ cifs_kcalloc(2, GFP_KERNEL); -+ ses->serverNOS = -+ cifs_kcalloc(2, GFP_KERNEL); -+ } -+ } else { /* ASCII */ -+ len = strnlen(bcc_ptr, 1024); -+ if (((long) bcc_ptr + len) - (long) -+ pByteArea(smb_buffer_response) -+ <= BCC(smb_buffer_response)) { -+ ses->serverOS = -+ cifs_kcalloc(len + 1, -+ GFP_KERNEL); -+ strncpy(ses->serverOS, -+ bcc_ptr, len); -+ -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; /* null terminate string */ -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverNOS = -+ cifs_kcalloc(len + 1, -+ GFP_KERNEL); -+ strncpy(ses->serverNOS, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverDomain = -+ cifs_kcalloc(len + 1, -+ GFP_KERNEL); -+ strncpy(ses->serverDomain, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ } else -+ cFYI(1, -+ ("Variable field of length %d extends beyond end of smb ", -+ len)); -+ } -+ } else { -+ cERROR(1, -+ (" Security Blob Length extends beyond end of SMB")); -+ } -+ } else { -+ cERROR(1, ("No session structure passed in.")); -+ } -+ } else { -+ cERROR(1, -+ (" Invalid Word count %d: ", -+ smb_buffer_response->WordCount)); -+ rc = -EIO; -+ } -+ -+ if (smb_buffer) -+ cifs_buf_release(smb_buffer); -+ -+ return rc; -+} -+ -+static int -+CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, -+ char *ntlm_session_key, int ntlmv2_flag, -+ const struct nls_table *nls_codepage) -+{ -+ struct smb_hdr *smb_buffer; -+ struct smb_hdr *smb_buffer_response; -+ SESSION_SETUP_ANDX *pSMB; -+ SESSION_SETUP_ANDX *pSMBr; -+ char *bcc_ptr; -+ char *user = ses->userName; -+ char *domain = ses->domainName; -+ int rc = 0; -+ int remaining_words = 0; -+ int bytes_returned = 0; -+ int len; -+ int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); -+ PAUTHENTICATE_MESSAGE SecurityBlob; -+ -+ cFYI(1, ("In NTLMSSPSessSetup (Authenticate)")); -+ -+ smb_buffer = cifs_buf_get(); -+ if (smb_buffer == 0) { -+ return -ENOMEM; -+ } -+ smb_buffer_response = smb_buffer; -+ pSMB = (SESSION_SETUP_ANDX *) smb_buffer; -+ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; -+ -+ /* send SMBsessionSetup here */ -+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, -+ NULL /* no tCon exists yet */ , 12 /* wct */ ); -+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); -+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; -+ pSMB->req.AndXCommand = 0xFF; -+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); -+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); -+ -+ pSMB->req.hdr.Uid = ses->Suid; -+ -+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) -+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; -+ -+ pSMB->req.Capabilities = -+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | -+ CAP_EXTENDED_SECURITY; -+ if (ses->capabilities & CAP_UNICODE) { -+ smb_buffer->Flags2 |= SMBFLG2_UNICODE; -+ pSMB->req.Capabilities |= CAP_UNICODE; -+ } -+ if (ses->capabilities & CAP_STATUS32) { -+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; -+ pSMB->req.Capabilities |= CAP_STATUS32; -+ } -+ if (ses->capabilities & CAP_DFS) { -+ smb_buffer->Flags2 |= SMBFLG2_DFS; -+ pSMB->req.Capabilities |= CAP_DFS; -+ } -+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities); -+ -+ bcc_ptr = (char *) &pSMB->req.SecurityBlob; -+ SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr; -+ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); -+ SecurityBlob->MessageType = NtLmAuthenticate; -+ bcc_ptr += SecurityBlobLength; -+ SecurityBlob->NegotiateFlags = -+ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | -+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | -+ 0x80000000 | NTLMSSP_NEGOTIATE_128; -+ if(sign_CIFS_PDUs) -+ SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; -+ if(ntlmv2_flag) -+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2; -+ -+/* setup pointers to domain name and workstation name */ -+ -+ SecurityBlob->WorkstationName.Buffer = 0; -+ SecurityBlob->WorkstationName.Length = 0; -+ SecurityBlob->WorkstationName.MaximumLength = 0; -+ SecurityBlob->SessionKey.Length = 0; -+ SecurityBlob->SessionKey.MaximumLength = 0; -+ SecurityBlob->SessionKey.Buffer = 0; -+ -+ SecurityBlob->LmChallengeResponse.Length = 0; -+ SecurityBlob->LmChallengeResponse.MaximumLength = 0; -+ SecurityBlob->LmChallengeResponse.Buffer = 0; -+ -+ SecurityBlob->NtChallengeResponse.Length = -+ cpu_to_le16(CIFS_SESSION_KEY_SIZE); -+ SecurityBlob->NtChallengeResponse.MaximumLength = -+ cpu_to_le16(CIFS_SESSION_KEY_SIZE); -+ memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); -+ SecurityBlob->NtChallengeResponse.Buffer = -+ cpu_to_le32(SecurityBlobLength); -+ SecurityBlobLength += CIFS_SESSION_KEY_SIZE; -+ bcc_ptr += CIFS_SESSION_KEY_SIZE; -+ -+ if (ses->capabilities & CAP_UNICODE) { -+ if (domain == NULL) { -+ SecurityBlob->DomainName.Buffer = 0; -+ SecurityBlob->DomainName.Length = 0; -+ SecurityBlob->DomainName.MaximumLength = 0; -+ } else { -+ SecurityBlob->DomainName.Length = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, -+ nls_codepage); -+ SecurityBlob->DomainName.Length *= 2; -+ SecurityBlob->DomainName.MaximumLength = -+ cpu_to_le16(SecurityBlob->DomainName.Length); -+ SecurityBlob->DomainName.Buffer = -+ cpu_to_le32(SecurityBlobLength); -+ bcc_ptr += SecurityBlob->DomainName.Length; -+ SecurityBlobLength += SecurityBlob->DomainName.Length; -+ SecurityBlob->DomainName.Length = -+ cpu_to_le16(SecurityBlob->DomainName.Length); -+ } -+ if (user == NULL) { -+ SecurityBlob->UserName.Buffer = 0; -+ SecurityBlob->UserName.Length = 0; -+ SecurityBlob->UserName.MaximumLength = 0; -+ } else { -+ SecurityBlob->UserName.Length = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64, -+ nls_codepage); -+ SecurityBlob->UserName.Length *= 2; -+ SecurityBlob->UserName.MaximumLength = -+ cpu_to_le16(SecurityBlob->UserName.Length); -+ SecurityBlob->UserName.Buffer = -+ cpu_to_le32(SecurityBlobLength); -+ bcc_ptr += SecurityBlob->UserName.Length; -+ SecurityBlobLength += SecurityBlob->UserName.Length; -+ SecurityBlob->UserName.Length = -+ cpu_to_le16(SecurityBlob->UserName.Length); -+ } -+ -+ /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage); -+ SecurityBlob->WorkstationName.Length *= 2; -+ SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length); -+ SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength); -+ bcc_ptr += SecurityBlob->WorkstationName.Length; -+ SecurityBlobLength += SecurityBlob->WorkstationName.Length; -+ SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */ -+ -+ if ((long) bcc_ptr % 2) { -+ *bcc_ptr = 0; -+ bcc_ptr++; -+ } -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", -+ 32, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32, -+ nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ bcc_ptr += 2; /* null term version string */ -+ bytes_returned = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, -+ 64, nls_codepage); -+ bcc_ptr += 2 * bytes_returned; -+ *(bcc_ptr + 1) = 0; -+ *(bcc_ptr + 2) = 0; -+ bcc_ptr += 2; /* null terminate network opsys string */ -+ *(bcc_ptr + 1) = 0; -+ *(bcc_ptr + 2) = 0; -+ bcc_ptr += 2; /* null domain */ -+ } else { /* ASCII */ -+ if (domain == NULL) { -+ SecurityBlob->DomainName.Buffer = 0; -+ SecurityBlob->DomainName.Length = 0; -+ SecurityBlob->DomainName.MaximumLength = 0; -+ } else { -+ SecurityBlob->NegotiateFlags |= -+ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; -+ strncpy(bcc_ptr, domain, 63); -+ SecurityBlob->DomainName.Length = strnlen(domain, 64); -+ SecurityBlob->DomainName.MaximumLength = -+ cpu_to_le16(SecurityBlob->DomainName.Length); -+ SecurityBlob->DomainName.Buffer = -+ cpu_to_le32(SecurityBlobLength); -+ bcc_ptr += SecurityBlob->DomainName.Length; -+ SecurityBlobLength += SecurityBlob->DomainName.Length; -+ SecurityBlob->DomainName.Length = -+ cpu_to_le16(SecurityBlob->DomainName.Length); -+ } -+ if (user == NULL) { -+ SecurityBlob->UserName.Buffer = 0; -+ SecurityBlob->UserName.Length = 0; -+ SecurityBlob->UserName.MaximumLength = 0; -+ } else { -+ strncpy(bcc_ptr, user, 63); -+ SecurityBlob->UserName.Length = strnlen(user, 64); -+ SecurityBlob->UserName.MaximumLength = -+ cpu_to_le16(SecurityBlob->UserName.Length); -+ SecurityBlob->UserName.Buffer = -+ cpu_to_le32(SecurityBlobLength); -+ bcc_ptr += SecurityBlob->UserName.Length; -+ SecurityBlobLength += SecurityBlob->UserName.Length; -+ SecurityBlob->UserName.Length = -+ cpu_to_le16(SecurityBlob->UserName.Length); -+ } -+ /* BB fill in our workstation name if known BB */ -+ -+ strcpy(bcc_ptr, "Linux version "); -+ bcc_ptr += strlen("Linux version "); -+ strcpy(bcc_ptr, UTS_RELEASE); -+ bcc_ptr += strlen(UTS_RELEASE) + 1; -+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); -+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; -+ bcc_ptr++; /* null domain */ -+ *bcc_ptr = 0; -+ } -+ SecurityBlob->NegotiateFlags = -+ cpu_to_le32(SecurityBlob->NegotiateFlags); -+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); -+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); -+ smb_buffer->smb_buf_length += BCC(smb_buffer); -+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); -+ -+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, -+ &bytes_returned, 1); -+ if (rc) { -+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ -+ } else if ((smb_buffer_response->WordCount == 3) -+ || (smb_buffer_response->WordCount == 4)) { -+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); -+ pSMBr->resp.SecurityBlobLength = -+ le16_to_cpu(pSMBr->resp.SecurityBlobLength); -+ if (pSMBr->resp.Action & GUEST_LOGIN) -+ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */ -+/* if(SecurityBlob2->MessageType != NtLm??){ -+ cFYI("Unexpected message type on auth response is %d ")); -+ } */ -+ if (ses) { -+ cFYI(1, -+ ("Does UID on challenge %d match auth response UID %d ", -+ ses->Suid, smb_buffer_response->Uid)); -+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */ -+ bcc_ptr = pByteArea(smb_buffer_response); -+ /* response can have either 3 or 4 word count - Samba sends 3 */ -+ if ((pSMBr->resp.hdr.WordCount == 3) -+ || ((pSMBr->resp.hdr.WordCount == 4) -+ && (pSMBr->resp.SecurityBlobLength < -+ pSMBr->resp.ByteCount))) { -+ if (pSMBr->resp.hdr.WordCount == 4) { -+ bcc_ptr += -+ pSMBr->resp.SecurityBlobLength; -+ cFYI(1, -+ ("Security Blob Length %d ", -+ pSMBr->resp.SecurityBlobLength)); -+ } -+ -+ cFYI(1, -+ ("NTLMSSP response to Authenticate ")); -+ -+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { -+ if ((long) (bcc_ptr) % 2) { -+ remaining_words = -+ (BCC(smb_buffer_response) -+ - 1) / 2; -+ bcc_ptr++; /* Unicode strings must be word aligned */ -+ } else { -+ remaining_words = BCC(smb_buffer_response) / 2; -+ } -+ len = -+ UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1); -+/* We look for obvious messed up bcc or strings in response so we do not go off -+ the end since (at least) WIN2K and Windows XP have a major bug in not null -+ terminating last Unicode string in response */ -+ ses->serverOS = -+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL); -+ cifs_strfromUCS_le(ses->serverOS, -+ (wchar_t *) -+ bcc_ptr, len, -+ nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ remaining_words -= len + 1; -+ ses->serverOS[2 * len] = 0; -+ ses->serverOS[1 + (2 * len)] = 0; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *) -+ bcc_ptr, -+ remaining_words -+ - 1); -+ ses->serverNOS = -+ cifs_kcalloc(2 * (len + 1), -+ GFP_KERNEL); -+ cifs_strfromUCS_le(ses-> -+ serverNOS, -+ (wchar_t *) -+ bcc_ptr, -+ len, -+ nls_codepage); -+ bcc_ptr += 2 * (len + 1); -+ ses->serverNOS[2 * len] = 0; -+ ses->serverNOS[1+(2*len)] = 0; -+ remaining_words -= len + 1; -+ if (remaining_words > 0) { -+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); -+ /* last string not always null terminated (e.g. for Windows XP & 2000) */ -+ ses->serverDomain = -+ cifs_kcalloc(2 * -+ (len + -+ 1), -+ GFP_KERNEL); -+ cifs_strfromUCS_le -+ (ses-> -+ serverDomain, -+ (wchar_t *) -+ bcc_ptr, len, -+ nls_codepage); -+ bcc_ptr += -+ 2 * (len + 1); -+ ses-> -+ serverDomain[2 -+ * len] -+ = 0; -+ ses-> -+ serverDomain[1 -+ + -+ (2 -+ * -+ len)] -+ = 0; -+ } /* else no more room so create dummy domain string */ -+ else -+ ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL); -+ } else { /* no room so create dummy domain and NOS string */ -+ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); -+ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); -+ } -+ } else { /* ASCII */ -+ len = strnlen(bcc_ptr, 1024); -+ if (((long) bcc_ptr + len) - -+ (long) pByteArea(smb_buffer_response) -+ <= BCC(smb_buffer_response)) { -+ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); -+ strncpy(ses->serverOS,bcc_ptr, len); -+ -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; /* null terminate the string */ -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL); -+ strncpy(ses->serverNOS, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ -+ len = strnlen(bcc_ptr, 1024); -+ ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL); -+ strncpy(ses->serverDomain, bcc_ptr, len); -+ bcc_ptr += len; -+ bcc_ptr[0] = 0; -+ bcc_ptr++; -+ } else -+ cFYI(1, -+ ("Variable field of length %d extends beyond end of smb ", -+ len)); -+ } -+ } else { -+ cERROR(1, -+ (" Security Blob Length extends beyond end of SMB")); -+ } -+ } else { -+ cERROR(1, ("No session structure passed in.")); -+ } -+ } else { -+ cERROR(1, -+ (" Invalid Word count %d: ", -+ smb_buffer_response->WordCount)); -+ rc = -EIO; -+ } -+ -+ if (smb_buffer) -+ cifs_buf_release(smb_buffer); -+ -+ return rc; -+} -+ -+int -+CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, -+ const char *tree, struct cifsTconInfo *tcon, -+ const struct nls_table *nls_codepage) -+{ -+ struct smb_hdr *smb_buffer; -+ struct smb_hdr *smb_buffer_response; -+ TCONX_REQ *pSMB; -+ TCONX_RSP *pSMBr; -+ char *bcc_ptr; -+ int rc = 0; -+ int length; -+ -+ if (ses == NULL) -+ return -EIO; -+ -+ smb_buffer = cifs_buf_get(); -+ if (smb_buffer == 0) { -+ return -ENOMEM; -+ } -+ smb_buffer_response = smb_buffer; -+ -+ header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, -+ NULL /*no tid */ , 4 /*wct */ ); -+ smb_buffer->Uid = ses->Suid; -+ pSMB = (TCONX_REQ *) smb_buffer; -+ pSMBr = (TCONX_RSP *) smb_buffer_response; -+ -+ pSMB->AndXCommand = 0xFF; -+ pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); -+ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ -+ bcc_ptr = &(pSMB->Password[0]); -+ bcc_ptr++; /* skip password */ -+ -+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) -+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; -+ -+ if (ses->capabilities & CAP_STATUS32) { -+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; -+ } -+ if (ses->capabilities & CAP_DFS) { -+ smb_buffer->Flags2 |= SMBFLG2_DFS; -+ } -+ if (ses->capabilities & CAP_UNICODE) { -+ smb_buffer->Flags2 |= SMBFLG2_UNICODE; -+ length = -+ cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage); -+ bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ -+ bcc_ptr += 2; /* skip trailing null */ -+ } else { /* ASCII */ -+ -+ strcpy(bcc_ptr, tree); -+ bcc_ptr += strlen(tree) + 1; -+ } -+ strcpy(bcc_ptr, "?????"); -+ bcc_ptr += strlen("?????"); -+ bcc_ptr += 1; -+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); -+ smb_buffer->smb_buf_length += BCC(smb_buffer); -+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); -+ -+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0); -+ -+ /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ -+ /* above now done in SendReceive */ -+ if ((rc == 0) && (tcon != NULL)) { -+ tcon->tidStatus = CifsGood; -+ tcon->tid = smb_buffer_response->Tid; -+ bcc_ptr = pByteArea(smb_buffer_response); -+ length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); -+ /* skip service field (NB: this field is always ASCII) */ -+ bcc_ptr += length + 1; -+ strncpy(tcon->treeName, tree, MAX_TREE_SIZE); -+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { -+ length = UniStrnlen((wchar_t *) bcc_ptr, 512); -+ if (((long) bcc_ptr + (2 * length)) - -+ (long) pByteArea(smb_buffer_response) <= -+ BCC(smb_buffer_response)) { -+ if(tcon->nativeFileSystem) -+ kfree(tcon->nativeFileSystem); -+ tcon->nativeFileSystem = -+ cifs_kcalloc(length + 2, GFP_KERNEL); -+ cifs_strfromUCS_le(tcon->nativeFileSystem, -+ (wchar_t *) bcc_ptr, -+ length, nls_codepage); -+ bcc_ptr += 2 * length; -+ bcc_ptr[0] = 0; /* null terminate the string */ -+ bcc_ptr[1] = 0; -+ bcc_ptr += 2; -+ } -+ /* else do not bother copying these informational fields */ -+ } else { -+ length = strnlen(bcc_ptr, 1024); -+ if (((long) bcc_ptr + length) - -+ (long) pByteArea(smb_buffer_response) <= -+ BCC(smb_buffer_response)) { -+ if(tcon->nativeFileSystem) -+ kfree(tcon->nativeFileSystem); -+ tcon->nativeFileSystem = -+ cifs_kcalloc(length + 1, GFP_KERNEL); -+ strncpy(tcon->nativeFileSystem, bcc_ptr, -+ length); -+ } -+ /* else do not bother copying these informational fields */ -+ } -+ tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); -+ cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); -+ } else if ((rc == 0) && tcon == NULL) { -+ /* all we need to save for IPC$ connection */ -+ ses->ipc_tid = smb_buffer_response->Tid; -+ } -+ -+ if (smb_buffer) -+ cifs_buf_release(smb_buffer); -+ return rc; -+} -+ -+int -+cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) -+{ -+ int rc = 0; -+ int xid; -+ struct cifsSesInfo *ses = NULL; -+ struct task_struct *cifsd_task; -+ -+ xid = GetXid(); -+ -+ if (cifs_sb->tcon) { -+ ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/ -+ rc = CIFSSMBTDis(xid, cifs_sb->tcon); -+ if (rc == -EBUSY) { -+ FreeXid(xid); -+ return 0; -+ } -+ tconInfoFree(cifs_sb->tcon); -+ if ((ses) && (ses->server)) { -+ /* save off task so we do not refer to ses later */ -+ cifsd_task = ses->server->tsk; -+ cFYI(1, ("About to do SMBLogoff ")); -+ rc = CIFSSMBLogoff(xid, ses); -+ if (rc == -EBUSY) { -+ FreeXid(xid); -+ return 0; -+ } else if (rc == -ESHUTDOWN) { -+ cFYI(1,("Waking up socket by sending it signal")); -+ send_sig(SIGKILL,cifsd_task,1); -+ rc = 0; -+ } /* else - we have an smb session -+ left on this socket do not kill cifsd */ -+ } else -+ cFYI(1, ("No session or bad tcon")); -+ } -+ -+ cifs_sb->tcon = NULL; -+ if (ses) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ / 2); -+ } -+ if (ses) -+ sesInfoFree(ses); -+ -+ FreeXid(xid); -+ return rc; /* BB check if we should always return zero here */ -+} -+ -+int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, -+ struct nls_table * nls_info) -+{ -+ int rc = 0; -+ char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; -+ int ntlmv2_flag = FALSE; -+ -+ /* what if server changes its buffer size after dropping the session? */ -+ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { -+ rc = CIFSSMBNegotiate(xid, pSesInfo); -+ if(rc == -EAGAIN) /* retry only once on 1st time connection */ { -+ rc = CIFSSMBNegotiate(xid, pSesInfo); -+ if(rc == -EAGAIN) -+ rc = -EHOSTDOWN; -+ } -+ if(rc == 0) { -+ spin_lock(&GlobalMid_Lock); -+ if(pSesInfo->server->tcpStatus != CifsExiting) -+ pSesInfo->server->tcpStatus = CifsGood; -+ else -+ rc = -EHOSTDOWN; -+ spin_unlock(&GlobalMid_Lock); -+ -+ } -+ } -+ if (!rc) { -+ pSesInfo->capabilities = pSesInfo->server->capabilities; -+ if(linuxExtEnabled == 0) -+ pSesInfo->capabilities &= (~CAP_UNIX); -+ pSesInfo->sequence_number = 0; -+ cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", -+ pSesInfo->server->secMode, -+ pSesInfo->server->capabilities, -+ pSesInfo->server->timeZone)); -+ if (extended_security -+ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) -+ && (pSesInfo->server->secType == NTLMSSP)) { -+ cFYI(1, ("New style sesssetup ")); -+ rc = CIFSSpnegoSessSetup(xid, pSesInfo, -+ NULL /* security blob */, -+ 0 /* blob length */, -+ nls_info); -+ } else if (extended_security -+ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) -+ && (pSesInfo->server->secType == RawNTLMSSP)) { -+ cFYI(1, ("NTLMSSP sesssetup ")); -+ rc = CIFSNTLMSSPNegotiateSessSetup(xid, -+ pSesInfo, -+ &ntlmv2_flag, -+ nls_info); -+ if (!rc) { -+ if(ntlmv2_flag) { -+ char * v2_response; -+ cFYI(1,("Can use more secure NTLM version 2 password hash")); -+ CalcNTLMv2_partial_mac_key(pSesInfo, -+ nls_info); -+ v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); -+ if(v2_response) { -+ CalcNTLMv2_response(pSesInfo,v2_response); -+/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */ -+ kfree(v2_response); -+ /* BB Put dummy sig in SessSetup PDU? */ -+ } else -+ rc = -ENOMEM; -+ -+ } else { -+ SMBNTencrypt(pSesInfo->password, -+ pSesInfo->server->cryptKey, -+ ntlm_session_key); -+ -+ cifs_calculate_mac_key(pSesInfo->mac_signing_key, -+ ntlm_session_key, -+ pSesInfo->password); -+ } -+ /* for better security the weaker lanman hash not sent -+ in AuthSessSetup so we no longer calculate it */ -+ -+ rc = CIFSNTLMSSPAuthSessSetup(xid, -+ pSesInfo, -+ ntlm_session_key, -+ ntlmv2_flag, -+ nls_info); -+ } -+ } else { /* old style NTLM 0.12 session setup */ -+ SMBNTencrypt(pSesInfo->password, -+ pSesInfo->server->cryptKey, -+ ntlm_session_key); -+ -+ cifs_calculate_mac_key(pSesInfo->mac_signing_key, -+ ntlm_session_key, pSesInfo->password); -+ rc = CIFSSessSetup(xid, pSesInfo, -+ ntlm_session_key, nls_info); -+ } -+ if (rc) { -+ cERROR(1,("Send error in SessSetup = %d",rc)); -+ } else { -+ cFYI(1,("CIFS Session Established successfully")); -+ pSesInfo->status = CifsGood; -+ } -+ } -+ return rc; -+} -+ ---- /dev/null -+++ b/fs/cifs/dir.c -@@ -0,0 +1,425 @@ -+/* -+ * fs/cifs/dir.c -+ * -+ * vfs operations that deal with dentries -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2003 -+ * 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 -+ */ -+#include <linux/fs.h> -+#include <linux/stat.h> -+#include <linux/slab.h> -+#include "cifsfs.h" -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_debug.h" -+#include "cifs_fs_sb.h" -+ -+void -+renew_parental_timestamps(struct dentry *direntry) -+{ -+ /* BB check if there is a way to get the kernel to do this or if we really need this */ -+ do { -+ direntry->d_time = jiffies; -+ direntry = direntry->d_parent; -+ } while (!IS_ROOT(direntry)); -+} -+ -+/* Note: caller must free return buffer */ -+char * -+build_path_from_dentry(struct dentry *direntry) -+{ -+ struct dentry *temp; -+ int namelen = 0; -+ char *full_path; -+ -+ if(direntry == NULL) -+ return NULL; /* not much we can do if dentry is freed and -+ we need to reopen the file after it was closed implicitly -+ when the server crashed */ -+ -+cifs_bp_rename_retry: -+ for (temp = direntry; !IS_ROOT(temp);) { -+ namelen += (1 + temp->d_name.len); -+ temp = temp->d_parent; -+ if(temp == NULL) { -+ cERROR(1,("corrupt dentry")); -+ return NULL; -+ } -+ } -+ -+ full_path = kmalloc(namelen+1, GFP_KERNEL); -+ if(full_path == NULL) -+ return full_path; -+ full_path[namelen] = 0; /* trailing null */ -+ -+ for (temp = direntry; !IS_ROOT(temp);) { -+ namelen -= 1 + temp->d_name.len; -+ if (namelen < 0) { -+ break; -+ } else { -+ full_path[namelen] = '\\'; -+ strncpy(full_path + namelen + 1, temp->d_name.name, -+ temp->d_name.len); -+ cFYI(0, (" name: %s ", full_path + namelen)); -+ } -+ temp = temp->d_parent; -+ if(temp == NULL) { -+ cERROR(1,("corrupt dentry")); -+ kfree(full_path); -+ return NULL; -+ } -+ } -+ if (namelen != 0) { -+ cERROR(1, -+ ("We did not end path lookup where we expected namelen is %d", -+ namelen)); -+ /* presumably this is only possible if we were racing with a rename -+ of one of the parent directories (we can not lock the dentries -+ above us to prevent this, but retrying should be harmless) */ -+ kfree(full_path); -+ namelen = 0; -+ goto cifs_bp_rename_retry; -+ } -+ -+ return full_path; -+} -+ -+/* Note: caller must free return buffer */ -+char * -+build_wildcard_path_from_dentry(struct dentry *direntry) -+{ -+ struct dentry *temp; -+ int namelen = 0; -+ char *full_path; -+ -+ if(direntry == NULL) -+ return NULL; /* not much we can do if dentry is freed and -+ we need to reopen the file after it was closed implicitly -+ when the server crashed */ -+ -+cifs_bwp_rename_retry: -+ for (temp = direntry; !IS_ROOT(temp);) { -+ namelen += (1 + temp->d_name.len); -+ temp = temp->d_parent; -+ if(temp == NULL) { -+ cERROR(1,("corrupt dentry")); -+ return NULL; -+ } -+ } -+ -+ full_path = kmalloc(namelen+3, GFP_KERNEL); -+ if(full_path == NULL) -+ return full_path; -+ -+ full_path[namelen] = '\\'; -+ full_path[namelen+1] = '*'; -+ full_path[namelen+2] = 0; /* trailing null */ -+ -+ for (temp = direntry; !IS_ROOT(temp);) { -+ namelen -= 1 + temp->d_name.len; -+ if (namelen < 0) { -+ break; -+ } else { -+ full_path[namelen] = '\\'; -+ strncpy(full_path + namelen + 1, temp->d_name.name, -+ temp->d_name.len); -+ cFYI(0, (" name: %s ", full_path + namelen)); -+ } -+ temp = temp->d_parent; -+ if(temp == NULL) { -+ cERROR(1,("corrupt dentry")); -+ kfree(full_path); -+ return NULL; -+ } -+ } -+ if (namelen != 0) { -+ cERROR(1, -+ ("We did not end path lookup where we expected namelen is %d", -+ namelen)); -+ /* presumably this is only possible if we were racing with a rename -+ of one of the parent directories (we can not lock the dentries -+ above us to prevent this, but retrying should be harmless) */ -+ kfree(full_path); -+ namelen = 0; -+ goto cifs_bwp_rename_retry; -+ } -+ -+ return full_path; -+} -+ -+/* Inode operations in similar order to how they appear in the Linux file fs.h */ -+ -+int -+cifs_create(struct inode *inode, struct dentry *direntry, int mode) -+{ -+ int rc = -ENOENT; -+ int xid; -+ int oplock = 0; /* no sense requested oplock if we are just going to -+ immediately close the file */ -+ __u16 fileHandle; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ FILE_ALL_INFO * buf = NULL; -+ struct inode *newinode = NULL; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ down(&direntry->d_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(direntry); -+ up(&direntry->d_sb->s_vfs_rename_sem); -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ -+ /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */ -+ -+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); -+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF, -+ GENERIC_WRITE, CREATE_NOT_DIR, -+ &fileHandle, &oplock, buf, cifs_sb->local_nls); -+ if (rc) { -+ cFYI(1, ("cifs_create returned 0x%x ", rc)); -+ } else { -+ /* BB for case of overwriting existing file can we use the inode that was -+ passed in rather than creating new one?? */ -+ if (pTcon->ses->capabilities & CAP_UNIX) -+ rc = cifs_get_inode_info_unix(&newinode, full_path, -+ inode->i_sb,xid); -+ else -+ rc = cifs_get_inode_info(&newinode, full_path, -+ buf, inode->i_sb,xid); -+ -+ if (rc != 0) { -+ cFYI(1,("Create worked but get_inode_info failed with rc = %d", -+ rc)); -+ } else { -+ direntry->d_op = &cifs_dentry_ops; -+ d_instantiate(direntry, newinode); -+ } -+ CIFSSMBClose(xid, pTcon, fileHandle); -+ -+ if(newinode) { -+ newinode->i_mode = mode; -+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) -+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode, -+ (__u64)-1, -+ (__u64)-1, -+ 0 /* dev */, -+ cifs_sb->local_nls); -+ else { /* BB implement via Windows security descriptors */ -+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ -+ /* in the meantime could set r/o dos attribute when perms are eg: -+ mode & 0222 == 0 */ -+ } -+ } -+ } -+ -+ if (buf) -+ kfree(buf); -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ -+ return rc; -+} -+ -+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number) -+{ -+ int rc = -EPERM; -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ struct inode * newinode = NULL; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ down(&direntry->d_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(direntry); -+ up(&direntry->d_sb->s_vfs_rename_sem); -+ if(full_path == NULL) -+ rc = -ENOMEM; -+ -+ if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) { -+ rc = CIFSSMBUnixSetPerms(xid, pTcon, -+ full_path, mode, current->euid, current->egid, -+ device_number, cifs_sb->local_nls); -+ if(!rc) { -+ rc = cifs_get_inode_info_unix(&newinode, full_path, -+ inode->i_sb,xid); -+ direntry->d_op = &cifs_dentry_ops; -+ if(rc == 0) -+ d_instantiate(direntry, newinode); -+ } -+ } -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ -+ return rc; -+} -+ -+ -+struct dentry * -+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry) -+{ -+ int xid; -+ int rc = 0; /* to get around spurious gcc warning, set to zero here */ -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct inode *newInode = NULL; -+ char *full_path = NULL; -+ -+ xid = GetXid(); -+ -+ cFYI(1, -+ (" parent inode = 0x%p name is: %s and dentry = 0x%p", -+ parent_dir_inode, direntry->d_name.name, direntry)); -+ -+ /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */ -+ -+ /* check whether path exists */ -+ -+ cifs_sb = CIFS_SB(parent_dir_inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ /* can not grab the rename sem here since it would -+ deadlock in the cases (beginning of sys_rename itself) -+ in which we already have the sb rename sem */ -+ full_path = build_path_from_dentry(direntry); -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ if (direntry->d_inode != NULL) { -+ cFYI(1, (" non-NULL inode in lookup")); -+ } else { -+ cFYI(1, (" NULL inode in lookup")); -+ } -+ cFYI(1, -+ (" Full path: %s inode = 0x%p", full_path, direntry->d_inode)); -+ -+ if (pTcon->ses->capabilities & CAP_UNIX) -+ rc = cifs_get_inode_info_unix(&newInode, full_path, -+ parent_dir_inode->i_sb,xid); -+ else -+ rc = cifs_get_inode_info(&newInode, full_path, NULL, -+ parent_dir_inode->i_sb,xid); -+ -+ if ((rc == 0) && (newInode != NULL)) { -+ direntry->d_op = &cifs_dentry_ops; -+ d_add(direntry, newInode); -+ -+ /* since paths are not looked up by component - the parent directories are presumed to be good here */ -+ renew_parental_timestamps(direntry); -+ -+ } else if (rc == -ENOENT) { -+ rc = 0; -+ d_add(direntry, NULL); -+ } else { -+ cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc)); -+ /* BB special case check for Access Denied - watch security -+ exposure of returning dir info implicitly via different rc -+ if file exists or not but no access BB */ -+ } -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return ERR_PTR(rc); -+} -+ -+int -+cifs_dir_open(struct inode *inode, struct file *file) -+{ /* NB: currently unused since searches are opened in readdir */ -+ int rc = 0; -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ if(file->f_dentry) { -+ down(&file->f_dentry->d_sb->s_vfs_rename_sem); -+ full_path = build_wildcard_path_from_dentry(file->f_dentry); -+ up(&file->f_dentry->d_sb->s_vfs_rename_sem); -+ } else { -+ FreeXid(xid); -+ return -EIO; -+ } -+ -+ cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path)); -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+static int -+cifs_d_revalidate(struct dentry *direntry, int flags) -+{ -+ int isValid = 1; -+ -+/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */ -+ -+ if (direntry->d_inode) { -+ if (cifs_revalidate(direntry)) { -+ /* unlock_kernel(); */ -+ return 0; -+ } -+ } else { -+ cFYI(1, -+ ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p", -+ direntry->d_name.name, direntry)); -+ } -+ -+/* unlock_kernel(); */ -+ -+ return isValid; -+} -+ -+/* static int cifs_d_delete(struct dentry *direntry) -+{ -+ int rc = 0; -+ -+ cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name)); -+ -+ return rc; -+} */ -+ -+struct dentry_operations cifs_dentry_ops = { -+ .d_revalidate = cifs_d_revalidate, -+/* d_delete: cifs_d_delete, *//* not needed except for debugging */ -+ /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ -+}; ---- /dev/null -+++ b/fs/cifs/file.c -@@ -0,0 +1,2185 @@ -+/* -+ * fs/cifs/file.c -+ * -+ * vfs operations that deal with files -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2003 -+ * 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 -+ */ -+#include <linux/fs.h> -+#include <linux/stat.h> -+#include <linux/fcntl.h> -+#include <linux/version.h> -+#include <linux/pagemap.h> -+#include <linux/smp_lock.h> -+#include <linux/list.h> -+#include <asm/div64.h> -+#include <linux/mm.h> -+#include <linux/types.h> -+#include "cifsfs.h" -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_unicode.h" -+#include "cifs_debug.h" -+#include "cifs_fs_sb.h" -+ -+int -+cifs_open(struct inode *inode, struct file *file) -+{ -+ int rc = -EACCES; -+ int xid, oplock; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct cifsFileInfo *pCifsFile; -+ struct cifsInodeInfo *pCifsInode; -+ char *full_path = NULL; -+ int desiredAccess = 0x20197; -+ int disposition; -+ __u16 netfid; -+ FILE_ALL_INFO * buf = NULL; -+ time_t temp; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ down(&inode->i_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(file->f_dentry); -+ up(&inode->i_sb->s_vfs_rename_sem); -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ -+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path)); -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ desiredAccess = GENERIC_READ; -+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY) -+ desiredAccess = GENERIC_WRITE; -+ else if ((file->f_flags & O_ACCMODE) == O_RDWR) { -+ /* GENERIC_ALL is too much permission to request */ -+ /* can cause unnecessary access denied on create */ -+ /* desiredAccess = GENERIC_ALL; */ -+ desiredAccess = GENERIC_READ | GENERIC_WRITE; -+ } -+ -+/********************************************************************* -+ * open flag mapping table: -+ * -+ * POSIX Flag CIFS Disposition -+ * ---------- ---------------- -+ * O_CREAT FILE_OPEN_IF -+ * O_CREAT | O_EXCL FILE_CREATE -+ * O_CREAT | O_TRUNC FILE_OVERWRITE_IF -+ * O_TRUNC FILE_OVERWRITE -+ * none of the above FILE_OPEN -+ * -+ * Note that there is not a direct match between disposition -+ * FILE_SUPERSEDE (ie create whether or not file exists although -+ * O_CREAT | O_TRUNC is similar but truncates the existing -+ * file rather than creating a new file as FILE_SUPERSEDE does -+ * (which uses the attributes / metadata passed in on open call) -+ *? -+ *? O_SYNC is a reasonable match to CIFS writethrough flag -+ *? and the read write flags match reasonably. O_LARGEFILE -+ *? is irrelevant because largefile support is always used -+ *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY, -+ * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation -+ *********************************************************************/ -+ -+ /* For 2.4 case, file was already checked for existence -+ before create by vfs lookup and created in create -+ entry point, we are now just opening the newly -+ created file with the right desiredAccess flags */ -+ -+ if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) -+ disposition = FILE_OPEN_IF; -+ else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) -+ disposition = FILE_OVERWRITE_IF; -+ else if((file->f_flags & O_CREAT) == O_CREAT) -+ disposition = FILE_OPEN_IF; -+ else -+ disposition = FILE_OPEN; -+ -+ if (oplockEnabled) -+ oplock = REQ_OPLOCK; -+ else -+ oplock = FALSE; -+ -+ /* BB pass O_SYNC flag through on file attributes .. BB */ -+ -+ /* Also refresh inode by passing in file_info buf returned by SMBOpen -+ and calling get_inode_info with returned buf (at least -+ helps non-Unix server case */ -+ -+ /* BB we can not do this if this is the second open of a file -+ and the first handle has writebehind data, we might be -+ able to simply do a filemap_fdatawrite/filemap_fdatawait first */ -+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); -+ if(buf==0) { -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, -+ CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls); -+ if (rc) { -+ cFYI(1, ("cifs_open returned 0x%x ", rc)); -+ cFYI(1, ("oplock: %d ", oplock)); -+ } else { -+ file->private_data = -+ kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); -+ if (file->private_data) { -+ memset(file->private_data, 0, sizeof(struct cifsFileInfo)); -+ pCifsFile = (struct cifsFileInfo *) file->private_data; -+ pCifsFile->netfid = netfid; -+ pCifsFile->pid = current->pid; -+ init_MUTEX(&pCifsFile->fh_sem); -+ pCifsFile->pfile = file; /* needed for writepage */ -+ pCifsFile->pInode = inode; -+ pCifsFile->invalidHandle = FALSE; -+ pCifsFile->closePend = FALSE; -+ write_lock(&GlobalSMBSeslock); -+ spin_lock(&files_lock); -+ list_add(&pCifsFile->tlist,&pTcon->openFileList); -+ pCifsInode = CIFS_I(file->f_dentry->d_inode); -+ if(pCifsInode) { -+ /* want handles we can use to read with first */ -+ /* in the list so we do not have to walk the */ -+ /* list to search for one in prepare_write */ -+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList); -+ } else { -+ list_add(&pCifsFile->flist,&pCifsInode->openFileList); -+ } -+ spin_unlock(&files_lock); -+ write_unlock(&GlobalSMBSeslock); -+ if(pCifsInode->clientCanCacheRead) { -+ /* we have the inode open somewhere else -+ no need to discard cache data */ -+ } else { -+ if(buf) { -+ /* BB need same check in cifs_create too? */ -+ -+ /* if not oplocked, invalidate inode pages if mtime -+ or file size changed */ -+ temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime)); -+ if((file->f_dentry->d_inode->i_mtime == temp) && -+ (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) { -+ cFYI(1,("inode unchanged on server")); -+ } else { -+ if(file->f_dentry->d_inode->i_mapping) { -+ /* BB no need to lock inode until after invalidate*/ -+ /* since namei code should already have it locked?*/ -+ filemap_fdatasync(file->f_dentry->d_inode->i_mapping); -+ } -+ cFYI(1,("invalidating remote inode since open detected it changed")); -+ invalidate_inode_pages(file->f_dentry->d_inode); -+ } -+ } -+ } -+ if (pTcon->ses->capabilities & CAP_UNIX) -+ rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode, -+ full_path, inode->i_sb,xid); -+ else -+ rc = cifs_get_inode_info(&file->f_dentry->d_inode, -+ full_path, buf, inode->i_sb,xid); -+ -+ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { -+ pCifsInode->clientCanCacheAll = TRUE; -+ pCifsInode->clientCanCacheRead = TRUE; -+ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode)); -+ } else if((oplock & 0xF) == OPLOCK_READ) -+ pCifsInode->clientCanCacheRead = TRUE; -+ } else { -+ spin_unlock(&files_lock); -+ write_unlock(&GlobalSMBSeslock); -+ } -+ if(oplock & CIFS_CREATE_ACTION) { -+ /* time to set mode which we can not set earlier due -+ to problems creating new read-only files */ -+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) -+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode, -+ (__u64)-1, -+ (__u64)-1, -+ 0 /* dev */, -+ cifs_sb->local_nls); -+ else {/* BB implement via Windows security descriptors */ -+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ -+ /* in the meantime could set r/o dos attribute when perms are eg: -+ mode & 0222 == 0 */ -+ } -+ } -+ } -+ } -+ -+ if (buf) -+ kfree(buf); -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+/* Try to reaquire byte range locks that were released when session */ -+/* to server was lost */ -+static int cifs_relock_file(struct cifsFileInfo * cifsFile) -+{ -+ int rc = 0; -+ -+/* BB list all locks open on this file and relock */ -+ -+ return rc; -+} -+ -+static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush) -+{ -+ int rc = -EACCES; -+ int xid, oplock; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct cifsFileInfo *pCifsFile; -+ struct cifsInodeInfo *pCifsInode; -+ char *full_path = NULL; -+ int desiredAccess = 0x20197; -+ int disposition = FILE_OPEN; -+ __u16 netfid; -+ -+ if(inode == NULL) -+ return -EBADF; -+ if (file->private_data) { -+ pCifsFile = (struct cifsFileInfo *) file->private_data; -+ } else -+ return -EBADF; -+ -+ xid = GetXid(); -+ down(&pCifsFile->fh_sem); -+ if(pCifsFile->invalidHandle == FALSE) { -+ up(&pCifsFile->fh_sem); -+ FreeXid(xid); -+ return 0; -+ } -+ -+ if(file->f_dentry == NULL) { -+ up(&pCifsFile->fh_sem); -+ cFYI(1,("failed file reopen, no valid name if dentry freed")); -+ FreeXid(xid); -+ return -EBADF; -+ } -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+/* can not grab rename sem here because various ops, including -+those that already have the rename sem can end up causing writepage -+to get called and if the server was down that means we end up here, -+and we can never tell if the caller already has the rename_sem */ -+ full_path = build_path_from_dentry(file->f_dentry); -+ if(full_path == NULL) { -+ up(&pCifsFile->fh_sem); -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ -+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path)); -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ desiredAccess = GENERIC_READ; -+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY) -+ desiredAccess = GENERIC_WRITE; -+ else if ((file->f_flags & O_ACCMODE) == O_RDWR) { -+ /* GENERIC_ALL is too much permission to request */ -+ /* can cause unnecessary access denied on create */ -+ /* desiredAccess = GENERIC_ALL; */ -+ desiredAccess = GENERIC_READ | GENERIC_WRITE; -+ } -+ -+ if (oplockEnabled) -+ oplock = REQ_OPLOCK; -+ else -+ oplock = FALSE; -+ -+ -+ /* Can not refresh inode by passing in file_info buf to be returned -+ by SMBOpen and then calling get_inode_info with returned buf -+ since file might have write behind data that needs to be flushed -+ and server version of file size can be stale. If we -+ knew for sure that inode was not dirty locally we could do this */ -+ -+/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); -+ if(buf==0) { -+ up(&pCifsFile->fh_sem); -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return -ENOMEM; -+ }*/ -+ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, -+ CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls); -+ if (rc) { -+ up(&pCifsFile->fh_sem); -+ cFYI(1, ("cifs_open returned 0x%x ", rc)); -+ cFYI(1, ("oplock: %d ", oplock)); -+ } else { -+ pCifsFile->netfid = netfid; -+ pCifsFile->invalidHandle = FALSE; -+ up(&pCifsFile->fh_sem); -+ pCifsInode = CIFS_I(inode); -+ if(pCifsInode) { -+ if(can_flush) { -+ filemap_fdatasync(inode->i_mapping); -+ filemap_fdatawait(inode->i_mapping); -+ /* temporarily disable caching while we -+ go to server to get inode info */ -+ pCifsInode->clientCanCacheAll = FALSE; -+ pCifsInode->clientCanCacheRead = FALSE; -+ if (pTcon->ses->capabilities & CAP_UNIX) -+ rc = cifs_get_inode_info_unix(&inode, -+ full_path, inode->i_sb,xid); -+ else -+ rc = cifs_get_inode_info(&inode, -+ full_path, NULL, inode->i_sb,xid); -+ } /* else we are writing out data to server already -+ and could deadlock if we tried to flush data, and -+ since we do not know if we have data that would -+ invalidate the current end of file on the server -+ we can not go to the server to get the new -+ inod info */ -+ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { -+ pCifsInode->clientCanCacheAll = TRUE; -+ pCifsInode->clientCanCacheRead = TRUE; -+ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode)); -+ } else if((oplock & 0xF) == OPLOCK_READ) { -+ pCifsInode->clientCanCacheRead = TRUE; -+ pCifsInode->clientCanCacheAll = FALSE; -+ } else { -+ pCifsInode->clientCanCacheRead = FALSE; -+ pCifsInode->clientCanCacheAll = FALSE; -+ } -+ cifs_relock_file(pCifsFile); -+ } -+ } -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_close(struct inode *inode, struct file *file) -+{ -+ int rc = 0; -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct cifsFileInfo *pSMBFile = -+ (struct cifsFileInfo *) file->private_data; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ if (pSMBFile) { -+ pSMBFile->closePend = TRUE; -+ spin_lock(&files_lock); -+ if(pTcon) { -+ /* no sense reconnecting to close a file that is -+ already closed */ -+ if (pTcon->tidStatus != CifsNeedReconnect) { -+ spin_unlock(&files_lock); -+ rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid); -+ spin_lock(&files_lock); -+ } -+ } -+ list_del(&pSMBFile->flist); -+ list_del(&pSMBFile->tlist); -+ spin_unlock(&files_lock); -+ if(pSMBFile->search_resume_name) -+ kfree(pSMBFile->search_resume_name); -+ kfree(file->private_data); -+ file->private_data = NULL; -+ } else -+ rc = -EBADF; -+ -+ if(list_empty(&(CIFS_I(inode)->openFileList))) { -+ cFYI(1,("closing last open instance for inode %p",inode)); -+ /* if the file is not open we do not know if we can cache -+ info on this inode, much less write behind and read ahead */ -+ CIFS_I(inode)->clientCanCacheRead = FALSE; -+ CIFS_I(inode)->clientCanCacheAll = FALSE; -+ } -+ if((rc ==0) && CIFS_I(inode)->write_behind_rc) -+ rc = CIFS_I(inode)->write_behind_rc; -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_closedir(struct inode *inode, struct file *file) -+{ -+ int rc = 0; -+ int xid; -+ struct cifsFileInfo *pSMBFileStruct = -+ (struct cifsFileInfo *) file->private_data; -+ -+ cFYI(1, ("Closedir inode = 0x%p with ", inode)); -+ -+ xid = GetXid(); -+ -+ if (pSMBFileStruct) { -+ cFYI(1, ("Freeing private data in close dir")); -+ kfree(file->private_data); -+ file->private_data = NULL; -+ } -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) -+{ -+ int rc, xid; -+ __u32 lockType = LOCKING_ANDX_LARGE_FILES; -+ __u32 numLock = 0; -+ __u32 numUnlock = 0; -+ __u64 length; -+ int wait_flag = FALSE; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ length = 1 + pfLock->fl_end - pfLock->fl_start; -+ -+ rc = -EACCES; -+ -+ xid = GetXid(); -+ -+ cFYI(1, -+ ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld", -+ cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start, -+ pfLock->fl_end)); -+ -+ if (pfLock->fl_flags & FL_POSIX) -+ cFYI(1, ("Posix ")); -+ if (pfLock->fl_flags & FL_FLOCK) -+ cFYI(1, ("Flock ")); -+/* if (pfLock->fl_flags & FL_SLEEP) { -+ cFYI(1, ("Blocking lock ")); -+ wait_flag = TRUE; -+ } */ -+ if (pfLock->fl_flags & FL_ACCESS) -+ cFYI(1, ("Process suspended by mandatory locking - not implemented yet ")); -+ if (pfLock->fl_flags & FL_LEASE) -+ cFYI(1, ("Lease on file - not implemented yet")); -+ if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_ACCESS | FL_LEASE))) -+ cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags)); -+ -+ if (pfLock->fl_type == F_WRLCK) { -+ cFYI(1, ("F_WRLCK ")); -+ numLock = 1; -+ } else if (pfLock->fl_type == F_UNLCK) { -+ cFYI(1, ("F_UNLCK ")); -+ numUnlock = 1; -+ } else if (pfLock->fl_type == F_RDLCK) { -+ cFYI(1, ("F_RDLCK ")); -+ lockType |= LOCKING_ANDX_SHARED_LOCK; -+ numLock = 1; -+ } else if (pfLock->fl_type == F_EXLCK) { -+ cFYI(1, ("F_EXLCK ")); -+ numLock = 1; -+ } else if (pfLock->fl_type == F_SHLCK) { -+ cFYI(1, ("F_SHLCK ")); -+ lockType |= LOCKING_ANDX_SHARED_LOCK; -+ numLock = 1; -+ } else -+ cFYI(1, ("Unknown type of lock ")); -+ -+ cifs_sb = CIFS_SB(file->f_dentry->d_sb); -+ pTcon = cifs_sb->tcon; -+ -+ if (file->private_data == NULL) { -+ FreeXid(xid); -+ return -EBADF; -+ } -+ -+ if (IS_GETLK(cmd)) { -+ rc = CIFSSMBLock(xid, pTcon, -+ ((struct cifsFileInfo *) file-> -+ private_data)->netfid, -+ length, -+ pfLock->fl_start, 0, 1, lockType, -+ 0 /* wait flag */ ); -+ if (rc == 0) { -+ rc = CIFSSMBLock(xid, pTcon, -+ ((struct cifsFileInfo *) file-> -+ private_data)->netfid, -+ length, -+ pfLock->fl_start, 1 /* numUnlock */ , -+ 0 /* numLock */ , lockType, -+ 0 /* wait flag */ ); -+ pfLock->fl_type = F_UNLCK; -+ if (rc != 0) -+ cERROR(1, -+ ("Error unlocking previously locked range %d during test of lock ", -+ rc)); -+ rc = 0; -+ -+ } else { -+ /* if rc == ERR_SHARING_VIOLATION ? */ -+ rc = 0; /* do not change lock type to unlock since range in use */ -+ } -+ -+ FreeXid(xid); -+ return rc; -+ } -+ -+ rc = CIFSSMBLock(xid, pTcon, -+ ((struct cifsFileInfo *) file->private_data)-> -+ netfid, length, -+ pfLock->fl_start, numUnlock, numLock, lockType, -+ wait_flag); -+ FreeXid(xid); -+ return rc; -+} -+ -+ssize_t -+cifs_write(struct file * file, const char *write_data, -+ size_t write_size, loff_t * poffset) -+{ -+ int rc = 0; -+ unsigned int bytes_written = 0; -+ unsigned int total_written; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ int xid, long_op; -+ struct cifsFileInfo * open_file; -+ -+ if(file->f_dentry == NULL) -+ return -EBADF; -+ -+ cifs_sb = CIFS_SB(file->f_dentry->d_sb); -+ if(cifs_sb == NULL) { -+ return -EBADF; -+ } -+ pTcon = cifs_sb->tcon; -+ -+ /*cFYI(1, -+ (" write %d bytes to offset %lld of %s", write_size, -+ *poffset, file->f_dentry->d_name.name)); */ -+ -+ if (file->private_data == NULL) { -+ return -EBADF; -+ } else { -+ open_file = (struct cifsFileInfo *) file->private_data; -+ } -+ -+ xid = GetXid(); -+ if(file->f_dentry->d_inode == NULL) { -+ FreeXid(xid); -+ return -EBADF; -+ } -+ -+ if (*poffset > file->f_dentry->d_inode->i_size) -+ long_op = 2; /* writes past end of file can take a long time */ -+ else -+ long_op = 1; -+ -+ for (total_written = 0; write_size > total_written; -+ total_written += bytes_written) { -+ rc = -EAGAIN; -+ while(rc == -EAGAIN) { -+ if(file->private_data == NULL) { -+ /* file has been closed on us */ -+ FreeXid(xid); -+ /* if we have gotten here we have written some data -+ and blocked, and the file has been freed on us -+ while we blocked so return what we managed to write */ -+ return total_written; -+ } -+ if(open_file->closePend) { -+ FreeXid(xid); -+ if(total_written) -+ return total_written; -+ else -+ return -EBADF; -+ } -+ if (open_file->invalidHandle) { -+ if((file->f_dentry == NULL) || -+ (file->f_dentry->d_inode == NULL)) { -+ FreeXid(xid); -+ return total_written; -+ } -+ /* we could deadlock if we called -+ filemap_fdatawait from here so tell -+ reopen_file not to flush data to server now */ -+ rc = cifs_reopen_file(file->f_dentry->d_inode, -+ file,FALSE); -+ if(rc != 0) -+ break; -+ } -+ -+ rc = CIFSSMBWrite(xid, pTcon, -+ open_file->netfid, -+ write_size - total_written, *poffset, -+ &bytes_written, -+ write_data + total_written, long_op); -+ } -+ if (rc || (bytes_written == 0)) { -+ if (total_written) -+ break; -+ else { -+ FreeXid(xid); -+ return rc; -+ } -+ } else -+ *poffset += bytes_written; -+ long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */ -+ } -+ -+#ifdef CONFIG_CIFS_STATS -+ if(total_written > 0) { -+ atomic_inc(&pTcon->num_writes); -+ spin_lock(&pTcon->stat_lock); -+ pTcon->bytes_written += total_written; -+ spin_unlock(&pTcon->stat_lock); -+ } -+#endif -+ -+ /* since the write may have blocked check these pointers again */ -+ if(file->f_dentry) { -+ if(file->f_dentry->d_inode) { -+ file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime = -+ CURRENT_TIME; -+ if (total_written > 0) { -+ if (*poffset > file->f_dentry->d_inode->i_size) -+ file->f_dentry->d_inode->i_size = *poffset; -+ } -+ mark_inode_dirty_sync(file->f_dentry->d_inode); -+ } -+ } -+ FreeXid(xid); -+ return total_written; -+} -+ -+static int -+cifs_partialpagewrite(struct page *page,unsigned from, unsigned to) -+{ -+ struct address_space *mapping = page->mapping; -+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; -+ char * write_data; -+ int rc = -EFAULT; -+ int bytes_written = 0; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct inode *inode; -+ struct cifsInodeInfo *cifsInode; -+ struct cifsFileInfo *open_file = NULL; -+ struct list_head *tmp; -+ struct list_head *tmp1; -+ -+ if (!mapping) { -+ return -EFAULT; -+ } else if(!mapping->host) { -+ return -EFAULT; -+ } -+ -+ inode = page->mapping->host; -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ offset += (loff_t)from; -+ write_data = kmap(page); -+ write_data += from; -+ -+ if((to > PAGE_CACHE_SIZE) || (from > to)) { -+ kunmap(page); -+ return -EIO; -+ } -+ -+ /* racing with truncate? */ -+ if(offset > mapping->host->i_size) { -+ kunmap(page); -+ return 0; /* don't care */ -+ } -+ -+ /* check to make sure that we are not extending the file */ -+ if(mapping->host->i_size - offset < (loff_t)to) -+ to = (unsigned)(mapping->host->i_size - offset); -+ -+ -+ cifsInode = CIFS_I(mapping->host); -+ read_lock(&GlobalSMBSeslock); -+ /* BB we should start at the end */ -+ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { -+ open_file = list_entry(tmp,struct cifsFileInfo, flist); -+ if(open_file->closePend) -+ continue; -+ /* We check if file is open for writing first */ -+ if((open_file->pfile) && -+ ((open_file->pfile->f_flags & O_RDWR) || -+ (open_file->pfile->f_flags & O_WRONLY))) { -+ read_unlock(&GlobalSMBSeslock); -+ bytes_written = cifs_write(open_file->pfile, write_data, -+ to-from, &offset); -+ read_lock(&GlobalSMBSeslock); -+ /* Does mm or vfs already set times? */ -+ inode->i_atime = inode->i_mtime = CURRENT_TIME; -+ if ((bytes_written > 0) && (offset)) { -+ rc = 0; -+ } else if(bytes_written < 0) { -+ if(rc == -EBADF) { -+ /* have seen a case in which -+ kernel seemed to have closed/freed a file -+ even with writes active so we might as well -+ see if there are other file structs to try -+ for the same inode before giving up */ -+ continue; -+ } else -+ rc = bytes_written; -+ } -+ break; /* now that we found a valid file handle -+ and tried to write to it we are done, no -+ sense continuing to loop looking for another */ -+ } -+ if(tmp->next == NULL) { -+ cFYI(1,("File instance %p removed",tmp)); -+ break; -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ if(open_file == NULL) { -+ cFYI(1,("No writeable filehandles for inode")); -+ rc = -EIO; -+ } -+ -+ kunmap(page); -+ return rc; -+} -+ -+#if 0 -+static int -+cifs_writepages(struct address_space *mapping, struct writeback_control *wbc) -+{ -+ int rc = -EFAULT; -+ int xid; -+ -+ xid = GetXid(); -+/* call 16K write then Setpageuptodate */ -+ FreeXid(xid); -+ return rc; -+} -+#endif -+ -+static int -+cifs_writepage(struct page* page) -+{ -+ int rc = -EFAULT; -+ int xid; -+ -+ xid = GetXid(); -+/* BB add check for wbc flags */ -+ page_cache_get(page); -+ if (!Page_Uptodate(page)) { -+ cFYI(1,("ppw - page not up to date")); -+ } -+ -+ rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE); -+ SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) -+ unlock_page(page); -+#else -+ UnlockPage(page); -+#endif -+ page_cache_release(page); -+ FreeXid(xid); -+ return rc; -+} -+ -+static int -+cifs_commit_write(struct file *file, struct page *page, unsigned offset, -+ unsigned to) -+{ -+ int xid; -+ int rc = 0; -+ struct inode *inode = page->mapping->host; -+ loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; -+ char * page_data; -+ -+ xid = GetXid(); -+ cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to)); -+ if (position > inode->i_size){ -+ inode->i_size = position; -+ /*if (file->private_data == NULL) { -+ rc = -EBADF; -+ } else { -+ open_file = (struct cifsFileInfo *)file->private_data; -+ cifs_sb = CIFS_SB(inode->i_sb); -+ rc = -EAGAIN; -+ while(rc == -EAGAIN) { -+ if((open_file->invalidHandle) && -+ (!open_file->closePend)) { -+ rc = cifs_reopen_file(file->f_dentry->d_inode,file); -+ if(rc != 0) -+ break; -+ } -+ if(!open_file->closePend) { -+ rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon, -+ position, open_file->netfid, -+ open_file->pid,FALSE); -+ } else { -+ rc = -EBADF; -+ break; -+ } -+ } -+ cFYI(1,(" SetEOF (commit write) rc = %d",rc)); -+ }*/ -+ } -+ if (!Page_Uptodate(page)) { -+ position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; -+ /* can not rely on (or let) writepage write this data */ -+ if(to < offset) { -+ cFYI(1,("Illegal offsets, can not copy from %d to %d", -+ offset,to)); -+ FreeXid(xid); -+ return rc; -+ } -+ /* this is probably better than directly calling -+ partialpage_write since in this function -+ the file handle is known which we might as well -+ leverage */ -+ /* BB check if anything else missing out of ppw */ -+ /* such as updating last write time */ -+ page_data = kmap(page); -+ rc = cifs_write(file, page_data+offset,to-offset, -+ &position); -+ if(rc > 0) -+ rc = 0; -+ /* else if rc < 0 should we set writebehind rc? */ -+ kunmap(page); -+ } else { -+ set_page_dirty(page); -+ } -+ -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_fsync(struct file *file, struct dentry *dentry, int datasync) -+{ -+ int xid; -+ int rc = 0; -+ struct inode * inode = file->f_dentry->d_inode; -+ -+ xid = GetXid(); -+ -+ cFYI(1, ("Sync file - name: %s datasync: 0x%x ", -+ dentry->d_name.name, datasync)); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17)) -+ rc = filemap_fdatasync(inode->i_mapping); -+#else -+ filemap_fdatasync(inode->i_mapping); -+#endif -+ if(rc == 0) -+ CIFS_I(inode)->write_behind_rc = 0; -+ FreeXid(xid); -+ return rc; -+} -+ -+static int -+cifs_sync_page(struct page *page) -+{ -+ struct address_space *mapping; -+ struct inode *inode; -+ unsigned long index = page->index; -+ unsigned int rpages = 0; -+ int rc = 0; -+ -+ cFYI(1,("sync page %p",page)); -+ mapping = page->mapping; -+ if (!mapping) -+ return 0; -+ inode = mapping->host; -+ if (!inode) -+ return 0; -+ -+/* fill in rpages then -+ result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */ -+ -+ cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); -+ -+ if (rc < 0) -+ return rc; -+ return 0; -+} -+ -+/* -+ * As file closes, flush all cached write data for this inode checking -+ * for write behind errors. -+ * -+ */ -+int cifs_flush(struct file *file) -+{ -+ struct inode * inode = file->f_dentry->d_inode; -+ int rc = 0; -+ -+ /* Rather than do the steps manually: */ -+ /* lock the inode for writing */ -+ /* loop through pages looking for write behind data (dirty pages) */ -+ /* coalesce into contiguous 16K (or smaller) chunks to write to server */ -+ /* send to server (prefer in parallel) */ -+ /* deal with writebehind errors */ -+ /* unlock inode for writing */ -+ /* filemapfdatawrite appears easier for the time being */ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17)) -+ rc = filemap_fdatasync(inode->i_mapping); -+#else -+ filemap_fdatasync(inode->i_mapping); -+#endif -+ if(rc == 0) /* reset wb rc if we were able to write out dirty pages */ -+ CIFS_I(inode)->write_behind_rc = 0; -+ -+ cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc)); -+ -+ return rc; -+} -+ -+ -+ssize_t -+cifs_read(struct file * file, char *read_data, size_t read_size, -+ loff_t * poffset) -+{ -+ int rc = -EACCES; -+ unsigned int bytes_read = 0; -+ unsigned int total_read; -+ unsigned int current_read_size; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ int xid; -+ char * current_offset; -+ struct cifsFileInfo * open_file; -+ -+ xid = GetXid(); -+ cifs_sb = CIFS_SB(file->f_dentry->d_sb); -+ pTcon = cifs_sb->tcon; -+ -+ if (file->private_data == NULL) { -+ FreeXid(xid); -+ return -EBADF; -+ } -+ open_file = (struct cifsFileInfo *)file->private_data; -+ -+ if((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ cFYI(1,("attempting read on write only file instance")); -+ } -+ -+ for (total_read = 0,current_offset=read_data; read_size > total_read; -+ total_read += bytes_read,current_offset+=bytes_read) { -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15)) -+ current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize); -+#else -+ current_read_size = min(read_size - total_read,cifs_sb->rsize); -+#endif -+ rc = -EAGAIN; -+ while(rc == -EAGAIN) { -+ if ((open_file->invalidHandle) && (!open_file->closePend)) { -+ rc = cifs_reopen_file(file->f_dentry->d_inode, -+ file,TRUE); -+ if(rc != 0) -+ break; -+ } -+ -+ rc = CIFSSMBRead(xid, pTcon, -+ open_file->netfid, -+ current_read_size, *poffset, -+ &bytes_read, ¤t_offset); -+ } -+ if (rc || (bytes_read == 0)) { -+ if (total_read) { -+ break; -+ } else { -+ FreeXid(xid); -+ return rc; -+ } -+ } else { -+#ifdef CONFIG_CIFS_STATS -+ atomic_inc(&pTcon->num_reads); -+ spin_lock(&pTcon->stat_lock); -+ pTcon->bytes_read += total_read; -+ spin_unlock(&pTcon->stat_lock); -+#endif -+ *poffset += bytes_read; -+ } -+ } -+ FreeXid(xid); -+ return total_read; -+} -+ -+int cifs_file_mmap(struct file * file, struct vm_area_struct * vma) -+{ -+ struct dentry * dentry = file->f_dentry; -+ int rc, xid; -+ -+ xid = GetXid(); -+ rc = cifs_revalidate(dentry); -+ if (rc) { -+ cFYI(1,("Validation prior to mmap failed, error=%d", rc)); -+ FreeXid(xid); -+ return rc; -+ } -+ rc = generic_file_mmap(file, vma); -+ FreeXid(xid); -+ return rc; -+} -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+static void cifs_copy_cache_pages(struct address_space *mapping, -+ struct list_head *pages, int bytes_read, -+ char *data,struct pagevec * plru_pvec) -+{ -+ struct page *page; -+ char * target; -+ -+ while (bytes_read > 0) { -+ if(list_empty(pages)) -+ break; -+ -+ page = list_entry(pages->prev, struct page, lru); -+ list_del(&page->lru); -+ -+ if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) { -+ page_cache_release(page); -+ cFYI(1,("Add page cache failed")); -+ continue; -+ } -+ -+ target = kmap_atomic(page,KM_USER0); -+ -+ if(PAGE_CACHE_SIZE > bytes_read) { -+ memcpy(target,data,bytes_read); -+ /* zero the tail end of this partial page */ -+ memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read); -+ bytes_read = 0; -+ } else { -+ memcpy(target,data,PAGE_CACHE_SIZE); -+ bytes_read -= PAGE_CACHE_SIZE; -+ } -+ kunmap_atomic(target,KM_USER0); -+ -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ if (!pagevec_add(plru_pvec, page)) -+ __pagevec_lru_add(plru_pvec); -+ data += PAGE_CACHE_SIZE; -+ } -+ return; -+} -+ -+ -+static int -+cifs_readpages(struct file *file, struct address_space *mapping, -+ struct list_head *page_list, unsigned num_pages) -+{ -+ int rc = -EACCES; -+ int xid; -+ loff_t offset; -+ struct page * page; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ int bytes_read = 0; -+ unsigned int read_size,i; -+ char * smb_read_data = NULL; -+ struct smb_com_read_rsp * pSMBr; -+ struct pagevec lru_pvec; -+ struct cifsFileInfo * open_file; -+ -+ xid = GetXid(); -+ if (file->private_data == NULL) { -+ FreeXid(xid); -+ return -EBADF; -+ } -+ open_file = (struct cifsFileInfo *)file->private_data; -+ cifs_sb = CIFS_SB(file->f_dentry->d_sb); -+ pTcon = cifs_sb->tcon; -+ -+ pagevec_init(&lru_pvec, 0); -+ -+ for(i = 0;i<num_pages;) { -+ unsigned contig_pages; -+ struct page * tmp_page; -+ unsigned long expected_index; -+ -+ if(list_empty(page_list)) { -+ break; -+ } -+ page = list_entry(page_list->prev, struct page, lru); -+ offset = (loff_t)page->index << PAGE_CACHE_SHIFT; -+ -+ /* count adjacent pages that we will read into */ -+ contig_pages = 0; -+ expected_index = list_entry(page_list->prev,struct page,lru)->index; -+ list_for_each_entry_reverse(tmp_page,page_list,lru) { -+ if(tmp_page->index == expected_index) { -+ contig_pages++; -+ expected_index++; -+ } else { -+ break; -+ } -+ } -+ if(contig_pages + i > num_pages) { -+ contig_pages = num_pages - i; -+ } -+ -+ /* for reads over a certain size could initiate async read ahead */ -+ -+ read_size = contig_pages * PAGE_CACHE_SIZE; -+ /* Read size needs to be in multiples of one page */ -+ read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK); -+ -+ rc = -EAGAIN; -+ while(rc == -EAGAIN) { -+ if ((open_file->invalidHandle) && (!open_file->closePend)) { -+ rc = cifs_reopen_file(file->f_dentry->d_inode, -+ file, TRUE); -+ if(rc != 0) -+ break; -+ } -+ -+ rc = CIFSSMBRead(xid, pTcon, -+ open_file->netfid, -+ read_size, offset, -+ &bytes_read, &smb_read_data); -+ /* BB need to check return code here */ -+ if(rc== -EAGAIN) { -+ if(smb_read_data) { -+ cifs_buf_release(smb_read_data); -+ smb_read_data = NULL; -+ } -+ } -+ } -+ if ((rc < 0) || (smb_read_data == NULL)) { -+ cFYI(1,("Read error in readpages: %d",rc)); -+ /* clean up remaing pages off list */ -+ while (!list_empty(page_list) && (i < num_pages)) { -+ page = list_entry(page_list->prev, struct page, lru); -+ list_del(&page->lru); -+ page_cache_release(page); -+ } -+ break; -+ } else if (bytes_read > 0) { -+ pSMBr = (struct smb_com_read_rsp *)smb_read_data; -+ cifs_copy_cache_pages(mapping, page_list, bytes_read, -+ smb_read_data + 4 /* RFC1001 hdr */ + -+ le16_to_cpu(pSMBr->DataOffset), &lru_pvec); -+ -+ i += bytes_read >> PAGE_CACHE_SHIFT; -+#ifdef CONFIG_CIFS_STATS -+ atomic_inc(&pTcon->num_reads); -+ spin_lock(&pTcon->stat_lock); -+ pTcon->bytes_read += bytes_read; -+ spin_unlock(&pTcon->stat_lock); -+#endif -+ if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { -+ cFYI(1,("Partial page %d of %d read to cache",i++,num_pages)); -+ -+ i++; /* account for partial page */ -+ -+ /* server copy of file can have smaller size than client */ -+ /* BB do we need to verify this common case ? this case is ok - -+ if we are at server EOF we will hit it on next read */ -+ -+ /* while(!list_empty(page_list) && (i < num_pages)) { -+ page = list_entry(page_list->prev,struct page, list); -+ list_del(&page->list); -+ page_cache_release(page); -+ } -+ break; */ -+ } -+ } else { -+ cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset)); -+ /* BB turn off caching and do new lookup on file size at server? */ -+ while (!list_empty(page_list) && (i < num_pages)) { -+ page = list_entry(page_list->prev, struct page, lru); -+ list_del(&page->lru); -+ page_cache_release(page); /* BB removeme - replace with zero of page? */ -+ } -+ break; -+ } -+ if(smb_read_data) { -+ cifs_buf_release(smb_read_data); -+ smb_read_data = NULL; -+ } -+ bytes_read = 0; -+ } -+ -+ pagevec_lru_add(&lru_pvec); -+ -+/* need to free smb_read_data buf before exit */ -+ if(smb_read_data) { -+ cifs_buf_release(smb_read_data); -+ smb_read_data = NULL; -+ } -+ -+ FreeXid(xid); -+ return rc; -+} -+#endif -+ -+static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset) -+{ -+ char * read_data; -+ int rc; -+ -+ page_cache_get(page); -+ read_data = kmap(page); -+ /* for reads over a certain size could initiate async read ahead */ -+ -+ rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset); -+ -+ if (rc < 0) -+ goto io_error; -+ else { -+ cFYI(1,("Bytes read %d ",rc)); -+ } -+ -+ file->f_dentry->d_inode->i_atime = CURRENT_TIME; -+ -+ if(PAGE_CACHE_SIZE > rc) { -+ memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc); -+ } -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ rc = 0; -+ -+io_error: -+ kunmap(page); -+ page_cache_release(page); -+ return rc; -+} -+ -+static int -+cifs_readpage(struct file *file, struct page *page) -+{ -+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; -+ int rc = -EACCES; -+ int xid; -+ -+ xid = GetXid(); -+ -+ if (file->private_data == NULL) { -+ FreeXid(xid); -+ return -EBADF; -+ } -+ -+ cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset)); -+ -+ rc = cifs_readpage_worker(file,page,&offset); -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) -+ unlock_page(page); -+#else -+ UnlockPage(page); -+#endif -+ -+ FreeXid(xid); -+ return rc; -+} -+ -+/* We do not want to update the file size from server for inodes -+ open for write - to avoid races with writepage extending -+ the file - in the future we could consider allowing -+ refreshing the inode only on increases in the file size -+ but this is tricky to do without racing with writebehind -+ page caching in the current Linux kernel design */ -+ -+int is_size_safe_to_change(struct cifsInodeInfo * cifsInode) -+{ -+ struct list_head *tmp; -+ struct list_head *tmp1; -+ struct cifsFileInfo *open_file = NULL; -+ int rc = TRUE; -+ -+ if(cifsInode == NULL) -+ return rc; -+ -+ read_lock(&GlobalSMBSeslock); -+ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { -+ open_file = list_entry(tmp,struct cifsFileInfo, flist); -+ if(open_file == NULL) -+ break; -+ if(open_file->closePend) -+ continue; -+ /* We check if file is open for writing, -+ BB we could supplement this with a check to see if file size -+ changes have been flushed to server - ie inode metadata dirty */ -+ if((open_file->pfile) && -+ ((open_file->pfile->f_flags & O_RDWR) || -+ (open_file->pfile->f_flags & O_WRONLY))) { -+ rc = FALSE; -+ break; -+ } -+ if(tmp->next == NULL) { -+ cFYI(1,("File instance %p removed",tmp)); -+ break; -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ return rc; -+} -+ -+ -+void -+fill_in_inode(struct inode *tmp_inode, -+ FILE_DIRECTORY_INFO * pfindData, int *pobject_type) -+{ -+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); -+ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); -+ -+ pfindData->ExtFileAttributes = -+ le32_to_cpu(pfindData->ExtFileAttributes); -+ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize); -+ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile); -+ cifsInfo->cifsAttrs = pfindData->ExtFileAttributes; -+ cifsInfo->time = jiffies; -+ -+ /* Linux can not store file creation time unfortunately so ignore it */ -+ tmp_inode->i_atime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); -+ tmp_inode->i_mtime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); -+ tmp_inode->i_ctime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); -+ /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ -+ /* 2767 perms - indicate mandatory locking */ -+ /* BB fill in uid and gid here? with help from winbind? -+ or retrieve from NTFS stream extended attribute */ -+ if(atomic_read(&cifsInfo->inUse) == 0) { -+ tmp_inode->i_uid = cifs_sb->mnt_uid; -+ tmp_inode->i_gid = cifs_sb->mnt_gid; -+ /* set default mode. will override for dirs below */ -+ tmp_inode->i_mode = cifs_sb->mnt_file_mode; -+ } -+ -+ cFYI(0, -+ ("CIFS FFIRST: Attributes came in as 0x%x", -+ pfindData->ExtFileAttributes)); -+ if (pfindData->ExtFileAttributes & ATTR_REPARSE) { -+ *pobject_type = DT_LNK; -+ /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */ -+ tmp_inode->i_mode |= S_IFLNK; -+ } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) { -+ *pobject_type = DT_DIR; -+ /* override default perms since we do not lock dirs */ -+ if(atomic_read(&cifsInfo->inUse) == 0) { -+ tmp_inode->i_mode = cifs_sb->mnt_dir_mode; -+ } -+ tmp_inode->i_mode |= S_IFDIR; -+ } else { -+ *pobject_type = DT_REG; -+ tmp_inode->i_mode |= S_IFREG; -+ if(pfindData->ExtFileAttributes & ATTR_READONLY) -+ tmp_inode->i_mode &= ~(S_IWUGO); -+ -+ }/* could add code here - to validate if device or weird share type? */ -+ -+ /* can not fill in nlink here as in qpathinfo version and Unx search */ -+ if(atomic_read(&cifsInfo->inUse) == 0) { -+ atomic_set(&cifsInfo->inUse,1); -+ } -+ if(is_size_safe_to_change(cifsInfo)) { -+ /* can not safely change the file size here if the -+ client is writing to it due to potential races */ -+ tmp_inode->i_size = pfindData->EndOfFile; -+ -+ /* 512 bytes (2**9) is the fake blocksize that must be used */ -+ /* for this calculation, even though the reported blocksize is larger */ -+ tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9; -+ } -+ -+ if (pfindData->AllocationSize < pfindData->EndOfFile) -+ cFYI(1, ("Possible sparse file: allocation size less than end of file ")); -+ cFYI(1, -+ ("File Size %ld and blocks %ld and blocksize %ld", -+ (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks, -+ tmp_inode->i_blksize)); -+ if (S_ISREG(tmp_inode->i_mode)) { -+ cFYI(1, (" File inode ")); -+ tmp_inode->i_op = &cifs_file_inode_ops; -+ tmp_inode->i_fop = &cifs_file_ops; -+ tmp_inode->i_data.a_ops = &cifs_addr_ops; -+ } else if (S_ISDIR(tmp_inode->i_mode)) { -+ cFYI(1, (" Directory inode")); -+ tmp_inode->i_op = &cifs_dir_inode_ops; -+ tmp_inode->i_fop = &cifs_dir_ops; -+ } else if (S_ISLNK(tmp_inode->i_mode)) { -+ cFYI(1, (" Symbolic Link inode ")); -+ tmp_inode->i_op = &cifs_symlink_inode_ops; -+ } else { -+ cFYI(1, (" Init special inode ")); -+ init_special_inode(tmp_inode, tmp_inode->i_mode, -+ kdev_t_to_nr(tmp_inode->i_rdev)); -+ } -+} -+ -+void -+unix_fill_in_inode(struct inode *tmp_inode, -+ FILE_UNIX_INFO * pfindData, int *pobject_type) -+{ -+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); -+ cifsInfo->time = jiffies; -+ atomic_inc(&cifsInfo->inUse); -+ -+ tmp_inode->i_atime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); -+ tmp_inode->i_mtime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime)); -+ tmp_inode->i_ctime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange)); -+ -+ tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); -+ pfindData->Type = le32_to_cpu(pfindData->Type); -+ if (pfindData->Type == UNIX_FILE) { -+ *pobject_type = DT_REG; -+ tmp_inode->i_mode |= S_IFREG; -+ } else if (pfindData->Type == UNIX_SYMLINK) { -+ *pobject_type = DT_LNK; -+ tmp_inode->i_mode |= S_IFLNK; -+ } else if (pfindData->Type == UNIX_DIR) { -+ *pobject_type = DT_DIR; -+ tmp_inode->i_mode |= S_IFDIR; -+ } else if (pfindData->Type == UNIX_CHARDEV) { -+ *pobject_type = DT_CHR; -+ tmp_inode->i_mode |= S_IFCHR; -+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), -+ le64_to_cpu(pfindData->DevMinor) & MINORMASK); -+ } else if (pfindData->Type == UNIX_BLOCKDEV) { -+ *pobject_type = DT_BLK; -+ tmp_inode->i_mode |= S_IFBLK; -+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), -+ le64_to_cpu(pfindData->DevMinor) & MINORMASK); -+ } else if (pfindData->Type == UNIX_FIFO) { -+ *pobject_type = DT_FIFO; -+ tmp_inode->i_mode |= S_IFIFO; -+ } else if (pfindData->Type == UNIX_SOCKET) { -+ *pobject_type = DT_SOCK; -+ tmp_inode->i_mode |= S_IFSOCK; -+ } -+ -+ tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); -+ tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); -+ tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); -+ -+ pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes); -+ if(is_size_safe_to_change(cifsInfo)) { -+ /* can not safely change the file size here if the -+ client is writing to it due to potential races */ -+ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile); -+ tmp_inode->i_size = pfindData->EndOfFile; -+ -+ /* 512 bytes (2**9) is the fake blocksize that must be used */ -+ /* for this calculation, not the real blocksize */ -+ tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9; -+ } -+ -+ if (S_ISREG(tmp_inode->i_mode)) { -+ cFYI(1, ("File inode")); -+ tmp_inode->i_op = &cifs_file_inode_ops; -+ tmp_inode->i_fop = &cifs_file_ops; -+ tmp_inode->i_data.a_ops = &cifs_addr_ops; -+ } else if (S_ISDIR(tmp_inode->i_mode)) { -+ cFYI(1, ("Directory inode")); -+ tmp_inode->i_op = &cifs_dir_inode_ops; -+ tmp_inode->i_fop = &cifs_dir_ops; -+ } else if (S_ISLNK(tmp_inode->i_mode)) { -+ cFYI(1, ("Symbolic Link inode")); -+ tmp_inode->i_op = &cifs_symlink_inode_ops; -+/* tmp_inode->i_fop = *//* do not need to set to anything */ -+ } else { -+ cFYI(1, ("Special inode")); -+ init_special_inode(tmp_inode, tmp_inode->i_mode, -+ kdev_t_to_nr(tmp_inode->i_rdev)); -+ } -+} -+ -+static void -+construct_dentry(struct qstr *qstring, struct file *file, -+ struct inode **ptmp_inode, struct dentry **pnew_dentry) -+{ -+ struct dentry *tmp_dentry; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct cifsInodeInfo *pCifsI; -+ -+ cFYI(1, ("For %s ", qstring->name)); -+ cifs_sb = CIFS_SB(file->f_dentry->d_sb); -+ pTcon = cifs_sb->tcon; -+ -+ qstring->hash = full_name_hash(qstring->name, qstring->len); -+ tmp_dentry = d_lookup(file->f_dentry, qstring); -+ if (tmp_dentry) { -+ cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode)); -+ *ptmp_inode = tmp_dentry->d_inode; -+ /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */ -+ if(*ptmp_inode == NULL) { -+ *ptmp_inode = new_inode(file->f_dentry->d_sb); -+ if(*ptmp_inode == NULL) -+ return; -+ d_instantiate(tmp_dentry, *ptmp_inode); -+ insert_inode_hash(*ptmp_inode); -+ pCifsI = CIFS_I(*ptmp_inode); -+ INIT_LIST_HEAD(&pCifsI->openFileList); -+ /* can not enable caching for this inode -+ until a file instance is open and we -+ can check the oplock flag on the open -+ response */ -+ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE; -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15)) -+ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ -+#endif -+ pCifsI->clientCanCacheRead = FALSE; -+ pCifsI->clientCanCacheAll = FALSE; -+ pCifsI->time = 0; -+ /* do not need to set cifs Attrs since -+ they are about to be overwritten -+ in fill_in_inode */ -+ atomic_set(&pCifsI->inUse, 0); -+ } -+ } else { -+ tmp_dentry = d_alloc(file->f_dentry, qstring); -+ if(tmp_dentry == NULL) { -+ cERROR(1,("Failed allocating dentry")); -+ return; -+ } -+ -+ if(ptmp_inode) { -+ *ptmp_inode = new_inode(file->f_dentry->d_sb); -+ if(*ptmp_inode == NULL) -+ return; -+ pCifsI = CIFS_I(*ptmp_inode); -+ insert_inode_hash(*ptmp_inode); -+ INIT_LIST_HEAD(&pCifsI->openFileList); -+ /* can not enable caching for this inode -+ until a file instance is open and we -+ can check the oplock flag on the open -+ response */ -+ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE; -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15)) -+ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ -+#endif -+ pCifsI->clientCanCacheRead = FALSE; -+ pCifsI->clientCanCacheAll = FALSE; -+ pCifsI->time = 0; -+ /* do not need to set cifs Attrs since -+ they are about to be overwritten -+ in fill_in_inode */ -+ atomic_set(&pCifsI->inUse, 0); -+ } -+ tmp_dentry->d_op = &cifs_dentry_ops; -+ d_instantiate(tmp_dentry, *ptmp_inode); -+ d_rehash(tmp_dentry); -+ } -+ -+ tmp_dentry->d_time = jiffies; -+ *pnew_dentry = tmp_dentry; -+} -+ -+static void reset_resume_key(struct file * dir_file, -+ unsigned char * filename, -+ unsigned int len,int Unicode,struct nls_table * nls_tab) { -+ struct cifsFileInfo *cifsFile; -+ -+ cifsFile = (struct cifsFileInfo *)dir_file->private_data; -+ if(cifsFile == NULL) -+ return; -+ if(cifsFile->search_resume_name) { -+ kfree(cifsFile->search_resume_name); -+ } -+ -+ if(Unicode) -+ len *= 2; -+ cifsFile->resume_name_length = len; -+ -+ cifsFile->search_resume_name = -+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL); -+ -+ if(cifsFile->search_resume_name == NULL) { -+ cERROR(1,("failed new resume key allocate, length %d", -+ cifsFile->resume_name_length)); -+ return; -+ } -+ if(Unicode) -+ cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name, -+ filename, len, nls_tab); -+ else -+ memcpy(cifsFile->search_resume_name, filename, -+ cifsFile->resume_name_length); -+ cFYI(1,("Reset resume key to: %s with len %d",filename,len)); -+ return; -+} -+ -+ -+ -+static int -+cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData, -+ struct file *file, filldir_t filldir, void *direntry) -+{ -+ struct inode *tmp_inode; -+ struct dentry *tmp_dentry; -+ int object_type,rc; -+ -+ pqstring->name = pfindData->FileName; -+ pqstring->len = pfindData->FileNameLength; -+ -+ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); -+ if((tmp_inode == NULL) || (tmp_dentry == NULL)) { -+ return -ENOMEM; -+ } -+ fill_in_inode(tmp_inode, pfindData, &object_type); -+ rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos, -+ tmp_inode->i_ino, object_type); -+ if(rc) { -+ /* due to readdir error we need to recalculate resume -+ key so next readdir will restart on right entry */ -+ cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName)); -+ } -+ dput(tmp_dentry); -+ return rc; -+} -+ -+static int -+cifs_filldir_unix(struct qstr *pqstring, -+ FILE_UNIX_INFO * pUnixFindData, struct file *file, -+ filldir_t filldir, void *direntry) -+{ -+ struct inode *tmp_inode; -+ struct dentry *tmp_dentry; -+ int object_type, rc; -+ -+ pqstring->name = pUnixFindData->FileName; -+ pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF); -+ -+ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); -+ if((tmp_inode == NULL) || (tmp_dentry == NULL)) { -+ return -ENOMEM; -+ } -+ -+ unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type); -+ rc = filldir(direntry, pUnixFindData->FileName, pqstring->len, -+ file->f_pos, tmp_inode->i_ino, object_type); -+ if(rc) { -+ /* due to readdir error we need to recalculate resume -+ key so next readdir will restart on right entry */ -+ cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName)); -+ } -+ dput(tmp_dentry); -+ return rc; -+} -+ -+int -+cifs_readdir(struct file *file, void *direntry, filldir_t filldir) -+{ -+ int rc = 0; -+ int xid; -+ int Unicode = FALSE; -+ int UnixSearch = FALSE; -+ unsigned int bufsize, i; -+ __u16 searchHandle; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct cifsFileInfo *cifsFile = NULL; -+ char *full_path = NULL; -+ char *data; -+ struct qstr qstring; -+ T2_FFIRST_RSP_PARMS findParms; -+ T2_FNEXT_RSP_PARMS findNextParms; -+ FILE_DIRECTORY_INFO *pfindData; -+ FILE_DIRECTORY_INFO *lastFindData; -+ FILE_UNIX_INFO *pfindDataUnix; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(file->f_dentry->d_sb); -+ pTcon = cifs_sb->tcon; -+ bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; -+ if(bufsize > CIFS_MAX_MSGSIZE) { -+ FreeXid(xid); -+ return -EIO; -+ } -+ data = kmalloc(bufsize, GFP_KERNEL); -+ pfindData = (FILE_DIRECTORY_INFO *) data; -+ -+ if(file->f_dentry == NULL) { -+ FreeXid(xid); -+ return -EIO; -+ } -+ down(&file->f_dentry->d_sb->s_vfs_rename_sem); -+ full_path = build_wildcard_path_from_dentry(file->f_dentry); -+ up(&file->f_dentry->d_sb->s_vfs_rename_sem); -+ -+ -+ cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); -+ -+ switch ((int) file->f_pos) { -+ case 0: -+ if (filldir(direntry, ".", 1, file->f_pos, -+ file->f_dentry->d_inode->i_ino, DT_DIR) < 0) { -+ cERROR(1, ("Filldir for current dir failed ")); -+ break; -+ } -+ file->f_pos++; -+ /* fallthrough */ -+ case 1: -+ if (filldir(direntry, "..", 2, file->f_pos, -+ file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { -+ cERROR(1, ("Filldir for parent dir failed ")); -+ break; -+ } -+ file->f_pos++; -+ /* fallthrough */ -+ case 2: -+ if (file->private_data != NULL) { -+ cifsFile = -+ (struct cifsFileInfo *) file->private_data; -+ if (cifsFile->endOfSearch) { -+ if(cifsFile->emptyDir) { -+ cFYI(1, ("End of search, empty dir")); -+ rc = 0; -+ break; -+ } -+ } else { -+ cifsFile->invalidHandle = TRUE; -+ CIFSFindClose(xid, pTcon, cifsFile->netfid); -+ } -+ if(cifsFile->search_resume_name) { -+ kfree(cifsFile->search_resume_name); -+ cifsFile->search_resume_name = NULL; -+ } -+ } -+ rc = CIFSFindFirst(xid, pTcon, full_path, pfindData, -+ &findParms, cifs_sb->local_nls, -+ &Unicode, &UnixSearch); -+ cFYI(1, ("Count: %d End: %d ", findParms.SearchCount, -+ findParms.EndofSearch)); -+ -+ if (rc == 0) { -+ searchHandle = findParms.SearchHandle; -+ if(file->private_data == NULL) -+ file->private_data = -+ kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL); -+ if (file->private_data) { -+ memset(file->private_data, 0, -+ sizeof (struct cifsFileInfo)); -+ cifsFile = -+ (struct cifsFileInfo *) file->private_data; -+ cifsFile->netfid = searchHandle; -+ cifsFile->invalidHandle = FALSE; -+ init_MUTEX(&cifsFile->fh_sem); -+ } else { -+ rc = -ENOMEM; -+ break; -+ } -+ -+ renew_parental_timestamps(file->f_dentry); -+ lastFindData = -+ (FILE_DIRECTORY_INFO *) ((char *) pfindData + -+ findParms.LastNameOffset); -+ if((char *)lastFindData > (char *)pfindData + bufsize) { -+ cFYI(1,("last search entry past end of packet")); -+ rc = -EIO; -+ break; -+ } -+ /* Offset of resume key same for levels 257 and 514 */ -+ cifsFile->resume_key = lastFindData->FileIndex; -+ if(UnixSearch == FALSE) { -+ cifsFile->resume_name_length = -+ le32_to_cpu(lastFindData->FileNameLength); -+ if(cifsFile->resume_name_length > bufsize - 64) { -+ cFYI(1,("Illegal resume file name length %d", -+ cifsFile->resume_name_length)); -+ rc = -ENOMEM; -+ break; -+ } -+ cifsFile->search_resume_name = -+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL); -+ cFYI(1,("Last file: %s with name %d bytes long", -+ lastFindData->FileName, -+ cifsFile->resume_name_length)); -+ memcpy(cifsFile->search_resume_name, -+ lastFindData->FileName, -+ cifsFile->resume_name_length); -+ } else { -+ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData; -+ if (Unicode == TRUE) { -+ for(i=0;(pfindDataUnix->FileName[i] -+ | pfindDataUnix->FileName[i+1]); -+ i+=2) { -+ if(i > bufsize-64) -+ break; -+ } -+ cifsFile->resume_name_length = i + 2; -+ } else { -+ cifsFile->resume_name_length = -+ strnlen(pfindDataUnix->FileName, -+ bufsize-63); -+ } -+ if(cifsFile->resume_name_length > bufsize - 64) { -+ cFYI(1,("Illegal resume file name length %d", -+ cifsFile->resume_name_length)); -+ rc = -ENOMEM; -+ break; -+ } -+ cifsFile->search_resume_name = -+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL); -+ cFYI(1,("Last file: %s with name %d bytes long", -+ pfindDataUnix->FileName, -+ cifsFile->resume_name_length)); -+ memcpy(cifsFile->search_resume_name, -+ pfindDataUnix->FileName, -+ cifsFile->resume_name_length); -+ } -+ for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) { -+ if (UnixSearch == FALSE) { -+ pfindData->FileNameLength = -+ le32_to_cpu(pfindData->FileNameLength); -+ if (Unicode == TRUE) -+ pfindData->FileNameLength = -+ cifs_strfromUCS_le -+ (pfindData->FileName, -+ (wchar_t *) -+ pfindData->FileName, -+ (pfindData-> -+ FileNameLength) / 2, -+ cifs_sb->local_nls); -+ qstring.len = pfindData->FileNameLength; -+ if (((qstring.len != 1) -+ || (pfindData->FileName[0] != '.')) -+ && ((qstring.len != 2) -+ || (pfindData-> -+ FileName[0] != '.') -+ || (pfindData-> -+ FileName[1] != '.'))) { -+ if(cifs_filldir(&qstring, -+ pfindData, -+ file, filldir, -+ direntry)) { -+ /* do not end search if -+ kernel not ready to take -+ remaining entries yet */ -+ reset_resume_key(file, pfindData->FileName,qstring.len, -+ Unicode, cifs_sb->local_nls); -+ findParms.EndofSearch = 0; -+ break; -+ } -+ file->f_pos++; -+ } -+ } else { /* UnixSearch */ -+ pfindDataUnix = -+ (FILE_UNIX_INFO *) pfindData; -+ if (Unicode == TRUE) -+ qstring.len = -+ cifs_strfromUCS_le -+ (pfindDataUnix->FileName, -+ (wchar_t *) -+ pfindDataUnix->FileName, -+ MAX_PATHCONF, -+ cifs_sb->local_nls); -+ else -+ qstring.len = -+ strnlen(pfindDataUnix-> -+ FileName, -+ MAX_PATHCONF); -+ if (((qstring.len != 1) -+ || (pfindDataUnix-> -+ FileName[0] != '.')) -+ && ((qstring.len != 2) -+ || (pfindDataUnix-> -+ FileName[0] != '.') -+ || (pfindDataUnix-> -+ FileName[1] != '.'))) { -+ if(cifs_filldir_unix(&qstring, -+ pfindDataUnix, -+ file, -+ filldir, -+ direntry)) { -+ /* do not end search if -+ kernel not ready to take -+ remaining entries yet */ -+ findParms.EndofSearch = 0; -+ reset_resume_key(file, pfindDataUnix->FileName, -+ qstring.len,Unicode,cifs_sb->local_nls); -+ break; -+ } -+ file->f_pos++; -+ } -+ } -+ /* works also for Unix ff struct since first field of both */ -+ pfindData = -+ (FILE_DIRECTORY_INFO *) ((char *) pfindData -+ + le32_to_cpu(pfindData->NextEntryOffset)); -+ /* BB also should check to make sure that pointer is not beyond the end of the SMB */ -+ /* if(pfindData > lastFindData) rc = -EIO; break; */ -+ } /* end for loop */ -+ if ((findParms.EndofSearch != 0) && cifsFile) { -+ cifsFile->endOfSearch = TRUE; -+ if(findParms.SearchCount == 2) -+ cifsFile->emptyDir = TRUE; -+ } -+ } else { -+ if (cifsFile) -+ cifsFile->endOfSearch = TRUE; -+ /* unless parent directory gone do not return error */ -+ rc = 0; -+ } -+ break; -+ default: -+ if (file->private_data == NULL) { -+ rc = -EBADF; -+ cFYI(1, -+ ("Readdir on closed srch, pos = %lld", -+ file->f_pos)); -+ } else { -+ cifsFile = (struct cifsFileInfo *) file->private_data; -+ if (cifsFile->endOfSearch) { -+ rc = 0; -+ cFYI(1, ("End of search ")); -+ break; -+ } -+ searchHandle = cifsFile->netfid; -+ rc = CIFSFindNext(xid, pTcon, pfindData, -+ &findNextParms, searchHandle, -+ cifsFile->search_resume_name, -+ cifsFile->resume_name_length, -+ cifsFile->resume_key, -+ &Unicode, &UnixSearch); -+ cFYI(1,("Count: %d End: %d ", -+ findNextParms.SearchCount, -+ findNextParms.EndofSearch)); -+ if ((rc == 0) && (findNextParms.SearchCount != 0)) { -+ /* BB save off resume key, key name and name length */ -+ lastFindData = -+ (FILE_DIRECTORY_INFO *) ((char *) pfindData -+ + findNextParms.LastNameOffset); -+ if((char *)lastFindData > (char *)pfindData + bufsize) { -+ cFYI(1,("last search entry past end of packet")); -+ rc = -EIO; -+ break; -+ } -+ /* Offset of resume key same for levels 257 and 514 */ -+ cifsFile->resume_key = lastFindData->FileIndex; -+ -+ if(UnixSearch == FALSE) { -+ cifsFile->resume_name_length = -+ le32_to_cpu(lastFindData->FileNameLength); -+ if(cifsFile->resume_name_length > bufsize - 64) { -+ cFYI(1,("Illegal resume file name length %d", -+ cifsFile->resume_name_length)); -+ rc = -ENOMEM; -+ break; -+ } -+ /* Free the memory allocated by previous findfirst -+ or findnext call - we can not reuse the memory since -+ the resume name may not be same string length */ -+ if(cifsFile->search_resume_name) -+ kfree(cifsFile->search_resume_name); -+ cifsFile->search_resume_name = -+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL); -+ cFYI(1,("Last file: %s with name %d bytes long", -+ lastFindData->FileName, -+ cifsFile->resume_name_length)); -+ memcpy(cifsFile->search_resume_name, -+ lastFindData->FileName, -+ cifsFile->resume_name_length); -+ } else { -+ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData; -+ if (Unicode == TRUE) { -+ for(i=0;(pfindDataUnix->FileName[i] -+ | pfindDataUnix->FileName[i+1]); -+ i+=2) { -+ if(i > bufsize-64) -+ break; -+ } -+ cifsFile->resume_name_length = i + 2; -+ } else { -+ cifsFile->resume_name_length = -+ strnlen(pfindDataUnix-> -+ FileName, -+ MAX_PATHCONF); -+ } -+ if(cifsFile->resume_name_length > bufsize - 64) { -+ cFYI(1,("Illegal resume file name length %d", -+ cifsFile->resume_name_length)); -+ rc = -ENOMEM; -+ break; -+ } -+ /* Free the memory allocated by previous findfirst -+ or findnext call - we can not reuse the memory since -+ the resume name may not be same string length */ -+ if(cifsFile->search_resume_name) -+ kfree(cifsFile->search_resume_name); -+ cifsFile->search_resume_name = -+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL); -+ cFYI(1,("fnext last file: %s with name %d bytes long", -+ pfindDataUnix->FileName, -+ cifsFile->resume_name_length)); -+ memcpy(cifsFile->search_resume_name, -+ pfindDataUnix->FileName, -+ cifsFile->resume_name_length); -+ } -+ -+ for (i = 0; i < findNextParms.SearchCount; i++) { -+ pfindData->FileNameLength = -+ le32_to_cpu(pfindData-> -+ FileNameLength); -+ if (UnixSearch == FALSE) { -+ if (Unicode == TRUE) -+ pfindData->FileNameLength = -+ cifs_strfromUCS_le -+ (pfindData->FileName, -+ (wchar_t *) -+ pfindData->FileName, -+ (pfindData->FileNameLength)/ 2, -+ cifs_sb->local_nls); -+ qstring.len = -+ pfindData->FileNameLength; -+ if (((qstring.len != 1) -+ || (pfindData->FileName[0] != '.')) -+ && ((qstring.len != 2) -+ || (pfindData->FileName[0] != '.') -+ || (pfindData->FileName[1] != -+ '.'))) { -+ if(cifs_filldir -+ (&qstring, -+ pfindData, -+ file, filldir, -+ direntry)) { -+ /* do not end search if -+ kernel not ready to take -+ remaining entries yet */ -+ findNextParms.EndofSearch = 0; -+ reset_resume_key(file, pfindData->FileName,qstring.len, -+ Unicode,cifs_sb->local_nls); -+ break; -+ } -+ file->f_pos++; -+ } -+ } else { /* UnixSearch */ -+ pfindDataUnix = -+ (FILE_UNIX_INFO *) -+ pfindData; -+ if (Unicode == TRUE) -+ qstring.len = -+ cifs_strfromUCS_le -+ (pfindDataUnix->FileName, -+ (wchar_t *) -+ pfindDataUnix->FileName, -+ MAX_PATHCONF, -+ cifs_sb->local_nls); -+ else -+ qstring.len = -+ strnlen -+ (pfindDataUnix-> -+ FileName, -+ MAX_PATHCONF); -+ if (((qstring.len != 1) -+ || (pfindDataUnix-> -+ FileName[0] != '.')) -+ && ((qstring.len != 2) -+ || (pfindDataUnix-> -+ FileName[0] != '.') -+ || (pfindDataUnix-> -+ FileName[1] != -+ '.'))) { -+ if(cifs_filldir_unix -+ (&qstring, -+ pfindDataUnix, -+ file, filldir, -+ direntry)) { -+ /* do not end search if -+ kernel not ready to take -+ remaining entries yet */ -+ findNextParms.EndofSearch = 0; -+ reset_resume_key(file, pfindDataUnix->FileName,qstring.len, -+ Unicode,cifs_sb->local_nls); -+ break; -+ } -+ file->f_pos++; -+ } -+ } -+ pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* works also for Unix find struct since this is the first field of both */ -+ /* BB also should check to make sure that pointer is not beyond the end of the SMB */ -+ } /* end for loop */ -+ if (findNextParms.EndofSearch != 0) { -+ cifsFile->endOfSearch = TRUE; -+ } -+ } else { -+ cifsFile->endOfSearch = TRUE; -+ rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */ -+ } -+ } -+ } /* end switch */ -+ if (data) -+ kfree(data); -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ -+ return rc; -+} -+int cifs_prepare_write(struct file *file, struct page *page, -+ unsigned from, unsigned to) -+{ -+ int rc = 0; -+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; -+ cFYI(1,("prepare write for page %p from %d to %d",page,from,to)); -+ if (!Page_Uptodate(page)) { -+ /* if (to - from != PAGE_CACHE_SIZE) { -+ void *kaddr = kmap_atomic(page, KM_USER0); -+ memset(kaddr, 0, from); -+ memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); -+ flush_dcache_page(page); -+ kunmap_atomic(kaddr, KM_USER0); -+ } */ -+ /* If we are writing a full page it will be up to date, -+ no need to read from the server */ -+ if((to==PAGE_CACHE_SIZE) && (from == 0)) -+ SetPageUptodate(page); -+ -+ /* might as well read a page, it is fast enough */ -+ if((file->f_flags & O_ACCMODE) != O_WRONLY) { -+ rc = cifs_readpage_worker(file,page,&offset); -+ } else { -+ /* should we try using another -+ file handle if there is one - how would we lock it -+ to prevent close of that handle racing with this read? */ -+ /* In any case this will be written out by commit_write */ -+ } -+ } -+ -+ /* BB should we pass any errors back? e.g. if we do not have read access to the file */ -+ return 0; -+} -+ -+ -+struct address_space_operations cifs_addr_ops = { -+ .readpage = cifs_readpage, -+/* .readpages = cifs_readpages, */ -+ .writepage = cifs_writepage, -+ .prepare_write = cifs_prepare_write, -+ .commit_write = cifs_commit_write, -+ .sync_page = cifs_sync_page, -+ /*.direct_IO = */ -+}; ---- /dev/null -+++ b/fs/cifs/inode.c -@@ -0,0 +1,1079 @@ -+/* -+ * fs/cifs/inode.c -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2003 -+ * 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 -+ */ -+#include <linux/fs.h> -+#include <linux/stat.h> -+#include <linux/pagemap.h> -+#include <linux/version.h> -+#include <asm/div64.h> -+#include "cifsfs.h" -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_debug.h" -+#include "cifs_fs_sb.h" -+ -+extern int is_size_safe_to_change(struct cifsInodeInfo *); -+ -+struct inode * get_cifs_inode(struct super_block * sb) -+{ -+ struct inode * newinode; -+ newinode = new_inode(sb); -+ cFYI(1,("got new inode %p",newinode)); -+ if(newinode) { -+ struct cifsInodeInfo * cifsInfo = CIFS_I(newinode); -+ cifsInfo->clientCanCacheRead = FALSE; -+ cifsInfo->clientCanCacheAll = FALSE; -+ INIT_LIST_HEAD(&cifsInfo->openFileList); -+ cifsInfo->cifsAttrs = 0x20; /* default */ -+ newinode->i_blksize = CIFS_MAX_MSGSIZE; -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15)) -+ newinode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ -+#endif -+ atomic_set(&cifsInfo->inUse, 0); -+ cifsInfo->time = 0; -+ insert_inode_hash(newinode); -+ } -+ return newinode; -+ -+} -+ -+int -+cifs_get_inode_info_unix(struct inode **pinode, -+ const unsigned char *search_path, -+ struct super_block *sb,int xid) -+{ -+ int rc = 0; -+ FILE_UNIX_BASIC_INFO findData; -+ struct cifsTconInfo *pTcon; -+ struct inode *inode; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -+ char *tmp_path; -+ -+ pTcon = cifs_sb->tcon; -+ cFYI(1, (" Getting info on %s ", search_path)); -+ /* we could have done a find first instead but this returns more info */ -+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, -+ cifs_sb->local_nls); -+ /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */ -+ if (rc) { -+ if (rc == -EREMOTE) { -+ tmp_path = -+ kmalloc(strnlen -+ (pTcon->treeName, -+ MAX_TREE_SIZE + 1) + -+ strnlen(search_path, MAX_PATHCONF) + 1, -+ GFP_KERNEL); -+ if (tmp_path == NULL) { -+ return -ENOMEM; -+ } -+ /* have to skip first of the double backslash of UNC name */ -+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); -+ strncat(tmp_path, search_path, MAX_PATHCONF); -+ rc = connect_to_dfs_path(xid, pTcon->ses, -+ /* treename + */ tmp_path, -+ cifs_sb->local_nls); -+ kfree(tmp_path); -+ -+ /* BB fix up inode etc. */ -+ } else if (rc) { -+ return rc; -+ } -+ -+ } else { -+ struct cifsInodeInfo *cifsInfo; -+ -+ /* get new inode */ -+ if (*pinode == NULL) { -+ *pinode = get_cifs_inode(sb); -+ } -+ if(*pinode == NULL) { -+ return -ENOMEM; -+ } -+ -+ inode = *pinode; -+ cifsInfo = CIFS_I(inode); -+ -+ cFYI(1, (" Old time %ld ", cifsInfo->time)); -+ cifsInfo->time = jiffies; -+ cFYI(1, (" New time %ld ", cifsInfo->time)); -+ atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */ -+ -+ inode->i_atime = -+ cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime)); -+ inode->i_mtime = -+ cifs_NTtimeToUnix(le64_to_cpu -+ (findData.LastModificationTime)); -+ inode->i_ctime = -+ cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); -+ inode->i_mode = le64_to_cpu(findData.Permissions); -+ findData.Type = le32_to_cpu(findData.Type); -+ if (findData.Type == UNIX_FILE) { -+ inode->i_mode |= S_IFREG; -+ } else if (findData.Type == UNIX_SYMLINK) { -+ inode->i_mode |= S_IFLNK; -+ } else if (findData.Type == UNIX_DIR) { -+ inode->i_mode |= S_IFDIR; -+ } else if (findData.Type == UNIX_CHARDEV) { -+ inode->i_mode |= S_IFCHR; -+ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor), -+ le64_to_cpu(findData.DevMinor) & MINORMASK); -+ } else if (findData.Type == UNIX_BLOCKDEV) { -+ inode->i_mode |= S_IFBLK; -+ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor), -+ le64_to_cpu(findData.DevMinor) & MINORMASK); -+ } else if (findData.Type == UNIX_FIFO) { -+ inode->i_mode |= S_IFIFO; -+ } else if (findData.Type == UNIX_SOCKET) { -+ inode->i_mode |= S_IFSOCK; -+ } -+ inode->i_uid = le64_to_cpu(findData.Uid); -+ inode->i_gid = le64_to_cpu(findData.Gid); -+ inode->i_nlink = le64_to_cpu(findData.Nlinks); -+ findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes); -+ findData.EndOfFile = le64_to_cpu(findData.EndOfFile); -+ -+ if(is_size_safe_to_change(cifsInfo)) { -+ /* can not safely change the file size here if the -+ client is writing to it due to potential races */ -+ inode->i_size = findData.EndOfFile; -+/* blksize needs to be multiple of two. So safer to default to blksize -+ and blkbits set in superblock so 2**blkbits and blksize will match */ -+/* inode->i_blksize = -+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ -+ -+ /* This seems incredibly stupid but it turns out that -+ i_blocks is not related to (i_size / i_blksize), instead a -+ size of 512 is required to be used for calculating num blocks */ -+ -+ -+/* inode->i_blocks = -+ (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/ -+ -+ /* 512 bytes (2**9) is the fake blocksize that must be used */ -+ /* for this calculation */ -+ inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9; -+ } -+ -+ if (findData.NumOfBytes < findData.EndOfFile) -+ cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file ")); -+ cFYI(1, -+ ("Size %ld and blocks %ld ", -+ (unsigned long) inode->i_size, inode->i_blocks)); -+ if (S_ISREG(inode->i_mode)) { -+ cFYI(1, (" File inode ")); -+ inode->i_op = &cifs_file_inode_ops; -+ inode->i_fop = &cifs_file_ops; -+ inode->i_data.a_ops = &cifs_addr_ops; -+ } else if (S_ISDIR(inode->i_mode)) { -+ cFYI(1, (" Directory inode")); -+ inode->i_op = &cifs_dir_inode_ops; -+ inode->i_fop = &cifs_dir_ops; -+ } else if (S_ISLNK(inode->i_mode)) { -+ cFYI(1, (" Symbolic Link inode ")); -+ inode->i_op = &cifs_symlink_inode_ops; -+/* tmp_inode->i_fop = *//* do not need to set to anything */ -+ } else { -+ cFYI(1, (" Init special inode ")); -+ init_special_inode(inode, inode->i_mode, -+ kdev_t_to_nr(inode->i_rdev)); -+ } -+ } -+ return rc; -+} -+ -+int -+cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, -+ FILE_ALL_INFO * pfindData, struct super_block *sb, int xid) -+{ -+ int rc = 0; -+ struct cifsTconInfo *pTcon; -+ struct inode *inode; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -+ char *tmp_path; -+ char *buf = NULL; -+ -+ pTcon = cifs_sb->tcon; -+ cFYI(1,("Getting info on %s ", search_path)); -+ -+ if((pfindData == NULL) && (*pinode != NULL)) { -+ if(CIFS_I(*pinode)->clientCanCacheRead) { -+ cFYI(1,("No need to revalidate inode sizes on cached file ")); -+ return rc; -+ } -+ } -+ -+ /* if file info not passed in then get it from server */ -+ if(pfindData == NULL) { -+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); -+ pfindData = (FILE_ALL_INFO *)buf; -+ /* could do find first instead but this returns more info */ -+ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, -+ cifs_sb->local_nls); -+ } -+ /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ -+ if (rc) { -+ if (rc == -EREMOTE) { -+ tmp_path = -+ kmalloc(strnlen -+ (pTcon->treeName, -+ MAX_TREE_SIZE + 1) + -+ strnlen(search_path, MAX_PATHCONF) + 1, -+ GFP_KERNEL); -+ if (tmp_path == NULL) { -+ if(buf) -+ kfree(buf); -+ return -ENOMEM; -+ } -+ -+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); -+ strncat(tmp_path, search_path, MAX_PATHCONF); -+ rc = connect_to_dfs_path(xid, pTcon->ses, -+ /* treename + */ tmp_path, -+ cifs_sb->local_nls); -+ kfree(tmp_path); -+ /* BB fix up inode etc. */ -+ } else if (rc) { -+ if(buf) -+ kfree(buf); -+ return rc; -+ } -+ } else { -+ struct cifsInodeInfo *cifsInfo; -+ -+ /* get new inode */ -+ if (*pinode == NULL) { -+ *pinode = get_cifs_inode(sb); -+ } -+ if(*pinode == NULL) -+ return -ENOMEM; -+ inode = *pinode; -+ cifsInfo = CIFS_I(inode); -+ pfindData->Attributes = le32_to_cpu(pfindData->Attributes); -+ cifsInfo->cifsAttrs = pfindData->Attributes; -+ cFYI(1, (" Old time %ld ", cifsInfo->time)); -+ cifsInfo->time = jiffies; -+ cFYI(1, (" New time %ld ", cifsInfo->time)); -+ -+/* blksize needs to be multiple of two. So safer to default to blksize -+ and blkbits set in superblock so 2**blkbits and blksize will match */ -+/* inode->i_blksize = -+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ -+ -+ /* Linux can not store file creation time unfortunately so we ignore it */ -+ inode->i_atime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); -+ inode->i_mtime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); -+ inode->i_ctime = -+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); -+ cFYI(0, -+ (" Attributes came in as 0x%x ", pfindData->Attributes)); -+ -+ /* set default mode. will override for dirs below */ -+ if(atomic_read(&cifsInfo->inUse) == 0) -+ /* new inode, can safely set these fields */ -+ inode->i_mode = cifs_sb->mnt_file_mode; -+ -+ if (pfindData->Attributes & ATTR_REPARSE) { -+ /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */ -+ inode->i_mode |= S_IFLNK; -+ } else if (pfindData->Attributes & ATTR_DIRECTORY) { -+ /* override default perms since we do not do byte range locking on dirs */ -+ inode->i_mode = cifs_sb->mnt_dir_mode; -+ inode->i_mode |= S_IFDIR; -+ } else { -+ inode->i_mode |= S_IFREG; -+ /* treat the dos attribute of read-only as read-only mode e.g. 555 */ -+ if(cifsInfo->cifsAttrs & ATTR_READONLY) -+ inode->i_mode &= ~(S_IWUGO); -+ /* BB add code here - validate if device or weird share or device type? */ -+ } -+ if(is_size_safe_to_change(cifsInfo)) { -+ /* can not safely change the file size here if the -+ client is writing to it due to potential races */ -+ inode->i_size = le64_to_cpu(pfindData->EndOfFile); -+ -+ /* 512 bytes (2**9) is the fake blocksize that must be used */ -+ /* for this calculation */ -+ inode->i_blocks = (512 - 1 + pfindData->AllocationSize) -+ >> 9; -+ } -+ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize); -+ -+ cFYI(1, -+ (" Size %ld and blocks %ld ", -+ (unsigned long) inode->i_size, inode->i_blocks)); -+ inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); -+ -+ /* BB fill in uid and gid here? with help from winbind? -+ or retrieve from NTFS stream extended attribute */ -+ if(atomic_read(&cifsInfo->inUse) == 0) { -+ inode->i_uid = cifs_sb->mnt_uid; -+ inode->i_gid = cifs_sb->mnt_gid; -+ /* set so we do not keep refreshing these fields with -+ bad data after user has changed them in memory */ -+ atomic_set(&cifsInfo->inUse,1); -+ } -+ -+ if (S_ISREG(inode->i_mode)) { -+ cFYI(1, (" File inode ")); -+ inode->i_op = &cifs_file_inode_ops; -+ inode->i_fop = &cifs_file_ops; -+ inode->i_data.a_ops = &cifs_addr_ops; -+ } else if (S_ISDIR(inode->i_mode)) { -+ cFYI(1, (" Directory inode ")); -+ inode->i_op = &cifs_dir_inode_ops; -+ inode->i_fop = &cifs_dir_ops; -+ } else if (S_ISLNK(inode->i_mode)) { -+ cFYI(1, (" Symbolic Link inode ")); -+ inode->i_op = &cifs_symlink_inode_ops; -+ } else { -+ init_special_inode(inode, inode->i_mode, -+ kdev_t_to_nr(inode->i_rdev)); -+ } -+ } -+ if(buf) -+ kfree(buf); -+ return rc; -+} -+ -+void -+cifs_read_inode(struct inode *inode) -+{ /* gets root inode */ -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsInodeInfo *cifs_inode; -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ xid = GetXid(); -+ -+ cifs_inode = CIFS_I(inode); -+ cifs_inode->cifsAttrs = ATTR_DIRECTORY; -+ atomic_set(&cifs_inode->inUse, 0); -+ cifs_inode->time = 0; -+ inode->i_blksize = CIFS_MAX_MSGSIZE; -+ inode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ -+ -+ INIT_LIST_HEAD(&cifs_inode->openFileList); -+ -+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) -+ cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid); -+ else -+ cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid); -+ /* can not call macro FreeXid here since in a void func */ -+ _FreeXid(xid); -+} -+ -+int -+cifs_unlink(struct inode *inode, struct dentry *direntry) -+{ -+ int rc = 0; -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ struct cifsInodeInfo *cifsInode; -+ FILE_BASIC_INFO * pinfo_buf; -+ -+ cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode)); -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+/* Unlink can be called from rename so we can not grab -+ the sem here since we deadlock otherwise */ -+/* down(&direntry->d_sb->s_vfs_rename_sem);*/ -+ full_path = build_path_from_dentry(direntry); -+/* up(&direntry->d_sb->s_vfs_rename_sem);*/ -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); -+ -+ if (!rc) { -+ direntry->d_inode->i_nlink--; -+ } else if (rc == -ENOENT) { -+ d_drop(direntry); -+ } else if (rc == -ETXTBSY) { -+ int oplock = FALSE; -+ __u16 netfid; -+ -+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, -+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, -+ &netfid, &oplock, NULL, cifs_sb->local_nls); -+ if(rc==0) { -+ CIFSSMBRenameOpenFile(xid,pTcon,netfid, -+ NULL, cifs_sb->local_nls); -+ CIFSSMBClose(xid, pTcon, netfid); -+ direntry->d_inode->i_nlink--; -+ } -+ } else if (rc == -EACCES) { -+ /* try only if r/o attribute set in local lookup data? */ -+ pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL); -+ if(pinfo_buf) { -+ memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO)); -+ /* ATTRS set to normal clears r/o bit */ -+ pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); -+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf, -+ cifs_sb->local_nls); -+ kfree(pinfo_buf); -+ } -+ if(rc==0) { -+ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); -+ if (!rc) { -+ direntry->d_inode->i_nlink--; -+ } else if (rc == -ETXTBSY) { -+ int oplock = FALSE; -+ __u16 netfid; -+ -+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, -+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, -+ &netfid, &oplock, NULL, cifs_sb->local_nls); -+ if(rc==0) { -+ CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls); -+ CIFSSMBClose(xid, pTcon, netfid); -+ direntry->d_inode->i_nlink--; -+ } -+ /* BB if rc = -ETXTBUSY goto the rename logic BB */ -+ } -+ } -+ } -+ cifsInode = CIFS_I(direntry->d_inode); -+ cifsInode->time = 0; /* will force revalidate to get info when needed */ -+ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = -+ CURRENT_TIME; -+ cifsInode = CIFS_I(inode); -+ cifsInode->time = 0; /* force revalidate of dir as well */ -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) -+{ -+ int rc = 0; -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ struct inode *newinode = NULL; -+ -+ cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ down(&inode->i_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(direntry); -+ up(&inode->i_sb->s_vfs_rename_sem); -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ /* BB add setting the equivalent of mode via CreateX w/ACLs */ -+ rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); -+ if (rc) { -+ cFYI(1, ("cifs_mkdir returned 0x%x ", rc)); -+ d_drop(direntry); -+ } else { -+ inode->i_nlink++; -+ if (pTcon->ses->capabilities & CAP_UNIX) -+ rc = cifs_get_inode_info_unix(&newinode, full_path, -+ inode->i_sb,xid); -+ else -+ rc = cifs_get_inode_info(&newinode, full_path,NULL, -+ inode->i_sb,xid); -+ -+ direntry->d_op = &cifs_dentry_ops; -+ d_instantiate(direntry, newinode); -+ if(direntry->d_inode) -+ direntry->d_inode->i_nlink = 2; -+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) -+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, -+ (__u64)-1, -+ (__u64)-1, -+ 0 /* dev_t */, -+ cifs_sb->local_nls); -+ else { /* BB to be implemented via Windows secrty descriptors*/ -+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ -+ } -+ } -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ -+ return rc; -+} -+ -+int -+cifs_rmdir(struct inode *inode, struct dentry *direntry) -+{ -+ int rc = 0; -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ struct cifsInodeInfo *cifsInode; -+ -+ cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode)); -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ down(&inode->i_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(direntry); -+ up(&inode->i_sb->s_vfs_rename_sem); -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ -+ rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls); -+ -+ if (!rc) { -+ inode->i_nlink--; -+ direntry->d_inode->i_size = 0; -+ direntry->d_inode->i_nlink = 0; -+ } -+ -+ cifsInode = CIFS_I(direntry->d_inode); -+ cifsInode->time = 0; /* force revalidate to go get info when needed */ -+ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = -+ CURRENT_TIME; -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_rename(struct inode *source_inode, struct dentry *source_direntry, -+ struct inode *target_inode, struct dentry *target_direntry) -+{ -+ char *fromName; -+ char *toName; -+ struct cifs_sb_info *cifs_sb_source; -+ struct cifs_sb_info *cifs_sb_target; -+ struct cifsTconInfo *pTcon; -+ int xid; -+ int rc = 0; -+ -+ xid = GetXid(); -+ -+ cifs_sb_target = CIFS_SB(target_inode->i_sb); -+ cifs_sb_source = CIFS_SB(source_inode->i_sb); -+ pTcon = cifs_sb_source->tcon; -+ -+ if (pTcon != cifs_sb_target->tcon) { -+ FreeXid(xid); -+ return -EXDEV; /* BB actually could be allowed if same server, but -+ different share. Might eventually add support for this */ -+ } -+ -+ /* we already have the rename sem so we do not need -+ to grab it again here to protect the path integrity */ -+ fromName = build_path_from_dentry(source_direntry); -+ toName = build_path_from_dentry(target_direntry); -+ if((fromName == NULL) || (toName == NULL)) { -+ rc = -ENOMEM; -+ goto cifs_rename_exit; -+ } -+ -+ rc = CIFSSMBRename(xid, pTcon, fromName, toName, -+ cifs_sb_source->local_nls); -+ if(rc == -EEXIST) { -+ /* check if they are the same file -+ because rename of hardlinked files is a noop */ -+ FILE_UNIX_BASIC_INFO * info_buf_source; -+ FILE_UNIX_BASIC_INFO * info_buf_target; -+ -+ info_buf_source = -+ kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL); -+ if(info_buf_source != NULL) { -+ info_buf_target = info_buf_source+1; -+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, -+ info_buf_source, cifs_sb_source->local_nls); -+ if(rc == 0) { -+ rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName, -+ info_buf_target, -+ cifs_sb_target->local_nls); -+ } -+ if((rc == 0) && -+ (info_buf_source->UniqueId == -+ info_buf_target->UniqueId)) { -+ /* do not rename since the files are hardlinked -+ which is a noop */ -+ } else { -+ /* we either can not tell the files are hardlinked -+ (as with Windows servers) or files are not hardlinked -+ so delete the target manually before renaming to -+ follow POSIX rather than Windows semantics */ -+ cifs_unlink(target_inode, target_direntry); -+ rc = CIFSSMBRename(xid, pTcon, fromName, toName, -+ cifs_sb_source->local_nls); -+ } -+ kfree(info_buf_source); -+ } /* if we can not get memory just leave rc as EEXIST */ -+ } -+ -+ if((rc == -EIO)||(rc == -EEXIST)) { -+ int oplock = FALSE; -+ __u16 netfid; -+ -+ rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ, -+ CREATE_NOT_DIR, -+ &netfid, &oplock, NULL, cifs_sb_source->local_nls); -+ if(rc==0) { -+ CIFSSMBRenameOpenFile(xid,pTcon,netfid, -+ toName, cifs_sb_source->local_nls); -+ CIFSSMBClose(xid, pTcon, netfid); -+ } -+ } -+ -+cifs_rename_exit: -+ if (fromName) -+ kfree(fromName); -+ if (toName) -+ kfree(toName); -+ -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_revalidate(struct dentry *direntry) -+{ -+ int xid; -+ int rc = 0; -+ char *full_path; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsInodeInfo *cifsInode; -+ loff_t local_size; -+ time_t local_mtime; -+ int invalidate_inode = FALSE; -+ -+ if(direntry->d_inode == NULL) -+ return -ENOENT; -+ -+ cifsInode = CIFS_I(direntry->d_inode); -+ -+ if(cifsInode == NULL) -+ return -ENOENT; -+ -+ /* no sense revalidating inode info on file that no one can write */ -+ if(CIFS_I(direntry->d_inode)->clientCanCacheRead) -+ return rc; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(direntry->d_sb); -+ -+ /* can not safely grab the rename sem here if -+ rename calls revalidate since that would deadlock */ -+ full_path = build_path_from_dentry(direntry); -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ cFYI(1, -+ ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld", -+ full_path, direntry->d_inode, -+ direntry->d_inode->i_count.counter, direntry, -+ direntry->d_time, jiffies)); -+ -+ if (cifsInode->time == 0){ -+ /* was set to zero previously to force revalidate */ -+ } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) { -+ if((S_ISREG(direntry->d_inode->i_mode) == 0) || -+ (direntry->d_inode->i_nlink == 1)) { -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+ } else { -+ cFYI(1,("Have to revalidate file due to hardlinks")); -+ } -+ } -+ -+ /* save mtime and size */ -+ local_mtime = direntry->d_inode->i_mtime; -+ local_size = direntry->d_inode->i_size; -+ -+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) { -+ rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path, -+ direntry->d_sb,xid); -+ if(rc) { -+ cFYI(1,("error on getting revalidate info %d",rc)); -+/* if(rc != -ENOENT) -+ rc = 0; */ /* BB should we cache info on certain errors? */ -+ } -+ } else { -+ rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, -+ direntry->d_sb,xid); -+ if(rc) { -+ cFYI(1,("error on getting revalidate info %d",rc)); -+/* if(rc != -ENOENT) -+ rc = 0; */ /* BB should we cache info on certain errors? */ -+ } -+ } -+ /* should we remap certain errors, access denied?, to zero */ -+ -+ /* if not oplocked, we invalidate inode pages if mtime -+ or file size had changed on server */ -+ -+ if((local_mtime == direntry->d_inode->i_mtime) && -+ (local_size == direntry->d_inode->i_size)) { -+ cFYI(1,("cifs_revalidate - inode unchanged")); -+ } else { -+ /* file may have changed on server */ -+ if(cifsInode->clientCanCacheRead) { -+ /* no need to invalidate inode pages since we were -+ the only ones who could have modified the file and -+ the server copy is staler than ours */ -+ } else { -+ invalidate_inode = TRUE; -+ } -+ } -+ -+ /* can not grab this sem since kernel filesys locking -+ documentation indicates i_sem may be taken by the kernel -+ on lookup and rename which could deadlock if we grab -+ the i_sem here as well */ -+/* down(&direntry->d_inode->i_sem);*/ -+ /* need to write out dirty pages here */ -+ if(direntry->d_inode->i_mapping) { -+ /* do we need to lock inode until after invalidate completes below? */ -+ filemap_fdatasync(direntry->d_inode->i_mapping); -+ } -+ if(invalidate_inode) { -+ filemap_fdatawait(direntry->d_inode->i_mapping); -+ /* may eventually have to do this for open files too */ -+ if(list_empty(&(cifsInode->openFileList))) { -+ /* Has changed on server - flush read ahead pages */ -+ cFYI(1,("Invalidating read ahead data on closed file")); -+ invalidate_inode_pages(direntry->d_inode); -+ } -+ } -+/* up(&direntry->d_inode->i_sem);*/ -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ -+ return rc; -+} -+ -+/* int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) -+{ -+ int err = cifs_revalidate(dentry); -+ if (!err) -+ generic_fillattr(dentry->d_inode, stat); -+ return err; -+} */ -+ -+void -+cifs_truncate_file(struct inode *inode) -+{ /* BB remove - may not need this function after all BB */ -+ int xid; -+ int rc = -EIO; -+ int found = FALSE; -+ struct cifsFileInfo *open_file = NULL; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ struct cifsInodeInfo *cifsInode; -+ struct dentry *dirent; -+ struct list_head * tmp; -+ char *full_path = NULL; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ /* To avoid spurious oplock breaks from server, in the case -+ of inodes that we already have open, avoid doing path -+ based setting of file size if we can do it by handle. -+ This keeps our caching token (oplock) and avoids -+ timeouts when the local oplock break takes longer to flush -+ writebehind data than the SMB timeout for the SetPathInfo -+ request would allow */ -+ read_lock(&GlobalSMBSeslock); -+ cifsInode = CIFS_I(inode); -+ list_for_each(tmp, &cifsInode->openFileList) { -+ open_file = list_entry(tmp,struct cifsFileInfo, flist); -+ /* We check if file is open for writing first */ -+ if((open_file->pfile) && (!open_file->invalidHandle) && -+ ((open_file->pfile->f_flags & O_RDWR) || -+ (open_file->pfile->f_flags & O_WRONLY))) { -+ read_unlock(&GlobalSMBSeslock); -+ found = TRUE; -+ rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size, -+ open_file->netfid,open_file->pid,FALSE); -+ if(rc == 0) { -+ FreeXid(xid); -+ return; -+ } -+ /* Do not need reopen and retry on EAGAIN since we will -+ retry by pathname below */ -+ if(rc == -EAGAIN) -+ rc = -EHOSTDOWN; -+ -+ break; /* now that we found one valid file handle no -+ sense continuing to loop trying others */ -+ } -+ } -+ if(found == FALSE) -+ read_unlock(&GlobalSMBSeslock); -+ -+ if (list_empty(&inode->i_dentry)) { -+ cERROR(1, -+ ("Can not get pathname from empty dentry in inode 0x%p ", -+ inode)); -+ FreeXid(xid); -+ return; -+ } -+ -+ dirent = list_entry(inode->i_dentry.next, struct dentry, d_alias); -+ if (dirent) { -+ full_path = build_path_from_dentry(dirent); -+ rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE, -+ cifs_sb->local_nls); -+ cFYI(1,(" SetEOF (truncate) rc = %d",rc)); -+ if (!rc) -+ CIFSSMBSetEOF(xid,pTcon,full_path,inode->i_size,TRUE,cifs_sb->local_nls); -+ /* allocation size setting seems optional so ignore return code */ -+ } -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return; -+} -+ -+static int cifs_truncate_page(struct address_space *mapping, loff_t from) -+{ -+ unsigned long index = from >> PAGE_CACHE_SHIFT; -+ unsigned offset = from & (PAGE_CACHE_SIZE-1); -+ struct page *page; -+ char *kaddr; -+ int rc = 0; -+ -+ page = grab_cache_page(mapping, index); -+ if (!page) -+ return -ENOMEM; -+ -+ kaddr = kmap_atomic(page, KM_USER0); -+ memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); -+ flush_dcache_page(page); -+ kunmap_atomic(kaddr, KM_USER0); -+ unlock_page(page); -+ page_cache_release(page); -+ return rc; -+} -+ -+int -+cifs_setattr(struct dentry *direntry, struct iattr *attrs) -+{ -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ int rc = -EACCES; -+ int found = FALSE; -+ struct cifsFileInfo *open_file = NULL; -+ FILE_BASIC_INFO time_buf; -+ int set_time = FALSE; -+ __u64 mode = 0xFFFFFFFFFFFFFFFFULL; -+ __u64 uid = 0xFFFFFFFFFFFFFFFFULL; -+ __u64 gid = 0xFFFFFFFFFFFFFFFFULL; -+ struct cifsInodeInfo *cifsInode; -+ struct list_head * tmp; -+ -+ xid = GetXid(); -+ -+ cFYI(1, -+ (" In cifs_setattr, name = %s attrs->iavalid 0x%x ", -+ direntry->d_name.name, attrs->ia_valid)); -+ cifs_sb = CIFS_SB(direntry->d_inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ down(&direntry->d_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(direntry); -+ up(&direntry->d_sb->s_vfs_rename_sem); -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ cifsInode = CIFS_I(direntry->d_inode); -+ -+ /* BB check if we need to refresh inode from server now ? BB */ -+ -+ /* need to flush data before changing file size on server */ -+ filemap_fdatasync(direntry->d_inode->i_mapping); -+ -+ if (attrs->ia_valid & ATTR_SIZE) { -+ read_lock(&GlobalSMBSeslock); -+ /* To avoid spurious oplock breaks from server, in the case -+ of inodes that we already have open, avoid doing path -+ based setting of file size if we can do it by handle. -+ This keeps our caching token (oplock) and avoids -+ timeouts when the local oplock break takes longer to flush -+ writebehind data than the SMB timeout for the SetPathInfo -+ request would allow */ -+ list_for_each(tmp, &cifsInode->openFileList) { -+ open_file = list_entry(tmp,struct cifsFileInfo, flist); -+ /* We check if file is open for writing first */ -+ if((open_file->pfile) && -+ ((open_file->pfile->f_flags & O_RDWR) || -+ (open_file->pfile->f_flags & O_WRONLY))) { -+ if(open_file->invalidHandle == FALSE) { -+ /* we found a valid, writeable network file -+ handle to use to try to set the file size */ -+ __u16 nfid = open_file->netfid; -+ __u32 npid = open_file->pid; -+ read_unlock(&GlobalSMBSeslock); -+ found = TRUE; -+ rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, -+ nfid,npid,FALSE); -+ cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc)); -+ /* Do not need reopen and retry on EAGAIN since we will -+ retry by pathname below */ -+ -+ break; /* now that we found one valid file handle no -+ sense continuing to loop trying others */ -+ } -+ } -+ } -+ if(found == FALSE) { -+ read_unlock(&GlobalSMBSeslock); -+ } -+ -+ -+ if(rc != 0) { -+ /* Set file size by pathname rather than by handle either -+ because no valid, writeable file handle for it was found or -+ because there was an error setting it by handle */ -+ rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE, -+ cifs_sb->local_nls); -+ cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc)); -+ } -+ -+ /* Server is ok setting allocation size implicitly - no need to call: */ -+ /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/ -+ -+ if (rc == 0) { -+ rc = vmtruncate(direntry->d_inode, attrs->ia_size); -+ cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size); -+ } -+ } -+ if (attrs->ia_valid & ATTR_UID) { -+ cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid)); -+ uid = attrs->ia_uid; -+ /* entry->uid = cpu_to_le16(attr->ia_uid); */ -+ } -+ if (attrs->ia_valid & ATTR_GID) { -+ cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid)); -+ gid = attrs->ia_gid; -+ /* entry->gid = cpu_to_le16(attr->ia_gid); */ -+ } -+ -+ time_buf.Attributes = 0; -+ if (attrs->ia_valid & ATTR_MODE) { -+ cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode)); -+ mode = attrs->ia_mode; -+ /* entry->mode = cpu_to_le16(attr->ia_mode); */ -+ } -+ -+ if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) -+ && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) -+ rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, -+ 0 /* dev_t */, cifs_sb->local_nls); -+ else if (attrs->ia_valid & ATTR_MODE) { -+ if((mode & S_IWUGO) == 0) /* not writeable */ { -+ if((cifsInode->cifsAttrs & ATTR_READONLY) == 0) -+ time_buf.Attributes = -+ cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY); -+ } else if((mode & S_IWUGO) == S_IWUGO) { -+ if(cifsInode->cifsAttrs & ATTR_READONLY) -+ time_buf.Attributes = -+ cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY)); -+ } -+ /* BB to be implemented - via Windows security descriptors or streams */ -+ /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/ -+ } -+ -+ if (attrs->ia_valid & ATTR_ATIME) { -+ set_time = TRUE; -+ time_buf.LastAccessTime = -+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); -+ } else -+ time_buf.LastAccessTime = 0; -+ -+ if (attrs->ia_valid & ATTR_MTIME) { -+ set_time = TRUE; -+ time_buf.LastWriteTime = -+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); -+ } else -+ time_buf.LastWriteTime = 0; -+ -+ if (attrs->ia_valid & ATTR_CTIME) { -+ set_time = TRUE; -+ time_buf.ChangeTime = -+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); -+ } else -+ time_buf.ChangeTime = 0; -+ -+ if (set_time | time_buf.Attributes) { -+ /* BB what if setting one attribute fails -+ (such as size) but time setting works */ -+ time_buf.CreationTime = 0; /* do not change */ -+ /* In the future we should experiment - try setting timestamps -+ via Handle (SetFileInfo) instead of by path */ -+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, -+ cifs_sb->local_nls); -+ } -+ -+ /* do not need local check to inode_check_ok since the server does that */ -+ if (!rc) -+ rc = inode_setattr(direntry->d_inode, attrs); -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+void -+cifs_delete_inode(struct inode *inode) -+{ -+ cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode)); -+ /* may have to add back in if and when safe distributed caching of -+ directories added e.g. via FindNotify */ -+} ---- /dev/null -+++ b/fs/cifs/link.c -@@ -0,0 +1,328 @@ -+/* -+ * fs/cifs/link.c -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2003 -+ * 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 -+ */ -+#include <linux/fs.h> -+#include <linux/stat.h> -+#include "cifsfs.h" -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_debug.h" -+#include "cifs_fs_sb.h" -+ -+int -+cifs_hardlink(struct dentry *old_file, struct inode *inode, -+ struct dentry *direntry) -+{ -+ int rc = -EACCES; -+ int xid; -+ char *fromName = NULL; -+ char *toName = NULL; -+ struct cifs_sb_info *cifs_sb_target; -+ struct cifsTconInfo *pTcon; -+ struct cifsInodeInfo *cifsInode; -+ -+ xid = GetXid(); -+ -+ cifs_sb_target = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb_target->tcon; -+ -+/* No need to check for cross device links since server will do that -+ BB note DFS case in future though (when we may have to check) */ -+ -+ down(&inode->i_sb->s_vfs_rename_sem); -+ fromName = build_path_from_dentry(old_file); -+ toName = build_path_from_dentry(direntry); -+ up(&inode->i_sb->s_vfs_rename_sem); -+ if((fromName == NULL) || (toName == NULL)) { -+ rc = -ENOMEM; -+ goto cifs_hl_exit; -+ } -+ -+ if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) -+ rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, -+ cifs_sb_target->local_nls); -+ else { -+ rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, -+ cifs_sb_target->local_nls); -+ if(rc == -EIO) -+ rc = -EOPNOTSUPP; -+ } -+ -+/* if (!rc) */ -+ { -+ /* renew_parental_timestamps(old_file); -+ inode->i_nlink++; -+ mark_inode_dirty(inode); -+ d_instantiate(direntry, inode); */ -+ /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */ -+ } -+ d_drop(direntry); /* force new lookup from server */ -+ cifsInode = CIFS_I(old_file->d_inode); -+ cifsInode->time = 0; /* will force revalidate to go get info when needed */ -+ -+cifs_hl_exit: -+ if (fromName) -+ kfree(fromName); -+ if (toName) -+ kfree(toName); -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_follow_link(struct dentry *direntry, struct nameidata *nd) -+{ -+ struct inode *inode = direntry->d_inode; -+ int rc = -EACCES; -+ int xid; -+ char *full_path = NULL; -+ char * target_path; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ -+ xid = GetXid(); -+ -+ down(&direntry->d_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(direntry); -+ up(&direntry->d_sb->s_vfs_rename_sem); -+ -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ target_path = kmalloc(PATH_MAX, GFP_KERNEL); -+ if(target_path == NULL) { -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */ -+ /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */ -+ -+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */ -+ if (pTcon->ses->capabilities & CAP_UNIX) -+ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, -+ target_path, -+ PATH_MAX-1, -+ cifs_sb->local_nls); -+ else { -+ /* rc = CIFSSMBQueryReparseLinkInfo */ -+ /* BB Add code to Query ReparsePoint info */ -+ } -+ /* BB Anything else to do to handle recursive links? */ -+ /* BB Should we be using page symlink ops here? */ -+ -+ if (rc == 0) { -+ -+/* BB Add special case check for Samba DFS symlinks */ -+ -+ target_path[PATH_MAX-1] = 0; -+ rc = vfs_follow_link(nd, target_path); -+ } -+ /* else EACCESS */ -+ -+ if (target_path) -+ kfree(target_path); -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) -+{ -+ int rc = -EOPNOTSUPP; -+ int xid; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ struct inode *newinode = NULL; -+ -+ xid = GetXid(); -+ -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+ down(&inode->i_sb->s_vfs_rename_sem); -+ full_path = build_path_from_dentry(direntry); -+ up(&inode->i_sb->s_vfs_rename_sem); -+ -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ -+ cFYI(1, ("Full path: %s ", full_path)); -+ cFYI(1, ("symname is %s", symname)); -+ -+ /* BB what if DFS and this volume is on different share? BB */ -+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) -+ rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, -+ cifs_sb->local_nls); -+ /* else -+ rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */ -+ -+ if (rc == 0) { -+ if (pTcon->ses->capabilities & CAP_UNIX) -+ rc = cifs_get_inode_info_unix(&newinode, full_path, -+ inode->i_sb,xid); -+ else -+ rc = cifs_get_inode_info(&newinode, full_path, NULL, -+ inode->i_sb,xid); -+ -+ if (rc != 0) { -+ cFYI(1, -+ ("Create symlink worked but get_inode_info failed with rc = %d ", -+ rc)); -+ } else { -+ direntry->d_op = &cifs_dentry_ops; -+ d_instantiate(direntry, newinode); -+ } -+ } -+ -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return rc; -+} -+ -+int -+cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen) -+{ -+ struct inode *inode = direntry->d_inode; -+ int rc = -EACCES; -+ int xid; -+ int oplock = FALSE; -+ struct cifs_sb_info *cifs_sb; -+ struct cifsTconInfo *pTcon; -+ char *full_path = NULL; -+ char *tmp_path = NULL; -+ char * tmpbuffer; -+ unsigned char * referrals = NULL; -+ int num_referrals = 0; -+ int len; -+ __u16 fid; -+ -+ xid = GetXid(); -+ cifs_sb = CIFS_SB(inode->i_sb); -+ pTcon = cifs_sb->tcon; -+ -+/* BB would it be safe against deadlock to grab this sem -+ even though rename itself grabs the sem and calls lookup? */ -+/* down(&inode->i_sb->s_vfs_rename_sem);*/ -+ full_path = build_path_from_dentry(direntry); -+/* up(&inode->i_sb->s_vfs_rename_sem);*/ -+ -+ if(full_path == NULL) { -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ -+ cFYI(1, -+ ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", -+ full_path, inode, pBuffer, buflen)); -+ if(buflen > PATH_MAX) -+ len = PATH_MAX; -+ else -+ len = buflen; -+ tmpbuffer = kmalloc(len,GFP_KERNEL); -+ if(tmpbuffer == NULL) { -+ if (full_path) -+ kfree(full_path); -+ FreeXid(xid); -+ return -ENOMEM; -+ } -+ -+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */ -+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) -+ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, -+ tmpbuffer, -+ len - 1, -+ cifs_sb->local_nls); -+ else { -+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, -+ OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls); -+ if(!rc) { -+ rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, -+ tmpbuffer, -+ len - 1, -+ fid, -+ cifs_sb->local_nls); -+ if(CIFSSMBClose(xid, pTcon, fid)) { -+ cFYI(1,("Error closing junction point (open for ioctl)")); -+ } -+ if(rc == -EIO) { -+ /* Query if DFS Junction */ -+ tmp_path = -+ kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1, -+ GFP_KERNEL); -+ if (tmp_path) { -+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); -+ strncat(tmp_path, full_path, MAX_PATHCONF); -+ rc = get_dfs_path(xid, pTcon->ses, tmp_path, -+ cifs_sb->local_nls, &num_referrals, &referrals); -+ cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc)); -+ if((num_referrals == 0) && (rc == 0)) -+ rc = -EACCES; -+ else { -+ cFYI(1,("num referral: %d",num_referrals)); -+ if(referrals) { -+ cFYI(1,("referral string: %s ",referrals)); -+ strncpy(tmpbuffer, referrals, len-1); -+ } -+ } -+ if(referrals) -+ kfree(referrals); -+ kfree(tmp_path); -+ if(referrals) { -+ kfree(referrals); -+ } -+ } -+ /* BB add code like else decode referrals then memcpy to -+ tmpbuffer and free referrals string array BB */ -+ } -+ } -+ } -+ /* BB Anything else to do to handle recursive links? */ -+ /* BB Should we be using page ops here? */ -+ -+ /* BB null terminate returned string in pBuffer? BB */ -+ if (rc == 0) { -+ rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer); -+ cFYI(1, -+ ("vfs_readlink called from cifs_readlink returned %d", -+ rc)); -+ } -+ -+ if (tmpbuffer) { -+ kfree(tmpbuffer); -+ } -+ if (full_path) { -+ kfree(full_path); -+ } -+ FreeXid(xid); -+ return rc; -+} ---- /dev/null -+++ b/fs/cifs/Makefile -@@ -0,0 +1,10 @@ -+# -+# Makefile for Linux CIFS VFS client -+# -+O_TARGET := cifs.o -+ -+obj-y := 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 cifsencrypt.o -+ -+obj-m := $(O_TARGET) -+ -+include $(TOPDIR)/Rules.make ---- /dev/null -+++ b/fs/cifs/md4.c -@@ -0,0 +1,203 @@ -+/* -+ Unix SMB/Netbios implementation. -+ Version 1.9. -+ a implementation of MD4 designed for use in the SMB authentication protocol -+ Copyright (C) Andrew Tridgell 1997-1998. -+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003 -+ -+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+#include <linux/module.h> -+#include <linux/fs.h> -+/* NOTE: This code makes no attempt to be fast! */ -+ -+static __u32 -+F(__u32 X, __u32 Y, __u32 Z) -+{ -+ return (X & Y) | ((~X) & Z); -+} -+ -+static __u32 -+G(__u32 X, __u32 Y, __u32 Z) -+{ -+ return (X & Y) | (X & Z) | (Y & Z); -+} -+ -+static __u32 -+H(__u32 X, __u32 Y, __u32 Z) -+{ -+ return X ^ Y ^ Z; -+} -+ -+static __u32 -+lshift(__u32 x, int s) -+{ -+ x &= 0xFFFFFFFF; -+ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); -+} -+ -+#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s) -+#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s) -+#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s) -+ -+/* this applies md4 to 64 byte chunks */ -+static void -+mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D) -+{ -+ int j; -+ __u32 AA, BB, CC, DD; -+ __u32 X[16]; -+ -+ -+ for (j = 0; j < 16; j++) -+ X[j] = M[j]; -+ -+ AA = *A; -+ BB = *B; -+ CC = *C; -+ DD = *D; -+ -+ ROUND1(A, B, C, D, 0, 3); -+ ROUND1(D, A, B, C, 1, 7); -+ ROUND1(C, D, A, B, 2, 11); -+ ROUND1(B, C, D, A, 3, 19); -+ ROUND1(A, B, C, D, 4, 3); -+ ROUND1(D, A, B, C, 5, 7); -+ ROUND1(C, D, A, B, 6, 11); -+ ROUND1(B, C, D, A, 7, 19); -+ ROUND1(A, B, C, D, 8, 3); -+ ROUND1(D, A, B, C, 9, 7); -+ ROUND1(C, D, A, B, 10, 11); -+ ROUND1(B, C, D, A, 11, 19); -+ ROUND1(A, B, C, D, 12, 3); -+ ROUND1(D, A, B, C, 13, 7); -+ ROUND1(C, D, A, B, 14, 11); -+ ROUND1(B, C, D, A, 15, 19); -+ -+ ROUND2(A, B, C, D, 0, 3); -+ ROUND2(D, A, B, C, 4, 5); -+ ROUND2(C, D, A, B, 8, 9); -+ ROUND2(B, C, D, A, 12, 13); -+ ROUND2(A, B, C, D, 1, 3); -+ ROUND2(D, A, B, C, 5, 5); -+ ROUND2(C, D, A, B, 9, 9); -+ ROUND2(B, C, D, A, 13, 13); -+ ROUND2(A, B, C, D, 2, 3); -+ ROUND2(D, A, B, C, 6, 5); -+ ROUND2(C, D, A, B, 10, 9); -+ ROUND2(B, C, D, A, 14, 13); -+ ROUND2(A, B, C, D, 3, 3); -+ ROUND2(D, A, B, C, 7, 5); -+ ROUND2(C, D, A, B, 11, 9); -+ ROUND2(B, C, D, A, 15, 13); -+ -+ ROUND3(A, B, C, D, 0, 3); -+ ROUND3(D, A, B, C, 8, 9); -+ ROUND3(C, D, A, B, 4, 11); -+ ROUND3(B, C, D, A, 12, 15); -+ ROUND3(A, B, C, D, 2, 3); -+ ROUND3(D, A, B, C, 10, 9); -+ ROUND3(C, D, A, B, 6, 11); -+ ROUND3(B, C, D, A, 14, 15); -+ ROUND3(A, B, C, D, 1, 3); -+ ROUND3(D, A, B, C, 9, 9); -+ ROUND3(C, D, A, B, 5, 11); -+ ROUND3(B, C, D, A, 13, 15); -+ ROUND3(A, B, C, D, 3, 3); -+ ROUND3(D, A, B, C, 11, 9); -+ ROUND3(C, D, A, B, 7, 11); -+ ROUND3(B, C, D, A, 15, 15); -+ -+ *A += AA; -+ *B += BB; -+ *C += CC; -+ *D += DD; -+ -+ *A &= 0xFFFFFFFF; -+ *B &= 0xFFFFFFFF; -+ *C &= 0xFFFFFFFF; -+ *D &= 0xFFFFFFFF; -+ -+ for (j = 0; j < 16; j++) -+ X[j] = 0; -+} -+ -+static void -+copy64(__u32 * M, unsigned char *in) -+{ -+ int i; -+ -+ for (i = 0; i < 16; i++) -+ M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) | -+ (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0); -+} -+ -+static void -+copy4(unsigned char *out, __u32 x) -+{ -+ out[0] = x & 0xFF; -+ out[1] = (x >> 8) & 0xFF; -+ out[2] = (x >> 16) & 0xFF; -+ out[3] = (x >> 24) & 0xFF; -+} -+ -+/* produce a md4 message digest from data of length n bytes */ -+void -+mdfour(unsigned char *out, unsigned char *in, int n) -+{ -+ unsigned char buf[128]; -+ __u32 M[16]; -+ __u32 b = n * 8; -+ int i; -+ __u32 A = 0x67452301; -+ __u32 B = 0xefcdab89; -+ __u32 C = 0x98badcfe; -+ __u32 D = 0x10325476; -+ -+ while (n > 64) { -+ copy64(M, in); -+ mdfour64(M,&A,&B, &C, &D); -+ in += 64; -+ n -= 64; -+ } -+ -+ for (i = 0; i < 128; i++) -+ buf[i] = 0; -+ memcpy(buf, in, n); -+ buf[n] = 0x80; -+ -+ if (n <= 55) { -+ copy4(buf + 56, b); -+ copy64(M, buf); -+ mdfour64(M, &A, &B, &C, &D); -+ } else { -+ copy4(buf + 120, b); -+ copy64(M, buf); -+ mdfour64(M, &A, &B, &C, &D); -+ copy64(M, buf + 64); -+ mdfour64(M, &A, &B, &C, &D); -+ } -+ -+ for (i = 0; i < 128; i++) -+ buf[i] = 0; -+ copy64(M, buf); -+ -+ copy4(out, A); -+ copy4(out + 4, B); -+ copy4(out + 8, C); -+ copy4(out + 12, D); -+ -+ A = B = C = D = 0; -+} ---- /dev/null -+++ b/fs/cifs/md5.c -@@ -0,0 +1,363 @@ -+/* -+ * This code implements the MD5 message-digest algorithm. -+ * The algorithm is due to Ron Rivest. This code was -+ * written by Colin Plumb in 1993, no copyright is claimed. -+ * This code is in the public domain; do with it what you wish. -+ * -+ * Equivalent code is available from RSA Data Security, Inc. -+ * This code has been tested against that, and is equivalent, -+ * except that you don't need to include two pages of legalese -+ * with every copy. -+ * -+ * To compute the message digest of a chunk of bytes, declare an -+ * MD5Context structure, pass it to MD5Init, call MD5Update as -+ * needed on buffers full of bytes, and then call MD5Final, which -+ * will fill a supplied 16-byte array with the digest. -+ */ -+ -+/* This code slightly modified to fit into Samba by -+ abartlet@samba.org Jun 2001 -+ and to fit the cifs vfs by -+ Steve French sfrench@us.ibm.com */ -+ -+#include <linux/string.h> -+#include "md5.h" -+ -+static void MD5Transform(__u32 buf[4], __u32 const in[16]); -+ -+/* -+ * Note: this code is harmless on little-endian machines. -+ */ -+static void -+byteReverse(unsigned char *buf, unsigned longs) -+{ -+ __u32 t; -+ do { -+ t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | -+ ((unsigned) buf[1] << 8 | buf[0]); -+ *(__u32 *) buf = t; -+ buf += 4; -+ } while (--longs); -+} -+ -+/* -+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious -+ * initialization constants. -+ */ -+void -+MD5Init(struct MD5Context *ctx) -+{ -+ ctx->buf[0] = 0x67452301; -+ ctx->buf[1] = 0xefcdab89; -+ ctx->buf[2] = 0x98badcfe; -+ ctx->buf[3] = 0x10325476; -+ -+ ctx->bits[0] = 0; -+ ctx->bits[1] = 0; -+} -+ -+/* -+ * Update context to reflect the concatenation of another buffer full -+ * of bytes. -+ */ -+void -+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -+{ -+ register __u32 t; -+ -+ /* Update bitcount */ -+ -+ t = ctx->bits[0]; -+ if ((ctx->bits[0] = t + ((__u32) len << 3)) < t) -+ ctx->bits[1]++; /* Carry from low to high */ -+ ctx->bits[1] += len >> 29; -+ -+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ -+ -+ /* Handle any leading odd-sized chunks */ -+ -+ if (t) { -+ unsigned char *p = (unsigned char *) ctx->in + t; -+ -+ t = 64 - t; -+ if (len < t) { -+ memmove(p, buf, len); -+ return; -+ } -+ memmove(p, buf, t); -+ byteReverse(ctx->in, 16); -+ MD5Transform(ctx->buf, (__u32 *) ctx->in); -+ buf += t; -+ len -= t; -+ } -+ /* Process data in 64-byte chunks */ -+ -+ while (len >= 64) { -+ memmove(ctx->in, buf, 64); -+ byteReverse(ctx->in, 16); -+ MD5Transform(ctx->buf, (__u32 *) ctx->in); -+ buf += 64; -+ len -= 64; -+ } -+ -+ /* Handle any remaining bytes of data. */ -+ -+ memmove(ctx->in, buf, len); -+} -+ -+/* -+ * Final wrapup - pad to 64-byte boundary with the bit pattern -+ * 1 0* (64-bit count of bits processed, MSB-first) -+ */ -+void -+MD5Final(unsigned char digest[16], struct MD5Context *ctx) -+{ -+ unsigned int count; -+ unsigned char *p; -+ -+ /* Compute number of bytes mod 64 */ -+ count = (ctx->bits[0] >> 3) & 0x3F; -+ -+ /* Set the first char of padding to 0x80. This is safe since there is -+ always at least one byte free */ -+ p = ctx->in + count; -+ *p++ = 0x80; -+ -+ /* Bytes of padding needed to make 64 bytes */ -+ count = 64 - 1 - count; -+ -+ /* Pad out to 56 mod 64 */ -+ if (count < 8) { -+ /* Two lots of padding: Pad the first block to 64 bytes */ -+ memset(p, 0, count); -+ byteReverse(ctx->in, 16); -+ MD5Transform(ctx->buf, (__u32 *) ctx->in); -+ -+ /* Now fill the next block with 56 bytes */ -+ memset(ctx->in, 0, 56); -+ } else { -+ /* Pad block to 56 bytes */ -+ memset(p, 0, count - 8); -+ } -+ byteReverse(ctx->in, 14); -+ -+ /* Append length in bits and transform */ -+ ((__u32 *) ctx->in)[14] = ctx->bits[0]; -+ ((__u32 *) ctx->in)[15] = ctx->bits[1]; -+ -+ MD5Transform(ctx->buf, (__u32 *) ctx->in); -+ byteReverse((unsigned char *) ctx->buf, 4); -+ memmove(digest, ctx->buf, 16); -+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ -+} -+ -+/* The four core functions - F1 is optimized somewhat */ -+ -+/* #define F1(x, y, z) (x & y | ~x & z) */ -+#define F1(x, y, z) (z ^ (x & (y ^ z))) -+#define F2(x, y, z) F1(z, x, y) -+#define F3(x, y, z) (x ^ y ^ z) -+#define F4(x, y, z) (y ^ (x | ~z)) -+ -+/* This is the central step in the MD5 algorithm. */ -+#define MD5STEP(f, w, x, y, z, data, s) \ -+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) -+ -+/* -+ * The core of the MD5 algorithm, this alters an existing MD5 hash to -+ * reflect the addition of 16 longwords of new data. MD5Update blocks -+ * the data and converts bytes into longwords for this routine. -+ */ -+static void -+MD5Transform(__u32 buf[4], __u32 const in[16]) -+{ -+ register __u32 a, b, c, d; -+ -+ a = buf[0]; -+ b = buf[1]; -+ c = buf[2]; -+ d = buf[3]; -+ -+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); -+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); -+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); -+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); -+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); -+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); -+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); -+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); -+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); -+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); -+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); -+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); -+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); -+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); -+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); -+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); -+ -+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); -+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); -+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); -+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); -+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); -+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); -+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); -+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); -+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); -+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); -+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); -+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); -+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); -+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); -+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); -+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); -+ -+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); -+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); -+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); -+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); -+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); -+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); -+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); -+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); -+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); -+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); -+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); -+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); -+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); -+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); -+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); -+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); -+ -+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); -+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); -+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); -+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); -+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); -+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); -+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); -+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); -+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); -+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); -+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); -+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); -+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); -+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); -+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); -+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); -+ -+ buf[0] += a; -+ buf[1] += b; -+ buf[2] += c; -+ buf[3] += d; -+} -+ -+/*********************************************************************** -+ the rfc 2104 version of hmac_md5 initialisation. -+***********************************************************************/ -+void -+hmac_md5_init_rfc2104(unsigned char *key, int key_len, -+ struct HMACMD5Context *ctx) -+{ -+ int i; -+ -+ /* if key is longer than 64 bytes reset it to key=MD5(key) */ -+ if (key_len > 64) { -+ unsigned char tk[16]; -+ struct MD5Context tctx; -+ -+ MD5Init(&tctx); -+ MD5Update(&tctx, key, key_len); -+ MD5Final(tk, &tctx); -+ -+ key = tk; -+ key_len = 16; -+ } -+ -+ /* start out by storing key in pads */ -+ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad)); -+ memset(ctx->k_opad, 0, sizeof (ctx->k_opad)); -+ memcpy(ctx->k_ipad, key, key_len); -+ memcpy(ctx->k_opad, key, key_len); -+ -+ /* XOR key with ipad and opad values */ -+ for (i = 0; i < 64; i++) { -+ ctx->k_ipad[i] ^= 0x36; -+ ctx->k_opad[i] ^= 0x5c; -+ } -+ -+ MD5Init(&ctx->ctx); -+ MD5Update(&ctx->ctx, ctx->k_ipad, 64); -+} -+ -+/*********************************************************************** -+ the microsoft version of hmac_md5 initialisation. -+***********************************************************************/ -+void -+hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, -+ struct HMACMD5Context *ctx) -+{ -+ int i; -+ -+ /* if key is longer than 64 bytes truncate it */ -+ if (key_len > 64) { -+ key_len = 64; -+ } -+ -+ /* start out by storing key in pads */ -+ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad)); -+ memset(ctx->k_opad, 0, sizeof (ctx->k_opad)); -+ memcpy(ctx->k_ipad, key, key_len); -+ memcpy(ctx->k_opad, key, key_len); -+ -+ /* XOR key with ipad and opad values */ -+ for (i = 0; i < 64; i++) { -+ ctx->k_ipad[i] ^= 0x36; -+ ctx->k_opad[i] ^= 0x5c; -+ } -+ -+ MD5Init(&ctx->ctx); -+ MD5Update(&ctx->ctx, ctx->k_ipad, 64); -+} -+ -+/*********************************************************************** -+ update hmac_md5 "inner" buffer -+***********************************************************************/ -+void -+hmac_md5_update(const unsigned char *text, int text_len, -+ struct HMACMD5Context *ctx) -+{ -+ MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */ -+} -+ -+/*********************************************************************** -+ finish off hmac_md5 "inner" buffer and generate outer one. -+***********************************************************************/ -+void -+hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) -+{ -+ struct MD5Context ctx_o; -+ -+ MD5Final(digest, &ctx->ctx); -+ -+ MD5Init(&ctx_o); -+ MD5Update(&ctx_o, ctx->k_opad, 64); -+ MD5Update(&ctx_o, digest, 16); -+ MD5Final(digest, &ctx_o); -+} -+ -+/*********************************************************** -+ single function to calculate an HMAC MD5 digest from data. -+ use the microsoft hmacmd5 init method because the key is 16 bytes. -+************************************************************/ -+void -+hmac_md5(unsigned char key[16], unsigned char *data, int data_len, -+ unsigned char *digest) -+{ -+ struct HMACMD5Context ctx; -+ hmac_md5_init_limK_to_64(key, 16, &ctx); -+ if (data_len != 0) { -+ hmac_md5_update(data, data_len, &ctx); -+ } -+ hmac_md5_final(digest, &ctx); -+} ---- /dev/null -+++ b/fs/cifs/md5.h -@@ -0,0 +1,38 @@ -+#ifndef MD5_H -+#define MD5_H -+#ifndef HEADER_MD5_H -+/* Try to avoid clashes with OpenSSL */ -+#define HEADER_MD5_H -+#endif -+ -+struct MD5Context { -+ __u32 buf[4]; -+ __u32 bits[2]; -+ unsigned char in[64]; -+}; -+#endif /* !MD5_H */ -+ -+#ifndef _HMAC_MD5_H -+struct HMACMD5Context { -+ struct MD5Context ctx; -+ unsigned char k_ipad[65]; -+ unsigned char k_opad[65]; -+}; -+#endif /* _HMAC_MD5_H */ -+ -+void MD5Init(struct MD5Context *context); -+void MD5Update(struct MD5Context *context, unsigned char const *buf, -+ unsigned len); -+void MD5Final(unsigned char digest[16], struct MD5Context *context); -+ -+/* The following definitions come from lib/hmacmd5.c */ -+ -+void hmac_md5_init_rfc2104(unsigned char *key, int key_len, -+ struct HMACMD5Context *ctx); -+void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, -+ struct HMACMD5Context *ctx); -+void hmac_md5_update(const unsigned char *text, int text_len, -+ struct HMACMD5Context *ctx); -+void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx); -+void hmac_md5(unsigned char key[16], unsigned char *data, int data_len, -+ unsigned char *digest); ---- /dev/null -+++ b/fs/cifs/misc.c -@@ -0,0 +1,463 @@ -+/* -+ * fs/cifs/misc.c -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2003 -+ * 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 -+ */ -+ -+#include <linux/slab.h> -+#include <linux/ctype.h> -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_debug.h" -+#include "smberr.h" -+#include "nterr.h" -+ -+extern kmem_cache_t *cifs_req_cachep; -+extern struct task_struct * oplockThread; -+ -+__u16 GlobalMid; /* multiplex id - rotating counter */ -+ -+/* The xid serves as a useful identifier for each incoming vfs request, -+ in a similar way to the mid which is useful to track each sent smb, -+ and CurrentXid can also provide a running counter (although it -+ will eventually wrap past zero) of the total vfs operations handled -+ since the cifs fs was mounted */ -+ -+unsigned int -+_GetXid(void) -+{ -+ unsigned int xid; -+ -+ spin_lock(&GlobalMid_Lock); -+ GlobalTotalActiveXid++; -+ if (GlobalTotalActiveXid > GlobalMaxActiveXid) -+ GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */ -+ xid = GlobalCurrentXid++; -+ spin_unlock(&GlobalMid_Lock); -+ return xid; -+} -+ -+void -+_FreeXid(unsigned int xid) -+{ -+ spin_lock(&GlobalMid_Lock); -+ /* if(GlobalTotalActiveXid == 0) -+ BUG(); */ -+ GlobalTotalActiveXid--; -+ spin_unlock(&GlobalMid_Lock); -+} -+ -+struct cifsSesInfo * -+sesInfoAlloc(void) -+{ -+ struct cifsSesInfo *ret_buf; -+ -+ ret_buf = -+ (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo), -+ GFP_KERNEL); -+ if (ret_buf) { -+ memset(ret_buf, 0, sizeof (struct cifsSesInfo)); -+ write_lock(&GlobalSMBSeslock); -+ atomic_inc(&sesInfoAllocCount); -+ ret_buf->status = CifsNew; -+ list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList); -+ init_MUTEX(&ret_buf->sesSem); -+ write_unlock(&GlobalSMBSeslock); -+ } -+ return ret_buf; -+} -+ -+void -+sesInfoFree(struct cifsSesInfo *buf_to_free) -+{ -+ if (buf_to_free == NULL) { -+ cFYI(1, ("Null buffer passed to sesInfoFree")); -+ return; -+ } -+ -+ write_lock(&GlobalSMBSeslock); -+ atomic_dec(&sesInfoAllocCount); -+ list_del(&buf_to_free->cifsSessionList); -+ write_unlock(&GlobalSMBSeslock); -+ if (buf_to_free->serverOS) -+ kfree(buf_to_free->serverOS); -+ if (buf_to_free->serverDomain) -+ kfree(buf_to_free->serverDomain); -+ if (buf_to_free->serverNOS) -+ kfree(buf_to_free->serverNOS); -+ if (buf_to_free->password) -+ kfree(buf_to_free->password); -+ kfree(buf_to_free); -+} -+ -+struct cifsTconInfo * -+tconInfoAlloc(void) -+{ -+ struct cifsTconInfo *ret_buf; -+ ret_buf = -+ (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo), -+ GFP_KERNEL); -+ if (ret_buf) { -+ memset(ret_buf, 0, sizeof (struct cifsTconInfo)); -+ write_lock(&GlobalSMBSeslock); -+ atomic_inc(&tconInfoAllocCount); -+ list_add(&ret_buf->cifsConnectionList, -+ &GlobalTreeConnectionList); -+ ret_buf->tidStatus = CifsNew; -+ INIT_LIST_HEAD(&ret_buf->openFileList); -+ init_MUTEX(&ret_buf->tconSem); -+#ifdef CONFIG_CIFS_STATS -+ ret_buf->stat_lock = SPIN_LOCK_UNLOCKED; -+#endif -+ write_unlock(&GlobalSMBSeslock); -+ } -+ return ret_buf; -+} -+ -+void -+tconInfoFree(struct cifsTconInfo *buf_to_free) -+{ -+ if (buf_to_free == NULL) { -+ cFYI(1, ("Null buffer passed to tconInfoFree")); -+ return; -+ } -+ write_lock(&GlobalSMBSeslock); -+ atomic_dec(&tconInfoAllocCount); -+ list_del(&buf_to_free->cifsConnectionList); -+ write_unlock(&GlobalSMBSeslock); -+ if (buf_to_free->nativeFileSystem) -+ kfree(buf_to_free->nativeFileSystem); -+ kfree(buf_to_free); -+} -+ -+struct smb_hdr * -+cifs_buf_get(void) -+{ -+ struct smb_hdr *ret_buf = NULL; -+ -+/* We could use negotiated size instead of max_msgsize - -+ but it may be more efficient to always alloc same size -+ albeit slightly larger than necessary and maxbuffersize -+ defaults to this and can not be bigger */ -+ ret_buf = -+ (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL); -+ -+ /* clear the first few header bytes */ -+ if (ret_buf) { -+ memset(ret_buf, 0, sizeof (struct smb_hdr)); -+ atomic_inc(&bufAllocCount); -+ } -+ -+ return ret_buf; -+} -+ -+void -+cifs_buf_release(void *buf_to_free) -+{ -+ -+ if (buf_to_free == NULL) { -+ cFYI(1, ("Null buffer passed to cifs_buf_release")); -+ return; -+ } -+ kmem_cache_free(cifs_req_cachep, buf_to_free); -+ -+ atomic_dec(&bufAllocCount); -+ return; -+} -+ -+void -+header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , -+ const struct cifsTconInfo *treeCon, int word_count -+ /* length of fixed section (word count) in two byte units */ -+ ) -+{ -+ int i; -+ __u32 tmp; -+ struct list_head* temp_item; -+ struct cifsSesInfo * ses; -+ char *temp = (char *) buffer; -+ -+ for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) { -+ temp[i] = 0; /* BB is this needed ?? */ -+ } -+ -+ buffer->smb_buf_length = -+ (2 * word_count) + sizeof (struct smb_hdr) - -+ 4 /* RFC 1001 length field does not count */ + -+ 2 /* for bcc field itself */ ; -+ /* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */ -+ -+ buffer->Protocol[0] = 0xFF; -+ buffer->Protocol[1] = 'S'; -+ buffer->Protocol[2] = 'M'; -+ buffer->Protocol[3] = 'B'; -+ buffer->Command = smb_command; -+ buffer->Flags = 0x00; /* case sensitive */ -+ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES; -+ tmp = cpu_to_le32(current->pid); -+ buffer->Pid = tmp & 0xFFFF; -+ tmp >>= 16; -+ buffer->PidHigh = tmp & 0xFFFF; -+ spin_lock(&GlobalMid_Lock); -+ GlobalMid++; -+ buffer->Mid = GlobalMid; -+ spin_unlock(&GlobalMid_Lock); -+ if (treeCon) { -+ buffer->Tid = treeCon->tid; -+ if (treeCon->ses) { -+ if (treeCon->ses->capabilities & CAP_UNICODE) -+ buffer->Flags2 |= SMBFLG2_UNICODE; -+ if (treeCon->ses->capabilities & CAP_STATUS32) { -+ buffer->Flags2 |= SMBFLG2_ERR_STATUS; -+ } -+ -+ buffer->Uid = treeCon->ses->Suid; /* always in LE format */ -+ if(multiuser_mount != 0) { -+ /* For the multiuser case, there are few obvious technically */ -+ /* possible mechanisms to match the local linux user (uid) */ -+ /* to a valid remote smb user (smb_uid): */ -+ /* 1) Query Winbind (or other local pam/nss daemon */ -+ /* for userid/password/logon_domain or credential */ -+ /* 2) Query Winbind for uid to sid to username mapping */ -+ /* and see if we have a matching password for existing*/ -+ /* session for that user perhas getting password by */ -+ /* adding a new pam_cifs module that stores passwords */ -+ /* so that the cifs vfs can get at that for all logged*/ -+ /* on users */ -+ /* 3) (Which is the mechanism we have chosen) */ -+ /* Search through sessions to the same server for a */ -+ /* a match on the uid that was passed in on mount */ -+ /* with the current processes uid (or euid?) and use */ -+ /* that smb uid. If no existing smb session for */ -+ /* that uid found, use the default smb session ie */ -+ /* the smb session for the volume mounted which is */ -+ /* the same as would be used if the multiuser mount */ -+ /* flag were disabled. */ -+ -+ /* BB Add support for establishing new tCon and SMB Session */ -+ /* with userid/password pairs found on the smb session */ -+ /* for other target tcp/ip addresses BB */ -+ if(current->uid != treeCon->ses->linux_uid) { -+ cFYI(1,("Multiuser mode and UID did not match tcon uid ")); -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(temp_item, &GlobalSMBSessionList) { -+ ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); -+ if(ses->linux_uid == current->uid) { -+ if(ses->server == treeCon->ses->server) { -+ cFYI(1,("found matching uid substitute right smb_uid")); -+ buffer->Uid = ses->Suid; -+ break; -+ } else { -+ /* BB eventually call cifs_setup_session here */ -+ cFYI(1,("local UID found but smb sess with this server does not exist")); -+ } -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ } -+ } -+ } -+ if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) -+ buffer->Flags2 |= SMBFLG2_DFS; -+ if(treeCon->ses->server) -+ if(treeCon->ses->server->secMode & -+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) -+ buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; -+ } -+ -+/* endian conversion of flags is now done just before sending */ -+ buffer->WordCount = (char) word_count; -+ return; -+} -+ -+int -+checkSMBhdr(struct smb_hdr *smb, __u16 mid) -+{ -+ /* Make sure that this really is an SMB, that it is a response, -+ and that the message ids match */ -+ if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) && -+ (mid == smb->Mid)) { -+ if(smb->Flags & SMBFLG_RESPONSE) -+ return 0; -+ else { -+ /* only one valid case where server sends us request */ -+ if(smb->Command == SMB_COM_LOCKING_ANDX) -+ return 0; -+ else -+ cERROR(1, ("Rcvd Request not response ")); -+ } -+ } else { /* bad signature or mid */ -+ if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff)) -+ cERROR(1, -+ ("Bad protocol string signature header %x ", -+ *(unsigned int *) smb->Protocol)); -+ if (mid != smb->Mid) -+ cERROR(1, ("Mids do not match")); -+ } -+ cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid)); -+ return 1; -+} -+ -+int -+checkSMB(struct smb_hdr *smb, __u16 mid, int length) -+{ -+ cFYI(0, -+ ("Entering checkSMB with Length: %x, smb_buf_length: %x ", -+ length, ntohl(smb->smb_buf_length))); -+ if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) -+ || (ntohl(smb->smb_buf_length) > -+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) { -+ if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { -+ cERROR(1, ("Length less than 2 + sizeof smb_hdr ")); -+ if (((unsigned int)length >= sizeof (struct smb_hdr) - 1) -+ && (smb->Status.CifsError != 0)) -+ return 0; /* some error cases do not return wct and bcc */ -+ -+ } -+ if (ntohl(smb->smb_buf_length) > -+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) -+ cERROR(1, -+ ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... ")); -+ cERROR(1, -+ ("bad smb detected. Illegal length. The mid=%d", -+ smb->Mid)); -+ return 1; -+ } -+ -+ if (checkSMBhdr(smb, mid)) -+ return 1; -+ -+ if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb)) -+ || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) { -+ return 0; -+ } else { -+ cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); -+ cERROR(1, -+ ("bad smb size detected. The Mid=%d", smb->Mid)); -+ return 1; -+ } -+} -+int -+is_valid_oplock_break(struct smb_hdr *buf) -+{ -+ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; -+ struct list_head *tmp; -+ struct list_head *tmp1; -+ struct cifsTconInfo *tcon; -+ struct cifsFileInfo *netfile; -+ -+ /* could add check for smb response flag 0x80 */ -+ cFYI(1,("Checking for oplock break")); -+ if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) -+ return FALSE; -+ if(pSMB->hdr.Flags & SMBFLG_RESPONSE) { -+ /* no sense logging error on invalid handle on oplock -+ break - harmless race between close request and oplock -+ break response is expected from time to time writing out -+ large dirty files cached on the client */ -+ if ((NT_STATUS_INVALID_HANDLE) == -+ le32_to_cpu(pSMB->hdr.Status.CifsError)) { -+ cFYI(1,("invalid handle on oplock break")); -+ return TRUE; -+ } else if (ERRbadfid == -+ le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { -+ return TRUE; -+ } else { -+ return FALSE; /* on valid oplock brk we get "request" */ -+ } -+ } -+ if(pSMB->hdr.WordCount != 8) -+ return FALSE; -+ -+ cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel)); -+ if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) -+ return FALSE; -+ -+ /* look up tcon based on tid & uid */ -+ read_lock(&GlobalSMBSeslock); -+ list_for_each(tmp, &GlobalTreeConnectionList) { -+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); -+ if (tcon->tid == buf->Tid) { -+#ifdef CONFIG_CIFS_STATS -+ atomic_inc(&tcon->num_oplock_brks); -+#endif -+ list_for_each(tmp1,&tcon->openFileList){ -+ netfile = list_entry(tmp1,struct cifsFileInfo,tlist); -+ if(pSMB->Fid == netfile->netfid) { -+ struct cifsInodeInfo *pCifsInode; -+ read_unlock(&GlobalSMBSeslock); -+ cFYI(1,("Matching file id, processing oplock break")); -+ pCifsInode = -+ CIFS_I(netfile->pInode); -+ pCifsInode->clientCanCacheAll = FALSE; -+ if(pSMB->OplockLevel == 0) -+ pCifsInode->clientCanCacheRead = FALSE; -+ pCifsInode->oplockPending = TRUE; -+ AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon); -+ cFYI(1,("about to wake up oplock thd")); -+ wake_up_process(oplockThread); -+ return TRUE; -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ cFYI(1,("No matching file for oplock break on connection")); -+ return TRUE; -+ } -+ } -+ read_unlock(&GlobalSMBSeslock); -+ cFYI(1,("Can not process oplock break for non-existent connection")); -+ return TRUE; -+} -+ -+void -+dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) -+{ -+ int i, j; -+ char debug_line[17]; -+ unsigned char *buffer; -+ -+ if (traceSMB == 0) -+ return; -+ -+ buffer = (unsigned char *) smb_buf; -+ for (i = 0, j = 0; i < smb_buf_length; i++, j++) { -+ if (i % 8 == 0) { /* we have reached the beginning of line */ -+ printk(KERN_DEBUG "| "); -+ j = 0; -+ } -+ printk("%0#4x ", buffer[i]); -+ debug_line[2 * j] = ' '; -+ if (isprint(buffer[i])) -+ debug_line[1 + (2 * j)] = buffer[i]; -+ else -+ debug_line[1 + (2 * j)] = '_'; -+ -+ if (i % 8 == 7) { /* we have reached end of line, time to print ascii */ -+ debug_line[16] = 0; -+ printk(" | %s\n", debug_line); -+ } -+ } -+ for (; j < 8; j++) { -+ printk(" "); -+ debug_line[2 * j] = ' '; -+ debug_line[1 + (2 * j)] = ' '; -+ } -+ printk( " | %s\n", debug_line); -+ return; -+} ---- /dev/null -+++ b/fs/cifs/netmisc.c -@@ -0,0 +1,905 @@ -+/* -+ * fs/cifs/netmisc.c -+ * -+ * Copyright (c) International Business Machines Corp., 2002 -+ * Author(s): Steve French (sfrench@us.ibm.com) -+ * -+ * Error mapping routines from Samba libsmb/errormap.c -+ * Copyright (C) Andrew Tridgell 2001 -+ * -+ * -+ * 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 <linux/net.h> -+#include <linux/string.h> -+#include <linux/in.h> -+#include <linux/ctype.h> -+#include <linux/fs.h> -+#include <asm/div64.h> -+#include <asm/byteorder.h> -+#include "cifsfs.h" -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "smberr.h" -+#include "cifs_debug.h" -+#include "nterr.h" -+ -+struct smb_to_posix_error { -+ __u16 smb_err; -+ int posix_code; -+}; -+ -+const struct smb_to_posix_error mapping_table_ERRDOS[] = { -+ {ERRbadfunc, -EINVAL}, -+ {ERRbadfile, -ENOENT}, -+ {ERRbadpath, -ENOTDIR}, -+ {ERRnofids, -EMFILE}, -+ {ERRnoaccess, -EACCES}, -+ {ERRbadfid, -EBADF}, -+ {ERRbadmcb, -EIO}, -+ {ERRnomem, -ENOMEM}, -+ {ERRbadmem, -EFAULT}, -+ {ERRbadenv, -EFAULT}, -+ {ERRbadformat, -EINVAL}, -+ {ERRbadaccess, -EACCES}, -+ {ERRbaddata, -EIO}, -+ {ERRbaddrive, -ENXIO}, -+ {ERRremcd, -EACCES}, -+ {ERRdiffdevice, -EXDEV}, -+ {ERRnofiles, -ENOENT}, -+ {ERRbadshare, -ETXTBSY}, -+ {ERRlock, -EACCES}, -+ {ERRunsup, -EINVAL}, -+ {ERRnosuchshare,-ENXIO}, -+ {ERRfilexists, -EEXIST}, -+ {ERRinvparm, -EINVAL}, -+ {ERRdiskfull, -ENOSPC}, -+ {ERRinvname, -ENOENT}, -+ {ERRdirnotempty, -ENOTEMPTY}, -+ {ERRnotlocked, -ENOLCK}, -+ {ERRalreadyexists, -EEXIST}, -+ {ERRmoredata, -EOVERFLOW}, -+ {ErrQuota, -EDQUOT}, -+ {ErrNotALink, -ENOLINK}, -+ {ERRnetlogonNotStarted,-ENOPROTOOPT}, -+ {0, 0} -+}; -+ -+const struct smb_to_posix_error mapping_table_ERRSRV[] = { -+ {ERRerror, -EIO}, -+ {ERRbadpw, -EPERM}, -+ {ERRbadtype, -EREMOTE}, -+ {ERRaccess, -EACCES}, -+ {ERRinvtid, -ENXIO}, -+ {ERRinvnetname, -ENODEV}, -+ {ERRinvdevice, -ENXIO}, -+ {ERRqfull, -ENOSPC}, -+ {ERRqtoobig, -ENOSPC}, -+ {ERRqeof, -EIO}, -+ {ERRinvpfid, -EBADF}, -+ {ERRsmbcmd, -EBADRQC}, -+ {ERRsrverror, -EIO}, -+ {ERRbadBID, -EIO}, -+ {ERRfilespecs, -EINVAL}, -+ {ERRbadLink, -EIO}, -+ {ERRbadpermits, -EINVAL}, -+ {ERRbadPID, -ESRCH}, -+ {ERRsetattrmode, -EINVAL}, -+ {ERRpaused, -EHOSTDOWN}, -+ {ERRmsgoff, -EHOSTDOWN}, -+ {ERRnoroom, -ENOSPC}, -+ {ERRrmuns, -EUSERS}, -+ {ERRtimeout, -ETIME}, -+ {ERRnoresource, -ENOBUFS}, -+ {ERRtoomanyuids, -EUSERS}, -+ {ERRbaduid, -EACCES}, -+ {ERRusempx, -EIO}, -+ {ERRusestd, -EIO}, -+ {ERR_NOTIFY_ENUM_DIR, -ENOBUFS}, -+ {ERRaccountexpired, -EACCES}, -+ {ERRbadclient, -EACCES}, -+ {ERRbadLogonTime, -EACCES}, -+ {ERRpasswordExpired, -EACCES}, -+ {ERRnosupport, -EINVAL}, -+ {0, 0} -+}; -+ -+const struct smb_to_posix_error mapping_table_ERRHRD[] = { -+ {0, 0} -+}; -+ -+/* Convert string containing dotted ip address to binary form */ -+/* returns 0 if invalid address */ -+ -+/* BB add address family, change rc to status flag and return union or for ipv6 */ -+/* will need parent to call something like inet_pton to convert ipv6 address BB */ -+int -+cifs_inet_pton(int address_family, char *cp,void *dst) -+{ -+ struct in_addr address; -+ int value; -+ int digit; -+ int i; -+ char temp; -+ char bytes[4]; -+ char *end = bytes; -+ static const int addr_class_max[4] = -+ { 0xffffffff, 0xffffff, 0xffff, 0xff }; -+ -+ if(address_family != AF_INET) -+ return -EAFNOSUPPORT; -+ -+ for (i = 0; i < 4; i++) { -+ bytes[i] = 0; -+ } -+ -+ temp = *cp; -+ -+ while (TRUE) { -+ if (!isdigit(temp)) -+ return 0; -+ -+ value = 0; -+ digit = 0; -+ for (;;) { -+ if (isascii(temp) && isdigit(temp)) { -+ value = (value * 10) + temp - '0'; -+ temp = *++cp; -+ digit = 1; -+ } else -+ break; -+ } -+ -+ if (temp == '.') { -+ if ((end > bytes + 2) || (value > 255)) -+ return 0; -+ *end++ = value; -+ temp = *++cp; -+ } else if (temp == ':') { -+ cFYI(1,("IPv6 addresses not supported for CIFS mounts yet")); -+ return -1; -+ } else -+ break; -+ } -+ -+ /* check for last characters */ -+ if (temp != '\0' && (!isascii(temp) || !isspace(temp))) -+ if (temp != '\\') { -+ if (temp != '/') -+ return 0; -+ else -+ (*cp = '\\'); /* switch the slash the expected way */ -+ } -+ if (value > addr_class_max[end - bytes]) -+ return 0; -+ -+ address.s_addr = *((int *) bytes) | htonl(value); -+ *((int *)dst) = address.s_addr; -+ return 1; /* success */ -+} -+ -+/***************************************************************************** -+convert a NT status code to a dos class/code -+ *****************************************************************************/ -+/* NT status -> dos error map */ -+static const struct { -+ __u8 dos_class; -+ __u16 dos_code; -+ __u32 ntstatus; -+} ntstatus_to_dos_map[] = { -+ { -+ ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, { -+ ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, { -+ ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, { -+ ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, { -+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, { -+ ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, { -+ ERRDOS, 87, NT_STATUS_INVALID_CID}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, { -+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, { -+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, { -+ ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, { -+ ERRDOS, 38, NT_STATUS_END_OF_FILE}, { -+ ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, { -+ ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, { -+ ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR}, -+/* { This NT error code was 'sqashed' -+ from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK -+ during the session setup } */ -+ { -+ ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, { -+ ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, { -+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, { -+ ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, { -+ ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, { -+ ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, { -+ ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED}, -+/* { This NT error code was 'sqashed' -+ from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE -+ during the session setup } */ -+ { -+ ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, { -+ ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, { -+ ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, { -+ ERRDOS, 158, NT_STATUS_NOT_LOCKED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, { -+ ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, { -+ ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, { -+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */ -+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, { -+ ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, { -+ ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, { -+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, { -+ ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, { -+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, { -+ ERRDOS, 23, NT_STATUS_DATA_ERROR}, { -+ ERRDOS, 23, NT_STATUS_CRC_ERROR}, { -+ ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, { -+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, { -+ ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, { -+ ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, { -+ ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, { -+ ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, { -+ ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, { -+ ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, { -+ ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, { -+ ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, { -+ ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, { -+ ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, { -+ ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, { -+ ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, { -+ ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, { -+ ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, { -+ ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, { -+ ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, { -+ ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS}, -+/* { This NT error code was 'sqashed' -+ from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE -+ during the session setup } */ -+ { -+ ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN}, -+/* { This NT error code was 'sqashed' -+ from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE -+ during the session setup } */ -+ { -+ ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { -+ ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { -+ ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { -+ ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, { -+ ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, { -+ ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, { -+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, { -+ ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, { -+ ERRDOS, 112, NT_STATUS_DISK_FULL}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, { -+ ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, { -+ ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, { -+ ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, { -+ ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, { -+ ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, { -+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, { -+ ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, { -+ ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED}, -+/* { This NT error code was 'sqashed' -+ from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES -+ during the session setup } */ -+ { -+ ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, { -+ ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, { -+ ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, { -+ ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, { -+ ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, { -+ ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, { -+ ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, { -+ ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, { -+ ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, { -+ ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, { -+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, { -+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, { -+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, { -+ ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, { -+ ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, { -+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, { -+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, { -+ ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, { -+ ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, { -+ ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, { -+ ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, { -+ ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, { -+ ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, { -+ ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, { -+ ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, { -+ ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, { -+ ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, { -+ ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, { -+ ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, { -+ ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, { -+ ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, { -+ ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, { -+ ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, { -+ ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, { -+ ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, { -+ ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, { -+ ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, { -+ ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, { -+ ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, { -+ ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, { -+ ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, { -+ ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, { -+ ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, { -+ ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, { -+ ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, { -+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, { -+ ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, { -+ ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, { -+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, { -+ ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, { -+ ERRDOS, 203, 0xc0000100}, { -+ ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, { -+ ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, { -+ ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, { -+ ERRDOS, 2401, NT_STATUS_FILES_OPEN}, { -+ ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, { -+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, { -+ ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, { -+ ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, { -+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, { -+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, { -+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, { -+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, { -+ ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, { -+ ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, { -+ ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, { -+ ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, { -+ ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, { -+ ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, { -+ ERRDOS, 59, NT_STATUS_LINK_FAILED}, { -+ ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, { -+ ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, { -+ ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, { -+ ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, { -+ ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, { -+ ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, { -+ ERRHRD, ERRgeneral, 0xc000016e}, { -+ ERRHRD, ERRgeneral, 0xc000016f}, { -+ ERRHRD, ERRgeneral, 0xc0000170}, { -+ ERRHRD, ERRgeneral, 0xc0000171}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, { -+ ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, { -+ ERRHRD, ERRgeneral, 0xc0000179}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, { -+ ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, { -+ ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, { -+ ERRDOS, 19, NT_STATUS_TOO_LATE}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET}, -+/* { This NT error code was 'sqashed' -+ from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE -+ during the session setup } */ -+ { -+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { -+ ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { -+ ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT}, -+/* { This NT error code was 'sqashed' -+ from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE -+ during the session setup } */ -+ { -+ ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, { -+ ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, { -+ ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, { -+ ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, { -+ ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, { -+ ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, { -+ ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, { -+ ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, { -+ ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, { -+ ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, { -+ ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, { -+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, { -+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, { -+ ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, { -+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, { -+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, { -+ ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, { -+ ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, { -+ ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, { -+ ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, { -+ ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_RETRY}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, { -+ ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, { -+ ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, { -+ ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, { -+ ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, { -+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, { -+ ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, { -+ ERRHRD, ERRgeneral, 0xc000024a}, { -+ ERRHRD, ERRgeneral, 0xc000024b}, { -+ ERRHRD, ERRgeneral, 0xc000024c}, { -+ ERRHRD, ERRgeneral, 0xc000024d}, { -+ ERRHRD, ERRgeneral, 0xc000024e}, { -+ ERRHRD, ERRgeneral, 0xc000024f}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, { -+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, { -+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, { -+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, { -+ ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, { -+ ERRHRD, ERRgeneral, 0xc000025d}, { -+ ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, { -+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, { -+ ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, { -+ ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, { -+ ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, { -+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, { -+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, { -+ ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, { -+ ERRDOS, 21, 0xc000026e}, { -+ ERRDOS, 161, 0xc0000281}, { -+ ERRDOS, ERRnoaccess, 0xc000028a}, { -+ ERRDOS, ERRnoaccess, 0xc000028b}, { -+ ERRHRD, ERRgeneral, 0xc000028c}, { -+ ERRDOS, ERRnoaccess, 0xc000028d}, { -+ ERRDOS, ERRnoaccess, 0xc000028e}, { -+ ERRDOS, ERRnoaccess, 0xc000028f}, { -+ ERRDOS, ERRnoaccess, 0xc0000290}, { -+ERRDOS, ERRbadfunc, 0xc000029c},}; -+ -+/***************************************************************************** -+ Print an error message from the status code -+ *****************************************************************************/ -+static void -+cifs_print_status(__u32 status_code) -+{ -+ int idx = 0; -+ -+ while (nt_errs[idx].nt_errstr != NULL) { -+ if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) == -+ (status_code & 0xFFFFFF)) { -+ printk(KERN_NOTICE "Status code returned 0x%08x %s\n", -+ status_code,nt_errs[idx].nt_errstr); -+ } -+ idx++; -+ } -+ return; -+} -+ -+ -+static void -+ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode) -+{ -+ int i; -+ if (ntstatus == 0) { -+ *eclass = 0; -+ *ecode = 0; -+ return; -+ } -+ for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) { -+ if (ntstatus == ntstatus_to_dos_map[i].ntstatus) { -+ *eclass = ntstatus_to_dos_map[i].dos_class; -+ *ecode = ntstatus_to_dos_map[i].dos_code; -+ return; -+ } -+ } -+ *eclass = ERRHRD; -+ *ecode = ERRgeneral; -+} -+ -+int -+map_smb_to_linux_error(struct smb_hdr *smb) -+{ -+ unsigned int i; -+ int rc = -EIO; /* if transport error smb error may not be set */ -+ __u8 smberrclass; -+ __u16 smberrcode; -+ -+ /* BB if NT Status codes - map NT BB */ -+ -+ /* old style smb error codes */ -+ if (smb->Status.CifsError == 0) -+ return 0; -+ -+ if (smb->Flags2 & SMBFLG2_ERR_STATUS) { -+ /* translate the newer STATUS codes to old style errors and then to POSIX errors */ -+ smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError); -+ if(cifsFYI) -+ cifs_print_status(smb->Status.CifsError); -+ ntstatus_to_dos(smb->Status.CifsError, &smberrclass, -+ &smberrcode); -+ } else { -+ smberrclass = smb->Status.DosError.ErrorClass; -+ smb->Status.DosError.Error = -+ le16_to_cpu(smb->Status.DosError.Error); -+ smberrcode = smb->Status.DosError.Error; -+ } -+ -+ /* old style errors */ -+ -+ /* DOS class smb error codes - map DOS */ -+ if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */ -+ for (i = 0; -+ i < -+ sizeof (mapping_table_ERRDOS) / -+ sizeof (struct smb_to_posix_error); i++) { -+ if (mapping_table_ERRDOS[i].smb_err == 0) -+ break; -+ else if (mapping_table_ERRDOS[i].smb_err == smberrcode) { -+ rc = mapping_table_ERRDOS[i].posix_code; -+ break; -+ } -+ /* else try the next error mapping one to see if it will match */ -+ } -+ } else if (smberrclass == ERRSRV) { /* server class of error codes */ -+ for (i = 0; -+ i < -+ sizeof (mapping_table_ERRSRV) / -+ sizeof (struct smb_to_posix_error); i++) { -+ if (mapping_table_ERRSRV[i].smb_err == 0) -+ break; -+ else if (mapping_table_ERRSRV[i].smb_err == smberrcode) { -+ rc = mapping_table_ERRSRV[i].posix_code; -+ break; -+ } -+ /* else try the next error mapping one to see if it will match */ -+ } -+ } -+ /* else ERRHRD class errors or junk - return EIO */ -+ -+ cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc)); -+ -+ /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */ -+ -+ return rc; -+} -+ -+/* -+ * calculate the size of the SMB message based on the fixed header -+ * portion, the number of word parameters and the data portion of the message -+ */ -+unsigned int -+smbCalcSize(struct smb_hdr *ptr) -+{ -+ return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + -+ BCC(ptr)); -+} -+ -+/* The following are taken from fs/ntfs/util.c */ -+ -+#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) -+ -+ /* -+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units) -+ * into Unix UTC (based 1970-01-01, in seconds). -+ */ -+time_t -+cifs_NTtimeToUnix(__u64 ntutc) -+{ -+ /* BB what about the timezone? BB */ -+ -+ /* Subtract the NTFS time offset, then convert to 1s intervals. */ -+ u64 t; -+ -+ t = ntutc - NTFS_TIME_OFFSET; -+ do_div(t, 10000000); -+ return (time_t)t; -+} -+ -+/* Convert the Unix UTC into NT UTC. */ -+__u64 -+cifs_UnixTimeToNT(time_t t) -+{ -+ __u64 dce_time; -+ /* Convert to 100ns intervals and then add the NTFS time offset. */ -+ dce_time = (__u64) t * 10000000; -+ dce_time += NTFS_TIME_OFFSET; -+ return dce_time; -+} ---- /dev/null -+++ b/fs/cifs/nterr.c -@@ -0,0 +1,687 @@ -+/* -+ * Unix SMB/Netbios implementation. -+ * Version 1.9. -+ * RPC Pipe client / server routines -+ * Copyright (C) Luke Kenneth Casson Leighton 1997-2001. -+ * -+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+/* NT error codes - see nterr.h */ -+#include <linux/types.h> -+#include <linux/fs.h> -+#include "nterr.h" -+ -+const struct nt_err_code_struct nt_errs[] = { -+ {"NT_STATUS_OK", NT_STATUS_OK}, -+ {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL}, -+ {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED}, -+ {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS}, -+ {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH}, -+ {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION}, -+ {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW}, -+ {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR}, -+ {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA}, -+ {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE}, -+ {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK}, -+ {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC}, -+ {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID}, -+ {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED}, -+ {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER}, -+ {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE}, -+ {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE}, -+ {"NT_STATUS_INVALID_DEVICE_REQUEST", -+ NT_STATUS_INVALID_DEVICE_REQUEST}, -+ {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE}, -+ {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME}, -+ {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE}, -+ {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA}, -+ {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR}, -+ {"NT_STATUS_MORE_PROCESSING_REQUIRED", -+ NT_STATUS_MORE_PROCESSING_REQUIRED}, -+ {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY}, -+ {"NT_STATUS_CONFLICTING_ADDRESSES", -+ NT_STATUS_CONFLICTING_ADDRESSES}, -+ {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW}, -+ {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM}, -+ {"NT_STATUS_UNABLE_TO_DELETE_SECTION", -+ NT_STATUS_UNABLE_TO_DELETE_SECTION}, -+ {"NT_STATUS_INVALID_SYSTEM_SERVICE", -+ NT_STATUS_INVALID_SYSTEM_SERVICE}, -+ {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION}, -+ {"NT_STATUS_INVALID_LOCK_SEQUENCE", -+ NT_STATUS_INVALID_LOCK_SEQUENCE}, -+ {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE}, -+ {"NT_STATUS_INVALID_FILE_FOR_SECTION", -+ NT_STATUS_INVALID_FILE_FOR_SECTION}, -+ {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED}, -+ {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED}, -+ {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL}, -+ {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH}, -+ {"NT_STATUS_NONCONTINUABLE_EXCEPTION", -+ NT_STATUS_NONCONTINUABLE_EXCEPTION}, -+ {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION}, -+ {"NT_STATUS_UNWIND", NT_STATUS_UNWIND}, -+ {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK}, -+ {"NT_STATUS_INVALID_UNWIND_TARGET", -+ NT_STATUS_INVALID_UNWIND_TARGET}, -+ {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED}, -+ {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR}, -+ {"NT_STATUS_UNABLE_TO_DECOMMIT_VM", -+ NT_STATUS_UNABLE_TO_DECOMMIT_VM}, -+ {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED}, -+ {"NT_STATUS_INVALID_PORT_ATTRIBUTES", -+ NT_STATUS_INVALID_PORT_ATTRIBUTES}, -+ {"NT_STATUS_PORT_MESSAGE_TOO_LONG", -+ NT_STATUS_PORT_MESSAGE_TOO_LONG}, -+ {"NT_STATUS_INVALID_PARAMETER_MIX", -+ NT_STATUS_INVALID_PARAMETER_MIX}, -+ {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER}, -+ {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR}, -+ {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID}, -+ {"NT_STATUS_OBJECT_NAME_NOT_FOUND", -+ NT_STATUS_OBJECT_NAME_NOT_FOUND}, -+ {"NT_STATUS_OBJECT_NAME_COLLISION", -+ NT_STATUS_OBJECT_NAME_COLLISION}, -+ {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE}, -+ {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED}, -+ {"NT_STATUS_DEVICE_ALREADY_ATTACHED", -+ NT_STATUS_DEVICE_ALREADY_ATTACHED}, -+ {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID}, -+ {"NT_STATUS_OBJECT_PATH_NOT_FOUND", -+ NT_STATUS_OBJECT_PATH_NOT_FOUND}, -+ {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD", -+ NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, -+ {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN}, -+ {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR}, -+ {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR}, -+ {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR}, -+ {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG}, -+ {"NT_STATUS_PORT_CONNECTION_REFUSED", -+ NT_STATUS_PORT_CONNECTION_REFUSED}, -+ {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE}, -+ {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION}, -+ {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED}, -+ {"NT_STATUS_INVALID_PAGE_PROTECTION", -+ NT_STATUS_INVALID_PAGE_PROTECTION}, -+ {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED}, -+ {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED", -+ NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, -+ {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET}, -+ {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE}, -+ {"NT_STATUS_SUSPEND_COUNT_EXCEEDED", -+ NT_STATUS_SUSPEND_COUNT_EXCEEDED}, -+ {"NT_STATUS_THREAD_IS_TERMINATING", -+ NT_STATUS_THREAD_IS_TERMINATING}, -+ {"NT_STATUS_BAD_WORKING_SET_LIMIT", -+ NT_STATUS_BAD_WORKING_SET_LIMIT}, -+ {"NT_STATUS_INCOMPATIBLE_FILE_MAP", -+ NT_STATUS_INCOMPATIBLE_FILE_MAP}, -+ {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION}, -+ {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED}, -+ {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE}, -+ {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY}, -+ {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE}, -+ {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR}, -+ {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT}, -+ {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED}, -+ {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING}, -+ {"NT_STATUS_CTL_FILE_NOT_SUPPORTED", -+ NT_STATUS_CTL_FILE_NOT_SUPPORTED}, -+ {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION}, -+ {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH}, -+ {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER}, -+ {"NT_STATUS_INVALID_PRIMARY_GROUP", -+ NT_STATUS_INVALID_PRIMARY_GROUP}, -+ {"NT_STATUS_NO_IMPERSONATION_TOKEN", -+ NT_STATUS_NO_IMPERSONATION_TOKEN}, -+ {"NT_STATUS_CANT_DISABLE_MANDATORY", -+ NT_STATUS_CANT_DISABLE_MANDATORY}, -+ {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS}, -+ {"NT_STATUS_NO_SUCH_LOGON_SESSION", -+ NT_STATUS_NO_SUCH_LOGON_SESSION}, -+ {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE}, -+ {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD}, -+ {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME}, -+ {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS}, -+ {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER}, -+ {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS}, -+ {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP}, -+ {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP}, -+ {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP}, -+ {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN}, -+ {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD}, -+ {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD}, -+ {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION}, -+ {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE}, -+ {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION}, -+ {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS}, -+ {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION}, -+ {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED}, -+ {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED}, -+ {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED}, -+ {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED", -+ NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, -+ {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED}, -+ {"NT_STATUS_INVALID_SUB_AUTHORITY", -+ NT_STATUS_INVALID_SUB_AUTHORITY}, -+ {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL}, -+ {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID}, -+ {"NT_STATUS_INVALID_SECURITY_DESCR", -+ NT_STATUS_INVALID_SECURITY_DESCR}, -+ {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND}, -+ {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT}, -+ {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN}, -+ {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL}, -+ {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED}, -+ {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL}, -+ {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED}, -+ {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED}, -+ {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED", -+ NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, -+ {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED}, -+ {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY}, -+ {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED}, -+ {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL}, -+ {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED}, -+ {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA}, -+ {"NT_STATUS_RESOURCE_DATA_NOT_FOUND", -+ NT_STATUS_RESOURCE_DATA_NOT_FOUND}, -+ {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND", -+ NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, -+ {"NT_STATUS_RESOURCE_NAME_NOT_FOUND", -+ NT_STATUS_RESOURCE_NAME_NOT_FOUND}, -+ {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED", -+ NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, -+ {"NT_STATUS_FLOAT_DENORMAL_OPERAND", -+ NT_STATUS_FLOAT_DENORMAL_OPERAND}, -+ {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, -+ {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT}, -+ {"NT_STATUS_FLOAT_INVALID_OPERATION", -+ NT_STATUS_FLOAT_INVALID_OPERATION}, -+ {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW}, -+ {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK}, -+ {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW}, -+ {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO", -+ NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, -+ {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW}, -+ {"NT_STATUS_PRIVILEGED_INSTRUCTION", -+ NT_STATUS_PRIVILEGED_INSTRUCTION}, -+ {"NT_STATUS_TOO_MANY_PAGING_FILES", -+ NT_STATUS_TOO_MANY_PAGING_FILES}, -+ {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID}, -+ {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED", -+ NT_STATUS_ALLOTTED_SPACE_EXCEEDED}, -+ {"NT_STATUS_INSUFFICIENT_RESOURCES", -+ NT_STATUS_INSUFFICIENT_RESOURCES}, -+ {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND}, -+ {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR}, -+ {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED}, -+ {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE}, -+ {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE}, -+ {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED}, -+ {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA}, -+ {"NT_STATUS_MEDIA_WRITE_PROTECTED", -+ NT_STATUS_MEDIA_WRITE_PROTECTED}, -+ {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY}, -+ {"NT_STATUS_INVALID_GROUP_ATTRIBUTES", -+ NT_STATUS_INVALID_GROUP_ATTRIBUTES}, -+ {"NT_STATUS_BAD_IMPERSONATION_LEVEL", -+ NT_STATUS_BAD_IMPERSONATION_LEVEL}, -+ {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS}, -+ {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS}, -+ {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE}, -+ {"NT_STATUS_BAD_MASTER_BOOT_RECORD", -+ NT_STATUS_BAD_MASTER_BOOT_RECORD}, -+ {"NT_STATUS_INSTRUCTION_MISALIGNMENT", -+ NT_STATUS_INSTRUCTION_MISALIGNMENT}, -+ {"NT_STATUS_INSTANCE_NOT_AVAILABLE", -+ NT_STATUS_INSTANCE_NOT_AVAILABLE}, -+ {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE}, -+ {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE}, -+ {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY}, -+ {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION}, -+ {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED}, -+ {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING}, -+ {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED}, -+ {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING}, -+ {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE}, -+ {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT}, -+ {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED}, -+ {"NT_STATUS_PROFILING_NOT_STARTED", -+ NT_STATUS_PROFILING_NOT_STARTED}, -+ {"NT_STATUS_PROFILING_NOT_STOPPED", -+ NT_STATUS_PROFILING_NOT_STOPPED}, -+ {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET}, -+ {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY}, -+ {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED}, -+ {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING}, -+ {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME}, -+ {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH}, -+ {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY}, -+ {"NT_STATUS_DEVICE_DOES_NOT_EXIST", -+ NT_STATUS_DEVICE_DOES_NOT_EXIST}, -+ {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS}, -+ {"NT_STATUS_ADAPTER_HARDWARE_ERROR", -+ NT_STATUS_ADAPTER_HARDWARE_ERROR}, -+ {"NT_STATUS_INVALID_NETWORK_RESPONSE", -+ NT_STATUS_INVALID_NETWORK_RESPONSE}, -+ {"NT_STATUS_UNEXPECTED_NETWORK_ERROR", -+ NT_STATUS_UNEXPECTED_NETWORK_ERROR}, -+ {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER}, -+ {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL}, -+ {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE}, -+ {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED}, -+ {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED}, -+ {"NT_STATUS_NETWORK_ACCESS_DENIED", -+ NT_STATUS_NETWORK_ACCESS_DENIED}, -+ {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE}, -+ {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME}, -+ {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES}, -+ {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS}, -+ {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED}, -+ {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED}, -+ {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED}, -+ {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT}, -+ {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT}, -+ {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE}, -+ {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED}, -+ {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED", -+ NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, -+ {"NT_STATUS_NO_SECURITY_ON_OBJECT", -+ NT_STATUS_NO_SECURITY_ON_OBJECT}, -+ {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT}, -+ {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY}, -+ {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO", -+ NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, -+ {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF}, -+ {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE}, -+ {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE}, -+ {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE}, -+ {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN}, -+ {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS}, -+ {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED", -+ NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, -+ {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED}, -+ {"NT_STATUS_INVALID_OPLOCK_PROTOCOL", -+ NT_STATUS_INVALID_OPLOCK_PROTOCOL}, -+ {"NT_STATUS_INTERNAL_DB_CORRUPTION", -+ NT_STATUS_INTERNAL_DB_CORRUPTION}, -+ {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR}, -+ {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED}, -+ {"NT_STATUS_BAD_DESCRIPTOR_FORMAT", -+ NT_STATUS_BAD_DESCRIPTOR_FORMAT}, -+ {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER}, -+ {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR}, -+ {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR", -+ NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, -+ {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR", -+ NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, -+ {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR", -+ NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, -+ {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS}, -+ {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS}, -+ {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1}, -+ {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2}, -+ {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3}, -+ {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4}, -+ {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5}, -+ {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6}, -+ {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7}, -+ {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8}, -+ {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9}, -+ {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10}, -+ {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11}, -+ {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12}, -+ {"NT_STATUS_REDIRECTOR_NOT_STARTED", -+ NT_STATUS_REDIRECTOR_NOT_STARTED}, -+ {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED}, -+ {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW}, -+ {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE}, -+ {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE}, -+ {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY}, -+ {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR}, -+ {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY}, -+ {"NT_STATUS_BAD_LOGON_SESSION_STATE", -+ NT_STATUS_BAD_LOGON_SESSION_STATE}, -+ {"NT_STATUS_LOGON_SESSION_COLLISION", -+ NT_STATUS_LOGON_SESSION_COLLISION}, -+ {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG}, -+ {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN}, -+ {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE}, -+ {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND}, -+ {"NT_STATUS_PROCESS_IS_TERMINATING", -+ NT_STATUS_PROCESS_IS_TERMINATING}, -+ {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE}, -+ {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION}, -+ {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE}, -+ {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED}, -+ {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT}, -+ {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST}, -+ {"NT_STATUS_ABIOS_LID_ALREADY_OWNED", -+ NT_STATUS_ABIOS_LID_ALREADY_OWNED}, -+ {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER}, -+ {"NT_STATUS_ABIOS_INVALID_COMMAND", -+ NT_STATUS_ABIOS_INVALID_COMMAND}, -+ {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID}, -+ {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE", -+ NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, -+ {"NT_STATUS_ABIOS_INVALID_SELECTOR", -+ NT_STATUS_ABIOS_INVALID_SELECTOR}, -+ {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT}, -+ {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE}, -+ {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET}, -+ {"NT_STATUS_INVALID_LDT_DESCRIPTOR", -+ NT_STATUS_INVALID_LDT_DESCRIPTOR}, -+ {"NT_STATUS_INVALID_IMAGE_NE_FORMAT", -+ NT_STATUS_INVALID_IMAGE_NE_FORMAT}, -+ {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE}, -+ {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE}, -+ {"NT_STATUS_MAPPED_FILE_SIZE_ZERO", -+ NT_STATUS_MAPPED_FILE_SIZE_ZERO}, -+ {"NT_STATUS_TOO_MANY_OPENED_FILES", -+ NT_STATUS_TOO_MANY_OPENED_FILES}, -+ {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED}, -+ {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE}, -+ {"NT_STATUS_INVALID_COMPUTER_NAME", -+ NT_STATUS_INVALID_COMPUTER_NAME}, -+ {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED}, -+ {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT}, -+ {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP}, -+ {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER}, -+ {"NT_STATUS_MEMBERS_PRIMARY_GROUP", -+ NT_STATUS_MEMBERS_PRIMARY_GROUP}, -+ {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED}, -+ {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS}, -+ {"NT_STATUS_THREAD_NOT_IN_PROCESS", -+ NT_STATUS_THREAD_NOT_IN_PROCESS}, -+ {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE}, -+ {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED", -+ NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, -+ {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT}, -+ {"NT_STATUS_INVALID_IMAGE_LE_FORMAT", -+ NT_STATUS_INVALID_IMAGE_LE_FORMAT}, -+ {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ}, -+ {"NT_STATUS_INVALID_IMAGE_PROTECT", -+ NT_STATUS_INVALID_IMAGE_PROTECT}, -+ {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16}, -+ {"NT_STATUS_LOGON_SERVER_CONFLICT", -+ NT_STATUS_LOGON_SERVER_CONFLICT}, -+ {"NT_STATUS_TIME_DIFFERENCE_AT_DC", -+ NT_STATUS_TIME_DIFFERENCE_AT_DC}, -+ {"NT_STATUS_SYNCHRONIZATION_REQUIRED", -+ NT_STATUS_SYNCHRONIZATION_REQUIRED}, -+ {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND}, -+ {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED}, -+ {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED}, -+ {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND}, -+ {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND}, -+ {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT}, -+ {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT}, -+ {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT}, -+ {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES}, -+ {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED}, -+ {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT}, -+ {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION}, -+ {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS}, -+ {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED}, -+ {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE}, -+ {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION}, -+ {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE}, -+ {"NT_STATUS_PAGEFILE_CREATE_FAILED", -+ NT_STATUS_PAGEFILE_CREATE_FAILED}, -+ {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE}, -+ {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL}, -+ {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE}, -+ {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT", -+ NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, -+ {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN}, -+ {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT}, -+ {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED}, -+ {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR}, -+ {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME}, -+ {"NT_STATUS_SERIAL_NO_DEVICE_INITED", -+ NT_STATUS_SERIAL_NO_DEVICE_INITED}, -+ {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS}, -+ {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS}, -+ {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS}, -+ {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS}, -+ {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED}, -+ {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS}, -+ {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG}, -+ {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR}, -+ {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE}, -+ {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS}, -+ {"NT_STATUS_LOGON_TYPE_NOT_GRANTED", -+ NT_STATUS_LOGON_TYPE_NOT_GRANTED}, -+ {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE}, -+ {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED", -+ NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, -+ {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR", -+ NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, -+ {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER}, -+ {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY", -+ NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, -+ {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER}, -+ {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER}, -+ {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER}, -+ {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME}, -+ {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND", -+ NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, -+ {"NT_STATUS_FLOPPY_WRONG_CYLINDER", -+ NT_STATUS_FLOPPY_WRONG_CYLINDER}, -+ {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR}, -+ {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS}, -+ {"NT_STATUS_DISK_RECALIBRATE_FAILED", -+ NT_STATUS_DISK_RECALIBRATE_FAILED}, -+ {"NT_STATUS_DISK_OPERATION_FAILED", -+ NT_STATUS_DISK_OPERATION_FAILED}, -+ {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED}, -+ {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY}, -+ {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING}, -+ {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE}, -+ {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH}, -+ {"NT_STATUS_DEVICE_NOT_PARTITIONED", -+ NT_STATUS_DEVICE_NOT_PARTITIONED}, -+ {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA}, -+ {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA", -+ NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, -+ {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW}, -+ {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA}, -+ {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER}, -+ {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER}, -+ {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED}, -+ {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE}, -+ {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS}, -+ {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED", -+ NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, -+ {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN}, -+ {"NT_STATUS_CHILD_MUST_BE_VOLATILE", -+ NT_STATUS_CHILD_MUST_BE_VOLATILE}, -+ {"NT_STATUS_DEVICE_CONFIGURATION_ERROR", -+ NT_STATUS_DEVICE_CONFIGURATION_ERROR}, -+ {"NT_STATUS_DRIVER_INTERNAL_ERROR", -+ NT_STATUS_DRIVER_INTERNAL_ERROR}, -+ {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE}, -+ {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR}, -+ {"NT_STATUS_DEVICE_PROTOCOL_ERROR", -+ NT_STATUS_DEVICE_PROTOCOL_ERROR}, -+ {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER}, -+ {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL}, -+ {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE}, -+ {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET}, -+ {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT}, -+ {"NT_STATUS_TRUSTED_DOMAIN_FAILURE", -+ NT_STATUS_TRUSTED_DOMAIN_FAILURE}, -+ {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE", -+ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, -+ {"NT_STATUS_EVENTLOG_FILE_CORRUPT", -+ NT_STATUS_EVENTLOG_FILE_CORRUPT}, -+ {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START}, -+ {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE}, -+ {"NT_STATUS_MUTANT_LIMIT_EXCEEDED", -+ NT_STATUS_MUTANT_LIMIT_EXCEEDED}, -+ {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED}, -+ {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED}, -+ {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK}, -+ {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT", -+ NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, -+ {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT}, -+ {"NT_STATUS_EVENTLOG_FILE_CHANGED", -+ NT_STATUS_EVENTLOG_FILE_CHANGED}, -+ {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", -+ NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, -+ {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", -+ NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, -+ {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", -+ NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT}, -+ {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT", -+ NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, -+ {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED}, -+ {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY}, -+ {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED}, -+ {"NT_STATUS_RESOURCE_LANG_NOT_FOUND", -+ NT_STATUS_RESOURCE_LANG_NOT_FOUND}, -+ {"NT_STATUS_INSUFF_SERVER_RESOURCES", -+ NT_STATUS_INSUFF_SERVER_RESOURCES}, -+ {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE}, -+ {"NT_STATUS_INVALID_ADDRESS_COMPONENT", -+ NT_STATUS_INVALID_ADDRESS_COMPONENT}, -+ {"NT_STATUS_INVALID_ADDRESS_WILDCARD", -+ NT_STATUS_INVALID_ADDRESS_WILDCARD}, -+ {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES}, -+ {"NT_STATUS_ADDRESS_ALREADY_EXISTS", -+ NT_STATUS_ADDRESS_ALREADY_EXISTS}, -+ {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED}, -+ {"NT_STATUS_CONNECTION_DISCONNECTED", -+ NT_STATUS_CONNECTION_DISCONNECTED}, -+ {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET}, -+ {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES}, -+ {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED}, -+ {"NT_STATUS_TRANSACTION_TIMED_OUT", -+ NT_STATUS_TRANSACTION_TIMED_OUT}, -+ {"NT_STATUS_TRANSACTION_NO_RELEASE", -+ NT_STATUS_TRANSACTION_NO_RELEASE}, -+ {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH}, -+ {"NT_STATUS_TRANSACTION_RESPONDED", -+ NT_STATUS_TRANSACTION_RESPONDED}, -+ {"NT_STATUS_TRANSACTION_INVALID_ID", -+ NT_STATUS_TRANSACTION_INVALID_ID}, -+ {"NT_STATUS_TRANSACTION_INVALID_TYPE", -+ NT_STATUS_TRANSACTION_INVALID_TYPE}, -+ {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION}, -+ {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION}, -+ {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE", -+ NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, -+ {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED}, -+ {"NT_STATUS_SYSTEM_PROCESS_TERMINATED", -+ NT_STATUS_SYSTEM_PROCESS_TERMINATED}, -+ {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED}, -+ {"NT_STATUS_NO_BROWSER_SERVERS_FOUND", -+ NT_STATUS_NO_BROWSER_SERVERS_FOUND}, -+ {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR}, -+ {"NT_STATUS_DRIVER_CANCEL_TIMEOUT", -+ NT_STATUS_DRIVER_CANCEL_TIMEOUT}, -+ {"NT_STATUS_REPLY_MESSAGE_MISMATCH", -+ NT_STATUS_REPLY_MESSAGE_MISMATCH}, -+ {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT}, -+ {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH", -+ NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, -+ {"NT_STATUS_LOST_WRITEBEHIND_DATA", -+ NT_STATUS_LOST_WRITEBEHIND_DATA}, -+ {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID", -+ NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, -+ {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE}, -+ {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND}, -+ {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM}, -+ {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE}, -+ {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ}, -+ {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK}, -+ {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID}, -+ {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS}, -+ {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE}, -+ {"NT_STATUS_RETRY", NT_STATUS_RETRY}, -+ {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE}, -+ {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET}, -+ {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND}, -+ {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW}, -+ {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT}, -+ {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", -+ NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, -+ {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT}, -+ {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE}, -+ {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED}, -+ {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT}, -+ {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED", -+ NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, -+ {"NT_STATUS_ADDRESS_NOT_ASSOCIATED", -+ NT_STATUS_ADDRESS_NOT_ASSOCIATED}, -+ {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID}, -+ {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE}, -+ {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE}, -+ {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE}, -+ {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE}, -+ {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE}, -+ {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED}, -+ {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED}, -+ {"NT_STATUS_BAD_COMPRESSION_BUFFER", -+ NT_STATUS_BAD_COMPRESSION_BUFFER}, -+ {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE}, -+ {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED}, -+ {"NT_STATUS_TIMER_RESOLUTION_NOT_SET", -+ NT_STATUS_TIMER_RESOLUTION_NOT_SET}, -+ {"NT_STATUS_CONNECTION_COUNT_LIMIT", -+ NT_STATUS_CONNECTION_COUNT_LIMIT}, -+ {"NT_STATUS_LOGIN_TIME_RESTRICTION", -+ NT_STATUS_LOGIN_TIME_RESTRICTION}, -+ {"NT_STATUS_LOGIN_WKSTA_RESTRICTION", -+ NT_STATUS_LOGIN_WKSTA_RESTRICTION}, -+ {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH}, -+ {"NT_STATUS_INSUFFICIENT_LOGON_INFO", -+ NT_STATUS_INSUFFICIENT_LOGON_INFO}, -+ {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT}, -+ {"NT_STATUS_BAD_SERVICE_ENTRYPOINT", -+ NT_STATUS_BAD_SERVICE_ENTRYPOINT}, -+ {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST}, -+ {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1}, -+ {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2}, -+ {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT}, -+ {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED}, -+ {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE}, -+ {"NT_STATUS_LICENSE_QUOTA_EXCEEDED", -+ NT_STATUS_LICENSE_QUOTA_EXCEEDED}, -+ {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT}, -+ {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT}, -+ {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT}, -+ {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE}, -+ {"NT_STATUS_UNSUPPORTED_COMPRESSION", -+ NT_STATUS_UNSUPPORTED_COMPRESSION}, -+ {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE}, -+ {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH", -+ NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, -+ {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND", -+ NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, -+ {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND", -+ NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, -+ {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED}, -+ {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS}, -+ {"NT_STATUS_QUOTA_LIST_INCONSISTENT", -+ NT_STATUS_QUOTA_LIST_INCONSISTENT}, -+ {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE}, -+ {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES}, -+ {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES}, -+ {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED}, -+ {NULL, 0} -+}; ---- /dev/null -+++ b/fs/cifs/nterr.h -@@ -0,0 +1,556 @@ -+/* -+ Unix SMB/Netbios implementation. -+ Version 1.9. -+ NT error code constants -+ Copyright (C) Andrew Tridgell 1992-2000 -+ Copyright (C) John H Terpstra 1996-2000 -+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000 -+ Copyright (C) Paul Ashton 1998-2000 -+ -+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+ -+ -+#ifndef _NTERR_H -+#define _NTERR_H -+ -+struct nt_err_code_struct { -+ char *nt_errstr; -+ __u32 nt_errcode; -+}; -+ -+extern const struct nt_err_code_struct nt_errs[]; -+ -+/* Win32 Status codes. */ -+ -+#define STATUS_BUFFER_OVERFLOW 0x80000005 -+#define STATUS_MORE_ENTRIES 0x0105 -+#define ERROR_INVALID_PARAMETER 0x0057 -+#define ERROR_INSUFFICIENT_BUFFER 0x007a -+#define STATUS_1804 0x070c -+#define STATUS_NOTIFY_ENUM_DIR 0x010c -+ -+/* Win32 Error codes extracted using a loop in smbclient then printing a -+ netmon sniff to a file. */ -+ -+#define NT_STATUS_OK 0x0000 -+#define STATUS_SOME_UNMAPPED 0x0107 -+#define STATUS_BUFFER_OVERFLOW 0x80000005 -+#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a -+#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001 -+#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002 -+#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003 -+#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004 -+#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005 -+#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006 -+#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007 -+#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008 -+#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009 -+#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a -+#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b -+#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c -+#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d -+#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e -+#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f -+#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010 -+#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011 -+#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012 -+#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013 -+#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014 -+#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015 -+#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016 -+#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017 -+#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018 -+#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019 -+#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a -+#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b -+#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c -+#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d -+#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e -+#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f -+#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020 -+#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021 -+#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022 -+#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023 -+#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024 -+#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025 -+#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026 -+#define NT_STATUS_UNWIND 0xC0000000 | 0x0027 -+#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028 -+#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029 -+#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a -+#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b -+#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c -+#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d -+#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e -+#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f -+#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030 -+#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031 -+#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032 -+#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033 -+#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034 -+#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035 -+#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036 -+#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037 -+#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038 -+#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039 -+#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a -+#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b -+#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c -+#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d -+#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e -+#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f -+#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040 -+#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041 -+#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042 -+#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043 -+#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044 -+#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045 -+#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046 -+#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047 -+#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048 -+#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049 -+#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a -+#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b -+#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c -+#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d -+#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e -+#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f -+#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050 -+#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051 -+#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052 -+#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053 -+#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054 -+#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055 -+#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056 -+#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057 -+#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058 -+#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059 -+#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a -+#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b -+#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c -+#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d -+#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e -+#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f -+#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060 -+#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061 -+#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062 -+#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063 -+#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064 -+#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065 -+#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066 -+#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067 -+#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068 -+#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069 -+#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a -+#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b -+#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c -+#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d -+#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e -+#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f -+#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070 -+#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071 -+#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072 -+#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073 -+#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074 -+#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075 -+#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076 -+#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077 -+#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078 -+#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079 -+#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a -+#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b -+#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c -+#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d -+#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e -+#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f -+#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080 -+#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081 -+#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082 -+#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083 -+#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084 -+#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085 -+#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086 -+#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087 -+#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088 -+#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089 -+#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a -+#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b -+#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c -+#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d -+#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e -+#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f -+#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090 -+#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091 -+#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092 -+#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093 -+#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094 -+#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095 -+#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096 -+#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097 -+#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098 -+#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099 -+#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a -+#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b -+#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c -+#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d -+#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e -+#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f -+#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0 -+#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1 -+#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2 -+#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3 -+#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4 -+#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5 -+#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6 -+#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7 -+#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8 -+#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9 -+#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa -+#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab -+#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac -+#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad -+#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae -+#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af -+#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0 -+#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1 -+#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2 -+#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3 -+#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4 -+#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5 -+#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6 -+#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7 -+#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8 -+#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9 -+#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba -+#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb -+#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc -+#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd -+#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be -+#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf -+#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0 -+#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1 -+#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2 -+#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3 -+#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4 -+#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5 -+#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6 -+#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7 -+#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8 -+#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9 -+#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca -+#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb -+#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc -+#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd -+#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce -+#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf -+#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0 -+#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1 -+#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2 -+#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3 -+#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4 -+#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5 -+#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6 -+#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7 -+#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8 -+#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9 -+#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da -+#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db -+#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc -+#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd -+#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de -+#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df -+#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0 -+#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1 -+#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2 -+#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3 -+#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4 -+#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5 -+#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6 -+#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7 -+#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8 -+#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9 -+#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea -+#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb -+#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec -+#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed -+#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee -+#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef -+#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0 -+#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1 -+#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2 -+#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3 -+#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4 -+#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5 -+#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6 -+#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7 -+#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8 -+#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9 -+#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa -+#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb -+#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc -+#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd -+#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe -+#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff -+#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101 -+#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102 -+#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103 -+#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104 -+#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105 -+#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106 -+#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107 -+#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108 -+#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109 -+#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a -+#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b -+#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c -+#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d -+#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e -+#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f -+#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110 -+#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111 -+#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112 -+#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113 -+#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114 -+#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115 -+#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116 -+#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117 -+#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118 -+#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119 -+#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a -+#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b -+#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c -+#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d -+#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e -+#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f -+#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120 -+#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121 -+#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122 -+#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123 -+#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124 -+#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125 -+#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126 -+#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127 -+#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128 -+#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129 -+#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a -+#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b -+#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c -+#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d -+#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e -+#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f -+#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130 -+#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131 -+#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132 -+#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133 -+#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134 -+#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135 -+#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136 -+#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137 -+#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138 -+#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139 -+#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a -+#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b -+#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c -+#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d -+#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e -+#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f -+#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140 -+#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141 -+#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142 -+#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143 -+#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144 -+#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145 -+#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146 -+#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147 -+#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148 -+#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149 -+#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a -+#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b -+#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c -+#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d -+#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e -+#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f -+#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150 -+#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151 -+#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152 -+#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153 -+#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154 -+#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155 -+#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156 -+#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157 -+#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158 -+#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159 -+#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a -+#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b -+#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c -+#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d -+#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e -+#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f -+#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160 -+#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161 -+#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162 -+#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163 -+#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164 -+#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165 -+#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166 -+#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167 -+#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168 -+#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169 -+#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a -+#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b -+#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c -+#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d -+#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172 -+#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173 -+#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174 -+#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175 -+#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176 -+#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177 -+#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178 -+#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a -+#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b -+#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c -+#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d -+#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e -+#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f -+#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180 -+#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181 -+#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182 -+#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183 -+#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184 -+#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185 -+#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186 -+#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187 -+#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188 -+#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189 -+#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a -+#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b -+#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c -+#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d -+#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e -+#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f -+#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190 -+#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191 -+#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192 -+#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193 -+#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194 -+#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195 -+#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196 -+#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197 -+#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198 -+#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199 -+#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a -+#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b -+#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c -+#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202 -+#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203 -+#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204 -+#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205 -+#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206 -+#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207 -+#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208 -+#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209 -+#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a -+#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b -+#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c -+#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d -+#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e -+#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f -+#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210 -+#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211 -+#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212 -+#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213 -+#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214 -+#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215 -+#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216 -+#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217 -+#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218 -+#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219 -+#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a -+#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b -+#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c -+#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d -+#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e -+#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f -+#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220 -+#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221 -+#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222 -+#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223 -+#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224 -+#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225 -+#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226 -+#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227 -+#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228 -+#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229 -+#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a -+#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b -+#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c -+#define NT_STATUS_RETRY 0xC0000000 | 0x022d -+#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e -+#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f -+#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230 -+#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231 -+#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232 -+#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233 -+#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234 -+#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235 -+#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236 -+#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237 -+#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238 -+#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239 -+#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a -+#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b -+#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c -+#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d -+#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e -+#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f -+#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240 -+#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241 -+#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242 -+#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243 -+#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244 -+#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245 -+#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246 -+#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247 -+#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248 -+#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249 -+#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250 -+#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251 -+#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252 -+#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253 -+#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254 -+#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255 -+#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256 -+#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257 -+#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258 -+#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259 -+#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a -+#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b -+#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c -+#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e -+#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f -+#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260 -+#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261 -+#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262 -+#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263 -+#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264 -+#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265 -+#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266 -+#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267 -+#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */ -+ -+#endif /* _NTERR_H */ ---- /dev/null -+++ b/fs/cifs/ntlmssp.h -@@ -0,0 +1,101 @@ -+/* -+ * fs/cifs/ntlmssp.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 -+ */ -+ -+#pragma pack(1) -+ -+#define NTLMSSP_SIGNATURE "NTLMSSP" -+/* Message Types */ -+#define NtLmNegotiate 1 -+#define NtLmChallenge 2 -+#define NtLmAuthenticate 3 -+#define UnknownMessage 8 -+ -+/* Negotiate Flags */ -+#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode -+#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM -+#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm -+#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability -+#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality -+#define NTLMSSP_NEGOTIATE_DGRAM 0x0040 -+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal -+#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication -+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 -+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000 -+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine -+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels -+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 -+#define NTLMSSP_TARGET_TYPE_SERVER 0x20000 -+#define NTLMSSP_TARGET_TYPE_SHARE 0x40000 -+#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000 -+#define NTLMSSP_REQUEST_INIT_RESP 0x100000 -+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 -+#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000 -+#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000 -+#define NTLMSSP_NEGOTIATE_128 0x20000000 -+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 -+#define NTLMSSP_NEGOTIATE_56 0x80000000 -+ -+/* Although typedefs are not commonly used for structure definitions */ -+/* in the Linux kernel, in this particular case they are useful */ -+/* to more closely match the standards document for NTLMSSP from */ -+/* OpenGroup and to make the code more closely match the standard in */ -+/* appearance */ -+ -+typedef struct _SECURITY_BUFFER { -+ __u16 Length; -+ __u16 MaximumLength; -+ __u32 Buffer; /* offset to buffer */ -+} SECURITY_BUFFER; -+ -+typedef struct _NEGOTIATE_MESSAGE { -+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; -+ __u32 MessageType; /* 1 */ -+ __u32 NegotiateFlags; -+ SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ -+ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ -+ char DomainString[0]; -+ /* followed by WorkstationString */ -+} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; -+ -+typedef struct _CHALLENGE_MESSAGE { -+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; -+ __u32 MessageType; /* 2 */ -+ SECURITY_BUFFER TargetName; -+ __u32 NegotiateFlags; -+ __u8 Challenge[CIFS_CRYPTO_KEY_SIZE]; -+ __u8 Reserved[8]; -+ SECURITY_BUFFER TargetInfoArray; -+} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; -+ -+typedef struct _AUTHENTICATE_MESSAGE { -+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; -+ __u32 MessageType; /* 3 */ -+ SECURITY_BUFFER LmChallengeResponse; -+ SECURITY_BUFFER NtChallengeResponse; -+ SECURITY_BUFFER DomainName; -+ SECURITY_BUFFER UserName; -+ SECURITY_BUFFER WorkstationName; -+ SECURITY_BUFFER SessionKey; -+ __u32 NegotiateFlags; -+ char UserString[0]; -+} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; -+ -+#pragma pack() /* resume default structure packing */ ---- /dev/null -+++ b/fs/cifs/README -@@ -0,0 +1,356 @@ -+The CIFS VFS support for Linux supports many advanced network filesystem -+features such as heirarchical dfs like namespace, 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: -+================== -+For Linux 2.4: -+1) Get the kernel source (e.g.from http://www.kernel.org) -+and download the cifs vfs source (see the project page -+at http://us1.samba.org/samba/Linux_CIFS_client.html) -+and change directory into the top of the kernel directory -+then patch the kernel (e.g. "patch -p1 < cifs_24.patch") -+to add the cifs vfs to your kernel configure options if -+it has not already been added (e.g. current SuSE and UL -+users do not need to apply the cifs_24.patch since the cifs vfs is -+already in the kernel configure menu) and then -+mkdir linux/fs/cifs and then copy the current cifs vfs files from -+the cifs download to your kernel build directory e.g. -+ -+ cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs -+ -+2) make menuconfig (or make xconfig) -+3) select cifs from within the network filesystem choices -+4) save and exit -+5) make dep -+6) make modules (or "make" if CIFS VFS not to be built as a module) -+ -+For Linux 2.5: -+1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper -+at bk://linux.bkbits.net/linux-2.5) and change directory into the top -+of the kernel directory tree (e.g. /usr/src/linux-2.5.73) -+2) make menuconfig (or make xconfig) -+3) select cifs from within the network filesystem choices -+4) save and exit -+5) make -+ -+ -+Installation instructions: -+========================= -+If you have built the CIFS vfs as module (successfully) 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 same directory in which mount.smbfs and -+similar files reside (usually /sbin). Although the helper software is not -+required, 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 who are used to Windows e.g. net use <mount point> <UNC name or cifs URL> -+Note that running the Winbind pam/nss module (logon service) on all of your -+Linux clients is useful in mapping Uids and Gids consistently across the -+domain to the proper network user. The mount.cifs mount helper can be -+trivially built from Samba 3.0 or later source e.g. by executing: -+ -+ gcc samba/source/client/mount.cifs.c -o mount.cifs -+ -+Note that when the mount.cifs utility is run suid (allowing user mounts), -+in order to reduce risks, the "nosuid" mount flag is passed in on mount to -+disallow execution of an suid program mounted on the remote target. -+When mount is executed as root, nosuid is not passed in by default, -+and execution of suid programs on the remote target would be enabled -+by default. This can be changed, as with nfs and other filesystems, -+by simply specifying "nosuid" among the mount options. For user mounts -+though to be able to pass the suid flag to mount requires rebuilding -+mount.cifs with the following flag: -+ -+ gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs -+ -+There is a corresponding manual page for cifs mounting in the Samba 3.0 and -+later source tree in docs/manpages/mount.cifs.8 -+ -+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 later or -+Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers. -+Note that 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.5 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 -+ ea support = yes -+ -+Note that ea support is required for supporting Linux xattrs. -+Some administrators also change the "map archive" and the "create mask" -+parameters from their default values. Creating special devices (mknod) -+remotely may require specifying a mkdev function to Samba if you are not using -+Samba 3.0.5 or later. 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). -+Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete -+open files (required for strict POSIX compliance). Windows Servers already -+supported this feature. Samba server does not allow symlinks that refer to files -+outside of the share, so in Samba versions prior to 3.0.5, most symlinks to -+files with absolute paths (ie beginning with slash) such as: -+ ln -s /mnt/foo bar -+would be forbidden. Samba 3.0.5 server or later includes the ability to create -+such symlinks safely by converting unsafe symlinks (ie symlinks to server -+files that are outside of the share) to a samba specific format on the server -+that is ignored by local server applications and non-cifs clients and that will -+not be traversed by the Samba server). This is opaque to the Linux client -+application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or -+later, but only for remote clients using the CIFS Unix extensions, and will -+be invisbile to Windows clients and typically will not affect local -+applications running on the same server as Samba. -+ -+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 -+ -+Before -o the option -v may be specified to make the mount.cifs -+mount helper display the mount steps more verbosely. -+After -o the following commonly used cifs vfs specific options -+are supported: -+ -+ user=<username> -+ pass=<password> -+ domain=<domain name> -+ -+Other cifs mount options are described below. Use of TCP names (in addition to -+ip addresses) is available if the mount helper (mount.cifs) is installed. If -+you do not trust the server to which are mounted, or if you do not have -+cifs signing enabled (and the physical network is insecure), consider use -+of the standard mount options "noexec" and "nosuid" to reduce the risk of -+running an altered binary on your local system (downloaded from a hostile server -+or altered by a hostile router). -+ -+When using the mount helper mount.cifs, passwords may be specified via alternate -+mechanisms, instead of specifying it after -o using the normal "pass=" syntax -+on the command line: -+1) By including it in a credential file. Specify credentials=filename as one -+of the mount options. Credential files contain two lines -+ username=someuser -+ password=your_password -+2) By specifying the password in the PASSWD environment variable (similarly -+the user name can be taken from the USER environment variable). -+3) By specifying the password in a file by name via PASSWD_FILE -+4) By specifying the password in a file by file descriptor via PASSWD_FD -+ -+If no password is provided, mount.cifs will prompt for password entry -+ -+Restrictions -+============ -+Servers must support the NTLM SMB dialect (which is the most recent, supported -+by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers) -+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. -+ -+CIFS VFS Mount Options -+====================== -+A partial list of the supported mount options follows: -+ user The user name to use when trying to establish -+ the CIFS session. -+ password The user password. If the mount helper is -+ installed, the user will be prompted for password -+ if it is not supplied. -+ ip The ip address of the target server -+ unc The target server Universal Network Name (export) to -+ mount. -+ domain Set the SMB/CIFS workgroup name prepended to the -+ username during CIFS session establishment -+ uid If CIFS Unix extensions are not supported by the server -+ this overrides the default uid for inodes. For mounts to -+ servers which do support the CIFS Unix extensions, such -+ as a properly configured Samba server, the server provides -+ the uid, gid and mode. For servers which do not support -+ the Unix extensions, the default uid (and gid) returned on -+ lookup of existing files is the uid (gid) of the person -+ who executed the mount (root, except when mount.cifs -+ is configured setuid for user mounts) unless the "uid=" -+ (gid) mount option is specified. For the uid (gid) of newly -+ created files and directories, ie files created since -+ the last mount of the server share, the expected uid -+ (gid) is cached as as long as the inode remains in -+ memory on the client. Also note that permission -+ checks (authorization checks) on accesses to a file occur -+ at the server, but there are cases in which an administrator -+ may want to restrict at the client as well. For those -+ servers which do not report a uid/gid owner -+ (such as Windows), permissions can also be checked at the -+ client, and a crude form of client side permission checking -+ can be enabled by specifying file_mode and dir_mode on -+ the client -+ gid If CIFS Unix extensions are not supported by the server -+ this overrides the default gid for inodes. -+ file_mode If CIFS Unix extensions are not supported by the server -+ this overrides the default mode for file inodes. -+ dir_mode If CIFS Unix extensions are not supported by the server -+ this overrides the default mode for directory inodes. -+ port attempt to contact the server on this tcp port, before -+ trying the usual ports (port 445, then 139). -+ iocharset Codepage used to convert local path names to and from -+ Unicode. Unicode is used by default for network path -+ names if the server supports it. If iocharset is -+ not specified then the nls_default specified -+ during the local client kernel build will be used. -+ If server does not support Unicode, this parameter is -+ unused. -+ rsize default read size -+ wsize default write size -+ rw mount the network share read-write (note that the -+ server may still consider the share read-only) -+ ro mount network share read-only -+ version used to distinguish different versions of the -+ mount helper utility (not typically needed) -+ sep if first mount option (after the -o), overrides -+ the comma as the separator between the mount -+ parms. e.g. -+ -o user=myname,password=mypassword,domain=mydom -+ could be passed instead with period as the separator by -+ -o sep=.user=myname.password=mypassword.domain=mydom -+ this might be useful when comma is contained within username -+ or password or domain. This option is less important -+ when the cifs mount helper cifs.mount (version 1.1 or later) -+ is used. -+ nosuid Do not allow remote executables with the suid bit -+ program to be executed. This is only meaningful for mounts -+ to servers such as Samba which support the CIFS Unix Extensions. -+ If you do not trust the servers in your network (your mount -+ targets) it is recommended that you specify this option for -+ greater security. -+ suid Allow remote files on this mountpoint with suid enabled to -+ be executed (default for mounts when executed as root, -+ nosuid is default for user mounts). -+ credentials Although ignored by the cifs kernel component, it is used by -+ the mount helper, mount.cifs. When mount.cifs is installed it -+ opens and reads the credential file specified in order -+ to obtain the userid and password arguments which are passed to -+ the cifs vfs. -+ guest Although ignored by the kernel component, the mount.cifs -+ mount helper will not prompt the user for a password -+ if guest is specified on the mount options. If no -+ password is specified a null password will be used. -+ -+The mount.cifs mount helper also accepts a few mount options before -o -+including: -+ -+ -S take password from stdin (equivalent to setting the environment -+ variable "PASSWD_FD=0" -+ -V print mount.cifs version -+ -? display simple usage information -+ -+With recent 2.6 kernel versions of modutils, the version of the cifs kernel -+module can be displayed via modinfo. -+ -+Misc /proc/fs/cifs Flags and Debug Info -+======================================= -+Informational pseudo-files: -+DebugData Displays information about active CIFS sessions -+ and shares. -+Stats Lists summary resource usage information as well as per -+ share statistics, if CONFIG_CIFS_STATS in enabled -+ in the kernel configuration. -+ -+Configuration pseudo-files: -+MultiuserMount If set to one, more than one CIFS session to -+ the same server ip address can be established -+ if more than one uid accesses the same mount -+ point and if the uids user/password mapping -+ information is available. (default is 0) -+PacketSigningEnabled If set to one, cifs packet signing is enabled -+ and will be used if the server requires -+ it. If set to two, cifs packet signing is -+ required even if the server considers packet -+ signing optional. (default 1) -+cifsFYI If set to one, additional debug information is -+ logged to the system error log. (default 0) -+ExtendedSecurity If set to one, SPNEGO session establishment -+ is allowed which enables more advanced -+ secure CIFS session establishment (default 0) -+NTLMV2Enabled If set to one, more secure password hashes -+ are used when the server supports them and -+ when kerberos is not negotiated (default 0) -+traceSMB If set to one, debug information is logged to the -+ system error log with the start of smb requests -+ and responses (default 0) -+LookupCacheEnable If set to one, inode information is kept cached -+ for one second improving performance of lookups -+ (default 1) -+OplockEnabled If set to one, safe distributed caching enabled. -+ (default 1) -+LinuxExtensionsEnabled If set to one then the client will attempt to -+ use the CIFS "UNIX" extensions which are optional -+ protocol enhancements that allow CIFS servers -+ to return accurate UID/GID information as well -+ as support symbolic links. If you use servers -+ such as Samba that support the CIFS Unix -+ extensions but do not want to use symbolic link -+ support and want to map the uid and gid fields -+ to values supplied at mount (rather than the -+ actual values, then set this to zero. (default 1) -+ -+These 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 set it to 1 e.g. to enable -+tracing to the kernel message log type: -+ -+ echo 1 > /proc/fs/cifs/cifsFYI -+ -+and for more extensive tracing including the start of smb requests and responses -+ -+ echo 1 > /proc/fs/cifs/traceSMB -+ -+Three other experimental features are under development and to test -+require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h) -+ -+ CONFIG_CIFS_QUOTA -+ -+ CONFIG_CIFS_XATTR -+ -+ CONFIG_CIFS_FCNTL (fcntl needed for support of directory change -+ notification and perhaps later for file leases) -+ -+Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData -+if the kernel was configured with cifs statistics enabled. The statistics -+represent the number of successful (ie non-zero return code from the server) -+SMB responses to some of the more common commands (open, delete, mkdir etc.). -+Also recorded is the total bytes read and bytes written to the server for -+that share. Note that due to client caching effects this can be less than the -+number of bytes read and written by the application running on the client. -+The statistics for the number of total SMBs and oplock breaks are different in -+that they represent all for that share, not just those for which the server -+returned success. -+ -+Also note that "cat /proc/fs/cifs/DebugData" will display information about -+the active sessions and the shares that are mounted. Note: NTLMv2 enablement -+will not work since they its implementation is not quite complete yet. -+Do not alter these configuration values 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). ---- /dev/null -+++ b/fs/cifs/rfc1002pdu.h -@@ -0,0 +1,79 @@ -+/* -+ * fs/cifs/rfc1002pdu.h -+ * -+ * Protocol Data Unit definitions for RFC 1001/1002 support -+ * -+ * Copyright (c) International Business Machines Corp., 2004 -+ * 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 -+ */ -+ -+#pragma pack(1) -+ -+/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */ -+ -+ /* RFC 1002 session packet types */ -+#define RFC1002_SESSION_MESASAGE 0x00 -+#define RFC1002_SESSION_REQUEST 0x81 -+#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82 -+#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83 -+#define RFC1002_RETARGET_SESSION_RESPONSE 0x83 -+#define RFC1002_SESSION_KEEP_ALIVE 0x85 -+ -+ /* RFC 1002 flags (only one defined */ -+#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */ -+ -+struct rfc1002_session_packet { -+ __u8 type; -+ __u8 flags; -+ __u16 length; -+ union { -+ struct { -+ __u8 called_len; -+ __u8 called_name[32]; -+ __u8 scope1; /* null */ -+ __u8 calling_len; -+ __u8 calling_name[32]; -+ __u8 scope2; /* null */ -+ } session_req; -+ struct { -+ __u32 retarget_ip_addr; -+ __u16 port; -+ } retarget_resp; -+ __u8 neg_ses_resp_error_code; -+ /* POSITIVE_SESSION_RESPONSE packet does not include trailer. -+ SESSION_KEEP_ALIVE packet also does not include a trailer. -+ Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */ -+ } trailer; -+}; -+ -+/* Negative Session Response error codes */ -+#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */ -+#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */ -+#define RFC1002_NOT_PRESENT 0x82 /* called name not present */ -+#define RFC1002_INSUFFICIENT_RESOURCE 0x83 -+#define RFC1002_UNSPECIFIED_ERROR 0x8F -+ -+/* RFC 1002 Datagram service packets are not defined here as they -+are not needed for the network filesystem client unless we plan on -+implementing broadcast resolution of the server ip address (from -+server netbios name). Currently server names are resolved only via DNS -+(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/ -+ -+#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER " -+ -+#pragma pack() /* resume default structure packing */ -+ ---- /dev/null -+++ b/fs/cifs/smbdes.c -@@ -0,0 +1,408 @@ -+/* -+ Unix SMB/Netbios implementation. -+ Version 1.9. -+ -+ a partial implementation of DES designed for use in the -+ SMB authentication protocol -+ -+ Copyright (C) Andrew Tridgell 1998 -+ Modified by Steve French (sfrench@us.ibm.com) 2002,2004 -+ -+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+/* NOTES: -+ -+ This code makes no attempt to be fast! In fact, it is a very -+ slow implementation -+ -+ This code is NOT a complete DES implementation. It implements only -+ the minimum necessary for SMB authentication, as used by all SMB -+ products (including every copy of Microsoft Windows95 ever sold) -+ -+ In particular, it can only do a unchained forward DES pass. This -+ means it is not possible to use this code for encryption/decryption -+ of data, instead it is only useful as a "hash" algorithm. -+ -+ There is no entry point into this code that allows normal DES operation. -+ -+ I believe this means that this code does not come under ITAR -+ regulations but this is NOT a legal opinion. If you are concerned -+ about the applicability of ITAR regulations to this code then you -+ should confirm it for yourself (and maybe let me know if you come -+ up with a different answer to the one above) -+*/ -+#include <linux/slab.h> -+#define uchar unsigned char -+ -+static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9, -+ 1, 58, 50, 42, 34, 26, 18, -+ 10, 2, 59, 51, 43, 35, 27, -+ 19, 11, 3, 60, 52, 44, 36, -+ 63, 55, 47, 39, 31, 23, 15, -+ 7, 62, 54, 46, 38, 30, 22, -+ 14, 6, 61, 53, 45, 37, 29, -+ 21, 13, 5, 28, 20, 12, 4 -+}; -+ -+static uchar perm2[48] = { 14, 17, 11, 24, 1, 5, -+ 3, 28, 15, 6, 21, 10, -+ 23, 19, 12, 4, 26, 8, -+ 16, 7, 27, 20, 13, 2, -+ 41, 52, 31, 37, 47, 55, -+ 30, 40, 51, 45, 33, 48, -+ 44, 49, 39, 56, 34, 53, -+ 46, 42, 50, 36, 29, 32 -+}; -+ -+static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2, -+ 60, 52, 44, 36, 28, 20, 12, 4, -+ 62, 54, 46, 38, 30, 22, 14, 6, -+ 64, 56, 48, 40, 32, 24, 16, 8, -+ 57, 49, 41, 33, 25, 17, 9, 1, -+ 59, 51, 43, 35, 27, 19, 11, 3, -+ 61, 53, 45, 37, 29, 21, 13, 5, -+ 63, 55, 47, 39, 31, 23, 15, 7 -+}; -+ -+static uchar perm4[48] = { 32, 1, 2, 3, 4, 5, -+ 4, 5, 6, 7, 8, 9, -+ 8, 9, 10, 11, 12, 13, -+ 12, 13, 14, 15, 16, 17, -+ 16, 17, 18, 19, 20, 21, -+ 20, 21, 22, 23, 24, 25, -+ 24, 25, 26, 27, 28, 29, -+ 28, 29, 30, 31, 32, 1 -+}; -+ -+static uchar perm5[32] = { 16, 7, 20, 21, -+ 29, 12, 28, 17, -+ 1, 15, 23, 26, -+ 5, 18, 31, 10, -+ 2, 8, 24, 14, -+ 32, 27, 3, 9, -+ 19, 13, 30, 6, -+ 22, 11, 4, 25 -+}; -+ -+static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32, -+ 39, 7, 47, 15, 55, 23, 63, 31, -+ 38, 6, 46, 14, 54, 22, 62, 30, -+ 37, 5, 45, 13, 53, 21, 61, 29, -+ 36, 4, 44, 12, 52, 20, 60, 28, -+ 35, 3, 43, 11, 51, 19, 59, 27, -+ 34, 2, 42, 10, 50, 18, 58, 26, -+ 33, 1, 41, 9, 49, 17, 57, 25 -+}; -+ -+static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; -+ -+static uchar sbox[8][4][16] = { -+ {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, -+ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, -+ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, -+ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}}, -+ -+ {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, -+ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, -+ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, -+ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}}, -+ -+ {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, -+ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, -+ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, -+ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}}, -+ -+ {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, -+ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, -+ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, -+ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}}, -+ -+ {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, -+ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, -+ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, -+ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}}, -+ -+ {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, -+ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, -+ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, -+ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}}, -+ -+ {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, -+ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, -+ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, -+ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}}, -+ -+ {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, -+ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, -+ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, -+ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}} -+}; -+ -+static void -+permute(char *out, char *in, uchar * p, int n) -+{ -+ int i; -+ for (i = 0; i < n; i++) -+ out[i] = in[p[i] - 1]; -+} -+ -+static void -+lshift(char *d, int count, int n) -+{ -+ char out[64]; -+ int i; -+ for (i = 0; i < n; i++) -+ out[i] = d[(i + count) % n]; -+ for (i = 0; i < n; i++) -+ d[i] = out[i]; -+} -+ -+static void -+concat(char *out, char *in1, char *in2, int l1, int l2) -+{ -+ while (l1--) -+ *out++ = *in1++; -+ while (l2--) -+ *out++ = *in2++; -+} -+ -+static void -+xor(char *out, char *in1, char *in2, int n) -+{ -+ int i; -+ for (i = 0; i < n; i++) -+ out[i] = in1[i] ^ in2[i]; -+} -+ -+static void -+dohash(char *out, char *in, char *key, int forw) -+{ -+ int i, j, k; -+ char *pk1; -+ char c[28]; -+ char d[28]; -+ char *cd; -+ char ki[16][48]; -+ char *pd1; -+ char l[32], r[32]; -+ char *rl; -+ -+ /* Have to reduce stack usage */ -+ pk1 = kmalloc(56+56+64+64,GFP_KERNEL); -+ if(pk1 == NULL) -+ return; -+ -+ cd = pk1 + 56; -+ pd1= cd + 56; -+ rl = pd1 + 64; -+ -+ permute(pk1, key, perm1, 56); -+ -+ for (i = 0; i < 28; i++) -+ c[i] = pk1[i]; -+ for (i = 0; i < 28; i++) -+ d[i] = pk1[i + 28]; -+ -+ for (i = 0; i < 16; i++) { -+ lshift(c, sc[i], 28); -+ lshift(d, sc[i], 28); -+ -+ concat(cd, c, d, 28, 28); -+ permute(ki[i], cd, perm2, 48); -+ } -+ -+ permute(pd1, in, perm3, 64); -+ -+ for (j = 0; j < 32; j++) { -+ l[j] = pd1[j]; -+ r[j] = pd1[j + 32]; -+ } -+ -+ for (i = 0; i < 16; i++) { -+ char *er; /* er[48] */ -+ char *erk; /* erk[48] */ -+ char b[8][6]; -+ char *cb; /* cb[32] */ -+ char *pcb; /* pcb[32] */ -+ char *r2; /* r2[32] */ -+ -+ er = kmalloc(48+48+32+32+32, GFP_KERNEL); -+ if(er == NULL) { -+ kfree(pk1); -+ return; -+ } -+ erk = er+48; -+ cb = erk+48; -+ pcb = cb+32; -+ r2 = pcb+32; -+ -+ permute(er, r, perm4, 48); -+ -+ xor(erk, er, ki[forw ? i : 15 - i], 48); -+ -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 6; k++) -+ b[j][k] = erk[j * 6 + k]; -+ -+ for (j = 0; j < 8; j++) { -+ int m, n; -+ m = (b[j][0] << 1) | b[j][5]; -+ -+ n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << -+ 1) | b[j][4]; -+ -+ for (k = 0; k < 4; k++) -+ b[j][k] = -+ (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0; -+ } -+ -+ for (j = 0; j < 8; j++) -+ for (k = 0; k < 4; k++) -+ cb[j * 4 + k] = b[j][k]; -+ permute(pcb, cb, perm5, 32); -+ -+ xor(r2, l, pcb, 32); -+ -+ for (j = 0; j < 32; j++) -+ l[j] = r[j]; -+ -+ for (j = 0; j < 32; j++) -+ r[j] = r2[j]; -+ -+ kfree(er); -+ } -+ -+ concat(rl, r, l, 32, 32); -+ -+ permute(out, rl, perm6, 64); -+ kfree(pk1); -+} -+ -+static void -+str_to_key(unsigned char *str, unsigned char *key) -+{ -+ int i; -+ -+ key[0] = str[0] >> 1; -+ key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); -+ key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); -+ key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); -+ key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); -+ key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); -+ key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); -+ key[7] = str[6] & 0x7F; -+ for (i = 0; i < 8; i++) { -+ key[i] = (key[i] << 1); -+ } -+} -+ -+static void -+smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw) -+{ -+ int i; -+ char *outb; /* outb[64] */ -+ char *inb; /* inb[64] */ -+ char *keyb; /* keyb[64] */ -+ unsigned char key2[8]; -+ -+ outb = kmalloc(64 * 3,GFP_KERNEL); -+ if(outb == NULL) -+ return; -+ -+ inb = outb + 64; -+ keyb = inb + 64; -+ -+ str_to_key(key, key2); -+ -+ for (i = 0; i < 64; i++) { -+ inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; -+ keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; -+ outb[i] = 0; -+ } -+ -+ dohash(outb, inb, keyb, forw); -+ -+ for (i = 0; i < 8; i++) { -+ out[i] = 0; -+ } -+ -+ for (i = 0; i < 64; i++) { -+ if (outb[i]) -+ out[i / 8] |= (1 << (7 - (i % 8))); -+ } -+ kfree(outb); -+} -+ -+void -+E_P16(unsigned char *p14, unsigned char *p16) -+{ -+ unsigned char sp8[8] = -+ { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; -+ smbhash(p16, sp8, p14, 1); -+ smbhash(p16 + 8, sp8, p14 + 7, 1); -+} -+ -+void -+E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) -+{ -+ smbhash(p24, c8, p21, 1); -+ smbhash(p24 + 8, c8, p21 + 7, 1); -+ smbhash(p24 + 16, c8, p21 + 14, 1); -+} -+ -+void -+D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) -+{ -+ smbhash(out, in, p14, 0); -+ smbhash(out + 8, in + 8, p14 + 7, 0); -+} -+ -+void -+E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out) -+{ -+ smbhash(out, in, p14, 1); -+ smbhash(out + 8, in + 8, p14 + 7, 1); -+} -+ -+void -+cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key) -+{ -+ unsigned char buf[8]; -+ -+ smbhash(buf, in, key, 1); -+ smbhash(out, buf, key + 9, 1); -+} -+ -+void -+cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key) -+{ -+ unsigned char buf[8]; -+ static unsigned char key2[8]; -+ -+ smbhash(buf, in, key, 1); -+ key2[0] = key[7]; -+ smbhash(out, buf, key2, 1); -+} -+ -+void -+cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw) -+{ -+ static unsigned char key2[8]; -+ -+ smbhash(out, in, key, forw); -+ key2[0] = key[7]; -+ smbhash(out + 8, in + 8, key2, forw); -+} ---- /dev/null -+++ b/fs/cifs/smbencrypt.c -@@ -0,0 +1,295 @@ -+/* -+ Unix SMB/Netbios implementation. -+ Version 1.9. -+ SMB parameters and setup -+ Copyright (C) Andrew Tridgell 1992-2000 -+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000 -+ Modified by Jeremy Allison 1995. -+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 -+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003 -+ -+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#include <linux/module.h> -+#include <linux/fs.h> -+#include <linux/string.h> -+#include <linux/kernel.h> -+#include <linux/random.h> -+#include "cifs_unicode.h" -+#include "cifspdu.h" -+#include "md5.h" -+#include "cifs_debug.h" -+ -+#ifndef FALSE -+#define FALSE 0 -+#endif -+#ifndef TRUE -+#define TRUE 1 -+#endif -+ -+/* following came from the other byteorder.h to avoid include conflicts */ -+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) -+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) -+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) -+ -+/*The following definitions come from lib/md4.c */ -+ -+void mdfour(unsigned char *out, unsigned char *in, int n); -+ -+/*The following definitions come from libsmb/smbdes.c */ -+ -+void E_P16(unsigned char *p14, unsigned char *p16); -+void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); -+void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out); -+void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out); -+void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key); -+void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key); -+void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, -+ int forw); -+ -+/*The following definitions come from libsmb/smbencrypt.c */ -+ -+void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); -+void E_md4hash(const unsigned char *passwd, unsigned char *p16); -+void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]); -+void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, -+ unsigned char p24[24]); -+void NTLMSSPOWFencrypt(unsigned char passwd[8], -+ unsigned char *ntlmchalresp, unsigned char p24[24]); -+void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); -+int decode_pw_buffer(char in_buffer[516], char *new_pwrd, -+ int new_pwrd_size, __u32 * new_pw_len); -+ -+/* -+ This implements the X/Open SMB password encryption -+ It takes a password, a 8 byte "crypt key" and puts 24 bytes of -+ encrypted password into p24 */ -+/* Note that password must be uppercased and null terminated */ -+void -+SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) -+{ -+ unsigned char p14[15], p21[21]; -+ -+ memset(p21, '\0', 21); -+ memset(p14, '\0', 14); -+ strncpy((char *) p14, (char *) passwd, 14); -+ -+/* strupper((char *)p14); *//* BB at least uppercase the easy range */ -+ E_P16(p14, p21); -+ -+ SMBOWFencrypt(p21, c8, p24); -+ -+ memset(p14,0,15); -+ memset(p21,0,21); -+} -+ -+/* Routines for Windows NT MD4 Hash functions. */ -+static int -+_my_wcslen(__u16 * str) -+{ -+ int len = 0; -+ while (*str++ != 0) -+ len++; -+ return len; -+} -+ -+/* -+ * Convert a string into an NT UNICODE string. -+ * Note that regardless of processor type -+ * this must be in intel (little-endian) -+ * format. -+ */ -+ -+static int -+_my_mbstowcs(__u16 * dst, const unsigned char *src, int len) -+{ /* not a very good conversion routine - change/fix */ -+ int i; -+ __u16 val; -+ -+ for (i = 0; i < len; i++) { -+ val = *src; -+ SSVAL(dst, 0, val); -+ dst++; -+ src++; -+ if (val == 0) -+ break; -+ } -+ return i; -+} -+ -+/* -+ * Creates the MD4 Hash of the users password in NT UNICODE. -+ */ -+ -+void -+E_md4hash(const unsigned char *passwd, unsigned char *p16) -+{ -+ int len; -+ __u16 wpwd[129]; -+ -+ /* Password cannot be longer than 128 characters */ -+ if(passwd) { -+ len = strlen((char *) passwd); -+ if (len > 128) { -+ len = 128; -+ } -+ /* Password must be converted to NT unicode */ -+ _my_mbstowcs(wpwd, passwd, len); -+ } else -+ len = 0; -+ -+ wpwd[len] = 0; /* Ensure string is null terminated */ -+ /* Calculate length in bytes */ -+ len = _my_wcslen(wpwd) * sizeof (__u16); -+ -+ mdfour(p16, (unsigned char *) wpwd, len); -+ memset(wpwd,0,129 * 2); -+} -+ -+/* Does both the NT and LM owfs of a user's password */ -+void -+nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) -+{ -+ char passwd[514]; -+ -+ memset(passwd, '\0', 514); -+ if (strlen(pwd) < 513) -+ strcpy(passwd, pwd); -+ else -+ memcpy(passwd, pwd, 512); -+ /* Calculate the MD4 hash (NT compatible) of the password */ -+ memset(nt_p16, '\0', 16); -+ E_md4hash(passwd, nt_p16); -+ -+ /* Mangle the passwords into Lanman format */ -+ passwd[14] = '\0'; -+/* strupper(passwd); */ -+ -+ /* Calculate the SMB (lanman) hash functions of the password */ -+ -+ memset(p16, '\0', 16); -+ E_P16((unsigned char *) passwd, (unsigned char *) p16); -+ -+ /* clear out local copy of user's password (just being paranoid). */ -+ memset(passwd, '\0', sizeof (passwd)); -+} -+ -+/* Does the NTLMv2 owfs of a user's password */ -+void -+ntv2_owf_gen(const unsigned char owf[16], const char *user_n, -+ const char *domain_n, unsigned char kr_buf[16], -+ const struct nls_table *nls_codepage) -+{ -+ wchar_t * user_u; -+ wchar_t * dom_u; -+ int user_l, domain_l; -+ struct HMACMD5Context ctx; -+ -+ /* might as well do one alloc to hold both (user_u and dom_u) */ -+ user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL); -+ if(user_u == NULL) -+ return; -+ dom_u = user_u + 1024; -+ -+ /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); -+ push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */ -+ -+ /* BB user and domain may need to be uppercased */ -+ user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage); -+ domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage); -+ -+ user_l++; /* trailing null */ -+ domain_l++; -+ -+ hmac_md5_init_limK_to_64(owf, 16, &ctx); -+ hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx); -+ hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx); -+ hmac_md5_final(kr_buf, &ctx); -+ -+ kfree(user_u); -+} -+ -+/* Does the des encryption from the NT or LM MD4 hash. */ -+void -+SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, -+ unsigned char p24[24]) -+{ -+ unsigned char p21[21]; -+ -+ memset(p21, '\0', 21); -+ -+ memcpy(p21, passwd, 16); -+ E_P24(p21, c8, p24); -+} -+ -+/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ -+void -+NTLMSSPOWFencrypt(unsigned char passwd[8], -+ unsigned char *ntlmchalresp, unsigned char p24[24]) -+{ -+ unsigned char p21[21]; -+ -+ memset(p21, '\0', 21); -+ memcpy(p21, passwd, 8); -+ memset(p21 + 8, 0xbd, 8); -+ -+ E_P24(p21, ntlmchalresp, p24); -+} -+ -+/* Does the NT MD4 hash then des encryption. */ -+ -+void -+SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) -+{ -+ unsigned char p21[21]; -+ -+ memset(p21, '\0', 21); -+ -+ E_md4hash(passwd, p21); -+ SMBOWFencrypt(p21, c8, p24); -+} -+ -+/* Does the md5 encryption from the NT hash for NTLMv2. */ -+void -+SMBOWFencrypt_ntv2(const unsigned char kr[16], -+ const struct data_blob * srv_chal, -+ const struct data_blob * cli_chal, unsigned char resp_buf[16]) -+{ -+ struct HMACMD5Context ctx; -+ -+ hmac_md5_init_limK_to_64(kr, 16, &ctx); -+ hmac_md5_update(srv_chal->data, srv_chal->length, &ctx); -+ hmac_md5_update(cli_chal->data, cli_chal->length, &ctx); -+ hmac_md5_final(resp_buf, &ctx); -+} -+ -+void -+SMBsesskeygen_ntv2(const unsigned char kr[16], -+ const unsigned char *nt_resp, __u8 sess_key[16]) -+{ -+ struct HMACMD5Context ctx; -+ -+ hmac_md5_init_limK_to_64(kr, 16, &ctx); -+ hmac_md5_update(nt_resp, 16, &ctx); -+ hmac_md5_final((unsigned char *) sess_key, &ctx); -+} -+ -+void -+SMBsesskeygen_ntv1(const unsigned char kr[16], -+ const unsigned char *nt_resp, __u8 sess_key[16]) -+{ -+ mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16); -+} ---- /dev/null -+++ b/fs/cifs/smberr.c -@@ -0,0 +1,240 @@ -+/* -+ Unix SMB/Netbios implementation. -+ Version 1.9. -+ Copyright (C) Andrew Tridgell 1998 -+ Copyright (C) Steve French (sfrench@us.ibm.com) 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+include "smberr.h" -+#define NO_SYSLOG -+/* error code stuff - put together by Merik Karman -+ merik@blackadder.dsh.oz.au */ -+ typedef const struct { -+ char *name; -+ int code; -+ char *message; -+ int posix_code; -+} err_code_struct; -+ -+/* Dos Error Messages */ -+err_code_struct dos_msgs[] = { -+ {"ERRbadfunc", ERRbadfunc, "Invalid function.", -EINVAL}, -+ {"ERRbadfile", ERRbadfile, "File not found.", -ENOENT}, -+ {"ERRbadpath", ERRbadpath, "Directory invalid.", -ENOENT}, -+ {"ERRnofids", ERRnofids, "No file descriptors available", -EMFILE}, -+ {"ERRnoaccess", ERRnoaccess, "Access denied.", -EACCES}, -+ {"ERRbadfid", ERRbadfid, "Invalid file handle.", -EBADF}, -+ {"ERRbadmcb", 7, "Memory control blocks destroyed.", -EIO}, -+ {"ERRnomem", ERRnomem, -+ "Insufficient server memory to perform the requested function.", -+ -ENOMEM}, -+ {"ERRbadmem", ERRbadmem, "Invalid memory block address.", -EFAULT}, -+ {"ERRbadenv", ERRbadenv, "Invalid environment.", -EFAULT}, -+ {"ERRbadformat", 11, "Invalid format.", -EINVAL}, -+ {"ERRbadaccess", ERRbadaccess, "Invalid open mode." - EACCES}, -+ {"ERRbaddata", ERRbaddata, "Invalid data.", -EIO}, -+ {"ERR", ERRres, "reserved.", -EIO}, -+ {"ERRbaddrive", ERRbaddrive, "Invalid drive specified.", -ENXIO}, -+ {"ERRremcd", ERRremcd, -+ "A Delete Directory request attempted to remove the server's current directory.", -+ -EIO}, -+ {"ERRdiffdevice", ERRdiffdevice, "Not same device.", -EXDEV}, -+ {"ERRnofiles", ERRnofiles, "A File Search command can find no more files matching the specified criteria.", -ENOENT}, /* Note: must map to zero manually in some places such as readdir */ -+ {"ERRbadshare", ERRbadshare, -+ "The sharing mode specified for an Open conflicts with existing FIDs on the file.", -+ -EXTBSY}, -+ {"ERRlock", ERRlock, -+ "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process.", -+ -EACCES}, -+ {"ERRunsup", ERRunsup, "The operation is unsupported", -EINVAL}, -+ {"ERRnosuchshare", ERRnosuchshare, -+ "You specified an invalid share name", -ENXIO}, -+ {"ERRfilexists", ERRfilexists, -+ "The file named in a Create Directory, Make New File or Link request already exists.", -+ -EEXIST}, -+ {"ERRinvalidname", ERRinvalidname, "Invalid name", -ENOENT}, -+ {"ERRdiskfull", ERRdiskfull, "Disk full", -ENOSPC} -+ -+ {"ERRmoredata", ERRmoredata, -+ "There is more data to be returned.",}, -+ {"ERRinvgroup", 2455, "Invalid workgroup (try the -W option)"}, -+ {NULL, -1, NULL, -EIO} -+}; -+ -+/* Server Error Messages */ -+err_code_struct server_msgs[] = { -+ {"ERRerror", 1, "Non-specific error code."}, -+ {"ERRbadpw", 2, -+ "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."}, -+ {"ERRbadtype", 3, "reserved."}, -+ {"ERRaccess", 4, -+ "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."}, -+ {"ERRinvnid", 5, -+ "The tree ID (TID) specified in a command was invalid."}, -+ {"ERRinvnetname", 6, "Invalid network name in tree connect."}, -+ {"ERRinvdevice", 7, -+ "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."}, -+ {"ERRqfull", 49, -+ "Print queue full (files) -- returned by open print file."}, -+ {"ERRqtoobig", 50, "Print queue full -- no space."}, -+ {"ERRqeof", 51, "EOF on print queue dump."}, -+ {"ERRinvpfid", 52, "Invalid print file FID."}, -+ {"ERRsmbcmd", 64, -+ "The server did not recognize the command received."}, -+ {"ERRsrverror", 65, -+ "The server encountered an internal error, e.g., system file unavailable."}, -+ {"ERRfilespecs", 67, -+ "The file handle (FID) and pathname parameters contained an invalid combination of values."}, -+ {"ERRreserved", 68, "reserved."}, -+ {"ERRbadpermits", 69, -+ "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."}, -+ {"ERRreserved", 70, "reserved."}, -+ {"ERRsetattrmode", 71, -+ "The attribute mode in the Set File Attribute request is invalid."}, -+ {"ERRpaused", 81, "Server is paused."}, -+ {"ERRmsgoff", 82, "Not receiving messages."}, -+ {"ERRnoroom", 83, "No room to buffer message."}, -+ {"ERRrmuns", 87, "Too many remote user names."}, -+ {"ERRtimeout", 88, "Operation timed out."}, -+ {"ERRnoresource", 89, -+ "No resources currently available for request."}, -+ {"ERRtoomanyuids", 90, "Too many UIDs active on this session."}, -+ {"ERRbaduid", 91, -+ "The UID is not known as a valid ID on this session."}, -+ {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode."}, -+ {"ERRusestd", 251, -+ "Temp unable to support Raw, use standard read/write."}, -+ {"ERRcontmpx", 252, "Continue in MPX mode."}, -+ {"ERRreserved", 253, "reserved."}, -+ {"ERRreserved", 254, "reserved."}, -+ {"ERRnosupport", 0xFFFF, "Function not supported."}, -+ {NULL, -1, NULL} -+}; -+ -+/* Hard Error Messages */ -+err_code_struct hard_msgs[] = { -+ {"ERRnowrite", 19, -+ "Attempt to write on write-protected diskette."}, -+ {"ERRbadunit", 20, "Unknown unit."}, -+ {"ERRnotready", 21, "Drive not ready."}, -+ {"ERRbadcmd", 22, "Unknown command."}, -+ {"ERRdata", 23, "Data error (CRC)."}, -+ {"ERRbadreq", 24, "Bad request structure length."}, -+ {"ERRseek", 25, "Seek error."}, -+ {"ERRbadmedia", 26, "Unknown media type."}, -+ {"ERRbadsector", 27, "Sector not found."}, -+ {"ERRnopaper", 28, "Printer out of paper."}, -+ {"ERRwrite", 29, "Write fault."}, -+ {"ERRread", 30, "Read fault."}, -+ {"ERRgeneral", 31, "General failure."}, -+ {"ERRbadshare", 32, "An open conflicts with an existing open."}, -+ {"ERRlock", 33, -+ "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, -+ {"ERRwrongdisk", 34, "The wrong disk was found in a drive."}, -+ {"ERRFCBUnavail", 35, "No FCBs are available to process request."}, -+ {"ERRsharebufexc", 36, "A sharing buffer has been exceeded."}, -+ {NULL, -1, NULL} -+}; -+ -+ -+const struct { -+ int code; -+ char *class; -+ err_code_struct *err_msgs; -+} err_classes[] = { -+ { -+ 0, "SUCCESS", NULL}, { -+ 0x01, "ERRDOS", dos_msgs}, { -+ 0x02, "ERRSRV", server_msgs}, { -+ 0x03, "ERRHRD", hard_msgs}, { -+ 0x04, "ERRXOS", NULL}, { -+ 0xE1, "ERRRMX1", NULL}, { -+ 0xE2, "ERRRMX2", NULL}, { -+ 0xE3, "ERRRMX3", NULL}, { -+ 0xFF, "ERRCMD", NULL}, { -+-1, NULL, NULL}}; -+ -+ -+/**************************************************************************** -+return a SMB error string from a SMB buffer -+****************************************************************************/ -+char *smb_dos_errstr(char *inbuf) -+{ -+ static pstring ret; -+ int class = CVAL(inbuf, smb_rcls); -+ int num = SVAL(inbuf, smb_err); -+ int i, j; -+ -+ for (i = 0; err_classes[i].class; i++) -+ if (err_classes[i].code == class) { -+ if (err_classes[i].err_msgs) { -+ err_code_struct *err = -+ err_classes[i].err_msgs; -+ for (j = 0; err[j].name; j++) -+ if (num == err[j].code) { -+ if (DEBUGLEVEL > 0) -+ slprintf(ret, -+ sizeof -+ (ret) - 1, -+ "%s - %s (%s)", -+ err_classes -+ [i].class, -+ err[j]. -+ name, -+ err[j]. -+ message); -+ else -+ slprintf(ret, -+ sizeof -+ (ret) - 1, -+ "%s - %s", -+ err_classes -+ [i].class, -+ err[j]. -+ name); -+ return ret; -+ } -+ } -+ -+ slprintf(ret, sizeof(ret) - 1, "%s - %d", -+ err_classes[i].class, num); -+ return ret; -+ } -+ -+ slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)", -+ class, num); -+ return (ret); -+} -+ -+ -+/***************************************************************************** -+ returns an WERROR error message. -+ *****************************************************************************/ -+char *werror_str(WERROR status) -+{ -+ static fstring msg; -+ slprintf(msg, sizeof(msg), "WIN32 code 0x%08x", W_ERROR_V(status)); -+ return msg; -+} -+ -+ -+/***************************************************************************** -+map a unix errno to a win32 error -+ *****************************************************************************/ -+WERROR map_werror_from_unix(int error) -+{ -+ NTSTATUS status = map_nt_error_from_unix(error); -+ return ntstatus_to_werror(status); -+} ---- /dev/null -+++ b/fs/cifs/smberr.h -@@ -0,0 +1,113 @@ -+/* -+ * fs/cifs/smberr.h -+ * -+ * Copyright (c) International Business Machines Corp., 2002 -+ * Author(s): Steve French (sfrench@us.ibm.com) -+ * -+ * See Error Codes section of the SNIA CIFS Specification -+ * for more information -+ * -+ * 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 -+ */ -+ -+#define SUCCESS 0 /* The request was successful. */ -+#define ERRDOS 0x01 /* Error is from the core DOS operating system set */ -+#define ERRSRV 0x02 /* Error is generated by the file server daemon */ -+#define ERRHRD 0x03 /* Error is a hardware error. */ -+#define ERRCMD 0xFF /* Command was not in the "SMB" format. */ -+ -+/* The following error codes may be generated with the SUCCESS error class.*/ -+ -+#define SUCCESS 0 /* The request was successful. */ -+ -+/* The following error codes may be generated with the ERRDOS error class.*/ -+ -+#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */ -+#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */ -+#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */ -+#define ERRnofids 4 /* Too many open files. The server has no file handles available. */ -+#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */ -+#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */ -+#define ERRbadmcb 7 /* Memory control blocks destroyed. */ -+#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */ -+#define ERRbadmem 9 /* Invalid memory block address. */ -+#define ERRbadenv 10 /* Invalid environment. */ -+#define ERRbadformat 11 /* Invalid format. */ -+#define ERRbadaccess 12 /* Invalid open mode. */ -+#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */ -+#define ERRbaddrive 15 /* Invalid drive specified. */ -+#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */ -+#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */ -+#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */ -+#define ERRgeneral 31 -+#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */ -+#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */ -+#define ERRunsup 50 -+#define ERRnosuchshare 67 -+#define ERRfilexists 80 /* The file named in the request already exists. */ -+#define ERRinvparm 87 -+#define ERRdiskfull 112 -+#define ERRinvname 123 -+#define ERRdirnotempty 145 -+#define ERRnotlocked 158 -+#define ERRalreadyexists 183 -+#define ERRbadpipe 230 -+#define ERRpipebusy 231 -+#define ERRpipeclosing 232 -+#define ERRnotconnected 233 -+#define ERRmoredata 234 -+#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */ -+#define ErrNotALink 0x201 /* A link operation was performed on a pathname that -+ was not a link. */ -+ -+/* Following error codes may be generated with the ERRSRV error -+class.*/ -+ -+#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */ -+#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */ -+#define ERRbadtype 3 /* used for indicating DFS referral needed */ -+#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */ -+#define ERRinvtid 5 /* The Tid specified in a command was invalid. */ -+#define ERRinvnetname 6 /* Invalid network name in tree connect. */ -+#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */ -+#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */ -+#define ERRqtoobig 50 /* Print queue full -- no space. */ -+#define ERRqeof 51 /* EOF on print queue dump */ -+#define ERRinvpfid 52 /* Invalid print file FID. */ -+#define ERRsmbcmd 64 /* The server did not recognize the command received. */ -+#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */ -+#define ERRbadBID 66 /* (obsolete) */ -+#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */ -+#define ERRbadLink 68 /* (obsolete) */ -+#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */ -+#define ERRbadPID 70 -+#define ERRsetattrmode 71 /* attribute (mode) is invalid */ -+#define ERRpaused 81 /* Server is paused */ -+#define ERRmsgoff 82 /* reserved - messaging off */ -+#define ERRnoroom 83 /* reserved - no room for message */ -+#define ERRrmuns 87 /* reserved - too many remote names */ -+#define ERRtimeout 88 /* operation timed out */ -+#define ERRnoresource 89 /* No resources available for request */ -+#define ERRtoomanyuids 90 /* Too many UIDs active on this session */ -+#define ERRbaduid 91 /* The UID is not known as a valid user */ -+#define ERRusempx 250 /* temporarily unable to use raw */ -+#define ERRusestd 251 /* temporarily unable to use either raw or mpx */ -+#define ERR_NOTIFY_ENUM_DIR 1024 -+#define ERRaccountexpired 2239 -+#define ERRbadclient 2240 -+#define ERRbadLogonTime 2241 -+#define ERRpasswordExpired 2242 -+#define ERRnetlogonNotStarted 2455 -+#define ERRnosupport 0xFFFF ---- /dev/null -+++ b/fs/cifs/TODO -@@ -0,0 +1,106 @@ -+version 1.16 May 27, 2004 -+ -+A Partial List of 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 so -+these can be supported for Windows servers -+ -+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 (mostly implemented) -+ -+f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup -+used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM -+and raw NTLMSSP already. This is important when enabling -+extended security and mounting to Windows 2003 Servers -+ -+f) Directory entry caching relies on a 1 second timer, rather than -+using FindNotify or equivalent. - (started) -+ -+g) A few byte range testcases fail due to POSIX vs. Windows/CIFS -+style byte range lock differences -+ -+h) quota support -+ -+i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr -+which will allow us to expose dos attributes as well as real -+ACLs. This support has been started in the current code, but is -+ifdeffed out. -+ -+k) finish writepages support (multi-page write behind for improved -+performance) and syncpage -+ -+l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the -+extra copy in/out of the socket buffers in some cases. -+ -+m) finish support for IPv6. This is mostly complete but -+needs a simple inet_pton like function to convert ipv6 -+addresses in string representation. -+ -+o) Better optimize open (and pathbased setfilesize) to reduce the -+oplock breaks coming from windows srv. Piggyback identical file -+opens on top of each other by incrementing reference count rather -+than resending (helps reduce server resource utilization and avoid -+spurious oplock breaks). -+ -+p) Improve performance of readpages by sending more than one read -+at a time when 8 pages or more are requested. Evaluate whether -+reads larger than 16K would be helpful. -+ -+q) For support of Windows9x/98 we need to retry failed mounts -+to *SMBSERVER (default server name) with the uppercase hostname -+in the RFC1001 session_init request. -+ -+r) Add Extended Attributed support (for storing UID/GID info -+to Windows servers) -+ -+s) Finish fcntl D_NOTIFY support so kde and gnome file list windows -+will autorefresh -+ -+t) Add GUI tool to configure /proc/fs/cifs settings and for display of -+the CIFS statistics -+ -+KNOWN BUGS (updated May 27, 2004) -+==================================== -+1) existing 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) follow_link and readdir code does not follow dfs junctions -+but recognizes them -+3) create of new files to FAT partitions on Windows servers can -+succeed but still return access denied (appears to be Windows -+server not cifs client problem) and has not been reproduced recently. -+NTFS partitions do not have this problem. -+4) debug connectathon lock test case 10 which fails against -+Samba (may be unmappable due to POSIX to Windows lock model -+differences but worth investigating). Also debug Samba to -+see why lock test case 7 takes longer to complete to Samba -+than to Windows. -+ -+Misc testing to do -+================== -+1) check out max path names and max path name components against various server -+types. Try nested symlinks. Return max path name in stat -f information -+ -+2) Modify file portion of ltp so it can run against a mounted network -+share and run it against cifs vfs. -+ -+3) Additional performance testing and optimization using iozone and similar - -+there are some easy changes that can be done to parallelize sequential writes, -+and when signing is disabled to request larger read sizes (larger than -+negotiated size) and send larger write sizes to modern servers. -+ -+4) More exhaustively test the recently added NT4 support against various -+NT4 service pack levels. -+ ---- /dev/null -+++ b/fs/cifs/transport.c -@@ -0,0 +1,434 @@ -+/* -+ * fs/cifs/transport.c -+ * -+ * Copyright (C) International Business Machines Corp., 2002,2004 -+ * 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 -+ */ -+ -+#include <linux/fs.h> -+#include <linux/list.h> -+#include <linux/wait.h> -+#include <linux/net.h> -+#include <linux/version.h> -+#include <asm/uaccess.h> -+#include <asm/processor.h> -+#include "cifspdu.h" -+#include "cifsglob.h" -+#include "cifsproto.h" -+#include "cifs_debug.h" -+ -+extern kmem_cache_t *cifs_mid_cachep; -+extern kmem_cache_t *cifs_oplock_cachep; -+ -+struct mid_q_entry * -+AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) -+{ -+ struct mid_q_entry *temp; -+ -+ if (ses == NULL) { -+ cERROR(1, ("Null session passed in to AllocMidQEntry ")); -+ return NULL; -+ } -+ if (ses->server == NULL) { -+ cERROR(1, ("Null TCP session in AllocMidQEntry")); -+ return NULL; -+ } -+ -+ temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep, -+ SLAB_KERNEL); -+ if (temp == NULL) -+ return temp; -+ else { -+ memset(temp, 0, sizeof (struct mid_q_entry)); -+ temp->mid = smb_buffer->Mid; /* always LE */ -+ temp->pid = current->pid; -+ temp->command = smb_buffer->Command; -+ cFYI(1, ("For smb_command %d", temp->command)); -+ do_gettimeofday(&temp->when_sent); -+ temp->ses = ses; -+ temp->tsk = current; -+ } -+ -+ spin_lock(&GlobalMid_Lock); -+ list_add_tail(&temp->qhead, &ses->server->pending_mid_q); -+ atomic_inc(&midCount); -+ temp->midState = MID_REQUEST_ALLOCATED; -+ spin_unlock(&GlobalMid_Lock); -+ return temp; -+} -+ -+void -+DeleteMidQEntry(struct mid_q_entry *midEntry) -+{ -+ spin_lock(&GlobalMid_Lock); -+ midEntry->midState = MID_FREE; -+ list_del(&midEntry->qhead); -+ atomic_dec(&midCount); -+ spin_unlock(&GlobalMid_Lock); -+ cifs_buf_release(midEntry->resp_buf); -+ kmem_cache_free(cifs_mid_cachep, midEntry); -+} -+ -+struct oplock_q_entry * -+AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon) -+{ -+ struct oplock_q_entry *temp; -+ if ((pinode== NULL) || (tcon == NULL)) { -+ cERROR(1, ("Null parms passed to AllocOplockQEntry")); -+ return NULL; -+ } -+ temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep, -+ SLAB_KERNEL); -+ if (temp == NULL) -+ return temp; -+ else { -+ temp->pinode = pinode; -+ temp->tcon = tcon; -+ temp->netfid = fid; -+ spin_lock(&GlobalMid_Lock); -+ list_add_tail(&temp->qhead, &GlobalOplock_Q); -+ spin_unlock(&GlobalMid_Lock); -+ } -+ return temp; -+ -+} -+ -+void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry) -+{ -+ spin_lock(&GlobalMid_Lock); -+ /* should we check if list empty first? */ -+ list_del(&oplockEntry->qhead); -+ spin_unlock(&GlobalMid_Lock); -+ kmem_cache_free(cifs_oplock_cachep, oplockEntry); -+} -+ -+int -+smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, -+ unsigned int smb_buf_length, struct sockaddr *sin) -+{ -+ int rc = 0; -+ int i = 0; -+ struct msghdr smb_msg; -+ struct iovec iov; -+ mm_segment_t temp_fs; -+ -+ if(ssocket == NULL) -+ return -ENOTSOCK; /* BB eventually add reconnect code here */ -+ iov.iov_base = smb_buffer; -+ iov.iov_len = smb_buf_length + 4; -+ -+ smb_msg.msg_name = sin; -+ smb_msg.msg_namelen = sizeof (struct sockaddr); -+ smb_msg.msg_iov = &iov; -+ smb_msg.msg_iovlen = 1; -+ smb_msg.msg_control = NULL; -+ smb_msg.msg_controllen = 0; -+ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ -+ -+ /* smb header is converted in header_assemble. bcc and rest of SMB word -+ area, and byte area if necessary, is converted to littleendian in -+ cifssmb.c and RFC1001 len is converted to bigendian in smb_send -+ Flags2 is converted in SendReceive */ -+ -+ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); -+ cFYI(1, ("Sending smb of length %d ", smb_buf_length)); -+ dump_smb(smb_buffer, smb_buf_length + 4); -+ -+ temp_fs = get_fs(); /* we must turn off socket api parm checking */ -+ set_fs(get_ds()); -+ while(iov.iov_len > 0) { -+ rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4); -+ if ((rc == -ENOSPC) || (rc == -EAGAIN)) { -+ i++; -+ if(i > 60) { -+ cERROR(1, -+ ("sends on sock %p stuck for 30 seconds", -+ ssocket)); -+ rc = -EAGAIN; -+ break; -+ } -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ/2); -+ continue; -+ } -+ if (rc < 0) -+ break; -+ iov.iov_base += rc; -+ iov.iov_len -= rc; -+ } -+ set_fs(temp_fs); -+ -+ if (rc < 0) { -+ cERROR(1,("Error %d sending data on socket to server.", rc)); -+ } else { -+ rc = 0; -+ } -+ -+ return rc; -+} -+ -+int -+SendReceive(const unsigned int xid, struct cifsSesInfo *ses, -+ struct smb_hdr *in_buf, struct smb_hdr *out_buf, -+ int *pbytes_returned, const int long_op) -+{ -+ int rc = 0; -+ unsigned int receive_len; -+ long timeout; -+ struct mid_q_entry *midQ; -+ -+ if (ses == NULL) { -+ cERROR(1,("Null smb session")); -+ return -EIO; -+ } -+ if(ses->server == NULL) { -+ cERROR(1,("Null tcp session")); -+ return -EIO; -+ } -+ -+ /* Ensure that we do not send more than 50 overlapping requests -+ to the same server. We may make this configurable later or -+ use ses->maxReq */ -+ if(long_op == -1) { -+ /* oplock breaks must not be held up */ -+ atomic_inc(&ses->server->inFlight); -+ } else { -+ spin_lock(&GlobalMid_Lock); -+ while(1) { -+ if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){ -+ spin_unlock(&GlobalMid_Lock); -+ wait_event(ses->server->request_q, -+ atomic_read(&ses->server->inFlight) -+ < CIFS_MAX_REQ); -+ spin_lock(&GlobalMid_Lock); -+ } else { -+ if(ses->server->tcpStatus == CifsExiting) { -+ spin_unlock(&GlobalMid_Lock); -+ return -ENOENT; -+ } -+ -+ /* can not count locking commands against total since -+ they are allowed to block on server */ -+ -+ if(long_op < 3) { -+ /* update # of requests on the wire to server */ -+ atomic_inc(&ses->server->inFlight); -+ } -+ spin_unlock(&GlobalMid_Lock); -+ break; -+ } -+ } -+ } -+ /* make sure that we sign in the same order that we send on this socket -+ and avoid races inside tcp sendmsg code that could cause corruption -+ of smb data */ -+ -+ down(&ses->server->tcpSem); -+ -+ if (ses->server->tcpStatus == CifsExiting) { -+ rc = -ENOENT; -+ goto out_unlock; -+ } else if (ses->server->tcpStatus == CifsNeedReconnect) { -+ cFYI(1,("tcp session dead - return to caller to retry")); -+ rc = -EAGAIN; -+ goto out_unlock; -+ } else if (ses->status != CifsGood) { -+ /* check if SMB session is bad because we are setting it up */ -+ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && -+ (in_buf->Command != SMB_COM_NEGOTIATE)) { -+ rc = -EAGAIN; -+ goto out_unlock; -+ } /* else ok - we are setting up session */ -+ } -+ midQ = AllocMidQEntry(in_buf, ses); -+ if (midQ == NULL) { -+ up(&ses->server->tcpSem); -+ /* If not lock req, update # of requests on wire to server */ -+ if(long_op < 3) { -+ atomic_dec(&ses->server->inFlight); -+ wake_up(&ses->server->request_q); -+ } -+ return -ENOMEM; -+ } -+ -+ if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) { -+ up(&ses->server->tcpSem); -+ cERROR(1, -+ ("Illegal length, greater than maximum frame, %d ", -+ in_buf->smb_buf_length)); -+ DeleteMidQEntry(midQ); -+ /* If not lock req, update # of requests on wire to server */ -+ if(long_op < 3) { -+ atomic_dec(&ses->server->inFlight); -+ wake_up(&ses->server->request_q); -+ } -+ return -EIO; -+ } -+ -+ if (in_buf->smb_buf_length > 12) -+ in_buf->Flags2 = cpu_to_le16(in_buf->Flags2); -+ -+ rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); -+ -+ midQ->midState = MID_REQUEST_SUBMITTED; -+ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, -+ (struct sockaddr *) &(ses->server->addr.sockAddr)); -+ if(rc < 0) { -+ DeleteMidQEntry(midQ); -+ up(&ses->server->tcpSem); -+ /* If not lock req, update # of requests on wire to server */ -+ if(long_op < 3) { -+ atomic_dec(&ses->server->inFlight); -+ wake_up(&ses->server->request_q); -+ } -+ return rc; -+ } else -+ up(&ses->server->tcpSem); -+ if (long_op == -1) -+ goto cifs_no_response_exit; -+ else if (long_op == 2) /* writes past end of file can take looooong time */ -+ timeout = 300 * HZ; -+ else if (long_op == 1) -+ timeout = 45 * HZ; /* should be greater than -+ servers oplock break timeout (about 43 seconds) */ -+ else if (long_op > 2) { -+ timeout = MAX_SCHEDULE_TIMEOUT; -+ } else -+ timeout = 15 * HZ; -+ /* wait for 15 seconds or until woken up due to response arriving or -+ due to last connection to this server being unmounted */ -+ if (signal_pending(current)) { -+ /* if signal pending do not hold up user for full smb timeout -+ but we still give response a change to complete */ -+ if(midQ->midState & MID_REQUEST_SUBMITTED) { -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ); -+ } -+ } else { /* using normal timeout */ -+ /* timeout = wait_event_interruptible_timeout(ses->server->response_q, -+ (midQ->midState & MID_RESPONSE_RECEIVED) || -+ ((ses->server->tcpStatus != CifsGood) && -+ (ses->server->tcpStatus != CifsNew)), -+ timeout); */ -+ /* Can not allow user interrupts- wreaks havoc with performance */ -+ if(midQ->midState & MID_REQUEST_SUBMITTED) { -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ timeout = sleep_on_timeout(&ses->server->response_q,timeout); -+ } -+ } -+ -+ spin_lock(&GlobalMid_Lock); -+ if (midQ->resp_buf) { -+ spin_unlock(&GlobalMid_Lock); -+ receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length); -+ } else { -+ cERROR(1,("No response buffer")); -+ if(midQ->midState == MID_REQUEST_SUBMITTED) { -+ if(ses->server->tcpStatus == CifsExiting) -+ rc = -EHOSTDOWN; -+ else { -+ ses->server->tcpStatus = CifsNeedReconnect; -+ midQ->midState = MID_RETRY_NEEDED; -+ } -+ } -+ -+ if (rc != -EHOSTDOWN) { -+ if(midQ->midState == MID_RETRY_NEEDED) { -+ rc = -EAGAIN; -+ cFYI(1,("marking request for retry")); -+ } else { -+ rc = -EIO; -+ } -+ } -+ spin_unlock(&GlobalMid_Lock); -+ DeleteMidQEntry(midQ); -+ /* If not lock req, update # of requests on wire to server */ -+ if(long_op < 3) { -+ atomic_dec(&ses->server->inFlight); -+ wake_up(&ses->server->request_q); -+ } -+ return rc; -+ } -+ -+ if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { -+ cERROR(1, -+ ("Frame too large received. Length: %d Xid: %d", -+ receive_len, xid)); -+ rc = -EIO; -+ } else { /* rcvd frame is ok */ -+ -+ if (midQ->resp_buf && out_buf -+ && (midQ->midState == MID_RESPONSE_RECEIVED)) { -+ memcpy(out_buf, midQ->resp_buf, -+ receive_len + -+ 4 /* include 4 byte RFC1001 header */ ); -+ -+ dump_smb(out_buf, 92); -+ /* convert the length into a more usable form */ -+ out_buf->smb_buf_length = -+ be32_to_cpu(out_buf->smb_buf_length); -+ if((out_buf->smb_buf_length > 24) && -+ (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { -+ rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */ -+ if(rc) -+ cFYI(1,("Unexpected signature received from server")); -+ } -+ -+ if (out_buf->smb_buf_length > 12) -+ out_buf->Flags2 = le16_to_cpu(out_buf->Flags2); -+ if (out_buf->smb_buf_length > 28) -+ out_buf->Pid = le16_to_cpu(out_buf->Pid); -+ if (out_buf->smb_buf_length > 28) -+ out_buf->PidHigh = -+ le16_to_cpu(out_buf->PidHigh); -+ -+ *pbytes_returned = out_buf->smb_buf_length; -+ -+ /* BB special case reconnect tid and reconnect uid here? */ -+ rc = map_smb_to_linux_error(out_buf); -+ -+ /* convert ByteCount if necessary */ -+ if (receive_len >= -+ sizeof (struct smb_hdr) - -+ 4 /* do not count RFC1001 header */ + -+ (2 * out_buf->WordCount) + 2 /* bcc */ ) -+ BCC(out_buf) = le16_to_cpu(BCC(out_buf)); -+ } else { -+ rc = -EIO; -+ cFYI(1,("Bad MID state? ")); -+ } -+ } -+cifs_no_response_exit: -+ DeleteMidQEntry(midQ); -+ -+ if(long_op < 3) { -+ atomic_dec(&ses->server->inFlight); -+ wake_up(&ses->server->request_q); -+ } -+ -+ return rc; -+ -+out_unlock: -+ up(&ses->server->tcpSem); -+ /* If not lock req, update # of requests on wire to server */ -+ if(long_op < 3) { -+ atomic_dec(&ses->server->inFlight); -+ wake_up(&ses->server->request_q); -+ } -+ -+ return rc; -+} ---- a/fs/Config.in -+++ b/fs/Config.in -@@ -153,6 +153,10 @@ if [ "$CONFIG_NET" = "y" ]; then - define_bool CONFIG_LOCKD_V4 y - fi - -+ dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)' CONFIG_CIFS $CONFIG_INET -+ dep_mbool ' CIFS statistics' CONFIG_CIFS_STATS $CONFIG_CIFS -+ dep_mbool ' CIFS POSIX Protocol Extensions' CONFIG_CIFS_POSIX $CONFIG_CIFS -+ - 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 ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -37,6 +37,7 @@ subdir-$(CONFIG_MSDOS_FS) += msdos - subdir-$(CONFIG_VFAT_FS) += vfat - subdir-$(CONFIG_BFS_FS) += bfs - subdir-$(CONFIG_ISO9660_FS) += isofs -+subdir-$(CONFIG_CIFS) += cifs - subdir-$(CONFIG_DEVFS_FS) += devfs - subdir-$(CONFIG_HFSPLUS_FS) += hfsplus # Before hfs to find wrapped HFS+ - subdir-$(CONFIG_HFS_FS) += hfs ---- a/fs/nls/Config.in -+++ b/fs/nls/Config.in -@@ -11,6 +11,7 @@ fi - - # msdos and Joliet want NLS - if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \ -+ -o "$CONFIG_CIFS" != "n" \ - -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \ - -o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \ - -o "$CONFIG_BEFS_FS" != "n" -o "$CONFIG_HFSPLUS_FS" != "n" ]; then |