3ca3fb57e1d224b637e6f76df67783064d9ab4db
[openwrt/svn-archive/archive.git] / target / linux / generic-2.4 / patches / 107-cifs.patch
1 --- a/Documentation/Configure.help
2 +++ b/Documentation/Configure.help
3 @@ -17995,6 +17995,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