Root/target/linux/generic-2.4/patches/107-cifs.patch

1--- a/Documentation/Configure.help
2+++ b/Documentation/Configure.help
3@@ -18007,6 +18007,34 @@ CONFIG_UNIXWARE_DISKLABEL
4 
5   If you don't know what all this is about, say N.
6 
7+CIFS (Common Internet File System) support
8+CONFIG_CIFS
9+ This is the client VFS module for the Common Internet File System
10+ (CIFS) protocol which is the successor to the Server Message Block
11+ (SMB) protocol, the native file sharing mechanism for most early
12+ PC operating systems. CIFS is fully supported by current network
13+ file servers such as Windows 2000, Windows 2003 (including
14+ Windows XP) as well by Samba (which provides excellent CIFS
15+ server support for Linux and many other operating systems).
16+ The smbfs module should be used instead of this cifs module for
17+ mounting to older SMB servers such as OS/2. The smbfs and cifs
18+ modules can coexist and do not conflict.
19+
20+ The intent of this module is to provide the most advanced network
21+ file system function for CIFS compliant servers, including better
22+ POSIX compliance, secure per-user session establishment, high
23+ performance safe distributed caching (oplock), optional packet
24+ signing, Unicode support and other internationalization improvements
25+ For more information see the project page at
26+ http://us1.samba.org/samba/Linux_CIFS_client.html
27+
28+CIFS Debugging
29+CONFIG_CIFS_DEBUG
30+ If you are experiencing any problems with the CIFS filesystem, say
31+ Y here. This will result in additional debugging messages to be
32+ written to the system log. Under normal circumstances, this
33+ results in very little overhead.
34+
35 SMB file system support (to mount Windows shares etc.)
36 CONFIG_SMB_FS
37   SMB (Server Message Block) is the protocol Windows for Workgroups
38--- a/Documentation/filesystems/00-INDEX
39+++ b/Documentation/filesystems/00-INDEX
40@@ -10,6 +10,8 @@ befs.txt
41     - info for the BeOS file system (BFS)
42 bfs.txt
43     - info for the SCO UnixWare Boot Filesystem (BFS).
44+cifs.txt
45+ - info on the Common Internet File System (CIFS)
46 coda.txt
47     - description of the CODA filesystem.
48 cramfs.txt
49--- /dev/null
50+++ b/Documentation/filesystems/cifs.txt
51@@ -0,0 +1,51 @@
52+ This is the client VFS module for the Common Internet File System
53+ (CIFS) protocol which is the successor to the Server Message Block
54+ (SMB) protocol, the native file sharing mechanism for most early
55+ PC operating systems. CIFS is fully supported by current network
56+ file servers such as Windows 2000, Windows 2003 (including
57+ Windows XP) as well by Samba (which provides excellent CIFS
58+ server support for Linux and many other operating systems), so
59+ this network filesystem client can mount to a wide variety of
60+ servers. The smbfs module should be used instead of this cifs module
61+ for mounting to older SMB servers such as OS/2. The smbfs and cifs
62+ modules can coexist and do not conflict. The CIFS VFS filesystem
63+ module is designed to work well with servers that implement the
64+ newer versions (dialects) of the SMB/CIFS protocol such as Samba,
65+ the program written by Andrew Tridgell that turns any Unix host
66+ into a SMB/CIFS file server.
67+
68+ The intent of this module is to provide the most advanced network
69+ file system function for CIFS compliant servers, including better
70+ POSIX compliance, secure per-user session establishment, high
71+ performance safe distributed caching (oplock), optional packet
72+ signing, large files, Unicode support and other internationalization
73+ improvements. Since both Samba server and this filesystem client support
74+ the CIFS Unix extensions, the combination can provide a reasonable
75+ alternative to NFSv4 for fileserving in some Linux to Linux environments,
76+ not just in Linux to Windows environments.
77+
78+ This filesystem has an optional mount utility (mount.cifs) that can
79+ be obtained from the project page and installed in the path in the same
80+ directory with the other mount helpers (such as mount.smbfs).
81+ Mounting using the cifs filesystem without installing the mount helper
82+ requires specifying the server's ip address.
83+
84+ For Linux 2.4:
85+ mount //anything/here /mnt_target -o
86+ user=username,pass=password,unc=//ip_address_of_server/sharename
87+
88+ For Linux 2.5:
89+ mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
90+
91+
92+ For more information on the module see the project page at
93+
94+ http://us1.samba.org/samba/Linux_CIFS_client.html
95+
96+ For more information on CIFS see:
97+
98+ http://www.snia.org/tech_activities/CIFS
99+
100+ or the Samba site:
101+
102+ http://www.samba.org
103--- /dev/null
104+++ b/fs/cifs/asn1.c
105@@ -0,0 +1,614 @@
106+/*
107+ * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
108+ * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
109+ *
110+ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
111+ *
112+ * This program is free software; you can redistribute it and/or modify
113+ * it under the terms of the GNU General Public License as published by
114+ * the Free Software Foundation; either version 2 of the License, or
115+ * (at your option) any later version.
116+ * This program is distributed in the hope that it will be useful,
117+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
118+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
119+ * GNU General Public License for more details.
120+ * You should have received a copy of the GNU General Public License
121+ * along with this program; if not, write to the Free Software
122+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
123+ */
124+
125+#include <linux/config.h>
126+#include <linux/module.h>
127+#include <linux/types.h>
128+#include <linux/kernel.h>
129+#include <linux/mm.h>
130+#include <linux/slab.h>
131+#include "cifspdu.h"
132+#include "cifsglob.h"
133+#include "cifs_debug.h"
134+
135+/*****************************************************************************
136+ *
137+ * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
138+ *
139+ *****************************************************************************/
140+
141+/* Class */
142+#define ASN1_UNI 0 /* Universal */
143+#define ASN1_APL 1 /* Application */
144+#define ASN1_CTX 2 /* Context */
145+#define ASN1_PRV 3 /* Private */
146+
147+/* Tag */
148+#define ASN1_EOC 0 /* End Of Contents or N/A */
149+#define ASN1_BOL 1 /* Boolean */
150+#define ASN1_INT 2 /* Integer */
151+#define ASN1_BTS 3 /* Bit String */
152+#define ASN1_OTS 4 /* Octet String */
153+#define ASN1_NUL 5 /* Null */
154+#define ASN1_OJI 6 /* Object Identifier */
155+#define ASN1_OJD 7 /* Object Description */
156+#define ASN1_EXT 8 /* External */
157+#define ASN1_SEQ 16 /* Sequence */
158+#define ASN1_SET 17 /* Set */
159+#define ASN1_NUMSTR 18 /* Numerical String */
160+#define ASN1_PRNSTR 19 /* Printable String */
161+#define ASN1_TEXSTR 20 /* Teletext String */
162+#define ASN1_VIDSTR 21 /* Video String */
163+#define ASN1_IA5STR 22 /* IA5 String */
164+#define ASN1_UNITIM 23 /* Universal Time */
165+#define ASN1_GENTIM 24 /* General Time */
166+#define ASN1_GRASTR 25 /* Graphical String */
167+#define ASN1_VISSTR 26 /* Visible String */
168+#define ASN1_GENSTR 27 /* General String */
169+
170+/* Primitive / Constructed methods*/
171+#define ASN1_PRI 0 /* Primitive */
172+#define ASN1_CON 1 /* Constructed */
173+
174+/*
175+ * Error codes.
176+ */
177+#define ASN1_ERR_NOERROR 0
178+#define ASN1_ERR_DEC_EMPTY 2
179+#define ASN1_ERR_DEC_EOC_MISMATCH 3
180+#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
181+#define ASN1_ERR_DEC_BADVALUE 5
182+
183+#define SPNEGO_OID_LEN 7
184+#define NTLMSSP_OID_LEN 10
185+unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
186+unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
187+
188+/*
189+ * ASN.1 context.
190+ */
191+struct asn1_ctx {
192+ int error; /* Error condition */
193+ unsigned char *pointer; /* Octet just to be decoded */
194+ unsigned char *begin; /* First octet */
195+ unsigned char *end; /* Octet after last octet */
196+};
197+
198+/*
199+ * Octet string (not null terminated)
200+ */
201+struct asn1_octstr {
202+ unsigned char *data;
203+ unsigned int len;
204+};
205+
206+static void
207+asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
208+{
209+ ctx->begin = buf;
210+ ctx->end = buf + len;
211+ ctx->pointer = buf;
212+ ctx->error = ASN1_ERR_NOERROR;
213+}
214+
215+static unsigned char
216+asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
217+{
218+ if (ctx->pointer >= ctx->end) {
219+ ctx->error = ASN1_ERR_DEC_EMPTY;
220+ return 0;
221+ }
222+ *ch = *(ctx->pointer)++;
223+ return 1;
224+}
225+
226+static unsigned char
227+asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
228+{
229+ unsigned char ch;
230+
231+ *tag = 0;
232+
233+ do {
234+ if (!asn1_octet_decode(ctx, &ch))
235+ return 0;
236+ *tag <<= 7;
237+ *tag |= ch & 0x7F;
238+ } while ((ch & 0x80) == 0x80);
239+ return 1;
240+}
241+
242+static unsigned char
243+asn1_id_decode(struct asn1_ctx *ctx,
244+ unsigned int *cls, unsigned int *con, unsigned int *tag)
245+{
246+ unsigned char ch;
247+
248+ if (!asn1_octet_decode(ctx, &ch))
249+ return 0;
250+
251+ *cls = (ch & 0xC0) >> 6;
252+ *con = (ch & 0x20) >> 5;
253+ *tag = (ch & 0x1F);
254+
255+ if (*tag == 0x1F) {
256+ if (!asn1_tag_decode(ctx, tag))
257+ return 0;
258+ }
259+ return 1;
260+}
261+
262+static unsigned char
263+asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
264+{
265+ unsigned char ch, cnt;
266+
267+ if (!asn1_octet_decode(ctx, &ch))
268+ return 0;
269+
270+ if (ch == 0x80)
271+ *def = 0;
272+ else {
273+ *def = 1;
274+
275+ if (ch < 0x80)
276+ *len = ch;
277+ else {
278+ cnt = (unsigned char) (ch & 0x7F);
279+ *len = 0;
280+
281+ while (cnt > 0) {
282+ if (!asn1_octet_decode(ctx, &ch))
283+ return 0;
284+ *len <<= 8;
285+ *len |= ch;
286+ cnt--;
287+ }
288+ }
289+ }
290+ return 1;
291+}
292+
293+static unsigned char
294+asn1_header_decode(struct asn1_ctx *ctx,
295+ unsigned char **eoc,
296+ unsigned int *cls, unsigned int *con, unsigned int *tag)
297+{
298+ unsigned int def, len;
299+
300+ if (!asn1_id_decode(ctx, cls, con, tag))
301+ return 0;
302+
303+ if (!asn1_length_decode(ctx, &def, &len))
304+ return 0;
305+
306+ if (def)
307+ *eoc = ctx->pointer + len;
308+ else
309+ *eoc = NULL;
310+ return 1;
311+}
312+
313+static unsigned char
314+asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
315+{
316+ unsigned char ch;
317+
318+ if (eoc == 0) {
319+ if (!asn1_octet_decode(ctx, &ch))
320+ return 0;
321+
322+ if (ch != 0x00) {
323+ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
324+ return 0;
325+ }
326+
327+ if (!asn1_octet_decode(ctx, &ch))
328+ return 0;
329+
330+ if (ch != 0x00) {
331+ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
332+ return 0;
333+ }
334+ return 1;
335+ } else {
336+ if (ctx->pointer != eoc) {
337+ ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
338+ return 0;
339+ }
340+ return 1;
341+ }
342+}
343+
344+/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
345+ unsigned char *eoc)
346+{
347+ ctx->pointer = eoc;
348+ return 1;
349+}
350+
351+static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
352+ unsigned char *eoc, long *integer)
353+{
354+ unsigned char ch;
355+ unsigned int len;
356+
357+ if (!asn1_octet_decode(ctx, &ch))
358+ return 0;
359+
360+ *integer = (signed char) ch;
361+ len = 1;
362+
363+ while (ctx->pointer < eoc) {
364+ if (++len > sizeof(long)) {
365+ ctx->error = ASN1_ERR_DEC_BADVALUE;
366+ return 0;
367+ }
368+
369+ if (!asn1_octet_decode(ctx, &ch))
370+ return 0;
371+
372+ *integer <<= 8;
373+ *integer |= ch;
374+ }
375+ return 1;
376+}
377+
378+static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
379+ unsigned char *eoc,
380+ unsigned int *integer)
381+{
382+ unsigned char ch;
383+ unsigned int len;
384+
385+ if (!asn1_octet_decode(ctx, &ch))
386+ return 0;
387+
388+ *integer = ch;
389+ if (ch == 0)
390+ len = 0;
391+ else
392+ len = 1;
393+
394+ while (ctx->pointer < eoc) {
395+ if (++len > sizeof(unsigned int)) {
396+ ctx->error = ASN1_ERR_DEC_BADVALUE;
397+ return 0;
398+ }
399+
400+ if (!asn1_octet_decode(ctx, &ch))
401+ return 0;
402+
403+ *integer <<= 8;
404+ *integer |= ch;
405+ }
406+ return 1;
407+}
408+
409+static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
410+ unsigned char *eoc,
411+ unsigned long *integer)
412+{
413+ unsigned char ch;
414+ unsigned int len;
415+
416+ if (!asn1_octet_decode(ctx, &ch))
417+ return 0;
418+
419+ *integer = ch;
420+ if (ch == 0)
421+ len = 0;
422+ else
423+ len = 1;
424+
425+ while (ctx->pointer < eoc) {
426+ if (++len > sizeof(unsigned long)) {
427+ ctx->error = ASN1_ERR_DEC_BADVALUE;
428+ return 0;
429+ }
430+
431+ if (!asn1_octet_decode(ctx, &ch))
432+ return 0;
433+
434+ *integer <<= 8;
435+ *integer |= ch;
436+ }
437+ return 1;
438+}
439+
440+static unsigned char
441+asn1_octets_decode(struct asn1_ctx *ctx,
442+ unsigned char *eoc,
443+ unsigned char **octets, unsigned int *len)
444+{
445+ unsigned char *ptr;
446+
447+ *len = 0;
448+
449+ *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
450+ if (*octets == NULL) {
451+ return 0;
452+ }
453+
454+ ptr = *octets;
455+ while (ctx->pointer < eoc) {
456+ if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
457+ kfree(*octets);
458+ *octets = NULL;
459+ return 0;
460+ }
461+ (*len)++;
462+ }
463+ return 1;
464+} */
465+
466+static unsigned char
467+asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
468+{
469+ unsigned char ch;
470+
471+ *subid = 0;
472+
473+ do {
474+ if (!asn1_octet_decode(ctx, &ch))
475+ return 0;
476+
477+ *subid <<= 7;
478+ *subid |= ch & 0x7F;
479+ } while ((ch & 0x80) == 0x80);
480+ return 1;
481+}
482+
483+static unsigned char
484+asn1_oid_decode(struct asn1_ctx *ctx,
485+ unsigned char *eoc, unsigned long **oid, unsigned int *len)
486+{
487+ unsigned long subid;
488+ unsigned int size;
489+ unsigned long *optr;
490+
491+ size = eoc - ctx->pointer + 1;
492+ *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
493+ if (*oid == NULL) {
494+ return 0;
495+ }
496+
497+ optr = *oid;
498+
499+ if (!asn1_subid_decode(ctx, &subid)) {
500+ kfree(*oid);
501+ *oid = NULL;
502+ return 0;
503+ }
504+
505+ if (subid < 40) {
506+ optr[0] = 0;
507+ optr[1] = subid;
508+ } else if (subid < 80) {
509+ optr[0] = 1;
510+ optr[1] = subid - 40;
511+ } else {
512+ optr[0] = 2;
513+ optr[1] = subid - 80;
514+ }
515+
516+ *len = 2;
517+ optr += 2;
518+
519+ while (ctx->pointer < eoc) {
520+ if (++(*len) > size) {
521+ ctx->error = ASN1_ERR_DEC_BADVALUE;
522+ kfree(*oid);
523+ *oid = NULL;
524+ return 0;
525+ }
526+
527+ if (!asn1_subid_decode(ctx, optr++)) {
528+ kfree(*oid);
529+ *oid = NULL;
530+ return 0;
531+ }
532+ }
533+ return 1;
534+}
535+
536+static int
537+compare_oid(unsigned long *oid1, unsigned int oid1len,
538+ unsigned long *oid2, unsigned int oid2len)
539+{
540+ unsigned int i;
541+
542+ if (oid1len != oid2len)
543+ return 0;
544+ else {
545+ for (i = 0; i < oid1len; i++) {
546+ if (oid1[i] != oid2[i])
547+ return 0;
548+ }
549+ return 1;
550+ }
551+}
552+
553+ /* BB check for endian conversion issues here */
554+
555+int
556+decode_negTokenInit(unsigned char *security_blob, int length,
557+ enum securityEnum *secType)
558+{
559+ struct asn1_ctx ctx;
560+ unsigned char *end;
561+ unsigned char *sequence_end;
562+ unsigned long *oid;
563+ unsigned int cls, con, tag, oidlen, rc;
564+ int use_ntlmssp = FALSE;
565+
566+ *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
567+
568+ /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
569+
570+ asn1_open(&ctx, security_blob, length);
571+
572+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
573+ cFYI(1, ("Error decoding negTokenInit header "));
574+ return 0;
575+ } else if ((cls != ASN1_APL) || (con != ASN1_CON)
576+ || (tag != ASN1_EOC)) {
577+ cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
578+ return 0;
579+ } else {
580+ /* remember to free obj->oid */
581+ rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
582+ if (rc) {
583+ if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
584+ rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
585+ if (rc) {
586+ rc = compare_oid(oid, oidlen,
587+ SPNEGO_OID,
588+ SPNEGO_OID_LEN);
589+ kfree(oid);
590+ }
591+ } else
592+ rc = 0;
593+ }
594+
595+ if (!rc) {
596+ cFYI(1, ("Error decoding negTokenInit header"));
597+ return 0;
598+ }
599+
600+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
601+ cFYI(1, ("Error decoding negTokenInit "));
602+ return 0;
603+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
604+ || (tag != ASN1_EOC)) {
605+ cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
606+ cls, con, tag, end, *end));
607+ return 0;
608+ }
609+
610+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
611+ cFYI(1, ("Error decoding negTokenInit "));
612+ return 0;
613+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
614+ || (tag != ASN1_SEQ)) {
615+ cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
616+ cls, con, tag, end, *end));
617+ return 0;
618+ }
619+
620+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
621+ cFYI(1, ("Error decoding 2nd part of negTokenInit "));
622+ return 0;
623+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
624+ || (tag != ASN1_EOC)) {
625+ cFYI(1,
626+ ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
627+ cls, con, tag, end, *end));
628+ return 0;
629+ }
630+
631+ if (asn1_header_decode
632+ (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
633+ cFYI(1, ("Error decoding 2nd part of negTokenInit "));
634+ return 0;
635+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
636+ || (tag != ASN1_SEQ)) {
637+ cFYI(1,
638+ ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
639+ cls, con, tag, end, *end));
640+ return 0;
641+ }
642+
643+ while (!asn1_eoc_decode(&ctx, sequence_end)) {
644+ rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
645+ if (!rc) {
646+ cFYI(1,
647+ ("Error 1 decoding negTokenInit header exit 2"));
648+ return 0;
649+ }
650+ if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
651+ asn1_oid_decode(&ctx, end, &oid, &oidlen);
652+ cFYI(1,
653+ ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
654+ oidlen, *oid, *(oid + 1), *(oid + 2),
655+ *(oid + 3)));
656+ rc = compare_oid(oid, oidlen, NTLMSSP_OID,
657+ NTLMSSP_OID_LEN);
658+ kfree(oid);
659+ if (rc)
660+ use_ntlmssp = TRUE;
661+ } else {
662+ cFYI(1,("This should be an oid what is going on? "));
663+ }
664+ }
665+
666+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
667+ cFYI(1,
668+ ("Error decoding last part of negTokenInit exit 3"));
669+ return 0;
670+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
671+ cFYI(1,
672+ ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
673+ cls, con, tag, end, *end));
674+ return 0;
675+ }
676+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
677+ cFYI(1,
678+ ("Error decoding last part of negTokenInit exit 5"));
679+ return 0;
680+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
681+ || (tag != ASN1_SEQ)) {
682+ cFYI(1,
683+ ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
684+ cls, con, tag, end, *end));
685+ }
686+
687+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
688+ cFYI(1,
689+ ("Error decoding last part of negTokenInit exit 7"));
690+ return 0;
691+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
692+ cFYI(1,
693+ ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
694+ cls, con, tag, end, *end));
695+ return 0;
696+ }
697+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
698+ cFYI(1,
699+ ("Error decoding last part of negTokenInit exit 9"));
700+ return 0;
701+ } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
702+ || (tag != ASN1_GENSTR)) {
703+ cFYI(1,
704+ ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
705+ cls, con, tag, end, *end));
706+ return 0;
707+ }
708+ cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
709+ }
710+
711+ /* if (use_kerberos)
712+ *secType = Kerberos
713+ else */
714+ if (use_ntlmssp) {
715+ *secType = NTLMSSP;
716+ }
717+
718+ return 1;
719+}
720--- /dev/null
721+++ b/fs/cifs/AUTHORS
722@@ -0,0 +1,37 @@
723+Original Author
724+===============
725+Steve French (sfrench@samba.org)
726+
727+The author wishes to express his appreciation and thanks to:
728+Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
729+improvements. Thanks to IBM for allowing me the time and test resources to pursue
730+this project. Jim McDonough from IBM (and the Samba Team) for his help.
731+The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
732+Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
733+for proving years ago that a very good smb/cifs client could be done on a Unix like
734+operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
735+and others for their work on the Linux smbfs module over the years. Thanks to
736+the other members of the Storage Network Industry Association CIFS Technical
737+Workgroup for their work specifying this highly complex protocol and finally
738+thanks to the Samba team for their technical advice and encouragement.
739+
740+Patch Contributors
741+------------------
742+Zwane Mwaikambo
743+Andi Kleen
744+Amrut Joshi
745+Shobhit Dayal
746+Sergey Vlasov
747+Richard Hughes
748+Yury Umanets
749+
750+Test case and Bug Report contributors
751+-------------------------------------
752+Thanks to those in the community who have submitted detailed bug reports
753+and debug of problems they have found: Jochen Dolze, David Blaine,
754+Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
755+Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
756+Olaf Kirch, Kieron Briggs, Nick Millington and others.
757+
758+And thanks to the IBM LTC and Power test teams and SuSE testers for
759+finding multiple bugs during excellent stress test runs.
760--- /dev/null
761+++ b/fs/cifs/CHANGES
762@@ -0,0 +1,572 @@
763+Version 1.20
764+------------
765+Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
766+info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir
767+(in build_wildcard_path_from_dentry). Fix mknod to pass type field
768+(block/char/fifo) properly. Remove spurious mount warning log entry when
769+credentials passed as mount argument. Set major/minor device number in
770+inode for block and char devices when unix extensions enabled.
771+
772+Version 1.19
773+------------
774+Fix /proc/fs/cifs/Stats and DebugData display to handle larger
775+amounts of return data. Properly limit requests to MAX_REQ (50
776+is the usual maximum active multiplex SMB/CIFS requests per server).
777+Do not kill cifsd (and thus hurt the other SMB session) when more than one
778+session to the same server (but with different userids) exists and one
779+of the two user's smb sessions is being removed while leaving the other.
780+Do not loop reconnecting in cifsd demultiplex thread when admin
781+kills the thread without going through unmount.
782+
783+Version 1.18
784+------------
785+Do not rename hardlinked files (since that should be a noop). Flush
786+cached write behind data when reopening a file after session abend,
787+except when already in write. Grab per socket sem during reconnect
788+to avoid oops in sendmsg if overlapping with reconnect. Do not
789+reset cached inode file size on readdir for files open for write on
790+client.
791+
792+
793+Version 1.17
794+------------
795+Update number of blocks in file so du command is happier (in Linux a fake
796+blocksize of 512 is required for calculating number of blocks in inode).
797+Fix prepare write of partial pages to read in data from server if possible.
798+Fix race on tcpStatus field between unmount and reconnection code, causing
799+cifsd process sometimes to hang around forever. Improve out of memory
800+checks in cifs_filldir
801+
802+Version 1.16
803+------------
804+Fix incorrect file size in file handle based setattr on big endian hardware.
805+Fix oops in build_path_from_dentry when out of memory. Add checks for invalid
806+and closing file structs in writepage/partialpagewrite. Add statistics
807+for each mounted share (new menuconfig option). Fix endianness problem in
808+volume information displayed in /proc/fs/cifs/DebugData (only affects
809+affects big endian architectures). Prevent renames while constructing
810+path names for open, mkdir and rmdir.
811+
812+Version 1.15
813+------------
814+Change to mempools for alloc smb request buffers and multiplex structs
815+to better handle low memory problems (and potential deadlocks).
816+
817+Version 1.14
818+------------
819+Fix incomplete listings of large directories on Samba servers when Unix
820+extensions enabled. Fix oops when smb_buffer can not be allocated. Fix
821+rename deadlock when writing out dirty pages at same time.
822+
823+Version 1.13
824+------------
825+Fix open of files in which O_CREATE can cause the mode to change in
826+some cases. Fix case in which retry of write overlaps file close.
827+Fix PPC64 build error. Reduce excessive stack usage in smb password
828+hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
829+
830+Version 1.12
831+------------
832+Fixes for large file copy, signal handling, socket retry, buffer
833+allocation and low memory situations.
834+
835+Version 1.11
836+------------
837+Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
838+also now allowing support for specifying client netbiosname. NT4 support added.
839+
840+Version 1.10
841+------------
842+Fix reconnection (and certain failed mounts) to properly wake up the
843+blocked users thread so it does not seem hung (in some cases was blocked
844+until the cifs receive timeout expired). Fix spurious error logging
845+to kernel log when application with open network files killed.
846+
847+Version 1.09
848+------------
849+Fix /proc/fs module unload warning message (that could be logged
850+to the kernel log). Fix intermittent failure in connectathon
851+test7 (hardlink count not immediately refreshed in case in which
852+inode metadata can be incorrectly kept cached when time near zero)
853+
854+Version 1.08
855+------------
856+Allow file_mode and dir_mode (specified at mount time) to be enforced
857+locally (the server already enforced its own ACLs too) for servers
858+that do not report the correct mode (do not support the
859+CIFS Unix Extensions).
860+
861+Version 1.07
862+------------
863+Fix some small memory leaks in some unmount error paths. Fix major leak
864+of cache pages in readpages causing multiple read oriented stress
865+testcases (including fsx, and even large file copy) to fail over time.
866+
867+Version 1.06
868+------------
869+Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
870+This allows files that differ only in case and improves performance of file
871+creation and file open to such servers. Fix semaphore conflict which causes
872+slow delete of open file to Samba (which unfortunately can cause an oplock
873+break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
874+
875+Version 1.05
876+------------
877+fixes to cifs_readpages for fsx test case
878+
879+Version 1.04
880+------------
881+Fix caching data integrity bug when extending file size especially when no
882+oplock on file. Fix spurious logging of valid already parsed mount options
883+that are parsed outside of the cifs vfs such as nosuid.
884+
885+
886+Version 1.03
887+------------
888+Connect to server when port number override not specified, and tcp port
889+unitialized. Reset search to restart at correct file when kernel routine
890+filldir returns error during large directory searches (readdir).
891+
892+Version 1.02
893+------------
894+Fix caching problem when files opened by multiple clients in which
895+page cache could contain stale data, and write through did
896+not occur often enough while file was still open when read ahead
897+(read oplock) not allowed. Treat "sep=" when first mount option
898+as an overrride of comma as the default separator between mount
899+options.
900+
901+Version 1.01
902+------------
903+Allow passwords longer than 16 bytes. Allow null password string.
904+
905+Version 1.00
906+------------
907+Gracefully clean up failed mounts when attempting to mount to servers such as
908+Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
909+embedded commas in mount parsing of passwords.
910+
911+Version 0.99
912+------------
913+Invalidate local inode cached pages on oplock break and when last file
914+instance is closed so that the client does not continue using stale local
915+copy rather than later modified server copy of file. Do not reconnect
916+when server drops the tcp session prematurely before negotiate
917+protocol response. Fix oops in roepen_file when dentry freed. Allow
918+the support for CIFS Unix Extensions to be disabled via proc interface.
919+
920+Version 0.98
921+------------
922+Fix hang in commit_write during reconnection of open files under heavy load.
923+Fix unload_nls oops in a mount failure path. Serialize writes to same socket
924+which also fixes any possible races when cifs signatures are enabled in SMBs
925+being sent out of signature sequence number order.
926+
927+Version 0.97
928+------------
929+Fix byte range locking bug (endian problem) causing bad offset and
930+length.
931+
932+Version 0.96
933+------------
934+Fix oops (in send_sig) caused by CIFS unmount code trying to
935+wake up the demultiplex thread after it had exited. Do not log
936+error on harmless oplock release of closed handle.
937+
938+Version 0.95
939+------------
940+Fix unsafe global variable usage and password hash failure on gcc 3.3.1
941+Fix problem reconnecting secondary mounts to same server after session
942+failure. Fix invalid dentry - race in mkdir when directory gets created
943+by another client between the lookup and mkdir.
944+
945+Version 0.94
946+------------
947+Fix to list processing in reopen_files. Fix reconnection when server hung
948+but tcpip session still alive. Set proper timeout on socket read.
949+
950+Version 0.93
951+------------
952+Add missing mount options including iocharset. SMP fixes in write and open.
953+Fix errors in reconnecting after TCP session failure. Fix module unloading
954+of default nls codepage
955+
956+Version 0.92
957+------------
958+Active smb transactions should never go negative (fix double FreeXid). Fix
959+list processing in file routines. Check return code on kmalloc in open.
960+Fix spinlock usage for SMP.
961+
962+Version 0.91
963+------------
964+Fix oops in reopen_files when invalid dentry. drop dentry on server rename
965+and on revalidate errors. Fix cases where pid is now tgid. Fix return code
966+on create hard link when server does not support them.
967+
968+Version 0.90
969+------------
970+Fix scheduling while atomic error in getting inode info on newly created file.
971+Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
972+
973+Version 0.89
974+------------
975+Fix oops on write to dead tcp session. Remove error log write for case when file open
976+O_CREAT but not O_EXCL
977+
978+Version 0.88
979+------------
980+Fix non-POSIX behavior on rename of open file and delete of open file by taking
981+advantage of trans2 SetFileInfo rename facility if available on target server.
982+Retry on ENOSPC and EAGAIN socket errors.
983+
984+Version 0.87
985+------------
986+Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
987+allocation size miscalculation. After oplock token lost do not read through
988+cache.
989+
990+Version 0.86
991+------------
992+Fix oops on empty file readahead. Fix for file size handling for locally cached files.
993+
994+Version 0.85
995+------------
996+Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
997+during auto reconnection to server after server recovered from failure.
998+
999+Version 0.84
1000+------------
1001+Finish support for Linux 2.5 open/create changes, which removes the
1002+redundant NTCreate/QPathInfo/close that was sent during file create.
1003+Enable oplock by default. Enable packet signing by default (needed to
1004+access many recent Windows servers)
1005+
1006+Version 0.83
1007+------------
1008+Fix oops when mounting to long server names caused by inverted parms to kmalloc.
1009+Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
1010+we will choose a cifs user session (smb uid) that better matches the local
1011+uid if a) the mount uid does not match the current uid and b) we have another
1012+session to the same server (ip address) for a different mount which
1013+matches the current local uid.
1014+
1015+Version 0.82
1016+------------
1017+Add support for mknod of block or character devices. Fix oplock
1018+code (distributed caching) to properly send response to oplock
1019+break from server.
1020+
1021+Version 0.81
1022+------------
1023+Finish up CIFS packet digital signing for the default
1024+NTLM security case. This should help Windows 2003
1025+network interoperability since it is common for
1026+packet signing to be required now. Fix statfs (stat -f)
1027+which recently started returning errors due to
1028+invalid value (-1 instead of 0) being set in the
1029+struct kstatfs f_ffiles field.
1030+
1031+Version 0.80
1032+-----------
1033+Fix oops on stopping oplock thread when removing cifs when
1034+built as module.
1035+
1036+Version 0.79
1037+------------
1038+Fix mount options for ro (readonly), uid, gid and file and directory mode.
1039+
1040+Version 0.78
1041+------------
1042+Fix errors displayed on failed mounts to be more understandable.
1043+Fixed various incorrect or misleading smb to posix error code mappings.
1044+
1045+Version 0.77
1046+------------
1047+Fix display of NTFS DFS junctions to display as symlinks.
1048+They are the network equivalent. Fix oops in
1049+cifs_partialpagewrite caused by missing spinlock protection
1050+of openfile linked list. Allow writebehind caching errors to
1051+be returned to the application at file close.
1052+
1053+Version 0.76
1054+------------
1055+Clean up options displayed in /proc/mounts by show_options to
1056+be more consistent with other filesystems.
1057+
1058+Version 0.75
1059+------------
1060+Fix delete of readonly file to Windows servers. Reflect
1061+presence or absence of read only dos attribute in mode
1062+bits for servers that do not support CIFS Unix extensions.
1063+Fix shortened results on readdir of large directories to
1064+servers supporting CIFS Unix extensions (caused by
1065+incorrect resume key).
1066+
1067+Version 0.74
1068+------------
1069+Fix truncate bug (set file size) that could cause hangs e.g. running fsx
1070+
1071+Version 0.73
1072+------------
1073+unload nls if mount fails.
1074+
1075+Version 0.72
1076+------------
1077+Add resume key support to search (readdir) code to workaround
1078+Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
1079+allows disabling caching of attribute information for
1080+lookups.
1081+
1082+Version 0.71
1083+------------
1084+Add more oplock handling (distributed caching code). Remove
1085+dead code. Remove excessive stack space utilization from
1086+symlink routines.
1087+
1088+Version 0.70
1089+------------
1090+Fix oops in get dfs referral (triggered when null path sent in to
1091+mount). Add support for overriding rsize at mount time.
1092+
1093+Version 0.69
1094+------------
1095+Fix buffer overrun in readdir which caused intermittent kernel oopses.
1096+Fix writepage code to release kmap on write data. Allow "-ip=" new
1097+mount option to be passed in on parameter distinct from the first part
1098+(server name portion of) the UNC name. Allow override of the
1099+tcp port of the target server via new mount option "-port="
1100+
1101+Version 0.68
1102+------------
1103+Fix search handle leak on rewind. Fix setuid and gid so that they are
1104+reflected in the local inode immediately. Cleanup of whitespace
1105+to make 2.4 and 2.5 versions more consistent.
1106+
1107+
1108+Version 0.67
1109+------------
1110+Fix signal sending so that captive thread (cifsd) exits on umount
1111+(which was causing the warning in kmem_cache_free of the request buffers
1112+at rmmod time). This had broken as a sideeffect of the recent global
1113+kernel change to daemonize. Fix memory leak in readdir code which
1114+showed up in "ls -R" (and applications that did search rewinding).
1115+
1116+Version 0.66
1117+------------
1118+Reconnect tids and fids after session reconnection (still do not
1119+reconnect byte range locks though). Fix problem caching
1120+lookup information for directory inodes, improving performance,
1121+especially in deep directory trees. Fix various build warnings.
1122+
1123+Version 0.65
1124+------------
1125+Finish fixes to commit write for caching/readahead consistency. fsx
1126+now works to Samba servers. Fix oops caused when readahead
1127+was interrupted by a signal.
1128+
1129+Version 0.64
1130+------------
1131+Fix data corruption (in partial page after truncate) that caused fsx to
1132+fail to Windows servers. Cleaned up some extraneous error logging in
1133+common error paths. Add generic sendfile support.
1134+
1135+Version 0.63
1136+------------
1137+Fix memory leak in AllocMidQEntry.
1138+Finish reconnection logic, so connection with server can be dropped
1139+(or server rebooted) and the cifs client will reconnect.
1140+
1141+Version 0.62
1142+------------
1143+Fix temporary socket leak when bad userid or password specified
1144+(or other SMBSessSetup failure). Increase maximum buffer size to slightly
1145+over 16K to allow negotiation of up to Samba and Windows server default read
1146+sizes. Add support for readpages
1147+
1148+Version 0.61
1149+------------
1150+Fix oops when username not passed in on mount. Extensive fixes and improvements
1151+to error logging (strip redundant newlines, change debug macros to ensure newline
1152+passed in and to be more consistent). Fix writepage wrong file handle problem,
1153+a readonly file handle could be incorrectly used to attempt to write out
1154+file updates through the page cache to multiply open files. This could cause
1155+the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
1156+shares to the same Windows server when using different usernames
1157+(doing this to Samba servers worked but Windows was rejecting it) - now it is
1158+possible to use different userids when connecting to the same server from a
1159+Linux client. Fix oops when treeDisconnect called during unmount on
1160+previously freed socket.
1161+
1162+Version 0.60
1163+------------
1164+Fix oops in readpages caused by not setting address space operations in inode in
1165+rare code path.
1166+
1167+Version 0.59
1168+------------
1169+Includes support for deleting of open files and renaming over existing files (per POSIX
1170+requirement). Add readlink support for Windows junction points (directory symlinks).
1171+
1172+Version 0.58
1173+------------
1174+Changed read and write to go through pagecache. Added additional address space operations.
1175+Memory mapped operations now working.
1176+
1177+Version 0.57
1178+------------
1179+Added writepage code for additional memory mapping support. Fixed leak in xids causing
1180+the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on
1181+every stat call. Additional formatting cleanup.
1182+
1183+Version 0.56
1184+------------
1185+Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup.
1186+
1187+Version 0.55
1188+------------
1189+Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
1190+Also included a modified version of his fix to protect global list manipulation of
1191+the smb session and tree connection and mid related global variables.
1192+
1193+Version 0.54
1194+------------
1195+Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre
1196+changes to superblock layout. Remove wasteful allocation of smb buffers (now the send
1197+buffer is reused for responses). Add more oplock handling. Additional minor cleanup.
1198+
1199+Version 0.53
1200+------------
1201+More stylistic updates to better match kernel style. Add additional statistics
1202+for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2
1203+and CIFS Packet Signing enablement.
1204+
1205+Version 0.52
1206+------------
1207+Replace call to sleep_on with safer wait_on_event.
1208+Make stylistic changes to better match kernel style recommendations.
1209+Remove most typedef usage (except for the PDUs themselves).
1210+
1211+Version 0.51
1212+------------
1213+Update mount so the -unc mount option is no longer required (the ip address can be specified
1214+in a UNC style device name. Implementation of readpage/writepage started.
1215+
1216+Version 0.50
1217+------------
1218+Fix intermittent problem with incorrect smb header checking on badly
1219+fragmented tcp responses
1220+
1221+Version 0.49
1222+------------
1223+Fixes to setting of allocation size and file size.
1224+
1225+Version 0.48
1226+------------
1227+Various 2.5.38 fixes. Now works on 2.5.38
1228+
1229+Version 0.47
1230+------------
1231+Prepare for 2.5 kernel merge. Remove ifdefs.
1232+
1233+Version 0.46
1234+------------
1235+Socket buffer management fixes. Fix dual free.
1236+
1237+Version 0.45
1238+------------
1239+Various big endian fixes for hardlinks and symlinks and also for dfs.
1240+
1241+Version 0.44
1242+------------
1243+Various big endian fixes for servers with Unix extensions such as Samba
1244+
1245+Version 0.43
1246+------------
1247+Various FindNext fixes for incorrect filenames on large directory searches on big endian
1248+clients. basic posix file i/o tests now work on big endian machines, not just le
1249+
1250+Version 0.42
1251+------------
1252+SessionSetup and NegotiateProtocol now work from Big Endian machines.
1253+Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older
1254+versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
1255+
1256+Version 0.41
1257+------------
1258+Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
1259+files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
1260+
1261+Version 0.40
1262+------------
1263+Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
1264+session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
1265+Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
1266+(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
1267+
1268+Version 0.38
1269+------------
1270+Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
1271+it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
1272+
1273+Version 0.37
1274+------------
1275+Rewrote much of connection and mount/unmount logic to handle bugs with
1276+multiple uses to same share, multiple users to same server etc.
1277+
1278+Version 0.36
1279+------------
1280+Fixed major problem with dentry corruption (missing call to dput)
1281+
1282+Version 0.35
1283+------------
1284+Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
1285+Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs
1286+although corresponding function not fully implemented in the vfs yet
1287+
1288+Version 0.34
1289+------------
1290+Fixed dentry caching bug, misc. cleanup
1291+
1292+Version 0.33
1293+------------
1294+Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build
1295+on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
1296+Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added.
1297+
1298+Version 0.32
1299+------------
1300+Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
1301+and tested against Samba 2.2.5
1302+
1303+
1304+Version 0.31
1305+------------
1306+1) Fixed lockrange to be correct (it was one byte too short)
1307+
1308+2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly
1309+show range as locked when there is a conflict with an existing lock.
1310+
1311+3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
1312+in most cases. Eventually will offer optional ability to query server for the correct perms.
1313+
1314+3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded
1315+but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
1316+session)
1317+
1318+4) Fixed error logging of valid mount options
1319+
1320+5) Removed logging of password field.
1321+
1322+6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
1323+and cleaned them up and made them more consistent with other cifs functions.
1324+
1325+7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
1326+(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
1327+nor is the symlink support using the Unix extensions
1328+
1329+8) Started adding the readlink and follow_link code
1330+
1331+Version 0.3
1332+-----------
1333+Initial drop
1334+
1335--- /dev/null
1336+++ b/fs/cifs/cifs_debug.c
1337@@ -0,0 +1,797 @@
1338+/*
1339+ * fs/cifs_debug.c
1340+ *
1341+ * Copyright (C) International Business Machines Corp., 2000,2003
1342+ *
1343+ * Modified by Steve French (sfrench@us.ibm.com)
1344+ *
1345+ * This program is free software; you can redistribute it and/or modify
1346+ * it under the terms of the GNU General Public License as published by
1347+ * the Free Software Foundation; either version 2 of the License, or
1348+ * (at your option) any later version.
1349+ *
1350+ * This program is distributed in the hope that it will be useful,
1351+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1352+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1353+ * the GNU General Public License for more details.
1354+ *
1355+ * You should have received a copy of the GNU General Public License
1356+ * along with this program; if not, write to the Free Software
1357+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1358+ */
1359+#include <linux/fs.h>
1360+#include <linux/string.h>
1361+#include <linux/ctype.h>
1362+#include <linux/module.h>
1363+#include <linux/proc_fs.h>
1364+#include <asm/uaccess.h>
1365+#include "cifspdu.h"
1366+#include "cifsglob.h"
1367+#include "cifsproto.h"
1368+#include "cifs_debug.h"
1369+
1370+void
1371+cifs_dump_mem(char *label, void *data, int length)
1372+{
1373+ int i, j;
1374+ int *intptr = data;
1375+ char *charptr = data;
1376+ char buf[10], line[80];
1377+
1378+ printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
1379+ label, length, data);
1380+ for (i = 0; i < length; i += 16) {
1381+ line[0] = 0;
1382+ for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
1383+ sprintf(buf, " %08x", intptr[i / 4 + j]);
1384+ strcat(line, buf);
1385+ }
1386+ buf[0] = ' ';
1387+ buf[2] = 0;
1388+ for (j = 0; (j < 16) && (i + j < length); j++) {
1389+ buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
1390+ strcat(line, buf);
1391+ }
1392+ printk(KERN_DEBUG "%s\n", line);
1393+ }
1394+}
1395+
1396+#ifdef CONFIG_PROC_FS
1397+int
1398+cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
1399+ int count, int *eof, void *data)
1400+{
1401+ struct list_head *tmp;
1402+ struct list_head *tmp1;
1403+ struct mid_q_entry * mid_entry;
1404+ struct cifsSesInfo *ses;
1405+ struct cifsTconInfo *tcon;
1406+ int i;
1407+ int length = 0;
1408+ char * original_buf = buf;
1409+
1410+ *beginBuffer = buf + offset;
1411+
1412+
1413+ length =
1414+ sprintf(buf,
1415+ "Display Internal CIFS Data Structures for Debugging\n"
1416+ "---------------------------------------------------\n");
1417+ buf += length;
1418+
1419+ length = sprintf(buf, "Servers:\n");
1420+ buf += length;
1421+
1422+ i = 0;
1423+ read_lock(&GlobalSMBSeslock);
1424+ list_for_each(tmp, &GlobalSMBSessionList) {
1425+ i++;
1426+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1427+ length =
1428+ sprintf(buf,
1429+ "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d",
1430+ i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
1431+ ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
1432+ buf += length;
1433+ if(ses->server) {
1434+ buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
1435+ atomic_read(&ses->server->socketUseCount),
1436+ ses->server->secMode,
1437+ atomic_read(&ses->server->inFlight));
1438+
1439+ length = sprintf(buf, "\nMIDs: \n");
1440+ buf += length;
1441+
1442+ spin_lock(&GlobalMid_Lock);
1443+ list_for_each(tmp1, &ses->server->pending_mid_q) {
1444+ mid_entry = list_entry(tmp1, struct
1445+ mid_q_entry,
1446+ qhead);
1447+ if(mid_entry) {
1448+ 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);
1449+ buf += length;
1450+ }
1451+ }
1452+ spin_unlock(&GlobalMid_Lock);
1453+ }
1454+
1455+ }
1456+ read_unlock(&GlobalSMBSeslock);
1457+ sprintf(buf, "\n");
1458+ buf++;
1459+
1460+ length = sprintf(buf, "\nShares:\n");
1461+ buf += length;
1462+
1463+ i = 0;
1464+ read_lock(&GlobalSMBSeslock);
1465+ list_for_each(tmp, &GlobalTreeConnectionList) {
1466+ i++;
1467+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1468+ length =
1469+ sprintf(buf,
1470+ "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
1471+ i, tcon->treeName,
1472+ atomic_read(&tcon->useCount),
1473+ tcon->nativeFileSystem,
1474+ tcon->fsDevInfo.DeviceCharacteristics,
1475+ tcon->fsAttrInfo.Attributes,
1476+ tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
1477+ buf += length;
1478+ if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
1479+ length = sprintf(buf, " type: DISK ");
1480+ else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
1481+ length = sprintf(buf, " type: CDROM ");
1482+ else
1483+ length =
1484+ sprintf(buf, " type: %d ",
1485+ tcon->fsDevInfo.DeviceType);
1486+ buf += length;
1487+ if(tcon->tidStatus == CifsNeedReconnect) {
1488+ buf += sprintf(buf, "\tDISCONNECTED ");
1489+ length += 14;
1490+ }
1491+ }
1492+ read_unlock(&GlobalSMBSeslock);
1493+
1494+ length = sprintf(buf, "\n");
1495+ buf += length;
1496+
1497+ /* BB add code to dump additional info such as TCP session info now */
1498+ /* Now calculate total size of returned data */
1499+ length = buf - original_buf;
1500+
1501+ if(offset + count >= length)
1502+ *eof = 1;
1503+ if(length < offset) {
1504+ *eof = 1;
1505+ return 0;
1506+ } else {
1507+ length = length - offset;
1508+ }
1509+ if (length > count)
1510+ length = count;
1511+
1512+ return length;
1513+}
1514+
1515+#ifdef CONFIG_CIFS_STATS
1516+int
1517+cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
1518+ int count, int *eof, void *data)
1519+{
1520+ int item_length,i,length;
1521+ struct list_head *tmp;
1522+ struct cifsTconInfo *tcon;
1523+
1524+ *beginBuffer = buf + offset;
1525+
1526+ length = sprintf(buf,
1527+ "Resources in use\nCIFS Session: %d\n",
1528+ sesInfoAllocCount.counter);
1529+ buf += length;
1530+ item_length =
1531+ sprintf(buf,"Share (unique mount targets): %d\n",
1532+ tconInfoAllocCount.counter);
1533+ length += item_length;
1534+ buf += item_length;
1535+ item_length =
1536+ sprintf(buf,"SMB Request/Response Buffer: %d\n",
1537+ bufAllocCount.counter);
1538+ length += item_length;
1539+ buf += item_length;
1540+ item_length =
1541+ sprintf(buf,"Operations (MIDs): %d\n",
1542+ midCount.counter);
1543+ length += item_length;
1544+ buf += item_length;
1545+ item_length = sprintf(buf,
1546+ "\n%d session %d share reconnects\n",
1547+ tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
1548+ length += item_length;
1549+ buf += item_length;
1550+
1551+ item_length = sprintf(buf,
1552+ "Total vfs operations: %d maximum at one time: %d\n",
1553+ GlobalCurrentXid,GlobalMaxActiveXid);
1554+ length += item_length;
1555+ buf += item_length;
1556+
1557+ i = 0;
1558+ read_lock(&GlobalSMBSeslock);
1559+ list_for_each(tmp, &GlobalTreeConnectionList) {
1560+ i++;
1561+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1562+ item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
1563+ buf += item_length;
1564+ length += item_length;
1565+ if(tcon->tidStatus == CifsNeedReconnect) {
1566+ buf += sprintf(buf, "\tDISCONNECTED ");
1567+ length += 14;
1568+ }
1569+ item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
1570+ atomic_read(&tcon->num_smbs_sent),
1571+ atomic_read(&tcon->num_oplock_brks));
1572+ buf += item_length;
1573+ length += item_length;
1574+ item_length = sprintf(buf,"\nReads: %d Bytes %lld",
1575+ atomic_read(&tcon->num_reads),
1576+ (long long)(tcon->bytes_read));
1577+ buf += item_length;
1578+ length += item_length;
1579+ item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
1580+ atomic_read(&tcon->num_writes),
1581+ (long long)(tcon->bytes_written));
1582+ buf += item_length;
1583+ length += item_length;
1584+ item_length = sprintf(buf,
1585+ "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
1586+ atomic_read(&tcon->num_opens),
1587+ atomic_read(&tcon->num_deletes),
1588+ atomic_read(&tcon->num_mkdirs),
1589+ atomic_read(&tcon->num_rmdirs));
1590+ buf += item_length;
1591+ length += item_length;
1592+ item_length = sprintf(buf,
1593+ "\nRenames: %d T2 Renames %d",
1594+ atomic_read(&tcon->num_renames),
1595+ atomic_read(&tcon->num_t2renames));
1596+ buf += item_length;
1597+ length += item_length;
1598+ }
1599+ read_unlock(&GlobalSMBSeslock);
1600+
1601+ buf += sprintf(buf,"\n");
1602+ length++;
1603+
1604+ if(offset + count >= length)
1605+ *eof = 1;
1606+ if(length < offset) {
1607+ *eof = 1;
1608+ return 0;
1609+ } else {
1610+ length = length - offset;
1611+ }
1612+ if (length > count)
1613+ length = count;
1614+
1615+ return length;
1616+}
1617+#endif
1618+
1619+struct proc_dir_entry *proc_fs_cifs;
1620+read_proc_t cifs_txanchor_read;
1621+static read_proc_t cifsFYI_read;
1622+static write_proc_t cifsFYI_write;
1623+static read_proc_t oplockEnabled_read;
1624+static write_proc_t oplockEnabled_write;
1625+static read_proc_t lookupFlag_read;
1626+static write_proc_t lookupFlag_write;
1627+static read_proc_t traceSMB_read;
1628+static write_proc_t traceSMB_write;
1629+static read_proc_t multiuser_mount_read;
1630+static write_proc_t multiuser_mount_write;
1631+static read_proc_t extended_security_read;
1632+static write_proc_t extended_security_write;
1633+static read_proc_t ntlmv2_enabled_read;
1634+static write_proc_t ntlmv2_enabled_write;
1635+static read_proc_t packet_signing_enabled_read;
1636+static write_proc_t packet_signing_enabled_write;
1637+static read_proc_t quotaEnabled_read;
1638+static write_proc_t quotaEnabled_write;
1639+static read_proc_t linuxExtensionsEnabled_read;
1640+static write_proc_t linuxExtensionsEnabled_write;
1641+
1642+void
1643+cifs_proc_init(void)
1644+{
1645+ struct proc_dir_entry *pde;
1646+
1647+ proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
1648+ if (proc_fs_cifs == NULL)
1649+ return;
1650+
1651+ proc_fs_cifs->owner = THIS_MODULE;
1652+ create_proc_read_entry("DebugData", 0, proc_fs_cifs,
1653+ cifs_debug_data_read, NULL);
1654+
1655+#ifdef CONFIG_CIFS_STATS
1656+ create_proc_read_entry("Stats", 0, proc_fs_cifs,
1657+ cifs_stats_read, NULL);
1658+#endif
1659+ pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
1660+ cifsFYI_read, NULL);
1661+ if (pde)
1662+ pde->write_proc = cifsFYI_write;
1663+
1664+ pde =
1665+ create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
1666+ traceSMB_read, NULL);
1667+ if (pde)
1668+ pde->write_proc = traceSMB_write;
1669+
1670+ pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
1671+ oplockEnabled_read, NULL);
1672+ if (pde)
1673+ pde->write_proc = oplockEnabled_write;
1674+
1675+ pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
1676+ quotaEnabled_read, NULL);
1677+ if (pde)
1678+ pde->write_proc = quotaEnabled_write;
1679+
1680+ pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
1681+ linuxExtensionsEnabled_read, NULL);
1682+ if (pde)
1683+ pde->write_proc = linuxExtensionsEnabled_write;
1684+
1685+ pde =
1686+ create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
1687+ multiuser_mount_read, NULL);
1688+ if (pde)
1689+ pde->write_proc = multiuser_mount_write;
1690+
1691+ pde =
1692+ create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
1693+ extended_security_read, NULL);
1694+ if (pde)
1695+ pde->write_proc = extended_security_write;
1696+
1697+ pde =
1698+ create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
1699+ lookupFlag_read, NULL);
1700+ if (pde)
1701+ pde->write_proc = lookupFlag_write;
1702+
1703+ pde =
1704+ create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
1705+ ntlmv2_enabled_read, NULL);
1706+ if (pde)
1707+ pde->write_proc = ntlmv2_enabled_write;
1708+
1709+ pde =
1710+ create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
1711+ packet_signing_enabled_read, NULL);
1712+ if (pde)
1713+ pde->write_proc = packet_signing_enabled_write;
1714+}
1715+
1716+void
1717+cifs_proc_clean(void)
1718+{
1719+ if (proc_fs_cifs == NULL)
1720+ return;
1721+
1722+ remove_proc_entry("DebugData", proc_fs_cifs);
1723+ remove_proc_entry("cifsFYI", proc_fs_cifs);
1724+ remove_proc_entry("traceSMB", proc_fs_cifs);
1725+#ifdef CONFIG_CIFS_STATS
1726+ remove_proc_entry("Stats", proc_fs_cifs);
1727+#endif
1728+ remove_proc_entry("MultiuserMount", proc_fs_cifs);
1729+ remove_proc_entry("OplockEnabled", proc_fs_cifs);
1730+ remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
1731+ remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
1732+ remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
1733+ remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
1734+ remove_proc_entry("QuotaEnabled",proc_fs_cifs);
1735+ remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
1736+ remove_proc_entry("cifs", proc_root_fs);
1737+}
1738+
1739+static int
1740+cifsFYI_read(char *page, char **start, off_t off, int count,
1741+ int *eof, void *data)
1742+{
1743+ int len;
1744+
1745+ len = sprintf(page, "%d\n", cifsFYI);
1746+
1747+ len -= off;
1748+ *start = page + off;
1749+
1750+ if (len > count)
1751+ len = count;
1752+ else
1753+ *eof = 1;
1754+
1755+ if (len < 0)
1756+ len = 0;
1757+
1758+ return len;
1759+}
1760+static int
1761+cifsFYI_write(struct file *file, const char *buffer,
1762+ unsigned long count, void *data)
1763+{
1764+ char c;
1765+ int rc;
1766+
1767+ rc = get_user(c, buffer);
1768+ if (rc)
1769+ return rc;
1770+ if (c == '0' || c == 'n' || c == 'N')
1771+ cifsFYI = 0;
1772+ else if (c == '1' || c == 'y' || c == 'Y')
1773+ cifsFYI = 1;
1774+
1775+ return count;
1776+}
1777+
1778+static int
1779+oplockEnabled_read(char *page, char **start, off_t off,
1780+ int count, int *eof, void *data)
1781+{
1782+ int len;
1783+
1784+ len = sprintf(page, "%d\n", oplockEnabled);
1785+
1786+ len -= off;
1787+ *start = page + off;
1788+
1789+ if (len > count)
1790+ len = count;
1791+ else
1792+ *eof = 1;
1793+
1794+ if (len < 0)
1795+ len = 0;
1796+
1797+ return len;
1798+}
1799+static int
1800+oplockEnabled_write(struct file *file, const char *buffer,
1801+ unsigned long count, void *data)
1802+{
1803+ char c;
1804+ int rc;
1805+
1806+ rc = get_user(c, buffer);
1807+ if (rc)
1808+ return rc;
1809+ if (c == '0' || c == 'n' || c == 'N')
1810+ oplockEnabled = 0;
1811+ else if (c == '1' || c == 'y' || c == 'Y')
1812+ oplockEnabled = 1;
1813+
1814+ return count;
1815+}
1816+
1817+static int
1818+quotaEnabled_read(char *page, char **start, off_t off,
1819+ int count, int *eof, void *data)
1820+{
1821+ int len;
1822+
1823+ len = sprintf(page, "%d\n", quotaEnabled);
1824+/* could also check if quotas are enabled in kernel
1825+ as a whole first */
1826+ len -= off;
1827+ *start = page + off;
1828+
1829+ if (len > count)
1830+ len = count;
1831+ else
1832+ *eof = 1;
1833+
1834+ if (len < 0)
1835+ len = 0;
1836+
1837+ return len;
1838+}
1839+static int
1840+quotaEnabled_write(struct file *file, const char *buffer,
1841+ unsigned long count, void *data)
1842+{
1843+ char c;
1844+ int rc;
1845+
1846+ rc = get_user(c, buffer);
1847+ if (rc)
1848+ return rc;
1849+ if (c == '0' || c == 'n' || c == 'N')
1850+ quotaEnabled = 0;
1851+ else if (c == '1' || c == 'y' || c == 'Y')
1852+ quotaEnabled = 1;
1853+
1854+ return count;
1855+}
1856+
1857+static int
1858+linuxExtensionsEnabled_read(char *page, char **start, off_t off,
1859+ int count, int *eof, void *data)
1860+{
1861+ int len;
1862+
1863+ len = sprintf(page, "%d\n", linuxExtEnabled);
1864+/* could also check if quotas are enabled in kernel
1865+ as a whole first */
1866+ len -= off;
1867+ *start = page + off;
1868+
1869+ if (len > count)
1870+ len = count;
1871+ else
1872+ *eof = 1;
1873+
1874+ if (len < 0)
1875+ len = 0;
1876+
1877+ return len;
1878+}
1879+static int
1880+linuxExtensionsEnabled_write(struct file *file, const char *buffer,
1881+ unsigned long count, void *data)
1882+{
1883+ char c;
1884+ int rc;
1885+
1886+ rc = get_user(c, buffer);
1887+ if (rc)
1888+ return rc;
1889+ if (c == '0' || c == 'n' || c == 'N')
1890+ linuxExtEnabled = 0;
1891+ else if (c == '1' || c == 'y' || c == 'Y')
1892+ linuxExtEnabled = 1;
1893+
1894+ return count;
1895+}
1896+
1897+
1898+static int
1899+lookupFlag_read(char *page, char **start, off_t off,
1900+ int count, int *eof, void *data)
1901+{
1902+ int len;
1903+
1904+ len = sprintf(page, "%d\n", lookupCacheEnabled);
1905+
1906+ len -= off;
1907+ *start = page + off;
1908+
1909+ if (len > count)
1910+ len = count;
1911+ else
1912+ *eof = 1;
1913+
1914+ if (len < 0)
1915+ len = 0;
1916+
1917+ return len;
1918+}
1919+static int
1920+lookupFlag_write(struct file *file, const char *buffer,
1921+ unsigned long count, void *data)
1922+{
1923+ char c;
1924+ int rc;
1925+
1926+ rc = get_user(c, buffer);
1927+ if (rc)
1928+ return rc;
1929+ if (c == '0' || c == 'n' || c == 'N')
1930+ lookupCacheEnabled = 0;
1931+ else if (c == '1' || c == 'y' || c == 'Y')
1932+ lookupCacheEnabled = 1;
1933+
1934+ return count;
1935+}
1936+static int
1937+traceSMB_read(char *page, char **start, off_t off, int count,
1938+ int *eof, void *data)
1939+{
1940+ int len;
1941+
1942+ len = sprintf(page, "%d\n", traceSMB);
1943+
1944+ len -= off;
1945+ *start = page + off;
1946+
1947+ if (len > count)
1948+ len = count;
1949+ else
1950+ *eof = 1;
1951+
1952+ if (len < 0)
1953+ len = 0;
1954+
1955+ return len;
1956+}
1957+static int
1958+traceSMB_write(struct file *file, const char *buffer,
1959+ unsigned long count, void *data)
1960+{
1961+ char c;
1962+ int rc;
1963+
1964+ rc = get_user(c, buffer);
1965+ if (rc)
1966+ return rc;
1967+ if (c == '0' || c == 'n' || c == 'N')
1968+ traceSMB = 0;
1969+ else if (c == '1' || c == 'y' || c == 'Y')
1970+ traceSMB = 1;
1971+
1972+ return count;
1973+}
1974+
1975+static int
1976+multiuser_mount_read(char *page, char **start, off_t off,
1977+ int count, int *eof, void *data)
1978+{
1979+ int len;
1980+
1981+ len = sprintf(page, "%d\n", multiuser_mount);
1982+
1983+ len -= off;
1984+ *start = page + off;
1985+
1986+ if (len > count)
1987+ len = count;
1988+ else
1989+ *eof = 1;
1990+
1991+ if (len < 0)
1992+ len = 0;
1993+
1994+ return len;
1995+}
1996+static int
1997+multiuser_mount_write(struct file *file, const char *buffer,
1998+ unsigned long count, void *data)
1999+{
2000+ char c;
2001+ int rc;
2002+
2003+ rc = get_user(c, buffer);
2004+ if (rc)
2005+ return rc;
2006+ if (c == '0' || c == 'n' || c == 'N')
2007+ multiuser_mount = 0;
2008+ else if (c == '1' || c == 'y' || c == 'Y')
2009+ multiuser_mount = 1;
2010+
2011+ return count;
2012+}
2013+
2014+static int
2015+extended_security_read(char *page, char **start, off_t off,
2016+ int count, int *eof, void *data)
2017+{
2018+ int len;
2019+
2020+ len = sprintf(page, "%d\n", extended_security);
2021+
2022+ len -= off;
2023+ *start = page + off;
2024+
2025+ if (len > count)
2026+ len = count;
2027+ else
2028+ *eof = 1;
2029+
2030+ if (len < 0)
2031+ len = 0;
2032+
2033+ return len;
2034+}
2035+static int
2036+extended_security_write(struct file *file, const char *buffer,
2037+ unsigned long count, void *data)
2038+{
2039+ char c;
2040+ int rc;
2041+
2042+ rc = get_user(c, buffer);
2043+ if (rc)
2044+ return rc;
2045+ if (c == '0' || c == 'n' || c == 'N')
2046+ extended_security = 0;
2047+ else if (c == '1' || c == 'y' || c == 'Y')
2048+ extended_security = 1;
2049+
2050+ return count;
2051+}
2052+
2053+static int
2054+ntlmv2_enabled_read(char *page, char **start, off_t off,
2055+ int count, int *eof, void *data)
2056+{
2057+ int len;
2058+
2059+ len = sprintf(page, "%d\n", ntlmv2_support);
2060+
2061+ len -= off;
2062+ *start = page + off;
2063+
2064+ if (len > count)
2065+ len = count;
2066+ else
2067+ *eof = 1;
2068+
2069+ if (len < 0)
2070+ len = 0;
2071+
2072+ return len;
2073+}
2074+static int
2075+ntlmv2_enabled_write(struct file *file, const char *buffer,
2076+ unsigned long count, void *data)
2077+{
2078+ char c;
2079+ int rc;
2080+
2081+ rc = get_user(c, buffer);
2082+ if (rc)
2083+ return rc;
2084+ if (c == '0' || c == 'n' || c == 'N')
2085+ ntlmv2_support = 0;
2086+ else if (c == '1' || c == 'y' || c == 'Y')
2087+ ntlmv2_support = 1;
2088+
2089+ return count;
2090+}
2091+
2092+static int
2093+packet_signing_enabled_read(char *page, char **start, off_t off,
2094+ int count, int *eof, void *data)
2095+{
2096+ int len;
2097+
2098+ len = sprintf(page, "%d\n", sign_CIFS_PDUs);
2099+
2100+ len -= off;
2101+ *start = page + off;
2102+
2103+ if (len > count)
2104+ len = count;
2105+ else
2106+ *eof = 1;
2107+
2108+ if (len < 0)
2109+ len = 0;
2110+
2111+ return len;
2112+}
2113+static int
2114+packet_signing_enabled_write(struct file *file, const char *buffer,
2115+ unsigned long count, void *data)
2116+{
2117+ char c;
2118+ int rc;
2119+
2120+ rc = get_user(c, buffer);
2121+ if (rc)
2122+ return rc;
2123+ if (c == '0' || c == 'n' || c == 'N')
2124+ sign_CIFS_PDUs = 0;
2125+ else if (c == '1' || c == 'y' || c == 'Y')
2126+ sign_CIFS_PDUs = 1;
2127+ else if (c == '2')
2128+ sign_CIFS_PDUs = 2;
2129+
2130+ return count;
2131+}
2132+
2133+
2134+#endif
2135--- /dev/null
2136+++ b/fs/cifs/cifs_debug.h
2137@@ -0,0 +1,66 @@
2138+/*
2139+ *
2140+ * Copyright (c) International Business Machines Corp., 2000,2002
2141+ * Modified by Steve French (sfrench@us.ibm.com)
2142+ *
2143+ * This program is free software; you can redistribute it and/or modify
2144+ * it under the terms of the GNU General Public License as published by
2145+ * the Free Software Foundation; either version 2 of the License, or
2146+ * (at your option) any later version.
2147+ *
2148+ * This program is distributed in the hope that it will be useful,
2149+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2150+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2151+ * the GNU General Public License for more details.
2152+ *
2153+ * You should have received a copy of the GNU General Public License
2154+ * along with this program; if not, write to the Free Software
2155+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2156+ *
2157+*/
2158+#define CIFS_DEBUG /* BB temporary */
2159+
2160+#ifndef _H_CIFS_DEBUG
2161+#define _H_CIFS_DEBUG
2162+
2163+void cifs_dump_mem(char *label, void *data, int length);
2164+extern int traceSMB; /* flag which enables the function below */
2165+void dump_smb(struct smb_hdr *, int);
2166+
2167+/*
2168+ * debug ON
2169+ * --------
2170+ */
2171+#ifdef CIFS_DEBUG
2172+
2173+
2174+/* information message: e.g., configuration, major event */
2175+extern int cifsFYI;
2176+#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
2177+
2178+#define cFYI(button,prspec) if (button) cifsfyi prspec
2179+
2180+#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
2181+
2182+/* debug event message: */
2183+extern int cifsERROR;
2184+
2185+#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
2186+
2187+/* error event message: e.g., i/o error */
2188+#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
2189+
2190+#define cERROR(button, prspec) if (button) cifserror prspec
2191+
2192+/*
2193+ * debug OFF
2194+ * ---------
2195+ */
2196+#else /* _CIFS_DEBUG */
2197+#define cERROR(button,prspec)
2198+#define cEVENT(format,arg...)
2199+#define cFYI(button, prspec)
2200+#define cifserror(format,arg...)
2201+#endif /* _CIFS_DEBUG */
2202+
2203+#endif /* _H_CIFS_DEBUG */
2204--- /dev/null
2205+++ b/fs/cifs/cifsencrypt.c
2206@@ -0,0 +1,204 @@
2207+/*
2208+ * fs/cifs/cifsencrypt.c
2209+ *
2210+ * Copyright (C) International Business Machines Corp., 2003
2211+ * Author(s): Steve French (sfrench@us.ibm.com)
2212+ *
2213+ * This library is free software; you can redistribute it and/or modify
2214+ * it under the terms of the GNU Lesser General Public License as published
2215+ * by the Free Software Foundation; either version 2.1 of the License, or
2216+ * (at your option) any later version.
2217+ *
2218+ * This library is distributed in the hope that it will be useful,
2219+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2220+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2221+ * the GNU Lesser General Public License for more details.
2222+ *
2223+ * You should have received a copy of the GNU Lesser General Public License
2224+ * along with this library; if not, write to the Free Software
2225+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2226+ */
2227+
2228+#include <linux/fs.h>
2229+#include "cifspdu.h"
2230+#include "cifsglob.h"
2231+#include "cifs_debug.h"
2232+#include "md5.h"
2233+#include "cifs_unicode.h"
2234+
2235+/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
2236+/* the 16 byte signature must be allocated by the caller */
2237+/* Note we only use the 1st eight bytes */
2238+/* Note that the smb header signature field on input contains the
2239+ sequence number before this function is called */
2240+
2241+extern void mdfour(unsigned char *out, unsigned char *in, int n);
2242+extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
2243+
2244+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
2245+{
2246+ struct MD5Context context;
2247+
2248+ if((cifs_pdu == NULL) || (signature == NULL))
2249+ return -EINVAL;
2250+
2251+ MD5Init(&context);
2252+ MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
2253+ MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
2254+ MD5Final(signature,&context);
2255+ return 0;
2256+}
2257+
2258+int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
2259+ __u32 * pexpected_response_sequence_number)
2260+{
2261+ int rc = 0;
2262+ char smb_signature[20];
2263+
2264+ /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
2265+ /* BB remember to add code to save expected sequence number in midQ entry BB */
2266+
2267+ if((cifs_pdu == NULL) || (ses == NULL))
2268+ return -EINVAL;
2269+
2270+ if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
2271+ return rc;
2272+
2273+ spin_lock(&GlobalMid_Lock);
2274+ cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
2275+ cifs_pdu->Signature.Sequence.Reserved = 0;
2276+
2277+ *pexpected_response_sequence_number = ses->sequence_number++;
2278+ ses->sequence_number++;
2279+ spin_unlock(&GlobalMid_Lock);
2280+
2281+ rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
2282+ if(rc)
2283+ memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
2284+ else
2285+ memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
2286+
2287+ return rc;
2288+}
2289+
2290+int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
2291+ __u32 expected_sequence_number)
2292+{
2293+ unsigned int rc;
2294+ char server_response_sig[8];
2295+ char what_we_think_sig_should_be[20];
2296+
2297+ if((cifs_pdu == NULL) || (mac_key == NULL))
2298+ return -EINVAL;
2299+
2300+ if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
2301+ return 0;
2302+
2303+ if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
2304+ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
2305+ if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
2306+ return 0;
2307+ }
2308+
2309+ /* BB what if signatures are supposed to be on for session but server does not
2310+ send one? BB */
2311+
2312+ /* Do not need to verify session setups with signature "BSRSPYL " */
2313+ if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
2314+ cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
2315+
2316+ expected_sequence_number = cpu_to_le32(expected_sequence_number);
2317+
2318+ /* save off the origiginal signature so we can modify the smb and check
2319+ its signature against what the server sent */
2320+ memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
2321+
2322+ cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
2323+ cifs_pdu->Signature.Sequence.Reserved = 0;
2324+
2325+ rc = cifs_calculate_signature(cifs_pdu, mac_key,
2326+ what_we_think_sig_should_be);
2327+
2328+ if(rc)
2329+ return rc;
2330+
2331+
2332+/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
2333+
2334+ if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
2335+ return -EACCES;
2336+ else
2337+ return 0;
2338+
2339+}
2340+
2341+/* We fill in key by putting in 40 byte array which was allocated by caller */
2342+int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
2343+{
2344+ char temp_key[16];
2345+ if ((key == NULL) || (rn == NULL))
2346+ return -EINVAL;
2347+
2348+ E_md4hash(password, temp_key);
2349+ mdfour(key,temp_key,16);
2350+ memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
2351+ return 0;
2352+}
2353+
2354+int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
2355+{
2356+ char temp_hash[16];
2357+ struct HMACMD5Context ctx;
2358+ char * ucase_buf;
2359+ wchar_t * unicode_buf;
2360+ unsigned int i,user_name_len,dom_name_len;
2361+
2362+ if(ses)
2363+ return -EINVAL;
2364+
2365+ E_md4hash(ses->password, temp_hash);
2366+
2367+ hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
2368+ user_name_len = strlen(ses->userName);
2369+ if(user_name_len > MAX_USERNAME_SIZE)
2370+ return -EINVAL;
2371+ dom_name_len = strlen(ses->domainName);
2372+ if(dom_name_len > MAX_USERNAME_SIZE)
2373+ return -EINVAL;
2374+
2375+ ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
2376+ unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
2377+
2378+ for(i=0;i<user_name_len;i++)
2379+ ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
2380+ ucase_buf[i] = 0;
2381+ user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
2382+ unicode_buf[user_name_len] = 0;
2383+ user_name_len++;
2384+
2385+ for(i=0;i<dom_name_len;i++)
2386+ ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
2387+ ucase_buf[i] = 0;
2388+ dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
2389+
2390+ unicode_buf[user_name_len + dom_name_len] = 0;
2391+ hmac_md5_update((const unsigned char *) unicode_buf,
2392+ (user_name_len+dom_name_len)*2,&ctx);
2393+
2394+ hmac_md5_final(ses->mac_signing_key,&ctx);
2395+ kfree(ucase_buf);
2396+ kfree(unicode_buf);
2397+ return 0;
2398+}
2399+void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
2400+{
2401+ struct HMACMD5Context context;
2402+ memcpy(v2_session_response + 8, ses->server->cryptKey,8);
2403+ /* gen_blob(v2_session_response + 16); */
2404+ hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
2405+
2406+ hmac_md5_update(ses->server->cryptKey,8,&context);
2407+/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
2408+
2409+ hmac_md5_final(v2_session_response,&context);
2410+}
2411--- /dev/null
2412+++ b/fs/cifs/cifserr.c
2413@@ -0,0 +1,70 @@
2414+/*
2415+ * fs/cifserr.c
2416+ *
2417+ * Copyright (c) International Business Machines Corp., 2002
2418+ * Author(s): Steve French (sfrench@us.ibm.com)
2419+ *
2420+ * This library is free software; you can redistribute it and/or modify
2421+ * it under the terms of the GNU Lesser General Public License as published
2422+ * by the Free Software Foundation; either version 2.1 of the License, or
2423+ * (at your option) any later version.
2424+ *
2425+ * This library is distributed in the hope that it will be useful,
2426+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2427+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2428+ * the GNU Lesser General Public License for more details.
2429+ *
2430+ * You should have received a copy of the GNU Lesser General Public License
2431+ * along with this library; if not, write to the Free Software
2432+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2433+ */
2434+
2435+#include <linux/errno.h>
2436+#include <linux/fs.h>
2437+#include <linux/smbno.h>
2438+#include "cifsfs.h"
2439+
2440+int map_cifs_error(int error_class, int error_code,
2441+ int status_codes_negotiated)
2442+{
2443+
2444+
2445+ if (status_codes_negotiated) {
2446+ switch (error_code) {
2447+ default:
2448+ return EIO;
2449+ }
2450+ } else
2451+ switch (error_class) {
2452+ case SUCCESS:
2453+ return 0;
2454+
2455+ case ERRDOS:
2456+ switch (error_code) {
2457+ case ERRbadfunc:
2458+ return EINVAL;
2459+ default:
2460+ return EIO;
2461+ }
2462+
2463+ case ERRSRV:
2464+ switch (error_code) {
2465+ default:
2466+ return EIO;
2467+ }
2468+
2469+ case ERRHRD:
2470+ switch (error_code) {
2471+ default:
2472+ return EIO;
2473+ }
2474+ default:
2475+ return EIO;
2476+ }
2477+ return 0;
2478+}
2479+
2480+int map_smb_error(int error_class, int error_code)
2481+{
2482+ return map_cifs_error(error_class, error_code, FALSE);
2483+}
2484--- /dev/null
2485+++ b/fs/cifs/cifsfs.c
2486@@ -0,0 +1,769 @@
2487+/*
2488+ * fs/cifs/cifsfs.c
2489+ *
2490+ * Copyright (C) International Business Machines Corp., 2002,2004
2491+ * Author(s): Steve French (sfrench@us.ibm.com)
2492+ *
2493+ * Common Internet FileSystem (CIFS) client
2494+ *
2495+ * This library is free software; you can redistribute it and/or modify
2496+ * it under the terms of the GNU Lesser General Public License as published
2497+ * by the Free Software Foundation; either version 2.1 of the License, or
2498+ * (at your option) any later version.
2499+ *
2500+ * This library is distributed in the hope that it will be useful,
2501+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2502+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2503+ * the GNU Lesser General Public License for more details.
2504+ *
2505+ * You should have received a copy of the GNU Lesser General Public License
2506+ * along with this library; if not, write to the Free Software
2507+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2508+ */
2509+
2510+/* Note that BB means BUGBUG (ie something to fix eventually) */
2511+
2512+#include <linux/module.h>
2513+#include <linux/fs.h>
2514+#include <linux/mount.h>
2515+#include <linux/slab.h>
2516+#include <linux/init.h>
2517+#include <linux/version.h>
2518+#include <linux/list.h>
2519+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2520+#include <linux/seq_file.h>
2521+#endif
2522+#include <linux/vfs.h>
2523+#include "cifsfs.h"
2524+#include "cifspdu.h"
2525+#define DECLARE_GLOBALS_HERE
2526+#include "cifsglob.h"
2527+#include "cifsproto.h"
2528+#include "cifs_debug.h"
2529+#include "cifs_fs_sb.h"
2530+#include <linux/mm.h>
2531+#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
2532+/* BB when mempool_resize is added back in, we will resize pool on new mount */
2533+#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
2534+
2535+#ifdef CONFIG_CIFS_QUOTA
2536+static struct quotactl_ops cifs_quotactl_ops;
2537+#endif
2538+
2539+extern struct file_system_type cifs_fs_type;
2540+
2541+int cifsFYI = 0;
2542+int cifsERROR = 1;
2543+int traceSMB = 0;
2544+unsigned int oplockEnabled = 1;
2545+unsigned int quotaEnabled = 0;
2546+unsigned int linuxExtEnabled = 1;
2547+unsigned int lookupCacheEnabled = 1;
2548+unsigned int multiuser_mount = 0;
2549+unsigned int extended_security = 0;
2550+unsigned int ntlmv2_support = 0;
2551+unsigned int sign_CIFS_PDUs = 1;
2552+unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
2553+struct task_struct * oplockThread = NULL;
2554+
2555+extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
2556+ const char *);
2557+extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
2558+void cifs_proc_init(void);
2559+void cifs_proc_clean(void);
2560+
2561+static DECLARE_COMPLETION(cifs_oplock_exited);
2562+
2563+
2564+struct super_block *
2565+cifs_read_super(struct super_block *sb, void *data, int silent)
2566+{
2567+ struct inode *inode;
2568+ struct cifs_sb_info *cifs_sb;
2569+ int rc = 0;
2570+
2571+ sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
2572+ cifs_sb = CIFS_SB(sb);
2573+ if(cifs_sb == NULL)
2574+ return 0;
2575+ else
2576+ memset(cifs_sb,0,sizeof(struct cifs_sb_info));
2577+
2578+
2579+ rc = cifs_mount(sb, cifs_sb, data, NULL);
2580+
2581+ if (rc) {
2582+ if (!silent)
2583+ cERROR(1,
2584+ ("cifs_mount failed w/return code = %d", rc));
2585+ goto out_mount_failed;
2586+ }
2587+
2588+ sb->s_magic = CIFS_MAGIC_NUMBER;
2589+ sb->s_op = &cifs_super_ops;
2590+/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
2591+ sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
2592+#ifdef CONFIG_CIFS_QUOTA
2593+ sb->s_qcop = &cifs_quotactl_ops;
2594+#endif
2595+ sb->s_blocksize = CIFS_MAX_MSGSIZE;
2596+ sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
2597+ inode = iget(sb, ROOT_I);
2598+
2599+ if (!inode) {
2600+ goto out_no_root;
2601+ }
2602+
2603+ sb->s_root = d_alloc_root(inode);
2604+
2605+ if (!sb->s_root) {
2606+ goto out_no_root;
2607+ }
2608+
2609+ return sb;
2610+
2611+out_no_root:
2612+ cERROR(1, ("cifs_read_super: get root inode failed"));
2613+ if (inode)
2614+ iput(inode);
2615+
2616+out_mount_failed:
2617+ if(cifs_sb->local_nls)
2618+ unload_nls(cifs_sb->local_nls);
2619+ sb->s_dev = 0;
2620+ return 0;
2621+}
2622+
2623+static void
2624+cifs_put_super(struct super_block *sb)
2625+{
2626+ int rc = 0;
2627+ struct cifs_sb_info *cifs_sb;
2628+
2629+ cFYI(1, ("In cifs_put_super"));
2630+ cifs_sb = CIFS_SB(sb);
2631+ if(cifs_sb == NULL) {
2632+ cFYI(1,("Empty cifs superblock info passed to unmount"));
2633+ return;
2634+ }
2635+ rc = cifs_umount(sb, cifs_sb);
2636+ if (rc) {
2637+ cERROR(1, ("cifs_umount failed with return code %d", rc));
2638+ }
2639+ unload_nls(cifs_sb->local_nls);
2640+ return;
2641+}
2642+
2643+static int
2644+cifs_statfs(struct super_block *sb, struct statfs *buf)
2645+{
2646+ int xid, rc;
2647+ struct cifs_sb_info *cifs_sb;
2648+ struct cifsTconInfo *pTcon;
2649+
2650+ xid = GetXid();
2651+
2652+ cifs_sb = CIFS_SB(sb);
2653+ pTcon = cifs_sb->tcon;
2654+
2655+ buf->f_type = CIFS_MAGIC_NUMBER;
2656+
2657+ /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
2658+ buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably
2659+ be length of total path, note that some servers may be
2660+ able to support more than this, but best to be safe
2661+ since Win2k and others can not handle very long filenames */
2662+ buf->f_files = 0; /* undefined */
2663+ buf->f_ffree = 0; /* unlimited */
2664+
2665+ rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
2666+
2667+ /*
2668+ int f_type;
2669+ __fsid_t f_fsid;
2670+ int f_namelen; */
2671+ /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
2672+ FreeXid(xid);
2673+ return 0; /* always return success? what if volume is no longer available? */
2674+}
2675+
2676+static int cifs_permission(struct inode * inode, int mask)
2677+{
2678+ /* the server does permission checks, we do not need to do it here */
2679+ return 0;
2680+}
2681+
2682+kmem_cache_t *cifs_req_cachep;
2683+kmem_cache_t *cifs_mid_cachep;
2684+kmem_cache_t *cifs_oplock_cachep;
2685+
2686+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2687+static struct inode *
2688+cifs_alloc_inode(struct super_block *sb)
2689+{
2690+ struct cifsInodeInfo *cifs_inode;
2691+ cifs_inode =
2692+ (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
2693+ SLAB_KERNEL);
2694+ if (!cifs_inode)
2695+ return NULL;
2696+ cifs_inode->cifsAttrs = 0x20; /* default */
2697+ atomic_set(&cifs_inode->inUse, 0);
2698+ cifs_inode->time = 0;
2699+ /* Until the file is open and we have gotten oplock
2700+ info back from the server, can not assume caching of
2701+ file data or metadata */
2702+ cifs_inode->clientCanCacheRead = FALSE;
2703+ cifs_inode->clientCanCacheAll = FALSE;
2704+ INIT_LIST_HEAD(&cifs_inode->openFileList);
2705+ return &cifs_inode->vfs_inode;
2706+}
2707+
2708+static void
2709+cifs_destroy_inode(struct inode *inode)
2710+{
2711+ kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
2712+}
2713+#endif
2714+
2715+/*
2716+ * cifs_show_options() is for displaying mount options in /proc/mounts.
2717+ * Not all settable options are displayed but most of the important
2718+ * ones are.
2719+ */
2720+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2721+static int
2722+cifs_show_options(struct seq_file *s, struct vfsmount *m)
2723+{
2724+ struct cifs_sb_info *cifs_sb;
2725+
2726+ cifs_sb = CIFS_SB(m->mnt_sb);
2727+
2728+ if (cifs_sb) {
2729+ if (cifs_sb->tcon) {
2730+ seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
2731+ if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
2732+ seq_printf(s, ",username=%s",
2733+ cifs_sb->tcon->ses->userName);
2734+ if(cifs_sb->tcon->ses->domainName)
2735+ seq_printf(s, ",domain=%s",
2736+ cifs_sb->tcon->ses->domainName);
2737+ }
2738+ seq_printf(s, ",rsize=%d",cifs_sb->rsize);
2739+ seq_printf(s, ",wsize=%d",cifs_sb->wsize);
2740+ }
2741+ return 0;
2742+}
2743+#endif
2744+
2745+#ifdef CONFIG_CIFS_QUOTA
2746+int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
2747+ struct fs_disk_quota * pdquota)
2748+{
2749+ int xid;
2750+ int rc = 0;
2751+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2752+ struct cifsTconInfo *pTcon;
2753+
2754+ if(cifs_sb)
2755+ pTcon = cifs_sb->tcon;
2756+ else
2757+ return -EIO;
2758+
2759+
2760+ xid = GetXid();
2761+ if(pTcon) {
2762+ cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
2763+ } else {
2764+ return -EIO;
2765+ }
2766+
2767+ FreeXid(xid);
2768+ return rc;
2769+}
2770+
2771+int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
2772+ struct fs_disk_quota * pdquota)
2773+{
2774+ int xid;
2775+ int rc = 0;
2776+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2777+ struct cifsTconInfo *pTcon;
2778+
2779+ if(cifs_sb)
2780+ pTcon = cifs_sb->tcon;
2781+ else
2782+ return -EIO;
2783+
2784+ xid = GetXid();
2785+ if(pTcon) {
2786+ cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
2787+ } else {
2788+ rc = -EIO;
2789+ }
2790+
2791+ FreeXid(xid);
2792+ return rc;
2793+}
2794+
2795+int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
2796+{
2797+ int xid;
2798+ int rc = 0;
2799+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2800+ struct cifsTconInfo *pTcon;
2801+
2802+ if(cifs_sb)
2803+ pTcon = cifs_sb->tcon;
2804+ else
2805+ return -EIO;
2806+
2807+ xid = GetXid();
2808+ if(pTcon) {
2809+ cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
2810+ } else {
2811+ rc = -EIO;
2812+ }
2813+
2814+ FreeXid(xid);
2815+ return rc;
2816+}
2817+
2818+int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
2819+{
2820+ int xid;
2821+ int rc = 0;
2822+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2823+ struct cifsTconInfo *pTcon;
2824+
2825+ if(cifs_sb) {
2826+ pTcon = cifs_sb->tcon;
2827+ } else {
2828+ return -EIO;
2829+ }
2830+ xid = GetXid();
2831+ if(pTcon) {
2832+ cFYI(1,("pqstats %p",qstats));
2833+ } else {
2834+ rc = -EIO;
2835+ }
2836+
2837+ FreeXid(xid);
2838+ return rc;
2839+}
2840+
2841+static struct quotactl_ops cifs_quotactl_ops = {
2842+ .set_xquota = cifs_xquota_set,
2843+ .get_xquota = cifs_xquota_set,
2844+ .set_xstate = cifs_xstate_set,
2845+ .get_xstate = cifs_xstate_get,
2846+};
2847+#endif
2848+
2849+static int cifs_remount(struct super_block *sb, int *flags, char *data)
2850+{
2851+ *flags |= MS_NODIRATIME;
2852+ return 0;
2853+}
2854+
2855+struct super_operations cifs_super_ops = {
2856+ .read_inode = cifs_read_inode,
2857+ .put_super = cifs_put_super,
2858+ .statfs = cifs_statfs,
2859+/* .alloc_inode = cifs_alloc_inode,
2860+ .destroy_inode = cifs_destroy_inode, */
2861+/* .drop_inode = generic_delete_inode,
2862+ .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
2863+ unless later we add lazy close of inodes or unless the kernel forgets to call
2864+ us with the same number of releases (closes) as opens */
2865+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2866+ .show_options = cifs_show_options,
2867+#endif
2868+/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
2869+};
2870+
2871+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2872+static struct super_block *
2873+cifs_get_sb(struct file_system_type *fs_type,
2874+ int flags, const char *dev_name, void *data)
2875+{
2876+ int rc;
2877+ struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
2878+
2879+ cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
2880+
2881+ if (IS_ERR(sb))
2882+ return sb;
2883+
2884+ sb->s_flags = flags;
2885+
2886+ rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
2887+ if (rc) {
2888+ up_write(&sb->s_umount);
2889+ deactivate_super(sb);
2890+ return ERR_PTR(rc);
2891+ }
2892+ sb->s_flags |= MS_ACTIVE;
2893+ return sb;
2894+}
2895+#endif
2896+
2897+static ssize_t
2898+cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
2899+ loff_t * poffset)
2900+{
2901+ if(file == NULL)
2902+ return -EIO;
2903+ else if(file->f_dentry == NULL)
2904+ return -EIO;
2905+ else if(file->f_dentry->d_inode == NULL)
2906+ return -EIO;
2907+
2908+ if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
2909+ return generic_file_read(file,read_data,read_size,poffset);
2910+ } else {
2911+ /* BB do we need to lock inode from here until after invalidate? */
2912+/* if(file->f_dentry->d_inode->i_mapping) {
2913+ filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
2914+ filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
2915+ }*/
2916+/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
2917+
2918+ /* BB we should make timer configurable - perhaps
2919+ by simply calling cifs_revalidate here */
2920+ /* invalidate_remote_inode(file->f_dentry->d_inode);*/
2921+ return generic_file_read(file,read_data,read_size,poffset);
2922+ }
2923+}
2924+
2925+static ssize_t
2926+cifs_write_wrapper(struct file * file, const char *write_data,
2927+ size_t write_size, loff_t * poffset)
2928+{
2929+ ssize_t written;
2930+
2931+ if(file == NULL)
2932+ return -EIO;
2933+ else if(file->f_dentry == NULL)
2934+ return -EIO;
2935+ else if(file->f_dentry->d_inode == NULL)
2936+ return -EIO;
2937+
2938+ /* check whether we can cache writes locally */
2939+ written = generic_file_write(file,write_data,write_size,poffset);
2940+ if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
2941+ if(file->f_dentry->d_inode->i_mapping) {
2942+ filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
2943+ }
2944+ }
2945+ return written;
2946+}
2947+
2948+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2949+static struct file_system_type cifs_fs_type = {
2950+ .owner = THIS_MODULE,
2951+ .name = "cifs",
2952+ .get_sb = cifs_get_sb,
2953+ .kill_sb = kill_anon_super,
2954+ /* .fs_flags */
2955+};
2956+#endif
2957+
2958+static DECLARE_FSTYPE(cifs_fs_type, "cifs", cifs_read_super,0);
2959+
2960+
2961+struct inode_operations cifs_dir_inode_ops = {
2962+ .create = cifs_create,
2963+ .lookup = cifs_lookup,
2964+ .unlink = cifs_unlink,
2965+ .link = cifs_hardlink,
2966+ .mkdir = cifs_mkdir,
2967+ .rmdir = cifs_rmdir,
2968+ .rename = cifs_rename,
2969+ .permission = cifs_permission,
2970+ .revalidate = cifs_revalidate,
2971+ .setattr = cifs_setattr,
2972+ .symlink = cifs_symlink,
2973+ .mknod = cifs_mknod,
2974+};
2975+
2976+struct inode_operations cifs_file_inode_ops = {
2977+ .revalidate = cifs_revalidate,
2978+ .setattr = cifs_setattr,
2979+/* .getattr = cifs_getattr,*/
2980+ .rename = cifs_rename,
2981+ .permission = cifs_permission,
2982+#ifdef CONFIG_CIFS_XATTR
2983+ .setxattr = cifs_setxattr,
2984+ .getxattr = cifs_getxattr,
2985+ .listxattr = cifs_listxattr,
2986+ .removexattr = cifs_removexattr,
2987+#endif
2988+};
2989+
2990+struct inode_operations cifs_symlink_inode_ops = {
2991+ .readlink = cifs_readlink,
2992+ .follow_link = cifs_follow_link,
2993+ .permission = cifs_permission,
2994+ /* BB add the following two eventually */
2995+ /* revalidate: cifs_revalidate,
2996+ setattr: cifs_notify_change, *//* BB do we need notify change */
2997+#ifdef CONFIG_CIFS_XATTR
2998+ .setxattr = cifs_setxattr,
2999+ .getxattr = cifs_getxattr,
3000+ .listxattr = cifs_listxattr,
3001+ .removexattr = cifs_removexattr,
3002+#endif
3003+};
3004+
3005+struct file_operations cifs_file_ops = {
3006+ .read = cifs_read_wrapper,
3007+ .write = cifs_write_wrapper,
3008+ .open = cifs_open,
3009+ .release = cifs_close,
3010+ .lock = cifs_lock,
3011+ .fsync = cifs_fsync,
3012+ .flush = cifs_flush,
3013+ .mmap = cifs_file_mmap,
3014+/* .sendfile = generic_file_sendfile,*/
3015+#ifdef CONFIG_CIFS_FCNTL
3016+ .fcntl = cifs_fcntl,
3017+#endif
3018+};
3019+
3020+struct file_operations cifs_dir_ops = {
3021+ .readdir = cifs_readdir,
3022+ .release = cifs_closedir,
3023+ .read = generic_read_dir,
3024+#ifdef CONFIG_CIFS_FCNTL
3025+ .fcntl = cifs_fcntl,
3026+#endif
3027+};
3028+/*
3029+static void
3030+cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
3031+{
3032+ struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
3033+
3034+ if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
3035+ SLAB_CTOR_CONSTRUCTOR) {
3036+ inode_init_once(&cifsi->vfs_inode);
3037+ INIT_LIST_HEAD(&cifsi->lockList);
3038+ }
3039+}
3040+
3041+static int
3042+cifs_init_inodecache(void)
3043+{
3044+ cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
3045+ sizeof (struct cifsInodeInfo),
3046+ 0, SLAB_HWCACHE_ALIGN,
3047+ cifs_init_once, NULL);
3048+ if (cifs_inode_cachep == NULL)
3049+ return -ENOMEM;
3050+
3051+
3052+ return 0;
3053+}
3054+
3055+static void
3056+cifs_destroy_inodecache(void)
3057+{
3058+ if (kmem_cache_destroy(cifs_inode_cachep))
3059+ printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
3060+} */
3061+
3062+static int
3063+cifs_init_request_bufs(void)
3064+{
3065+ cifs_req_cachep = kmem_cache_create("cifs_request",
3066+ CIFS_MAX_MSGSIZE +
3067+ MAX_CIFS_HDR_SIZE, 0,
3068+ SLAB_HWCACHE_ALIGN, NULL, NULL);
3069+ if (cifs_req_cachep == NULL)
3070+ return -ENOMEM;
3071+
3072+ return 0;
3073+}
3074+
3075+static void
3076+cifs_destroy_request_bufs(void)
3077+{
3078+ if (kmem_cache_destroy(cifs_req_cachep))
3079+ printk(KERN_WARNING
3080+ "cifs_destroy_request_cache: error not all structures were freed\n");
3081+}
3082+
3083+static int
3084+cifs_init_mids(void)
3085+{
3086+ cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
3087+ sizeof (struct mid_q_entry), 0,
3088+ SLAB_HWCACHE_ALIGN, NULL, NULL);
3089+ if (cifs_mid_cachep == NULL)
3090+ return -ENOMEM;
3091+ cifs_oplock_cachep = kmem_cache_create("cifs_oplock_struct",
3092+ sizeof (struct oplock_q_entry), 0,
3093+ SLAB_HWCACHE_ALIGN, NULL, NULL);
3094+ if (cifs_oplock_cachep == NULL) {
3095+ kmem_cache_destroy(cifs_mid_cachep);
3096+ return -ENOMEM;
3097+ }
3098+
3099+ return 0;
3100+}
3101+
3102+static void
3103+cifs_destroy_mids(void)
3104+{
3105+ if (kmem_cache_destroy(cifs_mid_cachep))
3106+ printk(KERN_WARNING
3107+ "cifs_destroy_mids: error not all structures were freed\n");
3108+ if (kmem_cache_destroy(cifs_oplock_cachep))
3109+ printk(KERN_WARNING
3110+ "error not all oplock structures were freed\n");
3111+}
3112+
3113+static int cifs_oplock_thread(void * dummyarg)
3114+{
3115+ struct oplock_q_entry * oplock_item;
3116+ struct cifsTconInfo *pTcon;
3117+ struct inode * inode;
3118+ __u16 netfid;
3119+ int rc = 0;
3120+
3121+ daemonize();
3122+ sprintf(current->comm,"cifsoplockd");
3123+
3124+ oplockThread = current;
3125+ do {
3126+ set_current_state(TASK_INTERRUPTIBLE);
3127+
3128+ schedule_timeout(1*HZ);
3129+ spin_lock(&GlobalMid_Lock);
3130+ if(list_empty(&GlobalOplock_Q)) {
3131+ spin_unlock(&GlobalMid_Lock);
3132+ set_current_state(TASK_INTERRUPTIBLE);
3133+ schedule_timeout(39*HZ);
3134+ } else {
3135+ oplock_item = list_entry(GlobalOplock_Q.next,
3136+ struct oplock_q_entry, qhead);
3137+ if(oplock_item) {
3138+ cFYI(1,("found oplock item to write out"));
3139+ pTcon = oplock_item->tcon;
3140+ inode = oplock_item->pinode;
3141+ netfid = oplock_item->netfid;
3142+ spin_unlock(&GlobalMid_Lock);
3143+ DeleteOplockQEntry(oplock_item);
3144+ /* can not grab inode sem here since it would
3145+ deadlock when oplock received on delete
3146+ since vfs_unlink holds the i_sem across
3147+ the call */
3148+ /* down(&inode->i_sem);*/
3149+ if (S_ISREG(inode->i_mode)) {
3150+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
3151+ rc = filemap_fdatasync(inode->i_mapping);
3152+ if(rc)
3153+ CIFS_I(inode)->write_behind_rc = rc;
3154+#else
3155+ filemap_fdatasync(inode->i_mapping);
3156+#endif
3157+ if(CIFS_I(inode)->clientCanCacheRead == 0)
3158+ invalidate_inode_pages(inode);
3159+ } else
3160+ rc = 0;
3161+ /* releasing a stale oplock after recent reconnection
3162+ of smb session using a now incorrect file
3163+ handle is not a data integrity issue but do
3164+ not bother sending an oplock release if session
3165+ to server still is disconnected since oplock
3166+ already released by the server in that case */
3167+ if(pTcon->tidStatus != CifsNeedReconnect) {
3168+ rc = CIFSSMBLock(0, pTcon,
3169+ netfid,
3170+ 0 /* len */ , 0 /* offset */, 0,
3171+ 0, LOCKING_ANDX_OPLOCK_RELEASE,
3172+ 0 /* wait flag */);
3173+ cFYI(1,("Oplock release rc = %d ",rc));
3174+ }
3175+ } else
3176+ spin_unlock(&GlobalMid_Lock);
3177+ }
3178+ } while(!signal_pending(current));
3179+ complete_and_exit (&cifs_oplock_exited, 0);
3180+}
3181+
3182+static int __init
3183+init_cifs(void)
3184+{
3185+ int rc = 0;
3186+#if CONFIG_PROC_FS
3187+ cifs_proc_init();
3188+#endif
3189+ INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
3190+ INIT_LIST_HEAD(&GlobalSMBSessionList);
3191+ INIT_LIST_HEAD(&GlobalTreeConnectionList);
3192+ INIT_LIST_HEAD(&GlobalOplock_Q);
3193+/*
3194+ * Initialize Global counters
3195+ */
3196+ atomic_set(&sesInfoAllocCount, 0);
3197+ atomic_set(&tconInfoAllocCount, 0);
3198+ atomic_set(&tcpSesReconnectCount, 0);
3199+ atomic_set(&tconInfoReconnectCount, 0);
3200+
3201+ atomic_set(&bufAllocCount, 0);
3202+ atomic_set(&midCount, 0);
3203+ GlobalCurrentXid = 0;
3204+ GlobalTotalActiveXid = 0;
3205+ GlobalMaxActiveXid = 0;
3206+ GlobalSMBSeslock = RW_LOCK_UNLOCKED;
3207+ GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
3208+
3209+/* rc = cifs_init_inodecache();*/
3210+ if (!rc) {
3211+ rc = cifs_init_mids();
3212+ if (!rc) {
3213+ rc = cifs_init_request_bufs();
3214+ if (!rc) {
3215+ rc = register_filesystem(&cifs_fs_type);
3216+ if (!rc) {
3217+ kernel_thread(cifs_oplock_thread, NULL,
3218+ CLONE_FS | CLONE_FILES | CLONE_VM);
3219+ return rc; /* Success */
3220+ } else
3221+ cifs_destroy_request_bufs();
3222+ }
3223+ cifs_destroy_mids();
3224+ }
3225+/* cifs_destroy_inodecache(); */
3226+ }
3227+#if CONFIG_PROC_FS
3228+ cifs_proc_clean();
3229+#endif
3230+ return rc;
3231+}
3232+
3233+static void __exit
3234+exit_cifs(void)
3235+{
3236+ cFYI(0, ("In unregister ie exit_cifs"));
3237+#if CONFIG_PROC_FS
3238+ cifs_proc_clean();
3239+#endif
3240+ unregister_filesystem(&cifs_fs_type);
3241+/* cifs_destroy_inodecache();*/
3242+ cifs_destroy_mids();
3243+ cifs_destroy_request_bufs();
3244+ if(oplockThread) {
3245+ send_sig(SIGTERM, oplockThread, 1);
3246+ wait_for_completion(&cifs_oplock_exited);
3247+ }
3248+}
3249+
3250+MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
3251+MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
3252+MODULE_DESCRIPTION
3253+ ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
3254+module_init(init_cifs)
3255+module_exit(exit_cifs)
3256--- /dev/null
3257+++ b/fs/cifs/cifsfs.h
3258@@ -0,0 +1,97 @@
3259+/*
3260+ * fs/cifs/cifsfs.h
3261+ *
3262+ * Copyright (c) International Business Machines Corp., 2002
3263+ * Author(s): Steve French (sfrench@us.ibm.com)
3264+ *
3265+ * This library is free software; you can redistribute it and/or modify
3266+ * it under the terms of the GNU Lesser General Public License as published
3267+ * by the Free Software Foundation; either version 2.1 of the License, or
3268+ * (at your option) any later version.
3269+ *
3270+ * This library is distributed in the hope that it will be useful,
3271+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3272+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3273+ * the GNU Lesser General Public License for more details.
3274+ *
3275+ * You should have received a copy of the GNU Lesser General Public License
3276+ * along with this library; if not, write to the Free Software
3277+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3278+ */
3279+
3280+#ifndef _CIFSFS_H
3281+#define _CIFSFS_H
3282+
3283+#define ROOT_I 2
3284+
3285+#ifndef FALSE
3286+#define FALSE 0
3287+#endif
3288+
3289+#ifndef TRUE
3290+#define TRUE 1
3291+#endif
3292+
3293+extern int map_cifs_error(int error_class, int error_code,
3294+ int status_codes_negotiated);
3295+
3296+extern struct address_space_operations cifs_addr_ops;
3297+
3298+/* Functions related to super block operations */
3299+extern struct super_operations cifs_super_ops;
3300+extern void cifs_put_inode(struct inode *);
3301+extern void cifs_read_inode(struct inode *);
3302+extern void cifs_delete_inode(struct inode *);
3303+/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
3304+
3305+/* Functions related to inodes */
3306+extern struct inode_operations cifs_dir_inode_ops;
3307+extern int cifs_create(struct inode *, struct dentry *, int);
3308+extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
3309+extern int cifs_unlink(struct inode *, struct dentry *);
3310+extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
3311+extern int cifs_mknod(struct inode *, struct dentry *, int, int);
3312+extern int cifs_mkdir(struct inode *, struct dentry *, int);
3313+extern int cifs_rmdir(struct inode *, struct dentry *);
3314+extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
3315+ struct dentry *);
3316+extern int cifs_revalidate(struct dentry *);
3317+extern int cifs_setattr(struct dentry *, struct iattr *);
3318+
3319+extern struct inode_operations cifs_file_inode_ops;
3320+extern void cifs_truncate_file(struct inode *);
3321+extern struct inode_operations cifs_symlink_inode_ops;
3322+
3323+/* Functions related to files and directories */
3324+extern struct file_operations cifs_file_ops;
3325+extern int cifs_open(struct inode *inode, struct file *file);
3326+extern int cifs_close(struct inode *inode, struct file *file);
3327+extern int cifs_closedir(struct inode *inode, struct file *file);
3328+extern ssize_t cifs_read(struct file *file, char *read_data,
3329+ size_t read_size, loff_t * poffset);
3330+extern ssize_t cifs_write(struct file *file, const char *write_data,
3331+ size_t write_size, loff_t * poffset);
3332+extern int cifs_lock(struct file *, int, struct file_lock *);
3333+extern int cifs_fsync(struct file *, struct dentry *, int);
3334+extern int cifs_flush(struct file *);
3335+extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
3336+extern struct file_operations cifs_dir_ops;
3337+extern int cifs_dir_open(struct inode *inode, struct file *file);
3338+extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
3339+extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *);
3340+
3341+/* Functions related to dir entries */
3342+extern struct dentry_operations cifs_dentry_ops;
3343+
3344+/* Functions related to symlinks */
3345+extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
3346+extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
3347+extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
3348+ const char *symname);
3349+extern int cifs_removexattr(struct dentry *, const char *);
3350+extern int cifs_setxattr(struct dentry *, const char *, const void *,
3351+ size_t, int);
3352+extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
3353+extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
3354+#define CIFS_VERSION "1.20"
3355+#endif /* _CIFSFS_H */
3356--- /dev/null
3357+++ b/fs/cifs/cifs_fs_sb.h
3358@@ -0,0 +1,32 @@
3359+/*
3360+ * fs/cifs/cifs_fs_sb.h
3361+ *
3362+ * Copyright (c) International Business Machines Corp., 2002
3363+ * Author(s): Steve French (sfrench@us.ibm.com)
3364+ *
3365+ * This library is free software; you can redistribute it and/or modify
3366+ * it under the terms of the GNU Lesser General Public License as published
3367+ * by the Free Software Foundation; either version 2.1 of the License, or
3368+ * (at your option) any later version.
3369+ *
3370+ * This library is distributed in the hope that it will be useful,
3371+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3372+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3373+ * the GNU Lesser General Public License for more details.
3374+ *
3375+ */
3376+#ifndef _CIFS_FS_SB_H
3377+#define _CIFS_FS_SB_H
3378+
3379+struct cifs_sb_info {
3380+ struct cifsTconInfo *tcon; /* primary mount */
3381+ struct list_head nested_tcon_q;
3382+ struct nls_table *local_nls;
3383+ unsigned int rsize;
3384+ unsigned int wsize;
3385+ uid_t mnt_uid;
3386+ gid_t mnt_gid;
3387+ mode_t mnt_file_mode;
3388+ mode_t mnt_dir_mode;
3389+};
3390+#endif /* _CIFS_FS_SB_H */
3391--- /dev/null
3392+++ b/fs/cifs/cifsglob.h
3393@@ -0,0 +1,413 @@
3394+/*
3395+ * fs/cifs/cifsglob.h
3396+ *
3397+ * Copyright (C) International Business Machines Corp., 2002,2003
3398+ * Author(s): Steve French (sfrench@us.ibm.com)
3399+ *
3400+ * This library is free software; you can redistribute it and/or modify
3401+ * it under the terms of the GNU Lesser General Public License as published
3402+ * by the Free Software Foundation; either version 2.1 of the License, or
3403+ * (at your option) any later version.
3404+ *
3405+ * This library is distributed in the hope that it will be useful,
3406+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3407+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3408+ * the GNU Lesser General Public License for more details.
3409+ *
3410+ */
3411+#include <linux/in.h>
3412+#include <linux/in6.h>
3413+#include "cifs_fs_sb.h"
3414+/*
3415+ * The sizes of various internal tables and strings
3416+ */
3417+#define MAX_UID_INFO 16
3418+#define MAX_SES_INFO 2
3419+#define MAX_TCON_INFO 4
3420+
3421+#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
3422+#define MAX_SERVER_SIZE 15
3423+#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
3424+#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
3425+ termination then *2 for unicode versions */
3426+#define MAX_PASSWORD_SIZE 16
3427+
3428+/*
3429+ * MAX_REQ is the maximum number of requests that WE will send
3430+ * on one socket concurently. It also matches the most common
3431+ * value of max multiplex returned by servers. We may
3432+ * eventually want to use the negotiated value (in case
3433+ * future servers can handle more) when we are more confident that
3434+ * we will not have problems oveloading the socket with pending
3435+ * write data.
3436+ */
3437+#define CIFS_MAX_REQ 50
3438+
3439+#define SERVER_NAME_LENGTH 15
3440+#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
3441+
3442+/* used to define string lengths for reversing unicode strings */
3443+/* (256+1)*2 = 514 */
3444+/* (max path length + 1 for null) * 2 for unicode */
3445+#define MAX_NAME 514
3446+
3447+#include "cifspdu.h"
3448+
3449+#ifndef FALSE
3450+#define FALSE 0
3451+#endif
3452+
3453+#ifndef TRUE
3454+#define TRUE 1
3455+#endif
3456+
3457+#ifndef XATTR_DOS_ATTRIB
3458+#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
3459+#endif
3460+
3461+/*
3462+ * This information is kept on every Server we know about.
3463+ *
3464+ * Some things to note:
3465+ *
3466+ */
3467+#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
3468+
3469+/*
3470+ * CIFS vfs client Status information (based on what we know.)
3471+ */
3472+
3473+ /* associated with each tcp and smb session */
3474+enum statusEnum {
3475+ CifsNew = 0,
3476+ CifsGood,
3477+ CifsExiting,
3478+ CifsNeedReconnect
3479+};
3480+
3481+enum securityEnum {
3482+ NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
3483+ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
3484+ RawNTLMSSP, /* NTLMSSP without SPNEGO */
3485+ NTLMSSP, /* NTLMSSP via SPNEGO */
3486+ Kerberos /* Kerberos via SPNEGO */
3487+};
3488+
3489+enum protocolEnum {
3490+ IPV4 = 0,
3491+ IPV6,
3492+ SCTP
3493+ /* Netbios frames protocol not supported at this time */
3494+};
3495+
3496+/*
3497+ *****************************************************************
3498+ * Except the CIFS PDUs themselves all the
3499+ * globally interesting structs should go here
3500+ *****************************************************************
3501+ */
3502+
3503+struct TCP_Server_Info {
3504+ char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
3505+ char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
3506+ struct socket *ssocket;
3507+ union {
3508+ struct sockaddr_in sockAddr;
3509+ struct sockaddr_in6 sockAddr6;
3510+ } addr;
3511+ wait_queue_head_t response_q;
3512+ wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
3513+ struct list_head pending_mid_q;
3514+ void *Server_NlsInfo; /* BB - placeholder for future NLS info */
3515+ unsigned short server_codepage; /* codepage for the server */
3516+ unsigned long ip_address; /* IP addr for the server if known */
3517+ enum protocolEnum protocolType;
3518+ char versionMajor;
3519+ char versionMinor;
3520+ int svlocal:1; /* local server or remote */
3521+ atomic_t socketUseCount; /* number of open cifs sessions on socket */
3522+ atomic_t inFlight; /* number of requests on the wire to server */
3523+ enum statusEnum tcpStatus; /* what we think the status is */
3524+ struct semaphore tcpSem;
3525+ struct task_struct *tsk;
3526+ char server_GUID[16];
3527+ char secMode;
3528+ enum securityEnum secType;
3529+ unsigned int maxReq; /* Clients should submit no more */
3530+ /* than maxReq distinct unanswered SMBs to the server when using */
3531+ /* multiplexed reads or writes */
3532+ unsigned int maxBuf; /* maxBuf specifies the maximum */
3533+ /* message size the server can send or receive for non-raw SMBs */
3534+ unsigned int maxRw; /* maxRw specifies the maximum */
3535+ /* message size the server can send or receive for */
3536+ /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
3537+ char sessid[4]; /* unique token id for this session */
3538+ /* (returned on Negotiate */
3539+ int capabilities; /* allow selective disabling of caps by smb sess */
3540+ __u16 timeZone;
3541+ char cryptKey[CIFS_CRYPTO_KEY_SIZE];
3542+ char workstation_RFC1001_name[16]; /* 16th byte is always zero */
3543+};
3544+
3545+/*
3546+ * The following is our shortcut to user information. We surface the uid,
3547+ * and name. We always get the password on the fly in case it
3548+ * has changed. We also hang a list of sessions owned by this user off here.
3549+ */
3550+struct cifsUidInfo {
3551+ struct list_head userList;
3552+ struct list_head sessionList; /* SMB sessions for this user */
3553+ uid_t linux_uid;
3554+ char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
3555+ /* BB may need ptr or callback for PAM or WinBind info */
3556+};
3557+
3558+/*
3559+ * Session structure. One of these for each uid session with a particular host
3560+ */
3561+struct cifsSesInfo {
3562+ struct list_head cifsSessionList;
3563+ struct semaphore sesSem;
3564+ struct cifsUidInfo *uidInfo; /* pointer to user info */
3565+ struct TCP_Server_Info *server; /* pointer to server info */
3566+ atomic_t inUse; /* # of mounts (tree connections) on this ses */
3567+ enum statusEnum status;
3568+ __u32 sequence_number; /* needed for CIFS PDU signature */
3569+ __u16 ipc_tid; /* special tid for connection to IPC share */
3570+ char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
3571+ char *serverOS; /* name of operating system underlying the server */
3572+ char *serverNOS; /* name of network operating system that the server is running */
3573+ char *serverDomain; /* security realm of server */
3574+ int Suid; /* remote smb uid */
3575+ uid_t linux_uid; /* local Linux uid */
3576+ int capabilities;
3577+ char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
3578+ char userName[MAX_USERNAME_SIZE + 1];
3579+ char domainName[MAX_USERNAME_SIZE + 1];
3580+ char * password;
3581+};
3582+
3583+/*
3584+ * there is one of these for each connection to a resource on a particular
3585+ * session
3586+ */
3587+struct cifsTconInfo {
3588+ struct list_head cifsConnectionList;
3589+ struct list_head openFileList;
3590+ struct semaphore tconSem;
3591+ struct cifsSesInfo *ses; /* pointer to session associated with */
3592+ char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
3593+ char *nativeFileSystem;
3594+ __u16 tid; /* The 2 byte tree id */
3595+ __u16 Flags; /* optional support bits */
3596+ enum statusEnum tidStatus;
3597+ atomic_t useCount; /* how many mounts (explicit or implicit) to this share */
3598+#ifdef CONFIG_CIFS_STATS
3599+ atomic_t num_smbs_sent;
3600+ atomic_t num_writes;
3601+ atomic_t num_reads;
3602+ atomic_t num_oplock_brks;
3603+ atomic_t num_opens;
3604+ atomic_t num_deletes;
3605+ atomic_t num_mkdirs;
3606+ atomic_t num_rmdirs;
3607+ atomic_t num_renames;
3608+ atomic_t num_t2renames;
3609+ __u64 bytes_read;
3610+ __u64 bytes_written;
3611+ spinlock_t stat_lock;
3612+#endif
3613+ FILE_SYSTEM_DEVICE_INFO fsDevInfo;
3614+ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
3615+ FILE_SYSTEM_UNIX_INFO fsUnixInfo;
3616+ int retry:1;
3617+ /* BB add field for back pointer to sb struct? */
3618+};
3619+
3620+/*
3621+ * This info hangs off the cifsFileInfo structure. This is used to track
3622+ * byte stream locks on the file
3623+ */
3624+struct cifsLockInfo {
3625+ struct cifsLockInfo *next;
3626+ int start;
3627+ int length;
3628+ int type;
3629+};
3630+
3631+/*
3632+ * One of these for each open instance of a file
3633+ */
3634+struct cifsFileInfo {
3635+ struct list_head tlist; /* pointer to next fid owned by tcon */
3636+ struct list_head flist; /* next fid (file instance) for this inode */
3637+ unsigned int uid; /* allows finding which FileInfo structure */
3638+ __u32 pid; /* process id who opened file */
3639+ __u16 netfid; /* file id from remote */
3640+ /* BB add lock scope info here if needed */ ;
3641+ /* lock scope id (0 if none) */
3642+ struct file * pfile; /* needed for writepage */
3643+ struct inode * pInode; /* needed for oplock break */
3644+ int endOfSearch:1; /* we have reached end of search */
3645+ int closePend:1; /* file is marked to close */
3646+ int emptyDir:1;
3647+ int invalidHandle:1; /* file closed via session abend */
3648+ struct semaphore fh_sem; /* prevents reopen race after dead ses*/
3649+ char * search_resume_name;
3650+ unsigned int resume_name_length;
3651+ __u32 resume_key;
3652+};
3653+
3654+/*
3655+ * One of these for each file inode
3656+ */
3657+
3658+struct cifsInodeInfo {
3659+ struct list_head lockList;
3660+ /* BB add in lists for dirty pages - i.e. write caching info for oplock */
3661+ struct list_head openFileList;
3662+ int write_behind_rc;
3663+ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
3664+ atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
3665+ unsigned long time; /* jiffies of last update/check of inode */
3666+ int clientCanCacheRead:1; /* read oplock */
3667+ int clientCanCacheAll:1; /* read and writebehind oplock */
3668+ int oplockPending:1;
3669+ struct inode vfs_inode;
3670+};
3671+
3672+static inline struct cifsInodeInfo * CIFS_I(struct inode *inode)
3673+{
3674+ return (struct cifsInodeInfo *)&(inode->u);
3675+}
3676+
3677+static inline struct cifs_sb_info * CIFS_SB(struct super_block *sb)
3678+{
3679+ return (struct cifs_sb_info *) &(sb->u);
3680+}
3681+
3682+
3683+/* one of these for every pending CIFS request to the server */
3684+struct mid_q_entry {
3685+ struct list_head qhead; /* mids waiting on reply from this server */
3686+ __u16 mid; /* multiplex id */
3687+ __u16 pid; /* process id */
3688+ __u32 sequence_number; /* for CIFS signing */
3689+ __u16 command; /* smb command code */
3690+ struct timeval when_sent; /* time when smb sent */
3691+ struct cifsSesInfo *ses; /* smb was sent to this server */
3692+ struct task_struct *tsk; /* task waiting for response */
3693+ struct smb_hdr *resp_buf; /* response buffer */
3694+ int midState; /* wish this were enum but can not pass to wait_event */
3695+};
3696+
3697+struct oplock_q_entry {
3698+ struct list_head qhead;
3699+ struct inode * pinode;
3700+ struct cifsTconInfo * tcon;
3701+ __u16 netfid;
3702+};
3703+
3704+#define MID_FREE 0
3705+#define MID_REQUEST_ALLOCATED 1
3706+#define MID_REQUEST_SUBMITTED 2
3707+#define MID_RESPONSE_RECEIVED 4
3708+#define MID_RETRY_NEEDED 8 /* session closed while this request out */
3709+
3710+/*
3711+ *****************************************************************
3712+ * All constants go here
3713+ *****************************************************************
3714+ */
3715+
3716+#define UID_HASH (16)
3717+
3718+/*
3719+ * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
3720+ * following to be declared.
3721+ */
3722+
3723+/****************************************************************************
3724+ * Locking notes. All updates to global variables and lists should be
3725+ * protected by spinlocks or semaphores.
3726+ *
3727+ * Spinlocks
3728+ * ---------
3729+ * GlobalMid_Lock protects:
3730+ * list operations on pending_mid_q and oplockQ
3731+ * updates to XID counters, multiplex id and SMB sequence numbers
3732+ * GlobalSMBSesLock protects:
3733+ * list operations on tcp and SMB session lists and tCon lists
3734+ * f_owner.lock protects certain per file struct operations
3735+ * mapping->page_lock protects certain per page operations
3736+ *
3737+ * Semaphores
3738+ * ----------
3739+ * sesSem operations on smb session
3740+ * tconSem operations on tree connection
3741+ * fh_sem file handle reconnection operations
3742+ *
3743+ ****************************************************************************/
3744+
3745+#ifdef DECLARE_GLOBALS_HERE
3746+#define GLOBAL_EXTERN
3747+#else
3748+#define GLOBAL_EXTERN extern
3749+#endif
3750+
3751+/*
3752+ * The list of servers that did not respond with NT LM 0.12.
3753+ * This list helps improve performance and eliminate the messages indicating
3754+ * that we had a communications error talking to the server in this list.
3755+ */
3756+GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
3757+
3758+/*
3759+ * The following is a hash table of all the users we know about.
3760+ */
3761+GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
3762+
3763+GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
3764+GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
3765+GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
3766+GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
3767+
3768+GLOBAL_EXTERN struct list_head GlobalOplock_Q;
3769+
3770+/*
3771+ * Global transaction id (XID) information
3772+ */
3773+GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
3774+GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
3775+GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
3776+GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
3777+ /* on midQ entries */
3778+GLOBAL_EXTERN char Local_System_Name[15];
3779+
3780+/*
3781+ * Global counters, updated atomically
3782+ */
3783+GLOBAL_EXTERN atomic_t sesInfoAllocCount;
3784+GLOBAL_EXTERN atomic_t tconInfoAllocCount;
3785+
3786+GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
3787+GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
3788+
3789+/* Various Debug counters to remove someday (BB) */
3790+GLOBAL_EXTERN atomic_t bufAllocCount;
3791+GLOBAL_EXTERN atomic_t midCount;
3792+
3793+/* Misc globals */
3794+GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
3795+ to be established on existing mount if we
3796+ have the uid/password or Kerberos credential
3797+ or equivalent for current user */
3798+GLOBAL_EXTERN unsigned int oplockEnabled;
3799+GLOBAL_EXTERN unsigned int quotaEnabled;
3800+GLOBAL_EXTERN unsigned int lookupCacheEnabled;
3801+GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
3802+ with more secure ntlmssp2 challenge/resp */
3803+GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
3804+GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
3805+GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */
3806+
3807--- /dev/null
3808+++ b/fs/cifs/cifspdu.h
3809@@ -0,0 +1,1793 @@
3810+/*
3811+ * fs/cifs/cifspdu.h
3812+ *
3813+ * Copyright (c) International Business Machines Corp., 2002
3814+ * Author(s): Steve French (sfrench@us.ibm.com)
3815+ *
3816+ * This library is free software; you can redistribute it and/or modify
3817+ * it under the terms of the GNU Lesser General Public License as published
3818+ * by the Free Software Foundation; either version 2.1 of the License, or
3819+ * (at your option) any later version.
3820+ *
3821+ * This library is distributed in the hope that it will be useful,
3822+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3823+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3824+ * the GNU Lesser General Public License for more details.
3825+ *
3826+ * You should have received a copy of the GNU Lesser General Public License
3827+ * along with this library; if not, write to the Free Software
3828+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3829+ */
3830+
3831+#ifndef _CIFSPDU_H
3832+#define _CIFSPDU_H
3833+
3834+#include <net/sock.h>
3835+
3836+#define CIFS_PROT 0
3837+#define BAD_PROT CIFS_PROT+1
3838+
3839+/* SMB command codes */
3840+#define SMB_COM_CREATE_DIRECTORY 0x00
3841+#define SMB_COM_DELETE_DIRECTORY 0x01
3842+#define SMB_COM_CLOSE 0x04
3843+#define SMB_COM_DELETE 0x06
3844+#define SMB_COM_RENAME 0x07
3845+#define SMB_COM_LOCKING_ANDX 0x24
3846+#define SMB_COM_COPY 0x29
3847+#define SMB_COM_READ_ANDX 0x2E
3848+#define SMB_COM_WRITE_ANDX 0x2F
3849+#define SMB_COM_TRANSACTION2 0x32
3850+#define SMB_COM_TRANSACTION2_SECONDARY 0x33
3851+#define SMB_COM_FIND_CLOSE2 0x34
3852+#define SMB_COM_TREE_DISCONNECT 0x71
3853+#define SMB_COM_NEGOTIATE 0x72
3854+#define SMB_COM_SESSION_SETUP_ANDX 0x73
3855+#define SMB_COM_LOGOFF_ANDX 0x74
3856+#define SMB_COM_TREE_CONNECT_ANDX 0x75
3857+#define SMB_COM_NT_TRANSACT 0xA0
3858+#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
3859+#define SMB_COM_NT_CREATE_ANDX 0xA2
3860+#define SMB_COM_NT_RENAME 0xA5
3861+
3862+/* Transact2 subcommand codes */
3863+#define TRANS2_OPEN 0x00
3864+#define TRANS2_FIND_FIRST 0x01
3865+#define TRANS2_FIND_NEXT 0x02
3866+#define TRANS2_QUERY_FS_INFORMATION 0x03
3867+#define TRANS2_QUERY_PATH_INFORMATION 0x05
3868+#define TRANS2_SET_PATH_INFORMATION 0x06
3869+#define TRANS2_QUERY_FILE_INFORMATION 0x07
3870+#define TRANS2_SET_FILE_INFORMATION 0x08
3871+#define TRANS2_GET_DFS_REFERRAL 0x10
3872+#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
3873+
3874+/* NT Transact subcommand codes */
3875+#define NT_TRANSACT_CREATE 0x01
3876+#define NT_TRANSACT_IOCTL 0x02
3877+#define NT_TRANSACT_SET_SECURITY_DESC 0x03
3878+#define NT_TRANSACT_NOTIFY_CHANGE 0x04
3879+#define NT_TRANSACT_RENAME 0x05
3880+#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
3881+#define NT_TRANSACT_GET_USER_QUOTA 0x07
3882+#define NT_TRANSACT_SET_USER_QUOTA 0x08
3883+
3884+#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
3885+
3886+/* internal cifs vfs structures */
3887+/*****************************************************************
3888+ * All constants go here
3889+ *****************************************************************
3890+ */
3891+
3892+/*
3893+ * Starting value for maximum SMB size negotiation
3894+ */
3895+#define CIFS_MAX_MSGSIZE (4*4096)
3896+
3897+/*
3898+ * Size of encrypted user password in bytes
3899+ */
3900+#define CIFS_ENCPWD_SIZE (16)
3901+
3902+/*
3903+ * Size of the crypto key returned on the negotiate SMB in bytes
3904+ */
3905+#define CIFS_CRYPTO_KEY_SIZE (8)
3906+
3907+/*
3908+ * Size of the session key (crypto key encrypted with the password
3909+ */
3910+#define CIFS_SESSION_KEY_SIZE (24)
3911+
3912+/*
3913+ * Maximum user name length
3914+ */
3915+#define CIFS_UNLEN (20)
3916+
3917+/*
3918+ * Flags on SMB open
3919+ */
3920+#define SMBOPEN_WRITE_THROUGH 0x4000
3921+#define SMBOPEN_DENY_ALL 0x0010
3922+#define SMBOPEN_DENY_WRITE 0x0020
3923+#define SMBOPEN_DENY_READ 0x0030
3924+#define SMBOPEN_DENY_NONE 0x0040
3925+#define SMBOPEN_READ 0x0000
3926+#define SMBOPEN_WRITE 0x0001
3927+#define SMBOPEN_READWRITE 0x0002
3928+#define SMBOPEN_EXECUTE 0x0003
3929+
3930+#define SMBOPEN_OCREATE 0x0010
3931+#define SMBOPEN_OTRUNC 0x0002
3932+#define SMBOPEN_OAPPEND 0x0001
3933+
3934+/*
3935+ * SMB flag definitions
3936+ */
3937+#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
3938+#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
3939+#define SMBFLG_RSVD 0x04
3940+#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
3941+#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
3942+#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
3943+#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
3944+#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
3945+
3946+/*
3947+ * SMB flag2 definitions
3948+ */
3949+#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */
3950+#define SMBFLG2_KNOWS_EAS 0x0002
3951+#define SMBFLG2_SECURITY_SIGNATURE 0x0004
3952+#define SMBFLG2_IS_LONG_NAME 0x0040
3953+#define SMBFLG2_EXT_SEC 0x0800
3954+#define SMBFLG2_DFS 0x1000
3955+#define SMBFLG2_PAGING_IO 0x2000
3956+#define SMBFLG2_ERR_STATUS 0x4000
3957+#define SMBFLG2_UNICODE 0x8000
3958+
3959+/*
3960+ * These are the file access permission bits defined in CIFS for the
3961+ * NTCreateAndX as well as the level 0x107
3962+ * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
3963+ * responds with the AccessFlags.
3964+ * The AccessFlags specifies the access permissions a caller has to the
3965+ * file and can have any suitable combination of the following values:
3966+ */
3967+
3968+#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
3969+#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
3970+#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
3971+#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
3972+ /* with the file can be read */
3973+#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
3974+ /* with the file can be written */
3975+#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
3976+ /* the file using system paging I/O */
3977+#define FILE_DELETE_CHILD 0x00000040
3978+#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
3979+ /* file can be read */
3980+#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
3981+ /* file can be written */
3982+#define DELETE 0x00010000 /* The file can be deleted */
3983+#define READ_CONTROL 0x00020000 /* The access control list and */
3984+ /* ownership associated with the */
3985+ /* file can be read */
3986+#define WRITE_DAC 0x00040000 /* The access control list and */
3987+ /* ownership associated with the */
3988+ /* file can be written. */
3989+#define WRITE_OWNER 0x00080000 /* Ownership information associated */
3990+ /* with the file can be written */
3991+#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
3992+ /* synchronize with the completion */
3993+ /* of an input/output request */
3994+#define GENERIC_ALL 0x10000000
3995+#define GENERIC_EXECUTE 0x20000000
3996+#define GENERIC_WRITE 0x40000000
3997+#define GENERIC_READ 0x80000000
3998+ /* In summary - Relevant file */
3999+ /* access flags from CIFS are */
4000+ /* file_read_data, file_write_data */
4001+ /* file_execute, file_read_attributes */
4002+ /* write_dac, and delete. */
4003+
4004+/*
4005+ * Invalid readdir handle
4006+ */
4007+#define CIFS_NO_HANDLE 0xFFFF
4008+
4009+/* IPC$ in ASCII */
4010+#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
4011+
4012+/* IPC$ in Unicode */
4013+#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
4014+
4015+/* Unicode Null terminate 2 bytes of 0 */
4016+#define UNICODE_NULL "\x00\x00"
4017+#define ASCII_NULL 0x00
4018+
4019+/*
4020+ * Server type values (returned on EnumServer API
4021+ */
4022+#define CIFS_SV_TYPE_DC 0x00000008
4023+#define CIFS_SV_TYPE_BACKDC 0x00000010
4024+
4025+/*
4026+ * Alias type flags (From EnumAlias API call
4027+ */
4028+#define CIFS_ALIAS_TYPE_FILE 0x0001
4029+#define CIFS_SHARE_TYPE_FILE 0x0000
4030+
4031+/*
4032+ * File Attribute flags
4033+ */
4034+#define ATTR_READONLY 0x0001
4035+#define ATTR_HIDDEN 0x0002
4036+#define ATTR_SYSTEM 0x0004
4037+#define ATTR_VOLUME 0x0008
4038+#define ATTR_DIRECTORY 0x0010
4039+#define ATTR_ARCHIVE 0x0020
4040+#define ATTR_DEVICE 0x0040
4041+#define ATTR_NORMAL 0x0080
4042+#define ATTR_TEMPORARY 0x0100
4043+#define ATTR_SPARSE 0x0200
4044+#define ATTR_REPARSE 0x0400
4045+#define ATTR_COMPRESSED 0x0800
4046+#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
4047+#define ATTR_NOT_CONTENT_INDEXED 0x2000
4048+#define ATTR_ENCRYPTED 0x4000
4049+#define ATTR_POSIX_SEMANTICS 0x01000000
4050+#define ATTR_BACKUP_SEMANTICS 0x02000000
4051+#define ATTR_DELETE_ON_CLOSE 0x04000000
4052+#define ATTR_SEQUENTIAL_SCAN 0x08000000
4053+#define ATTR_RANDOM_ACCESS 0x10000000
4054+#define ATTR_NO_BUFFERING 0x20000000
4055+#define ATTR_WRITE_THROUGH 0x80000000
4056+
4057+/* ShareAccess flags */
4058+#define FILE_NO_SHARE 0x00000000
4059+#define FILE_SHARE_READ 0x00000001
4060+#define FILE_SHARE_WRITE 0x00000002
4061+#define FILE_SHARE_DELETE 0x00000004
4062+#define FILE_SHARE_ALL 0x00000007
4063+
4064+/* CreateDisposition flags */
4065+#define FILE_SUPERSEDE 0x00000000
4066+#define FILE_OPEN 0x00000001
4067+#define FILE_CREATE 0x00000002
4068+#define FILE_OPEN_IF 0x00000003
4069+#define FILE_OVERWRITE 0x00000004
4070+#define FILE_OVERWRITE_IF 0x00000005
4071+
4072+/* CreateOptions */
4073+#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
4074+#define CREATE_WRITE_THROUGH 0x00000002
4075+#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
4076+#define CREATE_RANDOM_ACCESS 0x00000800
4077+#define CREATE_DELETE_ON_CLOSE 0x00001000
4078+#define OPEN_REPARSE_POINT 0x00200000
4079+
4080+/* ImpersonationLevel flags */
4081+#define SECURITY_ANONYMOUS 0
4082+#define SECURITY_IDENTIFICATION 1
4083+#define SECURITY_IMPERSONATION 2
4084+#define SECURITY_DELEGATION 3
4085+
4086+/* SecurityFlags */
4087+#define SECURITY_CONTEXT_TRACKING 0x01
4088+#define SECURITY_EFFECTIVE_ONLY 0x02
4089+
4090+/*
4091+ * Default PID value, used in all SMBs where the PID is not important
4092+ */
4093+#define CIFS_DFT_PID 0x1234
4094+
4095+/*
4096+ * We use the same routine for Copy and Move SMBs. This flag is used to
4097+ * distinguish
4098+ */
4099+#define CIFS_COPY_OP 1
4100+#define CIFS_RENAME_OP 2
4101+
4102+#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
4103+#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
4104+
4105+#pragma pack(1)
4106+
4107+struct smb_hdr {
4108+ __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 */
4109+ __u8 Protocol[4];
4110+ __u8 Command;
4111+ union {
4112+ struct {
4113+ __u8 ErrorClass;
4114+ __u8 Reserved;
4115+ __u16 Error; /* note: treated as little endian (le) on wire */
4116+ } DosError;
4117+ __u32 CifsError; /* note: le */
4118+ } Status;
4119+ __u8 Flags;
4120+ __u16 Flags2; /* note: le */
4121+ __u16 PidHigh; /* note: le */
4122+ union {
4123+ struct {
4124+ __u32 SequenceNumber; /* le */
4125+ __u32 Reserved; /* zero */
4126+ } Sequence;
4127+ __u8 SecuritySignature[8]; /* le */
4128+ } Signature;
4129+ __u8 pad[2];
4130+ __u16 Tid;
4131+ __u16 Pid; /* note: le */
4132+ __u16 Uid;
4133+ __u16 Mid;
4134+ __u8 WordCount;
4135+};
4136+/* given a pointer to an smb_hdr retrieve the value of byte count */
4137+#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
4138+
4139+/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
4140+#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
4141+
4142+/*
4143+ * Computer Name Length
4144+ */
4145+#define CNLEN 15
4146+
4147+/*
4148+ * Share Name Length @S8A
4149+ * Note: This length is limited by the SMB used to get @S8A
4150+ * the Share info. NetShareEnum only returns 13 @S8A
4151+ * chars, including the null termination. @S8A
4152+ */
4153+#define SNLEN 12 /*@S8A */
4154+
4155+/*
4156+ * Comment Length
4157+ */
4158+#define MAXCOMMENTLEN 40
4159+
4160+/*
4161+ * The OS/2 maximum path name
4162+ */
4163+#define MAX_PATHCONF 256
4164+
4165+/*
4166+ * SMB frame definitions (following must be packed structs)
4167+ * See the SNIA CIFS Specification for details.
4168+ *
4169+ * The Naming convention is the lower case version of the
4170+ * smb command code name for the struct and this is typedef to the
4171+ * uppercase version of the same name with the prefix SMB_ removed
4172+ * for brevity. Although typedefs are not commonly used for
4173+ * structure definitions in the Linux kernel, their use in the
4174+ * CIFS standards document, which this code is based on, may
4175+ * make this one of the cases where typedefs for structures make
4176+ * sense to improve readability for readers of the standards doc.
4177+ * Typedefs can always be removed later if they are too distracting
4178+ * and they are only used for the CIFSs PDUs themselves, not
4179+ * internal cifs vfs structures
4180+ *
4181+ */
4182+
4183+typedef struct negotiate_req {
4184+ struct smb_hdr hdr; /* wct = 0 */
4185+ __u16 ByteCount;
4186+ unsigned char DialectsArray[1];
4187+} NEGOTIATE_REQ;
4188+
4189+typedef struct negotiate_rsp {
4190+ struct smb_hdr hdr; /* wct = 17 */
4191+ __u16 DialectIndex;
4192+ __u8 SecurityMode;
4193+ __u16 MaxMpxCount;
4194+ __u16 MaxNumberVcs;
4195+ __u32 MaxBufferSize;
4196+ __u32 MaxRawSize;
4197+ __u32 SessionKey;
4198+ __u32 Capabilities; /* see below */
4199+ __u32 SystemTimeLow;
4200+ __u32 SystemTimeHigh;
4201+ __u16 ServerTimeZone;
4202+ __u8 EncryptionKeyLength;
4203+ __u16 ByteCount;
4204+ union {
4205+ unsigned char EncryptionKey[1]; /* if cap extended security is off */
4206+ /* followed by Domain name - if extended security is off */
4207+ /* followed by 16 bytes of server GUID */
4208+ /* followed by security blob if cap_extended_security negotiated */
4209+ struct {
4210+ unsigned char GUID[16];
4211+ unsigned char SecurityBlob[1];
4212+ } extended_response;
4213+ } u;
4214+} NEGOTIATE_RSP;
4215+
4216+/* SecurityMode bits */
4217+#define SECMODE_USER 0x01 /* off indicates share level security */
4218+#define SECMODE_PW_ENCRYPT 0x02
4219+#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
4220+#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
4221+
4222+/* Negotiate response Capabilities */
4223+#define CAP_RAW_MODE 0x00000001
4224+#define CAP_MPX_MODE 0x00000002
4225+#define CAP_UNICODE 0x00000004
4226+#define CAP_LARGE_FILES 0x00000008
4227+#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
4228+#define CAP_RPC_REMOTE_APIS 0x00000020
4229+#define CAP_STATUS32 0x00000040
4230+#define CAP_LEVEL_II_OPLOCKS 0x00000080
4231+#define CAP_LOCK_AND_READ 0x00000100
4232+#define CAP_NT_FIND 0x00000200
4233+#define CAP_DFS 0x00001000
4234+#define CAP_INFOLEVEL_PASSTHRU 0x00002000
4235+#define CAP_LARGE_READ_X 0x00004000
4236+#define CAP_LARGE_WRITE_X 0x00008000
4237+#define CAP_UNIX 0x00800000
4238+#define CAP_RESERVED 0x02000000
4239+#define CAP_BULK_TRANSFER 0x20000000
4240+#define CAP_COMPRESSED_DATA 0x40000000
4241+#define CAP_EXTENDED_SECURITY 0x80000000
4242+
4243+typedef union smb_com_session_setup_andx {
4244+ struct { /* request format */
4245+ struct smb_hdr hdr; /* wct = 12 */
4246+ __u8 AndXCommand;
4247+ __u8 AndXReserved;
4248+ __u16 AndXOffset;
4249+ __u16 MaxBufferSize;
4250+ __u16 MaxMpxCount;
4251+ __u16 VcNumber;
4252+ __u32 SessionKey;
4253+ __u16 SecurityBlobLength;
4254+ __u32 Reserved;
4255+ __u32 Capabilities; /* see below */
4256+ __u16 ByteCount;
4257+ unsigned char SecurityBlob[1]; /* followed by */
4258+ /* STRING NativeOS */
4259+ /* STRING NativeLanMan */
4260+ } req; /* NTLM request format (with extended security */
4261+
4262+ struct { /* request format */
4263+ struct smb_hdr hdr; /* wct = 13 */
4264+ __u8 AndXCommand;
4265+ __u8 AndXReserved;
4266+ __u16 AndXOffset;
4267+ __u16 MaxBufferSize;
4268+ __u16 MaxMpxCount;
4269+ __u16 VcNumber;
4270+ __u32 SessionKey;
4271+ __u16 CaseInsensitivePasswordLength; /* ASCII password length */
4272+ __u16 CaseSensitivePasswordLength; /* Unicode password length */
4273+ __u32 Reserved; /* see below */
4274+ __u32 Capabilities;
4275+ __u16 ByteCount;
4276+ unsigned char CaseInsensitivePassword[1]; /* followed by: */
4277+ /* unsigned char * CaseSensitivePassword; */
4278+ /* STRING AccountName */
4279+ /* STRING PrimaryDomain */
4280+ /* STRING NativeOS */
4281+ /* STRING NativeLanMan */
4282+ } req_no_secext; /* NTLM request format (without extended security */
4283+
4284+ struct { /* default (NTLM) response format */
4285+ struct smb_hdr hdr; /* wct = 4 */
4286+ __u8 AndXCommand;
4287+ __u8 AndXReserved;
4288+ __u16 AndXOffset;
4289+ __u16 Action; /* see below */
4290+ __u16 SecurityBlobLength;
4291+ __u16 ByteCount;
4292+ unsigned char SecurityBlob[1]; /* followed by */
4293+/* unsigned char * NativeOS; */
4294+/* unsigned char * NativeLanMan; */
4295+/* unsigned char * PrimaryDomain; */
4296+ } resp; /* NTLM response format (with or without extended security */
4297+
4298+ struct { /* request format */
4299+ struct smb_hdr hdr; /* wct = 10 */
4300+ __u8 AndXCommand;
4301+ __u8 AndXReserved;
4302+ __u16 AndXOffset;
4303+ __u16 MaxBufferSize;
4304+ __u16 MaxMpxCount;
4305+ __u16 VcNumber;
4306+ __u32 SessionKey;
4307+ __u16 PassswordLength;
4308+ __u32 Reserved;
4309+ __u16 ByteCount;
4310+ unsigned char AccountPassword[1]; /* followed by */
4311+ /* STRING AccountName */
4312+ /* STRING PrimaryDomain */
4313+ /* STRING NativeOS */
4314+ /* STRING NativeLanMan */
4315+ } old_req; /* pre-NTLM (LANMAN2.1) request format */
4316+
4317+ struct { /* default (NTLM) response format */
4318+ struct smb_hdr hdr; /* wct = 3 */
4319+ __u8 AndXCommand;
4320+ __u8 AndXReserved;
4321+ __u16 AndXOffset;
4322+ __u16 Action; /* see below */
4323+ __u16 ByteCount;
4324+ unsigned char NativeOS[1]; /* followed by */
4325+/* unsigned char * NativeLanMan; */
4326+/* unsigned char * PrimaryDomain; */
4327+ } old_resp; /* pre-NTLM (LANMAN2.1) response format */
4328+} SESSION_SETUP_ANDX;
4329+
4330+#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
4331+
4332+/* Capabilities bits (for NTLM SessSetup request) */
4333+#define CAP_UNICODE 0x00000004
4334+#define CAP_LARGE_FILES 0x00000008
4335+#define CAP_NT_SMBS 0x00000010
4336+#define CAP_STATUS32 0x00000040
4337+#define CAP_LEVEL_II_OPLOCKS 0x00000080
4338+#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
4339+#define CAP_BULK_TRANSFER 0x20000000
4340+#define CAP_EXTENDED_SECURITY 0x80000000
4341+
4342+/* Action bits */
4343+#define GUEST_LOGIN 1
4344+
4345+typedef struct smb_com_tconx_req {
4346+ struct smb_hdr hdr; /* wct = 4 */
4347+ __u8 AndXCommand;
4348+ __u8 AndXReserved;
4349+ __u16 AndXOffset;
4350+ __u16 Flags; /* see below */
4351+ __u16 PasswordLength;
4352+ __u16 ByteCount;
4353+ unsigned char Password[1]; /* followed by */
4354+/* STRING Path *//* \\server\share name */
4355+ /* STRING Service */
4356+} TCONX_REQ;
4357+
4358+typedef struct smb_com_tconx_rsp {
4359+ struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
4360+ __u8 AndXCommand;
4361+ __u8 AndXReserved;
4362+ __u16 AndXOffset;
4363+ __u16 OptionalSupport; /* see below */
4364+ __u16 ByteCount;
4365+ unsigned char Service[1]; /* always ASCII, not Unicode */
4366+ /* STRING NativeFileSystem */
4367+} TCONX_RSP;
4368+
4369+/* tree connect Flags */
4370+#define DISCONNECT_TID 0x0001
4371+#define TCON_EXTENDED_SECINFO 0x0008
4372+/* OptionalSupport bits */
4373+#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
4374+#define SMB_SHARE_IS_IN_DFS 0x0002
4375+
4376+typedef struct smb_com_logoff_andx_req {
4377+
4378+ struct smb_hdr hdr; /* wct = 2 */
4379+ __u8 AndXCommand;
4380+ __u8 AndXReserved;
4381+ __u16 AndXOffset;
4382+ __u16 ByteCount;
4383+} LOGOFF_ANDX_REQ;
4384+
4385+typedef struct smb_com_logoff_andx_rsp {
4386+ struct smb_hdr hdr; /* wct = 2 */
4387+ __u8 AndXCommand;
4388+ __u8 AndXReserved;
4389+ __u16 AndXOffset;
4390+ __u16 ByteCount;
4391+} LOGOFF_ANDX_RSP;
4392+
4393+typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
4394+ struct {
4395+ struct smb_hdr hdr; /* wct = 0 */
4396+ __u16 ByteCount; /* bcc = 0 */
4397+ } req;
4398+ struct {
4399+ struct smb_hdr hdr; /* wct = 0 */
4400+ __u16 ByteCount; /* bcc = 0 */
4401+ } resp;
4402+} TREE_DISCONNECT;
4403+
4404+typedef struct smb_com_close_req {
4405+ struct smb_hdr hdr; /* wct = 3 */
4406+ __u16 FileID;
4407+ __u32 LastWriteTime; /* should be zero */
4408+ __u16 ByteCount; /* 0 */
4409+} CLOSE_REQ;
4410+
4411+typedef struct smb_com_close_rsp {
4412+ struct smb_hdr hdr; /* wct = 0 */
4413+ __u16 ByteCount; /* bct = 0 */
4414+} CLOSE_RSP;
4415+
4416+typedef struct smb_com_findclose_req {
4417+ struct smb_hdr hdr; /* wct = 1 */
4418+ __u16 FileID;
4419+ __u16 ByteCount; /* 0 */
4420+} FINDCLOSE_REQ;
4421+
4422+/* OpenFlags */
4423+#define REQ_OPLOCK 0x00000002
4424+#define REQ_BATCHOPLOCK 0x00000004
4425+#define REQ_OPENDIRONLY 0x00000008
4426+
4427+typedef struct smb_com_open_req { /* also handles create */
4428+ struct smb_hdr hdr; /* wct = 24 */
4429+ __u8 AndXCommand;
4430+ __u8 AndXReserved;
4431+ __u16 AndXOffset;
4432+ __u8 Reserved; /* Must Be Zero */
4433+ __u16 NameLength;
4434+ __u32 OpenFlags;
4435+ __u32 RootDirectoryFid;
4436+ __u32 DesiredAccess;
4437+ __u64 AllocationSize;
4438+ __u32 FileAttributes;
4439+ __u32 ShareAccess;
4440+ __u32 CreateDisposition;
4441+ __u32 CreateOptions;
4442+ __u32 ImpersonationLevel;
4443+ __u8 SecurityFlags;
4444+ __u16 ByteCount;
4445+ char fileName[1];
4446+} OPEN_REQ;
4447+
4448+/* open response: oplock levels */
4449+#define OPLOCK_NONE 0
4450+#define OPLOCK_EXCLUSIVE 1
4451+#define OPLOCK_BATCH 2
4452+#define OPLOCK_READ 3 /* level 2 oplock */
4453+
4454+/* open response for CreateAction shifted left */
4455+#define CIFS_CREATE_ACTION 0x20000 /* file created */
4456+
4457+typedef struct smb_com_open_rsp {
4458+ struct smb_hdr hdr; /* wct = 34 BB */
4459+ __u8 AndXCommand;
4460+ __u8 AndXReserved;
4461+ __u16 AndXOffset;
4462+ __u8 OplockLevel;
4463+ __u16 Fid;
4464+ __u32 CreateAction;
4465+ __u64 CreationTime;
4466+ __u64 LastAccessTime;
4467+ __u64 LastWriteTime;
4468+ __u64 ChangeTime;
4469+ __u32 FileAttributes;
4470+ __u64 AllocationSize;
4471+ __u64 EndOfFile;
4472+ __u16 FileType;
4473+ __u16 DeviceState;
4474+ __u8 DirectoryFlag;
4475+ __u16 ByteCount; /* bct = 0 */
4476+} OPEN_RSP;
4477+
4478+typedef struct smb_com_write_req {
4479+ struct smb_hdr hdr; /* wct = 14 */
4480+ __u8 AndXCommand;
4481+ __u8 AndXReserved;
4482+ __u16 AndXOffset;
4483+ __u16 Fid;
4484+ __u32 OffsetLow;
4485+ __u32 Reserved;
4486+ __u16 WriteMode;
4487+ __u16 Remaining;
4488+ __u16 DataLengthHigh;
4489+ __u16 DataLengthLow;
4490+ __u16 DataOffset;
4491+ __u32 OffsetHigh;
4492+ __u16 ByteCount;
4493+ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
4494+ char Data[1];
4495+} WRITE_REQ;
4496+
4497+typedef struct smb_com_write_rsp {
4498+ struct smb_hdr hdr; /* wct = 6 */
4499+ __u8 AndXCommand;
4500+ __u8 AndXReserved;
4501+ __u16 AndXOffset;
4502+ __u16 Count;
4503+ __u16 Remaining;
4504+ __u32 Reserved;
4505+ __u16 ByteCount;
4506+} WRITE_RSP;
4507+
4508+typedef struct smb_com_read_req {
4509+ struct smb_hdr hdr; /* wct = 12 */
4510+ __u8 AndXCommand;
4511+ __u8 AndXReserved;
4512+ __u16 AndXOffset;
4513+ __u16 Fid;
4514+ __u32 OffsetLow;
4515+ __u16 MaxCount;
4516+ __u16 MinCount; /* obsolete */
4517+ __u32 MaxCountHigh;
4518+ __u16 Remaining;
4519+ __u32 OffsetHigh;
4520+ __u16 ByteCount;
4521+} READ_REQ;
4522+
4523+typedef struct smb_com_read_rsp {
4524+ struct smb_hdr hdr; /* wct = 12 */
4525+ __u8 AndXCommand;
4526+ __u8 AndXReserved;
4527+ __u16 AndXOffset;
4528+ __u16 Remaining;
4529+ __u16 DataCompactionMode;
4530+ __u16 Reserved;
4531+ __u16 DataLength;
4532+ __u16 DataOffset;
4533+ __u16 DataLengthHigh;
4534+ __u64 Reserved2;
4535+ __u16 ByteCount;
4536+ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
4537+ char Data[1];
4538+} READ_RSP;
4539+
4540+typedef struct locking_andx_range {
4541+ __u16 Pid;
4542+ __u16 Pad;
4543+ __u32 OffsetHigh;
4544+ __u32 OffsetLow;
4545+ __u32 LengthHigh;
4546+ __u32 LengthLow;
4547+} LOCKING_ANDX_RANGE;
4548+
4549+#define LOCKING_ANDX_SHARED_LOCK 0x01
4550+#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
4551+#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
4552+#define LOCKING_ANDX_CANCEL_LOCK 0x08
4553+#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
4554+
4555+typedef struct smb_com_lock_req {
4556+ struct smb_hdr hdr; /* wct = 8 */
4557+ __u8 AndXCommand;
4558+ __u8 AndXReserved;
4559+ __u16 AndXOffset;
4560+ __u16 Fid;
4561+ __u8 LockType;
4562+ __u8 OplockLevel;
4563+ __u32 Timeout;
4564+ __u16 NumberOfUnlocks;
4565+ __u16 NumberOfLocks;
4566+ __u16 ByteCount;
4567+ LOCKING_ANDX_RANGE Locks[1];
4568+} LOCK_REQ;
4569+
4570+typedef struct smb_com_lock_rsp {
4571+ struct smb_hdr hdr; /* wct = 2 */
4572+ __u8 AndXCommand;
4573+ __u8 AndXReserved;
4574+ __u16 AndXOffset;
4575+ __u16 ByteCount;
4576+} LOCK_RSP;
4577+
4578+typedef struct smb_com_rename_req {
4579+ struct smb_hdr hdr; /* wct = 1 */
4580+ __u16 SearchAttributes; /* target file attributes */
4581+ __u16 ByteCount;
4582+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
4583+ unsigned char OldFileName[1];
4584+ /* followed by __u8 BufferFormat2 */
4585+ /* followed by NewFileName */
4586+} RENAME_REQ;
4587+
4588+ /* copy request flags */
4589+#define COPY_MUST_BE_FILE 0x0001
4590+#define COPY_MUST_BE_DIR 0x0002
4591+#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
4592+#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
4593+#define COPY_VERIFY_WRITES 0x0010
4594+#define COPY_TREE 0x0020
4595+
4596+typedef struct smb_com_copy_req {
4597+ struct smb_hdr hdr; /* wct = 3 */
4598+ __u16 Tid2;
4599+ __u16 OpenFunction;
4600+ __u16 Flags;
4601+ __u16 ByteCount;
4602+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
4603+ unsigned char OldFileName[1];
4604+ /* followed by __u8 BufferFormat2 */
4605+ /* followed by NewFileName string */
4606+} COPY_REQ;
4607+
4608+typedef struct smb_com_copy_rsp {
4609+ struct smb_hdr hdr; /* wct = 1 */
4610+ __u16 CopyCount; /* number of files copied */
4611+ __u16 ByteCount; /* may be zero */
4612+ __u8 BufferFormat; /* 0x04 - only present if errored file follows */
4613+ unsigned char ErrorFileName[1]; /* only present if error in copy */
4614+} COPY_RSP;
4615+
4616+#define CREATE_HARD_LINK 0x103
4617+#define MOVEFILE_COPY_ALLOWED 0x0002
4618+#define MOVEFILE_REPLACE_EXISTING 0x0001
4619+
4620+typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
4621+ struct smb_hdr hdr; /* wct = 4 */
4622+ __u16 SearchAttributes; /* target file attributes */
4623+ __u16 Flags; /* spec says Information Level */
4624+ __u32 ClusterCount;
4625+ __u16 ByteCount;
4626+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
4627+ unsigned char OldFileName[1];
4628+ /* followed by __u8 BufferFormat2 */
4629+ /* followed by NewFileName */
4630+} NT_RENAME_REQ;
4631+
4632+typedef struct smb_com_rename_rsp {
4633+ struct smb_hdr hdr; /* wct = 0 */
4634+ __u16 ByteCount; /* bct = 0 */
4635+} RENAME_RSP;
4636+
4637+typedef struct smb_com_delete_file_req {
4638+ struct smb_hdr hdr; /* wct = 1 */
4639+ __u16 SearchAttributes;
4640+ __u16 ByteCount;
4641+ __u8 BufferFormat; /* 4 = ASCII */
4642+ unsigned char fileName[1];
4643+} DELETE_FILE_REQ;
4644+
4645+typedef struct smb_com_delete_file_rsp {
4646+ struct smb_hdr hdr; /* wct = 0 */
4647+ __u16 ByteCount; /* bct = 0 */
4648+} DELETE_FILE_RSP;
4649+
4650+typedef struct smb_com_delete_directory_req {
4651+ struct smb_hdr hdr; /* wct = 0 */
4652+ __u16 ByteCount;
4653+ __u8 BufferFormat; /* 4 = ASCII */
4654+ unsigned char DirName[1];
4655+} DELETE_DIRECTORY_REQ;
4656+
4657+typedef struct smb_com_delete_directory_rsp {
4658+ struct smb_hdr hdr; /* wct = 0 */
4659+ __u16 ByteCount; /* bct = 0 */
4660+} DELETE_DIRECTORY_RSP;
4661+
4662+typedef struct smb_com_create_directory_req {
4663+ struct smb_hdr hdr; /* wct = 0 */
4664+ __u16 ByteCount;
4665+ __u8 BufferFormat; /* 4 = ASCII */
4666+ unsigned char DirName[1];
4667+} CREATE_DIRECTORY_REQ;
4668+
4669+typedef struct smb_com_create_directory_rsp {
4670+ struct smb_hdr hdr; /* wct = 0 */
4671+ __u16 ByteCount; /* bct = 0 */
4672+} CREATE_DIRECTORY_RSP;
4673+
4674+/***************************************************/
4675+/* NT Transact structure defintions follow */
4676+/* Currently only ioctl and notify are implemented */
4677+/***************************************************/
4678+typedef struct smb_com_transaction_ioctl_req {
4679+ struct smb_hdr hdr; /* wct = 23 */
4680+ __u8 MaxSetupCount;
4681+ __u16 Reserved;
4682+ __u32 TotalParameterCount;
4683+ __u32 TotalDataCount;
4684+ __u32 MaxParameterCount;
4685+ __u32 MaxDataCount;
4686+ __u32 ParameterCount;
4687+ __u32 ParameterOffset;
4688+ __u32 DataCount;
4689+ __u32 DataOffset;
4690+ __u8 SetupCount; /* four setup words follow subcommand */
4691+ /* SNIA spec incorrectly included spurious pad here */
4692+ __u16 SubCommand;/* 2 = IOCTL/FSCTL */
4693+ __u32 FunctionCode;
4694+ __u16 Fid;
4695+ __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
4696+ __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
4697+ __u16 ByteCount;
4698+ __u8 Pad[3];
4699+ __u8 Data[1];
4700+} TRANSACT_IOCTL_REQ;
4701+
4702+typedef struct smb_com_transaction_ioctl_rsp {
4703+ struct smb_hdr hdr; /* wct = 19 */
4704+ __u8 Reserved[3];
4705+ __u32 TotalParameterCount;
4706+ __u32 TotalDataCount;
4707+ __u32 ParameterCount;
4708+ __u32 ParameterOffset;
4709+ __u32 ParameterDisplacement;
4710+ __u32 DataCount;
4711+ __u32 DataOffset;
4712+ __u32 DataDisplacement;
4713+ __u8 SetupCount; /* 1 */
4714+ __u16 ReturnedDataLen;
4715+ __u16 ByteCount;
4716+ __u8 Pad[3];
4717+} TRANSACT_IOCTL_RSP;
4718+
4719+typedef struct smb_com_transaction_change_notify_req {
4720+ struct smb_hdr hdr; /* wct = 23 */
4721+ __u8 MaxSetupCount;
4722+ __u16 Reserved;
4723+ __u32 TotalParameterCount;
4724+ __u32 TotalDataCount;
4725+ __u32 MaxParameterCount;
4726+ __u32 MaxDataCount;
4727+ __u32 ParameterCount;
4728+ __u32 ParameterOffset;
4729+ __u32 DataCount;
4730+ __u32 DataOffset;
4731+ __u8 SetupCount; /* four setup words follow subcommand */
4732+ /* SNIA spec incorrectly included spurious pad here */
4733+ __u16 SubCommand;/* 4 = Change Notify */
4734+ __u32 CompletionFilter; /* operation to monitor */
4735+ __u16 Fid;
4736+ __u8 WatchTree; /* 1 = Monitor subdirectories */
4737+ __u8 Reserved2;
4738+ __u16 ByteCount;
4739+/* __u8 Pad[3];*/
4740+/* __u8 Data[1];*/
4741+} TRANSACT_CHANGE_NOTIFY_REQ;
4742+
4743+typedef struct smb_com_transaction_change_notify_rsp {
4744+ struct smb_hdr hdr; /* wct = 18 */
4745+ __u8 Reserved[3];
4746+ __u32 TotalParameterCount;
4747+ __u32 TotalDataCount;
4748+ __u32 ParameterCount;
4749+ __u32 ParameterOffset;
4750+ __u32 ParameterDisplacement;
4751+ __u32 DataCount;
4752+ __u32 DataOffset;
4753+ __u32 DataDisplacement;
4754+ __u8 SetupCount; /* 0 */
4755+ __u16 ByteCount;
4756+ /* __u8 Pad[3]; */
4757+} TRANSACT_CHANGE_NOTIFY_RSP;
4758+/* Completion Filter flags for Notify */
4759+#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
4760+#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
4761+#define FILE_NOTIFY_CHANGE_NAME 0x00000003
4762+#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
4763+#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
4764+#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
4765+#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
4766+#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
4767+#define FILE_NOTIFY_CHANGE_EA 0x00000080
4768+#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
4769+#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
4770+#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
4771+#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
4772+
4773+#define FILE_ACTION_ADDED 0x00000001
4774+#define FILE_ACTION_REMOVED 0x00000002
4775+#define FILE_ACTION_MODIFIED 0x00000003
4776+#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
4777+#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
4778+#define FILE_ACTION_ADDED_STREAM 0x00000006
4779+#define FILE_ACTION_REMOVED_STREAM 0x00000007
4780+#define FILE_ACTION_MODIFIED_STREAM 0x00000008
4781+
4782+/* response contains array of the following structures */
4783+struct file_notify_information {
4784+ __u32 NextEntryOffset;
4785+ __u32 Action;
4786+ __u32 FileNameLength;
4787+ __u8 FileName[1];
4788+};
4789+
4790+struct reparse_data {
4791+ __u32 ReparseTag;
4792+ __u16 ReparseDataLength;
4793+ __u16 Reserved;
4794+ __u16 AltNameOffset;
4795+ __u16 AltNameLen;
4796+ __u16 TargetNameOffset;
4797+ __u16 TargetNameLen;
4798+ char LinkNamesBuf[1];
4799+};
4800+
4801+struct cifs_quota_data {
4802+ __u32 rsrvd1; /* 0 */
4803+ __u32 sid_size;
4804+ __u64 rsrvd2; /* 0 */
4805+ __u64 space_used;
4806+ __u64 soft_limit;
4807+ __u64 hard_limit;
4808+ char sid[1]; /* variable size? */
4809+};
4810+
4811+/* quota sub commands */
4812+#define QUOTA_LIST_CONTINUE 0
4813+#define QUOTA_LIST_START 0x100
4814+#define QUOTA_FOR_SID 0x101
4815+
4816+typedef union smb_com_transaction2 {
4817+ struct {
4818+ struct smb_hdr hdr; /* wct = 14+ */
4819+ __u16 TotalParameterCount;
4820+ __u16 TotalDataCount;
4821+ __u16 MaxParameterCount;
4822+ __u16 MaxDataCount;
4823+ __u8 MaxSetupCount;
4824+ __u8 Reserved;
4825+ __u16 Flags;
4826+ __u32 Timeout;
4827+ __u16 Reserved2;
4828+ __u16 ParameterCount;
4829+ __u16 ParameterOffset;
4830+ __u16 DataCount;
4831+ __u16 DataOffset;
4832+ __u8 SetupCount;
4833+ __u8 Reserved3;
4834+ __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */
4835+ __u16 ByteCount; /* careful - setupcount is not always one */
4836+ } req;
4837+ struct {
4838+ struct smb_hdr hdr; /* wct = 0 */
4839+ __u16 TotalParameterCount;
4840+ __u16 TotalDataCount;
4841+ __u16 Reserved;
4842+ __u16 ParameterCount;
4843+ __u16 ParamterOffset;
4844+ __u16 ParameterDisplacement;
4845+ __u16 DataCount;
4846+ __u16 DataOffset;
4847+ __u16 DataDisplacement;
4848+ __u8 SetupCount;
4849+ __u8 Reserved1; /* should be zero setup words following */
4850+ __u16 ByteCount;
4851+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4852+ /* data area follows */
4853+ } resp;
4854+} TRANSACTION2;
4855+
4856+/* PathInfo/FileInfo infolevels */
4857+#define SMB_INFO_STANDARD 1
4858+#define SMB_INFO_QUERY_EAS_FROM_LIST 3
4859+#define SMB_INFO_QUERY_ALL_EAS 4
4860+#define SMB_INFO_IS_NAME_VALID 6
4861+#define SMB_QUERY_FILE_BASIC_INFO 0x101
4862+#define SMB_QUERY_FILE_STANDARD_INFO 0x102
4863+#define SMB_QUERY_FILE_EA_INFO 0x103
4864+#define SMB_QUERY_FILE_NAME_INFO 0x104
4865+#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
4866+#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
4867+#define SMB_QUERY_FILE_ALL_INFO 0x107
4868+#define SMB_QUERY_ALT_NAME_INFO 0x108
4869+#define SMB_QUERY_FILE_STREAM_INFO 0x109
4870+#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
4871+#define SMB_QUERY_FILE_UNIX_BASIC 0x200
4872+#define SMB_QUERY_FILE_UNIX_LINK 0x201
4873+
4874+#define SMB_SET_FILE_BASIC_INFO 0x101
4875+#define SMB_SET_FILE_DISPOSITION_INFO 0x102
4876+#define SMB_SET_FILE_ALLOCATION_INFO 0x103
4877+#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
4878+#define SMB_SET_FILE_UNIX_BASIC 0x200
4879+#define SMB_SET_FILE_UNIX_LINK 0x201
4880+#define SMB_SET_FILE_UNIX_HLINK 0x203
4881+#define SMB_SET_FILE_BASIC_INFO2 0x3ec
4882+#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
4883+#define SMB_FILE_ALL_INFO2 0x3fa
4884+#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
4885+#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
4886+#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
4887+#define SMB_FILE_QUOTA_INFO 0x408
4888+#define SMB_FILE_REPARSEPOINT_INFO 0x409
4889+#define SMB_FILE_MAXIMUM_INFO 0x40d
4890+
4891+/* Find File infolevels */
4892+#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
4893+#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
4894+#define SMB_FIND_FILE_NAMES_INFO 0x103
4895+#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
4896+#define SMB_FIND_FILE_UNIX 0x202
4897+
4898+typedef struct smb_com_transaction2_qpi_req {
4899+ struct smb_hdr hdr; /* wct = 14+ */
4900+ __u16 TotalParameterCount;
4901+ __u16 TotalDataCount;
4902+ __u16 MaxParameterCount;
4903+ __u16 MaxDataCount;
4904+ __u8 MaxSetupCount;
4905+ __u8 Reserved;
4906+ __u16 Flags;
4907+ __u32 Timeout;
4908+ __u16 Reserved2;
4909+ __u16 ParameterCount;
4910+ __u16 ParameterOffset;
4911+ __u16 DataCount;
4912+ __u16 DataOffset;
4913+ __u8 SetupCount;
4914+ __u8 Reserved3;
4915+ __u16 SubCommand; /* one setup word */
4916+ __u16 ByteCount;
4917+ __u8 Pad;
4918+ __u16 InformationLevel;
4919+ __u32 Reserved4;
4920+ char FileName[1];
4921+} TRANSACTION2_QPI_REQ;
4922+
4923+typedef struct smb_com_transaction2_qpi_rsp {
4924+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
4925+ __u16 TotalParameterCount;
4926+ __u16 TotalDataCount;
4927+ __u16 Reserved;
4928+ __u16 ParameterCount;
4929+ __u16 ParameterOffset;
4930+ __u16 ParameterDisplacement;
4931+ __u16 DataCount;
4932+ __u16 DataOffset;
4933+ __u16 DataDisplacement;
4934+ __u8 SetupCount;
4935+ __u8 Reserved1; /* should be zero setup words following */
4936+ __u16 ByteCount;
4937+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4938+} TRANSACTION2_QPI_RSP;
4939+
4940+typedef struct smb_com_transaction2_spi_req {
4941+ struct smb_hdr hdr; /* wct = 15 */
4942+ __u16 TotalParameterCount;
4943+ __u16 TotalDataCount;
4944+ __u16 MaxParameterCount;
4945+ __u16 MaxDataCount;
4946+ __u8 MaxSetupCount;
4947+ __u8 Reserved;
4948+ __u16 Flags;
4949+ __u32 Timeout;
4950+ __u16 Reserved2;
4951+ __u16 ParameterCount;
4952+ __u16 ParameterOffset;
4953+ __u16 DataCount;
4954+ __u16 DataOffset;
4955+ __u8 SetupCount;
4956+ __u8 Reserved3;
4957+ __u16 SubCommand; /* one setup word */
4958+ __u16 ByteCount;
4959+ __u8 Pad;
4960+ __u16 Pad1;
4961+ __u16 InformationLevel;
4962+ __u32 Reserved4;
4963+ char FileName[1];
4964+} TRANSACTION2_SPI_REQ;
4965+
4966+typedef struct smb_com_transaction2_spi_rsp {
4967+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
4968+ __u16 TotalParameterCount;
4969+ __u16 TotalDataCount;
4970+ __u16 Reserved;
4971+ __u16 ParameterCount;
4972+ __u16 ParameterOffset;
4973+ __u16 ParameterDisplacement;
4974+ __u16 DataCount;
4975+ __u16 DataOffset;
4976+ __u16 DataDisplacement;
4977+ __u8 SetupCount;
4978+ __u8 Reserved1; /* should be zero setup words following */
4979+ __u16 ByteCount;
4980+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4981+} TRANSACTION2_SPI_RSP;
4982+
4983+struct set_file_rename {
4984+ __u32 overwrite; /* 1 = overwrite dest */
4985+ __u32 root_fid; /* zero */
4986+ __u32 target_name_len;
4987+ char target_name[0]; /* Must be unicode */
4988+};
4989+
4990+struct smb_com_transaction2_sfi_req {
4991+ struct smb_hdr hdr; /* wct = 15 */
4992+ __u16 TotalParameterCount;
4993+ __u16 TotalDataCount;
4994+ __u16 MaxParameterCount;
4995+ __u16 MaxDataCount;
4996+ __u8 MaxSetupCount;
4997+ __u8 Reserved;
4998+ __u16 Flags;
4999+ __u32 Timeout;
5000+ __u16 Reserved2;
5001+ __u16 ParameterCount;
5002+ __u16 ParameterOffset;
5003+ __u16 DataCount;
5004+ __u16 DataOffset;
5005+ __u8 SetupCount;
5006+ __u8 Reserved3;
5007+ __u16 SubCommand; /* one setup word */
5008+ __u16 ByteCount;
5009+ __u8 Pad;
5010+ __u16 Pad1;
5011+ __u16 Fid;
5012+ __u16 InformationLevel;
5013+ __u16 Reserved4;
5014+};
5015+
5016+struct smb_com_transaction2_sfi_rsp {
5017+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
5018+ __u16 TotalParameterCount;
5019+ __u16 TotalDataCount;
5020+ __u16 Reserved;
5021+ __u16 ParameterCount;
5022+ __u16 ParameterOffset;
5023+ __u16 ParameterDisplacement;
5024+ __u16 DataCount;
5025+ __u16 DataOffset;
5026+ __u16 DataDisplacement;
5027+ __u8 SetupCount;
5028+ __u8 Reserved1; /* should be zero setup words following */
5029+ __u16 ByteCount;
5030+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
5031+};
5032+
5033+
5034+/*
5035+ * Flags on T2 FINDFIRST and FINDNEXT
5036+ */
5037+#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
5038+#define CIFS_SEARCH_CLOSE_AT_END 0x0002
5039+#define CIFS_SEARCH_RETURN_RESUME 0x0004
5040+#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
5041+#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
5042+
5043+/*
5044+ * Size of the resume key on FINDFIRST and FINDNEXT calls
5045+ */
5046+#define CIFS_SMB_RESUME_KEY_SIZE 4
5047+
5048+typedef struct smb_com_transaction2_ffirst_req {
5049+ struct smb_hdr hdr; /* wct = 15 */
5050+ __u16 TotalParameterCount;
5051+ __u16 TotalDataCount;
5052+ __u16 MaxParameterCount;
5053+ __u16 MaxDataCount;
5054+ __u8 MaxSetupCount;
5055+ __u8 Reserved;
5056+ __u16 Flags;
5057+ __u32 Timeout;
5058+ __u16 Reserved2;
5059+ __u16 ParameterCount;
5060+ __u16 ParameterOffset;
5061+ __u16 DataCount;
5062+ __u16 DataOffset;
5063+ __u8 SetupCount; /* one */
5064+ __u8 Reserved3;
5065+ __u16 SubCommand; /* TRANS2_FIND_FIRST */
5066+ __u16 ByteCount;
5067+ __u8 Pad;
5068+ __u16 SearchAttributes;
5069+ __u16 SearchCount;
5070+ __u16 SearchFlags;
5071+ __u16 InformationLevel;
5072+ __u32 SearchStorageType;
5073+ char FileName[1];
5074+} TRANSACTION2_FFIRST_REQ;
5075+
5076+typedef struct smb_com_transaction2_ffirst_rsp {
5077+ struct smb_hdr hdr; /* wct = 10 */
5078+ __u16 TotalParameterCount;
5079+ __u16 TotalDataCount;
5080+ __u16 Reserved;
5081+ __u16 ParameterCount;
5082+ __u16 ParameterOffset;
5083+ __u16 ParameterDisplacement;
5084+ __u16 DataCount;
5085+ __u16 DataOffset;
5086+ __u16 DataDisplacement;
5087+ __u8 SetupCount;
5088+ __u8 Reserved1; /* should be zero setup words following */
5089+ __u16 ByteCount;
5090+} TRANSACTION2_FFIRST_RSP;
5091+
5092+typedef struct smb_com_transaction2_ffirst_rsp_parms {
5093+ __u16 SearchHandle;
5094+ __u16 SearchCount;
5095+ __u16 EndofSearch;
5096+ __u16 EAErrorOffset;
5097+ __u16 LastNameOffset;
5098+} T2_FFIRST_RSP_PARMS;
5099+
5100+typedef struct smb_com_transaction2_fnext_req {
5101+ struct smb_hdr hdr; /* wct = 15 */
5102+ __u16 TotalParameterCount;
5103+ __u16 TotalDataCount;
5104+ __u16 MaxParameterCount;
5105+ __u16 MaxDataCount;
5106+ __u8 MaxSetupCount;
5107+ __u8 Reserved;
5108+ __u16 Flags;
5109+ __u32 Timeout;
5110+ __u16 Reserved2;
5111+ __u16 ParameterCount;
5112+ __u16 ParameterOffset;
5113+ __u16 DataCount;
5114+ __u16 DataOffset;
5115+ __u8 SetupCount; /* one */
5116+ __u8 Reserved3;
5117+ __u16 SubCommand; /* TRANS2_FIND_NEXT */
5118+ __u16 ByteCount;
5119+ __u8 Pad;
5120+ __u16 SearchHandle;
5121+ __u16 SearchCount;
5122+ __u16 InformationLevel;
5123+ __u32 ResumeKey;
5124+ __u16 SearchFlags;
5125+ char ResumeFileName[1];
5126+} TRANSACTION2_FNEXT_REQ;
5127+
5128+typedef struct smb_com_transaction2_fnext_rsp {
5129+ struct smb_hdr hdr; /* wct = 10 */
5130+ __u16 TotalParameterCount;
5131+ __u16 TotalDataCount;
5132+ __u16 Reserved;
5133+ __u16 ParameterCount;
5134+ __u16 ParameterOffset;
5135+ __u16 ParameterDisplacement;
5136+ __u16 DataCount;
5137+ __u16 DataOffset;
5138+ __u16 DataDisplacement;
5139+ __u8 SetupCount;
5140+ __u8 Reserved1; /* should be zero setup words following */
5141+ __u16 ByteCount;
5142+} TRANSACTION2_FNEXT_RSP;
5143+
5144+typedef struct smb_com_transaction2_fnext_rsp_parms {
5145+ __u16 SearchCount;
5146+ __u16 EndofSearch;
5147+ __u16 EAErrorOffset;
5148+ __u16 LastNameOffset;
5149+} T2_FNEXT_RSP_PARMS;
5150+
5151+/* QFSInfo Levels */
5152+#define SMB_INFO_ALLOCATION 1
5153+#define SMB_INFO_VOLUME 2
5154+#define SMB_QUERY_FS_VOLUME_INFO 0x102
5155+#define SMB_QUERY_FS_SIZE_INFO 0x103
5156+#define SMB_QUERY_FS_DEVICE_INFO 0x104
5157+#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
5158+#define SMB_QUERY_CIFS_UNIX_INFO 0x200
5159+#define SMB_QUERY_LABEL_INFO 0x3ea
5160+#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
5161+
5162+typedef struct smb_com_transaction2_qfsi_req {
5163+ struct smb_hdr hdr; /* wct = 14+ */
5164+ __u16 TotalParameterCount;
5165+ __u16 TotalDataCount;
5166+ __u16 MaxParameterCount;
5167+ __u16 MaxDataCount;
5168+ __u8 MaxSetupCount;
5169+ __u8 Reserved;
5170+ __u16 Flags;
5171+ __u32 Timeout;
5172+ __u16 Reserved2;
5173+ __u16 ParameterCount;
5174+ __u16 ParameterOffset;
5175+ __u16 DataCount;
5176+ __u16 DataOffset;
5177+ __u8 SetupCount;
5178+ __u8 Reserved3;
5179+ __u16 SubCommand; /* one setup word */
5180+ __u16 ByteCount;
5181+ __u8 Pad;
5182+ __u16 InformationLevel;
5183+} TRANSACTION2_QFSI_REQ;
5184+
5185+typedef struct smb_com_transaction_qfsi_rsp {
5186+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
5187+ __u16 TotalParameterCount;
5188+ __u16 TotalDataCount;
5189+ __u16 Reserved;
5190+ __u16 ParameterCount;
5191+ __u16 ParameterOffset;
5192+ __u16 ParameterDisplacement;
5193+ __u16 DataCount;
5194+ __u16 DataOffset;
5195+ __u16 DataDisplacement;
5196+ __u8 SetupCount;
5197+ __u8 Reserved1; /* should be zero setup words following */
5198+ __u16 ByteCount;
5199+ __u8 Pad; /* may be three bytes *//* followed by data area */
5200+} TRANSACTION2_QFSI_RSP;
5201+
5202+typedef struct smb_com_transaction2_get_dfs_refer_req {
5203+ struct smb_hdr hdr; /* wct = 15 */
5204+ __u16 TotalParameterCount;
5205+ __u16 TotalDataCount;
5206+ __u16 MaxParameterCount;
5207+ __u16 MaxDataCount;
5208+ __u8 MaxSetupCount;
5209+ __u8 Reserved;
5210+ __u16 Flags;
5211+ __u32 Timeout;
5212+ __u16 Reserved2;
5213+ __u16 ParameterCount;
5214+ __u16 ParameterOffset;
5215+ __u16 DataCount;
5216+ __u16 DataOffset;
5217+ __u8 SetupCount;
5218+ __u8 Reserved3;
5219+ __u16 SubCommand; /* one setup word */
5220+ __u16 ByteCount;
5221+ __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
5222+ __u16 MaxReferralLevel;
5223+ char RequestFileName[1];
5224+} TRANSACTION2_GET_DFS_REFER_REQ;
5225+
5226+typedef struct dfs_referral_level_3 {
5227+ __u16 VersionNumber;
5228+ __u16 ReferralSize;
5229+ __u16 ServerType; /* 0x0001 = CIFS server */
5230+ __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 */
5231+ __u16 TimeToLive;
5232+ __u16 Proximity;
5233+ __u16 DfsPathOffset;
5234+ __u16 DfsAlternatePathOffset;
5235+ __u16 NetworkAddressOffset;
5236+} REFERRAL3;
5237+
5238+typedef struct smb_com_transaction_get_dfs_refer_rsp {
5239+ struct smb_hdr hdr; /* wct = 10 */
5240+ __u16 TotalParameterCount;
5241+ __u16 TotalDataCount;
5242+ __u16 Reserved;
5243+ __u16 ParameterCount;
5244+ __u16 ParameterOffset;
5245+ __u16 ParameterDisplacement;
5246+ __u16 DataCount;
5247+ __u16 DataOffset;
5248+ __u16 DataDisplacement;
5249+ __u8 SetupCount;
5250+ __u8 Reserved1; /* zero setup words following */
5251+ __u16 ByteCount;
5252+ __u8 Pad;
5253+ __u16 PathConsumed;
5254+ __u16 NumberOfReferrals;
5255+ __u16 DFSFlags;
5256+ __u16 Pad2;
5257+ REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
5258+ /* followed by the strings pointed to by the referral structures */
5259+} TRANSACTION2_GET_DFS_REFER_RSP;
5260+
5261+/* DFS Flags */
5262+#define DFSREF_REFERRAL_SERVER 0x0001
5263+#define DFSREF_STORAGE_SERVER 0x0002
5264+
5265+/* IOCTL information */
5266+/* List of ioctl function codes that look to be of interest to remote clients like this. */
5267+/* Need to do some experimentation to make sure they all work remotely. */
5268+/* Some of the following such as the encryption/compression ones would be */
5269+/* invoked from tools via a specialized hook into the VFS rather than via the */
5270+/* standard vfs entry points */
5271+#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
5272+#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
5273+#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
5274+#define FSCTL_LOCK_VOLUME 0x00090018
5275+#define FSCTL_UNLOCK_VOLUME 0x0009001C
5276+#define FSCTL_GET_COMPRESSION 0x0009003C
5277+#define FSCTL_SET_COMPRESSION 0x0009C040
5278+#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
5279+#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
5280+#define FSCTL_SET_REPARSE_POINT 0x000900A4
5281+#define FSCTL_GET_REPARSE_POINT 0x000900A8
5282+#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
5283+#define FSCTL_SET_SPARSE 0x000900C4
5284+#define FSCTL_SET_ZERO_DATA 0x000900C8
5285+#define FSCTL_SET_ENCRYPTION 0x000900D7
5286+#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
5287+#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
5288+#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
5289+#define FSCTL_SIS_COPYFILE 0x00090100
5290+#define FSCTL_SIS_LINK_FILES 0x0009C104
5291+
5292+#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
5293+#define IO_REPARSE_TAG_HSM 0xC0000004
5294+#define IO_REPARSE_TAG_SIS 0x80000007
5295+
5296+/*
5297+ ************************************************************************
5298+ * All structs for everything above the SMB PDUs themselves
5299+ * (such as the T2 level specific data) go here
5300+ ************************************************************************
5301+ */
5302+
5303+/*
5304+ * Information on a server
5305+ */
5306+
5307+struct serverInfo {
5308+ char name[16];
5309+ unsigned char versionMajor;
5310+ unsigned char versionMinor;
5311+ unsigned long type;
5312+ unsigned int commentOffset;
5313+};
5314+
5315+/*
5316+ * The following structure is the format of the data returned on a NetShareEnum
5317+ * with level "90" (x5A)
5318+ */
5319+
5320+struct shareInfo {
5321+ char shareName[13];
5322+ char pad;
5323+ unsigned short type;
5324+ unsigned int commentOffset;
5325+};
5326+
5327+struct aliasInfo {
5328+ char aliasName[9];
5329+ char pad;
5330+ unsigned int commentOffset;
5331+ unsigned char type[2];
5332+};
5333+
5334+struct aliasInfo92 {
5335+ int aliasNameOffset;
5336+ int serverNameOffset;
5337+ int shareNameOffset;
5338+};
5339+
5340+typedef struct {
5341+ __u64 TotalAllocationUnits;
5342+ __u64 FreeAllocationUnits;
5343+ __u32 SectorsPerAllocationUnit;
5344+ __u32 BytesPerSector;
5345+} FILE_SYSTEM_INFO; /* size info, level 0x103 */
5346+
5347+typedef struct {
5348+ __u16 MajorVersionNumber;
5349+ __u16 MinorVersionNumber;
5350+ __u64 Capability;
5351+} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
5352+/* Linux/Unix extensions capability flags */
5353+#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
5354+#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
5355+
5356+/* DeviceType Flags */
5357+#define FILE_DEVICE_CD_ROM 0x00000002
5358+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
5359+#define FILE_DEVICE_DFS 0x00000006
5360+#define FILE_DEVICE_DISK 0x00000007
5361+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
5362+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
5363+#define FILE_DEVICE_NAMED_PIPE 0x00000011
5364+#define FILE_DEVICE_NETWORK 0x00000012
5365+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
5366+#define FILE_DEVICE_NULL 0x00000015
5367+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
5368+#define FILE_DEVICE_PRINTER 0x00000018
5369+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
5370+#define FILE_DEVICE_STREAMS 0x0000001e
5371+#define FILE_DEVICE_TAPE 0x0000001f
5372+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
5373+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
5374+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
5375+
5376+typedef struct {
5377+ __u32 DeviceType;
5378+ __u32 DeviceCharacteristics;
5379+} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
5380+
5381+typedef struct {
5382+ __u32 Attributes;
5383+ __u32 MaxPathNameComponentLength;
5384+ __u32 FileSystemNameLen;
5385+ char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
5386+} FILE_SYSTEM_ATTRIBUTE_INFO;
5387+
5388+typedef struct { /* data block encoding of response to level 263 QPathInfo */
5389+ __u64 CreationTime;
5390+ __u64 LastAccessTime;
5391+ __u64 LastWriteTime;
5392+ __u64 ChangeTime;
5393+ __u32 Attributes;
5394+ __u32 Pad1;
5395+ __u64 AllocationSize;
5396+ __u64 EndOfFile; /* size ie offset to first free byte in file */
5397+ __u32 NumberOfLinks; /* hard links */
5398+ __u8 DeletePending;
5399+ __u8 Directory;
5400+ __u16 Pad2;
5401+ __u64 IndexNumber;
5402+ __u32 EASize;
5403+ __u32 AccessFlags;
5404+ __u64 IndexNumber1;
5405+ __u64 CurrentByteOffset;
5406+ __u32 Mode;
5407+ __u32 AlignmentRequirement;
5408+ __u32 FileNameLength;
5409+ char FileName[1];
5410+} FILE_ALL_INFO; /* level 263 QPathInfo */
5411+
5412+typedef struct {
5413+ __u64 EndOfFile;
5414+ __u64 NumOfBytes;
5415+ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
5416+ __u64 LastAccessTime;
5417+ __u64 LastModificationTime;
5418+ __u64 Uid;
5419+ __u64 Gid;
5420+ __u32 Type;
5421+ __u64 DevMajor;
5422+ __u64 DevMinor;
5423+ __u64 UniqueId;
5424+ __u64 Permissions;
5425+ __u64 Nlinks;
5426+} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */
5427+
5428+typedef struct {
5429+ char LinkDest[1];
5430+} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */
5431+
5432+/* defines for enumerating possible values of the Unix type field below */
5433+#define UNIX_FILE 0
5434+#define UNIX_DIR 1
5435+#define UNIX_SYMLINK 2
5436+#define UNIX_CHARDEV 3
5437+#define UNIX_BLOCKDEV 4
5438+#define UNIX_FIFO 5
5439+#define UNIX_SOCKET 6
5440+
5441+typedef struct {
5442+ __u32 NextEntryOffset;
5443+ __u32 ResumeKey;
5444+ __u64 EndOfFile;
5445+ __u64 NumOfBytes;
5446+ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
5447+ __u64 LastAccessTime;
5448+ __u64 LastModificationTime;
5449+ __u64 Uid;
5450+ __u64 Gid;
5451+ __u32 Type;
5452+ __u64 DevMajor;
5453+ __u64 DevMinor;
5454+ __u64 UniqueId;
5455+ __u64 Permissions;
5456+ __u64 Nlinks;
5457+ char FileName[1];
5458+} FILE_UNIX_INFO;
5459+
5460+typedef struct {
5461+ __u64 CreationTime;
5462+ __u64 LastAccessTime;
5463+ __u64 LastWriteTime;
5464+ __u64 ChangeTime;
5465+ __u32 Attributes;
5466+ __u32 Pad;
5467+} FILE_BASIC_INFO; /* size info, level 0x101 */
5468+
5469+struct file_allocation_info {
5470+ __u64 AllocationSize;
5471+}; /* size info, level 0x103 */
5472+
5473+struct file_end_of_file_info {
5474+ __u64 FileSize; /* offset to end of file */
5475+}; /* size info, level 0x104 */
5476+
5477+typedef struct {
5478+ __u32 NextEntryOffset;
5479+ __u32 FileIndex;
5480+ __u64 CreationTime;
5481+ __u64 LastAccessTime;
5482+ __u64 LastWriteTime;
5483+ __u64 ChangeTime;
5484+ __u64 EndOfFile;
5485+ __u64 AllocationSize;
5486+ __u32 ExtFileAttributes;
5487+ __u32 FileNameLength;
5488+ char FileName[1];
5489+} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
5490+
5491+struct gea {
5492+ unsigned char cbName;
5493+ char szName[1];
5494+};
5495+
5496+struct gealist {
5497+ unsigned long cbList;
5498+ struct gea list[1];
5499+};
5500+
5501+struct fea {
5502+ unsigned char EA_flags;
5503+ __u8 name_len;
5504+ __u16 value_len;
5505+ char szName[1];
5506+ /* optionally followed by value */
5507+};
5508+/* flags for _FEA.fEA */
5509+#define FEA_NEEDEA 0x80 /* need EA bit */
5510+
5511+struct fealist {
5512+ __u32 list_len;
5513+ struct fea list[1];
5514+};
5515+
5516+/* used to hold an arbitrary blob of data */
5517+struct data_blob {
5518+ __u8 *data;
5519+ size_t length;
5520+ void (*free) (struct data_blob * data_blob);
5521+};
5522+
5523+#ifdef CONFIG_CIFS_POSIX
5524+/*
5525+ For better POSIX semantics from Linux client, (even better
5526+ than the existing CIFS Unix Extensions) we need updated PDUs for:
5527+
5528+ 1) PosixCreateX - to set and return the mode, inode#, device info and
5529+ perhaps add a CreateDevice - to create Pipes and other special .inodes
5530+ Also note POSIX open flags
5531+ 2) Close - to return the last write time to do cache across close more safely
5532+ 3) PosixQFSInfo - to return statfs info
5533+ 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
5534+ 5) Mkdir - set mode
5535+
5536+ And under consideration:
5537+ 6) FindClose2 (return nanosecond timestamp ??)
5538+ 7) Use nanosecond timestamps throughout all time fields if
5539+ corresponding attribute flag is set
5540+ 8) sendfile - handle based copy
5541+ 9) Direct i/o
5542+ 10) "POSIX ACL" support
5543+ 11) Misc fcntls?
5544+
5545+ what about fixing 64 bit alignment
5546+
5547+ There are also various legacy SMB/CIFS requests used as is
5548+
5549+ From existing Lanman and NTLM dialects:
5550+ --------------------------------------
5551+ NEGOTIATE
5552+ SESSION_SETUP_ANDX (BB which?)
5553+ TREE_CONNECT_ANDX (BB which wct?)
5554+ TREE_DISCONNECT (BB add volume timestamp on response)
5555+ LOGOFF_ANDX
5556+ DELETE (note delete open file behavior)
5557+ DELETE_DIRECTORY
5558+ READ_AND_X
5559+ WRITE_AND_X
5560+ LOCKING_AND_X (note posix lock semantics)
5561+ RENAME (note rename across dirs and open file rename posix behaviors)
5562+ NT_RENAME (for hardlinks) Is this good enough for all features?
5563+ FIND_CLOSE2
5564+ TRANSACTION2 (18 cases)
5565+ SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
5566+ (BB verify that never need to set allocation size)
5567+ SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
5568+
5569+ COPY (note support for copy across directories) - FUTURE, OPTIONAL
5570+ setting/getting OS/2 EAs - FUTURE (BB can this handle
5571+ setting Linux xattrs perfectly) - OPTIONAL
5572+ dnotify - FUTURE, OPTIONAL
5573+ quota - FUTURE, OPTIONAL
5574+
5575+ Note that various requests implemented for NT interop such as
5576+ NT_TRANSACT (IOCTL) QueryReparseInfo
5577+ are unneeded to servers compliant with the CIFS POSIX extensions
5578+
5579+ From CIFS Unix Extensions:
5580+ -------------------------
5581+ T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
5582+ T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
5583+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
5584+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
5585+ Actually need QUERY_FILE_UNIX_INFO since has inode num
5586+ BB what about a) blksize/blkbits/blocks
5587+ b) i_version
5588+ c) i_rdev
5589+ d) notify mask?
5590+ e) generation
5591+ f) size_seqcount
5592+ T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
5593+ TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
5594+ T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
5595+
5596+
5597+ */
5598+#endif
5599+
5600+#pragma pack() /* resume default structure packing */
5601+
5602+#endif /* _CIFSPDU_H */
5603--- /dev/null
5604+++ b/fs/cifs/cifsproto.h
5605@@ -0,0 +1,254 @@
5606+/*
5607+ * fs/cifs/cifsproto.h
5608+ *
5609+ * Copyright (c) International Business Machines Corp., 2002
5610+ * Author(s): Steve French (sfrench@us.ibm.com)
5611+ *
5612+ * This library is free software; you can redistribute it and/or modify
5613+ * it under the terms of the GNU Lesser General Public License as published
5614+ * by the Free Software Foundation; either version 2.1 of the License, or
5615+ * (at your option) any later version.
5616+ *
5617+ * This library is distributed in the hope that it will be useful,
5618+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5619+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5620+ * the GNU Lesser General Public License for more details.
5621+ *
5622+ * You should have received a copy of the GNU Lesser General Public License
5623+ * along with this library; if not, write to the Free Software
5624+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5625+ */
5626+#ifndef _CIFSPROTO_H
5627+#define _CIFSPROTO_H
5628+#include <linux/nls.h>
5629+
5630+struct statfs;
5631+
5632+/*
5633+ *****************************************************************
5634+ * All Prototypes
5635+ *****************************************************************
5636+ */
5637+
5638+extern struct smb_hdr *cifs_buf_get(void);
5639+extern void cifs_buf_release(void *);
5640+extern int smb_send(struct socket *, struct smb_hdr *,
5641+ unsigned int /* length */ , struct sockaddr *);
5642+extern unsigned int _GetXid(void);
5643+extern void _FreeXid(unsigned int);
5644+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
5645+#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
5646+extern char *build_path_from_dentry(struct dentry *);
5647+extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
5648+extern void renew_parental_timestamps(struct dentry *direntry);
5649+extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
5650+ struct smb_hdr * /* input */ ,
5651+ struct smb_hdr * /* out */ ,
5652+ int * /* bytes returned */ , const int long_op);
5653+extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
5654+extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
5655+extern int is_valid_oplock_break(struct smb_hdr *smb);
5656+extern unsigned int smbCalcSize(struct smb_hdr *ptr);
5657+extern int decode_negTokenInit(unsigned char *security_blob, int length,
5658+ enum securityEnum *secType);
5659+extern int map_smb_to_linux_error(struct smb_hdr *smb);
5660+extern void header_assemble(struct smb_hdr *, char /* command */ ,
5661+ const struct cifsTconInfo *, int
5662+ /* length of fixed section (word count) in two byte units */
5663+ );
5664+struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
5665+void DeleteOplockQEntry(struct oplock_q_entry *);
5666+extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
5667+extern u64 cifs_UnixTimeToNT(time_t);
5668+extern int cifs_get_inode_info(struct inode **pinode,
5669+ const unsigned char *search_path,
5670+ FILE_ALL_INFO * pfile_info,
5671+ struct super_block *sb, int xid);
5672+extern int cifs_get_inode_info_unix(struct inode **pinode,
5673+ const unsigned char *search_path,
5674+ struct super_block *sb,int xid);
5675+
5676+extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
5677+ struct nls_table * nls_info);
5678+extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
5679+
5680+extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
5681+ const char *tree, struct cifsTconInfo *tcon,
5682+ const struct nls_table *);
5683+
5684+extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
5685+ const char *searchName,
5686+ FILE_DIRECTORY_INFO * findData,
5687+ T2_FFIRST_RSP_PARMS * findParms,
5688+ const struct nls_table *nls_codepage,
5689+ int *pUnicodeFlag,
5690+ int *pUnixFlag /* if Unix extensions used */ );
5691+extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
5692+ FILE_DIRECTORY_INFO * findData,
5693+ T2_FNEXT_RSP_PARMS * findParms,
5694+ const __u16 searchHandle, char * resume_name,
5695+ int name_length, __u32 resume_key,
5696+ int *UnicodeFlag, int *pUnixFlag);
5697+
5698+extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
5699+ const __u16 search_handle);
5700+
5701+extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
5702+ const unsigned char *searchName,
5703+ FILE_ALL_INFO * findData,
5704+ const struct nls_table *nls_codepage);
5705+
5706+extern int CIFSSMBUnixQPathInfo(const int xid,
5707+ struct cifsTconInfo *tcon,
5708+ const unsigned char *searchName,
5709+ FILE_UNIX_BASIC_INFO * pFindData,
5710+ const struct nls_table *nls_codepage);
5711+
5712+extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
5713+ const unsigned char *searchName,
5714+ unsigned char **targetUNCs,
5715+ unsigned int *number_of_UNC_in_array,
5716+ const struct nls_table *nls_codepage);
5717+
5718+extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
5719+ const char *old_path,
5720+ const struct nls_table *nls_codepage);
5721+extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
5722+ const char *old_path, const struct nls_table *nls_codepage,
5723+ unsigned int *pnum_referrals, unsigned char ** preferrals);
5724+extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
5725+ struct statfs *FSData,
5726+ const struct nls_table *nls_codepage);
5727+extern int CIFSSMBQFSAttributeInfo(const int xid,
5728+ struct cifsTconInfo *tcon,
5729+ const struct nls_table *nls_codepage);
5730+extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
5731+ const struct nls_table *nls_codepage);
5732+extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
5733+ const struct nls_table *nls_codepage);
5734+
5735+extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
5736+ char *fileName, FILE_BASIC_INFO * data,
5737+ const struct nls_table *nls_codepage);
5738+extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
5739+ char *fileName, __u64 size,int setAllocationSizeFlag,
5740+ const struct nls_table *nls_codepage);
5741+extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
5742+ __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
5743+extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
5744+ char *full_path, __u64 mode, __u64 uid,
5745+ __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
5746+
5747+extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
5748+ const char *newName,
5749+ const struct nls_table *nls_codepage);
5750+extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
5751+ const char *name, const struct nls_table *nls_codepage);
5752+
5753+extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
5754+ const char *name,
5755+ const struct nls_table *nls_codepage);
5756+extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
5757+ const char *fromName, const char *toName,
5758+ const struct nls_table *nls_codepage);
5759+extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
5760+ int netfid, char * target_name, const struct nls_table *nls_codepage);
5761+extern int CIFSCreateHardLink(const int xid,
5762+ struct cifsTconInfo *tcon,
5763+ const char *fromName, const char *toName,
5764+ const struct nls_table *nls_codepage);
5765+extern int CIFSUnixCreateHardLink(const int xid,
5766+ struct cifsTconInfo *tcon,
5767+ const char *fromName, const char *toName,
5768+ const struct nls_table *nls_codepage);
5769+extern int CIFSUnixCreateSymLink(const int xid,
5770+ struct cifsTconInfo *tcon,
5771+ const char *fromName, const char *toName,
5772+ const struct nls_table *nls_codepage);
5773+extern int CIFSSMBUnixQuerySymLink(const int xid,
5774+ struct cifsTconInfo *tcon,
5775+ const unsigned char *searchName,
5776+ char *syminfo, const int buflen,
5777+ const struct nls_table *nls_codepage);
5778+extern int CIFSSMBQueryReparseLinkInfo(const int xid,
5779+ struct cifsTconInfo *tcon,
5780+ const unsigned char *searchName,
5781+ char *symlinkinfo, const int buflen, __u16 fid,
5782+ const struct nls_table *nls_codepage);
5783+
5784+extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
5785+ const char *fileName, const int disposition,
5786+ const int access_flags, const int omode,
5787+ __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
5788+ const struct nls_table *nls_codepage);
5789+extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
5790+ const int smb_file_id);
5791+
5792+extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
5793+ const int netfid, unsigned int count,
5794+ const __u64 lseek, unsigned int *nbytes, char **buf);
5795+extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
5796+ const int netfid, const unsigned int count,
5797+ const __u64 lseek, unsigned int *nbytes,
5798+ const char *buf, const int long_op);
5799+extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
5800+ const __u16 netfid, const __u64 len,
5801+ const __u64 offset, const __u32 numUnlock,
5802+ const __u32 numLock, const __u8 lockType,
5803+ const int waitFlag);
5804+
5805+extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
5806+extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
5807+
5808+extern struct cifsSesInfo *sesInfoAlloc(void);
5809+extern void sesInfoFree(struct cifsSesInfo *);
5810+extern struct cifsTconInfo *tconInfoAlloc(void);
5811+extern void tconInfoFree(struct cifsTconInfo *);
5812+
5813+extern int cifs_reconnect(struct TCP_Server_Info *server);
5814+
5815+extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
5816+extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
5817+ __u32 expected_sequence_number);
5818+extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
5819+extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
5820+extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
5821+
5822+extern int CIFSBuildServerList(int xid, char *serverBufferList,
5823+ int recordlength, int *entries,
5824+ int *totalEntries, int *topoChangedFlag);
5825+extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
5826+ struct shareInfo *shareList, int bufferLen,
5827+ int *entries, int *totalEntries);
5828+extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
5829+ struct aliasInfo *aliasList, int bufferLen,
5830+ int *entries, int *totalEntries);
5831+extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
5832+ char *aliasName, char *serverName,
5833+ char *shareName, char *comment);
5834+extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
5835+ char *share, char *comment);
5836+extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
5837+ char *userName, char *searchName, int *perms);
5838+extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
5839+
5840+extern int CIFSSMBSeek(int xid,
5841+ struct cifsTconInfo *tcon,
5842+ int netfid,
5843+ int pid,
5844+ int whence, unsigned long offset, long long *newoffset);
5845+
5846+extern int CIFSSMBCopy(int xid,
5847+ struct cifsTconInfo *source_tcon,
5848+ const char *fromName,
5849+ const __u16 target_tid,
5850+ const char *toName, const int flags,
5851+ const struct nls_table *nls_codepage);
5852+extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5853+ const int notify_subdirs,const __u16 netfid,__u32 filter,
5854+ const struct nls_table *nls_codepage);
5855+extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5856+ const unsigned char *searchName,
5857+ char * EAData, size_t size,
5858+ const struct nls_table *nls_codepage);
5859+#endif /* _CIFSPROTO_H */
5860--- /dev/null
5861+++ b/fs/cifs/cifssmb.c
5862@@ -0,0 +1,3016 @@
5863+/*
5864+ * fs/cifs/cifssmb.c
5865+ *
5866+ * Copyright (C) International Business Machines Corp., 2002,2003
5867+ * Author(s): Steve French (sfrench@us.ibm.com)
5868+ *
5869+ * Contains the routines for constructing the SMB PDUs themselves
5870+ *
5871+ * This library is free software; you can redistribute it and/or modify
5872+ * it under the terms of the GNU Lesser General Public License as published
5873+ * by the Free Software Foundation; either version 2.1 of the License, or
5874+ * (at your option) any later version.
5875+ *
5876+ * This library is distributed in the hope that it will be useful,
5877+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5878+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5879+ * the GNU Lesser General Public License for more details.
5880+ *
5881+ * You should have received a copy of the GNU Lesser General Public License
5882+ * along with this library; if not, write to the Free Software
5883+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5884+ */
5885+
5886+ /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
5887+ /* These are mostly routines that operate on a pathname, or on a tree id */
5888+ /* (mounted volume), but there are eight handle based routines which must be */
5889+ /* treated slightly different for reconnection purposes since we never want */
5890+ /* to reuse a stale file handle and the caller knows the file handle */
5891+
5892+#include <linux/fs.h>
5893+#include <linux/kernel.h>
5894+#include <linux/vfs.h>
5895+#include <asm/uaccess.h>
5896+#include "cifspdu.h"
5897+#include "cifsglob.h"
5898+#include "cifsproto.h"
5899+#include "cifs_unicode.h"
5900+#include "cifs_debug.h"
5901+
5902+#ifdef CONFIG_CIFS_POSIX
5903+static struct {
5904+ int index;
5905+ char *name;
5906+} protocols[] = {
5907+ {CIFS_PROT, "\2NT LM 0.12"},
5908+ {CIFS_PROT, "\2POSIX 2"},
5909+ {BAD_PROT, "\2"}
5910+};
5911+#else
5912+static struct {
5913+ int index;
5914+ char *name;
5915+} protocols[] = {
5916+ {CIFS_PROT, "\2NT LM 0.12"},
5917+ {BAD_PROT, "\2"}
5918+};
5919+#endif
5920+
5921+
5922+/* Mark as invalid, all open files on tree connections since they
5923+ were closed when session to server was lost */
5924+static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
5925+{
5926+ struct cifsFileInfo *open_file = NULL;
5927+ struct list_head * tmp;
5928+ struct list_head * tmp1;
5929+
5930+/* list all files open on tree connection and mark them invalid */
5931+ write_lock(&GlobalSMBSeslock);
5932+ list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
5933+ open_file = list_entry(tmp,struct cifsFileInfo, tlist);
5934+ if(open_file) {
5935+ open_file->invalidHandle = TRUE;
5936+ }
5937+ }
5938+ write_unlock(&GlobalSMBSeslock);
5939+ /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
5940+}
5941+
5942+static int
5943+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
5944+ void **request_buf /* returned */ ,
5945+ void **response_buf /* returned */ )
5946+{
5947+ int rc = 0;
5948+ int timeout = 10 * HZ;
5949+
5950+ /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
5951+ check for tcp and smb session status done differently
5952+ for those three - in the calling routine */
5953+ if(tcon) {
5954+ if((tcon->ses) && (tcon->ses->server)){
5955+ struct nls_table *nls_codepage;
5956+ /* Give Demultiplex thread up to 10 seconds to
5957+ reconnect, should be greater than cifs socket
5958+ timeout which is 7 seconds */
5959+ while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
5960+ while ((tcon->ses->server->tcpStatus != CifsGood) && (timeout > 0)){
5961+ timeout = interruptible_sleep_on_timeout(&tcon->ses->server->response_q,timeout);
5962+ }
5963+ if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
5964+ /* on "soft" mounts we wait once */
5965+ if((tcon->retry == FALSE) ||
5966+ (tcon->ses->status == CifsExiting)) {
5967+ cFYI(1,("gave up waiting on reconnect in smb_init"));
5968+ return -EHOSTDOWN;
5969+ } /* else "hard" mount - keep retrying until
5970+ process is killed or server comes back up */
5971+ } else /* TCP session is reestablished now */
5972+ break;
5973+
5974+ }
5975+
5976+ nls_codepage = load_nls_default();
5977+ /* need to prevent multiple threads trying to
5978+ simultaneously reconnect the same SMB session */
5979+ down(&tcon->ses->sesSem);
5980+ if(tcon->ses->status == CifsNeedReconnect)
5981+ rc = cifs_setup_session(0, tcon->ses, nls_codepage);
5982+ if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
5983+ mark_open_files_invalid(tcon);
5984+ rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
5985+ nls_codepage);
5986+ up(&tcon->ses->sesSem);
5987+ if(rc == 0)
5988+ atomic_inc(&tconInfoReconnectCount);
5989+
5990+ cFYI(1, ("reconnect tcon rc = %d", rc));
5991+ /* Removed call to reopen open files here -
5992+ it is safer (and faster) to reopen files
5993+ one at a time as needed in read and write */
5994+
5995+ /* Check if handle based operation so we
5996+ know whether we can continue or not without
5997+ returning to caller to reset file handle */
5998+ switch(smb_command) {
5999+ case SMB_COM_READ_ANDX:
6000+ case SMB_COM_WRITE_ANDX:
6001+ case SMB_COM_CLOSE:
6002+ case SMB_COM_FIND_CLOSE2:
6003+ case SMB_COM_LOCKING_ANDX: {
6004+ unload_nls(nls_codepage);
6005+ return -EAGAIN;
6006+ }
6007+ }
6008+ } else {
6009+ up(&tcon->ses->sesSem);
6010+ }
6011+ unload_nls(nls_codepage);
6012+
6013+ } else {
6014+ return -EIO;
6015+ }
6016+ }
6017+ if(rc)
6018+ return rc;
6019+
6020+ *request_buf = cifs_buf_get();
6021+ if (*request_buf == 0) {
6022+ /* BB should we add a retry in here if not a writepage? */
6023+ return -ENOMEM;
6024+ }
6025+ /* Although the original thought was we needed the response buf for */
6026+ /* potential retries of smb operations it turns out we can determine */
6027+ /* from the mid flags when the request buffer can be resent without */
6028+ /* having to use a second distinct buffer for the response */
6029+ *response_buf = *request_buf;
6030+
6031+ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
6032+ wct /*wct */ );
6033+
6034+#ifdef CONFIG_CIFS_STATS
6035+ if(tcon != NULL) {
6036+ atomic_inc(&tcon->num_smbs_sent);
6037+ }
6038+#endif
6039+ return rc;
6040+}
6041+
6042+int
6043+CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
6044+{
6045+ NEGOTIATE_REQ *pSMB;
6046+ NEGOTIATE_RSP *pSMBr;
6047+ int rc = 0;
6048+ int bytes_returned;
6049+ struct TCP_Server_Info * server;
6050+
6051+ if(ses->server)
6052+ server = ses->server;
6053+ else {
6054+ rc = -EIO;
6055+ return rc;
6056+ }
6057+ rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
6058+ (void **) &pSMB, (void **) &pSMBr);
6059+ if (rc)
6060+ return rc;
6061+
6062+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
6063+ if (extended_security)
6064+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
6065+
6066+ pSMB->ByteCount = strlen(protocols[0].name) + 1;
6067+ strncpy(pSMB->DialectsArray, protocols[0].name, 30);
6068+ /* null guaranteed to be at end of source and target buffers anyway */
6069+
6070+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6071+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6072+
6073+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
6074+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6075+ if (rc == 0) {
6076+ server->secMode = pSMBr->SecurityMode;
6077+ server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
6078+ /* one byte - no need to convert this or EncryptionKeyLen from le,*/
6079+ server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
6080+ /* probably no need to store and check maxvcs */
6081+ server->maxBuf =
6082+ min(le32_to_cpu(pSMBr->MaxBufferSize),
6083+ (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
6084+ server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
6085+ cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
6086+ GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
6087+ server->capabilities = le32_to_cpu(pSMBr->Capabilities);
6088+ server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
6089+ /* BB with UTC do we ever need to be using srvr timezone? */
6090+ if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
6091+ memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
6092+ CIFS_CRYPTO_KEY_SIZE);
6093+ } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
6094+ && (pSMBr->EncryptionKeyLength == 0)) {
6095+ /* decode security blob */
6096+ } else
6097+ rc = -EIO;
6098+
6099+ /* BB might be helpful to save off the domain of server here */
6100+
6101+ if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
6102+ if (pSMBr->ByteCount < 16)
6103+ rc = -EIO;
6104+ else if (pSMBr->ByteCount == 16) {
6105+ server->secType = RawNTLMSSP;
6106+ if (server->socketUseCount.counter > 1) {
6107+ if (memcmp
6108+ (server->server_GUID,
6109+ pSMBr->u.extended_response.
6110+ GUID, 16) != 0) {
6111+ cFYI(1,
6112+ ("UID of server does not match previous connection to same ip address"));
6113+ memcpy(server->
6114+ server_GUID,
6115+ pSMBr->u.
6116+ extended_response.
6117+ GUID, 16);
6118+ }
6119+ } else
6120+ memcpy(server->server_GUID,
6121+ pSMBr->u.extended_response.
6122+ GUID, 16);
6123+ } else {
6124+ rc = decode_negTokenInit(pSMBr->u.
6125+ extended_response.
6126+ SecurityBlob,
6127+ pSMBr->ByteCount -
6128+ 16, &server->secType);
6129+ }
6130+ } else
6131+ server->capabilities &= ~CAP_EXTENDED_SECURITY;
6132+ if(sign_CIFS_PDUs == FALSE) {
6133+ if(server->secMode & SECMODE_SIGN_REQUIRED)
6134+ cERROR(1,
6135+ ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
6136+ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
6137+ } else if(sign_CIFS_PDUs == 1) {
6138+ if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
6139+ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
6140+ }
6141+
6142+ }
6143+ if (pSMB)
6144+ cifs_buf_release(pSMB);
6145+ return rc;
6146+}
6147+
6148+int
6149+CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
6150+{
6151+ struct smb_hdr *smb_buffer;
6152+ struct smb_hdr *smb_buffer_response;
6153+ int rc = 0;
6154+ int length;
6155+
6156+ cFYI(1, ("In tree disconnect"));
6157+ /*
6158+ * If last user of the connection and
6159+ * connection alive - disconnect it
6160+ * If this is the last connection on the server session disconnect it
6161+ * (and inside session disconnect we should check if tcp socket needs
6162+ * to be freed and kernel thread woken up).
6163+ */
6164+ if (tcon)
6165+ down(&tcon->tconSem);
6166+ else
6167+ return -EIO;
6168+
6169+ atomic_dec(&tcon->useCount);
6170+ if (atomic_read(&tcon->useCount) > 0) {
6171+ up(&tcon->tconSem);
6172+ return -EBUSY;
6173+ }
6174+
6175+ /* No need to return error on this operation if tid invalidated and
6176+ closed on server already e.g. due to tcp session crashing */
6177+ if(tcon->tidStatus == CifsNeedReconnect) {
6178+ up(&tcon->tconSem);
6179+ return 0;
6180+ }
6181+
6182+ if((tcon->ses == 0) || (tcon->ses->server == 0)) {
6183+ up(&tcon->tconSem);
6184+ return -EIO;
6185+ }
6186+
6187+ rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
6188+ (void **) &smb_buffer, (void **) &smb_buffer_response);
6189+ if (rc) {
6190+ up(&tcon->tconSem);
6191+ return rc;
6192+ }
6193+ rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
6194+ &length, 0);
6195+ if (rc)
6196+ cFYI(1, (" Tree disconnect failed %d", rc));
6197+
6198+ if (smb_buffer)
6199+ cifs_buf_release(smb_buffer);
6200+ up(&tcon->tconSem);
6201+
6202+ /* No need to return error on this operation if tid invalidated and
6203+ closed on server already e.g. due to tcp session crashing */
6204+ if (rc == -EAGAIN)
6205+ rc = 0;
6206+
6207+ return rc;
6208+}
6209+
6210+int
6211+CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
6212+{
6213+ struct smb_hdr *smb_buffer_response;
6214+ LOGOFF_ANDX_REQ *pSMB;
6215+ int rc = 0;
6216+ int length;
6217+
6218+ cFYI(1, ("In SMBLogoff for session disconnect"));
6219+ if (ses)
6220+ down(&ses->sesSem);
6221+ else
6222+ return -EIO;
6223+
6224+ atomic_dec(&ses->inUse);
6225+ if (atomic_read(&ses->inUse) > 0) {
6226+ up(&ses->sesSem);
6227+ return -EBUSY;
6228+ }
6229+
6230+ rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
6231+ (void **) &pSMB, (void **) &smb_buffer_response);
6232+
6233+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
6234+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
6235+
6236+ if (rc) {
6237+ up(&ses->sesSem);
6238+ return rc;
6239+ }
6240+
6241+ pSMB->hdr.Uid = ses->Suid;
6242+
6243+ pSMB->AndXCommand = 0xFF;
6244+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
6245+ smb_buffer_response, &length, 0);
6246+ if (ses->server) {
6247+ atomic_dec(&ses->server->socketUseCount);
6248+ if (atomic_read(&ses->server->socketUseCount) == 0) {
6249+ spin_lock(&GlobalMid_Lock);
6250+ ses->server->tcpStatus = CifsExiting;
6251+ spin_unlock(&GlobalMid_Lock);
6252+ rc = -ESHUTDOWN;
6253+ }
6254+ }
6255+ if (pSMB)
6256+ cifs_buf_release(pSMB);
6257+ up(&ses->sesSem);
6258+
6259+ /* if session dead then we do not need to do ulogoff,
6260+ since server closed smb session, no sense reporting
6261+ error */
6262+ if (rc == -EAGAIN)
6263+ rc = 0;
6264+ return rc;
6265+}
6266+
6267+int
6268+CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
6269+ const char *fileName, const struct nls_table *nls_codepage)
6270+{
6271+ DELETE_FILE_REQ *pSMB = NULL;
6272+ DELETE_FILE_RSP *pSMBr = NULL;
6273+ int rc = 0;
6274+ int bytes_returned;
6275+ int name_len;
6276+
6277+DelFileRetry:
6278+ rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
6279+ (void **) &pSMBr);
6280+ if (rc)
6281+ return rc;
6282+
6283+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6284+ name_len =
6285+ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
6286+ /* find define for this maxpathcomponent */
6287+ , nls_codepage);
6288+ name_len++; /* trailing null */
6289+ name_len *= 2;
6290+ } else { /* BB improve the check for buffer overruns BB */
6291+ name_len = strnlen(fileName, 530);
6292+ name_len++; /* trailing null */
6293+ strncpy(pSMB->fileName, fileName, name_len);
6294+ }
6295+ pSMB->SearchAttributes =
6296+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
6297+ pSMB->ByteCount = name_len + 1;
6298+ pSMB->BufferFormat = 0x04;
6299+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6300+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6301+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6302+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6303+ if (rc) {
6304+ cFYI(1, ("Error in RMFile = %d", rc));
6305+ }
6306+#ifdef CONFIG_CIFS_STATS
6307+ else {
6308+ atomic_inc(&tcon->num_deletes);
6309+ }
6310+#endif
6311+
6312+ if (pSMB)
6313+ cifs_buf_release(pSMB);
6314+ if (rc == -EAGAIN)
6315+ goto DelFileRetry;
6316+
6317+ return rc;
6318+}
6319+
6320+int
6321+CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
6322+ const char *dirName, const struct nls_table *nls_codepage)
6323+{
6324+ DELETE_DIRECTORY_REQ *pSMB = NULL;
6325+ DELETE_DIRECTORY_RSP *pSMBr = NULL;
6326+ int rc = 0;
6327+ int bytes_returned;
6328+ int name_len;
6329+
6330+ cFYI(1, ("In CIFSSMBRmDir"));
6331+RmDirRetry:
6332+ rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
6333+ (void **) &pSMBr);
6334+ if (rc)
6335+ return rc;
6336+
6337+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6338+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
6339+ /* find define for this maxpathcomponent */
6340+ , nls_codepage);
6341+ name_len++; /* trailing null */
6342+ name_len *= 2;
6343+ } else { /* BB improve the check for buffer overruns BB */
6344+ name_len = strnlen(dirName, 530);
6345+ name_len++; /* trailing null */
6346+ strncpy(pSMB->DirName, dirName, name_len);
6347+ }
6348+
6349+ pSMB->ByteCount = name_len + 1;
6350+ pSMB->BufferFormat = 0x04;
6351+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6352+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6353+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6354+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6355+ if (rc) {
6356+ cFYI(1, ("Error in RMDir = %d", rc));
6357+ }
6358+#ifdef CONFIG_CIFS_STATS
6359+ else {
6360+ atomic_inc(&tcon->num_rmdirs);
6361+ }
6362+#endif
6363+
6364+ if (pSMB)
6365+ cifs_buf_release(pSMB);
6366+ if (rc == -EAGAIN)
6367+ goto RmDirRetry;
6368+ return rc;
6369+}
6370+
6371+int
6372+CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
6373+ const char *name, const struct nls_table *nls_codepage)
6374+{
6375+ int rc = 0;
6376+ CREATE_DIRECTORY_REQ *pSMB = NULL;
6377+ CREATE_DIRECTORY_RSP *pSMBr = NULL;
6378+ int bytes_returned;
6379+ int name_len;
6380+
6381+ cFYI(1, ("In CIFSSMBMkDir"));
6382+MkDirRetry:
6383+ rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
6384+ (void **) &pSMBr);
6385+ if (rc)
6386+ return rc;
6387+
6388+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6389+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
6390+ /* find define for this maxpathcomponent */
6391+ , nls_codepage);
6392+ name_len++; /* trailing null */
6393+ name_len *= 2;
6394+ } else { /* BB improve the check for buffer overruns BB */
6395+ name_len = strnlen(name, 530);
6396+ name_len++; /* trailing null */
6397+ strncpy(pSMB->DirName, name, name_len);
6398+ }
6399+
6400+ pSMB->ByteCount = name_len + 1 /* for buf format */ ;
6401+ pSMB->BufferFormat = 0x04;
6402+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6403+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6404+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6405+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6406+ if (rc) {
6407+ cFYI(1, ("Error in Mkdir = %d", rc));
6408+ }
6409+#ifdef CONFIG_CIFS_STATS
6410+ else {
6411+ atomic_inc(&tcon->num_mkdirs);
6412+ }
6413+#endif
6414+ if (pSMB)
6415+ cifs_buf_release(pSMB);
6416+ if (rc == -EAGAIN)
6417+ goto MkDirRetry;
6418+ return rc;
6419+}
6420+
6421+int
6422+CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
6423+ const char *fileName, const int openDisposition,
6424+ const int access_flags, const int create_options, __u16 * netfid,
6425+ int *pOplock, FILE_ALL_INFO * pfile_info,
6426+ const struct nls_table *nls_codepage)
6427+{
6428+ int rc = -EACCES;
6429+ OPEN_REQ *pSMB = NULL;
6430+ OPEN_RSP *pSMBr = NULL;
6431+ int bytes_returned;
6432+ int name_len;
6433+
6434+openRetry:
6435+ rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
6436+ (void **) &pSMBr);
6437+ if (rc)
6438+ return rc;
6439+
6440+ pSMB->AndXCommand = 0xFF; /* none */
6441+
6442+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6443+ pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
6444+ name_len =
6445+ cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
6446+ fileName, 530
6447+ /* find define for this maxpathcomponent */
6448+ , nls_codepage);
6449+ name_len++; /* trailing null */
6450+ name_len *= 2;
6451+ pSMB->NameLength = cpu_to_le16(name_len);
6452+ } else { /* BB improve the check for buffer overruns BB */
6453+ pSMB->ByteCount = 0; /* no pad */
6454+ name_len = strnlen(fileName, 530);
6455+ name_len++; /* trailing null */
6456+ pSMB->NameLength = cpu_to_le16(name_len);
6457+ strncpy(pSMB->fileName, fileName, name_len);
6458+ }
6459+ if (*pOplock & REQ_OPLOCK)
6460+ pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
6461+ else if (*pOplock & REQ_BATCHOPLOCK) {
6462+ pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
6463+ }
6464+ pSMB->DesiredAccess = cpu_to_le32(access_flags);
6465+ pSMB->AllocationSize = 0;
6466+ pSMB->FileAttributes = ATTR_NORMAL;
6467+ /* XP does not handle ATTR_POSIX_SEMANTICS */
6468+ /* but it helps speed up case sensitive checks for other
6469+ servers such as Samba */
6470+ if (tcon->ses->capabilities & CAP_UNIX)
6471+ pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
6472+
6473+ /* if ((omode & S_IWUGO) == 0)
6474+ pSMB->FileAttributes |= ATTR_READONLY;*/
6475+ /* Above line causes problems due to vfs splitting create into two
6476+ pieces - need to set mode after file created not while it is
6477+ being created */
6478+ pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
6479+ pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
6480+ pSMB->CreateDisposition = cpu_to_le32(openDisposition);
6481+ pSMB->CreateOptions = cpu_to_le32(create_options);
6482+ pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
6483+ pSMB->SecurityFlags =
6484+ cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
6485+
6486+ pSMB->ByteCount += name_len;
6487+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6488+
6489+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6490+ /* long_op set to 1 to allow for oplock break timeouts */
6491+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6492+ (struct smb_hdr *) pSMBr, &bytes_returned, 1);
6493+ if (rc) {
6494+ cFYI(1, ("Error in Open = %d", rc));
6495+ } else {
6496+ *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
6497+ *netfid = pSMBr->Fid; /* cifs fid stays in le */
6498+ /* Let caller know file was created so we can set the mode. */
6499+ /* Do we care about the CreateAction in any other cases? */
6500+ if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
6501+ *pOplock |= CIFS_CREATE_ACTION;
6502+ if(pfile_info) {
6503+ memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
6504+ 36 /* CreationTime to Attributes */);
6505+ /* the file_info buf is endian converted by caller */
6506+ pfile_info->AllocationSize = pSMBr->AllocationSize;
6507+ pfile_info->EndOfFile = pSMBr->EndOfFile;
6508+ pfile_info->NumberOfLinks = cpu_to_le32(1);
6509+ }
6510+
6511+#ifdef CONFIG_CIFS_STATS
6512+ atomic_inc(&tcon->num_opens);
6513+#endif
6514+ }
6515+ if (pSMB)
6516+ cifs_buf_release(pSMB);
6517+ if (rc == -EAGAIN)
6518+ goto openRetry;
6519+ return rc;
6520+}
6521+
6522+/* If no buffer passed in, then caller wants to do the copy
6523+ as in the case of readpages so the SMB buffer must be
6524+ freed by the caller */
6525+
6526+int
6527+CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
6528+ const int netfid, const unsigned int count,
6529+ const __u64 lseek, unsigned int *nbytes, char **buf)
6530+{
6531+ int rc = -EACCES;
6532+ READ_REQ *pSMB = NULL;
6533+ READ_RSP *pSMBr = NULL;
6534+ char *pReadData = NULL;
6535+ int bytes_returned;
6536+
6537+ *nbytes = 0;
6538+ rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
6539+ (void **) &pSMBr);
6540+ if (rc)
6541+ return rc;
6542+
6543+ /* tcon and ses pointer are checked in smb_init */
6544+ if (tcon->ses->server == NULL)
6545+ return -ECONNABORTED;
6546+
6547+ pSMB->AndXCommand = 0xFF; /* none */
6548+ pSMB->Fid = netfid;
6549+ pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
6550+ pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
6551+ pSMB->Remaining = 0;
6552+ pSMB->MaxCount = cpu_to_le16(count);
6553+ pSMB->MaxCountHigh = 0;
6554+ pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
6555+
6556+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6557+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6558+ if (rc) {
6559+ cERROR(1, ("Send error in read = %d", rc));
6560+ } else {
6561+ pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
6562+ *nbytes = pSMBr->DataLength;
6563+ /*check that DataLength would not go beyond end of SMB */
6564+ if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
6565+ || (pSMBr->DataLength > count)) {
6566+ cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
6567+ rc = -EIO;
6568+ *nbytes = 0;
6569+ } else {
6570+ pReadData =
6571+ (char *) (&pSMBr->hdr.Protocol) +
6572+ le16_to_cpu(pSMBr->DataOffset);
6573+/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
6574+ cERROR(1,("Faulting on read rc = %d",rc));
6575+ rc = -EFAULT;
6576+ }*/ /* can not use copy_to_user when using page cache*/
6577+ if(*buf)
6578+ memcpy(*buf,pReadData,pSMBr->DataLength);
6579+ }
6580+ }
6581+ if (pSMB) {
6582+ if(*buf)
6583+ cifs_buf_release(pSMB);
6584+ else
6585+ *buf = (char *)pSMB;
6586+ }
6587+
6588+ /* Note: On -EAGAIN error only caller can retry on handle based calls
6589+ since file handle passed in no longer valid */
6590+ return rc;
6591+}
6592+
6593+int
6594+CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
6595+ const int netfid, const unsigned int count,
6596+ const __u64 offset, unsigned int *nbytes, const char *buf,
6597+ const int long_op)
6598+{
6599+ int rc = -EACCES;
6600+ WRITE_REQ *pSMB = NULL;
6601+ WRITE_RSP *pSMBr = NULL;
6602+ int bytes_returned;
6603+
6604+ rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
6605+ (void **) &pSMBr);
6606+ if (rc)
6607+ return rc;
6608+ /* tcon and ses pointer are checked in smb_init */
6609+ if (tcon->ses->server == NULL)
6610+ return -ECONNABORTED;
6611+
6612+ pSMB->AndXCommand = 0xFF; /* none */
6613+ pSMB->Fid = netfid;
6614+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
6615+ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
6616+ pSMB->Remaining = 0;
6617+ if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
6618+ pSMB->DataLengthLow =
6619+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
6620+ else
6621+ pSMB->DataLengthLow = count;
6622+ pSMB->DataLengthHigh = 0;
6623+ pSMB->DataOffset =
6624+ cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
6625+
6626+ memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
6627+
6628+ pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
6629+ pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
6630+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6631+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6632+
6633+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6634+ (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
6635+ if (rc) {
6636+ cFYI(1, ("Send error in write = %d", rc));
6637+ *nbytes = 0;
6638+ } else
6639+ *nbytes = le16_to_cpu(pSMBr->Count);
6640+
6641+ if (pSMB)
6642+ cifs_buf_release(pSMB);
6643+
6644+ /* Note: On -EAGAIN error only caller can retry on handle based calls
6645+ since file handle passed in no longer valid */
6646+
6647+ return rc;
6648+}
6649+
6650+int
6651+CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
6652+ const __u16 smb_file_id, const __u64 len,
6653+ const __u64 offset, const __u32 numUnlock,
6654+ const __u32 numLock, const __u8 lockType, const int waitFlag)
6655+{
6656+ int rc = 0;
6657+ LOCK_REQ *pSMB = NULL;
6658+ LOCK_RSP *pSMBr = NULL;
6659+ int bytes_returned;
6660+ int timeout = 0;
6661+ __u64 temp;
6662+
6663+ cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
6664+ rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
6665+ (void **) &pSMBr);
6666+ if (rc)
6667+ return rc;
6668+
6669+ if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
6670+ timeout = -1; /* no response expected */
6671+ pSMB->Timeout = 0;
6672+ } else if (waitFlag == TRUE) {
6673+ timeout = 3; /* blocking operation, no timeout */
6674+ pSMB->Timeout = -1; /* blocking - do not time out */
6675+ } else {
6676+ pSMB->Timeout = 0;
6677+ }
6678+
6679+ pSMB->NumberOfLocks = cpu_to_le32(numLock);
6680+ pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
6681+ pSMB->LockType = lockType;
6682+ pSMB->AndXCommand = 0xFF; /* none */
6683+ pSMB->Fid = smb_file_id; /* netfid stays le */
6684+
6685+ if(numLock != 0) {
6686+ pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
6687+ /* BB where to store pid high? */
6688+ temp = cpu_to_le64(len);
6689+ pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
6690+ pSMB->Locks[0].LengthHigh = (__u32)(temp>>32);
6691+ temp = cpu_to_le64(offset);
6692+ pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
6693+ pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
6694+ pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
6695+ } else {
6696+ /* oplock break */
6697+ pSMB->ByteCount = 0;
6698+ }
6699+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6700+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6701+
6702+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6703+ (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
6704+
6705+ if (rc) {
6706+ cFYI(1, ("Send error in Lock = %d", rc));
6707+ }
6708+ if (pSMB)
6709+ cifs_buf_release(pSMB);
6710+
6711+ /* Note: On -EAGAIN error only caller can retry on handle based calls
6712+ since file handle passed in no longer valid */
6713+ return rc;
6714+}
6715+
6716+int
6717+CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
6718+{
6719+ int rc = 0;
6720+ CLOSE_REQ *pSMB = NULL;
6721+ CLOSE_RSP *pSMBr = NULL;
6722+ int bytes_returned;
6723+ cFYI(1, ("In CIFSSMBClose"));
6724+
6725+/* do not retry on dead session on close */
6726+ rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
6727+ (void **) &pSMBr);
6728+ if(rc == -EAGAIN)
6729+ return 0;
6730+ if (rc)
6731+ return rc;
6732+
6733+ pSMB->FileID = (__u16) smb_file_id;
6734+ pSMB->LastWriteTime = 0;
6735+ pSMB->ByteCount = 0;
6736+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6737+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6738+ if (rc) {
6739+ if(rc!=-EINTR) {
6740+ /* EINTR is expected when user ctl-c to kill app */
6741+ cERROR(1, ("Send error in Close = %d", rc));
6742+ }
6743+ }
6744+ if (pSMB)
6745+ cifs_buf_release(pSMB);
6746+
6747+ /* Since session is dead, file will be closed on server already */
6748+ if(rc == -EAGAIN)
6749+ rc = 0;
6750+
6751+ return rc;
6752+}
6753+
6754+int
6755+CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
6756+ const char *fromName, const char *toName,
6757+ const struct nls_table *nls_codepage)
6758+{
6759+ int rc = 0;
6760+ RENAME_REQ *pSMB = NULL;
6761+ RENAME_RSP *pSMBr = NULL;
6762+ int bytes_returned;
6763+ int name_len, name_len2;
6764+
6765+ cFYI(1, ("In CIFSSMBRename"));
6766+renameRetry:
6767+ rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
6768+ (void **) &pSMBr);
6769+ if (rc)
6770+ return rc;
6771+
6772+ pSMB->BufferFormat = 0x04;
6773+ pSMB->SearchAttributes =
6774+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
6775+ ATTR_DIRECTORY);
6776+
6777+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6778+ name_len =
6779+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
6780+ /* find define for this maxpathcomponent */
6781+ , nls_codepage);
6782+ name_len++; /* trailing null */
6783+ name_len *= 2;
6784+ pSMB->OldFileName[name_len] = 0x04; /* pad */
6785+ /* protocol requires ASCII signature byte on Unicode string */
6786+ pSMB->OldFileName[name_len + 1] = 0x00;
6787+ name_len2 =
6788+ cifs_strtoUCS((wchar_t *) & pSMB->
6789+ OldFileName[name_len + 2], toName, 530,
6790+ nls_codepage);
6791+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
6792+ name_len2 *= 2; /* convert to bytes */
6793+ } else { /* BB improve the check for buffer overruns BB */
6794+ name_len = strnlen(fromName, 530);
6795+ name_len++; /* trailing null */
6796+ strncpy(pSMB->OldFileName, fromName, name_len);
6797+ name_len2 = strnlen(toName, 530);
6798+ name_len2++; /* trailing null */
6799+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
6800+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
6801+ name_len2++; /* trailing null */
6802+ name_len2++; /* signature byte */
6803+ }
6804+
6805+ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
6806+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6807+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6808+
6809+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6810+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6811+ if (rc) {
6812+ cFYI(1, ("Send error in rename = %d", rc));
6813+ }
6814+
6815+#ifdef CONFIG_CIFS_STATS
6816+ else {
6817+ atomic_inc(&tcon->num_renames);
6818+ }
6819+#endif
6820+
6821+ if (pSMB)
6822+ cifs_buf_release(pSMB);
6823+
6824+ if (rc == -EAGAIN)
6825+ goto renameRetry;
6826+
6827+ return rc;
6828+}
6829+
6830+int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
6831+ int netfid, char * target_name, const struct nls_table * nls_codepage)
6832+{
6833+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
6834+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
6835+ struct set_file_rename * rename_info;
6836+ char *data_offset;
6837+ char dummy_string[30];
6838+ int rc = 0;
6839+ int bytes_returned = 0;
6840+ int len_of_str;
6841+
6842+ cFYI(1, ("Rename to File by handle"));
6843+ rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
6844+ (void **) &pSMBr);
6845+ if (rc)
6846+ return rc;
6847+
6848+ pSMB->ParameterCount = 6;
6849+ pSMB->MaxSetupCount = 0;
6850+ pSMB->Reserved = 0;
6851+ pSMB->Flags = 0;
6852+ pSMB->Timeout = 0;
6853+ pSMB->Reserved2 = 0;
6854+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
6855+ Fid) - 4;
6856+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
6857+
6858+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
6859+ rename_info = (struct set_file_rename *) data_offset;
6860+ pSMB->MaxParameterCount = cpu_to_le16(2);
6861+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
6862+ pSMB->SetupCount = 1;
6863+ pSMB->Reserved3 = 0;
6864+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6865+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
6866+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
6867+ pSMB->TotalParameterCount = pSMB->ParameterCount;
6868+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
6869+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
6870+ /* construct random name ".cifs_tmp<inodenum><mid>" */
6871+ rename_info->overwrite = cpu_to_le32(1);
6872+ rename_info->root_fid = 0;
6873+ /* unicode only call */
6874+ if(target_name == NULL) {
6875+ sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
6876+ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
6877+ } else {
6878+ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
6879+ }
6880+ rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
6881+ pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
6882+ pSMB->ByteCount += pSMB->DataCount;
6883+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
6884+ pSMB->TotalDataCount = pSMB->DataCount;
6885+ pSMB->Fid = netfid;
6886+ pSMB->InformationLevel =
6887+ cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
6888+ pSMB->Reserved4 = 0;
6889+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6890+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6891+ rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
6892+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6893+ if (rc) {
6894+ cFYI(1,("Send error in Rename (by file handle) = %d", rc));
6895+ }
6896+#ifdef CONFIG_CIFS_STATS
6897+ else {
6898+ atomic_inc(&pTcon->num_t2renames);
6899+ }
6900+#endif
6901+ if (pSMB)
6902+ cifs_buf_release(pSMB);
6903+
6904+ /* Note: On -EAGAIN error only caller can retry on handle based calls
6905+ since file handle passed in no longer valid */
6906+
6907+ return rc;
6908+}
6909+
6910+int
6911+CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
6912+ const __u16 target_tid, const char *toName, const int flags,
6913+ const struct nls_table *nls_codepage)
6914+{
6915+ int rc = 0;
6916+ COPY_REQ *pSMB = NULL;
6917+ COPY_RSP *pSMBr = NULL;
6918+ int bytes_returned;
6919+ int name_len, name_len2;
6920+
6921+ cFYI(1, ("In CIFSSMBCopy"));
6922+copyRetry:
6923+ rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
6924+ (void **) &pSMBr);
6925+ if (rc)
6926+ return rc;
6927+
6928+ pSMB->BufferFormat = 0x04;
6929+ pSMB->Tid2 = target_tid;
6930+
6931+ if(flags & COPY_TREE)
6932+ pSMB->Flags |= COPY_TREE;
6933+ pSMB->Flags = cpu_to_le16(pSMB->Flags);
6934+
6935+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6936+ name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
6937+ fromName,
6938+ 530 /* find define for this maxpathcomponent */,
6939+ nls_codepage);
6940+ name_len++; /* trailing null */
6941+ name_len *= 2;
6942+ pSMB->OldFileName[name_len] = 0x04; /* pad */
6943+ /* protocol requires ASCII signature byte on Unicode string */
6944+ pSMB->OldFileName[name_len + 1] = 0x00;
6945+ name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
6946+ OldFileName[name_len + 2], toName, 530,
6947+ nls_codepage);
6948+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
6949+ name_len2 *= 2; /* convert to bytes */
6950+ } else { /* BB improve the check for buffer overruns BB */
6951+ name_len = strnlen(fromName, 530);
6952+ name_len++; /* trailing null */
6953+ strncpy(pSMB->OldFileName, fromName, name_len);
6954+ name_len2 = strnlen(toName, 530);
6955+ name_len2++; /* trailing null */
6956+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
6957+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
6958+ name_len2++; /* trailing null */
6959+ name_len2++; /* signature byte */
6960+ }
6961+
6962+ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
6963+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6964+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6965+
6966+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6967+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6968+ if (rc) {
6969+ cFYI(1, ("Send error in copy = %d with %d files copied",
6970+ rc, pSMBr->CopyCount));
6971+ }
6972+ if (pSMB)
6973+ cifs_buf_release(pSMB);
6974+
6975+ if (rc == -EAGAIN)
6976+ goto copyRetry;
6977+
6978+ return rc;
6979+}
6980+
6981+int
6982+CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
6983+ const char *fromName, const char *toName,
6984+ const struct nls_table *nls_codepage)
6985+{
6986+ TRANSACTION2_SPI_REQ *pSMB = NULL;
6987+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
6988+ char *data_offset;
6989+ int name_len;
6990+ int name_len_target;
6991+ int rc = 0;
6992+ int bytes_returned = 0;
6993+
6994+ cFYI(1, ("In Symlink Unix style"));
6995+createSymLinkRetry:
6996+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6997+ (void **) &pSMBr);
6998+ if (rc)
6999+ return rc;
7000+
7001+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7002+ name_len =
7003+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
7004+ /* find define for this maxpathcomponent */
7005+ , nls_codepage);
7006+ name_len++; /* trailing null */
7007+ name_len *= 2;
7008+
7009+ } else { /* BB improve the check for buffer overruns BB */
7010+ name_len = strnlen(fromName, 530);
7011+ name_len++; /* trailing null */
7012+ strncpy(pSMB->FileName, fromName, name_len);
7013+ }
7014+ pSMB->ParameterCount = 6 + name_len;
7015+ pSMB->MaxSetupCount = 0;
7016+ pSMB->Reserved = 0;
7017+ pSMB->Flags = 0;
7018+ pSMB->Timeout = 0;
7019+ pSMB->Reserved2 = 0;
7020+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
7021+ InformationLevel) - 4;
7022+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
7023+
7024+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
7025+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7026+ name_len_target =
7027+ cifs_strtoUCS((wchar_t *) data_offset, toName, 530
7028+ /* find define for this maxpathcomponent */
7029+ , nls_codepage);
7030+ name_len_target++; /* trailing null */
7031+ name_len_target *= 2;
7032+ } else { /* BB improve the check for buffer overruns BB */
7033+ name_len_target = strnlen(toName, 530);
7034+ name_len_target++; /* trailing null */
7035+ strncpy(data_offset, toName, name_len_target);
7036+ }
7037+
7038+ pSMB->DataCount = name_len_target;
7039+ pSMB->MaxParameterCount = cpu_to_le16(2);
7040+ /* BB find exact max on data count below from sess */
7041+ pSMB->MaxDataCount = cpu_to_le16(1000);
7042+ pSMB->SetupCount = 1;
7043+ pSMB->Reserved3 = 0;
7044+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
7045+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
7046+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
7047+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7048+ pSMB->TotalDataCount = pSMB->DataCount;
7049+ pSMB->TotalParameterCount = pSMB->ParameterCount;
7050+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
7051+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
7052+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
7053+ pSMB->Reserved4 = 0;
7054+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7055+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7056+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7057+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7058+ if (rc) {
7059+ cFYI(1,
7060+ ("Send error in SetPathInfo (create symlink) = %d",
7061+ rc));
7062+ }
7063+
7064+ if (pSMB)
7065+ cifs_buf_release(pSMB);
7066+
7067+ if (rc == -EAGAIN)
7068+ goto createSymLinkRetry;
7069+
7070+ return rc;
7071+}
7072+
7073+int
7074+CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
7075+ const char *fromName, const char *toName,
7076+ const struct nls_table *nls_codepage)
7077+{
7078+ TRANSACTION2_SPI_REQ *pSMB = NULL;
7079+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
7080+ char *data_offset;
7081+ int name_len;
7082+ int name_len_target;
7083+ int rc = 0;
7084+ int bytes_returned = 0;
7085+
7086+ cFYI(1, ("In Create Hard link Unix style"));
7087+createHardLinkRetry:
7088+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7089+ (void **) &pSMBr);
7090+ if (rc)
7091+ return rc;
7092+
7093+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7094+ name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
7095+ /* find define for this maxpathcomponent */
7096+ , nls_codepage);
7097+ name_len++; /* trailing null */
7098+ name_len *= 2;
7099+
7100+ } else { /* BB improve the check for buffer overruns BB */
7101+ name_len = strnlen(toName, 530);
7102+ name_len++; /* trailing null */
7103+ strncpy(pSMB->FileName, toName, name_len);
7104+ }
7105+ pSMB->ParameterCount = 6 + name_len;
7106+ pSMB->MaxSetupCount = 0;
7107+ pSMB->Reserved = 0;
7108+ pSMB->Flags = 0;
7109+ pSMB->Timeout = 0;
7110+ pSMB->Reserved2 = 0;
7111+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
7112+ InformationLevel) - 4;
7113+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
7114+
7115+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
7116+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7117+ name_len_target =
7118+ cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
7119+ /* find define for this maxpathcomponent */
7120+ , nls_codepage);
7121+ name_len_target++; /* trailing null */
7122+ name_len_target *= 2;
7123+ } else { /* BB improve the check for buffer overruns BB */
7124+ name_len_target = strnlen(fromName, 530);
7125+ name_len_target++; /* trailing null */
7126+ strncpy(data_offset, fromName, name_len_target);
7127+ }
7128+
7129+ pSMB->DataCount = name_len_target;
7130+ pSMB->MaxParameterCount = cpu_to_le16(2);
7131+ /* BB find exact max on data count below from sess*/
7132+ pSMB->MaxDataCount = cpu_to_le16(1000);
7133+ pSMB->SetupCount = 1;
7134+ pSMB->Reserved3 = 0;
7135+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
7136+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
7137+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7138+ pSMB->TotalParameterCount = pSMB->ParameterCount;
7139+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
7140+ pSMB->TotalDataCount = pSMB->DataCount;
7141+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
7142+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
7143+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
7144+ pSMB->Reserved4 = 0;
7145+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7146+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7147+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7148+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7149+ if (rc) {
7150+ cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
7151+ }
7152+
7153+ if (pSMB)
7154+ cifs_buf_release(pSMB);
7155+ if (rc == -EAGAIN)
7156+ goto createHardLinkRetry;
7157+
7158+ return rc;
7159+}
7160+
7161+int
7162+CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
7163+ const char *fromName, const char *toName,
7164+ const struct nls_table *nls_codepage)
7165+{
7166+ int rc = 0;
7167+ NT_RENAME_REQ *pSMB = NULL;
7168+ RENAME_RSP *pSMBr = NULL;
7169+ int bytes_returned;
7170+ int name_len, name_len2;
7171+
7172+ cFYI(1, ("In CIFSCreateHardLink"));
7173+winCreateHardLinkRetry:
7174+
7175+ rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
7176+ (void **) &pSMBr);
7177+ if (rc)
7178+ return rc;
7179+
7180+ pSMB->SearchAttributes =
7181+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7182+ ATTR_DIRECTORY);
7183+ pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
7184+ pSMB->ClusterCount = 0;
7185+
7186+ pSMB->BufferFormat = 0x04;
7187+
7188+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7189+ name_len =
7190+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
7191+ /* find define for this maxpathcomponent */
7192+ , nls_codepage);
7193+ name_len++; /* trailing null */
7194+ name_len *= 2;
7195+ pSMB->OldFileName[name_len] = 0; /* pad */
7196+ pSMB->OldFileName[name_len + 1] = 0x04;
7197+ name_len2 =
7198+ cifs_strtoUCS((wchar_t *) & pSMB->
7199+ OldFileName[name_len + 2], toName, 530,
7200+ nls_codepage);
7201+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
7202+ name_len2 *= 2; /* convert to bytes */
7203+ } else { /* BB improve the check for buffer overruns BB */
7204+ name_len = strnlen(fromName, 530);
7205+ name_len++; /* trailing null */
7206+ strncpy(pSMB->OldFileName, fromName, name_len);
7207+ name_len2 = strnlen(toName, 530);
7208+ name_len2++; /* trailing null */
7209+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
7210+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
7211+ name_len2++; /* trailing null */
7212+ name_len2++; /* signature byte */
7213+ }
7214+
7215+ pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
7216+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7217+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7218+
7219+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7220+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7221+ if (rc) {
7222+ cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
7223+ }
7224+ if (pSMB)
7225+ cifs_buf_release(pSMB);
7226+ if (rc == -EAGAIN)
7227+ goto winCreateHardLinkRetry;
7228+
7229+ return rc;
7230+}
7231+
7232+int
7233+CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
7234+ const unsigned char *searchName,
7235+ char *symlinkinfo, const int buflen,
7236+ const struct nls_table *nls_codepage)
7237+{
7238+/* SMB_QUERY_FILE_UNIX_LINK */
7239+ TRANSACTION2_QPI_REQ *pSMB = NULL;
7240+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
7241+ int rc = 0;
7242+ int bytes_returned;
7243+ int name_len;
7244+
7245+ cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
7246+
7247+querySymLinkRetry:
7248+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7249+ (void **) &pSMBr);
7250+ if (rc)
7251+ return rc;
7252+
7253+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7254+ name_len =
7255+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7256+ /* find define for this maxpathcomponent */
7257+ , nls_codepage);
7258+ name_len++; /* trailing null */
7259+ name_len *= 2;
7260+ } else { /* BB improve the check for buffer overruns BB */
7261+ name_len = strnlen(searchName, 530);
7262+ name_len++; /* trailing null */
7263+ strncpy(pSMB->FileName, searchName, name_len);
7264+ }
7265+
7266+ pSMB->TotalParameterCount =
7267+ 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
7268+ pSMB->TotalDataCount = 0;
7269+ pSMB->MaxParameterCount = cpu_to_le16(2);
7270+ /* BB find exact max data count below from sess structure BB */
7271+ pSMB->MaxDataCount = cpu_to_le16(4000);
7272+ pSMB->MaxSetupCount = 0;
7273+ pSMB->Reserved = 0;
7274+ pSMB->Flags = 0;
7275+ pSMB->Timeout = 0;
7276+ pSMB->Reserved2 = 0;
7277+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
7278+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7279+ pSMB->DataCount = 0;
7280+ pSMB->DataOffset = 0;
7281+ pSMB->SetupCount = 1;
7282+ pSMB->Reserved3 = 0;
7283+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7284+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7285+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7286+ pSMB->ParameterCount = pSMB->TotalParameterCount;
7287+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
7288+ pSMB->Reserved4 = 0;
7289+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7290+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7291+
7292+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7293+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7294+ if (rc) {
7295+ cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
7296+ } else { /* decode response */
7297+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7298+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
7299+ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
7300+ /* BB also check enough total bytes returned */
7301+ rc = -EIO; /* bad smb */
7302+ else {
7303+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
7304+ name_len = UniStrnlen((wchar_t *) ((char *)
7305+ &pSMBr->hdr.Protocol +pSMBr->DataOffset),
7306+ min_t(const int, buflen,pSMBr->DataCount) / 2);
7307+ cifs_strfromUCS_le(symlinkinfo,
7308+ (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
7309+ pSMBr->DataOffset),
7310+ name_len, nls_codepage);
7311+ } else {
7312+ strncpy(symlinkinfo,
7313+ (char *) &pSMBr->hdr.Protocol +
7314+ pSMBr->DataOffset,
7315+ min_t(const int, buflen, pSMBr->DataCount));
7316+ }
7317+ symlinkinfo[buflen] = 0;
7318+ /* just in case so calling code does not go off the end of buffer */
7319+ }
7320+ }
7321+ if (pSMB)
7322+ cifs_buf_release(pSMB);
7323+ if (rc == -EAGAIN)
7324+ goto querySymLinkRetry;
7325+ return rc;
7326+}
7327+
7328+
7329+
7330+int
7331+CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
7332+ const unsigned char *searchName,
7333+ char *symlinkinfo, const int buflen,__u16 fid,
7334+ const struct nls_table *nls_codepage)
7335+{
7336+ int rc = 0;
7337+ int bytes_returned;
7338+ int name_len;
7339+ struct smb_com_transaction_ioctl_req * pSMB;
7340+ struct smb_com_transaction_ioctl_rsp * pSMBr;
7341+
7342+ cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
7343+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
7344+ (void **) &pSMBr);
7345+ if (rc)
7346+ return rc;
7347+
7348+ pSMB->TotalParameterCount = 0 ;
7349+ pSMB->TotalDataCount = 0;
7350+ pSMB->MaxParameterCount = cpu_to_le32(2);
7351+ /* BB find exact data count max from sess structure BB */
7352+ pSMB->MaxDataCount = cpu_to_le32(4000);
7353+ pSMB->MaxSetupCount = 4;
7354+ pSMB->Reserved = 0;
7355+ pSMB->ParameterOffset = 0;
7356+ pSMB->DataCount = 0;
7357+ pSMB->DataOffset = 0;
7358+ pSMB->SetupCount = 4;
7359+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
7360+ pSMB->ParameterCount = pSMB->TotalParameterCount;
7361+ pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
7362+ pSMB->IsFsctl = 1; /* FSCTL */
7363+ pSMB->IsRootFlag = 0;
7364+ pSMB->Fid = fid; /* file handle always le */
7365+ pSMB->ByteCount = 0;
7366+
7367+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7368+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7369+ if (rc) {
7370+ cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
7371+ } else { /* decode response */
7372+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7373+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
7374+ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
7375+ /* BB also check enough total bytes returned */
7376+ rc = -EIO; /* bad smb */
7377+ else {
7378+ if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
7379+ /* could also validate reparse tag && better check name length */
7380+ struct reparse_data * reparse_buf = (struct reparse_data *)
7381+ ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
7382+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
7383+ name_len = UniStrnlen((wchar_t *)
7384+ (reparse_buf->LinkNamesBuf +
7385+ reparse_buf->TargetNameOffset),
7386+ min(buflen/2, reparse_buf->TargetNameLen / 2));
7387+ cifs_strfromUCS_le(symlinkinfo,
7388+ (wchar_t *) (reparse_buf->LinkNamesBuf +
7389+ reparse_buf->TargetNameOffset),
7390+ name_len, nls_codepage);
7391+ } else { /* ASCII names */
7392+ strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
7393+ reparse_buf->TargetNameOffset,
7394+ min_t(const int, buflen, reparse_buf->TargetNameLen));
7395+ }
7396+ } else {
7397+ rc = -EIO;
7398+ cFYI(1,("Invalid return data count on get reparse info ioctl"));
7399+ }
7400+ symlinkinfo[buflen] = 0; /* just in case so the caller
7401+ does not go off the end of the buffer */
7402+ cFYI(1,("readlink result - %s ",symlinkinfo));
7403+ }
7404+ }
7405+ if (pSMB)
7406+ cifs_buf_release(pSMB);
7407+
7408+ /* Note: On -EAGAIN error only caller can retry on handle based calls
7409+ since file handle passed in no longer valid */
7410+
7411+ return rc;
7412+}
7413+
7414+int
7415+CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
7416+ const unsigned char *searchName,
7417+ FILE_ALL_INFO * pFindData,
7418+ const struct nls_table *nls_codepage)
7419+{
7420+/* level 263 SMB_QUERY_FILE_ALL_INFO */
7421+ TRANSACTION2_QPI_REQ *pSMB = NULL;
7422+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
7423+ int rc = 0;
7424+ int bytes_returned;
7425+ int name_len;
7426+
7427+ cFYI(1, ("In QPathInfo path %s", searchName));
7428+QPathInfoRetry:
7429+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7430+ (void **) &pSMBr);
7431+ if (rc)
7432+ return rc;
7433+
7434+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7435+ name_len =
7436+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7437+ /* find define for this maxpathcomponent */
7438+ , nls_codepage);
7439+ name_len++; /* trailing null */
7440+ name_len *= 2;
7441+ } else { /* BB improve the check for buffer overruns BB */
7442+ name_len = strnlen(searchName, 530);
7443+ name_len++; /* trailing null */
7444+ strncpy(pSMB->FileName, searchName, name_len);
7445+ }
7446+
7447+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
7448+ name_len /* includes null */ ;
7449+ pSMB->TotalDataCount = 0;
7450+ pSMB->MaxParameterCount = cpu_to_le16(2);
7451+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7452+ pSMB->MaxSetupCount = 0;
7453+ pSMB->Reserved = 0;
7454+ pSMB->Flags = 0;
7455+ pSMB->Timeout = 0;
7456+ pSMB->Reserved2 = 0;
7457+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
7458+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7459+ pSMB->DataCount = 0;
7460+ pSMB->DataOffset = 0;
7461+ pSMB->SetupCount = 1;
7462+ pSMB->Reserved3 = 0;
7463+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7464+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7465+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7466+ pSMB->ParameterCount = pSMB->TotalParameterCount;
7467+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
7468+ pSMB->Reserved4 = 0;
7469+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7470+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7471+
7472+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7473+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7474+ if (rc) {
7475+ cFYI(1, ("Send error in QPathInfo = %d", rc));
7476+ } else { /* decode response */
7477+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7478+ /* BB also check enough total bytes returned */
7479+ /* BB we need to improve the validity checking
7480+ of these trans2 responses */
7481+ if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
7482+ rc = -EIO; /* bad smb */
7483+ else if (pFindData){
7484+ memcpy((char *) pFindData,
7485+ (char *) &pSMBr->hdr.Protocol +
7486+ pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
7487+ } else
7488+ rc = -ENOMEM;
7489+ }
7490+ if (pSMB)
7491+ cifs_buf_release(pSMB);
7492+ if (rc == -EAGAIN)
7493+ goto QPathInfoRetry;
7494+
7495+ return rc;
7496+}
7497+
7498+int
7499+CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
7500+ const unsigned char *searchName,
7501+ FILE_UNIX_BASIC_INFO * pFindData,
7502+ const struct nls_table *nls_codepage)
7503+{
7504+/* SMB_QUERY_FILE_UNIX_BASIC */
7505+ TRANSACTION2_QPI_REQ *pSMB = NULL;
7506+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
7507+ int rc = 0;
7508+ int bytes_returned = 0;
7509+ int name_len;
7510+
7511+ cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
7512+UnixQPathInfoRetry:
7513+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7514+ (void **) &pSMBr);
7515+ if (rc)
7516+ return rc;
7517+
7518+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7519+ name_len =
7520+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7521+ /* find define for this maxpathcomponent */
7522+ , nls_codepage);
7523+ name_len++; /* trailing null */
7524+ name_len *= 2;
7525+ } else { /* BB improve the check for buffer overruns BB */
7526+ name_len = strnlen(searchName, 530);
7527+ name_len++; /* trailing null */
7528+ strncpy(pSMB->FileName, searchName, name_len);
7529+ }
7530+
7531+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
7532+ name_len /* includes null */ ;
7533+ pSMB->TotalDataCount = 0;
7534+ pSMB->MaxParameterCount = cpu_to_le16(2);
7535+ /* BB find exact max SMB PDU from sess structure BB */
7536+ pSMB->MaxDataCount = cpu_to_le16(4000);
7537+ pSMB->MaxSetupCount = 0;
7538+ pSMB->Reserved = 0;
7539+ pSMB->Flags = 0;
7540+ pSMB->Timeout = 0;
7541+ pSMB->Reserved2 = 0;
7542+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
7543+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7544+ pSMB->DataCount = 0;
7545+ pSMB->DataOffset = 0;
7546+ pSMB->SetupCount = 1;
7547+ pSMB->Reserved3 = 0;
7548+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7549+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7550+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7551+ pSMB->ParameterCount = pSMB->TotalParameterCount;
7552+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
7553+ pSMB->Reserved4 = 0;
7554+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7555+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7556+
7557+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7558+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7559+ if (rc) {
7560+ cFYI(1, ("Send error in QPathInfo = %d", rc));
7561+ } else { /* decode response */
7562+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7563+ /* BB also check if enough total bytes returned */
7564+ if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
7565+ (pSMBr->DataOffset > 512) ||
7566+ (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
7567+ cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
7568+ (int)pSMBr->DataOffset,bytes_returned));
7569+ rc = -EIO; /* bad smb */
7570+ } else {
7571+ memcpy((char *) pFindData,
7572+ (char *) &pSMBr->hdr.Protocol +
7573+ pSMBr->DataOffset,
7574+ sizeof (FILE_UNIX_BASIC_INFO));
7575+ }
7576+ }
7577+ if (pSMB)
7578+ cifs_buf_release(pSMB);
7579+ if (rc == -EAGAIN)
7580+ goto UnixQPathInfoRetry;
7581+
7582+ return rc;
7583+}
7584+
7585+int
7586+CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
7587+ const char *searchName, FILE_ALL_INFO * findData,
7588+ const struct nls_table *nls_codepage)
7589+{
7590+/* level 257 SMB_ */
7591+ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
7592+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
7593+ int rc = 0;
7594+ int bytes_returned;
7595+ int name_len;
7596+
7597+ cFYI(1, ("In FindUnique"));
7598+findUniqueRetry:
7599+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7600+ (void **) &pSMBr);
7601+ if (rc)
7602+ return rc;
7603+
7604+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7605+ name_len =
7606+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7607+ /* find define for this maxpathcomponent */
7608+ , nls_codepage);
7609+ name_len++; /* trailing null */
7610+ name_len *= 2;
7611+ } else { /* BB improve the check for buffer overruns BB */
7612+ name_len = strnlen(searchName, 530);
7613+ name_len++; /* trailing null */
7614+ strncpy(pSMB->FileName, searchName, name_len);
7615+ }
7616+
7617+ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
7618+ pSMB->TotalDataCount = 0; /* no EAs */
7619+ pSMB->MaxParameterCount = cpu_to_le16(2);
7620+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7621+ pSMB->MaxSetupCount = 0;
7622+ pSMB->Reserved = 0;
7623+ pSMB->Flags = 0;
7624+ pSMB->Timeout = 0;
7625+ pSMB->Reserved2 = 0;
7626+ pSMB->ParameterOffset = cpu_to_le16(
7627+ offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
7628+ pSMB->DataCount = 0;
7629+ pSMB->DataOffset = 0;
7630+ pSMB->SetupCount = 1; /* one byte, no need to le convert */
7631+ pSMB->Reserved3 = 0;
7632+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
7633+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7634+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
7635+ pSMB->ParameterCount = pSMB->TotalParameterCount;
7636+ pSMB->SearchAttributes =
7637+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7638+ ATTR_DIRECTORY);
7639+ pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
7640+ pSMB->SearchFlags = cpu_to_le16(1);
7641+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7642+ pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
7643+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7644+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7645+
7646+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7647+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7648+
7649+ if (rc) {
7650+ cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
7651+ } else { /* decode response */
7652+
7653+ /* BB fill in */
7654+ }
7655+ if (pSMB)
7656+ cifs_buf_release(pSMB);
7657+ if (rc == -EAGAIN)
7658+ goto findUniqueRetry;
7659+
7660+ return rc;
7661+}
7662+
7663+int
7664+CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
7665+ const char *searchName, FILE_DIRECTORY_INFO * findData,
7666+ T2_FFIRST_RSP_PARMS * findParms,
7667+ const struct nls_table *nls_codepage, int *pUnicodeFlag,
7668+ int *pUnixFlag)
7669+{
7670+/* level 257 SMB_ */
7671+ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
7672+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
7673+ char *response_data;
7674+ int rc = 0;
7675+ int bytes_returned;
7676+ int name_len;
7677+
7678+ cFYI(1, ("In FindFirst"));
7679+findFirstRetry:
7680+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7681+ (void **) &pSMBr);
7682+ if (rc)
7683+ return rc;
7684+
7685+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7686+ name_len =
7687+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7688+ /* find define for this maxpathcomponent */
7689+ , nls_codepage);
7690+ name_len++; /* trailing null */
7691+ name_len *= 2;
7692+ } else { /* BB improve the check for buffer overruns BB */
7693+ name_len = strnlen(searchName, 530);
7694+ name_len++; /* trailing null */
7695+ strncpy(pSMB->FileName, searchName, name_len);
7696+ }
7697+
7698+ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
7699+ pSMB->TotalDataCount = 0; /* no EAs */
7700+ pSMB->MaxParameterCount = cpu_to_le16(10);
7701+ pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
7702+ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
7703+ pSMB->MaxSetupCount = 0;
7704+ pSMB->Reserved = 0;
7705+ pSMB->Flags = 0;
7706+ pSMB->Timeout = 0;
7707+ pSMB->Reserved2 = 0;
7708+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7709+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7710+ pSMB->ParameterCount = pSMB->TotalParameterCount;
7711+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
7712+ smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
7713+ pSMB->DataCount = 0;
7714+ pSMB->DataOffset = 0;
7715+ pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
7716+ pSMB->Reserved3 = 0;
7717+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
7718+ pSMB->SearchAttributes =
7719+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7720+ ATTR_DIRECTORY);
7721+ pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
7722+ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
7723+
7724+ /* test for Unix extensions */
7725+ if (tcon->ses->capabilities & CAP_UNIX) {
7726+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
7727+ *pUnixFlag = TRUE;
7728+ } else {
7729+ pSMB->InformationLevel =
7730+ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7731+ *pUnixFlag = FALSE;
7732+ }
7733+ pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
7734+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7735+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7736+
7737+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7738+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7739+
7740+ if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
7741+ cFYI(1, ("Error in FindFirst = %d", rc));
7742+ } else { /* decode response */
7743+ /* BB add safety checks for these memcpys */
7744+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
7745+ *pUnicodeFlag = TRUE;
7746+ else
7747+ *pUnicodeFlag = FALSE;
7748+ memcpy(findParms,
7749+ (char *) &pSMBr->hdr.Protocol +
7750+ le16_to_cpu(pSMBr->ParameterOffset),
7751+ sizeof (T2_FFIRST_RSP_PARMS));
7752+ /* search handle can stay LE and EAoffset not needed so not converted */
7753+ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
7754+ findParms->LastNameOffset =
7755+ le16_to_cpu(findParms->LastNameOffset);
7756+ findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
7757+ response_data =
7758+ (char *) &pSMBr->hdr.Protocol +
7759+ le16_to_cpu(pSMBr->DataOffset);
7760+ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
7761+ }
7762+ if (pSMB)
7763+ cifs_buf_release(pSMB);
7764+
7765+ if (rc == -EAGAIN)
7766+ goto findFirstRetry;
7767+
7768+ return rc;
7769+}
7770+
7771+int
7772+CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
7773+ FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
7774+ const __u16 searchHandle, char * resume_file_name, int name_len,
7775+ __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
7776+{
7777+/* level 257 SMB_ */
7778+ TRANSACTION2_FNEXT_REQ *pSMB = NULL;
7779+ TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
7780+ char *response_data;
7781+ int rc = 0;
7782+ int bytes_returned;
7783+
7784+ cFYI(1, ("In FindNext"));
7785+
7786+ if(resume_file_name == NULL) {
7787+ return -EIO;
7788+ }
7789+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7790+ (void **) &pSMBr);
7791+ if (rc)
7792+ return rc;
7793+
7794+ pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
7795+ pSMB->TotalDataCount = 0; /* no EAs */
7796+ pSMB->MaxParameterCount = cpu_to_le16(8);
7797+ pSMB->MaxDataCount =
7798+ cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
7799+ pSMB->MaxSetupCount = 0;
7800+ pSMB->Reserved = 0;
7801+ pSMB->Flags = 0;
7802+ pSMB->Timeout = 0;
7803+ pSMB->Reserved2 = 0;
7804+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
7805+ struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
7806+ pSMB->DataCount = 0;
7807+ pSMB->DataOffset = 0;
7808+ pSMB->SetupCount = 1;
7809+ pSMB->Reserved3 = 0;
7810+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
7811+ pSMB->SearchHandle = searchHandle; /* always kept as le */
7812+ findParms->SearchCount = 0; /* set to zero in case of error */
7813+ pSMB->SearchCount =
7814+ cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
7815+ /* test for Unix extensions */
7816+ if (tcon->ses->capabilities & CAP_UNIX) {
7817+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
7818+ *pUnixFlag = TRUE;
7819+ } else {
7820+ pSMB->InformationLevel =
7821+ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7822+ *pUnixFlag = FALSE;
7823+ }
7824+ pSMB->ResumeKey = resume_key;
7825+ pSMB->SearchFlags =
7826+ cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
7827+ /* BB add check to make sure we do not cross end of smb */
7828+ if(name_len < CIFS_MAX_MSGSIZE) {
7829+ memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
7830+ pSMB->ByteCount += name_len;
7831+ }
7832+ pSMB->TotalParameterCount += name_len;
7833+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7834+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7835+ pSMB->ParameterCount = pSMB->TotalParameterCount;
7836+ /* BB improve error handling here */
7837+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7838+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7839+
7840+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7841+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7842+
7843+ if (rc) {
7844+ if (rc == -EBADF)
7845+ rc = 0; /* search probably was closed at end of search above */
7846+ else
7847+ cFYI(1, ("FindNext returned = %d", rc));
7848+ } else { /* decode response */
7849+ /* BB add safety checks for these memcpys */
7850+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
7851+ *pUnicodeFlag = TRUE;
7852+ else
7853+ *pUnicodeFlag = FALSE;
7854+ memcpy(findParms,
7855+ (char *) &pSMBr->hdr.Protocol +
7856+ le16_to_cpu(pSMBr->ParameterOffset),
7857+ sizeof (T2_FNEXT_RSP_PARMS));
7858+ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
7859+ findParms->LastNameOffset =
7860+ le16_to_cpu(findParms->LastNameOffset);
7861+ findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
7862+ response_data =
7863+ (char *) &pSMBr->hdr.Protocol +
7864+ le16_to_cpu(pSMBr->DataOffset);
7865+ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
7866+ }
7867+ if (pSMB)
7868+ cifs_buf_release(pSMB);
7869+
7870+ /* Note: On -EAGAIN error only caller can retry on handle based calls
7871+ since file handle passed in no longer valid */
7872+
7873+ return rc;
7874+}
7875+
7876+int
7877+CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
7878+{
7879+ int rc = 0;
7880+ FINDCLOSE_REQ *pSMB = NULL;
7881+ CLOSE_RSP *pSMBr = NULL;
7882+ int bytes_returned;
7883+
7884+ cFYI(1, ("In CIFSSMBFindClose"));
7885+ rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
7886+ (void **) &pSMBr);
7887+ /* no sense returning error if session restarted
7888+ file handle has been closed */
7889+ if(rc == -EAGAIN)
7890+ return 0;
7891+ if (rc)
7892+ return rc;
7893+
7894+ pSMB->FileID = searchHandle;
7895+ pSMB->ByteCount = 0;
7896+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7897+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7898+ if (rc) {
7899+ cERROR(1, ("Send error in FindClose = %d", rc));
7900+ }
7901+ if (pSMB)
7902+ cifs_buf_release(pSMB);
7903+
7904+ /* Since session is dead, search handle closed on server already */
7905+ if (rc == -EAGAIN)
7906+ rc = 0;
7907+
7908+ return rc;
7909+}
7910+
7911+int
7912+CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
7913+ const unsigned char *searchName,
7914+ unsigned char **targetUNCs,
7915+ unsigned int *number_of_UNC_in_array,
7916+ const struct nls_table *nls_codepage)
7917+{
7918+/* TRANS2_GET_DFS_REFERRAL */
7919+ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
7920+ TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
7921+ struct dfs_referral_level_3 * referrals = NULL;
7922+ int rc = 0;
7923+ int bytes_returned;
7924+ int name_len;
7925+ unsigned int i;
7926+ char * temp;
7927+ *number_of_UNC_in_array = 0;
7928+ *targetUNCs = NULL;
7929+
7930+ cFYI(1, ("In GetDFSRefer the path %s", searchName));
7931+ if (ses == NULL)
7932+ return -ENODEV;
7933+getDFSRetry:
7934+ rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
7935+ (void **) &pSMBr);
7936+ if (rc)
7937+ return rc;
7938+
7939+ pSMB->hdr.Tid = ses->ipc_tid;
7940+ pSMB->hdr.Uid = ses->Suid;
7941+ if (ses->capabilities & CAP_STATUS32) {
7942+ pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
7943+ }
7944+ if (ses->capabilities & CAP_DFS) {
7945+ pSMB->hdr.Flags2 |= SMBFLG2_DFS;
7946+ }
7947+
7948+ if (ses->capabilities & CAP_UNICODE) {
7949+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
7950+ name_len =
7951+ cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
7952+ searchName, 530
7953+ /* find define for this maxpathcomponent */
7954+ , nls_codepage);
7955+ name_len++; /* trailing null */
7956+ name_len *= 2;
7957+ } else { /* BB improve the check for buffer overruns BB */
7958+ name_len = strnlen(searchName, 530);
7959+ name_len++; /* trailing null */
7960+ strncpy(pSMB->RequestFileName, searchName, name_len);
7961+ }
7962+
7963+ pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
7964+ pSMB->TotalDataCount = 0;
7965+ pSMB->DataCount = 0;
7966+ pSMB->DataOffset = 0;
7967+ pSMB->MaxParameterCount = 0;
7968+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7969+ pSMB->MaxSetupCount = 0;
7970+ pSMB->Reserved = 0;
7971+ pSMB->Flags = 0;
7972+ pSMB->Timeout = 0;
7973+ pSMB->Reserved2 = 0;
7974+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
7975+ struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
7976+ pSMB->SetupCount = 1;
7977+ pSMB->Reserved3 = 0;
7978+ pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
7979+ pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
7980+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7981+ pSMB->TotalParameterCount = pSMB->ParameterCount;
7982+ pSMB->MaxReferralLevel = cpu_to_le16(3);
7983+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7984+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7985+
7986+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
7987+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7988+ if (rc) {
7989+ cFYI(1, ("Send error in GetDFSRefer = %d", rc));
7990+ } else { /* decode response */
7991+/* BB Add logic to parse referrals here */
7992+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7993+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
7994+ cFYI(1,
7995+ ("Decoding GetDFSRefer response. BCC: %d Offset %d",
7996+ pSMBr->ByteCount, pSMBr->DataOffset));
7997+ if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
7998+ rc = -EIO; /* bad smb */
7999+ else {
8000+ referrals =
8001+ (struct dfs_referral_level_3 *)
8002+ (8 /* sizeof start of data block */ +
8003+ pSMBr->DataOffset +
8004+ (char *) &pSMBr->hdr.Protocol);
8005+ 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));
8006+ /* BB This field is actually two bytes in from start of
8007+ data block so we could do safety check that DataBlock
8008+ begins at address of pSMBr->NumberOfReferrals */
8009+ *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
8010+
8011+ /* BB Fix below so can return more than one referral */
8012+ if(*number_of_UNC_in_array > 1)
8013+ *number_of_UNC_in_array = 1;
8014+
8015+ /* get the length of the strings describing refs */
8016+ name_len = 0;
8017+ for(i=0;i<*number_of_UNC_in_array;i++) {
8018+ /* make sure that DfsPathOffset not past end */
8019+ referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
8020+ if(referrals->DfsPathOffset > pSMBr->DataCount) {
8021+ /* if invalid referral, stop here and do
8022+ not try to copy any more */
8023+ *number_of_UNC_in_array = i;
8024+ break;
8025+ }
8026+ temp = ((char *)referrals) + referrals->DfsPathOffset;
8027+
8028+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
8029+ name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
8030+ } else {
8031+ name_len += strnlen(temp,pSMBr->DataCount);
8032+ }
8033+ referrals++;
8034+ /* BB add check that referral pointer does not fall off end PDU */
8035+
8036+ }
8037+ /* BB add check for name_len bigger than bcc */
8038+ *targetUNCs =
8039+ kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
8040+ /* copy the ref strings */
8041+ referrals =
8042+ (struct dfs_referral_level_3 *)
8043+ (8 /* sizeof data hdr */ +
8044+ pSMBr->DataOffset +
8045+ (char *) &pSMBr->hdr.Protocol);
8046+
8047+ for(i=0;i<*number_of_UNC_in_array;i++) {
8048+ temp = ((char *)referrals) + referrals->DfsPathOffset;
8049+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
8050+ cifs_strfromUCS_le(*targetUNCs,
8051+ (wchar_t *) temp, name_len, nls_codepage);
8052+ } else {
8053+ strncpy(*targetUNCs,temp,name_len);
8054+ }
8055+ /* BB update target_uncs pointers */
8056+ referrals++;
8057+ }
8058+ temp = *targetUNCs;
8059+ temp[name_len] = 0;
8060+ }
8061+
8062+ }
8063+ if (pSMB)
8064+ cifs_buf_release(pSMB);
8065+
8066+ if (rc == -EAGAIN)
8067+ goto getDFSRetry;
8068+
8069+ return rc;
8070+}
8071+
8072+int
8073+CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
8074+ struct statfs *FSData, const struct nls_table *nls_codepage)
8075+{
8076+/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
8077+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
8078+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8079+ FILE_SYSTEM_INFO *response_data;
8080+ int rc = 0;
8081+ int bytes_returned = 0;
8082+
8083+ cFYI(1, ("In QFSInfo"));
8084+QFSInfoRetry:
8085+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8086+ (void **) &pSMBr);
8087+ if (rc)
8088+ return rc;
8089+
8090+ pSMB->TotalParameterCount = 2; /* level */
8091+ pSMB->TotalDataCount = 0;
8092+ pSMB->MaxParameterCount = cpu_to_le16(2);
8093+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8094+ pSMB->MaxSetupCount = 0;
8095+ pSMB->Reserved = 0;
8096+ pSMB->Flags = 0;
8097+ pSMB->Timeout = 0;
8098+ pSMB->Reserved2 = 0;
8099+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8100+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8101+ pSMB->ParameterCount = pSMB->TotalParameterCount;
8102+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
8103+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8104+ pSMB->DataCount = 0;
8105+ pSMB->DataOffset = 0;
8106+ pSMB->SetupCount = 1;
8107+ pSMB->Reserved3 = 0;
8108+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8109+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
8110+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8111+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8112+
8113+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8114+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8115+ if (rc) {
8116+ cERROR(1, ("Send error in QFSInfo = %d", rc));
8117+ } else { /* decode response */
8118+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8119+ cFYI(1,
8120+ ("Decoding qfsinfo response. BCC: %d Offset %d",
8121+ pSMBr->ByteCount, pSMBr->DataOffset));
8122+ if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
8123+ rc = -EIO; /* bad smb */
8124+ else {
8125+ response_data =
8126+ (FILE_SYSTEM_INFO
8127+ *) (((char *) &pSMBr->hdr.Protocol) +
8128+ pSMBr->DataOffset);
8129+ FSData->f_bsize =
8130+ le32_to_cpu(response_data->BytesPerSector) *
8131+ le32_to_cpu(response_data->
8132+ SectorsPerAllocationUnit);
8133+ FSData->f_blocks =
8134+ le64_to_cpu(response_data->TotalAllocationUnits);
8135+ FSData->f_bfree = FSData->f_bavail =
8136+ le64_to_cpu(response_data->FreeAllocationUnits);
8137+ cFYI(1,
8138+ ("Blocks: %lld Free: %lld Block size %ld",
8139+ (unsigned long long)FSData->f_blocks,
8140+ (unsigned long long)FSData->f_bfree,
8141+ FSData->f_bsize));
8142+ }
8143+ }
8144+ if (pSMB)
8145+ cifs_buf_release(pSMB);
8146+
8147+ if (rc == -EAGAIN)
8148+ goto QFSInfoRetry;
8149+
8150+ return rc;
8151+}
8152+
8153+int
8154+CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
8155+ const struct nls_table *nls_codepage)
8156+{
8157+/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
8158+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
8159+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8160+ FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
8161+ int rc = 0;
8162+ int bytes_returned = 0;
8163+
8164+ cFYI(1, ("In QFSAttributeInfo"));
8165+QFSAttributeRetry:
8166+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8167+ (void **) &pSMBr);
8168+ if (rc)
8169+ return rc;
8170+
8171+ pSMB->TotalParameterCount = 2; /* level */
8172+ pSMB->TotalDataCount = 0;
8173+ pSMB->MaxParameterCount = cpu_to_le16(2);
8174+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8175+ pSMB->MaxSetupCount = 0;
8176+ pSMB->Reserved = 0;
8177+ pSMB->Flags = 0;
8178+ pSMB->Timeout = 0;
8179+ pSMB->Reserved2 = 0;
8180+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8181+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8182+ pSMB->ParameterCount = pSMB->TotalParameterCount;
8183+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
8184+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8185+ pSMB->DataCount = 0;
8186+ pSMB->DataOffset = 0;
8187+ pSMB->SetupCount = 1;
8188+ pSMB->Reserved3 = 0;
8189+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8190+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
8191+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8192+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8193+
8194+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8195+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8196+ if (rc) {
8197+ cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
8198+ } else { /* decode response */
8199+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8200+ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
8201+ rc = -EIO; /* bad smb */
8202+ } else {
8203+ response_data =
8204+ (FILE_SYSTEM_ATTRIBUTE_INFO
8205+ *) (((char *) &pSMBr->hdr.Protocol) +
8206+ pSMBr->DataOffset);
8207+ response_data->Attributes = le32_to_cpu(response_data->Attributes);
8208+ response_data->MaxPathNameComponentLength =
8209+ le32_to_cpu(response_data->MaxPathNameComponentLength);
8210+ response_data->FileSystemNameLen =
8211+ le32_to_cpu(response_data->FileSystemNameLen);
8212+ memcpy(&tcon->fsAttrInfo, response_data,
8213+ sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
8214+ }
8215+ }
8216+ if (pSMB)
8217+ cifs_buf_release(pSMB);
8218+
8219+ if (rc == -EAGAIN)
8220+ goto QFSAttributeRetry;
8221+
8222+ return rc;
8223+}
8224+
8225+int
8226+CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
8227+ const struct nls_table *nls_codepage)
8228+{
8229+/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
8230+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
8231+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8232+ FILE_SYSTEM_DEVICE_INFO *response_data;
8233+ int rc = 0;
8234+ int bytes_returned = 0;
8235+
8236+ cFYI(1, ("In QFSDeviceInfo"));
8237+QFSDeviceRetry:
8238+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8239+ (void **) &pSMBr);
8240+ if (rc)
8241+ return rc;
8242+
8243+ pSMB->TotalParameterCount = 2; /* level */
8244+ pSMB->TotalDataCount = 0;
8245+ pSMB->MaxParameterCount = cpu_to_le16(2);
8246+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8247+ pSMB->MaxSetupCount = 0;
8248+ pSMB->Reserved = 0;
8249+ pSMB->Flags = 0;
8250+ pSMB->Timeout = 0;
8251+ pSMB->Reserved2 = 0;
8252+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8253+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8254+ pSMB->ParameterCount = pSMB->TotalParameterCount;
8255+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
8256+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8257+
8258+ pSMB->DataCount = 0;
8259+ pSMB->DataOffset = 0;
8260+ pSMB->SetupCount = 1;
8261+ pSMB->Reserved3 = 0;
8262+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8263+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
8264+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8265+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8266+
8267+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8268+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8269+ if (rc) {
8270+ cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
8271+ } else { /* decode response */
8272+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8273+ if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
8274+ || (pSMBr->DataOffset > 512))
8275+ rc = -EIO; /* bad smb */
8276+ else {
8277+ response_data =
8278+ (FILE_SYSTEM_DEVICE_INFO
8279+ *) (((char *) &pSMBr->hdr.Protocol) +
8280+ pSMBr->DataOffset);
8281+ response_data->DeviceType =
8282+ le32_to_cpu(response_data->DeviceType);
8283+ response_data->DeviceCharacteristics =
8284+ le32_to_cpu(response_data->DeviceCharacteristics);
8285+ memcpy(&tcon->fsDevInfo, response_data,
8286+ sizeof (FILE_SYSTEM_DEVICE_INFO));
8287+ }
8288+ }
8289+ if (pSMB)
8290+ cifs_buf_release(pSMB);
8291+
8292+ if (rc == -EAGAIN)
8293+ goto QFSDeviceRetry;
8294+
8295+ return rc;
8296+}
8297+
8298+int
8299+CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
8300+ const struct nls_table *nls_codepage)
8301+{
8302+/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
8303+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
8304+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8305+ FILE_SYSTEM_UNIX_INFO *response_data;
8306+ int rc = 0;
8307+ int bytes_returned = 0;
8308+
8309+ cFYI(1, ("In QFSUnixInfo"));
8310+QFSUnixRetry:
8311+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8312+ (void **) &pSMBr);
8313+ if (rc)
8314+ return rc;
8315+
8316+ pSMB->ParameterCount = 2; /* level */
8317+ pSMB->TotalDataCount = 0;
8318+ pSMB->DataCount = 0;
8319+ pSMB->DataOffset = 0;
8320+ pSMB->MaxParameterCount = cpu_to_le16(2);
8321+ pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
8322+ pSMB->MaxSetupCount = 0;
8323+ pSMB->Reserved = 0;
8324+ pSMB->Flags = 0;
8325+ pSMB->Timeout = 0;
8326+ pSMB->Reserved2 = 0;
8327+ pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
8328+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8329+ pSMB->TotalParameterCount = pSMB->ParameterCount;
8330+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
8331+ smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8332+ pSMB->SetupCount = 1;
8333+ pSMB->Reserved3 = 0;
8334+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8335+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
8336+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8337+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8338+
8339+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8340+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8341+ if (rc) {
8342+ cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
8343+ } else { /* decode response */
8344+ pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
8345+ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
8346+ rc = -EIO; /* bad smb */
8347+ } else {
8348+ response_data =
8349+ (FILE_SYSTEM_UNIX_INFO
8350+ *) (((char *) &pSMBr->hdr.Protocol) +
8351+ pSMBr->DataOffset);
8352+ response_data->MajorVersionNumber =
8353+ le16_to_cpu(response_data->MajorVersionNumber);
8354+ response_data->MinorVersionNumber =
8355+ le16_to_cpu(response_data->MinorVersionNumber);
8356+ response_data->Capability =
8357+ le64_to_cpu(response_data->Capability);
8358+ memcpy(&tcon->fsUnixInfo, response_data,
8359+ sizeof (FILE_SYSTEM_UNIX_INFO));
8360+ }
8361+ }
8362+ if (pSMB)
8363+ cifs_buf_release(pSMB);
8364+
8365+ if (rc == -EAGAIN)
8366+ goto QFSUnixRetry;
8367+
8368+
8369+ return rc;
8370+}
8371+
8372+/* We can not use write of zero bytes trick to
8373+ set file size due to need for large file support. Also note that
8374+ this SetPathInfo is preferred to SetFileInfo based method in next
8375+ routine which is only needed to work around a sharing violation bug
8376+ in Samba which this routine can run into */
8377+
8378+int
8379+CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
8380+ __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
8381+{
8382+ struct smb_com_transaction2_spi_req *pSMB = NULL;
8383+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
8384+ struct file_end_of_file_info *parm_data;
8385+ int name_len;
8386+ int rc = 0;
8387+ int bytes_returned = 0;
8388+
8389+ cFYI(1, ("In SetEOF"));
8390+SetEOFRetry:
8391+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8392+ (void **) &pSMBr);
8393+ if (rc)
8394+ return rc;
8395+
8396+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8397+ name_len =
8398+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8399+ /* find define for this maxpathcomponent */
8400+ , nls_codepage);
8401+ name_len++; /* trailing null */
8402+ name_len *= 2;
8403+ } else { /* BB improve the check for buffer overruns BB */
8404+ name_len = strnlen(fileName, 530);
8405+ name_len++; /* trailing null */
8406+ strncpy(pSMB->FileName, fileName, name_len);
8407+ }
8408+ pSMB->ParameterCount = 6 + name_len;
8409+ pSMB->DataCount = sizeof (struct file_end_of_file_info);
8410+ pSMB->MaxParameterCount = cpu_to_le16(2);
8411+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
8412+ pSMB->MaxSetupCount = 0;
8413+ pSMB->Reserved = 0;
8414+ pSMB->Flags = 0;
8415+ pSMB->Timeout = 0;
8416+ pSMB->Reserved2 = 0;
8417+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8418+ InformationLevel) - 4;
8419+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8420+ if(SetAllocation) {
8421+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8422+ pSMB->InformationLevel =
8423+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
8424+ else
8425+ pSMB->InformationLevel =
8426+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
8427+ } else /* Set File Size */ {
8428+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8429+ pSMB->InformationLevel =
8430+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
8431+ else
8432+ pSMB->InformationLevel =
8433+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
8434+ }
8435+
8436+ parm_data =
8437+ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
8438+ pSMB->DataOffset);
8439+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8440+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8441+ pSMB->SetupCount = 1;
8442+ pSMB->Reserved3 = 0;
8443+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8444+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8445+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8446+ pSMB->TotalDataCount = pSMB->DataCount;
8447+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8448+ pSMB->TotalParameterCount = pSMB->ParameterCount;
8449+ pSMB->Reserved4 = 0;
8450+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8451+ parm_data->FileSize = cpu_to_le64(size);
8452+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8453+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8454+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8455+ if (rc) {
8456+ cFYI(1, ("SetPathInfo (file size) returned %d", rc));
8457+ }
8458+
8459+ if (pSMB)
8460+ cifs_buf_release(pSMB);
8461+
8462+ if (rc == -EAGAIN)
8463+ goto SetEOFRetry;
8464+
8465+ return rc;
8466+}
8467+
8468+int
8469+CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
8470+ __u16 fid, __u32 pid_of_opener, int SetAllocation)
8471+{
8472+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
8473+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
8474+ char *data_offset;
8475+ struct file_end_of_file_info *parm_data;
8476+ int rc = 0;
8477+ int bytes_returned = 0;
8478+ __u32 tmp;
8479+
8480+ cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
8481+ (long long)size));
8482+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8483+ (void **) &pSMBr);
8484+ if (rc)
8485+ return rc;
8486+
8487+ tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
8488+ so network fid will be valid */
8489+ pSMB->hdr.Pid = tmp & 0xFFFF;
8490+ tmp >>= 16;
8491+ pSMB->hdr.PidHigh = tmp & 0xFFFF;
8492+
8493+ pSMB->ParameterCount = 6;
8494+ pSMB->MaxSetupCount = 0;
8495+ pSMB->Reserved = 0;
8496+ pSMB->Flags = 0;
8497+ pSMB->Timeout = 0;
8498+ pSMB->Reserved2 = 0;
8499+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
8500+ Fid) - 4;
8501+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8502+
8503+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
8504+
8505+ pSMB->DataCount = sizeof(struct file_end_of_file_info);
8506+ pSMB->MaxParameterCount = cpu_to_le16(2);
8507+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
8508+ pSMB->SetupCount = 1;
8509+ pSMB->Reserved3 = 0;
8510+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
8511+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8512+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8513+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8514+ pSMB->TotalDataCount = pSMB->DataCount;
8515+ pSMB->TotalParameterCount = pSMB->ParameterCount;
8516+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8517+ parm_data =
8518+ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
8519+ pSMB->DataOffset);
8520+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
8521+ parm_data->FileSize = cpu_to_le64(size);
8522+ pSMB->Fid = fid;
8523+ if(SetAllocation) {
8524+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8525+ pSMB->InformationLevel =
8526+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
8527+ else
8528+ pSMB->InformationLevel =
8529+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
8530+ } else /* Set File Size */ {
8531+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8532+ pSMB->InformationLevel =
8533+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
8534+ else
8535+ pSMB->InformationLevel =
8536+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
8537+ }
8538+ pSMB->Reserved4 = 0;
8539+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8540+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8541+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8542+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8543+ if (rc) {
8544+ cFYI(1,
8545+ ("Send error in SetFileInfo (SetFileSize) = %d",
8546+ rc));
8547+ }
8548+
8549+ if (pSMB)
8550+ cifs_buf_release(pSMB);
8551+
8552+ /* Note: On -EAGAIN error only caller can retry on handle based calls
8553+ since file handle passed in no longer valid */
8554+
8555+ return rc;
8556+}
8557+
8558+int
8559+CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
8560+ FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
8561+{
8562+ TRANSACTION2_SPI_REQ *pSMB = NULL;
8563+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
8564+ int name_len;
8565+ int rc = 0;
8566+ int bytes_returned = 0;
8567+ char *data_offset;
8568+
8569+ cFYI(1, ("In SetTimes"));
8570+
8571+SetTimesRetry:
8572+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8573+ (void **) &pSMBr);
8574+ if (rc)
8575+ return rc;
8576+
8577+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8578+ name_len =
8579+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8580+ /* find define for this maxpathcomponent */
8581+ , nls_codepage);
8582+ name_len++; /* trailing null */
8583+ name_len *= 2;
8584+ } else { /* BB improve the check for buffer overruns BB */
8585+ name_len = strnlen(fileName, 530);
8586+ name_len++; /* trailing null */
8587+ strncpy(pSMB->FileName, fileName, name_len);
8588+ }
8589+
8590+ pSMB->ParameterCount = 6 + name_len;
8591+ pSMB->DataCount = sizeof (FILE_BASIC_INFO);
8592+ pSMB->MaxParameterCount = cpu_to_le16(2);
8593+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8594+ pSMB->MaxSetupCount = 0;
8595+ pSMB->Reserved = 0;
8596+ pSMB->Flags = 0;
8597+ pSMB->Timeout = 0;
8598+ pSMB->Reserved2 = 0;
8599+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8600+ InformationLevel) - 4;
8601+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8602+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
8603+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8604+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8605+ pSMB->SetupCount = 1;
8606+ pSMB->Reserved3 = 0;
8607+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8608+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8609+
8610+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8611+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8612+ pSMB->TotalDataCount = pSMB->DataCount;
8613+ pSMB->TotalParameterCount = pSMB->ParameterCount;
8614+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8615+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
8616+ else
8617+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
8618+ pSMB->Reserved4 = 0;
8619+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8620+ memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
8621+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8622+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8623+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8624+ if (rc) {
8625+ cFYI(1, ("SetPathInfo (times) returned %d", rc));
8626+ }
8627+
8628+ if (pSMB)
8629+ cifs_buf_release(pSMB);
8630+
8631+ if (rc == -EAGAIN)
8632+ goto SetTimesRetry;
8633+
8634+ return rc;
8635+}
8636+
8637+int
8638+CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
8639+ char *fileName, __u64 mode, __u64 uid, __u64 gid,
8640+ dev_t device, const struct nls_table *nls_codepage)
8641+{
8642+ TRANSACTION2_SPI_REQ *pSMB = NULL;
8643+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
8644+ int name_len;
8645+ int rc = 0;
8646+ int bytes_returned = 0;
8647+ FILE_UNIX_BASIC_INFO *data_offset;
8648+
8649+ cFYI(1, ("In SetUID/GID/Mode"));
8650+setPermsRetry:
8651+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8652+ (void **) &pSMBr);
8653+ if (rc)
8654+ return rc;
8655+
8656+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8657+ name_len =
8658+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8659+ /* find define for this maxpathcomponent */
8660+ , nls_codepage);
8661+ name_len++; /* trailing null */
8662+ name_len *= 2;
8663+ } else { /* BB improve the check for buffer overruns BB */
8664+ name_len = strnlen(fileName, 530);
8665+ name_len++; /* trailing null */
8666+ strncpy(pSMB->FileName, fileName, name_len);
8667+ }
8668+
8669+ pSMB->ParameterCount = 6 + name_len;
8670+ pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
8671+ pSMB->MaxParameterCount = cpu_to_le16(2);
8672+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8673+ pSMB->MaxSetupCount = 0;
8674+ pSMB->Reserved = 0;
8675+ pSMB->Flags = 0;
8676+ pSMB->Timeout = 0;
8677+ pSMB->Reserved2 = 0;
8678+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8679+ InformationLevel) - 4;
8680+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8681+ data_offset =
8682+ (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
8683+ pSMB->DataOffset);
8684+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8685+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8686+ pSMB->SetupCount = 1;
8687+ pSMB->Reserved3 = 0;
8688+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8689+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8690+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8691+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8692+ pSMB->TotalParameterCount = pSMB->ParameterCount;
8693+ pSMB->TotalDataCount = pSMB->DataCount;
8694+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
8695+ pSMB->Reserved4 = 0;
8696+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8697+ data_offset->Uid = cpu_to_le64(uid);
8698+ data_offset->Gid = cpu_to_le64(gid);
8699+ /* better to leave device as zero when it is */
8700+ data_offset->DevMajor = cpu_to_le64(MAJOR(device));
8701+ data_offset->DevMinor = cpu_to_le64(MINOR(device));
8702+ data_offset->Permissions = cpu_to_le64(mode);
8703+
8704+ if(S_ISREG(mode))
8705+ data_offset->Type = cpu_to_le32(UNIX_FILE);
8706+ else if(S_ISDIR(mode))
8707+ data_offset->Type = cpu_to_le32(UNIX_DIR);
8708+ else if(S_ISLNK(mode))
8709+ data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
8710+ else if(S_ISCHR(mode))
8711+ data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
8712+ else if(S_ISBLK(mode))
8713+ data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
8714+ else if(S_ISFIFO(mode))
8715+ data_offset->Type = cpu_to_le32(UNIX_FIFO);
8716+ else if(S_ISSOCK(mode))
8717+ data_offset->Type = cpu_to_le32(UNIX_SOCKET);
8718+
8719+
8720+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8721+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8722+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8723+ if (rc) {
8724+ cFYI(1, ("SetPathInfo (perms) returned %d", rc));
8725+ }
8726+
8727+ if (pSMB)
8728+ cifs_buf_release(pSMB);
8729+ if (rc == -EAGAIN)
8730+ goto setPermsRetry;
8731+ return rc;
8732+}
8733+
8734+int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
8735+ const int notify_subdirs, const __u16 netfid,
8736+ __u32 filter, const struct nls_table *nls_codepage)
8737+{
8738+ int rc = 0;
8739+ struct smb_com_transaction_change_notify_req * pSMB = NULL;
8740+ struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
8741+ int bytes_returned;
8742+
8743+ cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
8744+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
8745+ (void **) &pSMBr);
8746+ if (rc)
8747+ return rc;
8748+
8749+ pSMB->TotalParameterCount = 0 ;
8750+ pSMB->TotalDataCount = 0;
8751+ pSMB->MaxParameterCount = cpu_to_le32(2);
8752+ /* BB find exact data count max from sess structure BB */
8753+ pSMB->MaxDataCount = 0; /* same in little endian or be */
8754+ pSMB->MaxSetupCount = 4;
8755+ pSMB->Reserved = 0;
8756+ pSMB->ParameterOffset = 0;
8757+ pSMB->DataCount = 0;
8758+ pSMB->DataOffset = 0;
8759+ pSMB->SetupCount = 4; /* single byte does not need le conversion */
8760+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
8761+ pSMB->ParameterCount = pSMB->TotalParameterCount;
8762+ if(notify_subdirs)
8763+ pSMB->WatchTree = 1; /* one byte - no le conversion needed */
8764+ pSMB->Reserved2 = 0;
8765+ pSMB->CompletionFilter = cpu_to_le32(filter);
8766+ pSMB->Fid = netfid; /* file handle always le */
8767+ pSMB->ByteCount = 0;
8768+
8769+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8770+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8771+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8772+ if (rc) {
8773+ cFYI(1, ("Error in Notify = %d", rc));
8774+ }
8775+ if (pSMB)
8776+ cifs_buf_release(pSMB);
8777+/* if (rc == -EAGAIN)
8778+ goto NotifyRetry; */
8779+ return rc;
8780+}
8781+#ifdef CONFIG_CIFS_XATTR
8782+int
8783+CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
8784+ const unsigned char *searchName,
8785+ char * EAData, size_t size,
8786+ const struct nls_table *nls_codepage)
8787+{
8788+ /* BB assumes one setup word */
8789+ TRANSACTION2_QPI_REQ *pSMB = NULL;
8790+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
8791+ int rc = 0;
8792+ int bytes_returned;
8793+ int name_len;
8794+
8795+ cFYI(1, ("In Query All EAs path %s", searchName));
8796+QAllEAsRetry:
8797+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8798+ (void **) &pSMBr);
8799+ if (rc)
8800+ return rc;
8801+
8802+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8803+ name_len =
8804+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
8805+ /* find define for this maxpathcomponent */
8806+ , nls_codepage);
8807+ name_len++; /* trailing null */
8808+ name_len *= 2;
8809+ } else { /* BB improve the check for buffer overruns BB */
8810+ name_len = strnlen(searchName, 530);
8811+ name_len++; /* trailing null */
8812+ strncpy(pSMB->FileName, searchName, name_len);
8813+ }
8814+
8815+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
8816+ name_len /* includes null */ ;
8817+ pSMB->TotalDataCount = 0;
8818+ pSMB->MaxParameterCount = cpu_to_le16(2);
8819+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
8820+ pSMB->MaxSetupCount = 0;
8821+ pSMB->Reserved = 0;
8822+ pSMB->Flags = 0;
8823+ pSMB->Timeout = 0;
8824+ pSMB->Reserved2 = 0;
8825+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
8826+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
8827+ pSMB->DataCount = 0;
8828+ pSMB->DataOffset = 0;
8829+ pSMB->SetupCount = 1;
8830+ pSMB->Reserved3 = 0;
8831+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
8832+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8833+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8834+ pSMB->ParameterCount = pSMB->TotalParameterCount;
8835+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
8836+ pSMB->Reserved4 = 0;
8837+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8838+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8839+
8840+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8841+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8842+ if (rc) {
8843+ cFYI(1, ("Send error in QueryAllEAs = %d", rc));
8844+ } else { /* decode response */
8845+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8846+ /* BB also check enough total bytes returned */
8847+ /* BB we need to improve the validity checking
8848+ of these trans2 responses */
8849+ if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
8850+ rc = -EIO; /* bad smb */
8851+ /* else if (pFindData){
8852+ memcpy((char *) pFindData,
8853+ (char *) &pSMBr->hdr.Protocol +
8854+ pSMBr->DataOffset, kl);
8855+ }*/ else {
8856+ /* check that length of list is not more than bcc */
8857+ /* check that each entry does not go beyond length
8858+ of list */
8859+ /* check that each element of each entry does not
8860+ go beyond end of list */
8861+ struct fealist * ea_response_data;
8862+ rc = 0;
8863+ /* validate_trans2_offsets() */
8864+ /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
8865+ ea_response_data = (struct fealist *)
8866+ (((char *) &pSMBr->hdr.Protocol) +
8867+ pSMBr->DataOffset);
8868+ cFYI(1,("ea length %d",ea_response_data->list_len));
8869+ }
8870+ }
8871+ if (pSMB)
8872+ cifs_buf_release(pSMB);
8873+ if (rc == -EAGAIN)
8874+ goto QAllEAsRetry;
8875+
8876+ return rc;
8877+}
8878+#endif
8879--- /dev/null
8880+++ b/fs/cifs/cifs_unicode.c
8881@@ -0,0 +1,87 @@
8882+/*
8883+ * fs/cifs/cifs_unicode.c
8884+ *
8885+ * Copyright (c) International Business Machines Corp., 2000,2002
8886+ * Modified by Steve French (sfrench@us.ibm.com)
8887+ *
8888+ * This program is free software; you can redistribute it and/or modify
8889+ * it under the terms of the GNU General Public License as published by
8890+ * the Free Software Foundation; either version 2 of the License, or
8891+ * (at your option) any later version.
8892+ *
8893+ * This program is distributed in the hope that it will be useful,
8894+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8895+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8896+ * the GNU General Public License for more details.
8897+ *
8898+ * You should have received a copy of the GNU General Public License
8899+ * along with this program; if not, write to the Free Software
8900+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8901+ */
8902+#include <linux/fs.h>
8903+#include "cifs_unicode.h"
8904+#include "cifs_uniupr.h"
8905+#include "cifspdu.h"
8906+#include "cifs_debug.h"
8907+
8908+/*
8909+ * NAME: cifs_strfromUCS()
8910+ *
8911+ * FUNCTION: Convert little-endian unicode string to character string
8912+ *
8913+ */
8914+int
8915+cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
8916+ int len, const struct nls_table *codepage)
8917+{
8918+ int i;
8919+ int outlen = 0;
8920+
8921+ for (i = 0; (i < len) && from[i]; i++) {
8922+ int charlen;
8923+ /* 2.4.0 kernel or greater */
8924+ charlen =
8925+ codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
8926+ NLS_MAX_CHARSET_SIZE);
8927+ if (charlen > 0) {
8928+ outlen += charlen;
8929+ } else {
8930+ to[outlen++] = '?';
8931+ }
8932+ }
8933+ to[outlen] = 0;
8934+ return outlen;
8935+}
8936+
8937+/*
8938+ * NAME: cifs_strtoUCS()
8939+ *
8940+ * FUNCTION: Convert character string to unicode string
8941+ *
8942+ */
8943+int
8944+cifs_strtoUCS(wchar_t * to, const char *from, int len,
8945+ const struct nls_table *codepage)
8946+{
8947+ int charlen;
8948+ int i;
8949+
8950+ for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
8951+
8952+ /* works for 2.4.0 kernel or later */
8953+ charlen = codepage->char2uni(from, len, &to[i]);
8954+ if (charlen < 1) {
8955+ cERROR(1,
8956+ ("cifs_strtoUCS: char2uni returned %d",
8957+ charlen));
8958+ to[i] = cpu_to_le16(0x003f); /* a question mark */
8959+ charlen = 1;
8960+ }
8961+ to[i] = cpu_to_le16(to[i]);
8962+
8963+ }
8964+
8965+ to[i] = 0;
8966+ return i;
8967+}
8968+
8969--- /dev/null
8970+++ b/fs/cifs/cifs_unicode.h
8971@@ -0,0 +1,353 @@
8972+/*
8973+ * cifs_unicode: Unicode kernel case support
8974+ *
8975+ * Function:
8976+ * Convert a unicode character to upper or lower case using
8977+ * compressed tables.
8978+ *
8979+ * Copyright (c) International Business Machines Corp., 2000,2002
8980+ *
8981+ * This program is free software; you can redistribute it and/or modify
8982+ * it under the terms of the GNU General Public License as published by
8983+ * the Free Software Foundation; either version 2 of the License, or
8984+ * (at your option) any later version.
8985+ *
8986+ * This program is distributed in the hope that it will be useful,
8987+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8988+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8989+ * the GNU General Public License for more details.
8990+ *
8991+ * You should have received a copy of the GNU General Public License
8992+ * along with this program; if not, write to the Free Software
8993+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8994+ *
8995+ *
8996+ * Notes:
8997+ * These APIs are based on the C library functions. The semantics
8998+ * should match the C functions but with expanded size operands.
8999+ *
9000+ * The upper/lower functions are based on a table created by mkupr.
9001+ * This is a compressed table of upper and lower case conversion.
9002+ *
9003+ */
9004+
9005+#include <asm/byteorder.h>
9006+#include <linux/types.h>
9007+#include <linux/nls.h>
9008+
9009+#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
9010+
9011+/* Just define what we want from uniupr.h. We don't want to define the tables
9012+ * in each source file.
9013+ */
9014+#ifndef UNICASERANGE_DEFINED
9015+struct UniCaseRange {
9016+ wchar_t start;
9017+ wchar_t end;
9018+ signed char *table;
9019+};
9020+#endif /* UNICASERANGE_DEFINED */
9021+
9022+#ifndef UNIUPR_NOUPPER
9023+extern signed char CifsUniUpperTable[512];
9024+extern const struct UniCaseRange CifsUniUpperRange[];
9025+#endif /* UNIUPR_NOUPPER */
9026+
9027+#ifndef UNIUPR_NOLOWER
9028+extern signed char UniLowerTable[512];
9029+extern struct UniCaseRange UniLowerRange[];
9030+#endif /* UNIUPR_NOLOWER */
9031+
9032+#ifdef __KERNEL__
9033+int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
9034+int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
9035+#endif
9036+
9037+/*
9038+ * UniStrcat: Concatenate the second string to the first
9039+ *
9040+ * Returns:
9041+ * Address of the first string
9042+ */
9043+static inline wchar_t *
9044+UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
9045+{
9046+ wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
9047+
9048+ while (*ucs1++) ; /* To end of first string */
9049+ ucs1--; /* Return to the null */
9050+ while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
9051+ return anchor;
9052+}
9053+
9054+/*
9055+ * UniStrchr: Find a character in a string
9056+ *
9057+ * Returns:
9058+ * Address of first occurrence of character in string
9059+ * or NULL if the character is not in the string
9060+ */
9061+static inline wchar_t *
9062+UniStrchr(const wchar_t * ucs, wchar_t uc)
9063+{
9064+ while ((*ucs != uc) && *ucs)
9065+ ucs++;
9066+
9067+ if (*ucs == uc)
9068+ return (wchar_t *) ucs;
9069+ return NULL;
9070+}
9071+
9072+/*
9073+ * UniStrcmp: Compare two strings
9074+ *
9075+ * Returns:
9076+ * < 0: First string is less than second
9077+ * = 0: Strings are equal
9078+ * > 0: First string is greater than second
9079+ */
9080+static inline int
9081+UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
9082+{
9083+ while ((*ucs1 == *ucs2) && *ucs1) {
9084+ ucs1++;
9085+ ucs2++;
9086+ }
9087+ return (int) *ucs1 - (int) *ucs2;
9088+}
9089+
9090+/*
9091+ * UniStrcpy: Copy a string
9092+ */
9093+static inline wchar_t *
9094+UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
9095+{
9096+ wchar_t *anchor = ucs1; /* save the start of result string */
9097+
9098+ while ((*ucs1++ = *ucs2++)) ;
9099+ return anchor;
9100+}
9101+
9102+/*
9103+ * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
9104+ */
9105+static inline size_t
9106+UniStrlen(const wchar_t * ucs1)
9107+{
9108+ int i = 0;
9109+
9110+ while (*ucs1++)
9111+ i++;
9112+ return i;
9113+}
9114+
9115+/*
9116+ * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
9117+ */
9118+static inline size_t
9119+UniStrnlen(const wchar_t * ucs1, int maxlen)
9120+{
9121+ int i = 0;
9122+
9123+ while (*ucs1++) {
9124+ i++;
9125+ if (i >= maxlen)
9126+ break;
9127+ }
9128+ return i;
9129+}
9130+
9131+/*
9132+ * UniStrncat: Concatenate length limited string
9133+ */
9134+static inline wchar_t *
9135+UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9136+{
9137+ wchar_t *anchor = ucs1; /* save pointer to string 1 */
9138+
9139+ while (*ucs1++) ;
9140+ ucs1--; /* point to null terminator of s1 */
9141+ while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
9142+ ucs1++;
9143+ ucs2++;
9144+ }
9145+ *ucs1 = 0; /* Null terminate the result */
9146+ return (anchor);
9147+}
9148+
9149+/*
9150+ * UniStrncmp: Compare length limited string
9151+ */
9152+static inline int
9153+UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9154+{
9155+ if (!n)
9156+ return 0; /* Null strings are equal */
9157+ while ((*ucs1 == *ucs2) && *ucs1 && --n) {
9158+ ucs1++;
9159+ ucs2++;
9160+ }
9161+ return (int) *ucs1 - (int) *ucs2;
9162+}
9163+
9164+/*
9165+ * UniStrncmp_le: Compare length limited string - native to little-endian
9166+ */
9167+static inline int
9168+UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9169+{
9170+ if (!n)
9171+ return 0; /* Null strings are equal */
9172+ while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
9173+ ucs1++;
9174+ ucs2++;
9175+ }
9176+ return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
9177+}
9178+
9179+/*
9180+ * UniStrncpy: Copy length limited string with pad
9181+ */
9182+static inline wchar_t *
9183+UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9184+{
9185+ wchar_t *anchor = ucs1;
9186+
9187+ while (n-- && *ucs2) /* Copy the strings */
9188+ *ucs1++ = *ucs2++;
9189+
9190+ n++;
9191+ while (n--) /* Pad with nulls */
9192+ *ucs1++ = 0;
9193+ return anchor;
9194+}
9195+
9196+/*
9197+ * UniStrncpy_le: Copy length limited string with pad to little-endian
9198+ */
9199+static inline wchar_t *
9200+UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9201+{
9202+ wchar_t *anchor = ucs1;
9203+
9204+ while (n-- && *ucs2) /* Copy the strings */
9205+ *ucs1++ = __le16_to_cpu(*ucs2++);
9206+
9207+ n++;
9208+ while (n--) /* Pad with nulls */
9209+ *ucs1++ = 0;
9210+ return anchor;
9211+}
9212+
9213+/*
9214+ * UniStrstr: Find a string in a string
9215+ *
9216+ * Returns:
9217+ * Address of first match found
9218+ * NULL if no matching string is found
9219+ */
9220+static inline wchar_t *
9221+UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
9222+{
9223+ const wchar_t *anchor1 = ucs1;
9224+ const wchar_t *anchor2 = ucs2;
9225+
9226+ while (*ucs1) {
9227+ if (*ucs1 == *ucs2) { /* Partial match found */
9228+ ucs1++;
9229+ ucs2++;
9230+ } else {
9231+ if (!*ucs2) /* Match found */
9232+ return (wchar_t *) anchor1;
9233+ ucs1 = ++anchor1; /* No match */
9234+ ucs2 = anchor2;
9235+ }
9236+ }
9237+
9238+ if (!*ucs2) /* Both end together */
9239+ return (wchar_t *) anchor1; /* Match found */
9240+ return NULL; /* No match */
9241+}
9242+
9243+#ifndef UNIUPR_NOUPPER
9244+/*
9245+ * UniToupper: Convert a unicode character to upper case
9246+ */
9247+static inline wchar_t
9248+UniToupper(register wchar_t uc)
9249+{
9250+ register const struct UniCaseRange *rp;
9251+
9252+ if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */
9253+ return uc + CifsUniUpperTable[uc]; /* Use base tables */
9254+ } else {
9255+ rp = CifsUniUpperRange; /* Use range tables */
9256+ while (rp->start) {
9257+ if (uc < rp->start) /* Before start of range */
9258+ return uc; /* Uppercase = input */
9259+ if (uc <= rp->end) /* In range */
9260+ return uc + rp->table[uc - rp->start];
9261+ rp++; /* Try next range */
9262+ }
9263+ }
9264+ return uc; /* Past last range */
9265+}
9266+
9267+/*
9268+ * UniStrupr: Upper case a unicode string
9269+ */
9270+static inline wchar_t *
9271+UniStrupr(register wchar_t * upin)
9272+{
9273+ register wchar_t *up;
9274+
9275+ up = upin;
9276+ while (*up) { /* For all characters */
9277+ *up = UniToupper(*up);
9278+ up++;
9279+ }
9280+ return upin; /* Return input pointer */
9281+}
9282+#endif /* UNIUPR_NOUPPER */
9283+
9284+#ifndef UNIUPR_NOLOWER
9285+/*
9286+ * UniTolower: Convert a unicode character to lower case
9287+ */
9288+static inline wchar_t
9289+UniTolower(wchar_t uc)
9290+{
9291+ register struct UniCaseRange *rp;
9292+
9293+ if (uc < sizeof (UniLowerTable)) { /* Latin characters */
9294+ return uc + UniLowerTable[uc]; /* Use base tables */
9295+ } else {
9296+ rp = UniLowerRange; /* Use range tables */
9297+ while (rp->start) {
9298+ if (uc < rp->start) /* Before start of range */
9299+ return uc; /* Uppercase = input */
9300+ if (uc <= rp->end) /* In range */
9301+ return uc + rp->table[uc - rp->start];
9302+ rp++; /* Try next range */
9303+ }
9304+ }
9305+ return uc; /* Past last range */
9306+}
9307+
9308+/*
9309+ * UniStrlwr: Lower case a unicode string
9310+ */
9311+static inline wchar_t *
9312+UniStrlwr(register wchar_t * upin)
9313+{
9314+ register wchar_t *up;
9315+
9316+ up = upin;
9317+ while (*up) { /* For all characters */
9318+ *up = UniTolower(*up);
9319+ up++;
9320+ }
9321+ return upin; /* Return input pointer */
9322+}
9323+
9324+#endif
9325--- /dev/null
9326+++ b/fs/cifs/cifs_uniupr.h
9327@@ -0,0 +1,253 @@
9328+/*
9329+ * Copyright (c) International Business Machines Corp., 2000,2002
9330+ *
9331+ * This program is free software; you can redistribute it and/or modify
9332+ * it under the terms of the GNU General Public License as published by
9333+ * the Free Software Foundation; either version 2 of the License, or
9334+ * (at your option) any later version.
9335+ *
9336+ * This program is distributed in the hope that it will be useful,
9337+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9338+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9339+ * the GNU General Public License for more details.
9340+ *
9341+ * You should have received a copy of the GNU General Public License
9342+ * along with this program; if not, write to the Free Software
9343+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9344+ *
9345+ * uniupr.h - Unicode compressed case ranges
9346+ *
9347+*/
9348+
9349+#ifndef UNIUPR_NOUPPER
9350+/*
9351+ * Latin upper case
9352+ */
9353+signed char CifsUniUpperTable[512] = {
9354+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
9355+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
9356+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
9357+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
9358+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
9359+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
9360+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
9361+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
9362+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
9363+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
9364+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
9365+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
9366+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
9367+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
9368+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
9369+ -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
9370+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
9371+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
9372+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
9373+ 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
9374+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
9375+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
9376+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
9377+ 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
9378+ 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
9379+ 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
9380+ 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
9381+ -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
9382+ 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
9383+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
9384+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
9385+ 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
9386+};
9387+
9388+/* Upper case range - Greek */
9389+static signed char UniCaseRangeU03a0[47] = {
9390+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
9391+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
9392+ -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
9393+ -63, -63,
9394+};
9395+
9396+/* Upper case range - Cyrillic */
9397+static signed char UniCaseRangeU0430[48] = {
9398+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
9399+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
9400+ 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
9401+};
9402+
9403+/* Upper case range - Extended cyrillic */
9404+static signed char UniCaseRangeU0490[61] = {
9405+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
9406+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
9407+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
9408+ 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
9409+};
9410+
9411+/* Upper case range - Extended latin and greek */
9412+static signed char UniCaseRangeU1e00[509] = {
9413+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
9414+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
9415+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
9416+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
9417+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
9418+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
9419+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
9420+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
9421+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
9422+ 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
9423+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
9424+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
9425+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
9426+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
9427+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
9428+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
9429+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
9430+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
9431+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
9432+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
9433+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
9434+ 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
9435+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
9436+ 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
9437+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
9438+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
9439+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
9440+ 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
9441+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
9442+ 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
9443+ 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
9444+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9445+};
9446+
9447+/* Upper case range - Wide latin */
9448+static signed char UniCaseRangeUff40[27] = {
9449+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
9450+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
9451+};
9452+
9453+/*
9454+ * Upper Case Range
9455+ */
9456+const struct UniCaseRange CifsUniUpperRange[] = {
9457+ {0x03a0, 0x03ce, UniCaseRangeU03a0},
9458+ {0x0430, 0x045f, UniCaseRangeU0430},
9459+ {0x0490, 0x04cc, UniCaseRangeU0490},
9460+ {0x1e00, 0x1ffc, UniCaseRangeU1e00},
9461+ {0xff40, 0xff5a, UniCaseRangeUff40},
9462+ {0, 0, NULL}
9463+};
9464+#endif
9465+
9466+#ifndef UNIUPR_NOLOWER
9467+/*
9468+ * Latin lower case
9469+ */
9470+static signed char CifsUniLowerTable[512] = {
9471+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
9472+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
9473+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
9474+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
9475+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
9476+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
9477+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
9478+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
9479+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
9480+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
9481+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
9482+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
9483+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
9484+ 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
9485+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
9486+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
9487+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
9488+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
9489+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
9490+ 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
9491+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
9492+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
9493+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
9494+ 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
9495+ 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
9496+ 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
9497+ 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
9498+ 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
9499+ 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
9500+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
9501+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
9502+ 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
9503+};
9504+
9505+/* Lower case range - Greek */
9506+static signed char UniCaseRangeL0380[44] = {
9507+ 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
9508+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
9509+ 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
9510+};
9511+
9512+/* Lower case range - Cyrillic */
9513+static signed char UniCaseRangeL0400[48] = {
9514+ 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
9515+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
9516+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
9517+};
9518+
9519+/* Lower case range - Extended cyrillic */
9520+static signed char UniCaseRangeL0490[60] = {
9521+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
9522+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
9523+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
9524+ 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
9525+};
9526+
9527+/* Lower case range - Extended latin and greek */
9528+static signed char UniCaseRangeL1e00[504] = {
9529+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
9530+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
9531+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
9532+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
9533+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
9534+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
9535+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
9536+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
9537+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
9538+ 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
9539+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
9540+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
9541+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
9542+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
9543+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
9544+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
9545+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
9546+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
9547+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
9548+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
9549+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
9550+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
9551+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
9552+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
9553+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
9554+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
9555+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
9556+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
9557+ 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
9558+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
9559+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
9560+ 0, 0, 0, 0, 0, 0, 0, 0,
9561+};
9562+
9563+/* Lower case range - Wide latin */
9564+static signed char UniCaseRangeLff20[27] = {
9565+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
9566+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
9567+};
9568+
9569+/*
9570+ * Lower Case Range
9571+ */
9572+const static struct UniCaseRange CifsUniLowerRange[] = {
9573+ 0x0380, 0x03ab, UniCaseRangeL0380,
9574+ 0x0400, 0x042f, UniCaseRangeL0400,
9575+ 0x0490, 0x04cb, UniCaseRangeL0490,
9576+ 0x1e00, 0x1ff7, UniCaseRangeL1e00,
9577+ 0xff20, 0xff3a, UniCaseRangeLff20,
9578+ 0, 0, 0
9579+};
9580+#endif
9581--- /dev/null
9582+++ b/fs/cifs/connect.c
9583@@ -0,0 +1,2924 @@
9584+/*
9585+ * fs/cifs/connect.c
9586+ *
9587+ * Copyright (C) International Business Machines Corp., 2002,2004
9588+ * Author(s): Steve French (sfrench@us.ibm.com)
9589+ *
9590+ * This library is free software; you can redistribute it and/or modify
9591+ * it under the terms of the GNU Lesser General Public License as published
9592+ * by the Free Software Foundation; either version 2.1 of the License, or
9593+ * (at your option) any later version.
9594+ *
9595+ * This library is distributed in the hope that it will be useful,
9596+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9597+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9598+ * the GNU Lesser General Public License for more details.
9599+ *
9600+ * You should have received a copy of the GNU Lesser General Public License
9601+ * along with this library; if not, write to the Free Software
9602+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9603+ */
9604+#include <linux/fs.h>
9605+#include <linux/net.h>
9606+#include <linux/string.h>
9607+#include <linux/list.h>
9608+#include <linux/wait.h>
9609+#include <linux/version.h>
9610+#include <linux/ipv6.h>
9611+#include <linux/pagemap.h>
9612+#include <linux/ctype.h>
9613+#include <linux/utsname.h>
9614+#include <asm/uaccess.h>
9615+#include <asm/processor.h>
9616+#include "cifspdu.h"
9617+#include "cifsglob.h"
9618+#include "cifsproto.h"
9619+#include "cifs_unicode.h"
9620+#include "cifs_debug.h"
9621+#include "cifs_fs_sb.h"
9622+#include "ntlmssp.h"
9623+#include "nterr.h"
9624+#include "rfc1002pdu.h"
9625+
9626+#define CIFS_PORT 445
9627+#define RFC1001_PORT 139
9628+
9629+extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
9630+ unsigned char *p24);
9631+extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
9632+ unsigned char *p24);
9633+extern int cifs_inet_pton(int, const char *, void *dst);
9634+
9635+struct smb_vol {
9636+ char *username;
9637+ char *password;
9638+ char *domainname;
9639+ char *UNC;
9640+ char *UNCip;
9641+ char *iocharset; /* local code page for mapping to and from Unicode */
9642+ char source_rfc1001_name[16]; /* netbios name of client */
9643+ uid_t linux_uid;
9644+ gid_t linux_gid;
9645+ mode_t file_mode;
9646+ mode_t dir_mode;
9647+ int rw:1;
9648+ int retry:1;
9649+ int intr:1;
9650+ unsigned int rsize;
9651+ unsigned int wsize;
9652+ unsigned int sockopt;
9653+ unsigned short int port;
9654+};
9655+
9656+static int ipv4_connect(struct sockaddr_in *psin_server,
9657+ struct socket **csocket,
9658+ char * netb_name);
9659+static int ipv6_connect(struct sockaddr_in6 *psin_server,
9660+ struct socket **csocket);
9661+
9662+
9663+ /*
9664+ * cifs tcp session reconnection
9665+ *
9666+ * mark tcp session as reconnecting so temporarily locked
9667+ * mark all smb sessions as reconnecting for tcp session
9668+ * reconnect tcp session
9669+ * wake up waiters on reconnection? - (not needed currently)
9670+ */
9671+
9672+int
9673+cifs_reconnect(struct TCP_Server_Info *server)
9674+{
9675+ int rc = 0;
9676+ struct list_head *tmp;
9677+ struct cifsSesInfo *ses;
9678+ struct cifsTconInfo *tcon;
9679+ struct mid_q_entry * mid_entry;
9680+
9681+ spin_lock(&GlobalMid_Lock);
9682+ if(server->tcpStatus == CifsExiting) {
9683+ /* the demux thread will exit normally
9684+ next time through the loop */
9685+ spin_unlock(&GlobalMid_Lock);
9686+ return rc;
9687+ } else
9688+ server->tcpStatus = CifsNeedReconnect;
9689+ spin_unlock(&GlobalMid_Lock);
9690+ server->maxBuf = 0;
9691+
9692+ cFYI(1, ("Reconnecting tcp session "));
9693+
9694+ /* before reconnecting the tcp session, mark the smb session (uid)
9695+ and the tid bad so they are not used until reconnected */
9696+ read_lock(&GlobalSMBSeslock);
9697+ list_for_each(tmp, &GlobalSMBSessionList) {
9698+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
9699+ if (ses->server) {
9700+ if (ses->server == server) {
9701+ ses->status = CifsNeedReconnect;
9702+ ses->ipc_tid = 0;
9703+ }
9704+ }
9705+ /* else tcp and smb sessions need reconnection */
9706+ }
9707+ list_for_each(tmp, &GlobalTreeConnectionList) {
9708+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
9709+ if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
9710+ tcon->tidStatus = CifsNeedReconnect;
9711+ }
9712+ }
9713+ read_unlock(&GlobalSMBSeslock);
9714+ /* do not want to be sending data on a socket we are freeing */
9715+ down(&server->tcpSem);
9716+ if(server->ssocket) {
9717+ cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
9718+ server->ssocket->flags));
9719+ server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
9720+ cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
9721+ server->ssocket->flags));
9722+ sock_release(server->ssocket);
9723+ server->ssocket = NULL;
9724+ }
9725+
9726+ spin_lock(&GlobalMid_Lock);
9727+ list_for_each(tmp, &server->pending_mid_q) {
9728+ mid_entry = list_entry(tmp, struct
9729+ mid_q_entry,
9730+ qhead);
9731+ if(mid_entry) {
9732+ if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
9733+ /* Mark other intransit requests as needing retry so
9734+ we do not immediately mark the session bad again
9735+ (ie after we reconnect below) as they timeout too */
9736+ mid_entry->midState = MID_RETRY_NEEDED;
9737+ }
9738+ }
9739+ }
9740+ spin_unlock(&GlobalMid_Lock);
9741+ up(&server->tcpSem);
9742+
9743+ while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
9744+ {
9745+ if(server->protocolType == IPV6) {
9746+ rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
9747+ } else {
9748+ rc = ipv4_connect(&server->addr.sockAddr,
9749+ &server->ssocket,
9750+ server->workstation_RFC1001_name);
9751+ }
9752+ if(rc) {
9753+ set_current_state(TASK_INTERRUPTIBLE);
9754+ schedule_timeout(3 * HZ);
9755+ } else {
9756+ atomic_inc(&tcpSesReconnectCount);
9757+ spin_lock(&GlobalMid_Lock);
9758+ if(server->tcpStatus != CifsExiting)
9759+ server->tcpStatus = CifsGood;
9760+ spin_unlock(&GlobalMid_Lock);
9761+ /* atomic_set(&server->inFlight,0);*/
9762+ wake_up(&server->response_q);
9763+ }
9764+ }
9765+ return rc;
9766+}
9767+
9768+static int
9769+cifs_demultiplex_thread(struct TCP_Server_Info *server)
9770+{
9771+ int length;
9772+ unsigned int pdu_length, total_read;
9773+ struct smb_hdr *smb_buffer = NULL;
9774+ struct msghdr smb_msg;
9775+ mm_segment_t temp_fs;
9776+ struct iovec iov;
9777+ struct socket *csocket = server->ssocket;
9778+ struct list_head *tmp;
9779+ struct cifsSesInfo *ses;
9780+ struct task_struct *task_to_wake = NULL;
9781+ struct mid_q_entry *mid_entry;
9782+ char *temp;
9783+
9784+ daemonize();
9785+ sprintf(current->comm,"cifsd");
9786+ /* allow_signal(SIGKILL);*/
9787+ current->flags |= PF_MEMALLOC;
9788+ server->tsk = current; /* save process info to wake at shutdown */
9789+ cFYI(1, ("Demultiplex PID: %d", current->pid));
9790+
9791+ temp_fs = get_fs(); /* we must turn off socket api parm checking */
9792+ set_fs(get_ds());
9793+
9794+ while (server->tcpStatus != CifsExiting) {
9795+ if (smb_buffer == NULL)
9796+ smb_buffer = cifs_buf_get();
9797+ else
9798+ memset(smb_buffer, 0, sizeof (struct smb_hdr));
9799+
9800+ if (smb_buffer == NULL) {
9801+ cERROR(1,("Can not get memory for SMB response"));
9802+ set_current_state(TASK_INTERRUPTIBLE);
9803+ schedule_timeout(HZ * 3); /* give system time to free memory */
9804+ continue;
9805+ }
9806+ iov.iov_base = smb_buffer;
9807+ iov.iov_len = sizeof (struct smb_hdr) - 1;
9808+ /* 1 byte less above since wct is not always returned in error cases */
9809+ smb_msg.msg_iov = &iov;
9810+ smb_msg.msg_iovlen = 1;
9811+ smb_msg.msg_control = NULL;
9812+ smb_msg.msg_controllen = 0;
9813+
9814+ length =
9815+ sock_recvmsg(csocket, &smb_msg,
9816+ sizeof (struct smb_hdr) -
9817+ 1 /* RFC1001 header and SMB header */ ,
9818+ MSG_PEEK /* flags see socket.h */ );
9819+
9820+ if(server->tcpStatus == CifsExiting) {
9821+ break;
9822+ } else if (server->tcpStatus == CifsNeedReconnect) {
9823+ cFYI(1,("Reconnecting after server stopped responding"));
9824+ cifs_reconnect(server);
9825+ cFYI(1,("call to reconnect done"));
9826+ csocket = server->ssocket;
9827+ continue;
9828+ } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
9829+ set_current_state(TASK_INTERRUPTIBLE);
9830+ schedule_timeout(1); /* minimum sleep to prevent looping
9831+ allowing socket to clear and app threads to set
9832+ tcpStatus CifsNeedReconnect if server hung */
9833+ continue;
9834+ } else if (length <= 0) {
9835+ if(server->tcpStatus == CifsNew) {
9836+ cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
9837+ /* some servers kill tcp session rather than returning
9838+ smb negprot error in which case reconnecting here is
9839+ not going to help - return error to mount */
9840+ break;
9841+ }
9842+ if(length == -EINTR) {
9843+ cFYI(1,("cifsd thread killed"));
9844+ break;
9845+ }
9846+ cFYI(1,("Reconnecting after unexpected peek error %d",length));
9847+ cifs_reconnect(server);
9848+ csocket = server->ssocket;
9849+ wake_up(&server->response_q);
9850+ continue;
9851+ }
9852+
9853+ pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
9854+ /* Ony read pdu_length after below checks for too short (due
9855+ to e.g. int overflow) and too long ie beyond end of buf */
9856+ cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
9857+
9858+ temp = (char *) smb_buffer;
9859+ if (length > 3) {
9860+ if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
9861+ iov.iov_base = smb_buffer;
9862+ iov.iov_len = 4;
9863+ length = sock_recvmsg(csocket, &smb_msg, 4, 0);
9864+ cFYI(0,("Received 4 byte keep alive packet"));
9865+ } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
9866+ iov.iov_base = smb_buffer;
9867+ iov.iov_len = 4;
9868+ length = sock_recvmsg(csocket, &smb_msg, 4, 0);
9869+ cFYI(1,("Good RFC 1002 session rsp"));
9870+ } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
9871+ && (length == 5)) {
9872+ /* we get this from Windows 98 instead of error on SMB negprot response */
9873+ cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
9874+ if(server->tcpStatus == CifsNew) {
9875+ /* if nack on negprot (rather than
9876+ ret of smb negprot error) reconnecting
9877+ not going to help, ret error to mount */
9878+ break;
9879+ } else {
9880+ /* give server a second to
9881+ clean up before reconnect attempt */
9882+ set_current_state(TASK_INTERRUPTIBLE);
9883+ schedule_timeout(HZ);
9884+ /* always try 445 first on reconnect
9885+ since we get NACK on some if we ever
9886+ connected to port 139 (the NACK is
9887+ since we do not begin with RFC1001
9888+ session initialize frame) */
9889+ server->addr.sockAddr.sin_port = CIFS_PORT;
9890+ cifs_reconnect(server);
9891+ csocket = server->ssocket;
9892+ wake_up(&server->response_q);
9893+ continue;
9894+ }
9895+ } else if (temp[0] != (char) 0) {
9896+ cERROR(1,("Unknown RFC 1002 frame"));
9897+ cifs_dump_mem(" Received Data: ", temp, length);
9898+ cifs_reconnect(server);
9899+ csocket = server->ssocket;
9900+ continue;
9901+ } else {
9902+ if ((length != sizeof (struct smb_hdr) - 1)
9903+ || (pdu_length >
9904+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
9905+ || (pdu_length <
9906+ sizeof (struct smb_hdr) - 1)
9907+ ||
9908+ (checkSMBhdr
9909+ (smb_buffer, smb_buffer->Mid))) {
9910+ cERROR(1,
9911+ ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
9912+ length, pdu_length));
9913+ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
9914+ /* could we fix this network corruption by finding next
9915+ smb header (instead of killing the session) and
9916+ restart reading from next valid SMB found? */
9917+ cifs_reconnect(server);
9918+ csocket = server->ssocket;
9919+ continue;
9920+ } else { /* length ok */
9921+
9922+ length = 0;
9923+ iov.iov_base = smb_buffer;
9924+ iov.iov_len = pdu_length;
9925+ for (total_read = 0;
9926+ total_read < pdu_length;
9927+ total_read += length) {
9928+ length = sock_recvmsg(csocket, &smb_msg,
9929+ pdu_length - total_read, 0);
9930+ if (length == 0) {
9931+ cERROR(1,
9932+ ("Zero length receive when expecting %d ",
9933+ pdu_length - total_read));
9934+ cifs_reconnect(server);
9935+ csocket = server->ssocket;
9936+ continue;
9937+ }
9938+ }
9939+ }
9940+
9941+ dump_smb(smb_buffer, length);
9942+ if (checkSMB
9943+ (smb_buffer, smb_buffer->Mid, total_read)) {
9944+ cERROR(1, ("Bad SMB Received "));
9945+ continue;
9946+ }
9947+
9948+ task_to_wake = NULL;
9949+ spin_lock(&GlobalMid_Lock);
9950+ list_for_each(tmp, &server->pending_mid_q) {
9951+ mid_entry = list_entry(tmp, struct
9952+ mid_q_entry,
9953+ qhead);
9954+
9955+ if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
9956+ cFYI(1,
9957+ (" Mid 0x%x matched - waking up ",mid_entry->mid));
9958+ task_to_wake = mid_entry->tsk;
9959+ mid_entry->resp_buf =
9960+ smb_buffer;
9961+ mid_entry->midState =
9962+ MID_RESPONSE_RECEIVED;
9963+ }
9964+ }
9965+ spin_unlock(&GlobalMid_Lock);
9966+ if (task_to_wake) {
9967+ smb_buffer = NULL; /* will be freed by users thread after he is done */
9968+ wake_up_process(task_to_wake);
9969+ } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
9970+ cERROR(1, ("No task to wake, unknown frame rcvd!"));
9971+ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
9972+ }
9973+ }
9974+ } else {
9975+ cFYI(0,
9976+ ("Frame less than four bytes received %d bytes long.",
9977+ length));
9978+ if (length > 0) {
9979+ length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
9980+ cFYI(1,
9981+ (" with junk 0x%x in it ",
9982+ *(__u32 *) smb_buffer));
9983+ }
9984+ }
9985+ }
9986+ spin_lock(&GlobalMid_Lock);
9987+ server->tcpStatus = CifsExiting;
9988+ server->tsk = NULL;
9989+ atomic_set(&server->inFlight, 0);
9990+ spin_unlock(&GlobalMid_Lock);
9991+ /* Although there should not be any requests blocked on
9992+ this queue it can not hurt to be paranoid and try to wake up requests
9993+ that may haven been blocked when more than 50 at time were on the wire
9994+ to the same server - they now will see the session is in exit state
9995+ and get out of SendReceive. */
9996+ wake_up_all(&server->request_q);
9997+ /* give those requests time to exit */
9998+ set_current_state(TASK_INTERRUPTIBLE);
9999+ schedule_timeout(HZ/8);
10000+
10001+ if(server->ssocket) {
10002+ sock_release(csocket);
10003+ server->ssocket = NULL;
10004+ }
10005+ set_fs(temp_fs);
10006+ if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
10007+ cifs_buf_release(smb_buffer);
10008+
10009+ read_lock(&GlobalSMBSeslock);
10010+ if (list_empty(&server->pending_mid_q)) {
10011+ /* loop through server session structures attached to this and mark them dead */
10012+ list_for_each(tmp, &GlobalSMBSessionList) {
10013+ ses =
10014+ list_entry(tmp, struct cifsSesInfo,
10015+ cifsSessionList);
10016+ if (ses->server == server) {
10017+ ses->status = CifsExiting;
10018+ ses->server = NULL;
10019+ }
10020+ }
10021+ read_unlock(&GlobalSMBSeslock);
10022+ } else {
10023+ spin_lock(&GlobalMid_Lock);
10024+ list_for_each(tmp, &server->pending_mid_q) {
10025+ mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
10026+ if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
10027+ cFYI(1,
10028+ (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
10029+ task_to_wake = mid_entry->tsk;
10030+ if(task_to_wake) {
10031+ wake_up_process(task_to_wake);
10032+ }
10033+ }
10034+ }
10035+ spin_unlock(&GlobalMid_Lock);
10036+ read_unlock(&GlobalSMBSeslock);
10037+ set_current_state(TASK_INTERRUPTIBLE);
10038+ /* 1/8th of sec is more than enough time for them to exit */
10039+ schedule_timeout(HZ/8);
10040+ }
10041+
10042+ if (list_empty(&server->pending_mid_q)) {
10043+ /* mpx threads have not exited yet give them
10044+ at least the smb send timeout time for long ops */
10045+ cFYI(1, ("Wait for exit from demultiplex thread"));
10046+ set_current_state(TASK_INTERRUPTIBLE);
10047+ schedule_timeout(46 * HZ);
10048+ /* if threads still have not exited they are probably never
10049+ coming home not much else we can do but free the memory */
10050+ }
10051+ kfree(server);
10052+
10053+ set_current_state(TASK_INTERRUPTIBLE);
10054+ schedule_timeout(HZ/4);
10055+ return 0;
10056+}
10057+
10058+static void *
10059+cifs_kcalloc(size_t size, int type)
10060+{
10061+ void *addr;
10062+ addr = kmalloc(size, type);
10063+ if (addr)
10064+ memset(addr, 0, size);
10065+ return addr;
10066+}
10067+
10068+static int
10069+cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
10070+{
10071+ char *value;
10072+ char *data;
10073+ unsigned int temp_len, i, j;
10074+ char separator[2];
10075+
10076+ separator[0] = ',';
10077+ separator[1] = 0;
10078+
10079+ memset(vol->source_rfc1001_name,0x20,15);
10080+ for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
10081+ /* does not have to be a perfect mapping since the field is
10082+ informational, only used for servers that do not support
10083+ port 445 and it can be overridden at mount time */
10084+ vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
10085+ }
10086+ vol->source_rfc1001_name[15] = 0;
10087+
10088+ vol->linux_uid = current->uid; /* current->euid instead? */
10089+ vol->linux_gid = current->gid;
10090+ vol->dir_mode = S_IRWXUGO;
10091+ /* 2767 perms indicate mandatory locking support */
10092+ vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
10093+
10094+ /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
10095+ vol->rw = TRUE;
10096+
10097+ if (!options)
10098+ return 1;
10099+
10100+ if(strncmp(options,"sep=",4) == 0) {
10101+ if(options[4] != 0) {
10102+ separator[0] = options[4];
10103+ options += 5;
10104+ } else {
10105+ cFYI(1,("Null separator not allowed"));
10106+ }
10107+ }
10108+
10109+ while ((data = strsep(&options, separator)) != NULL) {
10110+ if (!*data)
10111+ continue;
10112+ if ((value = strchr(data, '=')) != NULL)
10113+ *value++ = '\0';
10114+ if (strnicmp(data, "user", 4) == 0) {
10115+ if (!value || !*value) {
10116+ printk(KERN_WARNING
10117+ "CIFS: invalid or missing username\n");
10118+ return 1; /* needs_arg; */
10119+ }
10120+ if (strnlen(value, 200) < 200) {
10121+ vol->username = value;
10122+ } else {
10123+ printk(KERN_WARNING "CIFS: username too long\n");
10124+ return 1;
10125+ }
10126+ } else if (strnicmp(data, "pass", 4) == 0) {
10127+ if (!value || !*value) {
10128+ vol->password = NULL;
10129+ continue;
10130+ }
10131+ temp_len = strlen(value);
10132+ /* removed password length check, NTLM passwords
10133+ can be arbitrarily long */
10134+
10135+ /* if comma in password, the string will be
10136+ prematurely null terminated. Commas in password are
10137+ specified across the cifs mount interface by a double
10138+ comma ie ,, and a comma used as in other cases ie ','
10139+ as a parameter delimiter/separator is single and due
10140+ to the strsep above is temporarily zeroed. */
10141+
10142+ /* NB: password legally can have multiple commas and
10143+ the only illegal character in a password is null */
10144+
10145+ if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
10146+ /* reinsert comma */
10147+ value[temp_len] = separator[0];
10148+ temp_len+=2; /* move after the second comma */
10149+ while(value[temp_len] != 0) {
10150+ if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
10151+ /* single comma indicating start of next parm */
10152+ break;
10153+ }
10154+ temp_len++;
10155+ }
10156+ if(value[temp_len] == 0) {
10157+ options = NULL;
10158+ } else {
10159+ value[temp_len] = 0;
10160+ /* move options to point to start of next parm */
10161+ options = value + temp_len + 1;
10162+ }
10163+ /* go from value to (value + temp_len) condensing double commas to singles */
10164+ vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
10165+ for(i=0,j=0;i<temp_len;i++,j++) {
10166+ vol->password[j] = value[i];
10167+ if(value[i] == separator[0] && value[i+1] == separator[0]) {
10168+ /* skip second comma */
10169+ i++;
10170+ }
10171+ }
10172+ /* value[temp_len] is zeroed above so
10173+ vol->password[temp_len] guaranteed to be null */
10174+ } else {
10175+ vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
10176+ strcpy(vol->password, value);
10177+ }
10178+ } else if (strnicmp(data, "ip", 2) == 0) {
10179+ if (!value || !*value) {
10180+ vol->UNCip = NULL;
10181+ } else if (strnlen(value, 35) < 35) {
10182+ vol->UNCip = value;
10183+ } else {
10184+ printk(KERN_WARNING "CIFS: ip address too long\n");
10185+ return 1;
10186+ }
10187+ } else if ((strnicmp(data, "unc", 3) == 0)
10188+ || (strnicmp(data, "target", 6) == 0)
10189+ || (strnicmp(data, "path", 4) == 0)) {
10190+ if (!value || !*value) {
10191+ printk(KERN_WARNING
10192+ "CIFS: invalid path to network resource\n");
10193+ return 1; /* needs_arg; */
10194+ }
10195+ if ((temp_len = strnlen(value, 300)) < 300) {
10196+ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
10197+ if(vol->UNC == NULL)
10198+ return 1;
10199+ strcpy(vol->UNC,value);
10200+ if (strncmp(vol->UNC, "//", 2) == 0) {
10201+ vol->UNC[0] = '\\';
10202+ vol->UNC[1] = '\\';
10203+ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
10204+ printk(KERN_WARNING
10205+ "CIFS: UNC Path does not begin with // or \\\\ \n");
10206+ return 1;
10207+ }
10208+ } else {
10209+ printk(KERN_WARNING "CIFS: UNC name too long\n");
10210+ return 1;
10211+ }
10212+ } else if ((strnicmp(data, "domain", 3) == 0)
10213+ || (strnicmp(data, "workgroup", 5) == 0)) {
10214+ if (!value || !*value) {
10215+ printk(KERN_WARNING "CIFS: invalid domain name\n");
10216+ return 1; /* needs_arg; */
10217+ }
10218+ /* BB are there cases in which a comma can be valid in
10219+ a domain name and need special handling? */
10220+ if (strnlen(value, 65) < 65) {
10221+ vol->domainname = value;
10222+ cFYI(1, ("Domain name set"));
10223+ } else {
10224+ printk(KERN_WARNING "CIFS: domain name too long\n");
10225+ return 1;
10226+ }
10227+ } else if (strnicmp(data, "iocharset", 9) == 0) {
10228+ if (!value || !*value) {
10229+ printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
10230+ return 1; /* needs_arg; */
10231+ }
10232+ if (strnlen(value, 65) < 65) {
10233+ if(strnicmp(value,"default",7))
10234+ vol->iocharset = value;
10235+ /* if iocharset not set load_nls_default used by caller */
10236+ cFYI(1, ("iocharset set to %s",value));
10237+ } else {
10238+ printk(KERN_WARNING "CIFS: iocharset name too long.\n");
10239+ return 1;
10240+ }
10241+ } else if (strnicmp(data, "uid", 3) == 0) {
10242+ if (value && *value) {
10243+ vol->linux_uid =
10244+ simple_strtoul(value, &value, 0);
10245+ }
10246+ } else if (strnicmp(data, "gid", 3) == 0) {
10247+ if (value && *value) {
10248+ vol->linux_gid =
10249+ simple_strtoul(value, &value, 0);
10250+ }
10251+ } else if (strnicmp(data, "file_mode", 4) == 0) {
10252+ if (value && *value) {
10253+ vol->file_mode =
10254+ simple_strtoul(value, &value, 0);
10255+ }
10256+ } else if (strnicmp(data, "dir_mode", 3) == 0) {
10257+ if (value && *value) {
10258+ vol->dir_mode =
10259+ simple_strtoul(value, &value, 0);
10260+ }
10261+ } else if (strnicmp(data, "port", 4) == 0) {
10262+ if (value && *value) {
10263+ vol->port =
10264+ simple_strtoul(value, &value, 0);
10265+ }
10266+ } else if (strnicmp(data, "rsize", 5) == 0) {
10267+ if (value && *value) {
10268+ vol->rsize =
10269+ simple_strtoul(value, &value, 0);
10270+ }
10271+ } else if (strnicmp(data, "wsize", 5) == 0) {
10272+ if (value && *value) {
10273+ vol->wsize =
10274+ simple_strtoul(value, &value, 0);
10275+ }
10276+ } else if (strnicmp(data, "sockopt", 5) == 0) {
10277+ if (value && *value) {
10278+ vol->sockopt =
10279+ simple_strtoul(value, &value, 0);
10280+ }
10281+ } else if (strnicmp(data, "netbiosname", 4) == 0) {
10282+ if (!value || !*value || (*value == ' ')) {
10283+ cFYI(1,("invalid (empty) netbiosname specified"));
10284+ } else {
10285+ memset(vol->source_rfc1001_name,0x20,15);
10286+ for(i=0;i<15;i++) {
10287+ /* BB are there cases in which a comma can be
10288+ valid in this workstation netbios name (and need
10289+ special handling)? */
10290+
10291+ /* We do not uppercase netbiosname for user */
10292+ if (value[i]==0)
10293+ break;
10294+ else
10295+ vol->source_rfc1001_name[i] = value[i];
10296+ }
10297+ /* The string has 16th byte zero still from
10298+ set at top of the function */
10299+ if((i==15) && (value[i] != 0))
10300+ printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
10301+ }
10302+ } else if (strnicmp(data, "credentials", 4) == 0) {
10303+ /* ignore */
10304+ } else if (strnicmp(data, "version", 3) == 0) {
10305+ /* ignore */
10306+ } else if (strnicmp(data, "rw", 2) == 0) {
10307+ vol->rw = TRUE;
10308+ } else if ((strnicmp(data, "suid", 4) == 0) ||
10309+ (strnicmp(data, "nosuid", 6) == 0) ||
10310+ (strnicmp(data, "exec", 4) == 0) ||
10311+ (strnicmp(data, "noexec", 6) == 0) ||
10312+ (strnicmp(data, "nodev", 5) == 0) ||
10313+ (strnicmp(data, "noauto", 6) == 0) ||
10314+ (strnicmp(data, "dev", 3) == 0)) {
10315+ /* The mount tool or mount.cifs helper (if present)
10316+ uses these opts to set flags, and the flags are read
10317+ by the kernel vfs layer before we get here (ie
10318+ before read super) so there is no point trying to
10319+ parse these options again and set anything and it
10320+ is ok to just ignore them */
10321+ continue;
10322+ } else if (strnicmp(data, "ro", 2) == 0) {
10323+ vol->rw = FALSE;
10324+ } else if (strnicmp(data, "hard", 4) == 0) {
10325+ vol->retry = 1;
10326+ } else if (strnicmp(data, "soft", 4) == 0) {
10327+ vol->retry = 0;
10328+ } else if (strnicmp(data, "nohard", 6) == 0) {
10329+ vol->retry = 0;
10330+ } else if (strnicmp(data, "nosoft", 6) == 0) {
10331+ vol->retry = 1;
10332+ } else if (strnicmp(data, "nointr", 6) == 0) {
10333+ vol->intr = 0;
10334+ } else if (strnicmp(data, "intr", 4) == 0) {
10335+ vol->intr = 1;
10336+ } else if (strnicmp(data, "noac", 4) == 0) {
10337+ printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
10338+ } else
10339+ printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
10340+ }
10341+ if (vol->UNC == NULL) {
10342+ if(devname == NULL) {
10343+ printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
10344+ return 1;
10345+ }
10346+ if ((temp_len = strnlen(devname, 300)) < 300) {
10347+ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
10348+ if(vol->UNC == NULL)
10349+ return 1;
10350+ strcpy(vol->UNC,devname);
10351+ if (strncmp(vol->UNC, "//", 2) == 0) {
10352+ vol->UNC[0] = '\\';
10353+ vol->UNC[1] = '\\';
10354+ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
10355+ printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
10356+ return 1;
10357+ }
10358+ } else {
10359+ printk(KERN_WARNING "CIFS: UNC name too long\n");
10360+ return 1;
10361+ }
10362+ }
10363+ if(vol->UNCip == 0)
10364+ vol->UNCip = &vol->UNC[2];
10365+
10366+ return 0;
10367+}
10368+
10369+static struct cifsSesInfo *
10370+cifs_find_tcp_session(__u32 new_target_ip_addr,
10371+ char *userName, struct TCP_Server_Info **psrvTcp)
10372+{
10373+ struct list_head *tmp;
10374+ struct cifsSesInfo *ses;
10375+
10376+ *psrvTcp = NULL;
10377+ read_lock(&GlobalSMBSeslock);
10378+ list_for_each(tmp, &GlobalSMBSessionList) {
10379+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
10380+ if (ses->server) {
10381+ if (ses->server->addr.sockAddr.sin_addr.s_addr ==
10382+ new_target_ip_addr) {
10383+ /* BB lock server and tcp session and increment use count here?? */
10384+ *psrvTcp = ses->server; /* found a match on the TCP session */
10385+ /* BB check if reconnection needed */
10386+ if (strncmp
10387+ (ses->userName, userName,
10388+ MAX_USERNAME_SIZE) == 0){
10389+ read_unlock(&GlobalSMBSeslock);
10390+ return ses; /* found exact match on both tcp and SMB sessions */
10391+ }
10392+ }
10393+ }
10394+ /* else tcp and smb sessions need reconnection */
10395+ }
10396+ read_unlock(&GlobalSMBSeslock);
10397+ return NULL;
10398+}
10399+
10400+static struct cifsTconInfo *
10401+find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
10402+{
10403+ struct list_head *tmp;
10404+ struct cifsTconInfo *tcon;
10405+
10406+ read_lock(&GlobalSMBSeslock);
10407+ list_for_each(tmp, &GlobalTreeConnectionList) {
10408+ cFYI(1, ("Next tcon - "));
10409+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
10410+ if (tcon->ses) {
10411+ if (tcon->ses->server) {
10412+ cFYI(1,
10413+ (" old ip addr: %x == new ip %x ?",
10414+ tcon->ses->server->addr.sockAddr.sin_addr.
10415+ s_addr, new_target_ip_addr));
10416+ if (tcon->ses->server->addr.sockAddr.sin_addr.
10417+ s_addr == new_target_ip_addr) {
10418+ /* BB lock tcon and server and tcp session and increment use count here? */
10419+ /* found a match on the TCP session */
10420+ /* BB check if reconnection needed */
10421+ cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
10422+ tcon->treeName, uncName));
10423+ if (strncmp
10424+ (tcon->treeName, uncName,
10425+ MAX_TREE_SIZE) == 0) {
10426+ cFYI(1,
10427+ ("Matched UNC, old user: %s == new: %s ?",
10428+ tcon->treeName, uncName));
10429+ if (strncmp
10430+ (tcon->ses->userName,
10431+ userName,
10432+ MAX_USERNAME_SIZE) == 0) {
10433+ read_unlock(&GlobalSMBSeslock);
10434+ return tcon;/* also matched user (smb session)*/
10435+ }
10436+ }
10437+ }
10438+ }
10439+ }
10440+ }
10441+ read_unlock(&GlobalSMBSeslock);
10442+ return NULL;
10443+}
10444+
10445+int
10446+connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
10447+ const char *old_path, const struct nls_table *nls_codepage)
10448+{
10449+ unsigned char *referrals = NULL;
10450+ unsigned int num_referrals;
10451+ int rc = 0;
10452+
10453+ rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
10454+ &num_referrals, &referrals);
10455+
10456+ /* BB Add in code to: if valid refrl, if not ip address contact
10457+ the helper that resolves tcp names, mount to it, try to
10458+ tcon to it unmount it if fail */
10459+
10460+ if(referrals)
10461+ kfree(referrals);
10462+
10463+ return rc;
10464+}
10465+
10466+int
10467+get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
10468+ const char *old_path, const struct nls_table *nls_codepage,
10469+ unsigned int *pnum_referrals, unsigned char ** preferrals)
10470+{
10471+ char *temp_unc;
10472+ int rc = 0;
10473+
10474+ *pnum_referrals = 0;
10475+
10476+ if (pSesInfo->ipc_tid == 0) {
10477+ temp_unc = kmalloc(2 /* for slashes */ +
10478+ strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
10479+ + 1 + 4 /* slash IPC$ */ + 2,
10480+ GFP_KERNEL);
10481+ if (temp_unc == NULL)
10482+ return -ENOMEM;
10483+ temp_unc[0] = '\\';
10484+ temp_unc[1] = '\\';
10485+ strcpy(temp_unc + 2, pSesInfo->serverName);
10486+ strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
10487+ rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
10488+ cFYI(1,
10489+ ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
10490+ kfree(temp_unc);
10491+ }
10492+ if (rc == 0)
10493+ rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
10494+ pnum_referrals, nls_codepage);
10495+
10496+ return rc;
10497+}
10498+
10499+/* See RFC1001 section 14 on representation of Netbios names */
10500+static void rfc1002mangle(char * target,char * source, unsigned int length)
10501+{
10502+ unsigned int i,j;
10503+
10504+ for(i=0,j=0;i<(length);i++) {
10505+ /* mask a nibble at a time and encode */
10506+ target[j] = 'A' + (0x0F & (source[i] >> 4));
10507+ target[j+1] = 'A' + (0x0F & source[i]);
10508+ j+=2;
10509+ }
10510+
10511+}
10512+
10513+
10514+static int
10515+ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
10516+ char * netbios_name)
10517+{
10518+ int rc = 0;
10519+ int connected = 0;
10520+ unsigned short int orig_port = 0;
10521+
10522+ if(*csocket == NULL) {
10523+ rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
10524+ if (rc < 0) {
10525+ cERROR(1, ("Error %d creating socket",rc));
10526+ *csocket = NULL;
10527+ return rc;
10528+ } else {
10529+ /* BB other socket options to set KEEPALIVE, NODELAY? */
10530+ cFYI(1,("Socket created"));
10531+ (*csocket)->sk->allocation = GFP_NOFS;
10532+ }
10533+ }
10534+
10535+ psin_server->sin_family = AF_INET;
10536+ if(psin_server->sin_port) { /* user overrode default port */
10537+ rc = (*csocket)->ops->connect(*csocket,
10538+ (struct sockaddr *) psin_server,
10539+ sizeof (struct sockaddr_in),0);
10540+ if (rc >= 0)
10541+ connected = 1;
10542+ }
10543+
10544+ if(!connected) {
10545+ /* save original port so we can retry user specified port
10546+ later if fall back ports fail this time */
10547+ orig_port = psin_server->sin_port;
10548+
10549+ /* do not retry on the same port we just failed on */
10550+ if(psin_server->sin_port != htons(CIFS_PORT)) {
10551+ psin_server->sin_port = htons(CIFS_PORT);
10552+
10553+ rc = (*csocket)->ops->connect(*csocket,
10554+ (struct sockaddr *) psin_server,
10555+ sizeof (struct sockaddr_in),0);
10556+ if (rc >= 0)
10557+ connected = 1;
10558+ }
10559+ }
10560+ if (!connected) {
10561+ psin_server->sin_port = htons(RFC1001_PORT);
10562+ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
10563+ psin_server, sizeof (struct sockaddr_in),0);
10564+ if (rc >= 0)
10565+ connected = 1;
10566+ }
10567+
10568+ /* give up here - unless we want to retry on different
10569+ protocol families some day */
10570+ if (!connected) {
10571+ if(orig_port)
10572+ psin_server->sin_port = orig_port;
10573+ cFYI(1,("Error %d connecting to server via ipv4",rc));
10574+ sock_release(*csocket);
10575+ *csocket = NULL;
10576+ return rc;
10577+ }
10578+ /* Eventually check for other socket options to change from
10579+ the default. sock_setsockopt not used because it expects
10580+ user space buffer */
10581+ (*csocket)->sk->rcvtimeo = 7 * HZ;
10582+
10583+ /* send RFC1001 sessinit */
10584+
10585+ if(psin_server->sin_port == htons(139)) {
10586+ /* some servers require RFC1001 sessinit before sending
10587+ negprot - BB check reconnection in case where second
10588+ sessinit is sent but no second negprot */
10589+ struct rfc1002_session_packet * ses_init_buf;
10590+ struct smb_hdr * smb_buf;
10591+ ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
10592+ if(ses_init_buf) {
10593+ ses_init_buf->trailer.session_req.called_len = 32;
10594+ rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
10595+ DEFAULT_CIFS_CALLED_NAME,16);
10596+ ses_init_buf->trailer.session_req.calling_len = 32;
10597+ /* calling name ends in null (byte 16) from old smb
10598+ convention. */
10599+ if(netbios_name && (netbios_name[0] !=0)) {
10600+ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
10601+ netbios_name,16);
10602+ } else {
10603+ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
10604+ "LINUX_CIFS_CLNT",16);
10605+ }
10606+ ses_init_buf->trailer.session_req.scope1 = 0;
10607+ ses_init_buf->trailer.session_req.scope2 = 0;
10608+ smb_buf = (struct smb_hdr *)ses_init_buf;
10609+ /* sizeof RFC1002_SESSION_REQUEST with no scope */
10610+ smb_buf->smb_buf_length = 0x81000044;
10611+ rc = smb_send(*csocket, smb_buf, 0x44,
10612+ (struct sockaddr *)psin_server);
10613+ kfree(ses_init_buf);
10614+ }
10615+ /* else the negprot may still work without this
10616+ even though malloc failed */
10617+
10618+ }
10619+
10620+ return rc;
10621+}
10622+
10623+static int
10624+ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
10625+{
10626+ int rc = 0;
10627+ int connected = 0;
10628+
10629+ if(*csocket == NULL) {
10630+ rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
10631+ if (rc < 0) {
10632+ cERROR(1, ("Error %d creating ipv6 socket",rc));
10633+ *csocket = NULL;
10634+ return rc;
10635+ } else {
10636+ /* BB other socket options to set KEEPALIVE, NODELAY? */
10637+ cFYI(1,("ipv6 Socket created"));
10638+ (*csocket)->sk->allocation = GFP_NOFS;
10639+ }
10640+ }
10641+
10642+ psin_server->sin6_family = AF_INET6;
10643+
10644+ if(psin_server->sin6_port) { /* user overrode default port */
10645+ rc = (*csocket)->ops->connect(*csocket,
10646+ (struct sockaddr *) psin_server,
10647+ sizeof (struct sockaddr_in6),0);
10648+ if (rc >= 0)
10649+ connected = 1;
10650+ }
10651+
10652+ if(!connected) {
10653+ /* do not retry on the same port we just failed on */
10654+ if(psin_server->sin6_port != htons(CIFS_PORT)) {
10655+ psin_server->sin6_port = htons(CIFS_PORT);
10656+
10657+ rc = (*csocket)->ops->connect(*csocket,
10658+ (struct sockaddr *) psin_server,
10659+ sizeof (struct sockaddr_in6),0);
10660+ if (rc >= 0)
10661+ connected = 1;
10662+ }
10663+ }
10664+ if (!connected) {
10665+ psin_server->sin6_port = htons(RFC1001_PORT);
10666+ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
10667+ psin_server, sizeof (struct sockaddr_in6),0);
10668+ if (rc >= 0)
10669+ connected = 1;
10670+ }
10671+
10672+ /* give up here - unless we want to retry on different
10673+ protocol families some day */
10674+ if (!connected) {
10675+ cFYI(1,("Error %d connecting to server via ipv6",rc));
10676+ sock_release(*csocket);
10677+ *csocket = NULL;
10678+ return rc;
10679+ }
10680+ /* Eventually check for other socket options to change from
10681+ the default. sock_setsockopt not used because it expects
10682+ user space buffer */
10683+ (*csocket)->sk->rcvtimeo = 7 * HZ;
10684+
10685+ return rc;
10686+}
10687+
10688+int
10689+cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
10690+ char *mount_data, const char *devname)
10691+{
10692+ int rc = 0;
10693+ int xid;
10694+ struct socket *csocket = NULL;
10695+ struct sockaddr_in sin_server;
10696+ struct sockaddr_in6 sin_server6;
10697+ struct smb_vol volume_info;
10698+ struct cifsSesInfo *pSesInfo = NULL;
10699+ struct cifsSesInfo *existingCifsSes = NULL;
10700+ struct cifsTconInfo *tcon = NULL;
10701+ struct TCP_Server_Info *srvTcp = NULL;
10702+
10703+ xid = GetXid();
10704+
10705+ cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); /* BB removeme BB fixme */
10706+
10707+ memset(&volume_info,0,sizeof(struct smb_vol));
10708+ if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
10709+ if(volume_info.UNC)
10710+ kfree(volume_info.UNC);
10711+ if(volume_info.password)
10712+ kfree(volume_info.password);
10713+ FreeXid(xid);
10714+ return -EINVAL;
10715+ }
10716+
10717+ if (volume_info.username) {
10718+ cFYI(1, ("Username: %s ", volume_info.username));
10719+
10720+ } else {
10721+ cifserror("No username specified ");
10722+ /* In userspace mount helper we can get user name from alternate
10723+ locations such as env variables and files on disk */
10724+ if(volume_info.UNC)
10725+ kfree(volume_info.UNC);
10726+ if(volume_info.password)
10727+ kfree(volume_info.password);
10728+ FreeXid(xid);
10729+ return -EINVAL;
10730+ }
10731+
10732+ if (volume_info.UNCip && volume_info.UNC) {
10733+ rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
10734+
10735+ if(rc == 0) {
10736+ /* not ipv4 address, try ipv6 */
10737+ rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
10738+ }
10739+
10740+ if(rc != 1) {
10741+ /* we failed translating address */
10742+ if(volume_info.UNC)
10743+ kfree(volume_info.UNC);
10744+ if(volume_info.password)
10745+ kfree(volume_info.password);
10746+ FreeXid(xid);
10747+ return -EINVAL;
10748+ }
10749+
10750+ cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
10751+ /* success */
10752+ rc = 0;
10753+ } else if (volume_info.UNCip){
10754+ /* BB using ip addr as server name connect to the DFS root below */
10755+ cERROR(1,("Connecting to DFS root not implemented yet"));
10756+ if(volume_info.UNC)
10757+ kfree(volume_info.UNC);
10758+ if(volume_info.password)
10759+ kfree(volume_info.password);
10760+ FreeXid(xid);
10761+ return -EINVAL;
10762+ } else /* which servers DFS root would we conect to */ {
10763+ cERROR(1,
10764+ ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
10765+ if(volume_info.UNC)
10766+ kfree(volume_info.UNC);
10767+ if(volume_info.password)
10768+ kfree(volume_info.password);
10769+ FreeXid(xid);
10770+ return -EINVAL;
10771+ }
10772+
10773+ /* this is needed for ASCII cp to Unicode converts */
10774+ if(volume_info.iocharset == NULL) {
10775+ cifs_sb->local_nls = load_nls_default();
10776+ /* load_nls_default can not return null */
10777+ } else {
10778+ cifs_sb->local_nls = load_nls(volume_info.iocharset);
10779+ if(cifs_sb->local_nls == NULL) {
10780+ cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
10781+ if(volume_info.UNC)
10782+ kfree(volume_info.UNC);
10783+ if(volume_info.password)
10784+ kfree(volume_info.password);
10785+ FreeXid(xid);
10786+ return -ELIBACC;
10787+ }
10788+ }
10789+
10790+ existingCifsSes =
10791+ cifs_find_tcp_session(sin_server.sin_addr.s_addr,
10792+ volume_info.username, &srvTcp);
10793+ if (srvTcp) {
10794+ cFYI(1, ("Existing tcp session with server found "));
10795+ } else { /* create socket */
10796+ if(volume_info.port)
10797+ sin_server.sin_port = htons(volume_info.port);
10798+ else
10799+ sin_server.sin_port = 0;
10800+ rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
10801+ if (rc < 0) {
10802+ cERROR(1,
10803+ ("Error connecting to IPv4 socket. Aborting operation"));
10804+ if(csocket != NULL)
10805+ sock_release(csocket);
10806+ if(volume_info.UNC)
10807+ kfree(volume_info.UNC);
10808+ if(volume_info.password)
10809+ kfree(volume_info.password);
10810+ FreeXid(xid);
10811+ return rc;
10812+ }
10813+
10814+ srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
10815+ if (srvTcp == NULL) {
10816+ rc = -ENOMEM;
10817+ sock_release(csocket);
10818+ if(volume_info.UNC)
10819+ kfree(volume_info.UNC);
10820+ if(volume_info.password)
10821+ kfree(volume_info.password);
10822+ FreeXid(xid);
10823+ return rc;
10824+ } else {
10825+ memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
10826+ memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
10827+ atomic_set(&srvTcp->inFlight,0);
10828+ /* BB Add code for ipv6 case too */
10829+ srvTcp->ssocket = csocket;
10830+ srvTcp->protocolType = IPV4;
10831+ init_waitqueue_head(&srvTcp->response_q);
10832+ init_waitqueue_head(&srvTcp->request_q);
10833+ INIT_LIST_HEAD(&srvTcp->pending_mid_q);
10834+ /* at this point we are the only ones with the pointer
10835+ to the struct since the kernel thread not created yet
10836+ so no need to spinlock this init of tcpStatus */
10837+ srvTcp->tcpStatus = CifsNew;
10838+ init_MUTEX(&srvTcp->tcpSem);
10839+ kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
10840+ CLONE_FS | CLONE_FILES | CLONE_VM);
10841+ memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
10842+ }
10843+ }
10844+
10845+ if (existingCifsSes) {
10846+ pSesInfo = existingCifsSes;
10847+ cFYI(1, ("Existing smb sess found "));
10848+ if(volume_info.password)
10849+ kfree(volume_info.password);
10850+ /* volume_info.UNC freed at end of function */
10851+ } else if (!rc) {
10852+ cFYI(1, ("Existing smb sess not found "));
10853+ pSesInfo = sesInfoAlloc();
10854+ if (pSesInfo == NULL)
10855+ rc = -ENOMEM;
10856+ else {
10857+ pSesInfo->server = srvTcp;
10858+ sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
10859+ NIPQUAD(sin_server.sin_addr.s_addr));
10860+ }
10861+
10862+ if (!rc){
10863+ /* volume_info.password freed at unmount */
10864+ if (volume_info.password)
10865+ pSesInfo->password = volume_info.password;
10866+ if (volume_info.username)
10867+ strncpy(pSesInfo->userName,
10868+ volume_info.username,MAX_USERNAME_SIZE);
10869+ if (volume_info.domainname)
10870+ strncpy(pSesInfo->domainName,
10871+ volume_info.domainname,MAX_USERNAME_SIZE);
10872+ pSesInfo->linux_uid = volume_info.linux_uid;
10873+ down(&pSesInfo->sesSem);
10874+ rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
10875+ up(&pSesInfo->sesSem);
10876+ if(!rc)
10877+ atomic_inc(&srvTcp->socketUseCount);
10878+ } else
10879+ if(volume_info.password)
10880+ kfree(volume_info.password);
10881+ }
10882+
10883+ /* search for existing tcon to this server share */
10884+ if (!rc) {
10885+ if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
10886+ cifs_sb->rsize = volume_info.rsize;
10887+ else
10888+ cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
10889+ if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
10890+ cifs_sb->wsize = volume_info.wsize;
10891+ else
10892+ cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
10893+ if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
10894+ cifs_sb->rsize = PAGE_CACHE_SIZE;
10895+ cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
10896+ }
10897+ cifs_sb->mnt_uid = volume_info.linux_uid;
10898+ cifs_sb->mnt_gid = volume_info.linux_gid;
10899+ cifs_sb->mnt_file_mode = volume_info.file_mode;
10900+ cifs_sb->mnt_dir_mode = volume_info.dir_mode;
10901+ cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
10902+ tcon =
10903+ find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
10904+ volume_info.username);
10905+ if (tcon) {
10906+ cFYI(1, ("Found match on UNC path "));
10907+ /* we can have only one retry value for a connection
10908+ to a share so for resources mounted more than once
10909+ to the same server share the last value passed in
10910+ for the retry flag is used */
10911+ tcon->retry = volume_info.retry;
10912+ } else {
10913+ tcon = tconInfoAlloc();
10914+ if (tcon == NULL)
10915+ rc = -ENOMEM;
10916+ else {
10917+ /* check for null share name ie connect to dfs root */
10918+
10919+ /* BB check if this works for exactly length three strings */
10920+ if ((strchr(volume_info.UNC + 3, '\\') == NULL)
10921+ && (strchr(volume_info.UNC + 3, '/') ==
10922+ NULL)) {
10923+ rc = connect_to_dfs_path(xid,
10924+ pSesInfo,
10925+ "",
10926+ cifs_sb->
10927+ local_nls);
10928+ if(volume_info.UNC)
10929+ kfree(volume_info.UNC);
10930+ FreeXid(xid);
10931+ return -ENODEV;
10932+ } else {
10933+ rc = CIFSTCon(xid, pSesInfo,
10934+ volume_info.UNC,
10935+ tcon, cifs_sb->local_nls);
10936+ cFYI(1, ("CIFS Tcon rc = %d", rc));
10937+ }
10938+ if (!rc) {
10939+ atomic_inc(&pSesInfo->inUse);
10940+ tcon->retry = volume_info.retry;
10941+ }
10942+ }
10943+ }
10944+ }
10945+ if(pSesInfo) {
10946+ if (pSesInfo->capabilities & CAP_LARGE_FILES) {
10947+ sb->s_maxbytes = (u64) 1 << 63;
10948+ } else
10949+ sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
10950+ }
10951+
10952+/* on error free sesinfo and tcon struct if needed */
10953+ if (rc) {
10954+ /* if session setup failed, use count is zero but
10955+ we still need to free cifsd thread */
10956+ if(atomic_read(&srvTcp->socketUseCount) == 0) {
10957+ spin_lock(&GlobalMid_Lock);
10958+ srvTcp->tcpStatus = CifsExiting;
10959+ spin_unlock(&GlobalMid_Lock);
10960+ if(srvTcp->tsk)
10961+ send_sig(SIGKILL,srvTcp->tsk,1);
10962+ }
10963+ /* If find_unc succeeded then rc == 0 so we can not end */
10964+ if (tcon) /* up accidently freeing someone elses tcon struct */
10965+ tconInfoFree(tcon);
10966+ if (existingCifsSes == 0) {
10967+ if (pSesInfo) {
10968+ if ((pSesInfo->server) &&
10969+ (pSesInfo->status == CifsGood)) {
10970+ int temp_rc;
10971+ temp_rc = CIFSSMBLogoff(xid, pSesInfo);
10972+ /* if the socketUseCount is now zero */
10973+ if((temp_rc == -ESHUTDOWN) &&
10974+ (pSesInfo->server->tsk))
10975+ send_sig(SIGKILL,pSesInfo->server->tsk,1);
10976+ } else
10977+ cFYI(1, ("No session or bad tcon"));
10978+ sesInfoFree(pSesInfo);
10979+ /* pSesInfo = NULL; */
10980+ }
10981+ }
10982+ } else {
10983+ atomic_inc(&tcon->useCount);
10984+ cifs_sb->tcon = tcon;
10985+ tcon->ses = pSesInfo;
10986+
10987+ /* do not care if following two calls succeed - informational only */
10988+ CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
10989+ CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
10990+ if (tcon->ses->capabilities & CAP_UNIX)
10991+ CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
10992+ }
10993+
10994+ /* volume_info.password is freed above when existing session found
10995+ (in which case it is not needed anymore) but when new sesion is created
10996+ the password ptr is put in the new session structure (in which case the
10997+ password will be freed at unmount time) */
10998+ if(volume_info.UNC)
10999+ kfree(volume_info.UNC);
11000+ FreeXid(xid);
11001+ return rc;
11002+}
11003+
11004+static int
11005+CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11006+ char session_key[CIFS_SESSION_KEY_SIZE],
11007+ const struct nls_table *nls_codepage)
11008+{
11009+ struct smb_hdr *smb_buffer;
11010+ struct smb_hdr *smb_buffer_response;
11011+ SESSION_SETUP_ANDX *pSMB;
11012+ SESSION_SETUP_ANDX *pSMBr;
11013+ char *bcc_ptr;
11014+ char *user = ses->userName;
11015+ char *domain = ses->domainName;
11016+ int rc = 0;
11017+ int remaining_words = 0;
11018+ int bytes_returned = 0;
11019+ int len;
11020+
11021+ cFYI(1, ("In sesssetup "));
11022+
11023+ smb_buffer = cifs_buf_get();
11024+ if (smb_buffer == 0) {
11025+ return -ENOMEM;
11026+ }
11027+ smb_buffer_response = smb_buffer;
11028+ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11029+
11030+ /* send SMBsessionSetup here */
11031+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11032+ NULL /* no tCon exists yet */ , 13 /* wct */ );
11033+
11034+ pSMB->req_no_secext.AndXCommand = 0xFF;
11035+ pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11036+ pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11037+
11038+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11039+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11040+
11041+ pSMB->req_no_secext.Capabilities =
11042+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
11043+ if (ses->capabilities & CAP_UNICODE) {
11044+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11045+ pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
11046+ }
11047+ if (ses->capabilities & CAP_STATUS32) {
11048+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11049+ pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
11050+ }
11051+ if (ses->capabilities & CAP_DFS) {
11052+ smb_buffer->Flags2 |= SMBFLG2_DFS;
11053+ pSMB->req_no_secext.Capabilities |= CAP_DFS;
11054+ }
11055+ pSMB->req_no_secext.Capabilities =
11056+ cpu_to_le32(pSMB->req_no_secext.Capabilities);
11057+ /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
11058+ CIFS_SESSION_KEY_SIZE; */
11059+ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
11060+ pSMB->req_no_secext.CaseSensitivePasswordLength =
11061+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11062+ bcc_ptr = pByteArea(smb_buffer);
11063+ /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
11064+ bcc_ptr += CIFS_SESSION_KEY_SIZE; */
11065+ memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
11066+ bcc_ptr += CIFS_SESSION_KEY_SIZE;
11067+
11068+ if (ses->capabilities & CAP_UNICODE) {
11069+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
11070+ *bcc_ptr = 0;
11071+ bcc_ptr++;
11072+ }
11073+ if(user == NULL)
11074+ bytes_returned = 0; /* skill null user */
11075+ else
11076+ bytes_returned =
11077+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
11078+ nls_codepage);
11079+ bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
11080+ bcc_ptr += 2; /* trailing null */
11081+ if (domain == NULL)
11082+ bytes_returned =
11083+ cifs_strtoUCS((wchar_t *) bcc_ptr,
11084+ "CIFS_LINUX_DOM", 32, nls_codepage);
11085+ else
11086+ bytes_returned =
11087+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11088+ nls_codepage);
11089+ bcc_ptr += 2 * bytes_returned;
11090+ bcc_ptr += 2;
11091+ bytes_returned =
11092+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11093+ 32, nls_codepage);
11094+ bcc_ptr += 2 * bytes_returned;
11095+ bytes_returned =
11096+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11097+ nls_codepage);
11098+ bcc_ptr += 2 * bytes_returned;
11099+ bcc_ptr += 2;
11100+ bytes_returned =
11101+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11102+ 64, nls_codepage);
11103+ bcc_ptr += 2 * bytes_returned;
11104+ bcc_ptr += 2;
11105+ } else {
11106+ if(user != NULL) {
11107+ strncpy(bcc_ptr, user, 200);
11108+ bcc_ptr += strnlen(user, 200);
11109+ }
11110+ *bcc_ptr = 0;
11111+ bcc_ptr++;
11112+ if (domain == NULL) {
11113+ strcpy(bcc_ptr, "CIFS_LINUX_DOM");
11114+ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
11115+ } else {
11116+ strncpy(bcc_ptr, domain, 64);
11117+ bcc_ptr += strnlen(domain, 64);
11118+ *bcc_ptr = 0;
11119+ bcc_ptr++;
11120+ }
11121+ strcpy(bcc_ptr, "Linux version ");
11122+ bcc_ptr += strlen("Linux version ");
11123+ strcpy(bcc_ptr, UTS_RELEASE);
11124+ bcc_ptr += strlen(UTS_RELEASE) + 1;
11125+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11126+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11127+ }
11128+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11129+ smb_buffer->smb_buf_length += BCC(smb_buffer);
11130+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11131+
11132+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11133+ &bytes_returned, 1);
11134+ if (rc) {
11135+/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
11136+ } else if ((smb_buffer_response->WordCount == 3)
11137+ || (smb_buffer_response->WordCount == 4)) {
11138+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11139+ if (pSMBr->resp.Action & GUEST_LOGIN)
11140+ cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
11141+ if (ses) {
11142+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
11143+ cFYI(1, ("UID = %d ", ses->Suid));
11144+ /* response can have either 3 or 4 word count - Samba sends 3 */
11145+ bcc_ptr = pByteArea(smb_buffer_response);
11146+ if ((pSMBr->resp.hdr.WordCount == 3)
11147+ || ((pSMBr->resp.hdr.WordCount == 4)
11148+ && (pSMBr->resp.SecurityBlobLength <
11149+ pSMBr->resp.ByteCount))) {
11150+ if (pSMBr->resp.hdr.WordCount == 4)
11151+ bcc_ptr +=
11152+ pSMBr->resp.SecurityBlobLength;
11153+
11154+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11155+ if ((long) (bcc_ptr) % 2) {
11156+ remaining_words =
11157+ (BCC(smb_buffer_response)
11158+ - 1) / 2;
11159+ bcc_ptr++; /* Unicode strings must be word aligned */
11160+ } else {
11161+ remaining_words =
11162+ BCC
11163+ (smb_buffer_response) / 2;
11164+ }
11165+ len =
11166+ UniStrnlen((wchar_t *) bcc_ptr,
11167+ remaining_words - 1);
11168+/* We look for obvious messed up bcc or strings in response so we do not go off
11169+ the end since (at least) WIN2K and Windows XP have a major bug in not null
11170+ terminating last Unicode string in response */
11171+ ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11172+ cifs_strfromUCS_le(ses->serverOS,
11173+ (wchar_t *)bcc_ptr, len,nls_codepage);
11174+ bcc_ptr += 2 * (len + 1);
11175+ remaining_words -= len + 1;
11176+ ses->serverOS[2 * len] = 0;
11177+ ses->serverOS[1 + (2 * len)] = 0;
11178+ if (remaining_words > 0) {
11179+ len = UniStrnlen((wchar_t *)bcc_ptr,
11180+ remaining_words
11181+ - 1);
11182+ ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
11183+ cifs_strfromUCS_le(ses->serverNOS,
11184+ (wchar_t *)bcc_ptr,len,nls_codepage);
11185+ bcc_ptr += 2 * (len + 1);
11186+ ses->serverNOS[2 * len] = 0;
11187+ ses->serverNOS[1 + (2 * len)] = 0;
11188+ remaining_words -= len + 1;
11189+ if (remaining_words > 0) {
11190+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11191+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11192+ ses->serverDomain =
11193+ cifs_kcalloc(2*(len+1),GFP_KERNEL);
11194+ cifs_strfromUCS_le(ses->serverDomain,
11195+ (wchar_t *)bcc_ptr,len,nls_codepage);
11196+ bcc_ptr += 2 * (len + 1);
11197+ ses->serverDomain[2*len] = 0;
11198+ ses->serverDomain[1+(2*len)] = 0;
11199+ } /* else no more room so create dummy domain string */
11200+ else
11201+ ses->serverDomain =
11202+ cifs_kcalloc(2,
11203+ GFP_KERNEL);
11204+ } else { /* no room so create dummy domain and NOS string */
11205+ ses->serverDomain =
11206+ cifs_kcalloc(2, GFP_KERNEL);
11207+ ses->serverNOS =
11208+ cifs_kcalloc(2, GFP_KERNEL);
11209+ }
11210+ } else { /* ASCII */
11211+ len = strnlen(bcc_ptr, 1024);
11212+ if (((long) bcc_ptr + len) - (long)
11213+ pByteArea(smb_buffer_response)
11214+ <= BCC(smb_buffer_response)) {
11215+ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11216+ strncpy(ses->serverOS,bcc_ptr, len);
11217+
11218+ bcc_ptr += len;
11219+ bcc_ptr[0] = 0; /* null terminate the string */
11220+ bcc_ptr++;
11221+
11222+ len = strnlen(bcc_ptr, 1024);
11223+ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11224+ strncpy(ses->serverNOS, bcc_ptr, len);
11225+ bcc_ptr += len;
11226+ bcc_ptr[0] = 0;
11227+ bcc_ptr++;
11228+
11229+ len = strnlen(bcc_ptr, 1024);
11230+ ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
11231+ strncpy(ses->serverDomain, bcc_ptr, len);
11232+ bcc_ptr += len;
11233+ bcc_ptr[0] = 0;
11234+ bcc_ptr++;
11235+ } else
11236+ cFYI(1,
11237+ ("Variable field of length %d extends beyond end of smb ",
11238+ len));
11239+ }
11240+ } else {
11241+ cERROR(1,
11242+ (" Security Blob Length extends beyond end of SMB"));
11243+ }
11244+ } else {
11245+ cERROR(1, ("No session structure passed in."));
11246+ }
11247+ } else {
11248+ cERROR(1,
11249+ (" Invalid Word count %d: ",
11250+ smb_buffer_response->WordCount));
11251+ rc = -EIO;
11252+ }
11253+
11254+ if (smb_buffer)
11255+ cifs_buf_release(smb_buffer);
11256+
11257+ return rc;
11258+}
11259+
11260+static int
11261+CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11262+ char *SecurityBlob,int SecurityBlobLength,
11263+ const struct nls_table *nls_codepage)
11264+{
11265+ struct smb_hdr *smb_buffer;
11266+ struct smb_hdr *smb_buffer_response;
11267+ SESSION_SETUP_ANDX *pSMB;
11268+ SESSION_SETUP_ANDX *pSMBr;
11269+ char *bcc_ptr;
11270+ char *user = ses->userName;
11271+ char *domain = ses->domainName;
11272+ int rc = 0;
11273+ int remaining_words = 0;
11274+ int bytes_returned = 0;
11275+ int len;
11276+
11277+ cFYI(1, ("In spnego sesssetup "));
11278+
11279+ smb_buffer = cifs_buf_get();
11280+ if (smb_buffer == 0) {
11281+ return -ENOMEM;
11282+ }
11283+ smb_buffer_response = smb_buffer;
11284+ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11285+
11286+ /* send SMBsessionSetup here */
11287+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11288+ NULL /* no tCon exists yet */ , 12 /* wct */ );
11289+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11290+ pSMB->req.AndXCommand = 0xFF;
11291+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11292+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11293+
11294+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11295+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11296+
11297+ pSMB->req.Capabilities =
11298+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11299+ CAP_EXTENDED_SECURITY;
11300+ if (ses->capabilities & CAP_UNICODE) {
11301+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11302+ pSMB->req.Capabilities |= CAP_UNICODE;
11303+ }
11304+ if (ses->capabilities & CAP_STATUS32) {
11305+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11306+ pSMB->req.Capabilities |= CAP_STATUS32;
11307+ }
11308+ if (ses->capabilities & CAP_DFS) {
11309+ smb_buffer->Flags2 |= SMBFLG2_DFS;
11310+ pSMB->req.Capabilities |= CAP_DFS;
11311+ }
11312+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11313+
11314+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
11315+ bcc_ptr = pByteArea(smb_buffer);
11316+ memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
11317+ bcc_ptr += SecurityBlobLength;
11318+
11319+ if (ses->capabilities & CAP_UNICODE) {
11320+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
11321+ *bcc_ptr = 0;
11322+ bcc_ptr++;
11323+ }
11324+ bytes_returned =
11325+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
11326+ bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
11327+ bcc_ptr += 2; /* trailing null */
11328+ if (domain == NULL)
11329+ bytes_returned =
11330+ cifs_strtoUCS((wchar_t *) bcc_ptr,
11331+ "CIFS_LINUX_DOM", 32, nls_codepage);
11332+ else
11333+ bytes_returned =
11334+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11335+ nls_codepage);
11336+ bcc_ptr += 2 * bytes_returned;
11337+ bcc_ptr += 2;
11338+ bytes_returned =
11339+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11340+ 32, nls_codepage);
11341+ bcc_ptr += 2 * bytes_returned;
11342+ bytes_returned =
11343+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11344+ nls_codepage);
11345+ bcc_ptr += 2 * bytes_returned;
11346+ bcc_ptr += 2;
11347+ bytes_returned =
11348+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11349+ 64, nls_codepage);
11350+ bcc_ptr += 2 * bytes_returned;
11351+ bcc_ptr += 2;
11352+ } else {
11353+ strncpy(bcc_ptr, user, 200);
11354+ bcc_ptr += strnlen(user, 200);
11355+ *bcc_ptr = 0;
11356+ bcc_ptr++;
11357+ if (domain == NULL) {
11358+ strcpy(bcc_ptr, "CIFS_LINUX_DOM");
11359+ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
11360+ } else {
11361+ strncpy(bcc_ptr, domain, 64);
11362+ bcc_ptr += strnlen(domain, 64);
11363+ *bcc_ptr = 0;
11364+ bcc_ptr++;
11365+ }
11366+ strcpy(bcc_ptr, "Linux version ");
11367+ bcc_ptr += strlen("Linux version ");
11368+ strcpy(bcc_ptr, UTS_RELEASE);
11369+ bcc_ptr += strlen(UTS_RELEASE) + 1;
11370+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11371+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11372+ }
11373+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11374+ smb_buffer->smb_buf_length += BCC(smb_buffer);
11375+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11376+
11377+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11378+ &bytes_returned, 1);
11379+ if (rc) {
11380+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
11381+ } else if ((smb_buffer_response->WordCount == 3)
11382+ || (smb_buffer_response->WordCount == 4)) {
11383+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11384+ pSMBr->resp.SecurityBlobLength =
11385+ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
11386+ if (pSMBr->resp.Action & GUEST_LOGIN)
11387+ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
11388+ if (ses) {
11389+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
11390+ cFYI(1, ("UID = %d ", ses->Suid));
11391+ bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
11392+
11393+ /* BB Fix below to make endian neutral !! */
11394+
11395+ if ((pSMBr->resp.hdr.WordCount == 3)
11396+ || ((pSMBr->resp.hdr.WordCount == 4)
11397+ && (pSMBr->resp.SecurityBlobLength <
11398+ pSMBr->resp.ByteCount))) {
11399+ if (pSMBr->resp.hdr.WordCount == 4) {
11400+ bcc_ptr +=
11401+ pSMBr->resp.SecurityBlobLength;
11402+ cFYI(1,
11403+ ("Security Blob Length %d ",
11404+ pSMBr->resp.SecurityBlobLength));
11405+ }
11406+
11407+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11408+ if ((long) (bcc_ptr) % 2) {
11409+ remaining_words =
11410+ (BCC(smb_buffer_response)
11411+ - 1) / 2;
11412+ bcc_ptr++; /* Unicode strings must be word aligned */
11413+ } else {
11414+ remaining_words =
11415+ BCC
11416+ (smb_buffer_response) / 2;
11417+ }
11418+ len =
11419+ UniStrnlen((wchar_t *) bcc_ptr,
11420+ remaining_words - 1);
11421+/* We look for obvious messed up bcc or strings in response so we do not go off
11422+ the end since (at least) WIN2K and Windows XP have a major bug in not null
11423+ terminating last Unicode string in response */
11424+ ses->serverOS =
11425+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11426+ cifs_strfromUCS_le(ses->serverOS,
11427+ (wchar_t *)
11428+ bcc_ptr, len,
11429+ nls_codepage);
11430+ bcc_ptr += 2 * (len + 1);
11431+ remaining_words -= len + 1;
11432+ ses->serverOS[2 * len] = 0;
11433+ ses->serverOS[1 + (2 * len)] = 0;
11434+ if (remaining_words > 0) {
11435+ len = UniStrnlen((wchar_t *)bcc_ptr,
11436+ remaining_words
11437+ - 1);
11438+ ses->serverNOS =
11439+ cifs_kcalloc(2 * (len + 1),
11440+ GFP_KERNEL);
11441+ cifs_strfromUCS_le(ses->serverNOS,
11442+ (wchar_t *)bcc_ptr,
11443+ len,
11444+ nls_codepage);
11445+ bcc_ptr += 2 * (len + 1);
11446+ ses->serverNOS[2 * len] = 0;
11447+ ses->serverNOS[1 + (2 * len)] = 0;
11448+ remaining_words -= len + 1;
11449+ if (remaining_words > 0) {
11450+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11451+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11452+ ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
11453+ cifs_strfromUCS_le(ses->serverDomain,
11454+ (wchar_t *)bcc_ptr,
11455+ len,
11456+ nls_codepage);
11457+ bcc_ptr += 2*(len+1);
11458+ ses->serverDomain[2*len] = 0;
11459+ ses->serverDomain[1+(2*len)] = 0;
11460+ } /* else no more room so create dummy domain string */
11461+ else
11462+ ses->serverDomain =
11463+ cifs_kcalloc(2,GFP_KERNEL);
11464+ } else { /* no room so create dummy domain and NOS string */
11465+ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
11466+ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
11467+ }
11468+ } else { /* ASCII */
11469+
11470+ len = strnlen(bcc_ptr, 1024);
11471+ if (((long) bcc_ptr + len) - (long)
11472+ pByteArea(smb_buffer_response)
11473+ <= BCC(smb_buffer_response)) {
11474+ ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
11475+ strncpy(ses->serverOS, bcc_ptr, len);
11476+
11477+ bcc_ptr += len;
11478+ bcc_ptr[0] = 0; /* null terminate the string */
11479+ bcc_ptr++;
11480+
11481+ len = strnlen(bcc_ptr, 1024);
11482+ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11483+ strncpy(ses->serverNOS, bcc_ptr, len);
11484+ bcc_ptr += len;
11485+ bcc_ptr[0] = 0;
11486+ bcc_ptr++;
11487+
11488+ len = strnlen(bcc_ptr, 1024);
11489+ ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
11490+ strncpy(ses->serverDomain, bcc_ptr, len);
11491+ bcc_ptr += len;
11492+ bcc_ptr[0] = 0;
11493+ bcc_ptr++;
11494+ } else
11495+ cFYI(1,
11496+ ("Variable field of length %d extends beyond end of smb ",
11497+ len));
11498+ }
11499+ } else {
11500+ cERROR(1,
11501+ (" Security Blob Length extends beyond end of SMB"));
11502+ }
11503+ } else {
11504+ cERROR(1, ("No session structure passed in."));
11505+ }
11506+ } else {
11507+ cERROR(1,
11508+ (" Invalid Word count %d: ",
11509+ smb_buffer_response->WordCount));
11510+ rc = -EIO;
11511+ }
11512+
11513+ if (smb_buffer)
11514+ cifs_buf_release(smb_buffer);
11515+
11516+ return rc;
11517+}
11518+
11519+static int
11520+CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
11521+ struct cifsSesInfo *ses, int * pNTLMv2_flag,
11522+ const struct nls_table *nls_codepage)
11523+{
11524+ struct smb_hdr *smb_buffer;
11525+ struct smb_hdr *smb_buffer_response;
11526+ SESSION_SETUP_ANDX *pSMB;
11527+ SESSION_SETUP_ANDX *pSMBr;
11528+ char *bcc_ptr;
11529+ char *domain = ses->domainName;
11530+ int rc = 0;
11531+ int remaining_words = 0;
11532+ int bytes_returned = 0;
11533+ int len;
11534+ int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
11535+ PNEGOTIATE_MESSAGE SecurityBlob;
11536+ PCHALLENGE_MESSAGE SecurityBlob2;
11537+
11538+ cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
11539+ *pNTLMv2_flag = FALSE;
11540+ smb_buffer = cifs_buf_get();
11541+ if (smb_buffer == 0) {
11542+ return -ENOMEM;
11543+ }
11544+ smb_buffer_response = smb_buffer;
11545+ pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11546+ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
11547+
11548+ /* send SMBsessionSetup here */
11549+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11550+ NULL /* no tCon exists yet */ , 12 /* wct */ );
11551+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11552+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
11553+
11554+ pSMB->req.AndXCommand = 0xFF;
11555+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11556+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11557+
11558+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11559+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11560+
11561+ pSMB->req.Capabilities =
11562+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11563+ CAP_EXTENDED_SECURITY;
11564+ if (ses->capabilities & CAP_UNICODE) {
11565+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11566+ pSMB->req.Capabilities |= CAP_UNICODE;
11567+ }
11568+ if (ses->capabilities & CAP_STATUS32) {
11569+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11570+ pSMB->req.Capabilities |= CAP_STATUS32;
11571+ }
11572+ if (ses->capabilities & CAP_DFS) {
11573+ smb_buffer->Flags2 |= SMBFLG2_DFS;
11574+ pSMB->req.Capabilities |= CAP_DFS;
11575+ }
11576+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11577+
11578+ bcc_ptr = (char *) &pSMB->req.SecurityBlob;
11579+ SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
11580+ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
11581+ SecurityBlob->MessageType = NtLmNegotiate;
11582+ SecurityBlob->NegotiateFlags =
11583+ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
11584+ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
11585+ /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
11586+ if(sign_CIFS_PDUs)
11587+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
11588+ if(ntlmv2_support)
11589+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
11590+ /* setup pointers to domain name and workstation name */
11591+ bcc_ptr += SecurityBlobLength;
11592+
11593+ SecurityBlob->WorkstationName.Buffer = 0;
11594+ SecurityBlob->WorkstationName.Length = 0;
11595+ SecurityBlob->WorkstationName.MaximumLength = 0;
11596+
11597+ if (domain == NULL) {
11598+ SecurityBlob->DomainName.Buffer = 0;
11599+ SecurityBlob->DomainName.Length = 0;
11600+ SecurityBlob->DomainName.MaximumLength = 0;
11601+ } else {
11602+ SecurityBlob->NegotiateFlags |=
11603+ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
11604+ strncpy(bcc_ptr, domain, 63);
11605+ SecurityBlob->DomainName.Length = strnlen(domain, 64);
11606+ SecurityBlob->DomainName.MaximumLength =
11607+ cpu_to_le16(SecurityBlob->DomainName.Length);
11608+ SecurityBlob->DomainName.Buffer =
11609+ cpu_to_le32((long) &SecurityBlob->
11610+ DomainString -
11611+ (long) &SecurityBlob->Signature);
11612+ bcc_ptr += SecurityBlob->DomainName.Length;
11613+ SecurityBlobLength += SecurityBlob->DomainName.Length;
11614+ SecurityBlob->DomainName.Length =
11615+ cpu_to_le16(SecurityBlob->DomainName.Length);
11616+ }
11617+ if (ses->capabilities & CAP_UNICODE) {
11618+ if ((long) bcc_ptr % 2) {
11619+ *bcc_ptr = 0;
11620+ bcc_ptr++;
11621+ }
11622+
11623+ bytes_returned =
11624+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11625+ 32, nls_codepage);
11626+ bcc_ptr += 2 * bytes_returned;
11627+ bytes_returned =
11628+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11629+ nls_codepage);
11630+ bcc_ptr += 2 * bytes_returned;
11631+ bcc_ptr += 2; /* null terminate Linux version */
11632+ bytes_returned =
11633+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11634+ 64, nls_codepage);
11635+ bcc_ptr += 2 * bytes_returned;
11636+ *(bcc_ptr + 1) = 0;
11637+ *(bcc_ptr + 2) = 0;
11638+ bcc_ptr += 2; /* null terminate network opsys string */
11639+ *(bcc_ptr + 1) = 0;
11640+ *(bcc_ptr + 2) = 0;
11641+ bcc_ptr += 2; /* null domain */
11642+ } else { /* ASCII */
11643+ strcpy(bcc_ptr, "Linux version ");
11644+ bcc_ptr += strlen("Linux version ");
11645+ strcpy(bcc_ptr, UTS_RELEASE);
11646+ bcc_ptr += strlen(UTS_RELEASE) + 1;
11647+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11648+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11649+ bcc_ptr++; /* empty domain field */
11650+ *bcc_ptr = 0;
11651+ }
11652+ SecurityBlob->NegotiateFlags =
11653+ cpu_to_le32(SecurityBlob->NegotiateFlags);
11654+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
11655+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11656+ smb_buffer->smb_buf_length += BCC(smb_buffer);
11657+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11658+
11659+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11660+ &bytes_returned, 1);
11661+
11662+ if (smb_buffer_response->Status.CifsError ==
11663+ (NT_STATUS_MORE_PROCESSING_REQUIRED))
11664+ rc = 0;
11665+
11666+ if (rc) {
11667+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
11668+ } else if ((smb_buffer_response->WordCount == 3)
11669+ || (smb_buffer_response->WordCount == 4)) {
11670+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11671+ pSMBr->resp.SecurityBlobLength =
11672+ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
11673+ if (pSMBr->resp.Action & GUEST_LOGIN)
11674+ cFYI(1, (" Guest login"));
11675+ /* Do we want to set anything in SesInfo struct when guest login? */
11676+
11677+ bcc_ptr = pByteArea(smb_buffer_response);
11678+ /* response can have either 3 or 4 word count - Samba sends 3 */
11679+
11680+ SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
11681+ if (SecurityBlob2->MessageType != NtLmChallenge) {
11682+ cFYI(1,
11683+ ("Unexpected NTLMSSP message type received %d",
11684+ SecurityBlob2->MessageType));
11685+ } else if (ses) {
11686+ ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
11687+ cFYI(1, ("UID = %d ", ses->Suid));
11688+ if ((pSMBr->resp.hdr.WordCount == 3)
11689+ || ((pSMBr->resp.hdr.WordCount == 4)
11690+ && (pSMBr->resp.SecurityBlobLength <
11691+ pSMBr->resp.ByteCount))) {
11692+ if (pSMBr->resp.hdr.WordCount == 4) {
11693+ bcc_ptr +=
11694+ pSMBr->resp.SecurityBlobLength;
11695+ cFYI(1,
11696+ ("Security Blob Length %d ",
11697+ pSMBr->resp.SecurityBlobLength));
11698+ }
11699+
11700+ cFYI(1, ("NTLMSSP Challenge rcvd "));
11701+
11702+ memcpy(ses->server->cryptKey,
11703+ SecurityBlob2->Challenge,
11704+ CIFS_CRYPTO_KEY_SIZE);
11705+ if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
11706+ *pNTLMv2_flag = TRUE;
11707+
11708+ if((SecurityBlob2->NegotiateFlags &
11709+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
11710+ || (sign_CIFS_PDUs > 1))
11711+ ses->server->secMode |=
11712+ SECMODE_SIGN_REQUIRED;
11713+ if ((SecurityBlob2->NegotiateFlags &
11714+ NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
11715+ ses->server->secMode |=
11716+ SECMODE_SIGN_ENABLED;
11717+
11718+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11719+ if ((long) (bcc_ptr) % 2) {
11720+ remaining_words =
11721+ (BCC(smb_buffer_response)
11722+ - 1) / 2;
11723+ bcc_ptr++; /* Unicode strings must be word aligned */
11724+ } else {
11725+ remaining_words =
11726+ BCC
11727+ (smb_buffer_response) / 2;
11728+ }
11729+ len =
11730+ UniStrnlen((wchar_t *) bcc_ptr,
11731+ remaining_words - 1);
11732+/* We look for obvious messed up bcc or strings in response so we do not go off
11733+ the end since (at least) WIN2K and Windows XP have a major bug in not null
11734+ terminating last Unicode string in response */
11735+ ses->serverOS =
11736+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11737+ cifs_strfromUCS_le(ses->serverOS,
11738+ (wchar_t *)
11739+ bcc_ptr, len,
11740+ nls_codepage);
11741+ bcc_ptr += 2 * (len + 1);
11742+ remaining_words -= len + 1;
11743+ ses->serverOS[2 * len] = 0;
11744+ ses->serverOS[1 + (2 * len)] = 0;
11745+ if (remaining_words > 0) {
11746+ len = UniStrnlen((wchar_t *)
11747+ bcc_ptr,
11748+ remaining_words
11749+ - 1);
11750+ ses->serverNOS =
11751+ cifs_kcalloc(2 * (len + 1),
11752+ GFP_KERNEL);
11753+ cifs_strfromUCS_le(ses->
11754+ serverNOS,
11755+ (wchar_t *)
11756+ bcc_ptr,
11757+ len,
11758+ nls_codepage);
11759+ bcc_ptr += 2 * (len + 1);
11760+ ses->serverNOS[2 * len] = 0;
11761+ ses->serverNOS[1 +
11762+ (2 * len)] = 0;
11763+ remaining_words -= len + 1;
11764+ if (remaining_words > 0) {
11765+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11766+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11767+ ses->serverDomain =
11768+ cifs_kcalloc(2 *
11769+ (len +
11770+ 1),
11771+ GFP_KERNEL);
11772+ cifs_strfromUCS_le
11773+ (ses->
11774+ serverDomain,
11775+ (wchar_t *)
11776+ bcc_ptr, len,
11777+ nls_codepage);
11778+ bcc_ptr +=
11779+ 2 * (len + 1);
11780+ ses->
11781+ serverDomain[2
11782+ * len]
11783+ = 0;
11784+ ses->
11785+ serverDomain[1
11786+ +
11787+ (2
11788+ *
11789+ len)]
11790+ = 0;
11791+ } /* else no more room so create dummy domain string */
11792+ else
11793+ ses->serverDomain =
11794+ cifs_kcalloc(2,
11795+ GFP_KERNEL);
11796+ } else { /* no room so create dummy domain and NOS string */
11797+ ses->serverDomain =
11798+ cifs_kcalloc(2, GFP_KERNEL);
11799+ ses->serverNOS =
11800+ cifs_kcalloc(2, GFP_KERNEL);
11801+ }
11802+ } else { /* ASCII */
11803+ len = strnlen(bcc_ptr, 1024);
11804+ if (((long) bcc_ptr + len) - (long)
11805+ pByteArea(smb_buffer_response)
11806+ <= BCC(smb_buffer_response)) {
11807+ ses->serverOS =
11808+ cifs_kcalloc(len + 1,
11809+ GFP_KERNEL);
11810+ strncpy(ses->serverOS,
11811+ bcc_ptr, len);
11812+
11813+ bcc_ptr += len;
11814+ bcc_ptr[0] = 0; /* null terminate string */
11815+ bcc_ptr++;
11816+
11817+ len = strnlen(bcc_ptr, 1024);
11818+ ses->serverNOS =
11819+ cifs_kcalloc(len + 1,
11820+ GFP_KERNEL);
11821+ strncpy(ses->serverNOS, bcc_ptr, len);
11822+ bcc_ptr += len;
11823+ bcc_ptr[0] = 0;
11824+ bcc_ptr++;
11825+
11826+ len = strnlen(bcc_ptr, 1024);
11827+ ses->serverDomain =
11828+ cifs_kcalloc(len + 1,
11829+ GFP_KERNEL);
11830+ strncpy(ses->serverDomain, bcc_ptr, len);
11831+ bcc_ptr += len;
11832+ bcc_ptr[0] = 0;
11833+ bcc_ptr++;
11834+ } else
11835+ cFYI(1,
11836+ ("Variable field of length %d extends beyond end of smb ",
11837+ len));
11838+ }
11839+ } else {
11840+ cERROR(1,
11841+ (" Security Blob Length extends beyond end of SMB"));
11842+ }
11843+ } else {
11844+ cERROR(1, ("No session structure passed in."));
11845+ }
11846+ } else {
11847+ cERROR(1,
11848+ (" Invalid Word count %d: ",
11849+ smb_buffer_response->WordCount));
11850+ rc = -EIO;
11851+ }
11852+
11853+ if (smb_buffer)
11854+ cifs_buf_release(smb_buffer);
11855+
11856+ return rc;
11857+}
11858+
11859+static int
11860+CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11861+ char *ntlm_session_key, int ntlmv2_flag,
11862+ const struct nls_table *nls_codepage)
11863+{
11864+ struct smb_hdr *smb_buffer;
11865+ struct smb_hdr *smb_buffer_response;
11866+ SESSION_SETUP_ANDX *pSMB;
11867+ SESSION_SETUP_ANDX *pSMBr;
11868+ char *bcc_ptr;
11869+ char *user = ses->userName;
11870+ char *domain = ses->domainName;
11871+ int rc = 0;
11872+ int remaining_words = 0;
11873+ int bytes_returned = 0;
11874+ int len;
11875+ int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
11876+ PAUTHENTICATE_MESSAGE SecurityBlob;
11877+
11878+ cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
11879+
11880+ smb_buffer = cifs_buf_get();
11881+ if (smb_buffer == 0) {
11882+ return -ENOMEM;
11883+ }
11884+ smb_buffer_response = smb_buffer;
11885+ pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11886+ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
11887+
11888+ /* send SMBsessionSetup here */
11889+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11890+ NULL /* no tCon exists yet */ , 12 /* wct */ );
11891+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
11892+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11893+ pSMB->req.AndXCommand = 0xFF;
11894+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11895+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11896+
11897+ pSMB->req.hdr.Uid = ses->Suid;
11898+
11899+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11900+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11901+
11902+ pSMB->req.Capabilities =
11903+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11904+ CAP_EXTENDED_SECURITY;
11905+ if (ses->capabilities & CAP_UNICODE) {
11906+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11907+ pSMB->req.Capabilities |= CAP_UNICODE;
11908+ }
11909+ if (ses->capabilities & CAP_STATUS32) {
11910+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11911+ pSMB->req.Capabilities |= CAP_STATUS32;
11912+ }
11913+ if (ses->capabilities & CAP_DFS) {
11914+ smb_buffer->Flags2 |= SMBFLG2_DFS;
11915+ pSMB->req.Capabilities |= CAP_DFS;
11916+ }
11917+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11918+
11919+ bcc_ptr = (char *) &pSMB->req.SecurityBlob;
11920+ SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
11921+ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
11922+ SecurityBlob->MessageType = NtLmAuthenticate;
11923+ bcc_ptr += SecurityBlobLength;
11924+ SecurityBlob->NegotiateFlags =
11925+ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
11926+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
11927+ 0x80000000 | NTLMSSP_NEGOTIATE_128;
11928+ if(sign_CIFS_PDUs)
11929+ SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
11930+ if(ntlmv2_flag)
11931+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
11932+
11933+/* setup pointers to domain name and workstation name */
11934+
11935+ SecurityBlob->WorkstationName.Buffer = 0;
11936+ SecurityBlob->WorkstationName.Length = 0;
11937+ SecurityBlob->WorkstationName.MaximumLength = 0;
11938+ SecurityBlob->SessionKey.Length = 0;
11939+ SecurityBlob->SessionKey.MaximumLength = 0;
11940+ SecurityBlob->SessionKey.Buffer = 0;
11941+
11942+ SecurityBlob->LmChallengeResponse.Length = 0;
11943+ SecurityBlob->LmChallengeResponse.MaximumLength = 0;
11944+ SecurityBlob->LmChallengeResponse.Buffer = 0;
11945+
11946+ SecurityBlob->NtChallengeResponse.Length =
11947+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11948+ SecurityBlob->NtChallengeResponse.MaximumLength =
11949+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11950+ memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
11951+ SecurityBlob->NtChallengeResponse.Buffer =
11952+ cpu_to_le32(SecurityBlobLength);
11953+ SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
11954+ bcc_ptr += CIFS_SESSION_KEY_SIZE;
11955+
11956+ if (ses->capabilities & CAP_UNICODE) {
11957+ if (domain == NULL) {
11958+ SecurityBlob->DomainName.Buffer = 0;
11959+ SecurityBlob->DomainName.Length = 0;
11960+ SecurityBlob->DomainName.MaximumLength = 0;
11961+ } else {
11962+ SecurityBlob->DomainName.Length =
11963+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11964+ nls_codepage);
11965+ SecurityBlob->DomainName.Length *= 2;
11966+ SecurityBlob->DomainName.MaximumLength =
11967+ cpu_to_le16(SecurityBlob->DomainName.Length);
11968+ SecurityBlob->DomainName.Buffer =
11969+ cpu_to_le32(SecurityBlobLength);
11970+ bcc_ptr += SecurityBlob->DomainName.Length;
11971+ SecurityBlobLength += SecurityBlob->DomainName.Length;
11972+ SecurityBlob->DomainName.Length =
11973+ cpu_to_le16(SecurityBlob->DomainName.Length);
11974+ }
11975+ if (user == NULL) {
11976+ SecurityBlob->UserName.Buffer = 0;
11977+ SecurityBlob->UserName.Length = 0;
11978+ SecurityBlob->UserName.MaximumLength = 0;
11979+ } else {
11980+ SecurityBlob->UserName.Length =
11981+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
11982+ nls_codepage);
11983+ SecurityBlob->UserName.Length *= 2;
11984+ SecurityBlob->UserName.MaximumLength =
11985+ cpu_to_le16(SecurityBlob->UserName.Length);
11986+ SecurityBlob->UserName.Buffer =
11987+ cpu_to_le32(SecurityBlobLength);
11988+ bcc_ptr += SecurityBlob->UserName.Length;
11989+ SecurityBlobLength += SecurityBlob->UserName.Length;
11990+ SecurityBlob->UserName.Length =
11991+ cpu_to_le16(SecurityBlob->UserName.Length);
11992+ }
11993+
11994+ /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
11995+ SecurityBlob->WorkstationName.Length *= 2;
11996+ SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
11997+ SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
11998+ bcc_ptr += SecurityBlob->WorkstationName.Length;
11999+ SecurityBlobLength += SecurityBlob->WorkstationName.Length;
12000+ SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
12001+
12002+ if ((long) bcc_ptr % 2) {
12003+ *bcc_ptr = 0;
12004+ bcc_ptr++;
12005+ }
12006+ bytes_returned =
12007+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
12008+ 32, nls_codepage);
12009+ bcc_ptr += 2 * bytes_returned;
12010+ bytes_returned =
12011+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
12012+ nls_codepage);
12013+ bcc_ptr += 2 * bytes_returned;
12014+ bcc_ptr += 2; /* null term version string */
12015+ bytes_returned =
12016+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
12017+ 64, nls_codepage);
12018+ bcc_ptr += 2 * bytes_returned;
12019+ *(bcc_ptr + 1) = 0;
12020+ *(bcc_ptr + 2) = 0;
12021+ bcc_ptr += 2; /* null terminate network opsys string */
12022+ *(bcc_ptr + 1) = 0;
12023+ *(bcc_ptr + 2) = 0;
12024+ bcc_ptr += 2; /* null domain */
12025+ } else { /* ASCII */
12026+ if (domain == NULL) {
12027+ SecurityBlob->DomainName.Buffer = 0;
12028+ SecurityBlob->DomainName.Length = 0;
12029+ SecurityBlob->DomainName.MaximumLength = 0;
12030+ } else {
12031+ SecurityBlob->NegotiateFlags |=
12032+ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
12033+ strncpy(bcc_ptr, domain, 63);
12034+ SecurityBlob->DomainName.Length = strnlen(domain, 64);
12035+ SecurityBlob->DomainName.MaximumLength =
12036+ cpu_to_le16(SecurityBlob->DomainName.Length);
12037+ SecurityBlob->DomainName.Buffer =
12038+ cpu_to_le32(SecurityBlobLength);
12039+ bcc_ptr += SecurityBlob->DomainName.Length;
12040+ SecurityBlobLength += SecurityBlob->DomainName.Length;
12041+ SecurityBlob->DomainName.Length =
12042+ cpu_to_le16(SecurityBlob->DomainName.Length);
12043+ }
12044+ if (user == NULL) {
12045+ SecurityBlob->UserName.Buffer = 0;
12046+ SecurityBlob->UserName.Length = 0;
12047+ SecurityBlob->UserName.MaximumLength = 0;
12048+ } else {
12049+ strncpy(bcc_ptr, user, 63);
12050+ SecurityBlob->UserName.Length = strnlen(user, 64);
12051+ SecurityBlob->UserName.MaximumLength =
12052+ cpu_to_le16(SecurityBlob->UserName.Length);
12053+ SecurityBlob->UserName.Buffer =
12054+ cpu_to_le32(SecurityBlobLength);
12055+ bcc_ptr += SecurityBlob->UserName.Length;
12056+ SecurityBlobLength += SecurityBlob->UserName.Length;
12057+ SecurityBlob->UserName.Length =
12058+ cpu_to_le16(SecurityBlob->UserName.Length);
12059+ }
12060+ /* BB fill in our workstation name if known BB */
12061+
12062+ strcpy(bcc_ptr, "Linux version ");
12063+ bcc_ptr += strlen("Linux version ");
12064+ strcpy(bcc_ptr, UTS_RELEASE);
12065+ bcc_ptr += strlen(UTS_RELEASE) + 1;
12066+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
12067+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
12068+ bcc_ptr++; /* null domain */
12069+ *bcc_ptr = 0;
12070+ }
12071+ SecurityBlob->NegotiateFlags =
12072+ cpu_to_le32(SecurityBlob->NegotiateFlags);
12073+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
12074+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
12075+ smb_buffer->smb_buf_length += BCC(smb_buffer);
12076+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
12077+
12078+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
12079+ &bytes_returned, 1);
12080+ if (rc) {
12081+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
12082+ } else if ((smb_buffer_response->WordCount == 3)
12083+ || (smb_buffer_response->WordCount == 4)) {
12084+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
12085+ pSMBr->resp.SecurityBlobLength =
12086+ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
12087+ if (pSMBr->resp.Action & GUEST_LOGIN)
12088+ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
12089+/* if(SecurityBlob2->MessageType != NtLm??){
12090+ cFYI("Unexpected message type on auth response is %d "));
12091+ } */
12092+ if (ses) {
12093+ cFYI(1,
12094+ ("Does UID on challenge %d match auth response UID %d ",
12095+ ses->Suid, smb_buffer_response->Uid));
12096+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
12097+ bcc_ptr = pByteArea(smb_buffer_response);
12098+ /* response can have either 3 or 4 word count - Samba sends 3 */
12099+ if ((pSMBr->resp.hdr.WordCount == 3)
12100+ || ((pSMBr->resp.hdr.WordCount == 4)
12101+ && (pSMBr->resp.SecurityBlobLength <
12102+ pSMBr->resp.ByteCount))) {
12103+ if (pSMBr->resp.hdr.WordCount == 4) {
12104+ bcc_ptr +=
12105+ pSMBr->resp.SecurityBlobLength;
12106+ cFYI(1,
12107+ ("Security Blob Length %d ",
12108+ pSMBr->resp.SecurityBlobLength));
12109+ }
12110+
12111+ cFYI(1,
12112+ ("NTLMSSP response to Authenticate "));
12113+
12114+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
12115+ if ((long) (bcc_ptr) % 2) {
12116+ remaining_words =
12117+ (BCC(smb_buffer_response)
12118+ - 1) / 2;
12119+ bcc_ptr++; /* Unicode strings must be word aligned */
12120+ } else {
12121+ remaining_words = BCC(smb_buffer_response) / 2;
12122+ }
12123+ len =
12124+ UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
12125+/* We look for obvious messed up bcc or strings in response so we do not go off
12126+ the end since (at least) WIN2K and Windows XP have a major bug in not null
12127+ terminating last Unicode string in response */
12128+ ses->serverOS =
12129+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
12130+ cifs_strfromUCS_le(ses->serverOS,
12131+ (wchar_t *)
12132+ bcc_ptr, len,
12133+ nls_codepage);
12134+ bcc_ptr += 2 * (len + 1);
12135+ remaining_words -= len + 1;
12136+ ses->serverOS[2 * len] = 0;
12137+ ses->serverOS[1 + (2 * len)] = 0;
12138+ if (remaining_words > 0) {
12139+ len = UniStrnlen((wchar_t *)
12140+ bcc_ptr,
12141+ remaining_words
12142+ - 1);
12143+ ses->serverNOS =
12144+ cifs_kcalloc(2 * (len + 1),
12145+ GFP_KERNEL);
12146+ cifs_strfromUCS_le(ses->
12147+ serverNOS,
12148+ (wchar_t *)
12149+ bcc_ptr,
12150+ len,
12151+ nls_codepage);
12152+ bcc_ptr += 2 * (len + 1);
12153+ ses->serverNOS[2 * len] = 0;
12154+ ses->serverNOS[1+(2*len)] = 0;
12155+ remaining_words -= len + 1;
12156+ if (remaining_words > 0) {
12157+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
12158+ /* last string not always null terminated (e.g. for Windows XP & 2000) */
12159+ ses->serverDomain =
12160+ cifs_kcalloc(2 *
12161+ (len +
12162+ 1),
12163+ GFP_KERNEL);
12164+ cifs_strfromUCS_le
12165+ (ses->
12166+ serverDomain,
12167+ (wchar_t *)
12168+ bcc_ptr, len,
12169+ nls_codepage);
12170+ bcc_ptr +=
12171+ 2 * (len + 1);
12172+ ses->
12173+ serverDomain[2
12174+ * len]
12175+ = 0;
12176+ ses->
12177+ serverDomain[1
12178+ +
12179+ (2
12180+ *
12181+ len)]
12182+ = 0;
12183+ } /* else no more room so create dummy domain string */
12184+ else
12185+ ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
12186+ } else { /* no room so create dummy domain and NOS string */
12187+ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
12188+ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
12189+ }
12190+ } else { /* ASCII */
12191+ len = strnlen(bcc_ptr, 1024);
12192+ if (((long) bcc_ptr + len) -
12193+ (long) pByteArea(smb_buffer_response)
12194+ <= BCC(smb_buffer_response)) {
12195+ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
12196+ strncpy(ses->serverOS,bcc_ptr, len);
12197+
12198+ bcc_ptr += len;
12199+ bcc_ptr[0] = 0; /* null terminate the string */
12200+ bcc_ptr++;
12201+
12202+ len = strnlen(bcc_ptr, 1024);
12203+ ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
12204+ strncpy(ses->serverNOS, bcc_ptr, len);
12205+ bcc_ptr += len;
12206+ bcc_ptr[0] = 0;
12207+ bcc_ptr++;
12208+
12209+ len = strnlen(bcc_ptr, 1024);
12210+ ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
12211+ strncpy(ses->serverDomain, bcc_ptr, len);
12212+ bcc_ptr += len;
12213+ bcc_ptr[0] = 0;
12214+ bcc_ptr++;
12215+ } else
12216+ cFYI(1,
12217+ ("Variable field of length %d extends beyond end of smb ",
12218+ len));
12219+ }
12220+ } else {
12221+ cERROR(1,
12222+ (" Security Blob Length extends beyond end of SMB"));
12223+ }
12224+ } else {
12225+ cERROR(1, ("No session structure passed in."));
12226+ }
12227+ } else {
12228+ cERROR(1,
12229+ (" Invalid Word count %d: ",
12230+ smb_buffer_response->WordCount));
12231+ rc = -EIO;
12232+ }
12233+
12234+ if (smb_buffer)
12235+ cifs_buf_release(smb_buffer);
12236+
12237+ return rc;
12238+}
12239+
12240+int
12241+CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
12242+ const char *tree, struct cifsTconInfo *tcon,
12243+ const struct nls_table *nls_codepage)
12244+{
12245+ struct smb_hdr *smb_buffer;
12246+ struct smb_hdr *smb_buffer_response;
12247+ TCONX_REQ *pSMB;
12248+ TCONX_RSP *pSMBr;
12249+ char *bcc_ptr;
12250+ int rc = 0;
12251+ int length;
12252+
12253+ if (ses == NULL)
12254+ return -EIO;
12255+
12256+ smb_buffer = cifs_buf_get();
12257+ if (smb_buffer == 0) {
12258+ return -ENOMEM;
12259+ }
12260+ smb_buffer_response = smb_buffer;
12261+
12262+ header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
12263+ NULL /*no tid */ , 4 /*wct */ );
12264+ smb_buffer->Uid = ses->Suid;
12265+ pSMB = (TCONX_REQ *) smb_buffer;
12266+ pSMBr = (TCONX_RSP *) smb_buffer_response;
12267+
12268+ pSMB->AndXCommand = 0xFF;
12269+ pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
12270+ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
12271+ bcc_ptr = &(pSMB->Password[0]);
12272+ bcc_ptr++; /* skip password */
12273+
12274+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
12275+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
12276+
12277+ if (ses->capabilities & CAP_STATUS32) {
12278+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
12279+ }
12280+ if (ses->capabilities & CAP_DFS) {
12281+ smb_buffer->Flags2 |= SMBFLG2_DFS;
12282+ }
12283+ if (ses->capabilities & CAP_UNICODE) {
12284+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
12285+ length =
12286+ cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
12287+ bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
12288+ bcc_ptr += 2; /* skip trailing null */
12289+ } else { /* ASCII */
12290+
12291+ strcpy(bcc_ptr, tree);
12292+ bcc_ptr += strlen(tree) + 1;
12293+ }
12294+ strcpy(bcc_ptr, "?????");
12295+ bcc_ptr += strlen("?????");
12296+ bcc_ptr += 1;
12297+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
12298+ smb_buffer->smb_buf_length += BCC(smb_buffer);
12299+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
12300+
12301+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
12302+
12303+ /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
12304+ /* above now done in SendReceive */
12305+ if ((rc == 0) && (tcon != NULL)) {
12306+ tcon->tidStatus = CifsGood;
12307+ tcon->tid = smb_buffer_response->Tid;
12308+ bcc_ptr = pByteArea(smb_buffer_response);
12309+ length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
12310+ /* skip service field (NB: this field is always ASCII) */
12311+ bcc_ptr += length + 1;
12312+ strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
12313+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
12314+ length = UniStrnlen((wchar_t *) bcc_ptr, 512);
12315+ if (((long) bcc_ptr + (2 * length)) -
12316+ (long) pByteArea(smb_buffer_response) <=
12317+ BCC(smb_buffer_response)) {
12318+ if(tcon->nativeFileSystem)
12319+ kfree(tcon->nativeFileSystem);
12320+ tcon->nativeFileSystem =
12321+ cifs_kcalloc(length + 2, GFP_KERNEL);
12322+ cifs_strfromUCS_le(tcon->nativeFileSystem,
12323+ (wchar_t *) bcc_ptr,
12324+ length, nls_codepage);
12325+ bcc_ptr += 2 * length;
12326+ bcc_ptr[0] = 0; /* null terminate the string */
12327+ bcc_ptr[1] = 0;
12328+ bcc_ptr += 2;
12329+ }
12330+ /* else do not bother copying these informational fields */
12331+ } else {
12332+ length = strnlen(bcc_ptr, 1024);
12333+ if (((long) bcc_ptr + length) -
12334+ (long) pByteArea(smb_buffer_response) <=
12335+ BCC(smb_buffer_response)) {
12336+ if(tcon->nativeFileSystem)
12337+ kfree(tcon->nativeFileSystem);
12338+ tcon->nativeFileSystem =
12339+ cifs_kcalloc(length + 1, GFP_KERNEL);
12340+ strncpy(tcon->nativeFileSystem, bcc_ptr,
12341+ length);
12342+ }
12343+ /* else do not bother copying these informational fields */
12344+ }
12345+ tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
12346+ cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
12347+ } else if ((rc == 0) && tcon == NULL) {
12348+ /* all we need to save for IPC$ connection */
12349+ ses->ipc_tid = smb_buffer_response->Tid;
12350+ }
12351+
12352+ if (smb_buffer)
12353+ cifs_buf_release(smb_buffer);
12354+ return rc;
12355+}
12356+
12357+int
12358+cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
12359+{
12360+ int rc = 0;
12361+ int xid;
12362+ struct cifsSesInfo *ses = NULL;
12363+ struct task_struct *cifsd_task;
12364+
12365+ xid = GetXid();
12366+
12367+ if (cifs_sb->tcon) {
12368+ ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
12369+ rc = CIFSSMBTDis(xid, cifs_sb->tcon);
12370+ if (rc == -EBUSY) {
12371+ FreeXid(xid);
12372+ return 0;
12373+ }
12374+ tconInfoFree(cifs_sb->tcon);
12375+ if ((ses) && (ses->server)) {
12376+ /* save off task so we do not refer to ses later */
12377+ cifsd_task = ses->server->tsk;
12378+ cFYI(1, ("About to do SMBLogoff "));
12379+ rc = CIFSSMBLogoff(xid, ses);
12380+ if (rc == -EBUSY) {
12381+ FreeXid(xid);
12382+ return 0;
12383+ } else if (rc == -ESHUTDOWN) {
12384+ cFYI(1,("Waking up socket by sending it signal"));
12385+ send_sig(SIGKILL,cifsd_task,1);
12386+ rc = 0;
12387+ } /* else - we have an smb session
12388+ left on this socket do not kill cifsd */
12389+ } else
12390+ cFYI(1, ("No session or bad tcon"));
12391+ }
12392+
12393+ cifs_sb->tcon = NULL;
12394+ if (ses) {
12395+ set_current_state(TASK_INTERRUPTIBLE);
12396+ schedule_timeout(HZ / 2);
12397+ }
12398+ if (ses)
12399+ sesInfoFree(ses);
12400+
12401+ FreeXid(xid);
12402+ return rc; /* BB check if we should always return zero here */
12403+}
12404+
12405+int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
12406+ struct nls_table * nls_info)
12407+{
12408+ int rc = 0;
12409+ char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
12410+ int ntlmv2_flag = FALSE;
12411+
12412+ /* what if server changes its buffer size after dropping the session? */
12413+ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
12414+ rc = CIFSSMBNegotiate(xid, pSesInfo);
12415+ if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
12416+ rc = CIFSSMBNegotiate(xid, pSesInfo);
12417+ if(rc == -EAGAIN)
12418+ rc = -EHOSTDOWN;
12419+ }
12420+ if(rc == 0) {
12421+ spin_lock(&GlobalMid_Lock);
12422+ if(pSesInfo->server->tcpStatus != CifsExiting)
12423+ pSesInfo->server->tcpStatus = CifsGood;
12424+ else
12425+ rc = -EHOSTDOWN;
12426+ spin_unlock(&GlobalMid_Lock);
12427+
12428+ }
12429+ }
12430+ if (!rc) {
12431+ pSesInfo->capabilities = pSesInfo->server->capabilities;
12432+ if(linuxExtEnabled == 0)
12433+ pSesInfo->capabilities &= (~CAP_UNIX);
12434+ pSesInfo->sequence_number = 0;
12435+ cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
12436+ pSesInfo->server->secMode,
12437+ pSesInfo->server->capabilities,
12438+ pSesInfo->server->timeZone));
12439+ if (extended_security
12440+ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
12441+ && (pSesInfo->server->secType == NTLMSSP)) {
12442+ cFYI(1, ("New style sesssetup "));
12443+ rc = CIFSSpnegoSessSetup(xid, pSesInfo,
12444+ NULL /* security blob */,
12445+ 0 /* blob length */,
12446+ nls_info);
12447+ } else if (extended_security
12448+ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
12449+ && (pSesInfo->server->secType == RawNTLMSSP)) {
12450+ cFYI(1, ("NTLMSSP sesssetup "));
12451+ rc = CIFSNTLMSSPNegotiateSessSetup(xid,
12452+ pSesInfo,
12453+ &ntlmv2_flag,
12454+ nls_info);
12455+ if (!rc) {
12456+ if(ntlmv2_flag) {
12457+ char * v2_response;
12458+ cFYI(1,("Can use more secure NTLM version 2 password hash"));
12459+ CalcNTLMv2_partial_mac_key(pSesInfo,
12460+ nls_info);
12461+ v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
12462+ if(v2_response) {
12463+ CalcNTLMv2_response(pSesInfo,v2_response);
12464+/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
12465+ kfree(v2_response);
12466+ /* BB Put dummy sig in SessSetup PDU? */
12467+ } else
12468+ rc = -ENOMEM;
12469+
12470+ } else {
12471+ SMBNTencrypt(pSesInfo->password,
12472+ pSesInfo->server->cryptKey,
12473+ ntlm_session_key);
12474+
12475+ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
12476+ ntlm_session_key,
12477+ pSesInfo->password);
12478+ }
12479+ /* for better security the weaker lanman hash not sent
12480+ in AuthSessSetup so we no longer calculate it */
12481+
12482+ rc = CIFSNTLMSSPAuthSessSetup(xid,
12483+ pSesInfo,
12484+ ntlm_session_key,
12485+ ntlmv2_flag,
12486+ nls_info);
12487+ }
12488+ } else { /* old style NTLM 0.12 session setup */
12489+ SMBNTencrypt(pSesInfo->password,
12490+ pSesInfo->server->cryptKey,
12491+ ntlm_session_key);
12492+
12493+ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
12494+ ntlm_session_key, pSesInfo->password);
12495+ rc = CIFSSessSetup(xid, pSesInfo,
12496+ ntlm_session_key, nls_info);
12497+ }
12498+ if (rc) {
12499+ cERROR(1,("Send error in SessSetup = %d",rc));
12500+ } else {
12501+ cFYI(1,("CIFS Session Established successfully"));
12502+ pSesInfo->status = CifsGood;
12503+ }
12504+ }
12505+ return rc;
12506+}
12507+
12508--- /dev/null
12509+++ b/fs/cifs/dir.c
12510@@ -0,0 +1,425 @@
12511+/*
12512+ * fs/cifs/dir.c
12513+ *
12514+ * vfs operations that deal with dentries
12515+ *
12516+ * Copyright (C) International Business Machines Corp., 2002,2003
12517+ * Author(s): Steve French (sfrench@us.ibm.com)
12518+ *
12519+ * This library is free software; you can redistribute it and/or modify
12520+ * it under the terms of the GNU Lesser General Public License as published
12521+ * by the Free Software Foundation; either version 2.1 of the License, or
12522+ * (at your option) any later version.
12523+ *
12524+ * This library is distributed in the hope that it will be useful,
12525+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12526+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12527+ * the GNU Lesser General Public License for more details.
12528+ *
12529+ * You should have received a copy of the GNU Lesser General Public License
12530+ * along with this library; if not, write to the Free Software
12531+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12532+ */
12533+#include <linux/fs.h>
12534+#include <linux/stat.h>
12535+#include <linux/slab.h>
12536+#include "cifsfs.h"
12537+#include "cifspdu.h"
12538+#include "cifsglob.h"
12539+#include "cifsproto.h"
12540+#include "cifs_debug.h"
12541+#include "cifs_fs_sb.h"
12542+
12543+void
12544+renew_parental_timestamps(struct dentry *direntry)
12545+{
12546+ /* BB check if there is a way to get the kernel to do this or if we really need this */
12547+ do {
12548+ direntry->d_time = jiffies;
12549+ direntry = direntry->d_parent;
12550+ } while (!IS_ROOT(direntry));
12551+}
12552+
12553+/* Note: caller must free return buffer */
12554+char *
12555+build_path_from_dentry(struct dentry *direntry)
12556+{
12557+ struct dentry *temp;
12558+ int namelen = 0;
12559+ char *full_path;
12560+
12561+ if(direntry == NULL)
12562+ return NULL; /* not much we can do if dentry is freed and
12563+ we need to reopen the file after it was closed implicitly
12564+ when the server crashed */
12565+
12566+cifs_bp_rename_retry:
12567+ for (temp = direntry; !IS_ROOT(temp);) {
12568+ namelen += (1 + temp->d_name.len);
12569+ temp = temp->d_parent;
12570+ if(temp == NULL) {
12571+ cERROR(1,("corrupt dentry"));
12572+ return NULL;
12573+ }
12574+ }
12575+
12576+ full_path = kmalloc(namelen+1, GFP_KERNEL);
12577+ if(full_path == NULL)
12578+ return full_path;
12579+ full_path[namelen] = 0; /* trailing null */
12580+
12581+ for (temp = direntry; !IS_ROOT(temp);) {
12582+ namelen -= 1 + temp->d_name.len;
12583+ if (namelen < 0) {
12584+ break;
12585+ } else {
12586+ full_path[namelen] = '\\';
12587+ strncpy(full_path + namelen + 1, temp->d_name.name,
12588+ temp->d_name.len);
12589+ cFYI(0, (" name: %s ", full_path + namelen));
12590+ }
12591+ temp = temp->d_parent;
12592+ if(temp == NULL) {
12593+ cERROR(1,("corrupt dentry"));
12594+ kfree(full_path);
12595+ return NULL;
12596+ }
12597+ }
12598+ if (namelen != 0) {
12599+ cERROR(1,
12600+ ("We did not end path lookup where we expected namelen is %d",
12601+ namelen));
12602+ /* presumably this is only possible if we were racing with a rename
12603+ of one of the parent directories (we can not lock the dentries
12604+ above us to prevent this, but retrying should be harmless) */
12605+ kfree(full_path);
12606+ namelen = 0;
12607+ goto cifs_bp_rename_retry;
12608+ }
12609+
12610+ return full_path;
12611+}
12612+
12613+/* Note: caller must free return buffer */
12614+char *
12615+build_wildcard_path_from_dentry(struct dentry *direntry)
12616+{
12617+ struct dentry *temp;
12618+ int namelen = 0;
12619+ char *full_path;
12620+
12621+ if(direntry == NULL)
12622+ return NULL; /* not much we can do if dentry is freed and
12623+ we need to reopen the file after it was closed implicitly
12624+ when the server crashed */
12625+
12626+cifs_bwp_rename_retry:
12627+ for (temp = direntry; !IS_ROOT(temp);) {
12628+ namelen += (1 + temp->d_name.len);
12629+ temp = temp->d_parent;
12630+ if(temp == NULL) {
12631+ cERROR(1,("corrupt dentry"));
12632+ return NULL;
12633+ }
12634+ }
12635+
12636+ full_path = kmalloc(namelen+3, GFP_KERNEL);
12637+ if(full_path == NULL)
12638+ return full_path;
12639+
12640+ full_path[namelen] = '\\';
12641+ full_path[namelen+1] = '*';
12642+ full_path[namelen+2] = 0; /* trailing null */
12643+
12644+ for (temp = direntry; !IS_ROOT(temp);) {
12645+ namelen -= 1 + temp->d_name.len;
12646+ if (namelen < 0) {
12647+ break;
12648+ } else {
12649+ full_path[namelen] = '\\';
12650+ strncpy(full_path + namelen + 1, temp->d_name.name,
12651+ temp->d_name.len);
12652+ cFYI(0, (" name: %s ", full_path + namelen));
12653+ }
12654+ temp = temp->d_parent;
12655+ if(temp == NULL) {
12656+ cERROR(1,("corrupt dentry"));
12657+ kfree(full_path);
12658+ return NULL;
12659+ }
12660+ }
12661+ if (namelen != 0) {
12662+ cERROR(1,
12663+ ("We did not end path lookup where we expected namelen is %d",
12664+ namelen));
12665+ /* presumably this is only possible if we were racing with a rename
12666+ of one of the parent directories (we can not lock the dentries
12667+ above us to prevent this, but retrying should be harmless) */
12668+ kfree(full_path);
12669+ namelen = 0;
12670+ goto cifs_bwp_rename_retry;
12671+ }
12672+
12673+ return full_path;
12674+}
12675+
12676+/* Inode operations in similar order to how they appear in the Linux file fs.h */
12677+
12678+int
12679+cifs_create(struct inode *inode, struct dentry *direntry, int mode)
12680+{
12681+ int rc = -ENOENT;
12682+ int xid;
12683+ int oplock = 0; /* no sense requested oplock if we are just going to
12684+ immediately close the file */
12685+ __u16 fileHandle;
12686+ struct cifs_sb_info *cifs_sb;
12687+ struct cifsTconInfo *pTcon;
12688+ char *full_path = NULL;
12689+ FILE_ALL_INFO * buf = NULL;
12690+ struct inode *newinode = NULL;
12691+
12692+ xid = GetXid();
12693+
12694+ cifs_sb = CIFS_SB(inode->i_sb);
12695+ pTcon = cifs_sb->tcon;
12696+
12697+ down(&direntry->d_sb->s_vfs_rename_sem);
12698+ full_path = build_path_from_dentry(direntry);
12699+ up(&direntry->d_sb->s_vfs_rename_sem);
12700+ if(full_path == NULL) {
12701+ FreeXid(xid);
12702+ return -ENOMEM;
12703+ }
12704+
12705+ /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
12706+
12707+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
12708+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
12709+ GENERIC_WRITE, CREATE_NOT_DIR,
12710+ &fileHandle, &oplock, buf, cifs_sb->local_nls);
12711+ if (rc) {
12712+ cFYI(1, ("cifs_create returned 0x%x ", rc));
12713+ } else {
12714+ /* BB for case of overwriting existing file can we use the inode that was
12715+ passed in rather than creating new one?? */
12716+ if (pTcon->ses->capabilities & CAP_UNIX)
12717+ rc = cifs_get_inode_info_unix(&newinode, full_path,
12718+ inode->i_sb,xid);
12719+ else
12720+ rc = cifs_get_inode_info(&newinode, full_path,
12721+ buf, inode->i_sb,xid);
12722+
12723+ if (rc != 0) {
12724+ cFYI(1,("Create worked but get_inode_info failed with rc = %d",
12725+ rc));
12726+ } else {
12727+ direntry->d_op = &cifs_dentry_ops;
12728+ d_instantiate(direntry, newinode);
12729+ }
12730+ CIFSSMBClose(xid, pTcon, fileHandle);
12731+
12732+ if(newinode) {
12733+ newinode->i_mode = mode;
12734+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
12735+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
12736+ (__u64)-1,
12737+ (__u64)-1,
12738+ 0 /* dev */,
12739+ cifs_sb->local_nls);
12740+ else { /* BB implement via Windows security descriptors */
12741+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
12742+ /* in the meantime could set r/o dos attribute when perms are eg:
12743+ mode & 0222 == 0 */
12744+ }
12745+ }
12746+ }
12747+
12748+ if (buf)
12749+ kfree(buf);
12750+ if (full_path)
12751+ kfree(full_path);
12752+ FreeXid(xid);
12753+
12754+ return rc;
12755+}
12756+
12757+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number)
12758+{
12759+ int rc = -EPERM;
12760+ int xid;
12761+ struct cifs_sb_info *cifs_sb;
12762+ struct cifsTconInfo *pTcon;
12763+ char *full_path = NULL;
12764+ struct inode * newinode = NULL;
12765+
12766+ xid = GetXid();
12767+
12768+ cifs_sb = CIFS_SB(inode->i_sb);
12769+ pTcon = cifs_sb->tcon;
12770+
12771+ down(&direntry->d_sb->s_vfs_rename_sem);
12772+ full_path = build_path_from_dentry(direntry);
12773+ up(&direntry->d_sb->s_vfs_rename_sem);
12774+ if(full_path == NULL)
12775+ rc = -ENOMEM;
12776+
12777+ if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
12778+ rc = CIFSSMBUnixSetPerms(xid, pTcon,
12779+ full_path, mode, current->euid, current->egid,
12780+ device_number, cifs_sb->local_nls);
12781+ if(!rc) {
12782+ rc = cifs_get_inode_info_unix(&newinode, full_path,
12783+ inode->i_sb,xid);
12784+ direntry->d_op = &cifs_dentry_ops;
12785+ if(rc == 0)
12786+ d_instantiate(direntry, newinode);
12787+ }
12788+ }
12789+
12790+ if (full_path)
12791+ kfree(full_path);
12792+ FreeXid(xid);
12793+
12794+ return rc;
12795+}
12796+
12797+
12798+struct dentry *
12799+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
12800+{
12801+ int xid;
12802+ int rc = 0; /* to get around spurious gcc warning, set to zero here */
12803+ struct cifs_sb_info *cifs_sb;
12804+ struct cifsTconInfo *pTcon;
12805+ struct inode *newInode = NULL;
12806+ char *full_path = NULL;
12807+
12808+ xid = GetXid();
12809+
12810+ cFYI(1,
12811+ (" parent inode = 0x%p name is: %s and dentry = 0x%p",
12812+ parent_dir_inode, direntry->d_name.name, direntry));
12813+
12814+ /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
12815+
12816+ /* check whether path exists */
12817+
12818+ cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
12819+ pTcon = cifs_sb->tcon;
12820+
12821+ /* can not grab the rename sem here since it would
12822+ deadlock in the cases (beginning of sys_rename itself)
12823+ in which we already have the sb rename sem */
12824+ full_path = build_path_from_dentry(direntry);
12825+ if(full_path == NULL) {
12826+ FreeXid(xid);
12827+ return ERR_PTR(-ENOMEM);
12828+ }
12829+
12830+ if (direntry->d_inode != NULL) {
12831+ cFYI(1, (" non-NULL inode in lookup"));
12832+ } else {
12833+ cFYI(1, (" NULL inode in lookup"));
12834+ }
12835+ cFYI(1,
12836+ (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
12837+
12838+ if (pTcon->ses->capabilities & CAP_UNIX)
12839+ rc = cifs_get_inode_info_unix(&newInode, full_path,
12840+ parent_dir_inode->i_sb,xid);
12841+ else
12842+ rc = cifs_get_inode_info(&newInode, full_path, NULL,
12843+ parent_dir_inode->i_sb,xid);
12844+
12845+ if ((rc == 0) && (newInode != NULL)) {
12846+ direntry->d_op = &cifs_dentry_ops;
12847+ d_add(direntry, newInode);
12848+
12849+ /* since paths are not looked up by component - the parent directories are presumed to be good here */
12850+ renew_parental_timestamps(direntry);
12851+
12852+ } else if (rc == -ENOENT) {
12853+ rc = 0;
12854+ d_add(direntry, NULL);
12855+ } else {
12856+ cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
12857+ /* BB special case check for Access Denied - watch security
12858+ exposure of returning dir info implicitly via different rc
12859+ if file exists or not but no access BB */
12860+ }
12861+
12862+ if (full_path)
12863+ kfree(full_path);
12864+ FreeXid(xid);
12865+ return ERR_PTR(rc);
12866+}
12867+
12868+int
12869+cifs_dir_open(struct inode *inode, struct file *file)
12870+{ /* NB: currently unused since searches are opened in readdir */
12871+ int rc = 0;
12872+ int xid;
12873+ struct cifs_sb_info *cifs_sb;
12874+ struct cifsTconInfo *pTcon;
12875+ char *full_path = NULL;
12876+
12877+ xid = GetXid();
12878+
12879+ cifs_sb = CIFS_SB(inode->i_sb);
12880+ pTcon = cifs_sb->tcon;
12881+
12882+ if(file->f_dentry) {
12883+ down(&file->f_dentry->d_sb->s_vfs_rename_sem);
12884+ full_path = build_wildcard_path_from_dentry(file->f_dentry);
12885+ up(&file->f_dentry->d_sb->s_vfs_rename_sem);
12886+ } else {
12887+ FreeXid(xid);
12888+ return -EIO;
12889+ }
12890+
12891+ cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
12892+
12893+ if (full_path)
12894+ kfree(full_path);
12895+ FreeXid(xid);
12896+ return rc;
12897+}
12898+
12899+static int
12900+cifs_d_revalidate(struct dentry *direntry, int flags)
12901+{
12902+ int isValid = 1;
12903+
12904+/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
12905+
12906+ if (direntry->d_inode) {
12907+ if (cifs_revalidate(direntry)) {
12908+ /* unlock_kernel(); */
12909+ return 0;
12910+ }
12911+ } else {
12912+ cFYI(1,
12913+ ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
12914+ direntry->d_name.name, direntry));
12915+ }
12916+
12917+/* unlock_kernel(); */
12918+
12919+ return isValid;
12920+}
12921+
12922+/* static int cifs_d_delete(struct dentry *direntry)
12923+{
12924+ int rc = 0;
12925+
12926+ cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
12927+
12928+ return rc;
12929+} */
12930+
12931+struct dentry_operations cifs_dentry_ops = {
12932+ .d_revalidate = cifs_d_revalidate,
12933+/* d_delete: cifs_d_delete, *//* not needed except for debugging */
12934+ /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
12935+};
12936--- /dev/null
12937+++ b/fs/cifs/file.c
12938@@ -0,0 +1,2185 @@
12939+/*
12940+ * fs/cifs/file.c
12941+ *
12942+ * vfs operations that deal with files
12943+ *
12944+ * Copyright (C) International Business Machines Corp., 2002,2003
12945+ * Author(s): Steve French (sfrench@us.ibm.com)
12946+ *
12947+ * This library is free software; you can redistribute it and/or modify
12948+ * it under the terms of the GNU Lesser General Public License as published
12949+ * by the Free Software Foundation; either version 2.1 of the License, or
12950+ * (at your option) any later version.
12951+ *
12952+ * This library is distributed in the hope that it will be useful,
12953+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12954+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12955+ * the GNU Lesser General Public License for more details.
12956+ *
12957+ * You should have received a copy of the GNU Lesser General Public License
12958+ * along with this library; if not, write to the Free Software
12959+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12960+ */
12961+#include <linux/fs.h>
12962+#include <linux/stat.h>
12963+#include <linux/fcntl.h>
12964+#include <linux/version.h>
12965+#include <linux/pagemap.h>
12966+#include <linux/smp_lock.h>
12967+#include <linux/list.h>
12968+#include <asm/div64.h>
12969+#include <linux/mm.h>
12970+#include <linux/types.h>
12971+#include "cifsfs.h"
12972+#include "cifspdu.h"
12973+#include "cifsglob.h"
12974+#include "cifsproto.h"
12975+#include "cifs_unicode.h"
12976+#include "cifs_debug.h"
12977+#include "cifs_fs_sb.h"
12978+
12979+int
12980+cifs_open(struct inode *inode, struct file *file)
12981+{
12982+ int rc = -EACCES;
12983+ int xid, oplock;
12984+ struct cifs_sb_info *cifs_sb;
12985+ struct cifsTconInfo *pTcon;
12986+ struct cifsFileInfo *pCifsFile;
12987+ struct cifsInodeInfo *pCifsInode;
12988+ char *full_path = NULL;
12989+ int desiredAccess = 0x20197;
12990+ int disposition;
12991+ __u16 netfid;
12992+ FILE_ALL_INFO * buf = NULL;
12993+ time_t temp;
12994+
12995+ xid = GetXid();
12996+
12997+ cifs_sb = CIFS_SB(inode->i_sb);
12998+ pTcon = cifs_sb->tcon;
12999+
13000+ down(&inode->i_sb->s_vfs_rename_sem);
13001+ full_path = build_path_from_dentry(file->f_dentry);
13002+ up(&inode->i_sb->s_vfs_rename_sem);
13003+ if(full_path == NULL) {
13004+ FreeXid(xid);
13005+ return -ENOMEM;
13006+ }
13007+
13008+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
13009+ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
13010+ desiredAccess = GENERIC_READ;
13011+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
13012+ desiredAccess = GENERIC_WRITE;
13013+ else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
13014+ /* GENERIC_ALL is too much permission to request */
13015+ /* can cause unnecessary access denied on create */
13016+ /* desiredAccess = GENERIC_ALL; */
13017+ desiredAccess = GENERIC_READ | GENERIC_WRITE;
13018+ }
13019+
13020+/*********************************************************************
13021+ * open flag mapping table:
13022+ *
13023+ * POSIX Flag CIFS Disposition
13024+ * ---------- ----------------
13025+ * O_CREAT FILE_OPEN_IF
13026+ * O_CREAT | O_EXCL FILE_CREATE
13027+ * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
13028+ * O_TRUNC FILE_OVERWRITE
13029+ * none of the above FILE_OPEN
13030+ *
13031+ * Note that there is not a direct match between disposition
13032+ * FILE_SUPERSEDE (ie create whether or not file exists although
13033+ * O_CREAT | O_TRUNC is similar but truncates the existing
13034+ * file rather than creating a new file as FILE_SUPERSEDE does
13035+ * (which uses the attributes / metadata passed in on open call)
13036+ *?
13037+ *? O_SYNC is a reasonable match to CIFS writethrough flag
13038+ *? and the read write flags match reasonably. O_LARGEFILE
13039+ *? is irrelevant because largefile support is always used
13040+ *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
13041+ * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
13042+ *********************************************************************/
13043+
13044+ /* For 2.4 case, file was already checked for existence
13045+ before create by vfs lookup and created in create
13046+ entry point, we are now just opening the newly
13047+ created file with the right desiredAccess flags */
13048+
13049+ if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
13050+ disposition = FILE_OPEN_IF;
13051+ else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
13052+ disposition = FILE_OVERWRITE_IF;
13053+ else if((file->f_flags & O_CREAT) == O_CREAT)
13054+ disposition = FILE_OPEN_IF;
13055+ else
13056+ disposition = FILE_OPEN;
13057+
13058+ if (oplockEnabled)
13059+ oplock = REQ_OPLOCK;
13060+ else
13061+ oplock = FALSE;
13062+
13063+ /* BB pass O_SYNC flag through on file attributes .. BB */
13064+
13065+ /* Also refresh inode by passing in file_info buf returned by SMBOpen
13066+ and calling get_inode_info with returned buf (at least
13067+ helps non-Unix server case */
13068+
13069+ /* BB we can not do this if this is the second open of a file
13070+ and the first handle has writebehind data, we might be
13071+ able to simply do a filemap_fdatawrite/filemap_fdatawait first */
13072+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
13073+ if(buf==0) {
13074+ if (full_path)
13075+ kfree(full_path);
13076+ FreeXid(xid);
13077+ return -ENOMEM;
13078+ }
13079+ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
13080+ CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
13081+ if (rc) {
13082+ cFYI(1, ("cifs_open returned 0x%x ", rc));
13083+ cFYI(1, ("oplock: %d ", oplock));
13084+ } else {
13085+ file->private_data =
13086+ kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
13087+ if (file->private_data) {
13088+ memset(file->private_data, 0, sizeof(struct cifsFileInfo));
13089+ pCifsFile = (struct cifsFileInfo *) file->private_data;
13090+ pCifsFile->netfid = netfid;
13091+ pCifsFile->pid = current->pid;
13092+ init_MUTEX(&pCifsFile->fh_sem);
13093+ pCifsFile->pfile = file; /* needed for writepage */
13094+ pCifsFile->pInode = inode;
13095+ pCifsFile->invalidHandle = FALSE;
13096+ pCifsFile->closePend = FALSE;
13097+ write_lock(&GlobalSMBSeslock);
13098+ spin_lock(&files_lock);
13099+ list_add(&pCifsFile->tlist,&pTcon->openFileList);
13100+ pCifsInode = CIFS_I(file->f_dentry->d_inode);
13101+ if(pCifsInode) {
13102+ /* want handles we can use to read with first */
13103+ /* in the list so we do not have to walk the */
13104+ /* list to search for one in prepare_write */
13105+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
13106+ list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
13107+ } else {
13108+ list_add(&pCifsFile->flist,&pCifsInode->openFileList);
13109+ }
13110+ spin_unlock(&files_lock);
13111+ write_unlock(&GlobalSMBSeslock);
13112+ if(pCifsInode->clientCanCacheRead) {
13113+ /* we have the inode open somewhere else
13114+ no need to discard cache data */
13115+ } else {
13116+ if(buf) {
13117+ /* BB need same check in cifs_create too? */
13118+
13119+ /* if not oplocked, invalidate inode pages if mtime
13120+ or file size changed */
13121+ temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
13122+ if((file->f_dentry->d_inode->i_mtime == temp) &&
13123+ (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
13124+ cFYI(1,("inode unchanged on server"));
13125+ } else {
13126+ if(file->f_dentry->d_inode->i_mapping) {
13127+ /* BB no need to lock inode until after invalidate*/
13128+ /* since namei code should already have it locked?*/
13129+ filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
13130+ }
13131+ cFYI(1,("invalidating remote inode since open detected it changed"));
13132+ invalidate_inode_pages(file->f_dentry->d_inode);
13133+ }
13134+ }
13135+ }
13136+ if (pTcon->ses->capabilities & CAP_UNIX)
13137+ rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
13138+ full_path, inode->i_sb,xid);
13139+ else
13140+ rc = cifs_get_inode_info(&file->f_dentry->d_inode,
13141+ full_path, buf, inode->i_sb,xid);
13142+
13143+ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
13144+ pCifsInode->clientCanCacheAll = TRUE;
13145+ pCifsInode->clientCanCacheRead = TRUE;
13146+ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
13147+ } else if((oplock & 0xF) == OPLOCK_READ)
13148+ pCifsInode->clientCanCacheRead = TRUE;
13149+ } else {
13150+ spin_unlock(&files_lock);
13151+ write_unlock(&GlobalSMBSeslock);
13152+ }
13153+ if(oplock & CIFS_CREATE_ACTION) {
13154+ /* time to set mode which we can not set earlier due
13155+ to problems creating new read-only files */
13156+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
13157+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
13158+ (__u64)-1,
13159+ (__u64)-1,
13160+ 0 /* dev */,
13161+ cifs_sb->local_nls);
13162+ else {/* BB implement via Windows security descriptors */
13163+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
13164+ /* in the meantime could set r/o dos attribute when perms are eg:
13165+ mode & 0222 == 0 */
13166+ }
13167+ }
13168+ }
13169+ }
13170+
13171+ if (buf)
13172+ kfree(buf);
13173+ if (full_path)
13174+ kfree(full_path);
13175+ FreeXid(xid);
13176+ return rc;
13177+}
13178+
13179+/* Try to reaquire byte range locks that were released when session */
13180+/* to server was lost */
13181+static int cifs_relock_file(struct cifsFileInfo * cifsFile)
13182+{
13183+ int rc = 0;
13184+
13185+/* BB list all locks open on this file and relock */
13186+
13187+ return rc;
13188+}
13189+
13190+static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
13191+{
13192+ int rc = -EACCES;
13193+ int xid, oplock;
13194+ struct cifs_sb_info *cifs_sb;
13195+ struct cifsTconInfo *pTcon;
13196+ struct cifsFileInfo *pCifsFile;
13197+ struct cifsInodeInfo *pCifsInode;
13198+ char *full_path = NULL;
13199+ int desiredAccess = 0x20197;
13200+ int disposition = FILE_OPEN;
13201+ __u16 netfid;
13202+
13203+ if(inode == NULL)
13204+ return -EBADF;
13205+ if (file->private_data) {
13206+ pCifsFile = (struct cifsFileInfo *) file->private_data;
13207+ } else
13208+ return -EBADF;
13209+
13210+ xid = GetXid();
13211+ down(&pCifsFile->fh_sem);
13212+ if(pCifsFile->invalidHandle == FALSE) {
13213+ up(&pCifsFile->fh_sem);
13214+ FreeXid(xid);
13215+ return 0;
13216+ }
13217+
13218+ if(file->f_dentry == NULL) {
13219+ up(&pCifsFile->fh_sem);
13220+ cFYI(1,("failed file reopen, no valid name if dentry freed"));
13221+ FreeXid(xid);
13222+ return -EBADF;
13223+ }
13224+ cifs_sb = CIFS_SB(inode->i_sb);
13225+ pTcon = cifs_sb->tcon;
13226+/* can not grab rename sem here because various ops, including
13227+those that already have the rename sem can end up causing writepage
13228+to get called and if the server was down that means we end up here,
13229+and we can never tell if the caller already has the rename_sem */
13230+ full_path = build_path_from_dentry(file->f_dentry);
13231+ if(full_path == NULL) {
13232+ up(&pCifsFile->fh_sem);
13233+ FreeXid(xid);
13234+ return -ENOMEM;
13235+ }
13236+
13237+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
13238+ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
13239+ desiredAccess = GENERIC_READ;
13240+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
13241+ desiredAccess = GENERIC_WRITE;
13242+ else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
13243+ /* GENERIC_ALL is too much permission to request */
13244+ /* can cause unnecessary access denied on create */
13245+ /* desiredAccess = GENERIC_ALL; */
13246+ desiredAccess = GENERIC_READ | GENERIC_WRITE;
13247+ }
13248+
13249+ if (oplockEnabled)
13250+ oplock = REQ_OPLOCK;
13251+ else
13252+ oplock = FALSE;
13253+
13254+
13255+ /* Can not refresh inode by passing in file_info buf to be returned
13256+ by SMBOpen and then calling get_inode_info with returned buf
13257+ since file might have write behind data that needs to be flushed
13258+ and server version of file size can be stale. If we
13259+ knew for sure that inode was not dirty locally we could do this */
13260+
13261+/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
13262+ if(buf==0) {
13263+ up(&pCifsFile->fh_sem);
13264+ if (full_path)
13265+ kfree(full_path);
13266+ FreeXid(xid);
13267+ return -ENOMEM;
13268+ }*/
13269+ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
13270+ CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
13271+ if (rc) {
13272+ up(&pCifsFile->fh_sem);
13273+ cFYI(1, ("cifs_open returned 0x%x ", rc));
13274+ cFYI(1, ("oplock: %d ", oplock));
13275+ } else {
13276+ pCifsFile->netfid = netfid;
13277+ pCifsFile->invalidHandle = FALSE;
13278+ up(&pCifsFile->fh_sem);
13279+ pCifsInode = CIFS_I(inode);
13280+ if(pCifsInode) {
13281+ if(can_flush) {
13282+ filemap_fdatasync(inode->i_mapping);
13283+ filemap_fdatawait(inode->i_mapping);
13284+ /* temporarily disable caching while we
13285+ go to server to get inode info */
13286+ pCifsInode->clientCanCacheAll = FALSE;
13287+ pCifsInode->clientCanCacheRead = FALSE;
13288+ if (pTcon->ses->capabilities & CAP_UNIX)
13289+ rc = cifs_get_inode_info_unix(&inode,
13290+ full_path, inode->i_sb,xid);
13291+ else
13292+ rc = cifs_get_inode_info(&inode,
13293+ full_path, NULL, inode->i_sb,xid);
13294+ } /* else we are writing out data to server already
13295+ and could deadlock if we tried to flush data, and
13296+ since we do not know if we have data that would
13297+ invalidate the current end of file on the server
13298+ we can not go to the server to get the new
13299+ inod info */
13300+ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
13301+ pCifsInode->clientCanCacheAll = TRUE;
13302+ pCifsInode->clientCanCacheRead = TRUE;
13303+ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
13304+ } else if((oplock & 0xF) == OPLOCK_READ) {
13305+ pCifsInode->clientCanCacheRead = TRUE;
13306+ pCifsInode->clientCanCacheAll = FALSE;
13307+ } else {
13308+ pCifsInode->clientCanCacheRead = FALSE;
13309+ pCifsInode->clientCanCacheAll = FALSE;
13310+ }
13311+ cifs_relock_file(pCifsFile);
13312+ }
13313+ }
13314+
13315+ if (full_path)
13316+ kfree(full_path);
13317+ FreeXid(xid);
13318+ return rc;
13319+}
13320+
13321+int
13322+cifs_close(struct inode *inode, struct file *file)
13323+{
13324+ int rc = 0;
13325+ int xid;
13326+ struct cifs_sb_info *cifs_sb;
13327+ struct cifsTconInfo *pTcon;
13328+ struct cifsFileInfo *pSMBFile =
13329+ (struct cifsFileInfo *) file->private_data;
13330+
13331+ xid = GetXid();
13332+
13333+ cifs_sb = CIFS_SB(inode->i_sb);
13334+ pTcon = cifs_sb->tcon;
13335+ if (pSMBFile) {
13336+ pSMBFile->closePend = TRUE;
13337+ spin_lock(&files_lock);
13338+ if(pTcon) {
13339+ /* no sense reconnecting to close a file that is
13340+ already closed */
13341+ if (pTcon->tidStatus != CifsNeedReconnect) {
13342+ spin_unlock(&files_lock);
13343+ rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
13344+ spin_lock(&files_lock);
13345+ }
13346+ }
13347+ list_del(&pSMBFile->flist);
13348+ list_del(&pSMBFile->tlist);
13349+ spin_unlock(&files_lock);
13350+ if(pSMBFile->search_resume_name)
13351+ kfree(pSMBFile->search_resume_name);
13352+ kfree(file->private_data);
13353+ file->private_data = NULL;
13354+ } else
13355+ rc = -EBADF;
13356+
13357+ if(list_empty(&(CIFS_I(inode)->openFileList))) {
13358+ cFYI(1,("closing last open instance for inode %p",inode));
13359+ /* if the file is not open we do not know if we can cache
13360+ info on this inode, much less write behind and read ahead */
13361+ CIFS_I(inode)->clientCanCacheRead = FALSE;
13362+ CIFS_I(inode)->clientCanCacheAll = FALSE;
13363+ }
13364+ if((rc ==0) && CIFS_I(inode)->write_behind_rc)
13365+ rc = CIFS_I(inode)->write_behind_rc;
13366+ FreeXid(xid);
13367+ return rc;
13368+}
13369+
13370+int
13371+cifs_closedir(struct inode *inode, struct file *file)
13372+{
13373+ int rc = 0;
13374+ int xid;
13375+ struct cifsFileInfo *pSMBFileStruct =
13376+ (struct cifsFileInfo *) file->private_data;
13377+
13378+ cFYI(1, ("Closedir inode = 0x%p with ", inode));
13379+
13380+ xid = GetXid();
13381+
13382+ if (pSMBFileStruct) {
13383+ cFYI(1, ("Freeing private data in close dir"));
13384+ kfree(file->private_data);
13385+ file->private_data = NULL;
13386+ }
13387+ FreeXid(xid);
13388+ return rc;
13389+}
13390+
13391+int
13392+cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
13393+{
13394+ int rc, xid;
13395+ __u32 lockType = LOCKING_ANDX_LARGE_FILES;
13396+ __u32 numLock = 0;
13397+ __u32 numUnlock = 0;
13398+ __u64 length;
13399+ int wait_flag = FALSE;
13400+ struct cifs_sb_info *cifs_sb;
13401+ struct cifsTconInfo *pTcon;
13402+ length = 1 + pfLock->fl_end - pfLock->fl_start;
13403+
13404+ rc = -EACCES;
13405+
13406+ xid = GetXid();
13407+
13408+ cFYI(1,
13409+ ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
13410+ cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
13411+ pfLock->fl_end));
13412+
13413+ if (pfLock->fl_flags & FL_POSIX)
13414+ cFYI(1, ("Posix "));
13415+ if (pfLock->fl_flags & FL_FLOCK)
13416+ cFYI(1, ("Flock "));
13417+/* if (pfLock->fl_flags & FL_SLEEP) {
13418+ cFYI(1, ("Blocking lock "));
13419+ wait_flag = TRUE;
13420+ } */
13421+ if (pfLock->fl_flags & FL_ACCESS)
13422+ cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
13423+ if (pfLock->fl_flags & FL_LEASE)
13424+ cFYI(1, ("Lease on file - not implemented yet"));
13425+ if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_ACCESS | FL_LEASE)))
13426+ cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
13427+
13428+ if (pfLock->fl_type == F_WRLCK) {
13429+ cFYI(1, ("F_WRLCK "));
13430+ numLock = 1;
13431+ } else if (pfLock->fl_type == F_UNLCK) {
13432+ cFYI(1, ("F_UNLCK "));
13433+ numUnlock = 1;
13434+ } else if (pfLock->fl_type == F_RDLCK) {
13435+ cFYI(1, ("F_RDLCK "));
13436+ lockType |= LOCKING_ANDX_SHARED_LOCK;
13437+ numLock = 1;
13438+ } else if (pfLock->fl_type == F_EXLCK) {
13439+ cFYI(1, ("F_EXLCK "));
13440+ numLock = 1;
13441+ } else if (pfLock->fl_type == F_SHLCK) {
13442+ cFYI(1, ("F_SHLCK "));
13443+ lockType |= LOCKING_ANDX_SHARED_LOCK;
13444+ numLock = 1;
13445+ } else
13446+ cFYI(1, ("Unknown type of lock "));
13447+
13448+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13449+ pTcon = cifs_sb->tcon;
13450+
13451+ if (file->private_data == NULL) {
13452+ FreeXid(xid);
13453+ return -EBADF;
13454+ }
13455+
13456+ if (IS_GETLK(cmd)) {
13457+ rc = CIFSSMBLock(xid, pTcon,
13458+ ((struct cifsFileInfo *) file->
13459+ private_data)->netfid,
13460+ length,
13461+ pfLock->fl_start, 0, 1, lockType,
13462+ 0 /* wait flag */ );
13463+ if (rc == 0) {
13464+ rc = CIFSSMBLock(xid, pTcon,
13465+ ((struct cifsFileInfo *) file->
13466+ private_data)->netfid,
13467+ length,
13468+ pfLock->fl_start, 1 /* numUnlock */ ,
13469+ 0 /* numLock */ , lockType,
13470+ 0 /* wait flag */ );
13471+ pfLock->fl_type = F_UNLCK;
13472+ if (rc != 0)
13473+ cERROR(1,
13474+ ("Error unlocking previously locked range %d during test of lock ",
13475+ rc));
13476+ rc = 0;
13477+
13478+ } else {
13479+ /* if rc == ERR_SHARING_VIOLATION ? */
13480+ rc = 0; /* do not change lock type to unlock since range in use */
13481+ }
13482+
13483+ FreeXid(xid);
13484+ return rc;
13485+ }
13486+
13487+ rc = CIFSSMBLock(xid, pTcon,
13488+ ((struct cifsFileInfo *) file->private_data)->
13489+ netfid, length,
13490+ pfLock->fl_start, numUnlock, numLock, lockType,
13491+ wait_flag);
13492+ FreeXid(xid);
13493+ return rc;
13494+}
13495+
13496+ssize_t
13497+cifs_write(struct file * file, const char *write_data,
13498+ size_t write_size, loff_t * poffset)
13499+{
13500+ int rc = 0;
13501+ unsigned int bytes_written = 0;
13502+ unsigned int total_written;
13503+ struct cifs_sb_info *cifs_sb;
13504+ struct cifsTconInfo *pTcon;
13505+ int xid, long_op;
13506+ struct cifsFileInfo * open_file;
13507+
13508+ if(file->f_dentry == NULL)
13509+ return -EBADF;
13510+
13511+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13512+ if(cifs_sb == NULL) {
13513+ return -EBADF;
13514+ }
13515+ pTcon = cifs_sb->tcon;
13516+
13517+ /*cFYI(1,
13518+ (" write %d bytes to offset %lld of %s", write_size,
13519+ *poffset, file->f_dentry->d_name.name)); */
13520+
13521+ if (file->private_data == NULL) {
13522+ return -EBADF;
13523+ } else {
13524+ open_file = (struct cifsFileInfo *) file->private_data;
13525+ }
13526+
13527+ xid = GetXid();
13528+ if(file->f_dentry->d_inode == NULL) {
13529+ FreeXid(xid);
13530+ return -EBADF;
13531+ }
13532+
13533+ if (*poffset > file->f_dentry->d_inode->i_size)
13534+ long_op = 2; /* writes past end of file can take a long time */
13535+ else
13536+ long_op = 1;
13537+
13538+ for (total_written = 0; write_size > total_written;
13539+ total_written += bytes_written) {
13540+ rc = -EAGAIN;
13541+ while(rc == -EAGAIN) {
13542+ if(file->private_data == NULL) {
13543+ /* file has been closed on us */
13544+ FreeXid(xid);
13545+ /* if we have gotten here we have written some data
13546+ and blocked, and the file has been freed on us
13547+ while we blocked so return what we managed to write */
13548+ return total_written;
13549+ }
13550+ if(open_file->closePend) {
13551+ FreeXid(xid);
13552+ if(total_written)
13553+ return total_written;
13554+ else
13555+ return -EBADF;
13556+ }
13557+ if (open_file->invalidHandle) {
13558+ if((file->f_dentry == NULL) ||
13559+ (file->f_dentry->d_inode == NULL)) {
13560+ FreeXid(xid);
13561+ return total_written;
13562+ }
13563+ /* we could deadlock if we called
13564+ filemap_fdatawait from here so tell
13565+ reopen_file not to flush data to server now */
13566+ rc = cifs_reopen_file(file->f_dentry->d_inode,
13567+ file,FALSE);
13568+ if(rc != 0)
13569+ break;
13570+ }
13571+
13572+ rc = CIFSSMBWrite(xid, pTcon,
13573+ open_file->netfid,
13574+ write_size - total_written, *poffset,
13575+ &bytes_written,
13576+ write_data + total_written, long_op);
13577+ }
13578+ if (rc || (bytes_written == 0)) {
13579+ if (total_written)
13580+ break;
13581+ else {
13582+ FreeXid(xid);
13583+ return rc;
13584+ }
13585+ } else
13586+ *poffset += bytes_written;
13587+ long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
13588+ }
13589+
13590+#ifdef CONFIG_CIFS_STATS
13591+ if(total_written > 0) {
13592+ atomic_inc(&pTcon->num_writes);
13593+ spin_lock(&pTcon->stat_lock);
13594+ pTcon->bytes_written += total_written;
13595+ spin_unlock(&pTcon->stat_lock);
13596+ }
13597+#endif
13598+
13599+ /* since the write may have blocked check these pointers again */
13600+ if(file->f_dentry) {
13601+ if(file->f_dentry->d_inode) {
13602+ file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
13603+ CURRENT_TIME;
13604+ if (total_written > 0) {
13605+ if (*poffset > file->f_dentry->d_inode->i_size)
13606+ file->f_dentry->d_inode->i_size = *poffset;
13607+ }
13608+ mark_inode_dirty_sync(file->f_dentry->d_inode);
13609+ }
13610+ }
13611+ FreeXid(xid);
13612+ return total_written;
13613+}
13614+
13615+static int
13616+cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
13617+{
13618+ struct address_space *mapping = page->mapping;
13619+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
13620+ char * write_data;
13621+ int rc = -EFAULT;
13622+ int bytes_written = 0;
13623+ struct cifs_sb_info *cifs_sb;
13624+ struct cifsTconInfo *pTcon;
13625+ struct inode *inode;
13626+ struct cifsInodeInfo *cifsInode;
13627+ struct cifsFileInfo *open_file = NULL;
13628+ struct list_head *tmp;
13629+ struct list_head *tmp1;
13630+
13631+ if (!mapping) {
13632+ return -EFAULT;
13633+ } else if(!mapping->host) {
13634+ return -EFAULT;
13635+ }
13636+
13637+ inode = page->mapping->host;
13638+ cifs_sb = CIFS_SB(inode->i_sb);
13639+ pTcon = cifs_sb->tcon;
13640+
13641+ offset += (loff_t)from;
13642+ write_data = kmap(page);
13643+ write_data += from;
13644+
13645+ if((to > PAGE_CACHE_SIZE) || (from > to)) {
13646+ kunmap(page);
13647+ return -EIO;
13648+ }
13649+
13650+ /* racing with truncate? */
13651+ if(offset > mapping->host->i_size) {
13652+ kunmap(page);
13653+ return 0; /* don't care */
13654+ }
13655+
13656+ /* check to make sure that we are not extending the file */
13657+ if(mapping->host->i_size - offset < (loff_t)to)
13658+ to = (unsigned)(mapping->host->i_size - offset);
13659+
13660+
13661+ cifsInode = CIFS_I(mapping->host);
13662+ read_lock(&GlobalSMBSeslock);
13663+ /* BB we should start at the end */
13664+ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
13665+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
13666+ if(open_file->closePend)
13667+ continue;
13668+ /* We check if file is open for writing first */
13669+ if((open_file->pfile) &&
13670+ ((open_file->pfile->f_flags & O_RDWR) ||
13671+ (open_file->pfile->f_flags & O_WRONLY))) {
13672+ read_unlock(&GlobalSMBSeslock);
13673+ bytes_written = cifs_write(open_file->pfile, write_data,
13674+ to-from, &offset);
13675+ read_lock(&GlobalSMBSeslock);
13676+ /* Does mm or vfs already set times? */
13677+ inode->i_atime = inode->i_mtime = CURRENT_TIME;
13678+ if ((bytes_written > 0) && (offset)) {
13679+ rc = 0;
13680+ } else if(bytes_written < 0) {
13681+ if(rc == -EBADF) {
13682+ /* have seen a case in which
13683+ kernel seemed to have closed/freed a file
13684+ even with writes active so we might as well
13685+ see if there are other file structs to try
13686+ for the same inode before giving up */
13687+ continue;
13688+ } else
13689+ rc = bytes_written;
13690+ }
13691+ break; /* now that we found a valid file handle
13692+ and tried to write to it we are done, no
13693+ sense continuing to loop looking for another */
13694+ }
13695+ if(tmp->next == NULL) {
13696+ cFYI(1,("File instance %p removed",tmp));
13697+ break;
13698+ }
13699+ }
13700+ read_unlock(&GlobalSMBSeslock);
13701+ if(open_file == NULL) {
13702+ cFYI(1,("No writeable filehandles for inode"));
13703+ rc = -EIO;
13704+ }
13705+
13706+ kunmap(page);
13707+ return rc;
13708+}
13709+
13710+#if 0
13711+static int
13712+cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
13713+{
13714+ int rc = -EFAULT;
13715+ int xid;
13716+
13717+ xid = GetXid();
13718+/* call 16K write then Setpageuptodate */
13719+ FreeXid(xid);
13720+ return rc;
13721+}
13722+#endif
13723+
13724+static int
13725+cifs_writepage(struct page* page)
13726+{
13727+ int rc = -EFAULT;
13728+ int xid;
13729+
13730+ xid = GetXid();
13731+/* BB add check for wbc flags */
13732+ page_cache_get(page);
13733+ if (!Page_Uptodate(page)) {
13734+ cFYI(1,("ppw - page not up to date"));
13735+ }
13736+
13737+ rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
13738+ SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
13739+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
13740+ unlock_page(page);
13741+#else
13742+ UnlockPage(page);
13743+#endif
13744+ page_cache_release(page);
13745+ FreeXid(xid);
13746+ return rc;
13747+}
13748+
13749+static int
13750+cifs_commit_write(struct file *file, struct page *page, unsigned offset,
13751+ unsigned to)
13752+{
13753+ int xid;
13754+ int rc = 0;
13755+ struct inode *inode = page->mapping->host;
13756+ loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
13757+ char * page_data;
13758+
13759+ xid = GetXid();
13760+ cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
13761+ if (position > inode->i_size){
13762+ inode->i_size = position;
13763+ /*if (file->private_data == NULL) {
13764+ rc = -EBADF;
13765+ } else {
13766+ open_file = (struct cifsFileInfo *)file->private_data;
13767+ cifs_sb = CIFS_SB(inode->i_sb);
13768+ rc = -EAGAIN;
13769+ while(rc == -EAGAIN) {
13770+ if((open_file->invalidHandle) &&
13771+ (!open_file->closePend)) {
13772+ rc = cifs_reopen_file(file->f_dentry->d_inode,file);
13773+ if(rc != 0)
13774+ break;
13775+ }
13776+ if(!open_file->closePend) {
13777+ rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
13778+ position, open_file->netfid,
13779+ open_file->pid,FALSE);
13780+ } else {
13781+ rc = -EBADF;
13782+ break;
13783+ }
13784+ }
13785+ cFYI(1,(" SetEOF (commit write) rc = %d",rc));
13786+ }*/
13787+ }
13788+ if (!Page_Uptodate(page)) {
13789+ position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
13790+ /* can not rely on (or let) writepage write this data */
13791+ if(to < offset) {
13792+ cFYI(1,("Illegal offsets, can not copy from %d to %d",
13793+ offset,to));
13794+ FreeXid(xid);
13795+ return rc;
13796+ }
13797+ /* this is probably better than directly calling
13798+ partialpage_write since in this function
13799+ the file handle is known which we might as well
13800+ leverage */
13801+ /* BB check if anything else missing out of ppw */
13802+ /* such as updating last write time */
13803+ page_data = kmap(page);
13804+ rc = cifs_write(file, page_data+offset,to-offset,
13805+ &position);
13806+ if(rc > 0)
13807+ rc = 0;
13808+ /* else if rc < 0 should we set writebehind rc? */
13809+ kunmap(page);
13810+ } else {
13811+ set_page_dirty(page);
13812+ }
13813+
13814+ FreeXid(xid);
13815+ return rc;
13816+}
13817+
13818+int
13819+cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
13820+{
13821+ int xid;
13822+ int rc = 0;
13823+ struct inode * inode = file->f_dentry->d_inode;
13824+
13825+ xid = GetXid();
13826+
13827+ cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
13828+ dentry->d_name.name, datasync));
13829+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
13830+ rc = filemap_fdatasync(inode->i_mapping);
13831+#else
13832+ filemap_fdatasync(inode->i_mapping);
13833+#endif
13834+ if(rc == 0)
13835+ CIFS_I(inode)->write_behind_rc = 0;
13836+ FreeXid(xid);
13837+ return rc;
13838+}
13839+
13840+static int
13841+cifs_sync_page(struct page *page)
13842+{
13843+ struct address_space *mapping;
13844+ struct inode *inode;
13845+ unsigned long index = page->index;
13846+ unsigned int rpages = 0;
13847+ int rc = 0;
13848+
13849+ cFYI(1,("sync page %p",page));
13850+ mapping = page->mapping;
13851+ if (!mapping)
13852+ return 0;
13853+ inode = mapping->host;
13854+ if (!inode)
13855+ return 0;
13856+
13857+/* fill in rpages then
13858+ result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
13859+
13860+ cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
13861+
13862+ if (rc < 0)
13863+ return rc;
13864+ return 0;
13865+}
13866+
13867+/*
13868+ * As file closes, flush all cached write data for this inode checking
13869+ * for write behind errors.
13870+ *
13871+ */
13872+int cifs_flush(struct file *file)
13873+{
13874+ struct inode * inode = file->f_dentry->d_inode;
13875+ int rc = 0;
13876+
13877+ /* Rather than do the steps manually: */
13878+ /* lock the inode for writing */
13879+ /* loop through pages looking for write behind data (dirty pages) */
13880+ /* coalesce into contiguous 16K (or smaller) chunks to write to server */
13881+ /* send to server (prefer in parallel) */
13882+ /* deal with writebehind errors */
13883+ /* unlock inode for writing */
13884+ /* filemapfdatawrite appears easier for the time being */
13885+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
13886+ rc = filemap_fdatasync(inode->i_mapping);
13887+#else
13888+ filemap_fdatasync(inode->i_mapping);
13889+#endif
13890+ if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
13891+ CIFS_I(inode)->write_behind_rc = 0;
13892+
13893+ cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
13894+
13895+ return rc;
13896+}
13897+
13898+
13899+ssize_t
13900+cifs_read(struct file * file, char *read_data, size_t read_size,
13901+ loff_t * poffset)
13902+{
13903+ int rc = -EACCES;
13904+ unsigned int bytes_read = 0;
13905+ unsigned int total_read;
13906+ unsigned int current_read_size;
13907+ struct cifs_sb_info *cifs_sb;
13908+ struct cifsTconInfo *pTcon;
13909+ int xid;
13910+ char * current_offset;
13911+ struct cifsFileInfo * open_file;
13912+
13913+ xid = GetXid();
13914+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13915+ pTcon = cifs_sb->tcon;
13916+
13917+ if (file->private_data == NULL) {
13918+ FreeXid(xid);
13919+ return -EBADF;
13920+ }
13921+ open_file = (struct cifsFileInfo *)file->private_data;
13922+
13923+ if((file->f_flags & O_ACCMODE) == O_WRONLY) {
13924+ cFYI(1,("attempting read on write only file instance"));
13925+ }
13926+
13927+ for (total_read = 0,current_offset=read_data; read_size > total_read;
13928+ total_read += bytes_read,current_offset+=bytes_read) {
13929+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
13930+ current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
13931+#else
13932+ current_read_size = min(read_size - total_read,cifs_sb->rsize);
13933+#endif
13934+ rc = -EAGAIN;
13935+ while(rc == -EAGAIN) {
13936+ if ((open_file->invalidHandle) && (!open_file->closePend)) {
13937+ rc = cifs_reopen_file(file->f_dentry->d_inode,
13938+ file,TRUE);
13939+ if(rc != 0)
13940+ break;
13941+ }
13942+
13943+ rc = CIFSSMBRead(xid, pTcon,
13944+ open_file->netfid,
13945+ current_read_size, *poffset,
13946+ &bytes_read, &current_offset);
13947+ }
13948+ if (rc || (bytes_read == 0)) {
13949+ if (total_read) {
13950+ break;
13951+ } else {
13952+ FreeXid(xid);
13953+ return rc;
13954+ }
13955+ } else {
13956+#ifdef CONFIG_CIFS_STATS
13957+ atomic_inc(&pTcon->num_reads);
13958+ spin_lock(&pTcon->stat_lock);
13959+ pTcon->bytes_read += total_read;
13960+ spin_unlock(&pTcon->stat_lock);
13961+#endif
13962+ *poffset += bytes_read;
13963+ }
13964+ }
13965+ FreeXid(xid);
13966+ return total_read;
13967+}
13968+
13969+int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
13970+{
13971+ struct dentry * dentry = file->f_dentry;
13972+ int rc, xid;
13973+
13974+ xid = GetXid();
13975+ rc = cifs_revalidate(dentry);
13976+ if (rc) {
13977+ cFYI(1,("Validation prior to mmap failed, error=%d", rc));
13978+ FreeXid(xid);
13979+ return rc;
13980+ }
13981+ rc = generic_file_mmap(file, vma);
13982+ FreeXid(xid);
13983+ return rc;
13984+}
13985+
13986+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
13987+static void cifs_copy_cache_pages(struct address_space *mapping,
13988+ struct list_head *pages, int bytes_read,
13989+ char *data,struct pagevec * plru_pvec)
13990+{
13991+ struct page *page;
13992+ char * target;
13993+
13994+ while (bytes_read > 0) {
13995+ if(list_empty(pages))
13996+ break;
13997+
13998+ page = list_entry(pages->prev, struct page, lru);
13999+ list_del(&page->lru);
14000+
14001+ if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
14002+ page_cache_release(page);
14003+ cFYI(1,("Add page cache failed"));
14004+ continue;
14005+ }
14006+
14007+ target = kmap_atomic(page,KM_USER0);
14008+
14009+ if(PAGE_CACHE_SIZE > bytes_read) {
14010+ memcpy(target,data,bytes_read);
14011+ /* zero the tail end of this partial page */
14012+ memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
14013+ bytes_read = 0;
14014+ } else {
14015+ memcpy(target,data,PAGE_CACHE_SIZE);
14016+ bytes_read -= PAGE_CACHE_SIZE;
14017+ }
14018+ kunmap_atomic(target,KM_USER0);
14019+
14020+ flush_dcache_page(page);
14021+ SetPageUptodate(page);
14022+ unlock_page(page);
14023+ if (!pagevec_add(plru_pvec, page))
14024+ __pagevec_lru_add(plru_pvec);
14025+ data += PAGE_CACHE_SIZE;
14026+ }
14027+ return;
14028+}
14029+
14030+
14031+static int
14032+cifs_readpages(struct file *file, struct address_space *mapping,
14033+ struct list_head *page_list, unsigned num_pages)
14034+{
14035+ int rc = -EACCES;
14036+ int xid;
14037+ loff_t offset;
14038+ struct page * page;
14039+ struct cifs_sb_info *cifs_sb;
14040+ struct cifsTconInfo *pTcon;
14041+ int bytes_read = 0;
14042+ unsigned int read_size,i;
14043+ char * smb_read_data = NULL;
14044+ struct smb_com_read_rsp * pSMBr;
14045+ struct pagevec lru_pvec;
14046+ struct cifsFileInfo * open_file;
14047+
14048+ xid = GetXid();
14049+ if (file->private_data == NULL) {
14050+ FreeXid(xid);
14051+ return -EBADF;
14052+ }
14053+ open_file = (struct cifsFileInfo *)file->private_data;
14054+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14055+ pTcon = cifs_sb->tcon;
14056+
14057+ pagevec_init(&lru_pvec, 0);
14058+
14059+ for(i = 0;i<num_pages;) {
14060+ unsigned contig_pages;
14061+ struct page * tmp_page;
14062+ unsigned long expected_index;
14063+
14064+ if(list_empty(page_list)) {
14065+ break;
14066+ }
14067+ page = list_entry(page_list->prev, struct page, lru);
14068+ offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
14069+
14070+ /* count adjacent pages that we will read into */
14071+ contig_pages = 0;
14072+ expected_index = list_entry(page_list->prev,struct page,lru)->index;
14073+ list_for_each_entry_reverse(tmp_page,page_list,lru) {
14074+ if(tmp_page->index == expected_index) {
14075+ contig_pages++;
14076+ expected_index++;
14077+ } else {
14078+ break;
14079+ }
14080+ }
14081+ if(contig_pages + i > num_pages) {
14082+ contig_pages = num_pages - i;
14083+ }
14084+
14085+ /* for reads over a certain size could initiate async read ahead */
14086+
14087+ read_size = contig_pages * PAGE_CACHE_SIZE;
14088+ /* Read size needs to be in multiples of one page */
14089+ read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
14090+
14091+ rc = -EAGAIN;
14092+ while(rc == -EAGAIN) {
14093+ if ((open_file->invalidHandle) && (!open_file->closePend)) {
14094+ rc = cifs_reopen_file(file->f_dentry->d_inode,
14095+ file, TRUE);
14096+ if(rc != 0)
14097+ break;
14098+ }
14099+
14100+ rc = CIFSSMBRead(xid, pTcon,
14101+ open_file->netfid,
14102+ read_size, offset,
14103+ &bytes_read, &smb_read_data);
14104+ /* BB need to check return code here */
14105+ if(rc== -EAGAIN) {
14106+ if(smb_read_data) {
14107+ cifs_buf_release(smb_read_data);
14108+ smb_read_data = NULL;
14109+ }
14110+ }
14111+ }
14112+ if ((rc < 0) || (smb_read_data == NULL)) {
14113+ cFYI(1,("Read error in readpages: %d",rc));
14114+ /* clean up remaing pages off list */
14115+ while (!list_empty(page_list) && (i < num_pages)) {
14116+ page = list_entry(page_list->prev, struct page, lru);
14117+ list_del(&page->lru);
14118+ page_cache_release(page);
14119+ }
14120+ break;
14121+ } else if (bytes_read > 0) {
14122+ pSMBr = (struct smb_com_read_rsp *)smb_read_data;
14123+ cifs_copy_cache_pages(mapping, page_list, bytes_read,
14124+ smb_read_data + 4 /* RFC1001 hdr */ +
14125+ le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
14126+
14127+ i += bytes_read >> PAGE_CACHE_SHIFT;
14128+#ifdef CONFIG_CIFS_STATS
14129+ atomic_inc(&pTcon->num_reads);
14130+ spin_lock(&pTcon->stat_lock);
14131+ pTcon->bytes_read += bytes_read;
14132+ spin_unlock(&pTcon->stat_lock);
14133+#endif
14134+ if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
14135+ cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
14136+
14137+ i++; /* account for partial page */
14138+
14139+ /* server copy of file can have smaller size than client */
14140+ /* BB do we need to verify this common case ? this case is ok -
14141+ if we are at server EOF we will hit it on next read */
14142+
14143+ /* while(!list_empty(page_list) && (i < num_pages)) {
14144+ page = list_entry(page_list->prev,struct page, list);
14145+ list_del(&page->list);
14146+ page_cache_release(page);
14147+ }
14148+ break; */
14149+ }
14150+ } else {
14151+ cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
14152+ /* BB turn off caching and do new lookup on file size at server? */
14153+ while (!list_empty(page_list) && (i < num_pages)) {
14154+ page = list_entry(page_list->prev, struct page, lru);
14155+ list_del(&page->lru);
14156+ page_cache_release(page); /* BB removeme - replace with zero of page? */
14157+ }
14158+ break;
14159+ }
14160+ if(smb_read_data) {
14161+ cifs_buf_release(smb_read_data);
14162+ smb_read_data = NULL;
14163+ }
14164+ bytes_read = 0;
14165+ }
14166+
14167+ pagevec_lru_add(&lru_pvec);
14168+
14169+/* need to free smb_read_data buf before exit */
14170+ if(smb_read_data) {
14171+ cifs_buf_release(smb_read_data);
14172+ smb_read_data = NULL;
14173+ }
14174+
14175+ FreeXid(xid);
14176+ return rc;
14177+}
14178+#endif
14179+
14180+static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
14181+{
14182+ char * read_data;
14183+ int rc;
14184+
14185+ page_cache_get(page);
14186+ read_data = kmap(page);
14187+ /* for reads over a certain size could initiate async read ahead */
14188+
14189+ rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
14190+
14191+ if (rc < 0)
14192+ goto io_error;
14193+ else {
14194+ cFYI(1,("Bytes read %d ",rc));
14195+ }
14196+
14197+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
14198+
14199+ if(PAGE_CACHE_SIZE > rc) {
14200+ memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
14201+ }
14202+ flush_dcache_page(page);
14203+ SetPageUptodate(page);
14204+ rc = 0;
14205+
14206+io_error:
14207+ kunmap(page);
14208+ page_cache_release(page);
14209+ return rc;
14210+}
14211+
14212+static int
14213+cifs_readpage(struct file *file, struct page *page)
14214+{
14215+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
14216+ int rc = -EACCES;
14217+ int xid;
14218+
14219+ xid = GetXid();
14220+
14221+ if (file->private_data == NULL) {
14222+ FreeXid(xid);
14223+ return -EBADF;
14224+ }
14225+
14226+ cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
14227+
14228+ rc = cifs_readpage_worker(file,page,&offset);
14229+
14230+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
14231+ unlock_page(page);
14232+#else
14233+ UnlockPage(page);
14234+#endif
14235+
14236+ FreeXid(xid);
14237+ return rc;
14238+}
14239+
14240+/* We do not want to update the file size from server for inodes
14241+ open for write - to avoid races with writepage extending
14242+ the file - in the future we could consider allowing
14243+ refreshing the inode only on increases in the file size
14244+ but this is tricky to do without racing with writebehind
14245+ page caching in the current Linux kernel design */
14246+
14247+int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
14248+{
14249+ struct list_head *tmp;
14250+ struct list_head *tmp1;
14251+ struct cifsFileInfo *open_file = NULL;
14252+ int rc = TRUE;
14253+
14254+ if(cifsInode == NULL)
14255+ return rc;
14256+
14257+ read_lock(&GlobalSMBSeslock);
14258+ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
14259+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
14260+ if(open_file == NULL)
14261+ break;
14262+ if(open_file->closePend)
14263+ continue;
14264+ /* We check if file is open for writing,
14265+ BB we could supplement this with a check to see if file size
14266+ changes have been flushed to server - ie inode metadata dirty */
14267+ if((open_file->pfile) &&
14268+ ((open_file->pfile->f_flags & O_RDWR) ||
14269+ (open_file->pfile->f_flags & O_WRONLY))) {
14270+ rc = FALSE;
14271+ break;
14272+ }
14273+ if(tmp->next == NULL) {
14274+ cFYI(1,("File instance %p removed",tmp));
14275+ break;
14276+ }
14277+ }
14278+ read_unlock(&GlobalSMBSeslock);
14279+ return rc;
14280+}
14281+
14282+
14283+void
14284+fill_in_inode(struct inode *tmp_inode,
14285+ FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
14286+{
14287+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
14288+ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
14289+
14290+ pfindData->ExtFileAttributes =
14291+ le32_to_cpu(pfindData->ExtFileAttributes);
14292+ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
14293+ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
14294+ cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
14295+ cifsInfo->time = jiffies;
14296+
14297+ /* Linux can not store file creation time unfortunately so ignore it */
14298+ tmp_inode->i_atime =
14299+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
14300+ tmp_inode->i_mtime =
14301+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
14302+ tmp_inode->i_ctime =
14303+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
14304+ /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
14305+ /* 2767 perms - indicate mandatory locking */
14306+ /* BB fill in uid and gid here? with help from winbind?
14307+ or retrieve from NTFS stream extended attribute */
14308+ if(atomic_read(&cifsInfo->inUse) == 0) {
14309+ tmp_inode->i_uid = cifs_sb->mnt_uid;
14310+ tmp_inode->i_gid = cifs_sb->mnt_gid;
14311+ /* set default mode. will override for dirs below */
14312+ tmp_inode->i_mode = cifs_sb->mnt_file_mode;
14313+ }
14314+
14315+ cFYI(0,
14316+ ("CIFS FFIRST: Attributes came in as 0x%x",
14317+ pfindData->ExtFileAttributes));
14318+ if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
14319+ *pobject_type = DT_LNK;
14320+ /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
14321+ tmp_inode->i_mode |= S_IFLNK;
14322+ } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
14323+ *pobject_type = DT_DIR;
14324+ /* override default perms since we do not lock dirs */
14325+ if(atomic_read(&cifsInfo->inUse) == 0) {
14326+ tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
14327+ }
14328+ tmp_inode->i_mode |= S_IFDIR;
14329+ } else {
14330+ *pobject_type = DT_REG;
14331+ tmp_inode->i_mode |= S_IFREG;
14332+ if(pfindData->ExtFileAttributes & ATTR_READONLY)
14333+ tmp_inode->i_mode &= ~(S_IWUGO);
14334+
14335+ }/* could add code here - to validate if device or weird share type? */
14336+
14337+ /* can not fill in nlink here as in qpathinfo version and Unx search */
14338+ if(atomic_read(&cifsInfo->inUse) == 0) {
14339+ atomic_set(&cifsInfo->inUse,1);
14340+ }
14341+ if(is_size_safe_to_change(cifsInfo)) {
14342+ /* can not safely change the file size here if the
14343+ client is writing to it due to potential races */
14344+ tmp_inode->i_size = pfindData->EndOfFile;
14345+
14346+ /* 512 bytes (2**9) is the fake blocksize that must be used */
14347+ /* for this calculation, even though the reported blocksize is larger */
14348+ tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
14349+ }
14350+
14351+ if (pfindData->AllocationSize < pfindData->EndOfFile)
14352+ cFYI(1, ("Possible sparse file: allocation size less than end of file "));
14353+ cFYI(1,
14354+ ("File Size %ld and blocks %ld and blocksize %ld",
14355+ (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
14356+ tmp_inode->i_blksize));
14357+ if (S_ISREG(tmp_inode->i_mode)) {
14358+ cFYI(1, (" File inode "));
14359+ tmp_inode->i_op = &cifs_file_inode_ops;
14360+ tmp_inode->i_fop = &cifs_file_ops;
14361+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
14362+ } else if (S_ISDIR(tmp_inode->i_mode)) {
14363+ cFYI(1, (" Directory inode"));
14364+ tmp_inode->i_op = &cifs_dir_inode_ops;
14365+ tmp_inode->i_fop = &cifs_dir_ops;
14366+ } else if (S_ISLNK(tmp_inode->i_mode)) {
14367+ cFYI(1, (" Symbolic Link inode "));
14368+ tmp_inode->i_op = &cifs_symlink_inode_ops;
14369+ } else {
14370+ cFYI(1, (" Init special inode "));
14371+ init_special_inode(tmp_inode, tmp_inode->i_mode,
14372+ kdev_t_to_nr(tmp_inode->i_rdev));
14373+ }
14374+}
14375+
14376+void
14377+unix_fill_in_inode(struct inode *tmp_inode,
14378+ FILE_UNIX_INFO * pfindData, int *pobject_type)
14379+{
14380+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
14381+ cifsInfo->time = jiffies;
14382+ atomic_inc(&cifsInfo->inUse);
14383+
14384+ tmp_inode->i_atime =
14385+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
14386+ tmp_inode->i_mtime =
14387+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
14388+ tmp_inode->i_ctime =
14389+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
14390+
14391+ tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
14392+ pfindData->Type = le32_to_cpu(pfindData->Type);
14393+ if (pfindData->Type == UNIX_FILE) {
14394+ *pobject_type = DT_REG;
14395+ tmp_inode->i_mode |= S_IFREG;
14396+ } else if (pfindData->Type == UNIX_SYMLINK) {
14397+ *pobject_type = DT_LNK;
14398+ tmp_inode->i_mode |= S_IFLNK;
14399+ } else if (pfindData->Type == UNIX_DIR) {
14400+ *pobject_type = DT_DIR;
14401+ tmp_inode->i_mode |= S_IFDIR;
14402+ } else if (pfindData->Type == UNIX_CHARDEV) {
14403+ *pobject_type = DT_CHR;
14404+ tmp_inode->i_mode |= S_IFCHR;
14405+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
14406+ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
14407+ } else if (pfindData->Type == UNIX_BLOCKDEV) {
14408+ *pobject_type = DT_BLK;
14409+ tmp_inode->i_mode |= S_IFBLK;
14410+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
14411+ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
14412+ } else if (pfindData->Type == UNIX_FIFO) {
14413+ *pobject_type = DT_FIFO;
14414+ tmp_inode->i_mode |= S_IFIFO;
14415+ } else if (pfindData->Type == UNIX_SOCKET) {
14416+ *pobject_type = DT_SOCK;
14417+ tmp_inode->i_mode |= S_IFSOCK;
14418+ }
14419+
14420+ tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
14421+ tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
14422+ tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
14423+
14424+ pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
14425+ if(is_size_safe_to_change(cifsInfo)) {
14426+ /* can not safely change the file size here if the
14427+ client is writing to it due to potential races */
14428+ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
14429+ tmp_inode->i_size = pfindData->EndOfFile;
14430+
14431+ /* 512 bytes (2**9) is the fake blocksize that must be used */
14432+ /* for this calculation, not the real blocksize */
14433+ tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
14434+ }
14435+
14436+ if (S_ISREG(tmp_inode->i_mode)) {
14437+ cFYI(1, ("File inode"));
14438+ tmp_inode->i_op = &cifs_file_inode_ops;
14439+ tmp_inode->i_fop = &cifs_file_ops;
14440+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
14441+ } else if (S_ISDIR(tmp_inode->i_mode)) {
14442+ cFYI(1, ("Directory inode"));
14443+ tmp_inode->i_op = &cifs_dir_inode_ops;
14444+ tmp_inode->i_fop = &cifs_dir_ops;
14445+ } else if (S_ISLNK(tmp_inode->i_mode)) {
14446+ cFYI(1, ("Symbolic Link inode"));
14447+ tmp_inode->i_op = &cifs_symlink_inode_ops;
14448+/* tmp_inode->i_fop = *//* do not need to set to anything */
14449+ } else {
14450+ cFYI(1, ("Special inode"));
14451+ init_special_inode(tmp_inode, tmp_inode->i_mode,
14452+ kdev_t_to_nr(tmp_inode->i_rdev));
14453+ }
14454+}
14455+
14456+static void
14457+construct_dentry(struct qstr *qstring, struct file *file,
14458+ struct inode **ptmp_inode, struct dentry **pnew_dentry)
14459+{
14460+ struct dentry *tmp_dentry;
14461+ struct cifs_sb_info *cifs_sb;
14462+ struct cifsTconInfo *pTcon;
14463+ struct cifsInodeInfo *pCifsI;
14464+
14465+ cFYI(1, ("For %s ", qstring->name));
14466+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14467+ pTcon = cifs_sb->tcon;
14468+
14469+ qstring->hash = full_name_hash(qstring->name, qstring->len);
14470+ tmp_dentry = d_lookup(file->f_dentry, qstring);
14471+ if (tmp_dentry) {
14472+ cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
14473+ *ptmp_inode = tmp_dentry->d_inode;
14474+ /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
14475+ if(*ptmp_inode == NULL) {
14476+ *ptmp_inode = new_inode(file->f_dentry->d_sb);
14477+ if(*ptmp_inode == NULL)
14478+ return;
14479+ d_instantiate(tmp_dentry, *ptmp_inode);
14480+ insert_inode_hash(*ptmp_inode);
14481+ pCifsI = CIFS_I(*ptmp_inode);
14482+ INIT_LIST_HEAD(&pCifsI->openFileList);
14483+ /* can not enable caching for this inode
14484+ until a file instance is open and we
14485+ can check the oplock flag on the open
14486+ response */
14487+ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
14488+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
14489+ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
14490+#endif
14491+ pCifsI->clientCanCacheRead = FALSE;
14492+ pCifsI->clientCanCacheAll = FALSE;
14493+ pCifsI->time = 0;
14494+ /* do not need to set cifs Attrs since
14495+ they are about to be overwritten
14496+ in fill_in_inode */
14497+ atomic_set(&pCifsI->inUse, 0);
14498+ }
14499+ } else {
14500+ tmp_dentry = d_alloc(file->f_dentry, qstring);
14501+ if(tmp_dentry == NULL) {
14502+ cERROR(1,("Failed allocating dentry"));
14503+ return;
14504+ }
14505+
14506+ if(ptmp_inode) {
14507+ *ptmp_inode = new_inode(file->f_dentry->d_sb);
14508+ if(*ptmp_inode == NULL)
14509+ return;
14510+ pCifsI = CIFS_I(*ptmp_inode);
14511+ insert_inode_hash(*ptmp_inode);
14512+ INIT_LIST_HEAD(&pCifsI->openFileList);
14513+ /* can not enable caching for this inode
14514+ until a file instance is open and we
14515+ can check the oplock flag on the open
14516+ response */
14517+ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
14518+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
14519+ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
14520+#endif
14521+ pCifsI->clientCanCacheRead = FALSE;
14522+ pCifsI->clientCanCacheAll = FALSE;
14523+ pCifsI->time = 0;
14524+ /* do not need to set cifs Attrs since
14525+ they are about to be overwritten
14526+ in fill_in_inode */
14527+ atomic_set(&pCifsI->inUse, 0);
14528+ }
14529+ tmp_dentry->d_op = &cifs_dentry_ops;
14530+ d_instantiate(tmp_dentry, *ptmp_inode);
14531+ d_rehash(tmp_dentry);
14532+ }
14533+
14534+ tmp_dentry->d_time = jiffies;
14535+ *pnew_dentry = tmp_dentry;
14536+}
14537+
14538+static void reset_resume_key(struct file * dir_file,
14539+ unsigned char * filename,
14540+ unsigned int len,int Unicode,struct nls_table * nls_tab) {
14541+ struct cifsFileInfo *cifsFile;
14542+
14543+ cifsFile = (struct cifsFileInfo *)dir_file->private_data;
14544+ if(cifsFile == NULL)
14545+ return;
14546+ if(cifsFile->search_resume_name) {
14547+ kfree(cifsFile->search_resume_name);
14548+ }
14549+
14550+ if(Unicode)
14551+ len *= 2;
14552+ cifsFile->resume_name_length = len;
14553+
14554+ cifsFile->search_resume_name =
14555+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14556+
14557+ if(cifsFile->search_resume_name == NULL) {
14558+ cERROR(1,("failed new resume key allocate, length %d",
14559+ cifsFile->resume_name_length));
14560+ return;
14561+ }
14562+ if(Unicode)
14563+ cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
14564+ filename, len, nls_tab);
14565+ else
14566+ memcpy(cifsFile->search_resume_name, filename,
14567+ cifsFile->resume_name_length);
14568+ cFYI(1,("Reset resume key to: %s with len %d",filename,len));
14569+ return;
14570+}
14571+
14572+
14573+
14574+static int
14575+cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
14576+ struct file *file, filldir_t filldir, void *direntry)
14577+{
14578+ struct inode *tmp_inode;
14579+ struct dentry *tmp_dentry;
14580+ int object_type,rc;
14581+
14582+ pqstring->name = pfindData->FileName;
14583+ pqstring->len = pfindData->FileNameLength;
14584+
14585+ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
14586+ if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
14587+ return -ENOMEM;
14588+ }
14589+ fill_in_inode(tmp_inode, pfindData, &object_type);
14590+ rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
14591+ tmp_inode->i_ino, object_type);
14592+ if(rc) {
14593+ /* due to readdir error we need to recalculate resume
14594+ key so next readdir will restart on right entry */
14595+ cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
14596+ }
14597+ dput(tmp_dentry);
14598+ return rc;
14599+}
14600+
14601+static int
14602+cifs_filldir_unix(struct qstr *pqstring,
14603+ FILE_UNIX_INFO * pUnixFindData, struct file *file,
14604+ filldir_t filldir, void *direntry)
14605+{
14606+ struct inode *tmp_inode;
14607+ struct dentry *tmp_dentry;
14608+ int object_type, rc;
14609+
14610+ pqstring->name = pUnixFindData->FileName;
14611+ pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
14612+
14613+ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
14614+ if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
14615+ return -ENOMEM;
14616+ }
14617+
14618+ unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
14619+ rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
14620+ file->f_pos, tmp_inode->i_ino, object_type);
14621+ if(rc) {
14622+ /* due to readdir error we need to recalculate resume
14623+ key so next readdir will restart on right entry */
14624+ cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
14625+ }
14626+ dput(tmp_dentry);
14627+ return rc;
14628+}
14629+
14630+int
14631+cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
14632+{
14633+ int rc = 0;
14634+ int xid;
14635+ int Unicode = FALSE;
14636+ int UnixSearch = FALSE;
14637+ unsigned int bufsize, i;
14638+ __u16 searchHandle;
14639+ struct cifs_sb_info *cifs_sb;
14640+ struct cifsTconInfo *pTcon;
14641+ struct cifsFileInfo *cifsFile = NULL;
14642+ char *full_path = NULL;
14643+ char *data;
14644+ struct qstr qstring;
14645+ T2_FFIRST_RSP_PARMS findParms;
14646+ T2_FNEXT_RSP_PARMS findNextParms;
14647+ FILE_DIRECTORY_INFO *pfindData;
14648+ FILE_DIRECTORY_INFO *lastFindData;
14649+ FILE_UNIX_INFO *pfindDataUnix;
14650+
14651+ xid = GetXid();
14652+
14653+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14654+ pTcon = cifs_sb->tcon;
14655+ bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
14656+ if(bufsize > CIFS_MAX_MSGSIZE) {
14657+ FreeXid(xid);
14658+ return -EIO;
14659+ }
14660+ data = kmalloc(bufsize, GFP_KERNEL);
14661+ pfindData = (FILE_DIRECTORY_INFO *) data;
14662+
14663+ if(file->f_dentry == NULL) {
14664+ FreeXid(xid);
14665+ return -EIO;
14666+ }
14667+ down(&file->f_dentry->d_sb->s_vfs_rename_sem);
14668+ full_path = build_wildcard_path_from_dentry(file->f_dentry);
14669+ up(&file->f_dentry->d_sb->s_vfs_rename_sem);
14670+
14671+
14672+ cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
14673+
14674+ switch ((int) file->f_pos) {
14675+ case 0:
14676+ if (filldir(direntry, ".", 1, file->f_pos,
14677+ file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
14678+ cERROR(1, ("Filldir for current dir failed "));
14679+ break;
14680+ }
14681+ file->f_pos++;
14682+ /* fallthrough */
14683+ case 1:
14684+ if (filldir(direntry, "..", 2, file->f_pos,
14685+ file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
14686+ cERROR(1, ("Filldir for parent dir failed "));
14687+ break;
14688+ }
14689+ file->f_pos++;
14690+ /* fallthrough */
14691+ case 2:
14692+ if (file->private_data != NULL) {
14693+ cifsFile =
14694+ (struct cifsFileInfo *) file->private_data;
14695+ if (cifsFile->endOfSearch) {
14696+ if(cifsFile->emptyDir) {
14697+ cFYI(1, ("End of search, empty dir"));
14698+ rc = 0;
14699+ break;
14700+ }
14701+ } else {
14702+ cifsFile->invalidHandle = TRUE;
14703+ CIFSFindClose(xid, pTcon, cifsFile->netfid);
14704+ }
14705+ if(cifsFile->search_resume_name) {
14706+ kfree(cifsFile->search_resume_name);
14707+ cifsFile->search_resume_name = NULL;
14708+ }
14709+ }
14710+ rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
14711+ &findParms, cifs_sb->local_nls,
14712+ &Unicode, &UnixSearch);
14713+ cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
14714+ findParms.EndofSearch));
14715+
14716+ if (rc == 0) {
14717+ searchHandle = findParms.SearchHandle;
14718+ if(file->private_data == NULL)
14719+ file->private_data =
14720+ kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
14721+ if (file->private_data) {
14722+ memset(file->private_data, 0,
14723+ sizeof (struct cifsFileInfo));
14724+ cifsFile =
14725+ (struct cifsFileInfo *) file->private_data;
14726+ cifsFile->netfid = searchHandle;
14727+ cifsFile->invalidHandle = FALSE;
14728+ init_MUTEX(&cifsFile->fh_sem);
14729+ } else {
14730+ rc = -ENOMEM;
14731+ break;
14732+ }
14733+
14734+ renew_parental_timestamps(file->f_dentry);
14735+ lastFindData =
14736+ (FILE_DIRECTORY_INFO *) ((char *) pfindData +
14737+ findParms.LastNameOffset);
14738+ if((char *)lastFindData > (char *)pfindData + bufsize) {
14739+ cFYI(1,("last search entry past end of packet"));
14740+ rc = -EIO;
14741+ break;
14742+ }
14743+ /* Offset of resume key same for levels 257 and 514 */
14744+ cifsFile->resume_key = lastFindData->FileIndex;
14745+ if(UnixSearch == FALSE) {
14746+ cifsFile->resume_name_length =
14747+ le32_to_cpu(lastFindData->FileNameLength);
14748+ if(cifsFile->resume_name_length > bufsize - 64) {
14749+ cFYI(1,("Illegal resume file name length %d",
14750+ cifsFile->resume_name_length));
14751+ rc = -ENOMEM;
14752+ break;
14753+ }
14754+ cifsFile->search_resume_name =
14755+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14756+ cFYI(1,("Last file: %s with name %d bytes long",
14757+ lastFindData->FileName,
14758+ cifsFile->resume_name_length));
14759+ memcpy(cifsFile->search_resume_name,
14760+ lastFindData->FileName,
14761+ cifsFile->resume_name_length);
14762+ } else {
14763+ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
14764+ if (Unicode == TRUE) {
14765+ for(i=0;(pfindDataUnix->FileName[i]
14766+ | pfindDataUnix->FileName[i+1]);
14767+ i+=2) {
14768+ if(i > bufsize-64)
14769+ break;
14770+ }
14771+ cifsFile->resume_name_length = i + 2;
14772+ } else {
14773+ cifsFile->resume_name_length =
14774+ strnlen(pfindDataUnix->FileName,
14775+ bufsize-63);
14776+ }
14777+ if(cifsFile->resume_name_length > bufsize - 64) {
14778+ cFYI(1,("Illegal resume file name length %d",
14779+ cifsFile->resume_name_length));
14780+ rc = -ENOMEM;
14781+ break;
14782+ }
14783+ cifsFile->search_resume_name =
14784+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14785+ cFYI(1,("Last file: %s with name %d bytes long",
14786+ pfindDataUnix->FileName,
14787+ cifsFile->resume_name_length));
14788+ memcpy(cifsFile->search_resume_name,
14789+ pfindDataUnix->FileName,
14790+ cifsFile->resume_name_length);
14791+ }
14792+ for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
14793+ if (UnixSearch == FALSE) {
14794+ pfindData->FileNameLength =
14795+ le32_to_cpu(pfindData->FileNameLength);
14796+ if (Unicode == TRUE)
14797+ pfindData->FileNameLength =
14798+ cifs_strfromUCS_le
14799+ (pfindData->FileName,
14800+ (wchar_t *)
14801+ pfindData->FileName,
14802+ (pfindData->
14803+ FileNameLength) / 2,
14804+ cifs_sb->local_nls);
14805+ qstring.len = pfindData->FileNameLength;
14806+ if (((qstring.len != 1)
14807+ || (pfindData->FileName[0] != '.'))
14808+ && ((qstring.len != 2)
14809+ || (pfindData->
14810+ FileName[0] != '.')
14811+ || (pfindData->
14812+ FileName[1] != '.'))) {
14813+ if(cifs_filldir(&qstring,
14814+ pfindData,
14815+ file, filldir,
14816+ direntry)) {
14817+ /* do not end search if
14818+ kernel not ready to take
14819+ remaining entries yet */
14820+ reset_resume_key(file, pfindData->FileName,qstring.len,
14821+ Unicode, cifs_sb->local_nls);
14822+ findParms.EndofSearch = 0;
14823+ break;
14824+ }
14825+ file->f_pos++;
14826+ }
14827+ } else { /* UnixSearch */
14828+ pfindDataUnix =
14829+ (FILE_UNIX_INFO *) pfindData;
14830+ if (Unicode == TRUE)
14831+ qstring.len =
14832+ cifs_strfromUCS_le
14833+ (pfindDataUnix->FileName,
14834+ (wchar_t *)
14835+ pfindDataUnix->FileName,
14836+ MAX_PATHCONF,
14837+ cifs_sb->local_nls);
14838+ else
14839+ qstring.len =
14840+ strnlen(pfindDataUnix->
14841+ FileName,
14842+ MAX_PATHCONF);
14843+ if (((qstring.len != 1)
14844+ || (pfindDataUnix->
14845+ FileName[0] != '.'))
14846+ && ((qstring.len != 2)
14847+ || (pfindDataUnix->
14848+ FileName[0] != '.')
14849+ || (pfindDataUnix->
14850+ FileName[1] != '.'))) {
14851+ if(cifs_filldir_unix(&qstring,
14852+ pfindDataUnix,
14853+ file,
14854+ filldir,
14855+ direntry)) {
14856+ /* do not end search if
14857+ kernel not ready to take
14858+ remaining entries yet */
14859+ findParms.EndofSearch = 0;
14860+ reset_resume_key(file, pfindDataUnix->FileName,
14861+ qstring.len,Unicode,cifs_sb->local_nls);
14862+ break;
14863+ }
14864+ file->f_pos++;
14865+ }
14866+ }
14867+ /* works also for Unix ff struct since first field of both */
14868+ pfindData =
14869+ (FILE_DIRECTORY_INFO *) ((char *) pfindData
14870+ + le32_to_cpu(pfindData->NextEntryOffset));
14871+ /* BB also should check to make sure that pointer is not beyond the end of the SMB */
14872+ /* if(pfindData > lastFindData) rc = -EIO; break; */
14873+ } /* end for loop */
14874+ if ((findParms.EndofSearch != 0) && cifsFile) {
14875+ cifsFile->endOfSearch = TRUE;
14876+ if(findParms.SearchCount == 2)
14877+ cifsFile->emptyDir = TRUE;
14878+ }
14879+ } else {
14880+ if (cifsFile)
14881+ cifsFile->endOfSearch = TRUE;
14882+ /* unless parent directory gone do not return error */
14883+ rc = 0;
14884+ }
14885+ break;
14886+ default:
14887+ if (file->private_data == NULL) {
14888+ rc = -EBADF;
14889+ cFYI(1,
14890+ ("Readdir on closed srch, pos = %lld",
14891+ file->f_pos));
14892+ } else {
14893+ cifsFile = (struct cifsFileInfo *) file->private_data;
14894+ if (cifsFile->endOfSearch) {
14895+ rc = 0;
14896+ cFYI(1, ("End of search "));
14897+ break;
14898+ }
14899+ searchHandle = cifsFile->netfid;
14900+ rc = CIFSFindNext(xid, pTcon, pfindData,
14901+ &findNextParms, searchHandle,
14902+ cifsFile->search_resume_name,
14903+ cifsFile->resume_name_length,
14904+ cifsFile->resume_key,
14905+ &Unicode, &UnixSearch);
14906+ cFYI(1,("Count: %d End: %d ",
14907+ findNextParms.SearchCount,
14908+ findNextParms.EndofSearch));
14909+ if ((rc == 0) && (findNextParms.SearchCount != 0)) {
14910+ /* BB save off resume key, key name and name length */
14911+ lastFindData =
14912+ (FILE_DIRECTORY_INFO *) ((char *) pfindData
14913+ + findNextParms.LastNameOffset);
14914+ if((char *)lastFindData > (char *)pfindData + bufsize) {
14915+ cFYI(1,("last search entry past end of packet"));
14916+ rc = -EIO;
14917+ break;
14918+ }
14919+ /* Offset of resume key same for levels 257 and 514 */
14920+ cifsFile->resume_key = lastFindData->FileIndex;
14921+
14922+ if(UnixSearch == FALSE) {
14923+ cifsFile->resume_name_length =
14924+ le32_to_cpu(lastFindData->FileNameLength);
14925+ if(cifsFile->resume_name_length > bufsize - 64) {
14926+ cFYI(1,("Illegal resume file name length %d",
14927+ cifsFile->resume_name_length));
14928+ rc = -ENOMEM;
14929+ break;
14930+ }
14931+ /* Free the memory allocated by previous findfirst
14932+ or findnext call - we can not reuse the memory since
14933+ the resume name may not be same string length */
14934+ if(cifsFile->search_resume_name)
14935+ kfree(cifsFile->search_resume_name);
14936+ cifsFile->search_resume_name =
14937+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14938+ cFYI(1,("Last file: %s with name %d bytes long",
14939+ lastFindData->FileName,
14940+ cifsFile->resume_name_length));
14941+ memcpy(cifsFile->search_resume_name,
14942+ lastFindData->FileName,
14943+ cifsFile->resume_name_length);
14944+ } else {
14945+ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
14946+ if (Unicode == TRUE) {
14947+ for(i=0;(pfindDataUnix->FileName[i]
14948+ | pfindDataUnix->FileName[i+1]);
14949+ i+=2) {
14950+ if(i > bufsize-64)
14951+ break;
14952+ }
14953+ cifsFile->resume_name_length = i + 2;
14954+ } else {
14955+ cifsFile->resume_name_length =
14956+ strnlen(pfindDataUnix->
14957+ FileName,
14958+ MAX_PATHCONF);
14959+ }
14960+ if(cifsFile->resume_name_length > bufsize - 64) {
14961+ cFYI(1,("Illegal resume file name length %d",
14962+ cifsFile->resume_name_length));
14963+ rc = -ENOMEM;
14964+ break;
14965+ }
14966+ /* Free the memory allocated by previous findfirst
14967+ or findnext call - we can not reuse the memory since
14968+ the resume name may not be same string length */
14969+ if(cifsFile->search_resume_name)
14970+ kfree(cifsFile->search_resume_name);
14971+ cifsFile->search_resume_name =
14972+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14973+ cFYI(1,("fnext last file: %s with name %d bytes long",
14974+ pfindDataUnix->FileName,
14975+ cifsFile->resume_name_length));
14976+ memcpy(cifsFile->search_resume_name,
14977+ pfindDataUnix->FileName,
14978+ cifsFile->resume_name_length);
14979+ }
14980+
14981+ for (i = 0; i < findNextParms.SearchCount; i++) {
14982+ pfindData->FileNameLength =
14983+ le32_to_cpu(pfindData->
14984+ FileNameLength);
14985+ if (UnixSearch == FALSE) {
14986+ if (Unicode == TRUE)
14987+ pfindData->FileNameLength =
14988+ cifs_strfromUCS_le
14989+ (pfindData->FileName,
14990+ (wchar_t *)
14991+ pfindData->FileName,
14992+ (pfindData->FileNameLength)/ 2,
14993+ cifs_sb->local_nls);
14994+ qstring.len =
14995+ pfindData->FileNameLength;
14996+ if (((qstring.len != 1)
14997+ || (pfindData->FileName[0] != '.'))
14998+ && ((qstring.len != 2)
14999+ || (pfindData->FileName[0] != '.')
15000+ || (pfindData->FileName[1] !=
15001+ '.'))) {
15002+ if(cifs_filldir
15003+ (&qstring,
15004+ pfindData,
15005+ file, filldir,
15006+ direntry)) {
15007+ /* do not end search if
15008+ kernel not ready to take
15009+ remaining entries yet */
15010+ findNextParms.EndofSearch = 0;
15011+ reset_resume_key(file, pfindData->FileName,qstring.len,
15012+ Unicode,cifs_sb->local_nls);
15013+ break;
15014+ }
15015+ file->f_pos++;
15016+ }
15017+ } else { /* UnixSearch */
15018+ pfindDataUnix =
15019+ (FILE_UNIX_INFO *)
15020+ pfindData;
15021+ if (Unicode == TRUE)
15022+ qstring.len =
15023+ cifs_strfromUCS_le
15024+ (pfindDataUnix->FileName,
15025+ (wchar_t *)
15026+ pfindDataUnix->FileName,
15027+ MAX_PATHCONF,
15028+ cifs_sb->local_nls);
15029+ else
15030+ qstring.len =
15031+ strnlen
15032+ (pfindDataUnix->
15033+ FileName,
15034+ MAX_PATHCONF);
15035+ if (((qstring.len != 1)
15036+ || (pfindDataUnix->
15037+ FileName[0] != '.'))
15038+ && ((qstring.len != 2)
15039+ || (pfindDataUnix->
15040+ FileName[0] != '.')
15041+ || (pfindDataUnix->
15042+ FileName[1] !=
15043+ '.'))) {
15044+ if(cifs_filldir_unix
15045+ (&qstring,
15046+ pfindDataUnix,
15047+ file, filldir,
15048+ direntry)) {
15049+ /* do not end search if
15050+ kernel not ready to take
15051+ remaining entries yet */
15052+ findNextParms.EndofSearch = 0;
15053+ reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
15054+ Unicode,cifs_sb->local_nls);
15055+ break;
15056+ }
15057+ file->f_pos++;
15058+ }
15059+ }
15060+ 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 */
15061+ /* BB also should check to make sure that pointer is not beyond the end of the SMB */
15062+ } /* end for loop */
15063+ if (findNextParms.EndofSearch != 0) {
15064+ cifsFile->endOfSearch = TRUE;
15065+ }
15066+ } else {
15067+ cifsFile->endOfSearch = TRUE;
15068+ rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */
15069+ }
15070+ }
15071+ } /* end switch */
15072+ if (data)
15073+ kfree(data);
15074+ if (full_path)
15075+ kfree(full_path);
15076+ FreeXid(xid);
15077+
15078+ return rc;
15079+}
15080+int cifs_prepare_write(struct file *file, struct page *page,
15081+ unsigned from, unsigned to)
15082+{
15083+ int rc = 0;
15084+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
15085+ cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
15086+ if (!Page_Uptodate(page)) {
15087+ /* if (to - from != PAGE_CACHE_SIZE) {
15088+ void *kaddr = kmap_atomic(page, KM_USER0);
15089+ memset(kaddr, 0, from);
15090+ memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
15091+ flush_dcache_page(page);
15092+ kunmap_atomic(kaddr, KM_USER0);
15093+ } */
15094+ /* If we are writing a full page it will be up to date,
15095+ no need to read from the server */
15096+ if((to==PAGE_CACHE_SIZE) && (from == 0))
15097+ SetPageUptodate(page);
15098+
15099+ /* might as well read a page, it is fast enough */
15100+ if((file->f_flags & O_ACCMODE) != O_WRONLY) {
15101+ rc = cifs_readpage_worker(file,page,&offset);
15102+ } else {
15103+ /* should we try using another
15104+ file handle if there is one - how would we lock it
15105+ to prevent close of that handle racing with this read? */
15106+ /* In any case this will be written out by commit_write */
15107+ }
15108+ }
15109+
15110+ /* BB should we pass any errors back? e.g. if we do not have read access to the file */
15111+ return 0;
15112+}
15113+
15114+
15115+struct address_space_operations cifs_addr_ops = {
15116+ .readpage = cifs_readpage,
15117+/* .readpages = cifs_readpages, */
15118+ .writepage = cifs_writepage,
15119+ .prepare_write = cifs_prepare_write,
15120+ .commit_write = cifs_commit_write,
15121+ .sync_page = cifs_sync_page,
15122+ /*.direct_IO = */
15123+};
15124--- /dev/null
15125+++ b/fs/cifs/inode.c
15126@@ -0,0 +1,1079 @@
15127+/*
15128+ * fs/cifs/inode.c
15129+ *
15130+ * Copyright (C) International Business Machines Corp., 2002,2003
15131+ * Author(s): Steve French (sfrench@us.ibm.com)
15132+ *
15133+ * This library is free software; you can redistribute it and/or modify
15134+ * it under the terms of the GNU Lesser General Public License as published
15135+ * by the Free Software Foundation; either version 2.1 of the License, or
15136+ * (at your option) any later version.
15137+ *
15138+ * This library is distributed in the hope that it will be useful,
15139+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15140+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15141+ * the GNU Lesser General Public License for more details.
15142+ *
15143+ * You should have received a copy of the GNU Lesser General Public License
15144+ * along with this library; if not, write to the Free Software
15145+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15146+ */
15147+#include <linux/fs.h>
15148+#include <linux/stat.h>
15149+#include <linux/pagemap.h>
15150+#include <linux/version.h>
15151+#include <asm/div64.h>
15152+#include "cifsfs.h"
15153+#include "cifspdu.h"
15154+#include "cifsglob.h"
15155+#include "cifsproto.h"
15156+#include "cifs_debug.h"
15157+#include "cifs_fs_sb.h"
15158+
15159+extern int is_size_safe_to_change(struct cifsInodeInfo *);
15160+
15161+struct inode * get_cifs_inode(struct super_block * sb)
15162+{
15163+ struct inode * newinode;
15164+ newinode = new_inode(sb);
15165+ cFYI(1,("got new inode %p",newinode));
15166+ if(newinode) {
15167+ struct cifsInodeInfo * cifsInfo = CIFS_I(newinode);
15168+ cifsInfo->clientCanCacheRead = FALSE;
15169+ cifsInfo->clientCanCacheAll = FALSE;
15170+ INIT_LIST_HEAD(&cifsInfo->openFileList);
15171+ cifsInfo->cifsAttrs = 0x20; /* default */
15172+ newinode->i_blksize = CIFS_MAX_MSGSIZE;
15173+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
15174+ newinode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
15175+#endif
15176+ atomic_set(&cifsInfo->inUse, 0);
15177+ cifsInfo->time = 0;
15178+ insert_inode_hash(newinode);
15179+ }
15180+ return newinode;
15181+
15182+}
15183+
15184+int
15185+cifs_get_inode_info_unix(struct inode **pinode,
15186+ const unsigned char *search_path,
15187+ struct super_block *sb,int xid)
15188+{
15189+ int rc = 0;
15190+ FILE_UNIX_BASIC_INFO findData;
15191+ struct cifsTconInfo *pTcon;
15192+ struct inode *inode;
15193+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
15194+ char *tmp_path;
15195+
15196+ pTcon = cifs_sb->tcon;
15197+ cFYI(1, (" Getting info on %s ", search_path));
15198+ /* we could have done a find first instead but this returns more info */
15199+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
15200+ cifs_sb->local_nls);
15201+ /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
15202+ if (rc) {
15203+ if (rc == -EREMOTE) {
15204+ tmp_path =
15205+ kmalloc(strnlen
15206+ (pTcon->treeName,
15207+ MAX_TREE_SIZE + 1) +
15208+ strnlen(search_path, MAX_PATHCONF) + 1,
15209+ GFP_KERNEL);
15210+ if (tmp_path == NULL) {
15211+ return -ENOMEM;
15212+ }
15213+ /* have to skip first of the double backslash of UNC name */
15214+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
15215+ strncat(tmp_path, search_path, MAX_PATHCONF);
15216+ rc = connect_to_dfs_path(xid, pTcon->ses,
15217+ /* treename + */ tmp_path,
15218+ cifs_sb->local_nls);
15219+ kfree(tmp_path);
15220+
15221+ /* BB fix up inode etc. */
15222+ } else if (rc) {
15223+ return rc;
15224+ }
15225+
15226+ } else {
15227+ struct cifsInodeInfo *cifsInfo;
15228+
15229+ /* get new inode */
15230+ if (*pinode == NULL) {
15231+ *pinode = get_cifs_inode(sb);
15232+ }
15233+ if(*pinode == NULL) {
15234+ return -ENOMEM;
15235+ }
15236+
15237+ inode = *pinode;
15238+ cifsInfo = CIFS_I(inode);
15239+
15240+ cFYI(1, (" Old time %ld ", cifsInfo->time));
15241+ cifsInfo->time = jiffies;
15242+ cFYI(1, (" New time %ld ", cifsInfo->time));
15243+ atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
15244+
15245+ inode->i_atime =
15246+ cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
15247+ inode->i_mtime =
15248+ cifs_NTtimeToUnix(le64_to_cpu
15249+ (findData.LastModificationTime));
15250+ inode->i_ctime =
15251+ cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
15252+ inode->i_mode = le64_to_cpu(findData.Permissions);
15253+ findData.Type = le32_to_cpu(findData.Type);
15254+ if (findData.Type == UNIX_FILE) {
15255+ inode->i_mode |= S_IFREG;
15256+ } else if (findData.Type == UNIX_SYMLINK) {
15257+ inode->i_mode |= S_IFLNK;
15258+ } else if (findData.Type == UNIX_DIR) {
15259+ inode->i_mode |= S_IFDIR;
15260+ } else if (findData.Type == UNIX_CHARDEV) {
15261+ inode->i_mode |= S_IFCHR;
15262+ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
15263+ le64_to_cpu(findData.DevMinor) & MINORMASK);
15264+ } else if (findData.Type == UNIX_BLOCKDEV) {
15265+ inode->i_mode |= S_IFBLK;
15266+ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
15267+ le64_to_cpu(findData.DevMinor) & MINORMASK);
15268+ } else if (findData.Type == UNIX_FIFO) {
15269+ inode->i_mode |= S_IFIFO;
15270+ } else if (findData.Type == UNIX_SOCKET) {
15271+ inode->i_mode |= S_IFSOCK;
15272+ }
15273+ inode->i_uid = le64_to_cpu(findData.Uid);
15274+ inode->i_gid = le64_to_cpu(findData.Gid);
15275+ inode->i_nlink = le64_to_cpu(findData.Nlinks);
15276+ findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
15277+ findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
15278+
15279+ if(is_size_safe_to_change(cifsInfo)) {
15280+ /* can not safely change the file size here if the
15281+ client is writing to it due to potential races */
15282+ inode->i_size = findData.EndOfFile;
15283+/* blksize needs to be multiple of two. So safer to default to blksize
15284+ and blkbits set in superblock so 2**blkbits and blksize will match */
15285+/* inode->i_blksize =
15286+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
15287+
15288+ /* This seems incredibly stupid but it turns out that
15289+ i_blocks is not related to (i_size / i_blksize), instead a
15290+ size of 512 is required to be used for calculating num blocks */
15291+
15292+
15293+/* inode->i_blocks =
15294+ (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
15295+
15296+ /* 512 bytes (2**9) is the fake blocksize that must be used */
15297+ /* for this calculation */
15298+ inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
15299+ }
15300+
15301+ if (findData.NumOfBytes < findData.EndOfFile)
15302+ cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
15303+ cFYI(1,
15304+ ("Size %ld and blocks %ld ",
15305+ (unsigned long) inode->i_size, inode->i_blocks));
15306+ if (S_ISREG(inode->i_mode)) {
15307+ cFYI(1, (" File inode "));
15308+ inode->i_op = &cifs_file_inode_ops;
15309+ inode->i_fop = &cifs_file_ops;
15310+ inode->i_data.a_ops = &cifs_addr_ops;
15311+ } else if (S_ISDIR(inode->i_mode)) {
15312+ cFYI(1, (" Directory inode"));
15313+ inode->i_op = &cifs_dir_inode_ops;
15314+ inode->i_fop = &cifs_dir_ops;
15315+ } else if (S_ISLNK(inode->i_mode)) {
15316+ cFYI(1, (" Symbolic Link inode "));
15317+ inode->i_op = &cifs_symlink_inode_ops;
15318+/* tmp_inode->i_fop = *//* do not need to set to anything */
15319+ } else {
15320+ cFYI(1, (" Init special inode "));
15321+ init_special_inode(inode, inode->i_mode,
15322+ kdev_t_to_nr(inode->i_rdev));
15323+ }
15324+ }
15325+ return rc;
15326+}
15327+
15328+int
15329+cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
15330+ FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
15331+{
15332+ int rc = 0;
15333+ struct cifsTconInfo *pTcon;
15334+ struct inode *inode;
15335+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
15336+ char *tmp_path;
15337+ char *buf = NULL;
15338+
15339+ pTcon = cifs_sb->tcon;
15340+ cFYI(1,("Getting info on %s ", search_path));
15341+
15342+ if((pfindData == NULL) && (*pinode != NULL)) {
15343+ if(CIFS_I(*pinode)->clientCanCacheRead) {
15344+ cFYI(1,("No need to revalidate inode sizes on cached file "));
15345+ return rc;
15346+ }
15347+ }
15348+
15349+ /* if file info not passed in then get it from server */
15350+ if(pfindData == NULL) {
15351+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
15352+ pfindData = (FILE_ALL_INFO *)buf;
15353+ /* could do find first instead but this returns more info */
15354+ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
15355+ cifs_sb->local_nls);
15356+ }
15357+ /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
15358+ if (rc) {
15359+ if (rc == -EREMOTE) {
15360+ tmp_path =
15361+ kmalloc(strnlen
15362+ (pTcon->treeName,
15363+ MAX_TREE_SIZE + 1) +
15364+ strnlen(search_path, MAX_PATHCONF) + 1,
15365+ GFP_KERNEL);
15366+ if (tmp_path == NULL) {
15367+ if(buf)
15368+ kfree(buf);
15369+ return -ENOMEM;
15370+ }
15371+
15372+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
15373+ strncat(tmp_path, search_path, MAX_PATHCONF);
15374+ rc = connect_to_dfs_path(xid, pTcon->ses,
15375+ /* treename + */ tmp_path,
15376+ cifs_sb->local_nls);
15377+ kfree(tmp_path);
15378+ /* BB fix up inode etc. */
15379+ } else if (rc) {
15380+ if(buf)
15381+ kfree(buf);
15382+ return rc;
15383+ }
15384+ } else {
15385+ struct cifsInodeInfo *cifsInfo;
15386+
15387+ /* get new inode */
15388+ if (*pinode == NULL) {
15389+ *pinode = get_cifs_inode(sb);
15390+ }
15391+ if(*pinode == NULL)
15392+ return -ENOMEM;
15393+ inode = *pinode;
15394+ cifsInfo = CIFS_I(inode);
15395+ pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
15396+ cifsInfo->cifsAttrs = pfindData->Attributes;
15397+ cFYI(1, (" Old time %ld ", cifsInfo->time));
15398+ cifsInfo->time = jiffies;
15399+ cFYI(1, (" New time %ld ", cifsInfo->time));
15400+
15401+/* blksize needs to be multiple of two. So safer to default to blksize
15402+ and blkbits set in superblock so 2**blkbits and blksize will match */
15403+/* inode->i_blksize =
15404+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
15405+
15406+ /* Linux can not store file creation time unfortunately so we ignore it */
15407+ inode->i_atime =
15408+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
15409+ inode->i_mtime =
15410+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
15411+ inode->i_ctime =
15412+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
15413+ cFYI(0,
15414+ (" Attributes came in as 0x%x ", pfindData->Attributes));
15415+
15416+ /* set default mode. will override for dirs below */
15417+ if(atomic_read(&cifsInfo->inUse) == 0)
15418+ /* new inode, can safely set these fields */
15419+ inode->i_mode = cifs_sb->mnt_file_mode;
15420+
15421+ if (pfindData->Attributes & ATTR_REPARSE) {
15422+ /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
15423+ inode->i_mode |= S_IFLNK;
15424+ } else if (pfindData->Attributes & ATTR_DIRECTORY) {
15425+ /* override default perms since we do not do byte range locking on dirs */
15426+ inode->i_mode = cifs_sb->mnt_dir_mode;
15427+ inode->i_mode |= S_IFDIR;
15428+ } else {
15429+ inode->i_mode |= S_IFREG;
15430+ /* treat the dos attribute of read-only as read-only mode e.g. 555 */
15431+ if(cifsInfo->cifsAttrs & ATTR_READONLY)
15432+ inode->i_mode &= ~(S_IWUGO);
15433+ /* BB add code here - validate if device or weird share or device type? */
15434+ }
15435+ if(is_size_safe_to_change(cifsInfo)) {
15436+ /* can not safely change the file size here if the
15437+ client is writing to it due to potential races */
15438+ inode->i_size = le64_to_cpu(pfindData->EndOfFile);
15439+
15440+ /* 512 bytes (2**9) is the fake blocksize that must be used */
15441+ /* for this calculation */
15442+ inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
15443+ >> 9;
15444+ }
15445+ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
15446+
15447+ cFYI(1,
15448+ (" Size %ld and blocks %ld ",
15449+ (unsigned long) inode->i_size, inode->i_blocks));
15450+ inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
15451+
15452+ /* BB fill in uid and gid here? with help from winbind?
15453+ or retrieve from NTFS stream extended attribute */
15454+ if(atomic_read(&cifsInfo->inUse) == 0) {
15455+ inode->i_uid = cifs_sb->mnt_uid;
15456+ inode->i_gid = cifs_sb->mnt_gid;
15457+ /* set so we do not keep refreshing these fields with
15458+ bad data after user has changed them in memory */
15459+ atomic_set(&cifsInfo->inUse,1);
15460+ }
15461+
15462+ if (S_ISREG(inode->i_mode)) {
15463+ cFYI(1, (" File inode "));
15464+ inode->i_op = &cifs_file_inode_ops;
15465+ inode->i_fop = &cifs_file_ops;
15466+ inode->i_data.a_ops = &cifs_addr_ops;
15467+ } else if (S_ISDIR(inode->i_mode)) {
15468+ cFYI(1, (" Directory inode "));
15469+ inode->i_op = &cifs_dir_inode_ops;
15470+ inode->i_fop = &cifs_dir_ops;
15471+ } else if (S_ISLNK(inode->i_mode)) {
15472+ cFYI(1, (" Symbolic Link inode "));
15473+ inode->i_op = &cifs_symlink_inode_ops;
15474+ } else {
15475+ init_special_inode(inode, inode->i_mode,
15476+ kdev_t_to_nr(inode->i_rdev));
15477+ }
15478+ }
15479+ if(buf)
15480+ kfree(buf);
15481+ return rc;
15482+}
15483+
15484+void
15485+cifs_read_inode(struct inode *inode)
15486+{ /* gets root inode */
15487+ int xid;
15488+ struct cifs_sb_info *cifs_sb;
15489+ struct cifsInodeInfo *cifs_inode;
15490+
15491+ cifs_sb = CIFS_SB(inode->i_sb);
15492+ xid = GetXid();
15493+
15494+ cifs_inode = CIFS_I(inode);
15495+ cifs_inode->cifsAttrs = ATTR_DIRECTORY;
15496+ atomic_set(&cifs_inode->inUse, 0);
15497+ cifs_inode->time = 0;
15498+ inode->i_blksize = CIFS_MAX_MSGSIZE;
15499+ inode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
15500+
15501+ INIT_LIST_HEAD(&cifs_inode->openFileList);
15502+
15503+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
15504+ cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
15505+ else
15506+ cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
15507+ /* can not call macro FreeXid here since in a void func */
15508+ _FreeXid(xid);
15509+}
15510+
15511+int
15512+cifs_unlink(struct inode *inode, struct dentry *direntry)
15513+{
15514+ int rc = 0;
15515+ int xid;
15516+ struct cifs_sb_info *cifs_sb;
15517+ struct cifsTconInfo *pTcon;
15518+ char *full_path = NULL;
15519+ struct cifsInodeInfo *cifsInode;
15520+ FILE_BASIC_INFO * pinfo_buf;
15521+
15522+ cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
15523+
15524+ xid = GetXid();
15525+
15526+ cifs_sb = CIFS_SB(inode->i_sb);
15527+ pTcon = cifs_sb->tcon;
15528+
15529+/* Unlink can be called from rename so we can not grab
15530+ the sem here since we deadlock otherwise */
15531+/* down(&direntry->d_sb->s_vfs_rename_sem);*/
15532+ full_path = build_path_from_dentry(direntry);
15533+/* up(&direntry->d_sb->s_vfs_rename_sem);*/
15534+ if(full_path == NULL) {
15535+ FreeXid(xid);
15536+ return -ENOMEM;
15537+ }
15538+ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
15539+
15540+ if (!rc) {
15541+ direntry->d_inode->i_nlink--;
15542+ } else if (rc == -ENOENT) {
15543+ d_drop(direntry);
15544+ } else if (rc == -ETXTBSY) {
15545+ int oplock = FALSE;
15546+ __u16 netfid;
15547+
15548+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
15549+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
15550+ &netfid, &oplock, NULL, cifs_sb->local_nls);
15551+ if(rc==0) {
15552+ CIFSSMBRenameOpenFile(xid,pTcon,netfid,
15553+ NULL, cifs_sb->local_nls);
15554+ CIFSSMBClose(xid, pTcon, netfid);
15555+ direntry->d_inode->i_nlink--;
15556+ }
15557+ } else if (rc == -EACCES) {
15558+ /* try only if r/o attribute set in local lookup data? */
15559+ pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
15560+ if(pinfo_buf) {
15561+ memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
15562+ /* ATTRS set to normal clears r/o bit */
15563+ pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
15564+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
15565+ cifs_sb->local_nls);
15566+ kfree(pinfo_buf);
15567+ }
15568+ if(rc==0) {
15569+ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
15570+ if (!rc) {
15571+ direntry->d_inode->i_nlink--;
15572+ } else if (rc == -ETXTBSY) {
15573+ int oplock = FALSE;
15574+ __u16 netfid;
15575+
15576+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
15577+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
15578+ &netfid, &oplock, NULL, cifs_sb->local_nls);
15579+ if(rc==0) {
15580+ CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
15581+ CIFSSMBClose(xid, pTcon, netfid);
15582+ direntry->d_inode->i_nlink--;
15583+ }
15584+ /* BB if rc = -ETXTBUSY goto the rename logic BB */
15585+ }
15586+ }
15587+ }
15588+ cifsInode = CIFS_I(direntry->d_inode);
15589+ cifsInode->time = 0; /* will force revalidate to get info when needed */
15590+ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
15591+ CURRENT_TIME;
15592+ cifsInode = CIFS_I(inode);
15593+ cifsInode->time = 0; /* force revalidate of dir as well */
15594+
15595+ if (full_path)
15596+ kfree(full_path);
15597+ FreeXid(xid);
15598+ return rc;
15599+}
15600+
15601+int
15602+cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
15603+{
15604+ int rc = 0;
15605+ int xid;
15606+ struct cifs_sb_info *cifs_sb;
15607+ struct cifsTconInfo *pTcon;
15608+ char *full_path = NULL;
15609+ struct inode *newinode = NULL;
15610+
15611+ cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
15612+
15613+ xid = GetXid();
15614+
15615+ cifs_sb = CIFS_SB(inode->i_sb);
15616+ pTcon = cifs_sb->tcon;
15617+
15618+ down(&inode->i_sb->s_vfs_rename_sem);
15619+ full_path = build_path_from_dentry(direntry);
15620+ up(&inode->i_sb->s_vfs_rename_sem);
15621+ if(full_path == NULL) {
15622+ FreeXid(xid);
15623+ return -ENOMEM;
15624+ }
15625+ /* BB add setting the equivalent of mode via CreateX w/ACLs */
15626+ rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
15627+ if (rc) {
15628+ cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
15629+ d_drop(direntry);
15630+ } else {
15631+ inode->i_nlink++;
15632+ if (pTcon->ses->capabilities & CAP_UNIX)
15633+ rc = cifs_get_inode_info_unix(&newinode, full_path,
15634+ inode->i_sb,xid);
15635+ else
15636+ rc = cifs_get_inode_info(&newinode, full_path,NULL,
15637+ inode->i_sb,xid);
15638+
15639+ direntry->d_op = &cifs_dentry_ops;
15640+ d_instantiate(direntry, newinode);
15641+ if(direntry->d_inode)
15642+ direntry->d_inode->i_nlink = 2;
15643+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
15644+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
15645+ (__u64)-1,
15646+ (__u64)-1,
15647+ 0 /* dev_t */,
15648+ cifs_sb->local_nls);
15649+ else { /* BB to be implemented via Windows secrty descriptors*/
15650+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
15651+ }
15652+ }
15653+ if (full_path)
15654+ kfree(full_path);
15655+ FreeXid(xid);
15656+
15657+ return rc;
15658+}
15659+
15660+int
15661+cifs_rmdir(struct inode *inode, struct dentry *direntry)
15662+{
15663+ int rc = 0;
15664+ int xid;
15665+ struct cifs_sb_info *cifs_sb;
15666+ struct cifsTconInfo *pTcon;
15667+ char *full_path = NULL;
15668+ struct cifsInodeInfo *cifsInode;
15669+
15670+ cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
15671+
15672+ xid = GetXid();
15673+
15674+ cifs_sb = CIFS_SB(inode->i_sb);
15675+ pTcon = cifs_sb->tcon;
15676+
15677+ down(&inode->i_sb->s_vfs_rename_sem);
15678+ full_path = build_path_from_dentry(direntry);
15679+ up(&inode->i_sb->s_vfs_rename_sem);
15680+ if(full_path == NULL) {
15681+ FreeXid(xid);
15682+ return -ENOMEM;
15683+ }
15684+
15685+ rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
15686+
15687+ if (!rc) {
15688+ inode->i_nlink--;
15689+ direntry->d_inode->i_size = 0;
15690+ direntry->d_inode->i_nlink = 0;
15691+ }
15692+
15693+ cifsInode = CIFS_I(direntry->d_inode);
15694+ cifsInode->time = 0; /* force revalidate to go get info when needed */
15695+ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
15696+ CURRENT_TIME;
15697+
15698+ if (full_path)
15699+ kfree(full_path);
15700+ FreeXid(xid);
15701+ return rc;
15702+}
15703+
15704+int
15705+cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
15706+ struct inode *target_inode, struct dentry *target_direntry)
15707+{
15708+ char *fromName;
15709+ char *toName;
15710+ struct cifs_sb_info *cifs_sb_source;
15711+ struct cifs_sb_info *cifs_sb_target;
15712+ struct cifsTconInfo *pTcon;
15713+ int xid;
15714+ int rc = 0;
15715+
15716+ xid = GetXid();
15717+
15718+ cifs_sb_target = CIFS_SB(target_inode->i_sb);
15719+ cifs_sb_source = CIFS_SB(source_inode->i_sb);
15720+ pTcon = cifs_sb_source->tcon;
15721+
15722+ if (pTcon != cifs_sb_target->tcon) {
15723+ FreeXid(xid);
15724+ return -EXDEV; /* BB actually could be allowed if same server, but
15725+ different share. Might eventually add support for this */
15726+ }
15727+
15728+ /* we already have the rename sem so we do not need
15729+ to grab it again here to protect the path integrity */
15730+ fromName = build_path_from_dentry(source_direntry);
15731+ toName = build_path_from_dentry(target_direntry);
15732+ if((fromName == NULL) || (toName == NULL)) {
15733+ rc = -ENOMEM;
15734+ goto cifs_rename_exit;
15735+ }
15736+
15737+ rc = CIFSSMBRename(xid, pTcon, fromName, toName,
15738+ cifs_sb_source->local_nls);
15739+ if(rc == -EEXIST) {
15740+ /* check if they are the same file
15741+ because rename of hardlinked files is a noop */
15742+ FILE_UNIX_BASIC_INFO * info_buf_source;
15743+ FILE_UNIX_BASIC_INFO * info_buf_target;
15744+
15745+ info_buf_source =
15746+ kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
15747+ if(info_buf_source != NULL) {
15748+ info_buf_target = info_buf_source+1;
15749+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
15750+ info_buf_source, cifs_sb_source->local_nls);
15751+ if(rc == 0) {
15752+ rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
15753+ info_buf_target,
15754+ cifs_sb_target->local_nls);
15755+ }
15756+ if((rc == 0) &&
15757+ (info_buf_source->UniqueId ==
15758+ info_buf_target->UniqueId)) {
15759+ /* do not rename since the files are hardlinked
15760+ which is a noop */
15761+ } else {
15762+ /* we either can not tell the files are hardlinked
15763+ (as with Windows servers) or files are not hardlinked
15764+ so delete the target manually before renaming to
15765+ follow POSIX rather than Windows semantics */
15766+ cifs_unlink(target_inode, target_direntry);
15767+ rc = CIFSSMBRename(xid, pTcon, fromName, toName,
15768+ cifs_sb_source->local_nls);
15769+ }
15770+ kfree(info_buf_source);
15771+ } /* if we can not get memory just leave rc as EEXIST */
15772+ }
15773+
15774+ if((rc == -EIO)||(rc == -EEXIST)) {
15775+ int oplock = FALSE;
15776+ __u16 netfid;
15777+
15778+ rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
15779+ CREATE_NOT_DIR,
15780+ &netfid, &oplock, NULL, cifs_sb_source->local_nls);
15781+ if(rc==0) {
15782+ CIFSSMBRenameOpenFile(xid,pTcon,netfid,
15783+ toName, cifs_sb_source->local_nls);
15784+ CIFSSMBClose(xid, pTcon, netfid);
15785+ }
15786+ }
15787+
15788+cifs_rename_exit:
15789+ if (fromName)
15790+ kfree(fromName);
15791+ if (toName)
15792+ kfree(toName);
15793+
15794+ FreeXid(xid);
15795+ return rc;
15796+}
15797+
15798+int
15799+cifs_revalidate(struct dentry *direntry)
15800+{
15801+ int xid;
15802+ int rc = 0;
15803+ char *full_path;
15804+ struct cifs_sb_info *cifs_sb;
15805+ struct cifsInodeInfo *cifsInode;
15806+ loff_t local_size;
15807+ time_t local_mtime;
15808+ int invalidate_inode = FALSE;
15809+
15810+ if(direntry->d_inode == NULL)
15811+ return -ENOENT;
15812+
15813+ cifsInode = CIFS_I(direntry->d_inode);
15814+
15815+ if(cifsInode == NULL)
15816+ return -ENOENT;
15817+
15818+ /* no sense revalidating inode info on file that no one can write */
15819+ if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
15820+ return rc;
15821+
15822+ xid = GetXid();
15823+
15824+ cifs_sb = CIFS_SB(direntry->d_sb);
15825+
15826+ /* can not safely grab the rename sem here if
15827+ rename calls revalidate since that would deadlock */
15828+ full_path = build_path_from_dentry(direntry);
15829+ if(full_path == NULL) {
15830+ FreeXid(xid);
15831+ return -ENOMEM;
15832+ }
15833+ cFYI(1,
15834+ ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
15835+ full_path, direntry->d_inode,
15836+ direntry->d_inode->i_count.counter, direntry,
15837+ direntry->d_time, jiffies));
15838+
15839+ if (cifsInode->time == 0){
15840+ /* was set to zero previously to force revalidate */
15841+ } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
15842+ if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
15843+ (direntry->d_inode->i_nlink == 1)) {
15844+ if (full_path)
15845+ kfree(full_path);
15846+ FreeXid(xid);
15847+ return rc;
15848+ } else {
15849+ cFYI(1,("Have to revalidate file due to hardlinks"));
15850+ }
15851+ }
15852+
15853+ /* save mtime and size */
15854+ local_mtime = direntry->d_inode->i_mtime;
15855+ local_size = direntry->d_inode->i_size;
15856+
15857+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
15858+ rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
15859+ direntry->d_sb,xid);
15860+ if(rc) {
15861+ cFYI(1,("error on getting revalidate info %d",rc));
15862+/* if(rc != -ENOENT)
15863+ rc = 0; */ /* BB should we cache info on certain errors? */
15864+ }
15865+ } else {
15866+ rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
15867+ direntry->d_sb,xid);
15868+ if(rc) {
15869+ cFYI(1,("error on getting revalidate info %d",rc));
15870+/* if(rc != -ENOENT)
15871+ rc = 0; */ /* BB should we cache info on certain errors? */
15872+ }
15873+ }
15874+ /* should we remap certain errors, access denied?, to zero */
15875+
15876+ /* if not oplocked, we invalidate inode pages if mtime
15877+ or file size had changed on server */
15878+
15879+ if((local_mtime == direntry->d_inode->i_mtime) &&
15880+ (local_size == direntry->d_inode->i_size)) {
15881+ cFYI(1,("cifs_revalidate - inode unchanged"));
15882+ } else {
15883+ /* file may have changed on server */
15884+ if(cifsInode->clientCanCacheRead) {
15885+ /* no need to invalidate inode pages since we were
15886+ the only ones who could have modified the file and
15887+ the server copy is staler than ours */
15888+ } else {
15889+ invalidate_inode = TRUE;
15890+ }
15891+ }
15892+
15893+ /* can not grab this sem since kernel filesys locking
15894+ documentation indicates i_sem may be taken by the kernel
15895+ on lookup and rename which could deadlock if we grab
15896+ the i_sem here as well */
15897+/* down(&direntry->d_inode->i_sem);*/
15898+ /* need to write out dirty pages here */
15899+ if(direntry->d_inode->i_mapping) {
15900+ /* do we need to lock inode until after invalidate completes below? */
15901+ filemap_fdatasync(direntry->d_inode->i_mapping);
15902+ }
15903+ if(invalidate_inode) {
15904+ filemap_fdatawait(direntry->d_inode->i_mapping);
15905+ /* may eventually have to do this for open files too */
15906+ if(list_empty(&(cifsInode->openFileList))) {
15907+ /* Has changed on server - flush read ahead pages */
15908+ cFYI(1,("Invalidating read ahead data on closed file"));
15909+ invalidate_inode_pages(direntry->d_inode);
15910+ }
15911+ }
15912+/* up(&direntry->d_inode->i_sem);*/
15913+
15914+ if (full_path)
15915+ kfree(full_path);
15916+ FreeXid(xid);
15917+
15918+ return rc;
15919+}
15920+
15921+/* int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
15922+{
15923+ int err = cifs_revalidate(dentry);
15924+ if (!err)
15925+ generic_fillattr(dentry->d_inode, stat);
15926+ return err;
15927+} */
15928+
15929+void
15930+cifs_truncate_file(struct inode *inode)
15931+{ /* BB remove - may not need this function after all BB */
15932+ int xid;
15933+ int rc = -EIO;
15934+ int found = FALSE;
15935+ struct cifsFileInfo *open_file = NULL;
15936+ struct cifs_sb_info *cifs_sb;
15937+ struct cifsTconInfo *pTcon;
15938+ struct cifsInodeInfo *cifsInode;
15939+ struct dentry *dirent;
15940+ struct list_head * tmp;
15941+ char *full_path = NULL;
15942+
15943+ xid = GetXid();
15944+
15945+ cifs_sb = CIFS_SB(inode->i_sb);
15946+ pTcon = cifs_sb->tcon;
15947+
15948+ /* To avoid spurious oplock breaks from server, in the case
15949+ of inodes that we already have open, avoid doing path
15950+ based setting of file size if we can do it by handle.
15951+ This keeps our caching token (oplock) and avoids
15952+ timeouts when the local oplock break takes longer to flush
15953+ writebehind data than the SMB timeout for the SetPathInfo
15954+ request would allow */
15955+ read_lock(&GlobalSMBSeslock);
15956+ cifsInode = CIFS_I(inode);
15957+ list_for_each(tmp, &cifsInode->openFileList) {
15958+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
15959+ /* We check if file is open for writing first */
15960+ if((open_file->pfile) && (!open_file->invalidHandle) &&
15961+ ((open_file->pfile->f_flags & O_RDWR) ||
15962+ (open_file->pfile->f_flags & O_WRONLY))) {
15963+ read_unlock(&GlobalSMBSeslock);
15964+ found = TRUE;
15965+ rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
15966+ open_file->netfid,open_file->pid,FALSE);
15967+ if(rc == 0) {
15968+ FreeXid(xid);
15969+ return;
15970+ }
15971+ /* Do not need reopen and retry on EAGAIN since we will
15972+ retry by pathname below */
15973+ if(rc == -EAGAIN)
15974+ rc = -EHOSTDOWN;
15975+
15976+ break; /* now that we found one valid file handle no
15977+ sense continuing to loop trying others */
15978+ }
15979+ }
15980+ if(found == FALSE)
15981+ read_unlock(&GlobalSMBSeslock);
15982+
15983+ if (list_empty(&inode->i_dentry)) {
15984+ cERROR(1,
15985+ ("Can not get pathname from empty dentry in inode 0x%p ",
15986+ inode));
15987+ FreeXid(xid);
15988+ return;
15989+ }
15990+
15991+ dirent = list_entry(inode->i_dentry.next, struct dentry, d_alias);
15992+ if (dirent) {
15993+ full_path = build_path_from_dentry(dirent);
15994+ rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
15995+ cifs_sb->local_nls);
15996+ cFYI(1,(" SetEOF (truncate) rc = %d",rc));
15997+ if (!rc)
15998+ CIFSSMBSetEOF(xid,pTcon,full_path,inode->i_size,TRUE,cifs_sb->local_nls);
15999+ /* allocation size setting seems optional so ignore return code */
16000+ }
16001+ if (full_path)
16002+ kfree(full_path);
16003+ FreeXid(xid);
16004+ return;
16005+}
16006+
16007+static int cifs_truncate_page(struct address_space *mapping, loff_t from)
16008+{
16009+ unsigned long index = from >> PAGE_CACHE_SHIFT;
16010+ unsigned offset = from & (PAGE_CACHE_SIZE-1);
16011+ struct page *page;
16012+ char *kaddr;
16013+ int rc = 0;
16014+
16015+ page = grab_cache_page(mapping, index);
16016+ if (!page)
16017+ return -ENOMEM;
16018+
16019+ kaddr = kmap_atomic(page, KM_USER0);
16020+ memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
16021+ flush_dcache_page(page);
16022+ kunmap_atomic(kaddr, KM_USER0);
16023+ unlock_page(page);
16024+ page_cache_release(page);
16025+ return rc;
16026+}
16027+
16028+int
16029+cifs_setattr(struct dentry *direntry, struct iattr *attrs)
16030+{
16031+ int xid;
16032+ struct cifs_sb_info *cifs_sb;
16033+ struct cifsTconInfo *pTcon;
16034+ char *full_path = NULL;
16035+ int rc = -EACCES;
16036+ int found = FALSE;
16037+ struct cifsFileInfo *open_file = NULL;
16038+ FILE_BASIC_INFO time_buf;
16039+ int set_time = FALSE;
16040+ __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
16041+ __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
16042+ __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
16043+ struct cifsInodeInfo *cifsInode;
16044+ struct list_head * tmp;
16045+
16046+ xid = GetXid();
16047+
16048+ cFYI(1,
16049+ (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
16050+ direntry->d_name.name, attrs->ia_valid));
16051+ cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
16052+ pTcon = cifs_sb->tcon;
16053+
16054+ down(&direntry->d_sb->s_vfs_rename_sem);
16055+ full_path = build_path_from_dentry(direntry);
16056+ up(&direntry->d_sb->s_vfs_rename_sem);
16057+ if(full_path == NULL) {
16058+ FreeXid(xid);
16059+ return -ENOMEM;
16060+ }
16061+ cifsInode = CIFS_I(direntry->d_inode);
16062+
16063+ /* BB check if we need to refresh inode from server now ? BB */
16064+
16065+ /* need to flush data before changing file size on server */
16066+ filemap_fdatasync(direntry->d_inode->i_mapping);
16067+
16068+ if (attrs->ia_valid & ATTR_SIZE) {
16069+ read_lock(&GlobalSMBSeslock);
16070+ /* To avoid spurious oplock breaks from server, in the case
16071+ of inodes that we already have open, avoid doing path
16072+ based setting of file size if we can do it by handle.
16073+ This keeps our caching token (oplock) and avoids
16074+ timeouts when the local oplock break takes longer to flush
16075+ writebehind data than the SMB timeout for the SetPathInfo
16076+ request would allow */
16077+ list_for_each(tmp, &cifsInode->openFileList) {
16078+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
16079+ /* We check if file is open for writing first */
16080+ if((open_file->pfile) &&
16081+ ((open_file->pfile->f_flags & O_RDWR) ||
16082+ (open_file->pfile->f_flags & O_WRONLY))) {
16083+ if(open_file->invalidHandle == FALSE) {
16084+ /* we found a valid, writeable network file
16085+ handle to use to try to set the file size */
16086+ __u16 nfid = open_file->netfid;
16087+ __u32 npid = open_file->pid;
16088+ read_unlock(&GlobalSMBSeslock);
16089+ found = TRUE;
16090+ rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
16091+ nfid,npid,FALSE);
16092+ cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
16093+ /* Do not need reopen and retry on EAGAIN since we will
16094+ retry by pathname below */
16095+
16096+ break; /* now that we found one valid file handle no
16097+ sense continuing to loop trying others */
16098+ }
16099+ }
16100+ }
16101+ if(found == FALSE) {
16102+ read_unlock(&GlobalSMBSeslock);
16103+ }
16104+
16105+
16106+ if(rc != 0) {
16107+ /* Set file size by pathname rather than by handle either
16108+ because no valid, writeable file handle for it was found or
16109+ because there was an error setting it by handle */
16110+ rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
16111+ cifs_sb->local_nls);
16112+ cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
16113+ }
16114+
16115+ /* Server is ok setting allocation size implicitly - no need to call: */
16116+ /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
16117+
16118+ if (rc == 0) {
16119+ rc = vmtruncate(direntry->d_inode, attrs->ia_size);
16120+ cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
16121+ }
16122+ }
16123+ if (attrs->ia_valid & ATTR_UID) {
16124+ cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
16125+ uid = attrs->ia_uid;
16126+ /* entry->uid = cpu_to_le16(attr->ia_uid); */
16127+ }
16128+ if (attrs->ia_valid & ATTR_GID) {
16129+ cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
16130+ gid = attrs->ia_gid;
16131+ /* entry->gid = cpu_to_le16(attr->ia_gid); */
16132+ }
16133+
16134+ time_buf.Attributes = 0;
16135+ if (attrs->ia_valid & ATTR_MODE) {
16136+ cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
16137+ mode = attrs->ia_mode;
16138+ /* entry->mode = cpu_to_le16(attr->ia_mode); */
16139+ }
16140+
16141+ if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16142+ && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
16143+ rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
16144+ 0 /* dev_t */, cifs_sb->local_nls);
16145+ else if (attrs->ia_valid & ATTR_MODE) {
16146+ if((mode & S_IWUGO) == 0) /* not writeable */ {
16147+ if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
16148+ time_buf.Attributes =
16149+ cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
16150+ } else if((mode & S_IWUGO) == S_IWUGO) {
16151+ if(cifsInode->cifsAttrs & ATTR_READONLY)
16152+ time_buf.Attributes =
16153+ cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
16154+ }
16155+ /* BB to be implemented - via Windows security descriptors or streams */
16156+ /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
16157+ }
16158+
16159+ if (attrs->ia_valid & ATTR_ATIME) {
16160+ set_time = TRUE;
16161+ time_buf.LastAccessTime =
16162+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
16163+ } else
16164+ time_buf.LastAccessTime = 0;
16165+
16166+ if (attrs->ia_valid & ATTR_MTIME) {
16167+ set_time = TRUE;
16168+ time_buf.LastWriteTime =
16169+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
16170+ } else
16171+ time_buf.LastWriteTime = 0;
16172+
16173+ if (attrs->ia_valid & ATTR_CTIME) {
16174+ set_time = TRUE;
16175+ time_buf.ChangeTime =
16176+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
16177+ } else
16178+ time_buf.ChangeTime = 0;
16179+
16180+ if (set_time | time_buf.Attributes) {
16181+ /* BB what if setting one attribute fails
16182+ (such as size) but time setting works */
16183+ time_buf.CreationTime = 0; /* do not change */
16184+ /* In the future we should experiment - try setting timestamps
16185+ via Handle (SetFileInfo) instead of by path */
16186+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
16187+ cifs_sb->local_nls);
16188+ }
16189+
16190+ /* do not need local check to inode_check_ok since the server does that */
16191+ if (!rc)
16192+ rc = inode_setattr(direntry->d_inode, attrs);
16193+ if (full_path)
16194+ kfree(full_path);
16195+ FreeXid(xid);
16196+ return rc;
16197+}
16198+
16199+void
16200+cifs_delete_inode(struct inode *inode)
16201+{
16202+ cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
16203+ /* may have to add back in if and when safe distributed caching of
16204+ directories added e.g. via FindNotify */
16205+}
16206--- /dev/null
16207+++ b/fs/cifs/link.c
16208@@ -0,0 +1,328 @@
16209+/*
16210+ * fs/cifs/link.c
16211+ *
16212+ * Copyright (C) International Business Machines Corp., 2002,2003
16213+ * Author(s): Steve French (sfrench@us.ibm.com)
16214+ *
16215+ * This library is free software; you can redistribute it and/or modify
16216+ * it under the terms of the GNU Lesser General Public License as published
16217+ * by the Free Software Foundation; either version 2.1 of the License, or
16218+ * (at your option) any later version.
16219+ *
16220+ * This library is distributed in the hope that it will be useful,
16221+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16222+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16223+ * the GNU Lesser General Public License for more details.
16224+ *
16225+ * You should have received a copy of the GNU Lesser General Public License
16226+ * along with this library; if not, write to the Free Software
16227+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16228+ */
16229+#include <linux/fs.h>
16230+#include <linux/stat.h>
16231+#include "cifsfs.h"
16232+#include "cifspdu.h"
16233+#include "cifsglob.h"
16234+#include "cifsproto.h"
16235+#include "cifs_debug.h"
16236+#include "cifs_fs_sb.h"
16237+
16238+int
16239+cifs_hardlink(struct dentry *old_file, struct inode *inode,
16240+ struct dentry *direntry)
16241+{
16242+ int rc = -EACCES;
16243+ int xid;
16244+ char *fromName = NULL;
16245+ char *toName = NULL;
16246+ struct cifs_sb_info *cifs_sb_target;
16247+ struct cifsTconInfo *pTcon;
16248+ struct cifsInodeInfo *cifsInode;
16249+
16250+ xid = GetXid();
16251+
16252+ cifs_sb_target = CIFS_SB(inode->i_sb);
16253+ pTcon = cifs_sb_target->tcon;
16254+
16255+/* No need to check for cross device links since server will do that
16256+ BB note DFS case in future though (when we may have to check) */
16257+
16258+ down(&inode->i_sb->s_vfs_rename_sem);
16259+ fromName = build_path_from_dentry(old_file);
16260+ toName = build_path_from_dentry(direntry);
16261+ up(&inode->i_sb->s_vfs_rename_sem);
16262+ if((fromName == NULL) || (toName == NULL)) {
16263+ rc = -ENOMEM;
16264+ goto cifs_hl_exit;
16265+ }
16266+
16267+ if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
16268+ rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
16269+ cifs_sb_target->local_nls);
16270+ else {
16271+ rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
16272+ cifs_sb_target->local_nls);
16273+ if(rc == -EIO)
16274+ rc = -EOPNOTSUPP;
16275+ }
16276+
16277+/* if (!rc) */
16278+ {
16279+ /* renew_parental_timestamps(old_file);
16280+ inode->i_nlink++;
16281+ mark_inode_dirty(inode);
16282+ d_instantiate(direntry, inode); */
16283+ /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
16284+ }
16285+ d_drop(direntry); /* force new lookup from server */
16286+ cifsInode = CIFS_I(old_file->d_inode);
16287+ cifsInode->time = 0; /* will force revalidate to go get info when needed */
16288+
16289+cifs_hl_exit:
16290+ if (fromName)
16291+ kfree(fromName);
16292+ if (toName)
16293+ kfree(toName);
16294+ FreeXid(xid);
16295+ return rc;
16296+}
16297+
16298+int
16299+cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
16300+{
16301+ struct inode *inode = direntry->d_inode;
16302+ int rc = -EACCES;
16303+ int xid;
16304+ char *full_path = NULL;
16305+ char * target_path;
16306+ struct cifs_sb_info *cifs_sb;
16307+ struct cifsTconInfo *pTcon;
16308+
16309+ xid = GetXid();
16310+
16311+ down(&direntry->d_sb->s_vfs_rename_sem);
16312+ full_path = build_path_from_dentry(direntry);
16313+ up(&direntry->d_sb->s_vfs_rename_sem);
16314+
16315+ if(full_path == NULL) {
16316+ FreeXid(xid);
16317+ return -ENOMEM;
16318+ }
16319+ cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
16320+ cifs_sb = CIFS_SB(inode->i_sb);
16321+ pTcon = cifs_sb->tcon;
16322+ target_path = kmalloc(PATH_MAX, GFP_KERNEL);
16323+ if(target_path == NULL) {
16324+ if (full_path)
16325+ kfree(full_path);
16326+ FreeXid(xid);
16327+ return -ENOMEM;
16328+ }
16329+ /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
16330+ /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
16331+
16332+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
16333+ if (pTcon->ses->capabilities & CAP_UNIX)
16334+ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
16335+ target_path,
16336+ PATH_MAX-1,
16337+ cifs_sb->local_nls);
16338+ else {
16339+ /* rc = CIFSSMBQueryReparseLinkInfo */
16340+ /* BB Add code to Query ReparsePoint info */
16341+ }
16342+ /* BB Anything else to do to handle recursive links? */
16343+ /* BB Should we be using page symlink ops here? */
16344+
16345+ if (rc == 0) {
16346+
16347+/* BB Add special case check for Samba DFS symlinks */
16348+
16349+ target_path[PATH_MAX-1] = 0;
16350+ rc = vfs_follow_link(nd, target_path);
16351+ }
16352+ /* else EACCESS */
16353+
16354+ if (target_path)
16355+ kfree(target_path);
16356+ if (full_path)
16357+ kfree(full_path);
16358+ FreeXid(xid);
16359+ return rc;
16360+}
16361+
16362+int
16363+cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
16364+{
16365+ int rc = -EOPNOTSUPP;
16366+ int xid;
16367+ struct cifs_sb_info *cifs_sb;
16368+ struct cifsTconInfo *pTcon;
16369+ char *full_path = NULL;
16370+ struct inode *newinode = NULL;
16371+
16372+ xid = GetXid();
16373+
16374+ cifs_sb = CIFS_SB(inode->i_sb);
16375+ pTcon = cifs_sb->tcon;
16376+
16377+ down(&inode->i_sb->s_vfs_rename_sem);
16378+ full_path = build_path_from_dentry(direntry);
16379+ up(&inode->i_sb->s_vfs_rename_sem);
16380+
16381+ if(full_path == NULL) {
16382+ FreeXid(xid);
16383+ return -ENOMEM;
16384+ }
16385+
16386+ cFYI(1, ("Full path: %s ", full_path));
16387+ cFYI(1, ("symname is %s", symname));
16388+
16389+ /* BB what if DFS and this volume is on different share? BB */
16390+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16391+ rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
16392+ cifs_sb->local_nls);
16393+ /* else
16394+ rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
16395+
16396+ if (rc == 0) {
16397+ if (pTcon->ses->capabilities & CAP_UNIX)
16398+ rc = cifs_get_inode_info_unix(&newinode, full_path,
16399+ inode->i_sb,xid);
16400+ else
16401+ rc = cifs_get_inode_info(&newinode, full_path, NULL,
16402+ inode->i_sb,xid);
16403+
16404+ if (rc != 0) {
16405+ cFYI(1,
16406+ ("Create symlink worked but get_inode_info failed with rc = %d ",
16407+ rc));
16408+ } else {
16409+ direntry->d_op = &cifs_dentry_ops;
16410+ d_instantiate(direntry, newinode);
16411+ }
16412+ }
16413+
16414+ if (full_path)
16415+ kfree(full_path);
16416+ FreeXid(xid);
16417+ return rc;
16418+}
16419+
16420+int
16421+cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
16422+{
16423+ struct inode *inode = direntry->d_inode;
16424+ int rc = -EACCES;
16425+ int xid;
16426+ int oplock = FALSE;
16427+ struct cifs_sb_info *cifs_sb;
16428+ struct cifsTconInfo *pTcon;
16429+ char *full_path = NULL;
16430+ char *tmp_path = NULL;
16431+ char * tmpbuffer;
16432+ unsigned char * referrals = NULL;
16433+ int num_referrals = 0;
16434+ int len;
16435+ __u16 fid;
16436+
16437+ xid = GetXid();
16438+ cifs_sb = CIFS_SB(inode->i_sb);
16439+ pTcon = cifs_sb->tcon;
16440+
16441+/* BB would it be safe against deadlock to grab this sem
16442+ even though rename itself grabs the sem and calls lookup? */
16443+/* down(&inode->i_sb->s_vfs_rename_sem);*/
16444+ full_path = build_path_from_dentry(direntry);
16445+/* up(&inode->i_sb->s_vfs_rename_sem);*/
16446+
16447+ if(full_path == NULL) {
16448+ FreeXid(xid);
16449+ return -ENOMEM;
16450+ }
16451+
16452+ cFYI(1,
16453+ ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
16454+ full_path, inode, pBuffer, buflen));
16455+ if(buflen > PATH_MAX)
16456+ len = PATH_MAX;
16457+ else
16458+ len = buflen;
16459+ tmpbuffer = kmalloc(len,GFP_KERNEL);
16460+ if(tmpbuffer == NULL) {
16461+ if (full_path)
16462+ kfree(full_path);
16463+ FreeXid(xid);
16464+ return -ENOMEM;
16465+ }
16466+
16467+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
16468+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16469+ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
16470+ tmpbuffer,
16471+ len - 1,
16472+ cifs_sb->local_nls);
16473+ else {
16474+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
16475+ OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
16476+ if(!rc) {
16477+ rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
16478+ tmpbuffer,
16479+ len - 1,
16480+ fid,
16481+ cifs_sb->local_nls);
16482+ if(CIFSSMBClose(xid, pTcon, fid)) {
16483+ cFYI(1,("Error closing junction point (open for ioctl)"));
16484+ }
16485+ if(rc == -EIO) {
16486+ /* Query if DFS Junction */
16487+ tmp_path =
16488+ kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
16489+ GFP_KERNEL);
16490+ if (tmp_path) {
16491+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
16492+ strncat(tmp_path, full_path, MAX_PATHCONF);
16493+ rc = get_dfs_path(xid, pTcon->ses, tmp_path,
16494+ cifs_sb->local_nls, &num_referrals, &referrals);
16495+ cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
16496+ if((num_referrals == 0) && (rc == 0))
16497+ rc = -EACCES;
16498+ else {
16499+ cFYI(1,("num referral: %d",num_referrals));
16500+ if(referrals) {
16501+ cFYI(1,("referral string: %s ",referrals));
16502+ strncpy(tmpbuffer, referrals, len-1);
16503+ }
16504+ }
16505+ if(referrals)
16506+ kfree(referrals);
16507+ kfree(tmp_path);
16508+ if(referrals) {
16509+ kfree(referrals);
16510+ }
16511+ }
16512+ /* BB add code like else decode referrals then memcpy to
16513+ tmpbuffer and free referrals string array BB */
16514+ }
16515+ }
16516+ }
16517+ /* BB Anything else to do to handle recursive links? */
16518+ /* BB Should we be using page ops here? */
16519+
16520+ /* BB null terminate returned string in pBuffer? BB */
16521+ if (rc == 0) {
16522+ rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
16523+ cFYI(1,
16524+ ("vfs_readlink called from cifs_readlink returned %d",
16525+ rc));
16526+ }
16527+
16528+ if (tmpbuffer) {
16529+ kfree(tmpbuffer);
16530+ }
16531+ if (full_path) {
16532+ kfree(full_path);
16533+ }
16534+ FreeXid(xid);
16535+ return rc;
16536+}
16537--- /dev/null
16538+++ b/fs/cifs/Makefile
16539@@ -0,0 +1,10 @@
16540+#
16541+# Makefile for Linux CIFS VFS client
16542+#
16543+O_TARGET := cifs.o
16544+
16545+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
16546+
16547+obj-m := $(O_TARGET)
16548+
16549+include $(TOPDIR)/Rules.make
16550--- /dev/null
16551+++ b/fs/cifs/md4.c
16552@@ -0,0 +1,203 @@
16553+/*
16554+ Unix SMB/Netbios implementation.
16555+ Version 1.9.
16556+ a implementation of MD4 designed for use in the SMB authentication protocol
16557+ Copyright (C) Andrew Tridgell 1997-1998.
16558+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
16559+
16560+ This program is free software; you can redistribute it and/or modify
16561+ it under the terms of the GNU General Public License as published by
16562+ the Free Software Foundation; either version 2 of the License, or
16563+ (at your option) any later version.
16564+
16565+ This program is distributed in the hope that it will be useful,
16566+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16567+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16568+ GNU General Public License for more details.
16569+
16570+ You should have received a copy of the GNU General Public License
16571+ along with this program; if not, write to the Free Software
16572+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16573+*/
16574+#include <linux/module.h>
16575+#include <linux/fs.h>
16576+/* NOTE: This code makes no attempt to be fast! */
16577+
16578+static __u32
16579+F(__u32 X, __u32 Y, __u32 Z)
16580+{
16581+ return (X & Y) | ((~X) & Z);
16582+}
16583+
16584+static __u32
16585+G(__u32 X, __u32 Y, __u32 Z)
16586+{
16587+ return (X & Y) | (X & Z) | (Y & Z);
16588+}
16589+
16590+static __u32
16591+H(__u32 X, __u32 Y, __u32 Z)
16592+{
16593+ return X ^ Y ^ Z;
16594+}
16595+
16596+static __u32
16597+lshift(__u32 x, int s)
16598+{
16599+ x &= 0xFFFFFFFF;
16600+ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
16601+}
16602+
16603+#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
16604+#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
16605+#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
16606+
16607+/* this applies md4 to 64 byte chunks */
16608+static void
16609+mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
16610+{
16611+ int j;
16612+ __u32 AA, BB, CC, DD;
16613+ __u32 X[16];
16614+
16615+
16616+ for (j = 0; j < 16; j++)
16617+ X[j] = M[j];
16618+
16619+ AA = *A;
16620+ BB = *B;
16621+ CC = *C;
16622+ DD = *D;
16623+
16624+ ROUND1(A, B, C, D, 0, 3);
16625+ ROUND1(D, A, B, C, 1, 7);
16626+ ROUND1(C, D, A, B, 2, 11);
16627+ ROUND1(B, C, D, A, 3, 19);
16628+ ROUND1(A, B, C, D, 4, 3);
16629+ ROUND1(D, A, B, C, 5, 7);
16630+ ROUND1(C, D, A, B, 6, 11);
16631+ ROUND1(B, C, D, A, 7, 19);
16632+ ROUND1(A, B, C, D, 8, 3);
16633+ ROUND1(D, A, B, C, 9, 7);
16634+ ROUND1(C, D, A, B, 10, 11);
16635+ ROUND1(B, C, D, A, 11, 19);
16636+ ROUND1(A, B, C, D, 12, 3);
16637+ ROUND1(D, A, B, C, 13, 7);
16638+ ROUND1(C, D, A, B, 14, 11);
16639+ ROUND1(B, C, D, A, 15, 19);
16640+
16641+ ROUND2(A, B, C, D, 0, 3);
16642+ ROUND2(D, A, B, C, 4, 5);
16643+ ROUND2(C, D, A, B, 8, 9);
16644+ ROUND2(B, C, D, A, 12, 13);
16645+ ROUND2(A, B, C, D, 1, 3);
16646+ ROUND2(D, A, B, C, 5, 5);
16647+ ROUND2(C, D, A, B, 9, 9);
16648+ ROUND2(B, C, D, A, 13, 13);
16649+ ROUND2(A, B, C, D, 2, 3);
16650+ ROUND2(D, A, B, C, 6, 5);
16651+ ROUND2(C, D, A, B, 10, 9);
16652+ ROUND2(B, C, D, A, 14, 13);
16653+ ROUND2(A, B, C, D, 3, 3);
16654+ ROUND2(D, A, B, C, 7, 5);
16655+ ROUND2(C, D, A, B, 11, 9);
16656+ ROUND2(B, C, D, A, 15, 13);
16657+
16658+ ROUND3(A, B, C, D, 0, 3);
16659+ ROUND3(D, A, B, C, 8, 9);
16660+ ROUND3(C, D, A, B, 4, 11);
16661+ ROUND3(B, C, D, A, 12, 15);
16662+ ROUND3(A, B, C, D, 2, 3);
16663+ ROUND3(D, A, B, C, 10, 9);
16664+ ROUND3(C, D, A, B, 6, 11);
16665+ ROUND3(B, C, D, A, 14, 15);
16666+ ROUND3(A, B, C, D, 1, 3);
16667+ ROUND3(D, A, B, C, 9, 9);
16668+ ROUND3(C, D, A, B, 5, 11);
16669+ ROUND3(B, C, D, A, 13, 15);
16670+ ROUND3(A, B, C, D, 3, 3);
16671+ ROUND3(D, A, B, C, 11, 9);
16672+ ROUND3(C, D, A, B, 7, 11);
16673+ ROUND3(B, C, D, A, 15, 15);
16674+
16675+ *A += AA;
16676+ *B += BB;
16677+ *C += CC;
16678+ *D += DD;
16679+
16680+ *A &= 0xFFFFFFFF;
16681+ *B &= 0xFFFFFFFF;
16682+ *C &= 0xFFFFFFFF;
16683+ *D &= 0xFFFFFFFF;
16684+
16685+ for (j = 0; j < 16; j++)
16686+ X[j] = 0;
16687+}
16688+
16689+static void
16690+copy64(__u32 * M, unsigned char *in)
16691+{
16692+ int i;
16693+
16694+ for (i = 0; i < 16; i++)
16695+ M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
16696+ (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
16697+}
16698+
16699+static void
16700+copy4(unsigned char *out, __u32 x)
16701+{
16702+ out[0] = x & 0xFF;
16703+ out[1] = (x >> 8) & 0xFF;
16704+ out[2] = (x >> 16) & 0xFF;
16705+ out[3] = (x >> 24) & 0xFF;
16706+}
16707+
16708+/* produce a md4 message digest from data of length n bytes */
16709+void
16710+mdfour(unsigned char *out, unsigned char *in, int n)
16711+{
16712+ unsigned char buf[128];
16713+ __u32 M[16];
16714+ __u32 b = n * 8;
16715+ int i;
16716+ __u32 A = 0x67452301;
16717+ __u32 B = 0xefcdab89;
16718+ __u32 C = 0x98badcfe;
16719+ __u32 D = 0x10325476;
16720+
16721+ while (n > 64) {
16722+ copy64(M, in);
16723+ mdfour64(M,&A,&B, &C, &D);
16724+ in += 64;
16725+ n -= 64;
16726+ }
16727+
16728+ for (i = 0; i < 128; i++)
16729+ buf[i] = 0;
16730+ memcpy(buf, in, n);
16731+ buf[n] = 0x80;
16732+
16733+ if (n <= 55) {
16734+ copy4(buf + 56, b);
16735+ copy64(M, buf);
16736+ mdfour64(M, &A, &B, &C, &D);
16737+ } else {
16738+ copy4(buf + 120, b);
16739+ copy64(M, buf);
16740+ mdfour64(M, &A, &B, &C, &D);
16741+ copy64(M, buf + 64);
16742+ mdfour64(M, &A, &B, &C, &D);
16743+ }
16744+
16745+ for (i = 0; i < 128; i++)
16746+ buf[i] = 0;
16747+ copy64(M, buf);
16748+
16749+ copy4(out, A);
16750+ copy4(out + 4, B);
16751+ copy4(out + 8, C);
16752+ copy4(out + 12, D);
16753+
16754+ A = B = C = D = 0;
16755+}
16756--- /dev/null
16757+++ b/fs/cifs/md5.c
16758@@ -0,0 +1,363 @@
16759+/*
16760+ * This code implements the MD5 message-digest algorithm.
16761+ * The algorithm is due to Ron Rivest. This code was
16762+ * written by Colin Plumb in 1993, no copyright is claimed.
16763+ * This code is in the public domain; do with it what you wish.
16764+ *
16765+ * Equivalent code is available from RSA Data Security, Inc.
16766+ * This code has been tested against that, and is equivalent,
16767+ * except that you don't need to include two pages of legalese
16768+ * with every copy.
16769+ *
16770+ * To compute the message digest of a chunk of bytes, declare an
16771+ * MD5Context structure, pass it to MD5Init, call MD5Update as
16772+ * needed on buffers full of bytes, and then call MD5Final, which
16773+ * will fill a supplied 16-byte array with the digest.
16774+ */
16775+
16776+/* This code slightly modified to fit into Samba by
16777+ abartlet@samba.org Jun 2001
16778+ and to fit the cifs vfs by
16779+ Steve French sfrench@us.ibm.com */
16780+
16781+#include <linux/string.h>
16782+#include "md5.h"
16783+
16784+static void MD5Transform(__u32 buf[4], __u32 const in[16]);
16785+
16786+/*
16787+ * Note: this code is harmless on little-endian machines.
16788+ */
16789+static void
16790+byteReverse(unsigned char *buf, unsigned longs)
16791+{
16792+ __u32 t;
16793+ do {
16794+ t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
16795+ ((unsigned) buf[1] << 8 | buf[0]);
16796+ *(__u32 *) buf = t;
16797+ buf += 4;
16798+ } while (--longs);
16799+}
16800+
16801+/*
16802+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
16803+ * initialization constants.
16804+ */
16805+void
16806+MD5Init(struct MD5Context *ctx)
16807+{
16808+ ctx->buf[0] = 0x67452301;
16809+ ctx->buf[1] = 0xefcdab89;
16810+ ctx->buf[2] = 0x98badcfe;
16811+ ctx->buf[3] = 0x10325476;
16812+
16813+ ctx->bits[0] = 0;
16814+ ctx->bits[1] = 0;
16815+}
16816+
16817+/*
16818+ * Update context to reflect the concatenation of another buffer full
16819+ * of bytes.
16820+ */
16821+void
16822+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
16823+{
16824+ register __u32 t;
16825+
16826+ /* Update bitcount */
16827+
16828+ t = ctx->bits[0];
16829+ if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
16830+ ctx->bits[1]++; /* Carry from low to high */
16831+ ctx->bits[1] += len >> 29;
16832+
16833+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
16834+
16835+ /* Handle any leading odd-sized chunks */
16836+
16837+ if (t) {
16838+ unsigned char *p = (unsigned char *) ctx->in + t;
16839+
16840+ t = 64 - t;
16841+ if (len < t) {
16842+ memmove(p, buf, len);
16843+ return;
16844+ }
16845+ memmove(p, buf, t);
16846+ byteReverse(ctx->in, 16);
16847+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
16848+ buf += t;
16849+ len -= t;
16850+ }
16851+ /* Process data in 64-byte chunks */
16852+
16853+ while (len >= 64) {
16854+ memmove(ctx->in, buf, 64);
16855+ byteReverse(ctx->in, 16);
16856+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
16857+ buf += 64;
16858+ len -= 64;
16859+ }
16860+
16861+ /* Handle any remaining bytes of data. */
16862+
16863+ memmove(ctx->in, buf, len);
16864+}
16865+
16866+/*
16867+ * Final wrapup - pad to 64-byte boundary with the bit pattern
16868+ * 1 0* (64-bit count of bits processed, MSB-first)
16869+ */
16870+void
16871+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
16872+{
16873+ unsigned int count;
16874+ unsigned char *p;
16875+
16876+ /* Compute number of bytes mod 64 */
16877+ count = (ctx->bits[0] >> 3) & 0x3F;
16878+
16879+ /* Set the first char of padding to 0x80. This is safe since there is
16880+ always at least one byte free */
16881+ p = ctx->in + count;
16882+ *p++ = 0x80;
16883+
16884+ /* Bytes of padding needed to make 64 bytes */
16885+ count = 64 - 1 - count;
16886+
16887+ /* Pad out to 56 mod 64 */
16888+ if (count < 8) {
16889+ /* Two lots of padding: Pad the first block to 64 bytes */
16890+ memset(p, 0, count);
16891+ byteReverse(ctx->in, 16);
16892+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
16893+
16894+ /* Now fill the next block with 56 bytes */
16895+ memset(ctx->in, 0, 56);
16896+ } else {
16897+ /* Pad block to 56 bytes */
16898+ memset(p, 0, count - 8);
16899+ }
16900+ byteReverse(ctx->in, 14);
16901+
16902+ /* Append length in bits and transform */
16903+ ((__u32 *) ctx->in)[14] = ctx->bits[0];
16904+ ((__u32 *) ctx->in)[15] = ctx->bits[1];
16905+
16906+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
16907+ byteReverse((unsigned char *) ctx->buf, 4);
16908+ memmove(digest, ctx->buf, 16);
16909+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
16910+}
16911+
16912+/* The four core functions - F1 is optimized somewhat */
16913+
16914+/* #define F1(x, y, z) (x & y | ~x & z) */
16915+#define F1(x, y, z) (z ^ (x & (y ^ z)))
16916+#define F2(x, y, z) F1(z, x, y)
16917+#define F3(x, y, z) (x ^ y ^ z)
16918+#define F4(x, y, z) (y ^ (x | ~z))
16919+
16920+/* This is the central step in the MD5 algorithm. */
16921+#define MD5STEP(f, w, x, y, z, data, s) \
16922+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
16923+
16924+/*
16925+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
16926+ * reflect the addition of 16 longwords of new data. MD5Update blocks
16927+ * the data and converts bytes into longwords for this routine.
16928+ */
16929+static void
16930+MD5Transform(__u32 buf[4], __u32 const in[16])
16931+{
16932+ register __u32 a, b, c, d;
16933+
16934+ a = buf[0];
16935+ b = buf[1];
16936+ c = buf[2];
16937+ d = buf[3];
16938+
16939+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
16940+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
16941+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
16942+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
16943+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
16944+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
16945+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
16946+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
16947+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
16948+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
16949+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
16950+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
16951+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
16952+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
16953+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
16954+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
16955+
16956+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
16957+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
16958+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
16959+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
16960+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
16961+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
16962+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
16963+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
16964+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
16965+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
16966+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
16967+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
16968+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
16969+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
16970+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
16971+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
16972+
16973+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
16974+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
16975+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
16976+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
16977+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
16978+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
16979+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
16980+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
16981+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
16982+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
16983+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
16984+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
16985+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
16986+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
16987+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
16988+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
16989+
16990+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
16991+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
16992+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
16993+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
16994+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
16995+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
16996+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
16997+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
16998+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
16999+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
17000+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
17001+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
17002+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
17003+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
17004+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
17005+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
17006+
17007+ buf[0] += a;
17008+ buf[1] += b;
17009+ buf[2] += c;
17010+ buf[3] += d;
17011+}
17012+
17013+/***********************************************************************
17014+ the rfc 2104 version of hmac_md5 initialisation.
17015+***********************************************************************/
17016+void
17017+hmac_md5_init_rfc2104(unsigned char *key, int key_len,
17018+ struct HMACMD5Context *ctx)
17019+{
17020+ int i;
17021+
17022+ /* if key is longer than 64 bytes reset it to key=MD5(key) */
17023+ if (key_len > 64) {
17024+ unsigned char tk[16];
17025+ struct MD5Context tctx;
17026+
17027+ MD5Init(&tctx);
17028+ MD5Update(&tctx, key, key_len);
17029+ MD5Final(tk, &tctx);
17030+
17031+ key = tk;
17032+ key_len = 16;
17033+ }
17034+
17035+ /* start out by storing key in pads */
17036+ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
17037+ memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
17038+ memcpy(ctx->k_ipad, key, key_len);
17039+ memcpy(ctx->k_opad, key, key_len);
17040+
17041+ /* XOR key with ipad and opad values */
17042+ for (i = 0; i < 64; i++) {
17043+ ctx->k_ipad[i] ^= 0x36;
17044+ ctx->k_opad[i] ^= 0x5c;
17045+ }
17046+
17047+ MD5Init(&ctx->ctx);
17048+ MD5Update(&ctx->ctx, ctx->k_ipad, 64);
17049+}
17050+
17051+/***********************************************************************
17052+ the microsoft version of hmac_md5 initialisation.
17053+***********************************************************************/
17054+void
17055+hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
17056+ struct HMACMD5Context *ctx)
17057+{
17058+ int i;
17059+
17060+ /* if key is longer than 64 bytes truncate it */
17061+ if (key_len > 64) {
17062+ key_len = 64;
17063+ }
17064+
17065+ /* start out by storing key in pads */
17066+ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
17067+ memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
17068+ memcpy(ctx->k_ipad, key, key_len);
17069+ memcpy(ctx->k_opad, key, key_len);
17070+
17071+ /* XOR key with ipad and opad values */
17072+ for (i = 0; i < 64; i++) {
17073+ ctx->k_ipad[i] ^= 0x36;
17074+ ctx->k_opad[i] ^= 0x5c;
17075+ }
17076+
17077+ MD5Init(&ctx->ctx);
17078+ MD5Update(&ctx->ctx, ctx->k_ipad, 64);
17079+}
17080+
17081+/***********************************************************************
17082+ update hmac_md5 "inner" buffer
17083+***********************************************************************/
17084+void
17085+hmac_md5_update(const unsigned char *text, int text_len,
17086+ struct HMACMD5Context *ctx)
17087+{
17088+ MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
17089+}
17090+
17091+/***********************************************************************
17092+ finish off hmac_md5 "inner" buffer and generate outer one.
17093+***********************************************************************/
17094+void
17095+hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
17096+{
17097+ struct MD5Context ctx_o;
17098+
17099+ MD5Final(digest, &ctx->ctx);
17100+
17101+ MD5Init(&ctx_o);
17102+ MD5Update(&ctx_o, ctx->k_opad, 64);
17103+ MD5Update(&ctx_o, digest, 16);
17104+ MD5Final(digest, &ctx_o);
17105+}
17106+
17107+/***********************************************************
17108+ single function to calculate an HMAC MD5 digest from data.
17109+ use the microsoft hmacmd5 init method because the key is 16 bytes.
17110+************************************************************/
17111+void
17112+hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
17113+ unsigned char *digest)
17114+{
17115+ struct HMACMD5Context ctx;
17116+ hmac_md5_init_limK_to_64(key, 16, &ctx);
17117+ if (data_len != 0) {
17118+ hmac_md5_update(data, data_len, &ctx);
17119+ }
17120+ hmac_md5_final(digest, &ctx);
17121+}
17122--- /dev/null
17123+++ b/fs/cifs/md5.h
17124@@ -0,0 +1,38 @@
17125+#ifndef MD5_H
17126+#define MD5_H
17127+#ifndef HEADER_MD5_H
17128+/* Try to avoid clashes with OpenSSL */
17129+#define HEADER_MD5_H
17130+#endif
17131+
17132+struct MD5Context {
17133+ __u32 buf[4];
17134+ __u32 bits[2];
17135+ unsigned char in[64];
17136+};
17137+#endif /* !MD5_H */
17138+
17139+#ifndef _HMAC_MD5_H
17140+struct HMACMD5Context {
17141+ struct MD5Context ctx;
17142+ unsigned char k_ipad[65];
17143+ unsigned char k_opad[65];
17144+};
17145+#endif /* _HMAC_MD5_H */
17146+
17147+void MD5Init(struct MD5Context *context);
17148+void MD5Update(struct MD5Context *context, unsigned char const *buf,
17149+ unsigned len);
17150+void MD5Final(unsigned char digest[16], struct MD5Context *context);
17151+
17152+/* The following definitions come from lib/hmacmd5.c */
17153+
17154+void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
17155+ struct HMACMD5Context *ctx);
17156+void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
17157+ struct HMACMD5Context *ctx);
17158+void hmac_md5_update(const unsigned char *text, int text_len,
17159+ struct HMACMD5Context *ctx);
17160+void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
17161+void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
17162+ unsigned char *digest);
17163--- /dev/null
17164+++ b/fs/cifs/misc.c
17165@@ -0,0 +1,463 @@
17166+/*
17167+ * fs/cifs/misc.c
17168+ *
17169+ * Copyright (C) International Business Machines Corp., 2002,2003
17170+ * Author(s): Steve French (sfrench@us.ibm.com)
17171+ *
17172+ * This library is free software; you can redistribute it and/or modify
17173+ * it under the terms of the GNU Lesser General Public License as published
17174+ * by the Free Software Foundation; either version 2.1 of the License, or
17175+ * (at your option) any later version.
17176+ *
17177+ * This library is distributed in the hope that it will be useful,
17178+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17179+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17180+ * the GNU Lesser General Public License for more details.
17181+ *
17182+ * You should have received a copy of the GNU Lesser General Public License
17183+ * along with this library; if not, write to the Free Software
17184+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17185+ */
17186+
17187+#include <linux/slab.h>
17188+#include <linux/ctype.h>
17189+#include "cifspdu.h"
17190+#include "cifsglob.h"
17191+#include "cifsproto.h"
17192+#include "cifs_debug.h"
17193+#include "smberr.h"
17194+#include "nterr.h"
17195+
17196+extern kmem_cache_t *cifs_req_cachep;
17197+extern struct task_struct * oplockThread;
17198+
17199+__u16 GlobalMid; /* multiplex id - rotating counter */
17200+
17201+/* The xid serves as a useful identifier for each incoming vfs request,
17202+ in a similar way to the mid which is useful to track each sent smb,
17203+ and CurrentXid can also provide a running counter (although it
17204+ will eventually wrap past zero) of the total vfs operations handled
17205+ since the cifs fs was mounted */
17206+
17207+unsigned int
17208+_GetXid(void)
17209+{
17210+ unsigned int xid;
17211+
17212+ spin_lock(&GlobalMid_Lock);
17213+ GlobalTotalActiveXid++;
17214+ if (GlobalTotalActiveXid > GlobalMaxActiveXid)
17215+ GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
17216+ xid = GlobalCurrentXid++;
17217+ spin_unlock(&GlobalMid_Lock);
17218+ return xid;
17219+}
17220+
17221+void
17222+_FreeXid(unsigned int xid)
17223+{
17224+ spin_lock(&GlobalMid_Lock);
17225+ /* if(GlobalTotalActiveXid == 0)
17226+ BUG(); */
17227+ GlobalTotalActiveXid--;
17228+ spin_unlock(&GlobalMid_Lock);
17229+}
17230+
17231+struct cifsSesInfo *
17232+sesInfoAlloc(void)
17233+{
17234+ struct cifsSesInfo *ret_buf;
17235+
17236+ ret_buf =
17237+ (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
17238+ GFP_KERNEL);
17239+ if (ret_buf) {
17240+ memset(ret_buf, 0, sizeof (struct cifsSesInfo));
17241+ write_lock(&GlobalSMBSeslock);
17242+ atomic_inc(&sesInfoAllocCount);
17243+ ret_buf->status = CifsNew;
17244+ list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
17245+ init_MUTEX(&ret_buf->sesSem);
17246+ write_unlock(&GlobalSMBSeslock);
17247+ }
17248+ return ret_buf;
17249+}
17250+
17251+void
17252+sesInfoFree(struct cifsSesInfo *buf_to_free)
17253+{
17254+ if (buf_to_free == NULL) {
17255+ cFYI(1, ("Null buffer passed to sesInfoFree"));
17256+ return;
17257+ }
17258+
17259+ write_lock(&GlobalSMBSeslock);
17260+ atomic_dec(&sesInfoAllocCount);
17261+ list_del(&buf_to_free->cifsSessionList);
17262+ write_unlock(&GlobalSMBSeslock);
17263+ if (buf_to_free->serverOS)
17264+ kfree(buf_to_free->serverOS);
17265+ if (buf_to_free->serverDomain)
17266+ kfree(buf_to_free->serverDomain);
17267+ if (buf_to_free->serverNOS)
17268+ kfree(buf_to_free->serverNOS);
17269+ if (buf_to_free->password)
17270+ kfree(buf_to_free->password);
17271+ kfree(buf_to_free);
17272+}
17273+
17274+struct cifsTconInfo *
17275+tconInfoAlloc(void)
17276+{
17277+ struct cifsTconInfo *ret_buf;
17278+ ret_buf =
17279+ (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
17280+ GFP_KERNEL);
17281+ if (ret_buf) {
17282+ memset(ret_buf, 0, sizeof (struct cifsTconInfo));
17283+ write_lock(&GlobalSMBSeslock);
17284+ atomic_inc(&tconInfoAllocCount);
17285+ list_add(&ret_buf->cifsConnectionList,
17286+ &GlobalTreeConnectionList);
17287+ ret_buf->tidStatus = CifsNew;
17288+ INIT_LIST_HEAD(&ret_buf->openFileList);
17289+ init_MUTEX(&ret_buf->tconSem);
17290+#ifdef CONFIG_CIFS_STATS
17291+ ret_buf->stat_lock = SPIN_LOCK_UNLOCKED;
17292+#endif
17293+ write_unlock(&GlobalSMBSeslock);
17294+ }
17295+ return ret_buf;
17296+}
17297+
17298+void
17299+tconInfoFree(struct cifsTconInfo *buf_to_free)
17300+{
17301+ if (buf_to_free == NULL) {
17302+ cFYI(1, ("Null buffer passed to tconInfoFree"));
17303+ return;
17304+ }
17305+ write_lock(&GlobalSMBSeslock);
17306+ atomic_dec(&tconInfoAllocCount);
17307+ list_del(&buf_to_free->cifsConnectionList);
17308+ write_unlock(&GlobalSMBSeslock);
17309+ if (buf_to_free->nativeFileSystem)
17310+ kfree(buf_to_free->nativeFileSystem);
17311+ kfree(buf_to_free);
17312+}
17313+
17314+struct smb_hdr *
17315+cifs_buf_get(void)
17316+{
17317+ struct smb_hdr *ret_buf = NULL;
17318+
17319+/* We could use negotiated size instead of max_msgsize -
17320+ but it may be more efficient to always alloc same size
17321+ albeit slightly larger than necessary and maxbuffersize
17322+ defaults to this and can not be bigger */
17323+ ret_buf =
17324+ (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
17325+
17326+ /* clear the first few header bytes */
17327+ if (ret_buf) {
17328+ memset(ret_buf, 0, sizeof (struct smb_hdr));
17329+ atomic_inc(&bufAllocCount);
17330+ }
17331+
17332+ return ret_buf;
17333+}
17334+
17335+void
17336+cifs_buf_release(void *buf_to_free)
17337+{
17338+
17339+ if (buf_to_free == NULL) {
17340+ cFYI(1, ("Null buffer passed to cifs_buf_release"));
17341+ return;
17342+ }
17343+ kmem_cache_free(cifs_req_cachep, buf_to_free);
17344+
17345+ atomic_dec(&bufAllocCount);
17346+ return;
17347+}
17348+
17349+void
17350+header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
17351+ const struct cifsTconInfo *treeCon, int word_count
17352+ /* length of fixed section (word count) in two byte units */
17353+ )
17354+{
17355+ int i;
17356+ __u32 tmp;
17357+ struct list_head* temp_item;
17358+ struct cifsSesInfo * ses;
17359+ char *temp = (char *) buffer;
17360+
17361+ for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) {
17362+ temp[i] = 0; /* BB is this needed ?? */
17363+ }
17364+
17365+ buffer->smb_buf_length =
17366+ (2 * word_count) + sizeof (struct smb_hdr) -
17367+ 4 /* RFC 1001 length field does not count */ +
17368+ 2 /* for bcc field itself */ ;
17369+ /* 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 */
17370+
17371+ buffer->Protocol[0] = 0xFF;
17372+ buffer->Protocol[1] = 'S';
17373+ buffer->Protocol[2] = 'M';
17374+ buffer->Protocol[3] = 'B';
17375+ buffer->Command = smb_command;
17376+ buffer->Flags = 0x00; /* case sensitive */
17377+ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
17378+ tmp = cpu_to_le32(current->pid);
17379+ buffer->Pid = tmp & 0xFFFF;
17380+ tmp >>= 16;
17381+ buffer->PidHigh = tmp & 0xFFFF;
17382+ spin_lock(&GlobalMid_Lock);
17383+ GlobalMid++;
17384+ buffer->Mid = GlobalMid;
17385+ spin_unlock(&GlobalMid_Lock);
17386+ if (treeCon) {
17387+ buffer->Tid = treeCon->tid;
17388+ if (treeCon->ses) {
17389+ if (treeCon->ses->capabilities & CAP_UNICODE)
17390+ buffer->Flags2 |= SMBFLG2_UNICODE;
17391+ if (treeCon->ses->capabilities & CAP_STATUS32) {
17392+ buffer->Flags2 |= SMBFLG2_ERR_STATUS;
17393+ }
17394+
17395+ buffer->Uid = treeCon->ses->Suid; /* always in LE format */
17396+ if(multiuser_mount != 0) {
17397+ /* For the multiuser case, there are few obvious technically */
17398+ /* possible mechanisms to match the local linux user (uid) */
17399+ /* to a valid remote smb user (smb_uid): */
17400+ /* 1) Query Winbind (or other local pam/nss daemon */
17401+ /* for userid/password/logon_domain or credential */
17402+ /* 2) Query Winbind for uid to sid to username mapping */
17403+ /* and see if we have a matching password for existing*/
17404+ /* session for that user perhas getting password by */
17405+ /* adding a new pam_cifs module that stores passwords */
17406+ /* so that the cifs vfs can get at that for all logged*/
17407+ /* on users */
17408+ /* 3) (Which is the mechanism we have chosen) */
17409+ /* Search through sessions to the same server for a */
17410+ /* a match on the uid that was passed in on mount */
17411+ /* with the current processes uid (or euid?) and use */
17412+ /* that smb uid. If no existing smb session for */
17413+ /* that uid found, use the default smb session ie */
17414+ /* the smb session for the volume mounted which is */
17415+ /* the same as would be used if the multiuser mount */
17416+ /* flag were disabled. */
17417+
17418+ /* BB Add support for establishing new tCon and SMB Session */
17419+ /* with userid/password pairs found on the smb session */
17420+ /* for other target tcp/ip addresses BB */
17421+ if(current->uid != treeCon->ses->linux_uid) {
17422+ cFYI(1,("Multiuser mode and UID did not match tcon uid "));
17423+ read_lock(&GlobalSMBSeslock);
17424+ list_for_each(temp_item, &GlobalSMBSessionList) {
17425+ ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
17426+ if(ses->linux_uid == current->uid) {
17427+ if(ses->server == treeCon->ses->server) {
17428+ cFYI(1,("found matching uid substitute right smb_uid"));
17429+ buffer->Uid = ses->Suid;
17430+ break;
17431+ } else {
17432+ /* BB eventually call cifs_setup_session here */
17433+ cFYI(1,("local UID found but smb sess with this server does not exist"));
17434+ }
17435+ }
17436+ }
17437+ read_unlock(&GlobalSMBSeslock);
17438+ }
17439+ }
17440+ }
17441+ if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
17442+ buffer->Flags2 |= SMBFLG2_DFS;
17443+ if(treeCon->ses->server)
17444+ if(treeCon->ses->server->secMode &
17445+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
17446+ buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
17447+ }
17448+
17449+/* endian conversion of flags is now done just before sending */
17450+ buffer->WordCount = (char) word_count;
17451+ return;
17452+}
17453+
17454+int
17455+checkSMBhdr(struct smb_hdr *smb, __u16 mid)
17456+{
17457+ /* Make sure that this really is an SMB, that it is a response,
17458+ and that the message ids match */
17459+ if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
17460+ (mid == smb->Mid)) {
17461+ if(smb->Flags & SMBFLG_RESPONSE)
17462+ return 0;
17463+ else {
17464+ /* only one valid case where server sends us request */
17465+ if(smb->Command == SMB_COM_LOCKING_ANDX)
17466+ return 0;
17467+ else
17468+ cERROR(1, ("Rcvd Request not response "));
17469+ }
17470+ } else { /* bad signature or mid */
17471+ if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
17472+ cERROR(1,
17473+ ("Bad protocol string signature header %x ",
17474+ *(unsigned int *) smb->Protocol));
17475+ if (mid != smb->Mid)
17476+ cERROR(1, ("Mids do not match"));
17477+ }
17478+ cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
17479+ return 1;
17480+}
17481+
17482+int
17483+checkSMB(struct smb_hdr *smb, __u16 mid, int length)
17484+{
17485+ cFYI(0,
17486+ ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
17487+ length, ntohl(smb->smb_buf_length)));
17488+ if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
17489+ || (ntohl(smb->smb_buf_length) >
17490+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
17491+ if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
17492+ cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
17493+ if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
17494+ && (smb->Status.CifsError != 0))
17495+ return 0; /* some error cases do not return wct and bcc */
17496+
17497+ }
17498+ if (ntohl(smb->smb_buf_length) >
17499+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
17500+ cERROR(1,
17501+ ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
17502+ cERROR(1,
17503+ ("bad smb detected. Illegal length. The mid=%d",
17504+ smb->Mid));
17505+ return 1;
17506+ }
17507+
17508+ if (checkSMBhdr(smb, mid))
17509+ return 1;
17510+
17511+ if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
17512+ || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
17513+ return 0;
17514+ } else {
17515+ cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
17516+ cERROR(1,
17517+ ("bad smb size detected. The Mid=%d", smb->Mid));
17518+ return 1;
17519+ }
17520+}
17521+int
17522+is_valid_oplock_break(struct smb_hdr *buf)
17523+{
17524+ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
17525+ struct list_head *tmp;
17526+ struct list_head *tmp1;
17527+ struct cifsTconInfo *tcon;
17528+ struct cifsFileInfo *netfile;
17529+
17530+ /* could add check for smb response flag 0x80 */
17531+ cFYI(1,("Checking for oplock break"));
17532+ if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
17533+ return FALSE;
17534+ if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
17535+ /* no sense logging error on invalid handle on oplock
17536+ break - harmless race between close request and oplock
17537+ break response is expected from time to time writing out
17538+ large dirty files cached on the client */
17539+ if ((NT_STATUS_INVALID_HANDLE) ==
17540+ le32_to_cpu(pSMB->hdr.Status.CifsError)) {
17541+ cFYI(1,("invalid handle on oplock break"));
17542+ return TRUE;
17543+ } else if (ERRbadfid ==
17544+ le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
17545+ return TRUE;
17546+ } else {
17547+ return FALSE; /* on valid oplock brk we get "request" */
17548+ }
17549+ }
17550+ if(pSMB->hdr.WordCount != 8)
17551+ return FALSE;
17552+
17553+ cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
17554+ if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
17555+ return FALSE;
17556+
17557+ /* look up tcon based on tid & uid */
17558+ read_lock(&GlobalSMBSeslock);
17559+ list_for_each(tmp, &GlobalTreeConnectionList) {
17560+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
17561+ if (tcon->tid == buf->Tid) {
17562+#ifdef CONFIG_CIFS_STATS
17563+ atomic_inc(&tcon->num_oplock_brks);
17564+#endif
17565+ list_for_each(tmp1,&tcon->openFileList){
17566+ netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
17567+ if(pSMB->Fid == netfile->netfid) {
17568+ struct cifsInodeInfo *pCifsInode;
17569+ read_unlock(&GlobalSMBSeslock);
17570+ cFYI(1,("Matching file id, processing oplock break"));
17571+ pCifsInode =
17572+ CIFS_I(netfile->pInode);
17573+ pCifsInode->clientCanCacheAll = FALSE;
17574+ if(pSMB->OplockLevel == 0)
17575+ pCifsInode->clientCanCacheRead = FALSE;
17576+ pCifsInode->oplockPending = TRUE;
17577+ AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
17578+ cFYI(1,("about to wake up oplock thd"));
17579+ wake_up_process(oplockThread);
17580+ return TRUE;
17581+ }
17582+ }
17583+ read_unlock(&GlobalSMBSeslock);
17584+ cFYI(1,("No matching file for oplock break on connection"));
17585+ return TRUE;
17586+ }
17587+ }
17588+ read_unlock(&GlobalSMBSeslock);
17589+ cFYI(1,("Can not process oplock break for non-existent connection"));
17590+ return TRUE;
17591+}
17592+
17593+void
17594+dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
17595+{
17596+ int i, j;
17597+ char debug_line[17];
17598+ unsigned char *buffer;
17599+
17600+ if (traceSMB == 0)
17601+ return;
17602+
17603+ buffer = (unsigned char *) smb_buf;
17604+ for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
17605+ if (i % 8 == 0) { /* we have reached the beginning of line */
17606+ printk(KERN_DEBUG "| ");
17607+ j = 0;
17608+ }
17609+ printk("%0#4x ", buffer[i]);
17610+ debug_line[2 * j] = ' ';
17611+ if (isprint(buffer[i]))
17612+ debug_line[1 + (2 * j)] = buffer[i];
17613+ else
17614+ debug_line[1 + (2 * j)] = '_';
17615+
17616+ if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
17617+ debug_line[16] = 0;
17618+ printk(" | %s\n", debug_line);
17619+ }
17620+ }
17621+ for (; j < 8; j++) {
17622+ printk(" ");
17623+ debug_line[2 * j] = ' ';
17624+ debug_line[1 + (2 * j)] = ' ';
17625+ }
17626+ printk( " | %s\n", debug_line);
17627+ return;
17628+}
17629--- /dev/null
17630+++ b/fs/cifs/netmisc.c
17631@@ -0,0 +1,905 @@
17632+/*
17633+ * fs/cifs/netmisc.c
17634+ *
17635+ * Copyright (c) International Business Machines Corp., 2002
17636+ * Author(s): Steve French (sfrench@us.ibm.com)
17637+ *
17638+ * Error mapping routines from Samba libsmb/errormap.c
17639+ * Copyright (C) Andrew Tridgell 2001
17640+ *
17641+ *
17642+ * This program is free software; you can redistribute it and/or modify
17643+ * it under the terms of the GNU General Public License as published by
17644+ * the Free Software Foundation; either version 2 of the License, or
17645+ * (at your option) any later version.
17646+ *
17647+ * This program is distributed in the hope that it will be useful,
17648+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17649+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17650+ * the GNU General Public License for more details.
17651+ *
17652+ * You should have received a copy of the GNU General Public License
17653+ * along with this program; if not, write to the Free Software
17654+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17655+ */
17656+
17657+#include <linux/net.h>
17658+#include <linux/string.h>
17659+#include <linux/in.h>
17660+#include <linux/ctype.h>
17661+#include <linux/fs.h>
17662+#include <asm/div64.h>
17663+#include <asm/byteorder.h>
17664+#include "cifsfs.h"
17665+#include "cifspdu.h"
17666+#include "cifsglob.h"
17667+#include "cifsproto.h"
17668+#include "smberr.h"
17669+#include "cifs_debug.h"
17670+#include "nterr.h"
17671+
17672+struct smb_to_posix_error {
17673+ __u16 smb_err;
17674+ int posix_code;
17675+};
17676+
17677+const struct smb_to_posix_error mapping_table_ERRDOS[] = {
17678+ {ERRbadfunc, -EINVAL},
17679+ {ERRbadfile, -ENOENT},
17680+ {ERRbadpath, -ENOTDIR},
17681+ {ERRnofids, -EMFILE},
17682+ {ERRnoaccess, -EACCES},
17683+ {ERRbadfid, -EBADF},
17684+ {ERRbadmcb, -EIO},
17685+ {ERRnomem, -ENOMEM},
17686+ {ERRbadmem, -EFAULT},
17687+ {ERRbadenv, -EFAULT},
17688+ {ERRbadformat, -EINVAL},
17689+ {ERRbadaccess, -EACCES},
17690+ {ERRbaddata, -EIO},
17691+ {ERRbaddrive, -ENXIO},
17692+ {ERRremcd, -EACCES},
17693+ {ERRdiffdevice, -EXDEV},
17694+ {ERRnofiles, -ENOENT},
17695+ {ERRbadshare, -ETXTBSY},
17696+ {ERRlock, -EACCES},
17697+ {ERRunsup, -EINVAL},
17698+ {ERRnosuchshare,-ENXIO},
17699+ {ERRfilexists, -EEXIST},
17700+ {ERRinvparm, -EINVAL},
17701+ {ERRdiskfull, -ENOSPC},
17702+ {ERRinvname, -ENOENT},
17703+ {ERRdirnotempty, -ENOTEMPTY},
17704+ {ERRnotlocked, -ENOLCK},
17705+ {ERRalreadyexists, -EEXIST},
17706+ {ERRmoredata, -EOVERFLOW},
17707+ {ErrQuota, -EDQUOT},
17708+ {ErrNotALink, -ENOLINK},
17709+ {ERRnetlogonNotStarted,-ENOPROTOOPT},
17710+ {0, 0}
17711+};
17712+
17713+const struct smb_to_posix_error mapping_table_ERRSRV[] = {
17714+ {ERRerror, -EIO},
17715+ {ERRbadpw, -EPERM},
17716+ {ERRbadtype, -EREMOTE},
17717+ {ERRaccess, -EACCES},
17718+ {ERRinvtid, -ENXIO},
17719+ {ERRinvnetname, -ENODEV},
17720+ {ERRinvdevice, -ENXIO},
17721+ {ERRqfull, -ENOSPC},
17722+ {ERRqtoobig, -ENOSPC},
17723+ {ERRqeof, -EIO},
17724+ {ERRinvpfid, -EBADF},
17725+ {ERRsmbcmd, -EBADRQC},
17726+ {ERRsrverror, -EIO},
17727+ {ERRbadBID, -EIO},
17728+ {ERRfilespecs, -EINVAL},
17729+ {ERRbadLink, -EIO},
17730+ {ERRbadpermits, -EINVAL},
17731+ {ERRbadPID, -ESRCH},
17732+ {ERRsetattrmode, -EINVAL},
17733+ {ERRpaused, -EHOSTDOWN},
17734+ {ERRmsgoff, -EHOSTDOWN},
17735+ {ERRnoroom, -ENOSPC},
17736+ {ERRrmuns, -EUSERS},
17737+ {ERRtimeout, -ETIME},
17738+ {ERRnoresource, -ENOBUFS},
17739+ {ERRtoomanyuids, -EUSERS},
17740+ {ERRbaduid, -EACCES},
17741+ {ERRusempx, -EIO},
17742+ {ERRusestd, -EIO},
17743+ {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
17744+ {ERRaccountexpired, -EACCES},
17745+ {ERRbadclient, -EACCES},
17746+ {ERRbadLogonTime, -EACCES},
17747+ {ERRpasswordExpired, -EACCES},
17748+ {ERRnosupport, -EINVAL},
17749+ {0, 0}
17750+};
17751+
17752+const struct smb_to_posix_error mapping_table_ERRHRD[] = {
17753+ {0, 0}
17754+};
17755+
17756+/* Convert string containing dotted ip address to binary form */
17757+/* returns 0 if invalid address */
17758+
17759+/* BB add address family, change rc to status flag and return union or for ipv6 */
17760+/* will need parent to call something like inet_pton to convert ipv6 address BB */
17761+int
17762+cifs_inet_pton(int address_family, char *cp,void *dst)
17763+{
17764+ struct in_addr address;
17765+ int value;
17766+ int digit;
17767+ int i;
17768+ char temp;
17769+ char bytes[4];
17770+ char *end = bytes;
17771+ static const int addr_class_max[4] =
17772+ { 0xffffffff, 0xffffff, 0xffff, 0xff };
17773+
17774+ if(address_family != AF_INET)
17775+ return -EAFNOSUPPORT;
17776+
17777+ for (i = 0; i < 4; i++) {
17778+ bytes[i] = 0;
17779+ }
17780+
17781+ temp = *cp;
17782+
17783+ while (TRUE) {
17784+ if (!isdigit(temp))
17785+ return 0;
17786+
17787+ value = 0;
17788+ digit = 0;
17789+ for (;;) {
17790+ if (isascii(temp) && isdigit(temp)) {
17791+ value = (value * 10) + temp - '0';
17792+ temp = *++cp;
17793+ digit = 1;
17794+ } else
17795+ break;
17796+ }
17797+
17798+ if (temp == '.') {
17799+ if ((end > bytes + 2) || (value > 255))
17800+ return 0;
17801+ *end++ = value;
17802+ temp = *++cp;
17803+ } else if (temp == ':') {
17804+ cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
17805+ return -1;
17806+ } else
17807+ break;
17808+ }
17809+
17810+ /* check for last characters */
17811+ if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
17812+ if (temp != '\\') {
17813+ if (temp != '/')
17814+ return 0;
17815+ else
17816+ (*cp = '\\'); /* switch the slash the expected way */
17817+ }
17818+ if (value > addr_class_max[end - bytes])
17819+ return 0;
17820+
17821+ address.s_addr = *((int *) bytes) | htonl(value);
17822+ *((int *)dst) = address.s_addr;
17823+ return 1; /* success */
17824+}
17825+
17826+/*****************************************************************************
17827+convert a NT status code to a dos class/code
17828+ *****************************************************************************/
17829+/* NT status -> dos error map */
17830+static const struct {
17831+ __u8 dos_class;
17832+ __u16 dos_code;
17833+ __u32 ntstatus;
17834+} ntstatus_to_dos_map[] = {
17835+ {
17836+ ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
17837+ ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
17838+ ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
17839+ ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
17840+ ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
17841+ ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
17842+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
17843+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
17844+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
17845+ ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
17846+ ERRDOS, 87, NT_STATUS_INVALID_CID}, {
17847+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
17848+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
17849+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
17850+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
17851+ ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
17852+ ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
17853+ ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
17854+ ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
17855+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
17856+ ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
17857+/* { This NT error code was 'sqashed'
17858+ from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
17859+ during the session setup } */
17860+ {
17861+ ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
17862+ ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
17863+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
17864+ ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
17865+ ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
17866+ ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
17867+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
17868+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
17869+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
17870+ ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
17871+ ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
17872+/* { This NT error code was 'sqashed'
17873+ from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
17874+ during the session setup } */
17875+ {
17876+ ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
17877+ ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
17878+ ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
17879+ ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
17880+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
17881+ ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
17882+ ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
17883+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
17884+ ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
17885+ ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
17886+ ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
17887+ ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
17888+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
17889+ ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
17890+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
17891+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
17892+ ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
17893+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */
17894+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
17895+ ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
17896+ ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
17897+ ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
17898+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
17899+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
17900+ ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
17901+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
17902+ ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
17903+ ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
17904+ ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
17905+ ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
17906+ ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
17907+ ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
17908+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
17909+ ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
17910+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
17911+ ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
17912+ ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
17913+ ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
17914+ ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
17915+ ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
17916+ ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
17917+ ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
17918+ ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
17919+ ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
17920+ ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
17921+ ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, {
17922+ ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
17923+ ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
17924+ ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
17925+ ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
17926+ ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
17927+ ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
17928+ ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
17929+ ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
17930+ ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
17931+ ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
17932+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
17933+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
17934+ ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
17935+ ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
17936+ ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
17937+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
17938+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
17939+ ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
17940+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
17941+ ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
17942+/* { This NT error code was 'sqashed'
17943+ from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
17944+ during the session setup } */
17945+ {
17946+ ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
17947+ ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
17948+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
17949+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
17950+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
17951+ ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
17952+/* { This NT error code was 'sqashed'
17953+ from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
17954+ during the session setup } */
17955+ {
17956+ ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
17957+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
17958+ ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
17959+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
17960+ ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
17961+ ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
17962+ ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
17963+ ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
17964+ ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
17965+ ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
17966+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
17967+ ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
17968+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
17969+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
17970+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
17971+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
17972+ ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
17973+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
17974+ ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
17975+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
17976+ ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
17977+ ERRDOS, 112, NT_STATUS_DISK_FULL}, {
17978+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
17979+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
17980+ ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
17981+ ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
17982+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
17983+ ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
17984+ ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
17985+ ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
17986+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
17987+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
17988+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
17989+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
17990+ ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
17991+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
17992+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
17993+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
17994+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
17995+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
17996+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
17997+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
17998+ ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
17999+ ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
18000+ ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
18001+ ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
18002+ ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
18003+ ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
18004+/* { This NT error code was 'sqashed'
18005+ from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
18006+ during the session setup } */
18007+ {
18008+ ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
18009+ ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
18010+ ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
18011+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
18012+ ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
18013+ ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
18014+ ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
18015+ ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
18016+ ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
18017+ ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
18018+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
18019+ ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
18020+ ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
18021+ ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
18022+ ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
18023+ ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
18024+ ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
18025+ ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
18026+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
18027+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
18028+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
18029+ ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
18030+ ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
18031+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
18032+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
18033+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
18034+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
18035+ ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
18036+ ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
18037+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
18038+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
18039+ ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
18040+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
18041+ ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
18042+ ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
18043+ ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
18044+ ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
18045+ ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
18046+ ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
18047+ ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
18048+ ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
18049+ ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
18050+ ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
18051+ ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
18052+ ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
18053+ ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
18054+ ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
18055+ ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
18056+ ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
18057+ ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
18058+ ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
18059+ ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
18060+ ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
18061+ ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
18062+ ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
18063+ ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
18064+ ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
18065+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
18066+ ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
18067+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
18068+ ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
18069+ ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
18070+ ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
18071+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
18072+ ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
18073+ ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
18074+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
18075+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
18076+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
18077+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
18078+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
18079+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
18080+ ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
18081+ ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
18082+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
18083+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
18084+ ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
18085+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
18086+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
18087+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
18088+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
18089+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
18090+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
18091+ ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
18092+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
18093+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
18094+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
18095+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
18096+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
18097+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
18098+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
18099+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
18100+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
18101+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
18102+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
18103+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
18104+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
18105+ ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
18106+ ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
18107+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
18108+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
18109+ ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
18110+ ERRDOS, 203, 0xc0000100}, {
18111+ ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
18112+ ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
18113+ ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
18114+ ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
18115+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
18116+ ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
18117+ ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
18118+ ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
18119+ ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
18120+ ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
18121+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
18122+ ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
18123+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
18124+ ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
18125+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
18126+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
18127+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
18128+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
18129+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
18130+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
18131+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
18132+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
18133+ ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
18134+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
18135+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
18136+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
18137+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
18138+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
18139+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
18140+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
18141+ ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
18142+ ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
18143+ ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
18144+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
18145+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
18146+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
18147+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
18148+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
18149+ ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
18150+ ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
18151+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
18152+ ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
18153+ ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
18154+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
18155+ ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
18156+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
18157+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
18158+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
18159+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
18160+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
18161+ ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
18162+ ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
18163+ ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
18164+ ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
18165+ ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
18166+ ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
18167+ ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
18168+ ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
18169+ ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
18170+ ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
18171+ ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
18172+ ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
18173+ ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
18174+ ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
18175+ ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
18176+ ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
18177+ ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
18178+ ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
18179+ ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
18180+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
18181+ ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
18182+ ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
18183+ ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
18184+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
18185+ ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
18186+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
18187+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
18188+ ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
18189+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
18190+ ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
18191+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
18192+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
18193+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
18194+ ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
18195+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
18196+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
18197+ ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
18198+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
18199+ ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
18200+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
18201+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
18202+ ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
18203+ ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
18204+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
18205+ ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
18206+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
18207+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
18208+ ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
18209+ ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
18210+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
18211+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
18212+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
18213+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
18214+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
18215+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
18216+ ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
18217+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
18218+ ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
18219+ ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
18220+ ERRHRD, ERRgeneral, 0xc000016e}, {
18221+ ERRHRD, ERRgeneral, 0xc000016f}, {
18222+ ERRHRD, ERRgeneral, 0xc0000170}, {
18223+ ERRHRD, ERRgeneral, 0xc0000171}, {
18224+ ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
18225+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
18226+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
18227+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
18228+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
18229+ ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
18230+ ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
18231+ ERRHRD, ERRgeneral, 0xc0000179}, {
18232+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
18233+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
18234+ ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
18235+ ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
18236+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
18237+ ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
18238+ ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
18239+ ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
18240+ ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
18241+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
18242+ ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
18243+ ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
18244+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
18245+ ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
18246+ ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
18247+ ERRDOS, 19, NT_STATUS_TOO_LATE}, {
18248+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
18249+/* { This NT error code was 'sqashed'
18250+ from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
18251+ during the session setup } */
18252+ {
18253+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
18254+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
18255+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
18256+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
18257+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
18258+ ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
18259+ ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
18260+ ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
18261+ ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
18262+ ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
18263+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
18264+ ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
18265+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
18266+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
18267+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
18268+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
18269+/* { This NT error code was 'sqashed'
18270+ from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
18271+ during the session setup } */
18272+ {
18273+ ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
18274+ ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
18275+ ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
18276+ ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
18277+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
18278+ ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
18279+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
18280+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
18281+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
18282+ ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
18283+ ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
18284+ ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
18285+ ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
18286+ ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
18287+ ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
18288+ ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
18289+ ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
18290+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
18291+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
18292+ ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
18293+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
18294+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
18295+ ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
18296+ ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
18297+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
18298+ ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
18299+ ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
18300+ ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
18301+ ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
18302+ ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
18303+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
18304+ ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
18305+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
18306+ ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
18307+ ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
18308+ ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
18309+ ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
18310+ ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
18311+ ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
18312+ ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
18313+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
18314+ ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
18315+ ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
18316+ ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
18317+ ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
18318+ ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
18319+ ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
18320+ ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
18321+ ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
18322+ ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
18323+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
18324+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
18325+ ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
18326+ ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
18327+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
18328+ ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
18329+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
18330+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
18331+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
18332+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
18333+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
18334+ ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
18335+ ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
18336+ ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
18337+ ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
18338+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
18339+ ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
18340+ ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
18341+ ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
18342+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
18343+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
18344+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
18345+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
18346+ ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
18347+ ERRHRD, ERRgeneral, 0xc000024a}, {
18348+ ERRHRD, ERRgeneral, 0xc000024b}, {
18349+ ERRHRD, ERRgeneral, 0xc000024c}, {
18350+ ERRHRD, ERRgeneral, 0xc000024d}, {
18351+ ERRHRD, ERRgeneral, 0xc000024e}, {
18352+ ERRHRD, ERRgeneral, 0xc000024f}, {
18353+ ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
18354+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
18355+ ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
18356+ ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
18357+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
18358+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
18359+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
18360+ ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
18361+ ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
18362+ ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
18363+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
18364+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
18365+ ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
18366+ ERRHRD, ERRgeneral, 0xc000025d}, {
18367+ ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
18368+ ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
18369+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
18370+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
18371+ ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
18372+ ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
18373+ ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
18374+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
18375+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
18376+ ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
18377+ ERRDOS, 21, 0xc000026e}, {
18378+ ERRDOS, 161, 0xc0000281}, {
18379+ ERRDOS, ERRnoaccess, 0xc000028a}, {
18380+ ERRDOS, ERRnoaccess, 0xc000028b}, {
18381+ ERRHRD, ERRgeneral, 0xc000028c}, {
18382+ ERRDOS, ERRnoaccess, 0xc000028d}, {
18383+ ERRDOS, ERRnoaccess, 0xc000028e}, {
18384+ ERRDOS, ERRnoaccess, 0xc000028f}, {
18385+ ERRDOS, ERRnoaccess, 0xc0000290}, {
18386+ERRDOS, ERRbadfunc, 0xc000029c},};
18387+
18388+/*****************************************************************************
18389+ Print an error message from the status code
18390+ *****************************************************************************/
18391+static void
18392+cifs_print_status(__u32 status_code)
18393+{
18394+ int idx = 0;
18395+
18396+ while (nt_errs[idx].nt_errstr != NULL) {
18397+ if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
18398+ (status_code & 0xFFFFFF)) {
18399+ printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
18400+ status_code,nt_errs[idx].nt_errstr);
18401+ }
18402+ idx++;
18403+ }
18404+ return;
18405+}
18406+
18407+
18408+static void
18409+ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
18410+{
18411+ int i;
18412+ if (ntstatus == 0) {
18413+ *eclass = 0;
18414+ *ecode = 0;
18415+ return;
18416+ }
18417+ for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
18418+ if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
18419+ *eclass = ntstatus_to_dos_map[i].dos_class;
18420+ *ecode = ntstatus_to_dos_map[i].dos_code;
18421+ return;
18422+ }
18423+ }
18424+ *eclass = ERRHRD;
18425+ *ecode = ERRgeneral;
18426+}
18427+
18428+int
18429+map_smb_to_linux_error(struct smb_hdr *smb)
18430+{
18431+ unsigned int i;
18432+ int rc = -EIO; /* if transport error smb error may not be set */
18433+ __u8 smberrclass;
18434+ __u16 smberrcode;
18435+
18436+ /* BB if NT Status codes - map NT BB */
18437+
18438+ /* old style smb error codes */
18439+ if (smb->Status.CifsError == 0)
18440+ return 0;
18441+
18442+ if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
18443+ /* translate the newer STATUS codes to old style errors and then to POSIX errors */
18444+ smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
18445+ if(cifsFYI)
18446+ cifs_print_status(smb->Status.CifsError);
18447+ ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
18448+ &smberrcode);
18449+ } else {
18450+ smberrclass = smb->Status.DosError.ErrorClass;
18451+ smb->Status.DosError.Error =
18452+ le16_to_cpu(smb->Status.DosError.Error);
18453+ smberrcode = smb->Status.DosError.Error;
18454+ }
18455+
18456+ /* old style errors */
18457+
18458+ /* DOS class smb error codes - map DOS */
18459+ if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
18460+ for (i = 0;
18461+ i <
18462+ sizeof (mapping_table_ERRDOS) /
18463+ sizeof (struct smb_to_posix_error); i++) {
18464+ if (mapping_table_ERRDOS[i].smb_err == 0)
18465+ break;
18466+ else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
18467+ rc = mapping_table_ERRDOS[i].posix_code;
18468+ break;
18469+ }
18470+ /* else try the next error mapping one to see if it will match */
18471+ }
18472+ } else if (smberrclass == ERRSRV) { /* server class of error codes */
18473+ for (i = 0;
18474+ i <
18475+ sizeof (mapping_table_ERRSRV) /
18476+ sizeof (struct smb_to_posix_error); i++) {
18477+ if (mapping_table_ERRSRV[i].smb_err == 0)
18478+ break;
18479+ else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
18480+ rc = mapping_table_ERRSRV[i].posix_code;
18481+ break;
18482+ }
18483+ /* else try the next error mapping one to see if it will match */
18484+ }
18485+ }
18486+ /* else ERRHRD class errors or junk - return EIO */
18487+
18488+ cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
18489+
18490+ /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
18491+
18492+ return rc;
18493+}
18494+
18495+/*
18496+ * calculate the size of the SMB message based on the fixed header
18497+ * portion, the number of word parameters and the data portion of the message
18498+ */
18499+unsigned int
18500+smbCalcSize(struct smb_hdr *ptr)
18501+{
18502+ return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
18503+ BCC(ptr));
18504+}
18505+
18506+/* The following are taken from fs/ntfs/util.c */
18507+
18508+#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
18509+
18510+ /*
18511+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
18512+ * into Unix UTC (based 1970-01-01, in seconds).
18513+ */
18514+time_t
18515+cifs_NTtimeToUnix(__u64 ntutc)
18516+{
18517+ /* BB what about the timezone? BB */
18518+
18519+ /* Subtract the NTFS time offset, then convert to 1s intervals. */
18520+ u64 t;
18521+
18522+ t = ntutc - NTFS_TIME_OFFSET;
18523+ do_div(t, 10000000);
18524+ return (time_t)t;
18525+}
18526+
18527+/* Convert the Unix UTC into NT UTC. */
18528+__u64
18529+cifs_UnixTimeToNT(time_t t)
18530+{
18531+ __u64 dce_time;
18532+ /* Convert to 100ns intervals and then add the NTFS time offset. */
18533+ dce_time = (__u64) t * 10000000;
18534+ dce_time += NTFS_TIME_OFFSET;
18535+ return dce_time;
18536+}
18537--- /dev/null
18538+++ b/fs/cifs/nterr.c
18539@@ -0,0 +1,687 @@
18540+/*
18541+ * Unix SMB/Netbios implementation.
18542+ * Version 1.9.
18543+ * RPC Pipe client / server routines
18544+ * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
18545+ *
18546+ * This program is free software; you can redistribute it and/or modify
18547+ * it under the terms of the GNU General Public License as published by
18548+ * the Free Software Foundation; either version 2 of the License, or
18549+ * (at your option) any later version.
18550+ *
18551+ * This program is distributed in the hope that it will be useful,
18552+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18553+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18554+ * GNU General Public License for more details.
18555+ *
18556+ * You should have received a copy of the GNU General Public License
18557+ * along with this program; if not, write to the Free Software
18558+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18559+ */
18560+
18561+/* NT error codes - see nterr.h */
18562+#include <linux/types.h>
18563+#include <linux/fs.h>
18564+#include "nterr.h"
18565+
18566+const struct nt_err_code_struct nt_errs[] = {
18567+ {"NT_STATUS_OK", NT_STATUS_OK},
18568+ {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
18569+ {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
18570+ {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
18571+ {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
18572+ {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
18573+ {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
18574+ {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
18575+ {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
18576+ {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
18577+ {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
18578+ {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
18579+ {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
18580+ {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
18581+ {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
18582+ {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
18583+ {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
18584+ {"NT_STATUS_INVALID_DEVICE_REQUEST",
18585+ NT_STATUS_INVALID_DEVICE_REQUEST},
18586+ {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
18587+ {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
18588+ {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
18589+ {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
18590+ {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
18591+ {"NT_STATUS_MORE_PROCESSING_REQUIRED",
18592+ NT_STATUS_MORE_PROCESSING_REQUIRED},
18593+ {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
18594+ {"NT_STATUS_CONFLICTING_ADDRESSES",
18595+ NT_STATUS_CONFLICTING_ADDRESSES},
18596+ {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
18597+ {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
18598+ {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
18599+ NT_STATUS_UNABLE_TO_DELETE_SECTION},
18600+ {"NT_STATUS_INVALID_SYSTEM_SERVICE",
18601+ NT_STATUS_INVALID_SYSTEM_SERVICE},
18602+ {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
18603+ {"NT_STATUS_INVALID_LOCK_SEQUENCE",
18604+ NT_STATUS_INVALID_LOCK_SEQUENCE},
18605+ {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
18606+ {"NT_STATUS_INVALID_FILE_FOR_SECTION",
18607+ NT_STATUS_INVALID_FILE_FOR_SECTION},
18608+ {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
18609+ {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
18610+ {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
18611+ {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
18612+ {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
18613+ NT_STATUS_NONCONTINUABLE_EXCEPTION},
18614+ {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
18615+ {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
18616+ {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
18617+ {"NT_STATUS_INVALID_UNWIND_TARGET",
18618+ NT_STATUS_INVALID_UNWIND_TARGET},
18619+ {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
18620+ {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
18621+ {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
18622+ NT_STATUS_UNABLE_TO_DECOMMIT_VM},
18623+ {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
18624+ {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
18625+ NT_STATUS_INVALID_PORT_ATTRIBUTES},
18626+ {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
18627+ NT_STATUS_PORT_MESSAGE_TOO_LONG},
18628+ {"NT_STATUS_INVALID_PARAMETER_MIX",
18629+ NT_STATUS_INVALID_PARAMETER_MIX},
18630+ {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
18631+ {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
18632+ {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
18633+ {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
18634+ NT_STATUS_OBJECT_NAME_NOT_FOUND},
18635+ {"NT_STATUS_OBJECT_NAME_COLLISION",
18636+ NT_STATUS_OBJECT_NAME_COLLISION},
18637+ {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
18638+ {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
18639+ {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
18640+ NT_STATUS_DEVICE_ALREADY_ATTACHED},
18641+ {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
18642+ {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
18643+ NT_STATUS_OBJECT_PATH_NOT_FOUND},
18644+ {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
18645+ NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
18646+ {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
18647+ {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
18648+ {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
18649+ {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
18650+ {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
18651+ {"NT_STATUS_PORT_CONNECTION_REFUSED",
18652+ NT_STATUS_PORT_CONNECTION_REFUSED},
18653+ {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
18654+ {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
18655+ {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
18656+ {"NT_STATUS_INVALID_PAGE_PROTECTION",
18657+ NT_STATUS_INVALID_PAGE_PROTECTION},
18658+ {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
18659+ {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
18660+ NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
18661+ {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
18662+ {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
18663+ {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
18664+ NT_STATUS_SUSPEND_COUNT_EXCEEDED},
18665+ {"NT_STATUS_THREAD_IS_TERMINATING",
18666+ NT_STATUS_THREAD_IS_TERMINATING},
18667+ {"NT_STATUS_BAD_WORKING_SET_LIMIT",
18668+ NT_STATUS_BAD_WORKING_SET_LIMIT},
18669+ {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
18670+ NT_STATUS_INCOMPATIBLE_FILE_MAP},
18671+ {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
18672+ {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
18673+ {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
18674+ {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
18675+ {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
18676+ {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
18677+ {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
18678+ {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
18679+ {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
18680+ {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
18681+ NT_STATUS_CTL_FILE_NOT_SUPPORTED},
18682+ {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
18683+ {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
18684+ {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
18685+ {"NT_STATUS_INVALID_PRIMARY_GROUP",
18686+ NT_STATUS_INVALID_PRIMARY_GROUP},
18687+ {"NT_STATUS_NO_IMPERSONATION_TOKEN",
18688+ NT_STATUS_NO_IMPERSONATION_TOKEN},
18689+ {"NT_STATUS_CANT_DISABLE_MANDATORY",
18690+ NT_STATUS_CANT_DISABLE_MANDATORY},
18691+ {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
18692+ {"NT_STATUS_NO_SUCH_LOGON_SESSION",
18693+ NT_STATUS_NO_SUCH_LOGON_SESSION},
18694+ {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
18695+ {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
18696+ {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
18697+ {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
18698+ {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
18699+ {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
18700+ {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
18701+ {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
18702+ {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
18703+ {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
18704+ {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
18705+ {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
18706+ {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
18707+ {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
18708+ {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
18709+ {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
18710+ {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
18711+ {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
18712+ {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
18713+ {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
18714+ {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
18715+ NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
18716+ {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
18717+ {"NT_STATUS_INVALID_SUB_AUTHORITY",
18718+ NT_STATUS_INVALID_SUB_AUTHORITY},
18719+ {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
18720+ {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
18721+ {"NT_STATUS_INVALID_SECURITY_DESCR",
18722+ NT_STATUS_INVALID_SECURITY_DESCR},
18723+ {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
18724+ {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
18725+ {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
18726+ {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
18727+ {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
18728+ {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
18729+ {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
18730+ {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
18731+ {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
18732+ NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
18733+ {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
18734+ {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
18735+ {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
18736+ {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
18737+ {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
18738+ {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
18739+ {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
18740+ NT_STATUS_RESOURCE_DATA_NOT_FOUND},
18741+ {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
18742+ NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
18743+ {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
18744+ NT_STATUS_RESOURCE_NAME_NOT_FOUND},
18745+ {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
18746+ NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
18747+ {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
18748+ NT_STATUS_FLOAT_DENORMAL_OPERAND},
18749+ {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
18750+ {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
18751+ {"NT_STATUS_FLOAT_INVALID_OPERATION",
18752+ NT_STATUS_FLOAT_INVALID_OPERATION},
18753+ {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
18754+ {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
18755+ {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
18756+ {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
18757+ NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
18758+ {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
18759+ {"NT_STATUS_PRIVILEGED_INSTRUCTION",
18760+ NT_STATUS_PRIVILEGED_INSTRUCTION},
18761+ {"NT_STATUS_TOO_MANY_PAGING_FILES",
18762+ NT_STATUS_TOO_MANY_PAGING_FILES},
18763+ {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
18764+ {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
18765+ NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
18766+ {"NT_STATUS_INSUFFICIENT_RESOURCES",
18767+ NT_STATUS_INSUFFICIENT_RESOURCES},
18768+ {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
18769+ {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
18770+ {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
18771+ {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
18772+ {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
18773+ {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
18774+ {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
18775+ {"NT_STATUS_MEDIA_WRITE_PROTECTED",
18776+ NT_STATUS_MEDIA_WRITE_PROTECTED},
18777+ {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
18778+ {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
18779+ NT_STATUS_INVALID_GROUP_ATTRIBUTES},
18780+ {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
18781+ NT_STATUS_BAD_IMPERSONATION_LEVEL},
18782+ {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
18783+ {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
18784+ {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
18785+ {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
18786+ NT_STATUS_BAD_MASTER_BOOT_RECORD},
18787+ {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
18788+ NT_STATUS_INSTRUCTION_MISALIGNMENT},
18789+ {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
18790+ NT_STATUS_INSTANCE_NOT_AVAILABLE},
18791+ {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
18792+ {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
18793+ {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
18794+ {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
18795+ {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
18796+ {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
18797+ {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
18798+ {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
18799+ {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
18800+ {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
18801+ {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
18802+ {"NT_STATUS_PROFILING_NOT_STARTED",
18803+ NT_STATUS_PROFILING_NOT_STARTED},
18804+ {"NT_STATUS_PROFILING_NOT_STOPPED",
18805+ NT_STATUS_PROFILING_NOT_STOPPED},
18806+ {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
18807+ {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
18808+ {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
18809+ {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
18810+ {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
18811+ {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
18812+ {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
18813+ {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
18814+ NT_STATUS_DEVICE_DOES_NOT_EXIST},
18815+ {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
18816+ {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
18817+ NT_STATUS_ADAPTER_HARDWARE_ERROR},
18818+ {"NT_STATUS_INVALID_NETWORK_RESPONSE",
18819+ NT_STATUS_INVALID_NETWORK_RESPONSE},
18820+ {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
18821+ NT_STATUS_UNEXPECTED_NETWORK_ERROR},
18822+ {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
18823+ {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
18824+ {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
18825+ {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
18826+ {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
18827+ {"NT_STATUS_NETWORK_ACCESS_DENIED",
18828+ NT_STATUS_NETWORK_ACCESS_DENIED},
18829+ {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
18830+ {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
18831+ {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
18832+ {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
18833+ {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
18834+ {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
18835+ {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
18836+ {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
18837+ {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
18838+ {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
18839+ {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
18840+ {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
18841+ NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
18842+ {"NT_STATUS_NO_SECURITY_ON_OBJECT",
18843+ NT_STATUS_NO_SECURITY_ON_OBJECT},
18844+ {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
18845+ {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
18846+ {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
18847+ NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
18848+ {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
18849+ {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
18850+ {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
18851+ {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
18852+ {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
18853+ {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
18854+ {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
18855+ NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
18856+ {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
18857+ {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
18858+ NT_STATUS_INVALID_OPLOCK_PROTOCOL},
18859+ {"NT_STATUS_INTERNAL_DB_CORRUPTION",
18860+ NT_STATUS_INTERNAL_DB_CORRUPTION},
18861+ {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
18862+ {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
18863+ {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
18864+ NT_STATUS_BAD_DESCRIPTOR_FORMAT},
18865+ {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
18866+ {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
18867+ {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
18868+ NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
18869+ {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
18870+ NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
18871+ {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
18872+ NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
18873+ {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
18874+ {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
18875+ {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
18876+ {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
18877+ {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
18878+ {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
18879+ {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
18880+ {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
18881+ {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
18882+ {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
18883+ {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
18884+ {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
18885+ {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
18886+ {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
18887+ {"NT_STATUS_REDIRECTOR_NOT_STARTED",
18888+ NT_STATUS_REDIRECTOR_NOT_STARTED},
18889+ {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
18890+ {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
18891+ {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
18892+ {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
18893+ {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
18894+ {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
18895+ {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
18896+ {"NT_STATUS_BAD_LOGON_SESSION_STATE",
18897+ NT_STATUS_BAD_LOGON_SESSION_STATE},
18898+ {"NT_STATUS_LOGON_SESSION_COLLISION",
18899+ NT_STATUS_LOGON_SESSION_COLLISION},
18900+ {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
18901+ {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
18902+ {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
18903+ {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
18904+ {"NT_STATUS_PROCESS_IS_TERMINATING",
18905+ NT_STATUS_PROCESS_IS_TERMINATING},
18906+ {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
18907+ {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
18908+ {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
18909+ {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
18910+ {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
18911+ {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
18912+ {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
18913+ NT_STATUS_ABIOS_LID_ALREADY_OWNED},
18914+ {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
18915+ {"NT_STATUS_ABIOS_INVALID_COMMAND",
18916+ NT_STATUS_ABIOS_INVALID_COMMAND},
18917+ {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
18918+ {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
18919+ NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
18920+ {"NT_STATUS_ABIOS_INVALID_SELECTOR",
18921+ NT_STATUS_ABIOS_INVALID_SELECTOR},
18922+ {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
18923+ {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
18924+ {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
18925+ {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
18926+ NT_STATUS_INVALID_LDT_DESCRIPTOR},
18927+ {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
18928+ NT_STATUS_INVALID_IMAGE_NE_FORMAT},
18929+ {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
18930+ {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
18931+ {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
18932+ NT_STATUS_MAPPED_FILE_SIZE_ZERO},
18933+ {"NT_STATUS_TOO_MANY_OPENED_FILES",
18934+ NT_STATUS_TOO_MANY_OPENED_FILES},
18935+ {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
18936+ {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
18937+ {"NT_STATUS_INVALID_COMPUTER_NAME",
18938+ NT_STATUS_INVALID_COMPUTER_NAME},
18939+ {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
18940+ {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
18941+ {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
18942+ {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
18943+ {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
18944+ NT_STATUS_MEMBERS_PRIMARY_GROUP},
18945+ {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
18946+ {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
18947+ {"NT_STATUS_THREAD_NOT_IN_PROCESS",
18948+ NT_STATUS_THREAD_NOT_IN_PROCESS},
18949+ {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
18950+ {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
18951+ NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
18952+ {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
18953+ {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
18954+ NT_STATUS_INVALID_IMAGE_LE_FORMAT},
18955+ {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
18956+ {"NT_STATUS_INVALID_IMAGE_PROTECT",
18957+ NT_STATUS_INVALID_IMAGE_PROTECT},
18958+ {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
18959+ {"NT_STATUS_LOGON_SERVER_CONFLICT",
18960+ NT_STATUS_LOGON_SERVER_CONFLICT},
18961+ {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
18962+ NT_STATUS_TIME_DIFFERENCE_AT_DC},
18963+ {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
18964+ NT_STATUS_SYNCHRONIZATION_REQUIRED},
18965+ {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
18966+ {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
18967+ {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
18968+ {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
18969+ {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
18970+ {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
18971+ {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
18972+ {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
18973+ {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
18974+ {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
18975+ {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
18976+ {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
18977+ {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
18978+ {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
18979+ {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
18980+ {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
18981+ {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
18982+ {"NT_STATUS_PAGEFILE_CREATE_FAILED",
18983+ NT_STATUS_PAGEFILE_CREATE_FAILED},
18984+ {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
18985+ {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
18986+ {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
18987+ {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
18988+ NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
18989+ {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
18990+ {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
18991+ {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
18992+ {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
18993+ {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
18994+ {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
18995+ NT_STATUS_SERIAL_NO_DEVICE_INITED},
18996+ {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
18997+ {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
18998+ {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
18999+ {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
19000+ {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
19001+ {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
19002+ {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
19003+ {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
19004+ {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
19005+ {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
19006+ {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
19007+ NT_STATUS_LOGON_TYPE_NOT_GRANTED},
19008+ {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
19009+ {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
19010+ NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
19011+ {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
19012+ NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
19013+ {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
19014+ {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
19015+ NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
19016+ {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
19017+ {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
19018+ {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
19019+ {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
19020+ {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
19021+ NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
19022+ {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
19023+ NT_STATUS_FLOPPY_WRONG_CYLINDER},
19024+ {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
19025+ {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
19026+ {"NT_STATUS_DISK_RECALIBRATE_FAILED",
19027+ NT_STATUS_DISK_RECALIBRATE_FAILED},
19028+ {"NT_STATUS_DISK_OPERATION_FAILED",
19029+ NT_STATUS_DISK_OPERATION_FAILED},
19030+ {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
19031+ {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
19032+ {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
19033+ {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
19034+ {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
19035+ {"NT_STATUS_DEVICE_NOT_PARTITIONED",
19036+ NT_STATUS_DEVICE_NOT_PARTITIONED},
19037+ {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
19038+ {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
19039+ NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
19040+ {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
19041+ {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
19042+ {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
19043+ {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
19044+ {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
19045+ {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
19046+ {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
19047+ {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
19048+ NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
19049+ {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
19050+ {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
19051+ NT_STATUS_CHILD_MUST_BE_VOLATILE},
19052+ {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
19053+ NT_STATUS_DEVICE_CONFIGURATION_ERROR},
19054+ {"NT_STATUS_DRIVER_INTERNAL_ERROR",
19055+ NT_STATUS_DRIVER_INTERNAL_ERROR},
19056+ {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
19057+ {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
19058+ {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
19059+ NT_STATUS_DEVICE_PROTOCOL_ERROR},
19060+ {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
19061+ {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
19062+ {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
19063+ {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
19064+ {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
19065+ {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
19066+ NT_STATUS_TRUSTED_DOMAIN_FAILURE},
19067+ {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
19068+ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
19069+ {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
19070+ NT_STATUS_EVENTLOG_FILE_CORRUPT},
19071+ {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
19072+ {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
19073+ {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
19074+ NT_STATUS_MUTANT_LIMIT_EXCEEDED},
19075+ {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
19076+ {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
19077+ {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
19078+ {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
19079+ NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
19080+ {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
19081+ {"NT_STATUS_EVENTLOG_FILE_CHANGED",
19082+ NT_STATUS_EVENTLOG_FILE_CHANGED},
19083+ {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
19084+ NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
19085+ {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
19086+ NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
19087+ {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
19088+ NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
19089+ {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
19090+ NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
19091+ {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
19092+ {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
19093+ {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
19094+ {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
19095+ NT_STATUS_RESOURCE_LANG_NOT_FOUND},
19096+ {"NT_STATUS_INSUFF_SERVER_RESOURCES",
19097+ NT_STATUS_INSUFF_SERVER_RESOURCES},
19098+ {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
19099+ {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
19100+ NT_STATUS_INVALID_ADDRESS_COMPONENT},
19101+ {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
19102+ NT_STATUS_INVALID_ADDRESS_WILDCARD},
19103+ {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
19104+ {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
19105+ NT_STATUS_ADDRESS_ALREADY_EXISTS},
19106+ {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
19107+ {"NT_STATUS_CONNECTION_DISCONNECTED",
19108+ NT_STATUS_CONNECTION_DISCONNECTED},
19109+ {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
19110+ {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
19111+ {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
19112+ {"NT_STATUS_TRANSACTION_TIMED_OUT",
19113+ NT_STATUS_TRANSACTION_TIMED_OUT},
19114+ {"NT_STATUS_TRANSACTION_NO_RELEASE",
19115+ NT_STATUS_TRANSACTION_NO_RELEASE},
19116+ {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
19117+ {"NT_STATUS_TRANSACTION_RESPONDED",
19118+ NT_STATUS_TRANSACTION_RESPONDED},
19119+ {"NT_STATUS_TRANSACTION_INVALID_ID",
19120+ NT_STATUS_TRANSACTION_INVALID_ID},
19121+ {"NT_STATUS_TRANSACTION_INVALID_TYPE",
19122+ NT_STATUS_TRANSACTION_INVALID_TYPE},
19123+ {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
19124+ {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
19125+ {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
19126+ NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
19127+ {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
19128+ {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
19129+ NT_STATUS_SYSTEM_PROCESS_TERMINATED},
19130+ {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
19131+ {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
19132+ NT_STATUS_NO_BROWSER_SERVERS_FOUND},
19133+ {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
19134+ {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
19135+ NT_STATUS_DRIVER_CANCEL_TIMEOUT},
19136+ {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
19137+ NT_STATUS_REPLY_MESSAGE_MISMATCH},
19138+ {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
19139+ {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
19140+ NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
19141+ {"NT_STATUS_LOST_WRITEBEHIND_DATA",
19142+ NT_STATUS_LOST_WRITEBEHIND_DATA},
19143+ {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
19144+ NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
19145+ {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
19146+ {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
19147+ {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
19148+ {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
19149+ {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
19150+ {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
19151+ {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
19152+ {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
19153+ {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
19154+ {"NT_STATUS_RETRY", NT_STATUS_RETRY},
19155+ {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
19156+ {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
19157+ {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
19158+ {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
19159+ {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
19160+ {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
19161+ NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
19162+ {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
19163+ {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
19164+ {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
19165+ {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
19166+ {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
19167+ NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
19168+ {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
19169+ NT_STATUS_ADDRESS_NOT_ASSOCIATED},
19170+ {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
19171+ {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
19172+ {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
19173+ {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
19174+ {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
19175+ {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
19176+ {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
19177+ {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
19178+ {"NT_STATUS_BAD_COMPRESSION_BUFFER",
19179+ NT_STATUS_BAD_COMPRESSION_BUFFER},
19180+ {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
19181+ {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
19182+ {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
19183+ NT_STATUS_TIMER_RESOLUTION_NOT_SET},
19184+ {"NT_STATUS_CONNECTION_COUNT_LIMIT",
19185+ NT_STATUS_CONNECTION_COUNT_LIMIT},
19186+ {"NT_STATUS_LOGIN_TIME_RESTRICTION",
19187+ NT_STATUS_LOGIN_TIME_RESTRICTION},
19188+ {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
19189+ NT_STATUS_LOGIN_WKSTA_RESTRICTION},
19190+ {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
19191+ {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
19192+ NT_STATUS_INSUFFICIENT_LOGON_INFO},
19193+ {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
19194+ {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
19195+ NT_STATUS_BAD_SERVICE_ENTRYPOINT},
19196+ {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
19197+ {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
19198+ {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
19199+ {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
19200+ {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
19201+ {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
19202+ {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
19203+ NT_STATUS_LICENSE_QUOTA_EXCEEDED},
19204+ {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
19205+ {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
19206+ {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
19207+ {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
19208+ {"NT_STATUS_UNSUPPORTED_COMPRESSION",
19209+ NT_STATUS_UNSUPPORTED_COMPRESSION},
19210+ {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
19211+ {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
19212+ NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
19213+ {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
19214+ NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
19215+ {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
19216+ NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
19217+ {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
19218+ {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
19219+ {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
19220+ NT_STATUS_QUOTA_LIST_INCONSISTENT},
19221+ {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
19222+ {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
19223+ {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
19224+ {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
19225+ {NULL, 0}
19226+};
19227--- /dev/null
19228+++ b/fs/cifs/nterr.h
19229@@ -0,0 +1,556 @@
19230+/*
19231+ Unix SMB/Netbios implementation.
19232+ Version 1.9.
19233+ NT error code constants
19234+ Copyright (C) Andrew Tridgell 1992-2000
19235+ Copyright (C) John H Terpstra 1996-2000
19236+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
19237+ Copyright (C) Paul Ashton 1998-2000
19238+
19239+ This program is free software; you can redistribute it and/or modify
19240+ it under the terms of the GNU General Public License as published by
19241+ the Free Software Foundation; either version 2 of the License, or
19242+ (at your option) any later version.
19243+
19244+ This program is distributed in the hope that it will be useful,
19245+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19246+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19247+ GNU General Public License for more details.
19248+
19249+ You should have received a copy of the GNU General Public License
19250+ along with this program; if not, write to the Free Software
19251+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19252+*/
19253+
19254+
19255+
19256+#ifndef _NTERR_H
19257+#define _NTERR_H
19258+
19259+struct nt_err_code_struct {
19260+ char *nt_errstr;
19261+ __u32 nt_errcode;
19262+};
19263+
19264+extern const struct nt_err_code_struct nt_errs[];
19265+
19266+/* Win32 Status codes. */
19267+
19268+#define STATUS_BUFFER_OVERFLOW 0x80000005
19269+#define STATUS_MORE_ENTRIES 0x0105
19270+#define ERROR_INVALID_PARAMETER 0x0057
19271+#define ERROR_INSUFFICIENT_BUFFER 0x007a
19272+#define STATUS_1804 0x070c
19273+#define STATUS_NOTIFY_ENUM_DIR 0x010c
19274+
19275+/* Win32 Error codes extracted using a loop in smbclient then printing a
19276+ netmon sniff to a file. */
19277+
19278+#define NT_STATUS_OK 0x0000
19279+#define STATUS_SOME_UNMAPPED 0x0107
19280+#define STATUS_BUFFER_OVERFLOW 0x80000005
19281+#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
19282+#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
19283+#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
19284+#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
19285+#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
19286+#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
19287+#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
19288+#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
19289+#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
19290+#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
19291+#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
19292+#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
19293+#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
19294+#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
19295+#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
19296+#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
19297+#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
19298+#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
19299+#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
19300+#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
19301+#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
19302+#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
19303+#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
19304+#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
19305+#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
19306+#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
19307+#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
19308+#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
19309+#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
19310+#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
19311+#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
19312+#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
19313+#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
19314+#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
19315+#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
19316+#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
19317+#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
19318+#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
19319+#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
19320+#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
19321+#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
19322+#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
19323+#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
19324+#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
19325+#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
19326+#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
19327+#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
19328+#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
19329+#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
19330+#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
19331+#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
19332+#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
19333+#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
19334+#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
19335+#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
19336+#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
19337+#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
19338+#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
19339+#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
19340+#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
19341+#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
19342+#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
19343+#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
19344+#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
19345+#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
19346+#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
19347+#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
19348+#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
19349+#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
19350+#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
19351+#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
19352+#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
19353+#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
19354+#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
19355+#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
19356+#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
19357+#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
19358+#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
19359+#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
19360+#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
19361+#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
19362+#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
19363+#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
19364+#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
19365+#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
19366+#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
19367+#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
19368+#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
19369+#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
19370+#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
19371+#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
19372+#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
19373+#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
19374+#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
19375+#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
19376+#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
19377+#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
19378+#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
19379+#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
19380+#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
19381+#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
19382+#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
19383+#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
19384+#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
19385+#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
19386+#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
19387+#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
19388+#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
19389+#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
19390+#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
19391+#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
19392+#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
19393+#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
19394+#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
19395+#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
19396+#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
19397+#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
19398+#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
19399+#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
19400+#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
19401+#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
19402+#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
19403+#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
19404+#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
19405+#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
19406+#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
19407+#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
19408+#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
19409+#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
19410+#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
19411+#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
19412+#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
19413+#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
19414+#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
19415+#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
19416+#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
19417+#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
19418+#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
19419+#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
19420+#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
19421+#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
19422+#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
19423+#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
19424+#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
19425+#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
19426+#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
19427+#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
19428+#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
19429+#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
19430+#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
19431+#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
19432+#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
19433+#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
19434+#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
19435+#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
19436+#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
19437+#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
19438+#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
19439+#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
19440+#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
19441+#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
19442+#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
19443+#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
19444+#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
19445+#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
19446+#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
19447+#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
19448+#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
19449+#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
19450+#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
19451+#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
19452+#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
19453+#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
19454+#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
19455+#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
19456+#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
19457+#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
19458+#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
19459+#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
19460+#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
19461+#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
19462+#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
19463+#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
19464+#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
19465+#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
19466+#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
19467+#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
19468+#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
19469+#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
19470+#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
19471+#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
19472+#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
19473+#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
19474+#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
19475+#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
19476+#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
19477+#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
19478+#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
19479+#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
19480+#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
19481+#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
19482+#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
19483+#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
19484+#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
19485+#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
19486+#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
19487+#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
19488+#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
19489+#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
19490+#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
19491+#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
19492+#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
19493+#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
19494+#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
19495+#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
19496+#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
19497+#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
19498+#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
19499+#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
19500+#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
19501+#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
19502+#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
19503+#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
19504+#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
19505+#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
19506+#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
19507+#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
19508+#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
19509+#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
19510+#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
19511+#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
19512+#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
19513+#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
19514+#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
19515+#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
19516+#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
19517+#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
19518+#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
19519+#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
19520+#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
19521+#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
19522+#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
19523+#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
19524+#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
19525+#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
19526+#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
19527+#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
19528+#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
19529+#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
19530+#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
19531+#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
19532+#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
19533+#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
19534+#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
19535+#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
19536+#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
19537+#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
19538+#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
19539+#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
19540+#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
19541+#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
19542+#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
19543+#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
19544+#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
19545+#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
19546+#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
19547+#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
19548+#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
19549+#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
19550+#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
19551+#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
19552+#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
19553+#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
19554+#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
19555+#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
19556+#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
19557+#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
19558+#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
19559+#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
19560+#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
19561+#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
19562+#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
19563+#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
19564+#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
19565+#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
19566+#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
19567+#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
19568+#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
19569+#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
19570+#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
19571+#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
19572+#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
19573+#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
19574+#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
19575+#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
19576+#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
19577+#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
19578+#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
19579+#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
19580+#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
19581+#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
19582+#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
19583+#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
19584+#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
19585+#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
19586+#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
19587+#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
19588+#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
19589+#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
19590+#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
19591+#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
19592+#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
19593+#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
19594+#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
19595+#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
19596+#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
19597+#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
19598+#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
19599+#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
19600+#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
19601+#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
19602+#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
19603+#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
19604+#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
19605+#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
19606+#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
19607+#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
19608+#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
19609+#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
19610+#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
19611+#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
19612+#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
19613+#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
19614+#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
19615+#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
19616+#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
19617+#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
19618+#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
19619+#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
19620+#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
19621+#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
19622+#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
19623+#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
19624+#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
19625+#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
19626+#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
19627+#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
19628+#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
19629+#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
19630+#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
19631+#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
19632+#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
19633+#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
19634+#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
19635+#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
19636+#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
19637+#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
19638+#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
19639+#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
19640+#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
19641+#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
19642+#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
19643+#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
19644+#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
19645+#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
19646+#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
19647+#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
19648+#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
19649+#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
19650+#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
19651+#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
19652+#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
19653+#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
19654+#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
19655+#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
19656+#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
19657+#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
19658+#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
19659+#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
19660+#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
19661+#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
19662+#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
19663+#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
19664+#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
19665+#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
19666+#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
19667+#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
19668+#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
19669+#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
19670+#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
19671+#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
19672+#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
19673+#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
19674+#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
19675+#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
19676+#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
19677+#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
19678+#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
19679+#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
19680+#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
19681+#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
19682+#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
19683+#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
19684+#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
19685+#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
19686+#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
19687+#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
19688+#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
19689+#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
19690+#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
19691+#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
19692+#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
19693+#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
19694+#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
19695+#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
19696+#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
19697+#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
19698+#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
19699+#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
19700+#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
19701+#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
19702+#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
19703+#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
19704+#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
19705+#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
19706+#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
19707+#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
19708+#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
19709+#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
19710+#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
19711+#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
19712+#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
19713+#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
19714+#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
19715+#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
19716+#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
19717+#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
19718+#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
19719+#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
19720+#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
19721+#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
19722+#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
19723+#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
19724+#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
19725+#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
19726+#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
19727+#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
19728+#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
19729+#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
19730+#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
19731+#define NT_STATUS_RETRY 0xC0000000 | 0x022d
19732+#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
19733+#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
19734+#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
19735+#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
19736+#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
19737+#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
19738+#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
19739+#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
19740+#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
19741+#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
19742+#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
19743+#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
19744+#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
19745+#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
19746+#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
19747+#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
19748+#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
19749+#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
19750+#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
19751+#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
19752+#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
19753+#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
19754+#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
19755+#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
19756+#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
19757+#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
19758+#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
19759+#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
19760+#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
19761+#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
19762+#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
19763+#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
19764+#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
19765+#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
19766+#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
19767+#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
19768+#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
19769+#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
19770+#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
19771+#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
19772+#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
19773+#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
19774+#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
19775+#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
19776+#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
19777+#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
19778+#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
19779+#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
19780+#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
19781+#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
19782+#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
19783+#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
19784+
19785+#endif /* _NTERR_H */
19786--- /dev/null
19787+++ b/fs/cifs/ntlmssp.h
19788@@ -0,0 +1,101 @@
19789+/*
19790+ * fs/cifs/ntlmssp.h
19791+ *
19792+ * Copyright (c) International Business Machines Corp., 2002
19793+ * Author(s): Steve French (sfrench@us.ibm.com)
19794+ *
19795+ * This library is free software; you can redistribute it and/or modify
19796+ * it under the terms of the GNU Lesser General Public License as published
19797+ * by the Free Software Foundation; either version 2.1 of the License, or
19798+ * (at your option) any later version.
19799+ *
19800+ * This library is distributed in the hope that it will be useful,
19801+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19802+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19803+ * the GNU Lesser General Public License for more details.
19804+ *
19805+ * You should have received a copy of the GNU Lesser General Public License
19806+ * along with this library; if not, write to the Free Software
19807+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19808+ */
19809+
19810+#pragma pack(1)
19811+
19812+#define NTLMSSP_SIGNATURE "NTLMSSP"
19813+/* Message Types */
19814+#define NtLmNegotiate 1
19815+#define NtLmChallenge 2
19816+#define NtLmAuthenticate 3
19817+#define UnknownMessage 8
19818+
19819+/* Negotiate Flags */
19820+#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
19821+#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
19822+#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
19823+#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
19824+#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
19825+#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
19826+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
19827+#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
19828+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
19829+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
19830+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
19831+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
19832+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
19833+#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
19834+#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
19835+#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
19836+#define NTLMSSP_REQUEST_INIT_RESP 0x100000
19837+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
19838+#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
19839+#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
19840+#define NTLMSSP_NEGOTIATE_128 0x20000000
19841+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
19842+#define NTLMSSP_NEGOTIATE_56 0x80000000
19843+
19844+/* Although typedefs are not commonly used for structure definitions */
19845+/* in the Linux kernel, in this particular case they are useful */
19846+/* to more closely match the standards document for NTLMSSP from */
19847+/* OpenGroup and to make the code more closely match the standard in */
19848+/* appearance */
19849+
19850+typedef struct _SECURITY_BUFFER {
19851+ __u16 Length;
19852+ __u16 MaximumLength;
19853+ __u32 Buffer; /* offset to buffer */
19854+} SECURITY_BUFFER;
19855+
19856+typedef struct _NEGOTIATE_MESSAGE {
19857+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19858+ __u32 MessageType; /* 1 */
19859+ __u32 NegotiateFlags;
19860+ SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
19861+ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
19862+ char DomainString[0];
19863+ /* followed by WorkstationString */
19864+} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
19865+
19866+typedef struct _CHALLENGE_MESSAGE {
19867+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19868+ __u32 MessageType; /* 2 */
19869+ SECURITY_BUFFER TargetName;
19870+ __u32 NegotiateFlags;
19871+ __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
19872+ __u8 Reserved[8];
19873+ SECURITY_BUFFER TargetInfoArray;
19874+} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
19875+
19876+typedef struct _AUTHENTICATE_MESSAGE {
19877+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19878+ __u32 MessageType; /* 3 */
19879+ SECURITY_BUFFER LmChallengeResponse;
19880+ SECURITY_BUFFER NtChallengeResponse;
19881+ SECURITY_BUFFER DomainName;
19882+ SECURITY_BUFFER UserName;
19883+ SECURITY_BUFFER WorkstationName;
19884+ SECURITY_BUFFER SessionKey;
19885+ __u32 NegotiateFlags;
19886+ char UserString[0];
19887+} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
19888+
19889+#pragma pack() /* resume default structure packing */
19890--- /dev/null
19891+++ b/fs/cifs/README
19892@@ -0,0 +1,356 @@
19893+The CIFS VFS support for Linux supports many advanced network filesystem
19894+features such as heirarchical dfs like namespace, hardlinks, locking and more.
19895+It was designed to comply with the SNIA CIFS Technical Reference (which
19896+supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
19897+practical interoperability with Windows 2000, Windows XP, Samba and equivalent
19898+servers.
19899+
19900+For questions or bug reports please contact:
19901+ sfrench@samba.org (sfrench@us.ibm.com)
19902+
19903+Build instructions:
19904+==================
19905+For Linux 2.4:
19906+1) Get the kernel source (e.g.from http://www.kernel.org)
19907+and download the cifs vfs source (see the project page
19908+at http://us1.samba.org/samba/Linux_CIFS_client.html)
19909+and change directory into the top of the kernel directory
19910+then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
19911+to add the cifs vfs to your kernel configure options if
19912+it has not already been added (e.g. current SuSE and UL
19913+users do not need to apply the cifs_24.patch since the cifs vfs is
19914+already in the kernel configure menu) and then
19915+mkdir linux/fs/cifs and then copy the current cifs vfs files from
19916+the cifs download to your kernel build directory e.g.
19917+
19918+ cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
19919+
19920+2) make menuconfig (or make xconfig)
19921+3) select cifs from within the network filesystem choices
19922+4) save and exit
19923+5) make dep
19924+6) make modules (or "make" if CIFS VFS not to be built as a module)
19925+
19926+For Linux 2.5:
19927+1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
19928+at bk://linux.bkbits.net/linux-2.5) and change directory into the top
19929+of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
19930+2) make menuconfig (or make xconfig)
19931+3) select cifs from within the network filesystem choices
19932+4) save and exit
19933+5) make
19934+
19935+
19936+Installation instructions:
19937+=========================
19938+If you have built the CIFS vfs as module (successfully) simply
19939+type "make modules_install" (or if you prefer, manually copy the file to
19940+the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
19941+
19942+If you have built the CIFS vfs into the kernel itself, follow the instructions
19943+for your distribution on how to install a new kernel (usually you
19944+would simply type "make install").
19945+
19946+If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
19947+the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
19948+similar files reside (usually /sbin). Although the helper software is not
19949+required, mount.cifs is recommended. Eventually the Samba 3.0 utility program
19950+"net" may also be helpful since it may someday provide easier mount syntax for
19951+users who are used to Windows e.g. net use <mount point> <UNC name or cifs URL>
19952+Note that running the Winbind pam/nss module (logon service) on all of your
19953+Linux clients is useful in mapping Uids and Gids consistently across the
19954+domain to the proper network user. The mount.cifs mount helper can be
19955+trivially built from Samba 3.0 or later source e.g. by executing:
19956+
19957+ gcc samba/source/client/mount.cifs.c -o mount.cifs
19958+
19959+Note that when the mount.cifs utility is run suid (allowing user mounts),
19960+in order to reduce risks, the "nosuid" mount flag is passed in on mount to
19961+disallow execution of an suid program mounted on the remote target.
19962+When mount is executed as root, nosuid is not passed in by default,
19963+and execution of suid programs on the remote target would be enabled
19964+by default. This can be changed, as with nfs and other filesystems,
19965+by simply specifying "nosuid" among the mount options. For user mounts
19966+though to be able to pass the suid flag to mount requires rebuilding
19967+mount.cifs with the following flag:
19968+
19969+ gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
19970+
19971+There is a corresponding manual page for cifs mounting in the Samba 3.0 and
19972+later source tree in docs/manpages/mount.cifs.8
19973+
19974+Samba Considerations
19975+====================
19976+To get the maximum benefit from the CIFS VFS, we recommend using a server that
19977+supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
19978+Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
19979+Note that uid, gid and file permissions will display default values if you do
19980+not have a server that supports the Unix extensions for CIFS (such as Samba
19981+2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
19982+the line:
19983+
19984+ unix extensions = yes
19985+
19986+to your smb.conf file on the server. Note that the following smb.conf settings
19987+are also useful (on the Samba server) when the majority of clients are Unix or
19988+Linux:
19989+
19990+ case sensitive = yes
19991+ delete readonly = yes
19992+ ea support = yes
19993+
19994+Note that ea support is required for supporting Linux xattrs.
19995+Some administrators also change the "map archive" and the "create mask"
19996+parameters from their default values. Creating special devices (mknod)
19997+remotely may require specifying a mkdev function to Samba if you are not using
19998+Samba 3.0.5 or later. For more information on these see the manual pages
19999+("man smb.conf") on the Samba server system. Note that the cifs vfs,
20000+unlike the smbfs vfs, does not read the smb.conf on the client system
20001+(the few optional settings are passed in on mount via -o parameters instead).
20002+Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
20003+open files (required for strict POSIX compliance). Windows Servers already
20004+supported this feature. Samba server does not allow symlinks that refer to files
20005+outside of the share, so in Samba versions prior to 3.0.5, most symlinks to
20006+files with absolute paths (ie beginning with slash) such as:
20007+ ln -s /mnt/foo bar
20008+would be forbidden. Samba 3.0.5 server or later includes the ability to create
20009+such symlinks safely by converting unsafe symlinks (ie symlinks to server
20010+files that are outside of the share) to a samba specific format on the server
20011+that is ignored by local server applications and non-cifs clients and that will
20012+not be traversed by the Samba server). This is opaque to the Linux client
20013+application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
20014+later, but only for remote clients using the CIFS Unix extensions, and will
20015+be invisbile to Windows clients and typically will not affect local
20016+applications running on the same server as Samba.
20017+
20018+Use instructions:
20019+================
20020+Once the CIFS VFS support is built into the kernel or installed as a module
20021+(cifs.o), you can use mount syntax like the following to access Samba or Windows
20022+servers:
20023+
20024+ mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
20025+
20026+Before -o the option -v may be specified to make the mount.cifs
20027+mount helper display the mount steps more verbosely.
20028+After -o the following commonly used cifs vfs specific options
20029+are supported:
20030+
20031+ user=<username>
20032+ pass=<password>
20033+ domain=<domain name>
20034+
20035+Other cifs mount options are described below. Use of TCP names (in addition to
20036+ip addresses) is available if the mount helper (mount.cifs) is installed. If
20037+you do not trust the server to which are mounted, or if you do not have
20038+cifs signing enabled (and the physical network is insecure), consider use
20039+of the standard mount options "noexec" and "nosuid" to reduce the risk of
20040+running an altered binary on your local system (downloaded from a hostile server
20041+or altered by a hostile router).
20042+
20043+When using the mount helper mount.cifs, passwords may be specified via alternate
20044+mechanisms, instead of specifying it after -o using the normal "pass=" syntax
20045+on the command line:
20046+1) By including it in a credential file. Specify credentials=filename as one
20047+of the mount options. Credential files contain two lines
20048+ username=someuser
20049+ password=your_password
20050+2) By specifying the password in the PASSWD environment variable (similarly
20051+the user name can be taken from the USER environment variable).
20052+3) By specifying the password in a file by name via PASSWD_FILE
20053+4) By specifying the password in a file by file descriptor via PASSWD_FD
20054+
20055+If no password is provided, mount.cifs will prompt for password entry
20056+
20057+Restrictions
20058+============
20059+Servers must support the NTLM SMB dialect (which is the most recent, supported
20060+by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
20061+Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
20062+1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
20063+problem as most servers support this. IPv6 support is planned for the future.
20064+
20065+CIFS VFS Mount Options
20066+======================
20067+A partial list of the supported mount options follows:
20068+ user The user name to use when trying to establish
20069+ the CIFS session.
20070+ password The user password. If the mount helper is
20071+ installed, the user will be prompted for password
20072+ if it is not supplied.
20073+ ip The ip address of the target server
20074+ unc The target server Universal Network Name (export) to
20075+ mount.
20076+ domain Set the SMB/CIFS workgroup name prepended to the
20077+ username during CIFS session establishment
20078+ uid If CIFS Unix extensions are not supported by the server
20079+ this overrides the default uid for inodes. For mounts to
20080+ servers which do support the CIFS Unix extensions, such
20081+ as a properly configured Samba server, the server provides
20082+ the uid, gid and mode. For servers which do not support
20083+ the Unix extensions, the default uid (and gid) returned on
20084+ lookup of existing files is the uid (gid) of the person
20085+ who executed the mount (root, except when mount.cifs
20086+ is configured setuid for user mounts) unless the "uid="
20087+ (gid) mount option is specified. For the uid (gid) of newly
20088+ created files and directories, ie files created since
20089+ the last mount of the server share, the expected uid
20090+ (gid) is cached as as long as the inode remains in
20091+ memory on the client. Also note that permission
20092+ checks (authorization checks) on accesses to a file occur
20093+ at the server, but there are cases in which an administrator
20094+ may want to restrict at the client as well. For those
20095+ servers which do not report a uid/gid owner
20096+ (such as Windows), permissions can also be checked at the
20097+ client, and a crude form of client side permission checking
20098+ can be enabled by specifying file_mode and dir_mode on
20099+ the client
20100+ gid If CIFS Unix extensions are not supported by the server
20101+ this overrides the default gid for inodes.
20102+ file_mode If CIFS Unix extensions are not supported by the server
20103+ this overrides the default mode for file inodes.
20104+ dir_mode If CIFS Unix extensions are not supported by the server
20105+ this overrides the default mode for directory inodes.
20106+ port attempt to contact the server on this tcp port, before
20107+ trying the usual ports (port 445, then 139).
20108+ iocharset Codepage used to convert local path names to and from
20109+ Unicode. Unicode is used by default for network path
20110+ names if the server supports it. If iocharset is
20111+ not specified then the nls_default specified
20112+ during the local client kernel build will be used.
20113+ If server does not support Unicode, this parameter is
20114+ unused.
20115+ rsize default read size
20116+ wsize default write size
20117+ rw mount the network share read-write (note that the
20118+ server may still consider the share read-only)
20119+ ro mount network share read-only
20120+ version used to distinguish different versions of the
20121+ mount helper utility (not typically needed)
20122+ sep if first mount option (after the -o), overrides
20123+ the comma as the separator between the mount
20124+ parms. e.g.
20125+ -o user=myname,password=mypassword,domain=mydom
20126+ could be passed instead with period as the separator by
20127+ -o sep=.user=myname.password=mypassword.domain=mydom
20128+ this might be useful when comma is contained within username
20129+ or password or domain. This option is less important
20130+ when the cifs mount helper cifs.mount (version 1.1 or later)
20131+ is used.
20132+ nosuid Do not allow remote executables with the suid bit
20133+ program to be executed. This is only meaningful for mounts
20134+ to servers such as Samba which support the CIFS Unix Extensions.
20135+ If you do not trust the servers in your network (your mount
20136+ targets) it is recommended that you specify this option for
20137+ greater security.
20138+ suid Allow remote files on this mountpoint with suid enabled to
20139+ be executed (default for mounts when executed as root,
20140+ nosuid is default for user mounts).
20141+ credentials Although ignored by the cifs kernel component, it is used by
20142+ the mount helper, mount.cifs. When mount.cifs is installed it
20143+ opens and reads the credential file specified in order
20144+ to obtain the userid and password arguments which are passed to
20145+ the cifs vfs.
20146+ guest Although ignored by the kernel component, the mount.cifs
20147+ mount helper will not prompt the user for a password
20148+ if guest is specified on the mount options. If no
20149+ password is specified a null password will be used.
20150+
20151+The mount.cifs mount helper also accepts a few mount options before -o
20152+including:
20153+
20154+ -S take password from stdin (equivalent to setting the environment
20155+ variable "PASSWD_FD=0"
20156+ -V print mount.cifs version
20157+ -? display simple usage information
20158+
20159+With recent 2.6 kernel versions of modutils, the version of the cifs kernel
20160+module can be displayed via modinfo.
20161+
20162+Misc /proc/fs/cifs Flags and Debug Info
20163+=======================================
20164+Informational pseudo-files:
20165+DebugData Displays information about active CIFS sessions
20166+ and shares.
20167+Stats Lists summary resource usage information as well as per
20168+ share statistics, if CONFIG_CIFS_STATS in enabled
20169+ in the kernel configuration.
20170+
20171+Configuration pseudo-files:
20172+MultiuserMount If set to one, more than one CIFS session to
20173+ the same server ip address can be established
20174+ if more than one uid accesses the same mount
20175+ point and if the uids user/password mapping
20176+ information is available. (default is 0)
20177+PacketSigningEnabled If set to one, cifs packet signing is enabled
20178+ and will be used if the server requires
20179+ it. If set to two, cifs packet signing is
20180+ required even if the server considers packet
20181+ signing optional. (default 1)
20182+cifsFYI If set to one, additional debug information is
20183+ logged to the system error log. (default 0)
20184+ExtendedSecurity If set to one, SPNEGO session establishment
20185+ is allowed which enables more advanced
20186+ secure CIFS session establishment (default 0)
20187+NTLMV2Enabled If set to one, more secure password hashes
20188+ are used when the server supports them and
20189+ when kerberos is not negotiated (default 0)
20190+traceSMB If set to one, debug information is logged to the
20191+ system error log with the start of smb requests
20192+ and responses (default 0)
20193+LookupCacheEnable If set to one, inode information is kept cached
20194+ for one second improving performance of lookups
20195+ (default 1)
20196+OplockEnabled If set to one, safe distributed caching enabled.
20197+ (default 1)
20198+LinuxExtensionsEnabled If set to one then the client will attempt to
20199+ use the CIFS "UNIX" extensions which are optional
20200+ protocol enhancements that allow CIFS servers
20201+ to return accurate UID/GID information as well
20202+ as support symbolic links. If you use servers
20203+ such as Samba that support the CIFS Unix
20204+ extensions but do not want to use symbolic link
20205+ support and want to map the uid and gid fields
20206+ to values supplied at mount (rather than the
20207+ actual values, then set this to zero. (default 1)
20208+
20209+These experimental features and tracing can be enabled by changing flags in
20210+/proc/fs/cifs (after the cifs module has been installed or built into the
20211+kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
20212+tracing to the kernel message log type:
20213+
20214+ echo 1 > /proc/fs/cifs/cifsFYI
20215+
20216+and for more extensive tracing including the start of smb requests and responses
20217+
20218+ echo 1 > /proc/fs/cifs/traceSMB
20219+
20220+Three other experimental features are under development and to test
20221+require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
20222+
20223+ CONFIG_CIFS_QUOTA
20224+
20225+ CONFIG_CIFS_XATTR
20226+
20227+ CONFIG_CIFS_FCNTL (fcntl needed for support of directory change
20228+ notification and perhaps later for file leases)
20229+
20230+Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData
20231+if the kernel was configured with cifs statistics enabled. The statistics
20232+represent the number of successful (ie non-zero return code from the server)
20233+SMB responses to some of the more common commands (open, delete, mkdir etc.).
20234+Also recorded is the total bytes read and bytes written to the server for
20235+that share. Note that due to client caching effects this can be less than the
20236+number of bytes read and written by the application running on the client.
20237+The statistics for the number of total SMBs and oplock breaks are different in
20238+that they represent all for that share, not just those for which the server
20239+returned success.
20240+
20241+Also note that "cat /proc/fs/cifs/DebugData" will display information about
20242+the active sessions and the shares that are mounted. Note: NTLMv2 enablement
20243+will not work since they its implementation is not quite complete yet.
20244+Do not alter these configuration values unless you are doing specific testing.
20245+Enabling extended security works to Windows 2000 Workstations and XP but not to
20246+Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
20247+(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
20248+complete in the CIFS VFS yet).
20249--- /dev/null
20250+++ b/fs/cifs/rfc1002pdu.h
20251@@ -0,0 +1,79 @@
20252+/*
20253+ * fs/cifs/rfc1002pdu.h
20254+ *
20255+ * Protocol Data Unit definitions for RFC 1001/1002 support
20256+ *
20257+ * Copyright (c) International Business Machines Corp., 2004
20258+ * Author(s): Steve French (sfrench@us.ibm.com)
20259+ *
20260+ * This library is free software; you can redistribute it and/or modify
20261+ * it under the terms of the GNU Lesser General Public License as published
20262+ * by the Free Software Foundation; either version 2.1 of the License, or
20263+ * (at your option) any later version.
20264+ *
20265+ * This library is distributed in the hope that it will be useful,
20266+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20267+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20268+ * the GNU Lesser General Public License for more details.
20269+ *
20270+ * You should have received a copy of the GNU Lesser General Public License
20271+ * along with this library; if not, write to the Free Software
20272+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20273+ */
20274+
20275+#pragma pack(1)
20276+
20277+/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
20278+
20279+ /* RFC 1002 session packet types */
20280+#define RFC1002_SESSION_MESASAGE 0x00
20281+#define RFC1002_SESSION_REQUEST 0x81
20282+#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
20283+#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
20284+#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
20285+#define RFC1002_SESSION_KEEP_ALIVE 0x85
20286+
20287+ /* RFC 1002 flags (only one defined */
20288+#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
20289+
20290+struct rfc1002_session_packet {
20291+ __u8 type;
20292+ __u8 flags;
20293+ __u16 length;
20294+ union {
20295+ struct {
20296+ __u8 called_len;
20297+ __u8 called_name[32];
20298+ __u8 scope1; /* null */
20299+ __u8 calling_len;
20300+ __u8 calling_name[32];
20301+ __u8 scope2; /* null */
20302+ } session_req;
20303+ struct {
20304+ __u32 retarget_ip_addr;
20305+ __u16 port;
20306+ } retarget_resp;
20307+ __u8 neg_ses_resp_error_code;
20308+ /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
20309+ SESSION_KEEP_ALIVE packet also does not include a trailer.
20310+ Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
20311+ } trailer;
20312+};
20313+
20314+/* Negative Session Response error codes */
20315+#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
20316+#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
20317+#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
20318+#define RFC1002_INSUFFICIENT_RESOURCE 0x83
20319+#define RFC1002_UNSPECIFIED_ERROR 0x8F
20320+
20321+/* RFC 1002 Datagram service packets are not defined here as they
20322+are not needed for the network filesystem client unless we plan on
20323+implementing broadcast resolution of the server ip address (from
20324+server netbios name). Currently server names are resolved only via DNS
20325+(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
20326+
20327+#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
20328+
20329+#pragma pack() /* resume default structure packing */
20330+
20331--- /dev/null
20332+++ b/fs/cifs/smbdes.c
20333@@ -0,0 +1,408 @@
20334+/*
20335+ Unix SMB/Netbios implementation.
20336+ Version 1.9.
20337+
20338+ a partial implementation of DES designed for use in the
20339+ SMB authentication protocol
20340+
20341+ Copyright (C) Andrew Tridgell 1998
20342+ Modified by Steve French (sfrench@us.ibm.com) 2002,2004
20343+
20344+ This program is free software; you can redistribute it and/or modify
20345+ it under the terms of the GNU General Public License as published by
20346+ the Free Software Foundation; either version 2 of the License, or
20347+ (at your option) any later version.
20348+
20349+ This program is distributed in the hope that it will be useful,
20350+ but WITHOUT ANY WARRANTY; without even the implied warranty of
20351+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20352+ GNU General Public License for more details.
20353+
20354+ You should have received a copy of the GNU General Public License
20355+ along with this program; if not, write to the Free Software
20356+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20357+*/
20358+
20359+/* NOTES:
20360+
20361+ This code makes no attempt to be fast! In fact, it is a very
20362+ slow implementation
20363+
20364+ This code is NOT a complete DES implementation. It implements only
20365+ the minimum necessary for SMB authentication, as used by all SMB
20366+ products (including every copy of Microsoft Windows95 ever sold)
20367+
20368+ In particular, it can only do a unchained forward DES pass. This
20369+ means it is not possible to use this code for encryption/decryption
20370+ of data, instead it is only useful as a "hash" algorithm.
20371+
20372+ There is no entry point into this code that allows normal DES operation.
20373+
20374+ I believe this means that this code does not come under ITAR
20375+ regulations but this is NOT a legal opinion. If you are concerned
20376+ about the applicability of ITAR regulations to this code then you
20377+ should confirm it for yourself (and maybe let me know if you come
20378+ up with a different answer to the one above)
20379+*/
20380+#include <linux/slab.h>
20381+#define uchar unsigned char
20382+
20383+static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
20384+ 1, 58, 50, 42, 34, 26, 18,
20385+ 10, 2, 59, 51, 43, 35, 27,
20386+ 19, 11, 3, 60, 52, 44, 36,
20387+ 63, 55, 47, 39, 31, 23, 15,
20388+ 7, 62, 54, 46, 38, 30, 22,
20389+ 14, 6, 61, 53, 45, 37, 29,
20390+ 21, 13, 5, 28, 20, 12, 4
20391+};
20392+
20393+static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
20394+ 3, 28, 15, 6, 21, 10,
20395+ 23, 19, 12, 4, 26, 8,
20396+ 16, 7, 27, 20, 13, 2,
20397+ 41, 52, 31, 37, 47, 55,
20398+ 30, 40, 51, 45, 33, 48,
20399+ 44, 49, 39, 56, 34, 53,
20400+ 46, 42, 50, 36, 29, 32
20401+};
20402+
20403+static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
20404+ 60, 52, 44, 36, 28, 20, 12, 4,
20405+ 62, 54, 46, 38, 30, 22, 14, 6,
20406+ 64, 56, 48, 40, 32, 24, 16, 8,
20407+ 57, 49, 41, 33, 25, 17, 9, 1,
20408+ 59, 51, 43, 35, 27, 19, 11, 3,
20409+ 61, 53, 45, 37, 29, 21, 13, 5,
20410+ 63, 55, 47, 39, 31, 23, 15, 7
20411+};
20412+
20413+static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
20414+ 4, 5, 6, 7, 8, 9,
20415+ 8, 9, 10, 11, 12, 13,
20416+ 12, 13, 14, 15, 16, 17,
20417+ 16, 17, 18, 19, 20, 21,
20418+ 20, 21, 22, 23, 24, 25,
20419+ 24, 25, 26, 27, 28, 29,
20420+ 28, 29, 30, 31, 32, 1
20421+};
20422+
20423+static uchar perm5[32] = { 16, 7, 20, 21,
20424+ 29, 12, 28, 17,
20425+ 1, 15, 23, 26,
20426+ 5, 18, 31, 10,
20427+ 2, 8, 24, 14,
20428+ 32, 27, 3, 9,
20429+ 19, 13, 30, 6,
20430+ 22, 11, 4, 25
20431+};
20432+
20433+static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
20434+ 39, 7, 47, 15, 55, 23, 63, 31,
20435+ 38, 6, 46, 14, 54, 22, 62, 30,
20436+ 37, 5, 45, 13, 53, 21, 61, 29,
20437+ 36, 4, 44, 12, 52, 20, 60, 28,
20438+ 35, 3, 43, 11, 51, 19, 59, 27,
20439+ 34, 2, 42, 10, 50, 18, 58, 26,
20440+ 33, 1, 41, 9, 49, 17, 57, 25
20441+};
20442+
20443+static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
20444+
20445+static uchar sbox[8][4][16] = {
20446+ {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
20447+ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
20448+ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
20449+ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
20450+
20451+ {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
20452+ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
20453+ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
20454+ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
20455+
20456+ {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
20457+ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
20458+ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
20459+ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
20460+
20461+ {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
20462+ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
20463+ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
20464+ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
20465+
20466+ {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
20467+ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
20468+ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
20469+ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
20470+
20471+ {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
20472+ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
20473+ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
20474+ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
20475+
20476+ {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
20477+ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
20478+ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
20479+ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
20480+
20481+ {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
20482+ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
20483+ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
20484+ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
20485+};
20486+
20487+static void
20488+permute(char *out, char *in, uchar * p, int n)
20489+{
20490+ int i;
20491+ for (i = 0; i < n; i++)
20492+ out[i] = in[p[i] - 1];
20493+}
20494+
20495+static void
20496+lshift(char *d, int count, int n)
20497+{
20498+ char out[64];
20499+ int i;
20500+ for (i = 0; i < n; i++)
20501+ out[i] = d[(i + count) % n];
20502+ for (i = 0; i < n; i++)
20503+ d[i] = out[i];
20504+}
20505+
20506+static void
20507+concat(char *out, char *in1, char *in2, int l1, int l2)
20508+{
20509+ while (l1--)
20510+ *out++ = *in1++;
20511+ while (l2--)
20512+ *out++ = *in2++;
20513+}
20514+
20515+static void
20516+xor(char *out, char *in1, char *in2, int n)
20517+{
20518+ int i;
20519+ for (i = 0; i < n; i++)
20520+ out[i] = in1[i] ^ in2[i];
20521+}
20522+
20523+static void
20524+dohash(char *out, char *in, char *key, int forw)
20525+{
20526+ int i, j, k;
20527+ char *pk1;
20528+ char c[28];
20529+ char d[28];
20530+ char *cd;
20531+ char ki[16][48];
20532+ char *pd1;
20533+ char l[32], r[32];
20534+ char *rl;
20535+
20536+ /* Have to reduce stack usage */
20537+ pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
20538+ if(pk1 == NULL)
20539+ return;
20540+
20541+ cd = pk1 + 56;
20542+ pd1= cd + 56;
20543+ rl = pd1 + 64;
20544+
20545+ permute(pk1, key, perm1, 56);
20546+
20547+ for (i = 0; i < 28; i++)
20548+ c[i] = pk1[i];
20549+ for (i = 0; i < 28; i++)
20550+ d[i] = pk1[i + 28];
20551+
20552+ for (i = 0; i < 16; i++) {
20553+ lshift(c, sc[i], 28);
20554+ lshift(d, sc[i], 28);
20555+
20556+ concat(cd, c, d, 28, 28);
20557+ permute(ki[i], cd, perm2, 48);
20558+ }
20559+
20560+ permute(pd1, in, perm3, 64);
20561+
20562+ for (j = 0; j < 32; j++) {
20563+ l[j] = pd1[j];
20564+ r[j] = pd1[j + 32];
20565+ }
20566+
20567+ for (i = 0; i < 16; i++) {
20568+ char *er; /* er[48] */
20569+ char *erk; /* erk[48] */
20570+ char b[8][6];
20571+ char *cb; /* cb[32] */
20572+ char *pcb; /* pcb[32] */
20573+ char *r2; /* r2[32] */
20574+
20575+ er = kmalloc(48+48+32+32+32, GFP_KERNEL);
20576+ if(er == NULL) {
20577+ kfree(pk1);
20578+ return;
20579+ }
20580+ erk = er+48;
20581+ cb = erk+48;
20582+ pcb = cb+32;
20583+ r2 = pcb+32;
20584+
20585+ permute(er, r, perm4, 48);
20586+
20587+ xor(erk, er, ki[forw ? i : 15 - i], 48);
20588+
20589+ for (j = 0; j < 8; j++)
20590+ for (k = 0; k < 6; k++)
20591+ b[j][k] = erk[j * 6 + k];
20592+
20593+ for (j = 0; j < 8; j++) {
20594+ int m, n;
20595+ m = (b[j][0] << 1) | b[j][5];
20596+
20597+ n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
20598+ 1) | b[j][4];
20599+
20600+ for (k = 0; k < 4; k++)
20601+ b[j][k] =
20602+ (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
20603+ }
20604+
20605+ for (j = 0; j < 8; j++)
20606+ for (k = 0; k < 4; k++)
20607+ cb[j * 4 + k] = b[j][k];
20608+ permute(pcb, cb, perm5, 32);
20609+
20610+ xor(r2, l, pcb, 32);
20611+
20612+ for (j = 0; j < 32; j++)
20613+ l[j] = r[j];
20614+
20615+ for (j = 0; j < 32; j++)
20616+ r[j] = r2[j];
20617+
20618+ kfree(er);
20619+ }
20620+
20621+ concat(rl, r, l, 32, 32);
20622+
20623+ permute(out, rl, perm6, 64);
20624+ kfree(pk1);
20625+}
20626+
20627+static void
20628+str_to_key(unsigned char *str, unsigned char *key)
20629+{
20630+ int i;
20631+
20632+ key[0] = str[0] >> 1;
20633+ key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
20634+ key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
20635+ key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
20636+ key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
20637+ key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
20638+ key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
20639+ key[7] = str[6] & 0x7F;
20640+ for (i = 0; i < 8; i++) {
20641+ key[i] = (key[i] << 1);
20642+ }
20643+}
20644+
20645+static void
20646+smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
20647+{
20648+ int i;
20649+ char *outb; /* outb[64] */
20650+ char *inb; /* inb[64] */
20651+ char *keyb; /* keyb[64] */
20652+ unsigned char key2[8];
20653+
20654+ outb = kmalloc(64 * 3,GFP_KERNEL);
20655+ if(outb == NULL)
20656+ return;
20657+
20658+ inb = outb + 64;
20659+ keyb = inb + 64;
20660+
20661+ str_to_key(key, key2);
20662+
20663+ for (i = 0; i < 64; i++) {
20664+ inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
20665+ keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
20666+ outb[i] = 0;
20667+ }
20668+
20669+ dohash(outb, inb, keyb, forw);
20670+
20671+ for (i = 0; i < 8; i++) {
20672+ out[i] = 0;
20673+ }
20674+
20675+ for (i = 0; i < 64; i++) {
20676+ if (outb[i])
20677+ out[i / 8] |= (1 << (7 - (i % 8)));
20678+ }
20679+ kfree(outb);
20680+}
20681+
20682+void
20683+E_P16(unsigned char *p14, unsigned char *p16)
20684+{
20685+ unsigned char sp8[8] =
20686+ { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
20687+ smbhash(p16, sp8, p14, 1);
20688+ smbhash(p16 + 8, sp8, p14 + 7, 1);
20689+}
20690+
20691+void
20692+E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
20693+{
20694+ smbhash(p24, c8, p21, 1);
20695+ smbhash(p24 + 8, c8, p21 + 7, 1);
20696+ smbhash(p24 + 16, c8, p21 + 14, 1);
20697+}
20698+
20699+void
20700+D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
20701+{
20702+ smbhash(out, in, p14, 0);
20703+ smbhash(out + 8, in + 8, p14 + 7, 0);
20704+}
20705+
20706+void
20707+E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
20708+{
20709+ smbhash(out, in, p14, 1);
20710+ smbhash(out + 8, in + 8, p14 + 7, 1);
20711+}
20712+
20713+void
20714+cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
20715+{
20716+ unsigned char buf[8];
20717+
20718+ smbhash(buf, in, key, 1);
20719+ smbhash(out, buf, key + 9, 1);
20720+}
20721+
20722+void
20723+cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
20724+{
20725+ unsigned char buf[8];
20726+ static unsigned char key2[8];
20727+
20728+ smbhash(buf, in, key, 1);
20729+ key2[0] = key[7];
20730+ smbhash(out, buf, key2, 1);
20731+}
20732+
20733+void
20734+cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
20735+{
20736+ static unsigned char key2[8];
20737+
20738+ smbhash(out, in, key, forw);
20739+ key2[0] = key[7];
20740+ smbhash(out + 8, in + 8, key2, forw);
20741+}
20742--- /dev/null
20743+++ b/fs/cifs/smbencrypt.c
20744@@ -0,0 +1,295 @@
20745+/*
20746+ Unix SMB/Netbios implementation.
20747+ Version 1.9.
20748+ SMB parameters and setup
20749+ Copyright (C) Andrew Tridgell 1992-2000
20750+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
20751+ Modified by Jeremy Allison 1995.
20752+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
20753+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
20754+
20755+ This program is free software; you can redistribute it and/or modify
20756+ it under the terms of the GNU General Public License as published by
20757+ the Free Software Foundation; either version 2 of the License, or
20758+ (at your option) any later version.
20759+
20760+ This program is distributed in the hope that it will be useful,
20761+ but WITHOUT ANY WARRANTY; without even the implied warranty of
20762+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20763+ GNU General Public License for more details.
20764+
20765+ You should have received a copy of the GNU General Public License
20766+ along with this program; if not, write to the Free Software
20767+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20768+*/
20769+
20770+#include <linux/module.h>
20771+#include <linux/fs.h>
20772+#include <linux/string.h>
20773+#include <linux/kernel.h>
20774+#include <linux/random.h>
20775+#include "cifs_unicode.h"
20776+#include "cifspdu.h"
20777+#include "md5.h"
20778+#include "cifs_debug.h"
20779+
20780+#ifndef FALSE
20781+#define FALSE 0
20782+#endif
20783+#ifndef TRUE
20784+#define TRUE 1
20785+#endif
20786+
20787+/* following came from the other byteorder.h to avoid include conflicts */
20788+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
20789+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
20790+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
20791+
20792+/*The following definitions come from lib/md4.c */
20793+
20794+void mdfour(unsigned char *out, unsigned char *in, int n);
20795+
20796+/*The following definitions come from libsmb/smbdes.c */
20797+
20798+void E_P16(unsigned char *p14, unsigned char *p16);
20799+void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
20800+void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
20801+void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
20802+void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
20803+void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
20804+void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
20805+ int forw);
20806+
20807+/*The following definitions come from libsmb/smbencrypt.c */
20808+
20809+void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
20810+void E_md4hash(const unsigned char *passwd, unsigned char *p16);
20811+void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
20812+void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
20813+ unsigned char p24[24]);
20814+void NTLMSSPOWFencrypt(unsigned char passwd[8],
20815+ unsigned char *ntlmchalresp, unsigned char p24[24]);
20816+void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
20817+int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
20818+ int new_pwrd_size, __u32 * new_pw_len);
20819+
20820+/*
20821+ This implements the X/Open SMB password encryption
20822+ It takes a password, a 8 byte "crypt key" and puts 24 bytes of
20823+ encrypted password into p24 */
20824+/* Note that password must be uppercased and null terminated */
20825+void
20826+SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
20827+{
20828+ unsigned char p14[15], p21[21];
20829+
20830+ memset(p21, '\0', 21);
20831+ memset(p14, '\0', 14);
20832+ strncpy((char *) p14, (char *) passwd, 14);
20833+
20834+/* strupper((char *)p14); *//* BB at least uppercase the easy range */
20835+ E_P16(p14, p21);
20836+
20837+ SMBOWFencrypt(p21, c8, p24);
20838+
20839+ memset(p14,0,15);
20840+ memset(p21,0,21);
20841+}
20842+
20843+/* Routines for Windows NT MD4 Hash functions. */
20844+static int
20845+_my_wcslen(__u16 * str)
20846+{
20847+ int len = 0;
20848+ while (*str++ != 0)
20849+ len++;
20850+ return len;
20851+}
20852+
20853+/*
20854+ * Convert a string into an NT UNICODE string.
20855+ * Note that regardless of processor type
20856+ * this must be in intel (little-endian)
20857+ * format.
20858+ */
20859+
20860+static int
20861+_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
20862+{ /* not a very good conversion routine - change/fix */
20863+ int i;
20864+ __u16 val;
20865+
20866+ for (i = 0; i < len; i++) {
20867+ val = *src;
20868+ SSVAL(dst, 0, val);
20869+ dst++;
20870+ src++;
20871+ if (val == 0)
20872+ break;
20873+ }
20874+ return i;
20875+}
20876+
20877+/*
20878+ * Creates the MD4 Hash of the users password in NT UNICODE.
20879+ */
20880+
20881+void
20882+E_md4hash(const unsigned char *passwd, unsigned char *p16)
20883+{
20884+ int len;
20885+ __u16 wpwd[129];
20886+
20887+ /* Password cannot be longer than 128 characters */
20888+ if(passwd) {
20889+ len = strlen((char *) passwd);
20890+ if (len > 128) {
20891+ len = 128;
20892+ }
20893+ /* Password must be converted to NT unicode */
20894+ _my_mbstowcs(wpwd, passwd, len);
20895+ } else
20896+ len = 0;
20897+
20898+ wpwd[len] = 0; /* Ensure string is null terminated */
20899+ /* Calculate length in bytes */
20900+ len = _my_wcslen(wpwd) * sizeof (__u16);
20901+
20902+ mdfour(p16, (unsigned char *) wpwd, len);
20903+ memset(wpwd,0,129 * 2);
20904+}
20905+
20906+/* Does both the NT and LM owfs of a user's password */
20907+void
20908+nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
20909+{
20910+ char passwd[514];
20911+
20912+ memset(passwd, '\0', 514);
20913+ if (strlen(pwd) < 513)
20914+ strcpy(passwd, pwd);
20915+ else
20916+ memcpy(passwd, pwd, 512);
20917+ /* Calculate the MD4 hash (NT compatible) of the password */
20918+ memset(nt_p16, '\0', 16);
20919+ E_md4hash(passwd, nt_p16);
20920+
20921+ /* Mangle the passwords into Lanman format */
20922+ passwd[14] = '\0';
20923+/* strupper(passwd); */
20924+
20925+ /* Calculate the SMB (lanman) hash functions of the password */
20926+
20927+ memset(p16, '\0', 16);
20928+ E_P16((unsigned char *) passwd, (unsigned char *) p16);
20929+
20930+ /* clear out local copy of user's password (just being paranoid). */
20931+ memset(passwd, '\0', sizeof (passwd));
20932+}
20933+
20934+/* Does the NTLMv2 owfs of a user's password */
20935+void
20936+ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
20937+ const char *domain_n, unsigned char kr_buf[16],
20938+ const struct nls_table *nls_codepage)
20939+{
20940+ wchar_t * user_u;
20941+ wchar_t * dom_u;
20942+ int user_l, domain_l;
20943+ struct HMACMD5Context ctx;
20944+
20945+ /* might as well do one alloc to hold both (user_u and dom_u) */
20946+ user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
20947+ if(user_u == NULL)
20948+ return;
20949+ dom_u = user_u + 1024;
20950+
20951+ /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
20952+ push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
20953+
20954+ /* BB user and domain may need to be uppercased */
20955+ user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
20956+ domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
20957+
20958+ user_l++; /* trailing null */
20959+ domain_l++;
20960+
20961+ hmac_md5_init_limK_to_64(owf, 16, &ctx);
20962+ hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
20963+ hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
20964+ hmac_md5_final(kr_buf, &ctx);
20965+
20966+ kfree(user_u);
20967+}
20968+
20969+/* Does the des encryption from the NT or LM MD4 hash. */
20970+void
20971+SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
20972+ unsigned char p24[24])
20973+{
20974+ unsigned char p21[21];
20975+
20976+ memset(p21, '\0', 21);
20977+
20978+ memcpy(p21, passwd, 16);
20979+ E_P24(p21, c8, p24);
20980+}
20981+
20982+/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
20983+void
20984+NTLMSSPOWFencrypt(unsigned char passwd[8],
20985+ unsigned char *ntlmchalresp, unsigned char p24[24])
20986+{
20987+ unsigned char p21[21];
20988+
20989+ memset(p21, '\0', 21);
20990+ memcpy(p21, passwd, 8);
20991+ memset(p21 + 8, 0xbd, 8);
20992+
20993+ E_P24(p21, ntlmchalresp, p24);
20994+}
20995+
20996+/* Does the NT MD4 hash then des encryption. */
20997+
20998+void
20999+SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
21000+{
21001+ unsigned char p21[21];
21002+
21003+ memset(p21, '\0', 21);
21004+
21005+ E_md4hash(passwd, p21);
21006+ SMBOWFencrypt(p21, c8, p24);
21007+}
21008+
21009+/* Does the md5 encryption from the NT hash for NTLMv2. */
21010+void
21011+SMBOWFencrypt_ntv2(const unsigned char kr[16],
21012+ const struct data_blob * srv_chal,
21013+ const struct data_blob * cli_chal, unsigned char resp_buf[16])
21014+{
21015+ struct HMACMD5Context ctx;
21016+
21017+ hmac_md5_init_limK_to_64(kr, 16, &ctx);
21018+ hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
21019+ hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
21020+ hmac_md5_final(resp_buf, &ctx);
21021+}
21022+
21023+void
21024+SMBsesskeygen_ntv2(const unsigned char kr[16],
21025+ const unsigned char *nt_resp, __u8 sess_key[16])
21026+{
21027+ struct HMACMD5Context ctx;
21028+
21029+ hmac_md5_init_limK_to_64(kr, 16, &ctx);
21030+ hmac_md5_update(nt_resp, 16, &ctx);
21031+ hmac_md5_final((unsigned char *) sess_key, &ctx);
21032+}
21033+
21034+void
21035+SMBsesskeygen_ntv1(const unsigned char kr[16],
21036+ const unsigned char *nt_resp, __u8 sess_key[16])
21037+{
21038+ mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
21039+}
21040--- /dev/null
21041+++ b/fs/cifs/smberr.c
21042@@ -0,0 +1,240 @@
21043+/*
21044+ Unix SMB/Netbios implementation.
21045+ Version 1.9.
21046+ Copyright (C) Andrew Tridgell 1998
21047+ Copyright (C) Steve French (sfrench@us.ibm.com) 2002
21048+ This program is free software; you can redistribute it and/or modify
21049+ it under the terms of the GNU General Public License as published by
21050+ the Free Software Foundation; either version 2 of the License, or
21051+ (at your option) any later version.
21052+
21053+ This program is distributed in the hope that it will be useful,
21054+ but WITHOUT ANY WARRANTY; without even the implied warranty of
21055+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21056+ GNU General Public License for more details.
21057+
21058+ You should have received a copy of the GNU General Public License
21059+ along with this program; if not, write to the Free Software
21060+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21061+*/
21062+include "smberr.h"
21063+#define NO_SYSLOG
21064+/* error code stuff - put together by Merik Karman
21065+ merik@blackadder.dsh.oz.au */
21066+ typedef const struct {
21067+ char *name;
21068+ int code;
21069+ char *message;
21070+ int posix_code;
21071+} err_code_struct;
21072+
21073+/* Dos Error Messages */
21074+err_code_struct dos_msgs[] = {
21075+ {"ERRbadfunc", ERRbadfunc, "Invalid function.", -EINVAL},
21076+ {"ERRbadfile", ERRbadfile, "File not found.", -ENOENT},
21077+ {"ERRbadpath", ERRbadpath, "Directory invalid.", -ENOENT},
21078+ {"ERRnofids", ERRnofids, "No file descriptors available", -EMFILE},
21079+ {"ERRnoaccess", ERRnoaccess, "Access denied.", -EACCES},
21080+ {"ERRbadfid", ERRbadfid, "Invalid file handle.", -EBADF},
21081+ {"ERRbadmcb", 7, "Memory control blocks destroyed.", -EIO},
21082+ {"ERRnomem", ERRnomem,
21083+ "Insufficient server memory to perform the requested function.",
21084+ -ENOMEM},
21085+ {"ERRbadmem", ERRbadmem, "Invalid memory block address.", -EFAULT},
21086+ {"ERRbadenv", ERRbadenv, "Invalid environment.", -EFAULT},
21087+ {"ERRbadformat", 11, "Invalid format.", -EINVAL},
21088+ {"ERRbadaccess", ERRbadaccess, "Invalid open mode." - EACCES},
21089+ {"ERRbaddata", ERRbaddata, "Invalid data.", -EIO},
21090+ {"ERR", ERRres, "reserved.", -EIO},
21091+ {"ERRbaddrive", ERRbaddrive, "Invalid drive specified.", -ENXIO},
21092+ {"ERRremcd", ERRremcd,
21093+ "A Delete Directory request attempted to remove the server's current directory.",
21094+ -EIO},
21095+ {"ERRdiffdevice", ERRdiffdevice, "Not same device.", -EXDEV},
21096+ {"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 */
21097+ {"ERRbadshare", ERRbadshare,
21098+ "The sharing mode specified for an Open conflicts with existing FIDs on the file.",
21099+ -EXTBSY},
21100+ {"ERRlock", ERRlock,
21101+ "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.",
21102+ -EACCES},
21103+ {"ERRunsup", ERRunsup, "The operation is unsupported", -EINVAL},
21104+ {"ERRnosuchshare", ERRnosuchshare,
21105+ "You specified an invalid share name", -ENXIO},
21106+ {"ERRfilexists", ERRfilexists,
21107+ "The file named in a Create Directory, Make New File or Link request already exists.",
21108+ -EEXIST},
21109+ {"ERRinvalidname", ERRinvalidname, "Invalid name", -ENOENT},
21110+ {"ERRdiskfull", ERRdiskfull, "Disk full", -ENOSPC}
21111+
21112+ {"ERRmoredata", ERRmoredata,
21113+ "There is more data to be returned.",},
21114+ {"ERRinvgroup", 2455, "Invalid workgroup (try the -W option)"},
21115+ {NULL, -1, NULL, -EIO}
21116+};
21117+
21118+/* Server Error Messages */
21119+err_code_struct server_msgs[] = {
21120+ {"ERRerror", 1, "Non-specific error code."},
21121+ {"ERRbadpw", 2,
21122+ "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
21123+ {"ERRbadtype", 3, "reserved."},
21124+ {"ERRaccess", 4,
21125+ "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."},
21126+ {"ERRinvnid", 5,
21127+ "The tree ID (TID) specified in a command was invalid."},
21128+ {"ERRinvnetname", 6, "Invalid network name in tree connect."},
21129+ {"ERRinvdevice", 7,
21130+ "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
21131+ {"ERRqfull", 49,
21132+ "Print queue full (files) -- returned by open print file."},
21133+ {"ERRqtoobig", 50, "Print queue full -- no space."},
21134+ {"ERRqeof", 51, "EOF on print queue dump."},
21135+ {"ERRinvpfid", 52, "Invalid print file FID."},
21136+ {"ERRsmbcmd", 64,
21137+ "The server did not recognize the command received."},
21138+ {"ERRsrverror", 65,
21139+ "The server encountered an internal error, e.g., system file unavailable."},
21140+ {"ERRfilespecs", 67,
21141+ "The file handle (FID) and pathname parameters contained an invalid combination of values."},
21142+ {"ERRreserved", 68, "reserved."},
21143+ {"ERRbadpermits", 69,
21144+ "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
21145+ {"ERRreserved", 70, "reserved."},
21146+ {"ERRsetattrmode", 71,
21147+ "The attribute mode in the Set File Attribute request is invalid."},
21148+ {"ERRpaused", 81, "Server is paused."},
21149+ {"ERRmsgoff", 82, "Not receiving messages."},
21150+ {"ERRnoroom", 83, "No room to buffer message."},
21151+ {"ERRrmuns", 87, "Too many remote user names."},
21152+ {"ERRtimeout", 88, "Operation timed out."},
21153+ {"ERRnoresource", 89,
21154+ "No resources currently available for request."},
21155+ {"ERRtoomanyuids", 90, "Too many UIDs active on this session."},
21156+ {"ERRbaduid", 91,
21157+ "The UID is not known as a valid ID on this session."},
21158+ {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode."},
21159+ {"ERRusestd", 251,
21160+ "Temp unable to support Raw, use standard read/write."},
21161+ {"ERRcontmpx", 252, "Continue in MPX mode."},
21162+ {"ERRreserved", 253, "reserved."},
21163+ {"ERRreserved", 254, "reserved."},
21164+ {"ERRnosupport", 0xFFFF, "Function not supported."},
21165+ {NULL, -1, NULL}
21166+};
21167+
21168+/* Hard Error Messages */
21169+err_code_struct hard_msgs[] = {
21170+ {"ERRnowrite", 19,
21171+ "Attempt to write on write-protected diskette."},
21172+ {"ERRbadunit", 20, "Unknown unit."},
21173+ {"ERRnotready", 21, "Drive not ready."},
21174+ {"ERRbadcmd", 22, "Unknown command."},
21175+ {"ERRdata", 23, "Data error (CRC)."},
21176+ {"ERRbadreq", 24, "Bad request structure length."},
21177+ {"ERRseek", 25, "Seek error."},
21178+ {"ERRbadmedia", 26, "Unknown media type."},
21179+ {"ERRbadsector", 27, "Sector not found."},
21180+ {"ERRnopaper", 28, "Printer out of paper."},
21181+ {"ERRwrite", 29, "Write fault."},
21182+ {"ERRread", 30, "Read fault."},
21183+ {"ERRgeneral", 31, "General failure."},
21184+ {"ERRbadshare", 32, "An open conflicts with an existing open."},
21185+ {"ERRlock", 33,
21186+ "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."},
21187+ {"ERRwrongdisk", 34, "The wrong disk was found in a drive."},
21188+ {"ERRFCBUnavail", 35, "No FCBs are available to process request."},
21189+ {"ERRsharebufexc", 36, "A sharing buffer has been exceeded."},
21190+ {NULL, -1, NULL}
21191+};
21192+
21193+
21194+const struct {
21195+ int code;
21196+ char *class;
21197+ err_code_struct *err_msgs;
21198+} err_classes[] = {
21199+ {
21200+ 0, "SUCCESS", NULL}, {
21201+ 0x01, "ERRDOS", dos_msgs}, {
21202+ 0x02, "ERRSRV", server_msgs}, {
21203+ 0x03, "ERRHRD", hard_msgs}, {
21204+ 0x04, "ERRXOS", NULL}, {
21205+ 0xE1, "ERRRMX1", NULL}, {
21206+ 0xE2, "ERRRMX2", NULL}, {
21207+ 0xE3, "ERRRMX3", NULL}, {
21208+ 0xFF, "ERRCMD", NULL}, {
21209+-1, NULL, NULL}};
21210+
21211+
21212+/****************************************************************************
21213+return a SMB error string from a SMB buffer
21214+****************************************************************************/
21215+char *smb_dos_errstr(char *inbuf)
21216+{
21217+ static pstring ret;
21218+ int class = CVAL(inbuf, smb_rcls);
21219+ int num = SVAL(inbuf, smb_err);
21220+ int i, j;
21221+
21222+ for (i = 0; err_classes[i].class; i++)
21223+ if (err_classes[i].code == class) {
21224+ if (err_classes[i].err_msgs) {
21225+ err_code_struct *err =
21226+ err_classes[i].err_msgs;
21227+ for (j = 0; err[j].name; j++)
21228+ if (num == err[j].code) {
21229+ if (DEBUGLEVEL > 0)
21230+ slprintf(ret,
21231+ sizeof
21232+ (ret) - 1,
21233+ "%s - %s (%s)",
21234+ err_classes
21235+ [i].class,
21236+ err[j].
21237+ name,
21238+ err[j].
21239+ message);
21240+ else
21241+ slprintf(ret,
21242+ sizeof
21243+ (ret) - 1,
21244+ "%s - %s",
21245+ err_classes
21246+ [i].class,
21247+ err[j].
21248+ name);
21249+ return ret;
21250+ }
21251+ }
21252+
21253+ slprintf(ret, sizeof(ret) - 1, "%s - %d",
21254+ err_classes[i].class, num);
21255+ return ret;
21256+ }
21257+
21258+ slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",
21259+ class, num);
21260+ return (ret);
21261+}
21262+
21263+
21264+/*****************************************************************************
21265+ returns an WERROR error message.
21266+ *****************************************************************************/
21267+char *werror_str(WERROR status)
21268+{
21269+ static fstring msg;
21270+ slprintf(msg, sizeof(msg), "WIN32 code 0x%08x", W_ERROR_V(status));
21271+ return msg;
21272+}
21273+
21274+
21275+/*****************************************************************************
21276+map a unix errno to a win32 error
21277+ *****************************************************************************/
21278+WERROR map_werror_from_unix(int error)
21279+{
21280+ NTSTATUS status = map_nt_error_from_unix(error);
21281+ return ntstatus_to_werror(status);
21282+}
21283--- /dev/null
21284+++ b/fs/cifs/smberr.h
21285@@ -0,0 +1,113 @@
21286+/*
21287+ * fs/cifs/smberr.h
21288+ *
21289+ * Copyright (c) International Business Machines Corp., 2002
21290+ * Author(s): Steve French (sfrench@us.ibm.com)
21291+ *
21292+ * See Error Codes section of the SNIA CIFS Specification
21293+ * for more information
21294+ *
21295+ * This library is free software; you can redistribute it and/or modify
21296+ * it under the terms of the GNU Lesser General Public License as published
21297+ * by the Free Software Foundation; either version 2.1 of the License, or
21298+ * (at your option) any later version.
21299+ *
21300+ * This library is distributed in the hope that it will be useful,
21301+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21302+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21303+ * the GNU Lesser General Public License for more details.
21304+ *
21305+ * You should have received a copy of the GNU Lesser General Public License
21306+ * along with this library; if not, write to the Free Software
21307+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21308+ */
21309+
21310+#define SUCCESS 0 /* The request was successful. */
21311+#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
21312+#define ERRSRV 0x02 /* Error is generated by the file server daemon */
21313+#define ERRHRD 0x03 /* Error is a hardware error. */
21314+#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
21315+
21316+/* The following error codes may be generated with the SUCCESS error class.*/
21317+
21318+#define SUCCESS 0 /* The request was successful. */
21319+
21320+/* The following error codes may be generated with the ERRDOS error class.*/
21321+
21322+#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. */
21323+#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */
21324+#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */
21325+#define ERRnofids 4 /* Too many open files. The server has no file handles available. */
21326+#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 */
21327+#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */
21328+#define ERRbadmcb 7 /* Memory control blocks destroyed. */
21329+#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */
21330+#define ERRbadmem 9 /* Invalid memory block address. */
21331+#define ERRbadenv 10 /* Invalid environment. */
21332+#define ERRbadformat 11 /* Invalid format. */
21333+#define ERRbadaccess 12 /* Invalid open mode. */
21334+#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */
21335+#define ERRbaddrive 15 /* Invalid drive specified. */
21336+#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */
21337+#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */
21338+#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */
21339+#define ERRgeneral 31
21340+#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
21341+#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. */
21342+#define ERRunsup 50
21343+#define ERRnosuchshare 67
21344+#define ERRfilexists 80 /* The file named in the request already exists. */
21345+#define ERRinvparm 87
21346+#define ERRdiskfull 112
21347+#define ERRinvname 123
21348+#define ERRdirnotempty 145
21349+#define ERRnotlocked 158
21350+#define ERRalreadyexists 183
21351+#define ERRbadpipe 230
21352+#define ERRpipebusy 231
21353+#define ERRpipeclosing 232
21354+#define ERRnotconnected 233
21355+#define ERRmoredata 234
21356+#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
21357+#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
21358+ was not a link. */
21359+
21360+/* Following error codes may be generated with the ERRSRV error
21361+class.*/
21362+
21363+#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. */
21364+#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
21365+#define ERRbadtype 3 /* used for indicating DFS referral needed */
21366+#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */
21367+#define ERRinvtid 5 /* The Tid specified in a command was invalid. */
21368+#define ERRinvnetname 6 /* Invalid network name in tree connect. */
21369+#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
21370+#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */
21371+#define ERRqtoobig 50 /* Print queue full -- no space. */
21372+#define ERRqeof 51 /* EOF on print queue dump */
21373+#define ERRinvpfid 52 /* Invalid print file FID. */
21374+#define ERRsmbcmd 64 /* The server did not recognize the command received. */
21375+#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */
21376+#define ERRbadBID 66 /* (obsolete) */
21377+#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */
21378+#define ERRbadLink 68 /* (obsolete) */
21379+#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */
21380+#define ERRbadPID 70
21381+#define ERRsetattrmode 71 /* attribute (mode) is invalid */
21382+#define ERRpaused 81 /* Server is paused */
21383+#define ERRmsgoff 82 /* reserved - messaging off */
21384+#define ERRnoroom 83 /* reserved - no room for message */
21385+#define ERRrmuns 87 /* reserved - too many remote names */
21386+#define ERRtimeout 88 /* operation timed out */
21387+#define ERRnoresource 89 /* No resources available for request */
21388+#define ERRtoomanyuids 90 /* Too many UIDs active on this session */
21389+#define ERRbaduid 91 /* The UID is not known as a valid user */
21390+#define ERRusempx 250 /* temporarily unable to use raw */
21391+#define ERRusestd 251 /* temporarily unable to use either raw or mpx */
21392+#define ERR_NOTIFY_ENUM_DIR 1024
21393+#define ERRaccountexpired 2239
21394+#define ERRbadclient 2240
21395+#define ERRbadLogonTime 2241
21396+#define ERRpasswordExpired 2242
21397+#define ERRnetlogonNotStarted 2455
21398+#define ERRnosupport 0xFFFF
21399--- /dev/null
21400+++ b/fs/cifs/TODO
21401@@ -0,0 +1,106 @@
21402+version 1.16 May 27, 2004
21403+
21404+A Partial List of Missing Features
21405+==================================
21406+
21407+Contributions are welcome. There are plenty of opportunities
21408+for visible, important contributions to this module. Here
21409+is a partial list of the known problems and missing features:
21410+
21411+a) Support for SecurityDescriptors for chmod/chgrp/chown so
21412+these can be supported for Windows servers
21413+
21414+b) Better pam/winbind integration
21415+
21416+c) multi-user mounts - multiplexed sessionsetups over single vc
21417+(ie tcp session) - prettying up needed
21418+
21419+d) Kerberos/SPNEGO session setup support - (started)
21420+
21421+e) NTLMv2 authentication (mostly implemented)
21422+
21423+f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
21424+used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
21425+and raw NTLMSSP already. This is important when enabling
21426+extended security and mounting to Windows 2003 Servers
21427+
21428+f) Directory entry caching relies on a 1 second timer, rather than
21429+using FindNotify or equivalent. - (started)
21430+
21431+g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
21432+style byte range lock differences
21433+
21434+h) quota support
21435+
21436+i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
21437+which will allow us to expose dos attributes as well as real
21438+ACLs. This support has been started in the current code, but is
21439+ifdeffed out.
21440+
21441+k) finish writepages support (multi-page write behind for improved
21442+performance) and syncpage
21443+
21444+l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
21445+extra copy in/out of the socket buffers in some cases.
21446+
21447+m) finish support for IPv6. This is mostly complete but
21448+needs a simple inet_pton like function to convert ipv6
21449+addresses in string representation.
21450+
21451+o) Better optimize open (and pathbased setfilesize) to reduce the
21452+oplock breaks coming from windows srv. Piggyback identical file
21453+opens on top of each other by incrementing reference count rather
21454+than resending (helps reduce server resource utilization and avoid
21455+spurious oplock breaks).
21456+
21457+p) Improve performance of readpages by sending more than one read
21458+at a time when 8 pages or more are requested. Evaluate whether
21459+reads larger than 16K would be helpful.
21460+
21461+q) For support of Windows9x/98 we need to retry failed mounts
21462+to *SMBSERVER (default server name) with the uppercase hostname
21463+in the RFC1001 session_init request.
21464+
21465+r) Add Extended Attributed support (for storing UID/GID info
21466+to Windows servers)
21467+
21468+s) Finish fcntl D_NOTIFY support so kde and gnome file list windows
21469+will autorefresh
21470+
21471+t) Add GUI tool to configure /proc/fs/cifs settings and for display of
21472+the CIFS statistics
21473+
21474+KNOWN BUGS (updated May 27, 2004)
21475+====================================
21476+1) existing symbolic links (Windows reparse points) are recognized but
21477+can not be created remotely. They are implemented for Samba and those that
21478+support the CIFS Unix extensions but Samba has a bug currently handling
21479+symlink text beginning with slash
21480+2) follow_link and readdir code does not follow dfs junctions
21481+but recognizes them
21482+3) create of new files to FAT partitions on Windows servers can
21483+succeed but still return access denied (appears to be Windows
21484+server not cifs client problem) and has not been reproduced recently.
21485+NTFS partitions do not have this problem.
21486+4) debug connectathon lock test case 10 which fails against
21487+Samba (may be unmappable due to POSIX to Windows lock model
21488+differences but worth investigating). Also debug Samba to
21489+see why lock test case 7 takes longer to complete to Samba
21490+than to Windows.
21491+
21492+Misc testing to do
21493+==================
21494+1) check out max path names and max path name components against various server
21495+types. Try nested symlinks. Return max path name in stat -f information
21496+
21497+2) Modify file portion of ltp so it can run against a mounted network
21498+share and run it against cifs vfs.
21499+
21500+3) Additional performance testing and optimization using iozone and similar -
21501+there are some easy changes that can be done to parallelize sequential writes,
21502+and when signing is disabled to request larger read sizes (larger than
21503+negotiated size) and send larger write sizes to modern servers.
21504+
21505+4) More exhaustively test the recently added NT4 support against various
21506+NT4 service pack levels.
21507+
21508--- /dev/null
21509+++ b/fs/cifs/transport.c
21510@@ -0,0 +1,434 @@
21511+/*
21512+ * fs/cifs/transport.c
21513+ *
21514+ * Copyright (C) International Business Machines Corp., 2002,2004
21515+ * Author(s): Steve French (sfrench@us.ibm.com)
21516+ *
21517+ * This library is free software; you can redistribute it and/or modify
21518+ * it under the terms of the GNU Lesser General Public License as published
21519+ * by the Free Software Foundation; either version 2.1 of the License, or
21520+ * (at your option) any later version.
21521+ *
21522+ * This library is distributed in the hope that it will be useful,
21523+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21524+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21525+ * the GNU Lesser General Public License for more details.
21526+ *
21527+ * You should have received a copy of the GNU Lesser General Public License
21528+ * along with this library; if not, write to the Free Software
21529+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21530+ */
21531+
21532+#include <linux/fs.h>
21533+#include <linux/list.h>
21534+#include <linux/wait.h>
21535+#include <linux/net.h>
21536+#include <linux/version.h>
21537+#include <asm/uaccess.h>
21538+#include <asm/processor.h>
21539+#include "cifspdu.h"
21540+#include "cifsglob.h"
21541+#include "cifsproto.h"
21542+#include "cifs_debug.h"
21543+
21544+extern kmem_cache_t *cifs_mid_cachep;
21545+extern kmem_cache_t *cifs_oplock_cachep;
21546+
21547+struct mid_q_entry *
21548+AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
21549+{
21550+ struct mid_q_entry *temp;
21551+
21552+ if (ses == NULL) {
21553+ cERROR(1, ("Null session passed in to AllocMidQEntry "));
21554+ return NULL;
21555+ }
21556+ if (ses->server == NULL) {
21557+ cERROR(1, ("Null TCP session in AllocMidQEntry"));
21558+ return NULL;
21559+ }
21560+
21561+ temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
21562+ SLAB_KERNEL);
21563+ if (temp == NULL)
21564+ return temp;
21565+ else {
21566+ memset(temp, 0, sizeof (struct mid_q_entry));
21567+ temp->mid = smb_buffer->Mid; /* always LE */
21568+ temp->pid = current->pid;
21569+ temp->command = smb_buffer->Command;
21570+ cFYI(1, ("For smb_command %d", temp->command));
21571+ do_gettimeofday(&temp->when_sent);
21572+ temp->ses = ses;
21573+ temp->tsk = current;
21574+ }
21575+
21576+ spin_lock(&GlobalMid_Lock);
21577+ list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
21578+ atomic_inc(&midCount);
21579+ temp->midState = MID_REQUEST_ALLOCATED;
21580+ spin_unlock(&GlobalMid_Lock);
21581+ return temp;
21582+}
21583+
21584+void
21585+DeleteMidQEntry(struct mid_q_entry *midEntry)
21586+{
21587+ spin_lock(&GlobalMid_Lock);
21588+ midEntry->midState = MID_FREE;
21589+ list_del(&midEntry->qhead);
21590+ atomic_dec(&midCount);
21591+ spin_unlock(&GlobalMid_Lock);
21592+ cifs_buf_release(midEntry->resp_buf);
21593+ kmem_cache_free(cifs_mid_cachep, midEntry);
21594+}
21595+
21596+struct oplock_q_entry *
21597+AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
21598+{
21599+ struct oplock_q_entry *temp;
21600+ if ((pinode== NULL) || (tcon == NULL)) {
21601+ cERROR(1, ("Null parms passed to AllocOplockQEntry"));
21602+ return NULL;
21603+ }
21604+ temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
21605+ SLAB_KERNEL);
21606+ if (temp == NULL)
21607+ return temp;
21608+ else {
21609+ temp->pinode = pinode;
21610+ temp->tcon = tcon;
21611+ temp->netfid = fid;
21612+ spin_lock(&GlobalMid_Lock);
21613+ list_add_tail(&temp->qhead, &GlobalOplock_Q);
21614+ spin_unlock(&GlobalMid_Lock);
21615+ }
21616+ return temp;
21617+
21618+}
21619+
21620+void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
21621+{
21622+ spin_lock(&GlobalMid_Lock);
21623+ /* should we check if list empty first? */
21624+ list_del(&oplockEntry->qhead);
21625+ spin_unlock(&GlobalMid_Lock);
21626+ kmem_cache_free(cifs_oplock_cachep, oplockEntry);
21627+}
21628+
21629+int
21630+smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
21631+ unsigned int smb_buf_length, struct sockaddr *sin)
21632+{
21633+ int rc = 0;
21634+ int i = 0;
21635+ struct msghdr smb_msg;
21636+ struct iovec iov;
21637+ mm_segment_t temp_fs;
21638+
21639+ if(ssocket == NULL)
21640+ return -ENOTSOCK; /* BB eventually add reconnect code here */
21641+ iov.iov_base = smb_buffer;
21642+ iov.iov_len = smb_buf_length + 4;
21643+
21644+ smb_msg.msg_name = sin;
21645+ smb_msg.msg_namelen = sizeof (struct sockaddr);
21646+ smb_msg.msg_iov = &iov;
21647+ smb_msg.msg_iovlen = 1;
21648+ smb_msg.msg_control = NULL;
21649+ smb_msg.msg_controllen = 0;
21650+ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
21651+
21652+ /* smb header is converted in header_assemble. bcc and rest of SMB word
21653+ area, and byte area if necessary, is converted to littleendian in
21654+ cifssmb.c and RFC1001 len is converted to bigendian in smb_send
21655+ Flags2 is converted in SendReceive */
21656+
21657+ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
21658+ cFYI(1, ("Sending smb of length %d ", smb_buf_length));
21659+ dump_smb(smb_buffer, smb_buf_length + 4);
21660+
21661+ temp_fs = get_fs(); /* we must turn off socket api parm checking */
21662+ set_fs(get_ds());
21663+ while(iov.iov_len > 0) {
21664+ rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
21665+ if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
21666+ i++;
21667+ if(i > 60) {
21668+ cERROR(1,
21669+ ("sends on sock %p stuck for 30 seconds",
21670+ ssocket));
21671+ rc = -EAGAIN;
21672+ break;
21673+ }
21674+ set_current_state(TASK_INTERRUPTIBLE);
21675+ schedule_timeout(HZ/2);
21676+ continue;
21677+ }
21678+ if (rc < 0)
21679+ break;
21680+ iov.iov_base += rc;
21681+ iov.iov_len -= rc;
21682+ }
21683+ set_fs(temp_fs);
21684+
21685+ if (rc < 0) {
21686+ cERROR(1,("Error %d sending data on socket to server.", rc));
21687+ } else {
21688+ rc = 0;
21689+ }
21690+
21691+ return rc;
21692+}
21693+
21694+int
21695+SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
21696+ struct smb_hdr *in_buf, struct smb_hdr *out_buf,
21697+ int *pbytes_returned, const int long_op)
21698+{
21699+ int rc = 0;
21700+ unsigned int receive_len;
21701+ long timeout;
21702+ struct mid_q_entry *midQ;
21703+
21704+ if (ses == NULL) {
21705+ cERROR(1,("Null smb session"));
21706+ return -EIO;
21707+ }
21708+ if(ses->server == NULL) {
21709+ cERROR(1,("Null tcp session"));
21710+ return -EIO;
21711+ }
21712+
21713+ /* Ensure that we do not send more than 50 overlapping requests
21714+ to the same server. We may make this configurable later or
21715+ use ses->maxReq */
21716+ if(long_op == -1) {
21717+ /* oplock breaks must not be held up */
21718+ atomic_inc(&ses->server->inFlight);
21719+ } else {
21720+ spin_lock(&GlobalMid_Lock);
21721+ while(1) {
21722+ if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){
21723+ spin_unlock(&GlobalMid_Lock);
21724+ wait_event(ses->server->request_q,
21725+ atomic_read(&ses->server->inFlight)
21726+ < CIFS_MAX_REQ);
21727+ spin_lock(&GlobalMid_Lock);
21728+ } else {
21729+ if(ses->server->tcpStatus == CifsExiting) {
21730+ spin_unlock(&GlobalMid_Lock);
21731+ return -ENOENT;
21732+ }
21733+
21734+ /* can not count locking commands against total since
21735+ they are allowed to block on server */
21736+
21737+ if(long_op < 3) {
21738+ /* update # of requests on the wire to server */
21739+ atomic_inc(&ses->server->inFlight);
21740+ }
21741+ spin_unlock(&GlobalMid_Lock);
21742+ break;
21743+ }
21744+ }
21745+ }
21746+ /* make sure that we sign in the same order that we send on this socket
21747+ and avoid races inside tcp sendmsg code that could cause corruption
21748+ of smb data */
21749+
21750+ down(&ses->server->tcpSem);
21751+
21752+ if (ses->server->tcpStatus == CifsExiting) {
21753+ rc = -ENOENT;
21754+ goto out_unlock;
21755+ } else if (ses->server->tcpStatus == CifsNeedReconnect) {
21756+ cFYI(1,("tcp session dead - return to caller to retry"));
21757+ rc = -EAGAIN;
21758+ goto out_unlock;
21759+ } else if (ses->status != CifsGood) {
21760+ /* check if SMB session is bad because we are setting it up */
21761+ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
21762+ (in_buf->Command != SMB_COM_NEGOTIATE)) {
21763+ rc = -EAGAIN;
21764+ goto out_unlock;
21765+ } /* else ok - we are setting up session */
21766+ }
21767+ midQ = AllocMidQEntry(in_buf, ses);
21768+ if (midQ == NULL) {
21769+ up(&ses->server->tcpSem);
21770+ /* If not lock req, update # of requests on wire to server */
21771+ if(long_op < 3) {
21772+ atomic_dec(&ses->server->inFlight);
21773+ wake_up(&ses->server->request_q);
21774+ }
21775+ return -ENOMEM;
21776+ }
21777+
21778+ if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
21779+ up(&ses->server->tcpSem);
21780+ cERROR(1,
21781+ ("Illegal length, greater than maximum frame, %d ",
21782+ in_buf->smb_buf_length));
21783+ DeleteMidQEntry(midQ);
21784+ /* If not lock req, update # of requests on wire to server */
21785+ if(long_op < 3) {
21786+ atomic_dec(&ses->server->inFlight);
21787+ wake_up(&ses->server->request_q);
21788+ }
21789+ return -EIO;
21790+ }
21791+
21792+ if (in_buf->smb_buf_length > 12)
21793+ in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
21794+
21795+ rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
21796+
21797+ midQ->midState = MID_REQUEST_SUBMITTED;
21798+ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
21799+ (struct sockaddr *) &(ses->server->addr.sockAddr));
21800+ if(rc < 0) {
21801+ DeleteMidQEntry(midQ);
21802+ up(&ses->server->tcpSem);
21803+ /* If not lock req, update # of requests on wire to server */
21804+ if(long_op < 3) {
21805+ atomic_dec(&ses->server->inFlight);
21806+ wake_up(&ses->server->request_q);
21807+ }
21808+ return rc;
21809+ } else
21810+ up(&ses->server->tcpSem);
21811+ if (long_op == -1)
21812+ goto cifs_no_response_exit;
21813+ else if (long_op == 2) /* writes past end of file can take looooong time */
21814+ timeout = 300 * HZ;
21815+ else if (long_op == 1)
21816+ timeout = 45 * HZ; /* should be greater than
21817+ servers oplock break timeout (about 43 seconds) */
21818+ else if (long_op > 2) {
21819+ timeout = MAX_SCHEDULE_TIMEOUT;
21820+ } else
21821+ timeout = 15 * HZ;
21822+ /* wait for 15 seconds or until woken up due to response arriving or
21823+ due to last connection to this server being unmounted */
21824+ if (signal_pending(current)) {
21825+ /* if signal pending do not hold up user for full smb timeout
21826+ but we still give response a change to complete */
21827+ if(midQ->midState & MID_REQUEST_SUBMITTED) {
21828+ set_current_state(TASK_UNINTERRUPTIBLE);
21829+ timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
21830+ }
21831+ } else { /* using normal timeout */
21832+ /* timeout = wait_event_interruptible_timeout(ses->server->response_q,
21833+ (midQ->midState & MID_RESPONSE_RECEIVED) ||
21834+ ((ses->server->tcpStatus != CifsGood) &&
21835+ (ses->server->tcpStatus != CifsNew)),
21836+ timeout); */
21837+ /* Can not allow user interrupts- wreaks havoc with performance */
21838+ if(midQ->midState & MID_REQUEST_SUBMITTED) {
21839+ set_current_state(TASK_UNINTERRUPTIBLE);
21840+ timeout = sleep_on_timeout(&ses->server->response_q,timeout);
21841+ }
21842+ }
21843+
21844+ spin_lock(&GlobalMid_Lock);
21845+ if (midQ->resp_buf) {
21846+ spin_unlock(&GlobalMid_Lock);
21847+ receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
21848+ } else {
21849+ cERROR(1,("No response buffer"));
21850+ if(midQ->midState == MID_REQUEST_SUBMITTED) {
21851+ if(ses->server->tcpStatus == CifsExiting)
21852+ rc = -EHOSTDOWN;
21853+ else {
21854+ ses->server->tcpStatus = CifsNeedReconnect;
21855+ midQ->midState = MID_RETRY_NEEDED;
21856+ }
21857+ }
21858+
21859+ if (rc != -EHOSTDOWN) {
21860+ if(midQ->midState == MID_RETRY_NEEDED) {
21861+ rc = -EAGAIN;
21862+ cFYI(1,("marking request for retry"));
21863+ } else {
21864+ rc = -EIO;
21865+ }
21866+ }
21867+ spin_unlock(&GlobalMid_Lock);
21868+ DeleteMidQEntry(midQ);
21869+ /* If not lock req, update # of requests on wire to server */
21870+ if(long_op < 3) {
21871+ atomic_dec(&ses->server->inFlight);
21872+ wake_up(&ses->server->request_q);
21873+ }
21874+ return rc;
21875+ }
21876+
21877+ if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
21878+ cERROR(1,
21879+ ("Frame too large received. Length: %d Xid: %d",
21880+ receive_len, xid));
21881+ rc = -EIO;
21882+ } else { /* rcvd frame is ok */
21883+
21884+ if (midQ->resp_buf && out_buf
21885+ && (midQ->midState == MID_RESPONSE_RECEIVED)) {
21886+ memcpy(out_buf, midQ->resp_buf,
21887+ receive_len +
21888+ 4 /* include 4 byte RFC1001 header */ );
21889+
21890+ dump_smb(out_buf, 92);
21891+ /* convert the length into a more usable form */
21892+ out_buf->smb_buf_length =
21893+ be32_to_cpu(out_buf->smb_buf_length);
21894+ if((out_buf->smb_buf_length > 24) &&
21895+ (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
21896+ rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
21897+ if(rc)
21898+ cFYI(1,("Unexpected signature received from server"));
21899+ }
21900+
21901+ if (out_buf->smb_buf_length > 12)
21902+ out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
21903+ if (out_buf->smb_buf_length > 28)
21904+ out_buf->Pid = le16_to_cpu(out_buf->Pid);
21905+ if (out_buf->smb_buf_length > 28)
21906+ out_buf->PidHigh =
21907+ le16_to_cpu(out_buf->PidHigh);
21908+
21909+ *pbytes_returned = out_buf->smb_buf_length;
21910+
21911+ /* BB special case reconnect tid and reconnect uid here? */
21912+ rc = map_smb_to_linux_error(out_buf);
21913+
21914+ /* convert ByteCount if necessary */
21915+ if (receive_len >=
21916+ sizeof (struct smb_hdr) -
21917+ 4 /* do not count RFC1001 header */ +
21918+ (2 * out_buf->WordCount) + 2 /* bcc */ )
21919+ BCC(out_buf) = le16_to_cpu(BCC(out_buf));
21920+ } else {
21921+ rc = -EIO;
21922+ cFYI(1,("Bad MID state? "));
21923+ }
21924+ }
21925+cifs_no_response_exit:
21926+ DeleteMidQEntry(midQ);
21927+
21928+ if(long_op < 3) {
21929+ atomic_dec(&ses->server->inFlight);
21930+ wake_up(&ses->server->request_q);
21931+ }
21932+
21933+ return rc;
21934+
21935+out_unlock:
21936+ up(&ses->server->tcpSem);
21937+ /* If not lock req, update # of requests on wire to server */
21938+ if(long_op < 3) {
21939+ atomic_dec(&ses->server->inFlight);
21940+ wake_up(&ses->server->request_q);
21941+ }
21942+
21943+ return rc;
21944+}
21945--- a/fs/Config.in
21946+++ b/fs/Config.in
21947@@ -153,6 +153,10 @@ if [ "$CONFIG_NET" = "y" ]; then
21948      define_bool CONFIG_LOCKD_V4 y
21949    fi
21950 
21951+ dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)' CONFIG_CIFS $CONFIG_INET
21952+ dep_mbool ' CIFS statistics' CONFIG_CIFS_STATS $CONFIG_CIFS
21953+ dep_mbool ' CIFS POSIX Protocol Extensions' CONFIG_CIFS_POSIX $CONFIG_CIFS
21954+
21955    dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
21956    if [ "$CONFIG_SMB_FS" != "n" ]; then
21957       bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT
21958--- a/fs/Makefile
21959+++ b/fs/Makefile
21960@@ -37,6 +37,7 @@ subdir-$(CONFIG_MSDOS_FS) += msdos
21961 subdir-$(CONFIG_VFAT_FS) += vfat
21962 subdir-$(CONFIG_BFS_FS) += bfs
21963 subdir-$(CONFIG_ISO9660_FS) += isofs
21964+subdir-$(CONFIG_CIFS) += cifs
21965 subdir-$(CONFIG_DEVFS_FS) += devfs
21966 subdir-$(CONFIG_HFSPLUS_FS) += hfsplus # Before hfs to find wrapped HFS+
21967 subdir-$(CONFIG_HFS_FS) += hfs
21968--- a/fs/nls/Config.in
21969+++ b/fs/nls/Config.in
21970@@ -11,6 +11,7 @@ fi
21971 
21972 # msdos and Joliet want NLS
21973 if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
21974+ -o "$CONFIG_CIFS" != "n" \
21975     -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
21976     -o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \
21977     -o "$CONFIG_BEFS_FS" != "n" -o "$CONFIG_HFSPLUS_FS" != "n" ]; then
21978

Archive Download this file



interactive