This series of patches closes the support gap on one of the explicitly
[openwrt/svn-archive/archive.git] / target / linux / generic-2.4 / patches / 107-cifs.patch
1 Index: linux-2.4.35.4/Documentation/Configure.help
2 ===================================================================
3 --- linux-2.4.35.4.orig/Documentation/Configure.help
4 +++ linux-2.4.35.4/Documentation/Configure.help
5 @@ -17995,6 +17995,34 @@ CONFIG_UNIXWARE_DISKLABEL
6
7 If you don't know what all this is about, say N.
8
9 +CIFS (Common Internet File System) support
10 +CONFIG_CIFS
11 + This is the client VFS module for the Common Internet File System
12 + (CIFS) protocol which is the successor to the Server Message Block
13 + (SMB) protocol, the native file sharing mechanism for most early
14 + PC operating systems. CIFS is fully supported by current network
15 + file servers such as Windows 2000, Windows 2003 (including
16 + Windows XP) as well by Samba (which provides excellent CIFS
17 + server support for Linux and many other operating systems).
18 + The smbfs module should be used instead of this cifs module for
19 + mounting to older SMB servers such as OS/2. The smbfs and cifs
20 + modules can coexist and do not conflict.
21 +
22 + The intent of this module is to provide the most advanced network
23 + file system function for CIFS compliant servers, including better
24 + POSIX compliance, secure per-user session establishment, high
25 + performance safe distributed caching (oplock), optional packet
26 + signing, Unicode support and other internationalization improvements
27 + For more information see the project page at
28 + http://us1.samba.org/samba/Linux_CIFS_client.html
29 +
30 +CIFS Debugging
31 +CONFIG_CIFS_DEBUG
32 + If you are experiencing any problems with the CIFS filesystem, say
33 + Y here. This will result in additional debugging messages to be
34 + written to the system log. Under normal circumstances, this
35 + results in very little overhead.
36 +
37 SMB file system support (to mount Windows shares etc.)
38 CONFIG_SMB_FS
39 SMB (Server Message Block) is the protocol Windows for Workgroups
40 Index: linux-2.4.35.4/Documentation/filesystems/00-INDEX
41 ===================================================================
42 --- linux-2.4.35.4.orig/Documentation/filesystems/00-INDEX
43 +++ linux-2.4.35.4/Documentation/filesystems/00-INDEX
44 @@ -10,6 +10,8 @@ befs.txt
45 - info for the BeOS file system (BFS)
46 bfs.txt
47 - info for the SCO UnixWare Boot Filesystem (BFS).
48 +cifs.txt
49 + - info on the Common Internet File System (CIFS)
50 coda.txt
51 - description of the CODA filesystem.
52 cramfs.txt
53 Index: linux-2.4.35.4/Documentation/filesystems/cifs.txt
54 ===================================================================
55 --- /dev/null
56 +++ linux-2.4.35.4/Documentation/filesystems/cifs.txt
57 @@ -0,0 +1,51 @@
58 + This is the client VFS module for the Common Internet File System
59 + (CIFS) protocol which is the successor to the Server Message Block
60 + (SMB) protocol, the native file sharing mechanism for most early
61 + PC operating systems. CIFS is fully supported by current network
62 + file servers such as Windows 2000, Windows 2003 (including
63 + Windows XP) as well by Samba (which provides excellent CIFS
64 + server support for Linux and many other operating systems), so
65 + this network filesystem client can mount to a wide variety of
66 + servers. The smbfs module should be used instead of this cifs module
67 + for mounting to older SMB servers such as OS/2. The smbfs and cifs
68 + modules can coexist and do not conflict. The CIFS VFS filesystem
69 + module is designed to work well with servers that implement the
70 + newer versions (dialects) of the SMB/CIFS protocol such as Samba,
71 + the program written by Andrew Tridgell that turns any Unix host
72 + into a SMB/CIFS file server.
73 +
74 + The intent of this module is to provide the most advanced network
75 + file system function for CIFS compliant servers, including better
76 + POSIX compliance, secure per-user session establishment, high
77 + performance safe distributed caching (oplock), optional packet
78 + signing, large files, Unicode support and other internationalization
79 + improvements. Since both Samba server and this filesystem client support
80 + the CIFS Unix extensions, the combination can provide a reasonable
81 + alternative to NFSv4 for fileserving in some Linux to Linux environments,
82 + not just in Linux to Windows environments.
83 +
84 + This filesystem has an optional mount utility (mount.cifs) that can
85 + be obtained from the project page and installed in the path in the same
86 + directory with the other mount helpers (such as mount.smbfs).
87 + Mounting using the cifs filesystem without installing the mount helper
88 + requires specifying the server's ip address.
89 +
90 + For Linux 2.4:
91 + mount //anything/here /mnt_target -o
92 + user=username,pass=password,unc=//ip_address_of_server/sharename
93 +
94 + For Linux 2.5:
95 + mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
96 +
97 +
98 + For more information on the module see the project page at
99 +
100 + http://us1.samba.org/samba/Linux_CIFS_client.html
101 +
102 + For more information on CIFS see:
103 +
104 + http://www.snia.org/tech_activities/CIFS
105 +
106 + or the Samba site:
107 +
108 + http://www.samba.org
109 Index: linux-2.4.35.4/fs/cifs/asn1.c
110 ===================================================================
111 --- /dev/null
112 +++ linux-2.4.35.4/fs/cifs/asn1.c
113 @@ -0,0 +1,614 @@
114 +/*
115 + * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
116 + * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
117 + *
118 + * Copyright (c) 2000 RP Internet (www.rpi.net.au).
119 + *
120 + * This program is free software; you can redistribute it and/or modify
121 + * it under the terms of the GNU General Public License as published by
122 + * the Free Software Foundation; either version 2 of the License, or
123 + * (at your option) any later version.
124 + * This program is distributed in the hope that it will be useful,
125 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
126 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
127 + * GNU General Public License for more details.
128 + * You should have received a copy of the GNU General Public License
129 + * along with this program; if not, write to the Free Software
130 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
131 + */
132 +
133 +#include <linux/config.h>
134 +#include <linux/module.h>
135 +#include <linux/types.h>
136 +#include <linux/kernel.h>
137 +#include <linux/mm.h>
138 +#include <linux/slab.h>
139 +#include "cifspdu.h"
140 +#include "cifsglob.h"
141 +#include "cifs_debug.h"
142 +
143 +/*****************************************************************************
144 + *
145 + * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
146 + *
147 + *****************************************************************************/
148 +
149 +/* Class */
150 +#define ASN1_UNI 0 /* Universal */
151 +#define ASN1_APL 1 /* Application */
152 +#define ASN1_CTX 2 /* Context */
153 +#define ASN1_PRV 3 /* Private */
154 +
155 +/* Tag */
156 +#define ASN1_EOC 0 /* End Of Contents or N/A */
157 +#define ASN1_BOL 1 /* Boolean */
158 +#define ASN1_INT 2 /* Integer */
159 +#define ASN1_BTS 3 /* Bit String */
160 +#define ASN1_OTS 4 /* Octet String */
161 +#define ASN1_NUL 5 /* Null */
162 +#define ASN1_OJI 6 /* Object Identifier */
163 +#define ASN1_OJD 7 /* Object Description */
164 +#define ASN1_EXT 8 /* External */
165 +#define ASN1_SEQ 16 /* Sequence */
166 +#define ASN1_SET 17 /* Set */
167 +#define ASN1_NUMSTR 18 /* Numerical String */
168 +#define ASN1_PRNSTR 19 /* Printable String */
169 +#define ASN1_TEXSTR 20 /* Teletext String */
170 +#define ASN1_VIDSTR 21 /* Video String */
171 +#define ASN1_IA5STR 22 /* IA5 String */
172 +#define ASN1_UNITIM 23 /* Universal Time */
173 +#define ASN1_GENTIM 24 /* General Time */
174 +#define ASN1_GRASTR 25 /* Graphical String */
175 +#define ASN1_VISSTR 26 /* Visible String */
176 +#define ASN1_GENSTR 27 /* General String */
177 +
178 +/* Primitive / Constructed methods*/
179 +#define ASN1_PRI 0 /* Primitive */
180 +#define ASN1_CON 1 /* Constructed */
181 +
182 +/*
183 + * Error codes.
184 + */
185 +#define ASN1_ERR_NOERROR 0
186 +#define ASN1_ERR_DEC_EMPTY 2
187 +#define ASN1_ERR_DEC_EOC_MISMATCH 3
188 +#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
189 +#define ASN1_ERR_DEC_BADVALUE 5
190 +
191 +#define SPNEGO_OID_LEN 7
192 +#define NTLMSSP_OID_LEN 10
193 +unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
194 +unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
195 +
196 +/*
197 + * ASN.1 context.
198 + */
199 +struct asn1_ctx {
200 + int error; /* Error condition */
201 + unsigned char *pointer; /* Octet just to be decoded */
202 + unsigned char *begin; /* First octet */
203 + unsigned char *end; /* Octet after last octet */
204 +};
205 +
206 +/*
207 + * Octet string (not null terminated)
208 + */
209 +struct asn1_octstr {
210 + unsigned char *data;
211 + unsigned int len;
212 +};
213 +
214 +static void
215 +asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
216 +{
217 + ctx->begin = buf;
218 + ctx->end = buf + len;
219 + ctx->pointer = buf;
220 + ctx->error = ASN1_ERR_NOERROR;
221 +}
222 +
223 +static unsigned char
224 +asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
225 +{
226 + if (ctx->pointer >= ctx->end) {
227 + ctx->error = ASN1_ERR_DEC_EMPTY;
228 + return 0;
229 + }
230 + *ch = *(ctx->pointer)++;
231 + return 1;
232 +}
233 +
234 +static unsigned char
235 +asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
236 +{
237 + unsigned char ch;
238 +
239 + *tag = 0;
240 +
241 + do {
242 + if (!asn1_octet_decode(ctx, &ch))
243 + return 0;
244 + *tag <<= 7;
245 + *tag |= ch & 0x7F;
246 + } while ((ch & 0x80) == 0x80);
247 + return 1;
248 +}
249 +
250 +static unsigned char
251 +asn1_id_decode(struct asn1_ctx *ctx,
252 + unsigned int *cls, unsigned int *con, unsigned int *tag)
253 +{
254 + unsigned char ch;
255 +
256 + if (!asn1_octet_decode(ctx, &ch))
257 + return 0;
258 +
259 + *cls = (ch & 0xC0) >> 6;
260 + *con = (ch & 0x20) >> 5;
261 + *tag = (ch & 0x1F);
262 +
263 + if (*tag == 0x1F) {
264 + if (!asn1_tag_decode(ctx, tag))
265 + return 0;
266 + }
267 + return 1;
268 +}
269 +
270 +static unsigned char
271 +asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
272 +{
273 + unsigned char ch, cnt;
274 +
275 + if (!asn1_octet_decode(ctx, &ch))
276 + return 0;
277 +
278 + if (ch == 0x80)
279 + *def = 0;
280 + else {
281 + *def = 1;
282 +
283 + if (ch < 0x80)
284 + *len = ch;
285 + else {
286 + cnt = (unsigned char) (ch & 0x7F);
287 + *len = 0;
288 +
289 + while (cnt > 0) {
290 + if (!asn1_octet_decode(ctx, &ch))
291 + return 0;
292 + *len <<= 8;
293 + *len |= ch;
294 + cnt--;
295 + }
296 + }
297 + }
298 + return 1;
299 +}
300 +
301 +static unsigned char
302 +asn1_header_decode(struct asn1_ctx *ctx,
303 + unsigned char **eoc,
304 + unsigned int *cls, unsigned int *con, unsigned int *tag)
305 +{
306 + unsigned int def, len;
307 +
308 + if (!asn1_id_decode(ctx, cls, con, tag))
309 + return 0;
310 +
311 + if (!asn1_length_decode(ctx, &def, &len))
312 + return 0;
313 +
314 + if (def)
315 + *eoc = ctx->pointer + len;
316 + else
317 + *eoc = NULL;
318 + return 1;
319 +}
320 +
321 +static unsigned char
322 +asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
323 +{
324 + unsigned char ch;
325 +
326 + if (eoc == 0) {
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 +
335 + if (!asn1_octet_decode(ctx, &ch))
336 + return 0;
337 +
338 + if (ch != 0x00) {
339 + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
340 + return 0;
341 + }
342 + return 1;
343 + } else {
344 + if (ctx->pointer != eoc) {
345 + ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
346 + return 0;
347 + }
348 + return 1;
349 + }
350 +}
351 +
352 +/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
353 + unsigned char *eoc)
354 +{
355 + ctx->pointer = eoc;
356 + return 1;
357 +}
358 +
359 +static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
360 + unsigned char *eoc, long *integer)
361 +{
362 + unsigned char ch;
363 + unsigned int len;
364 +
365 + if (!asn1_octet_decode(ctx, &ch))
366 + return 0;
367 +
368 + *integer = (signed char) ch;
369 + len = 1;
370 +
371 + while (ctx->pointer < eoc) {
372 + if (++len > sizeof(long)) {
373 + ctx->error = ASN1_ERR_DEC_BADVALUE;
374 + return 0;
375 + }
376 +
377 + if (!asn1_octet_decode(ctx, &ch))
378 + return 0;
379 +
380 + *integer <<= 8;
381 + *integer |= ch;
382 + }
383 + return 1;
384 +}
385 +
386 +static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
387 + unsigned char *eoc,
388 + unsigned int *integer)
389 +{
390 + unsigned char ch;
391 + unsigned int len;
392 +
393 + if (!asn1_octet_decode(ctx, &ch))
394 + return 0;
395 +
396 + *integer = ch;
397 + if (ch == 0)
398 + len = 0;
399 + else
400 + len = 1;
401 +
402 + while (ctx->pointer < eoc) {
403 + if (++len > sizeof(unsigned int)) {
404 + ctx->error = ASN1_ERR_DEC_BADVALUE;
405 + return 0;
406 + }
407 +
408 + if (!asn1_octet_decode(ctx, &ch))
409 + return 0;
410 +
411 + *integer <<= 8;
412 + *integer |= ch;
413 + }
414 + return 1;
415 +}
416 +
417 +static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
418 + unsigned char *eoc,
419 + unsigned long *integer)
420 +{
421 + unsigned char ch;
422 + unsigned int len;
423 +
424 + if (!asn1_octet_decode(ctx, &ch))
425 + return 0;
426 +
427 + *integer = ch;
428 + if (ch == 0)
429 + len = 0;
430 + else
431 + len = 1;
432 +
433 + while (ctx->pointer < eoc) {
434 + if (++len > sizeof(unsigned long)) {
435 + ctx->error = ASN1_ERR_DEC_BADVALUE;
436 + return 0;
437 + }
438 +
439 + if (!asn1_octet_decode(ctx, &ch))
440 + return 0;
441 +
442 + *integer <<= 8;
443 + *integer |= ch;
444 + }
445 + return 1;
446 +}
447 +
448 +static unsigned char
449 +asn1_octets_decode(struct asn1_ctx *ctx,
450 + unsigned char *eoc,
451 + unsigned char **octets, unsigned int *len)
452 +{
453 + unsigned char *ptr;
454 +
455 + *len = 0;
456 +
457 + *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
458 + if (*octets == NULL) {
459 + return 0;
460 + }
461 +
462 + ptr = *octets;
463 + while (ctx->pointer < eoc) {
464 + if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
465 + kfree(*octets);
466 + *octets = NULL;
467 + return 0;
468 + }
469 + (*len)++;
470 + }
471 + return 1;
472 +} */
473 +
474 +static unsigned char
475 +asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
476 +{
477 + unsigned char ch;
478 +
479 + *subid = 0;
480 +
481 + do {
482 + if (!asn1_octet_decode(ctx, &ch))
483 + return 0;
484 +
485 + *subid <<= 7;
486 + *subid |= ch & 0x7F;
487 + } while ((ch & 0x80) == 0x80);
488 + return 1;
489 +}
490 +
491 +static unsigned char
492 +asn1_oid_decode(struct asn1_ctx *ctx,
493 + unsigned char *eoc, unsigned long **oid, unsigned int *len)
494 +{
495 + unsigned long subid;
496 + unsigned int size;
497 + unsigned long *optr;
498 +
499 + size = eoc - ctx->pointer + 1;
500 + *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
501 + if (*oid == NULL) {
502 + return 0;
503 + }
504 +
505 + optr = *oid;
506 +
507 + if (!asn1_subid_decode(ctx, &subid)) {
508 + kfree(*oid);
509 + *oid = NULL;
510 + return 0;
511 + }
512 +
513 + if (subid < 40) {
514 + optr[0] = 0;
515 + optr[1] = subid;
516 + } else if (subid < 80) {
517 + optr[0] = 1;
518 + optr[1] = subid - 40;
519 + } else {
520 + optr[0] = 2;
521 + optr[1] = subid - 80;
522 + }
523 +
524 + *len = 2;
525 + optr += 2;
526 +
527 + while (ctx->pointer < eoc) {
528 + if (++(*len) > size) {
529 + ctx->error = ASN1_ERR_DEC_BADVALUE;
530 + kfree(*oid);
531 + *oid = NULL;
532 + return 0;
533 + }
534 +
535 + if (!asn1_subid_decode(ctx, optr++)) {
536 + kfree(*oid);
537 + *oid = NULL;
538 + return 0;
539 + }
540 + }
541 + return 1;
542 +}
543 +
544 +static int
545 +compare_oid(unsigned long *oid1, unsigned int oid1len,
546 + unsigned long *oid2, unsigned int oid2len)
547 +{
548 + unsigned int i;
549 +
550 + if (oid1len != oid2len)
551 + return 0;
552 + else {
553 + for (i = 0; i < oid1len; i++) {
554 + if (oid1[i] != oid2[i])
555 + return 0;
556 + }
557 + return 1;
558 + }
559 +}
560 +
561 + /* BB check for endian conversion issues here */
562 +
563 +int
564 +decode_negTokenInit(unsigned char *security_blob, int length,
565 + enum securityEnum *secType)
566 +{
567 + struct asn1_ctx ctx;
568 + unsigned char *end;
569 + unsigned char *sequence_end;
570 + unsigned long *oid;
571 + unsigned int cls, con, tag, oidlen, rc;
572 + int use_ntlmssp = FALSE;
573 +
574 + *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
575 +
576 + /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
577 +
578 + asn1_open(&ctx, security_blob, length);
579 +
580 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
581 + cFYI(1, ("Error decoding negTokenInit header "));
582 + return 0;
583 + } else if ((cls != ASN1_APL) || (con != ASN1_CON)
584 + || (tag != ASN1_EOC)) {
585 + cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
586 + return 0;
587 + } else {
588 + /* remember to free obj->oid */
589 + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
590 + if (rc) {
591 + if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
592 + rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
593 + if (rc) {
594 + rc = compare_oid(oid, oidlen,
595 + SPNEGO_OID,
596 + SPNEGO_OID_LEN);
597 + kfree(oid);
598 + }
599 + } else
600 + rc = 0;
601 + }
602 +
603 + if (!rc) {
604 + cFYI(1, ("Error decoding negTokenInit header"));
605 + return 0;
606 + }
607 +
608 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
609 + cFYI(1, ("Error decoding negTokenInit "));
610 + return 0;
611 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
612 + || (tag != ASN1_EOC)) {
613 + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
614 + cls, con, tag, end, *end));
615 + return 0;
616 + }
617 +
618 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
619 + cFYI(1, ("Error decoding negTokenInit "));
620 + return 0;
621 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
622 + || (tag != ASN1_SEQ)) {
623 + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
624 + cls, con, tag, end, *end));
625 + return 0;
626 + }
627 +
628 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
629 + cFYI(1, ("Error decoding 2nd part of negTokenInit "));
630 + return 0;
631 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
632 + || (tag != ASN1_EOC)) {
633 + cFYI(1,
634 + ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
635 + cls, con, tag, end, *end));
636 + return 0;
637 + }
638 +
639 + if (asn1_header_decode
640 + (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
641 + cFYI(1, ("Error decoding 2nd part of negTokenInit "));
642 + return 0;
643 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
644 + || (tag != ASN1_SEQ)) {
645 + cFYI(1,
646 + ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
647 + cls, con, tag, end, *end));
648 + return 0;
649 + }
650 +
651 + while (!asn1_eoc_decode(&ctx, sequence_end)) {
652 + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
653 + if (!rc) {
654 + cFYI(1,
655 + ("Error 1 decoding negTokenInit header exit 2"));
656 + return 0;
657 + }
658 + if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
659 + asn1_oid_decode(&ctx, end, &oid, &oidlen);
660 + cFYI(1,
661 + ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
662 + oidlen, *oid, *(oid + 1), *(oid + 2),
663 + *(oid + 3)));
664 + rc = compare_oid(oid, oidlen, NTLMSSP_OID,
665 + NTLMSSP_OID_LEN);
666 + kfree(oid);
667 + if (rc)
668 + use_ntlmssp = TRUE;
669 + } else {
670 + cFYI(1,("This should be an oid what is going on? "));
671 + }
672 + }
673 +
674 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
675 + cFYI(1,
676 + ("Error decoding last part of negTokenInit exit 3"));
677 + return 0;
678 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
679 + cFYI(1,
680 + ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
681 + cls, con, tag, end, *end));
682 + return 0;
683 + }
684 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
685 + cFYI(1,
686 + ("Error decoding last part of negTokenInit exit 5"));
687 + return 0;
688 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
689 + || (tag != ASN1_SEQ)) {
690 + cFYI(1,
691 + ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
692 + cls, con, tag, end, *end));
693 + }
694 +
695 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
696 + cFYI(1,
697 + ("Error decoding last part of negTokenInit exit 7"));
698 + return 0;
699 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
700 + cFYI(1,
701 + ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
702 + cls, con, tag, end, *end));
703 + return 0;
704 + }
705 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
706 + cFYI(1,
707 + ("Error decoding last part of negTokenInit exit 9"));
708 + return 0;
709 + } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
710 + || (tag != ASN1_GENSTR)) {
711 + cFYI(1,
712 + ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
713 + cls, con, tag, end, *end));
714 + return 0;
715 + }
716 + cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
717 + }
718 +
719 + /* if (use_kerberos)
720 + *secType = Kerberos
721 + else */
722 + if (use_ntlmssp) {
723 + *secType = NTLMSSP;
724 + }
725 +
726 + return 1;
727 +}
728 Index: linux-2.4.35.4/fs/cifs/AUTHORS
729 ===================================================================
730 --- /dev/null
731 +++ linux-2.4.35.4/fs/cifs/AUTHORS
732 @@ -0,0 +1,37 @@
733 +Original Author
734 +===============
735 +Steve French (sfrench@samba.org)
736 +
737 +The author wishes to express his appreciation and thanks to:
738 +Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
739 +improvements. Thanks to IBM for allowing me the time and test resources to pursue
740 +this project. Jim McDonough from IBM (and the Samba Team) for his help.
741 +The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
742 +Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
743 +for proving years ago that a very good smb/cifs client could be done on a Unix like
744 +operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
745 +and others for their work on the Linux smbfs module over the years. Thanks to
746 +the other members of the Storage Network Industry Association CIFS Technical
747 +Workgroup for their work specifying this highly complex protocol and finally
748 +thanks to the Samba team for their technical advice and encouragement.
749 +
750 +Patch Contributors
751 +------------------
752 +Zwane Mwaikambo
753 +Andi Kleen
754 +Amrut Joshi
755 +Shobhit Dayal
756 +Sergey Vlasov
757 +Richard Hughes
758 +Yury Umanets
759 +
760 +Test case and Bug Report contributors
761 +-------------------------------------
762 +Thanks to those in the community who have submitted detailed bug reports
763 +and debug of problems they have found: Jochen Dolze, David Blaine,
764 +Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
765 +Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
766 +Olaf Kirch, Kieron Briggs, Nick Millington and others.
767 +
768 +And thanks to the IBM LTC and Power test teams and SuSE testers for
769 +finding multiple bugs during excellent stress test runs.
770 Index: linux-2.4.35.4/fs/cifs/CHANGES
771 ===================================================================
772 --- /dev/null
773 +++ linux-2.4.35.4/fs/cifs/CHANGES
774 @@ -0,0 +1,572 @@
775 +Version 1.20
776 +------------
777 +Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
778 +info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir
779 +(in build_wildcard_path_from_dentry). Fix mknod to pass type field
780 +(block/char/fifo) properly. Remove spurious mount warning log entry when
781 +credentials passed as mount argument. Set major/minor device number in
782 +inode for block and char devices when unix extensions enabled.
783 +
784 +Version 1.19
785 +------------
786 +Fix /proc/fs/cifs/Stats and DebugData display to handle larger
787 +amounts of return data. Properly limit requests to MAX_REQ (50
788 +is the usual maximum active multiplex SMB/CIFS requests per server).
789 +Do not kill cifsd (and thus hurt the other SMB session) when more than one
790 +session to the same server (but with different userids) exists and one
791 +of the two user's smb sessions is being removed while leaving the other.
792 +Do not loop reconnecting in cifsd demultiplex thread when admin
793 +kills the thread without going through unmount.
794 +
795 +Version 1.18
796 +------------
797 +Do not rename hardlinked files (since that should be a noop). Flush
798 +cached write behind data when reopening a file after session abend,
799 +except when already in write. Grab per socket sem during reconnect
800 +to avoid oops in sendmsg if overlapping with reconnect. Do not
801 +reset cached inode file size on readdir for files open for write on
802 +client.
803 +
804 +
805 +Version 1.17
806 +------------
807 +Update number of blocks in file so du command is happier (in Linux a fake
808 +blocksize of 512 is required for calculating number of blocks in inode).
809 +Fix prepare write of partial pages to read in data from server if possible.
810 +Fix race on tcpStatus field between unmount and reconnection code, causing
811 +cifsd process sometimes to hang around forever. Improve out of memory
812 +checks in cifs_filldir
813 +
814 +Version 1.16
815 +------------
816 +Fix incorrect file size in file handle based setattr on big endian hardware.
817 +Fix oops in build_path_from_dentry when out of memory. Add checks for invalid
818 +and closing file structs in writepage/partialpagewrite. Add statistics
819 +for each mounted share (new menuconfig option). Fix endianness problem in
820 +volume information displayed in /proc/fs/cifs/DebugData (only affects
821 +affects big endian architectures). Prevent renames while constructing
822 +path names for open, mkdir and rmdir.
823 +
824 +Version 1.15
825 +------------
826 +Change to mempools for alloc smb request buffers and multiplex structs
827 +to better handle low memory problems (and potential deadlocks).
828 +
829 +Version 1.14
830 +------------
831 +Fix incomplete listings of large directories on Samba servers when Unix
832 +extensions enabled. Fix oops when smb_buffer can not be allocated. Fix
833 +rename deadlock when writing out dirty pages at same time.
834 +
835 +Version 1.13
836 +------------
837 +Fix open of files in which O_CREATE can cause the mode to change in
838 +some cases. Fix case in which retry of write overlaps file close.
839 +Fix PPC64 build error. Reduce excessive stack usage in smb password
840 +hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
841 +
842 +Version 1.12
843 +------------
844 +Fixes for large file copy, signal handling, socket retry, buffer
845 +allocation and low memory situations.
846 +
847 +Version 1.11
848 +------------
849 +Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
850 +also now allowing support for specifying client netbiosname. NT4 support added.
851 +
852 +Version 1.10
853 +------------
854 +Fix reconnection (and certain failed mounts) to properly wake up the
855 +blocked users thread so it does not seem hung (in some cases was blocked
856 +until the cifs receive timeout expired). Fix spurious error logging
857 +to kernel log when application with open network files killed.
858 +
859 +Version 1.09
860 +------------
861 +Fix /proc/fs module unload warning message (that could be logged
862 +to the kernel log). Fix intermittent failure in connectathon
863 +test7 (hardlink count not immediately refreshed in case in which
864 +inode metadata can be incorrectly kept cached when time near zero)
865 +
866 +Version 1.08
867 +------------
868 +Allow file_mode and dir_mode (specified at mount time) to be enforced
869 +locally (the server already enforced its own ACLs too) for servers
870 +that do not report the correct mode (do not support the
871 +CIFS Unix Extensions).
872 +
873 +Version 1.07
874 +------------
875 +Fix some small memory leaks in some unmount error paths. Fix major leak
876 +of cache pages in readpages causing multiple read oriented stress
877 +testcases (including fsx, and even large file copy) to fail over time.
878 +
879 +Version 1.06
880 +------------
881 +Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
882 +This allows files that differ only in case and improves performance of file
883 +creation and file open to such servers. Fix semaphore conflict which causes
884 +slow delete of open file to Samba (which unfortunately can cause an oplock
885 +break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
886 +
887 +Version 1.05
888 +------------
889 +fixes to cifs_readpages for fsx test case
890 +
891 +Version 1.04
892 +------------
893 +Fix caching data integrity bug when extending file size especially when no
894 +oplock on file. Fix spurious logging of valid already parsed mount options
895 +that are parsed outside of the cifs vfs such as nosuid.
896 +
897 +
898 +Version 1.03
899 +------------
900 +Connect to server when port number override not specified, and tcp port
901 +unitialized. Reset search to restart at correct file when kernel routine
902 +filldir returns error during large directory searches (readdir).
903 +
904 +Version 1.02
905 +------------
906 +Fix caching problem when files opened by multiple clients in which
907 +page cache could contain stale data, and write through did
908 +not occur often enough while file was still open when read ahead
909 +(read oplock) not allowed. Treat "sep=" when first mount option
910 +as an overrride of comma as the default separator between mount
911 +options.
912 +
913 +Version 1.01
914 +------------
915 +Allow passwords longer than 16 bytes. Allow null password string.
916 +
917 +Version 1.00
918 +------------
919 +Gracefully clean up failed mounts when attempting to mount to servers such as
920 +Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
921 +embedded commas in mount parsing of passwords.
922 +
923 +Version 0.99
924 +------------
925 +Invalidate local inode cached pages on oplock break and when last file
926 +instance is closed so that the client does not continue using stale local
927 +copy rather than later modified server copy of file. Do not reconnect
928 +when server drops the tcp session prematurely before negotiate
929 +protocol response. Fix oops in roepen_file when dentry freed. Allow
930 +the support for CIFS Unix Extensions to be disabled via proc interface.
931 +
932 +Version 0.98
933 +------------
934 +Fix hang in commit_write during reconnection of open files under heavy load.
935 +Fix unload_nls oops in a mount failure path. Serialize writes to same socket
936 +which also fixes any possible races when cifs signatures are enabled in SMBs
937 +being sent out of signature sequence number order.
938 +
939 +Version 0.97
940 +------------
941 +Fix byte range locking bug (endian problem) causing bad offset and
942 +length.
943 +
944 +Version 0.96
945 +------------
946 +Fix oops (in send_sig) caused by CIFS unmount code trying to
947 +wake up the demultiplex thread after it had exited. Do not log
948 +error on harmless oplock release of closed handle.
949 +
950 +Version 0.95
951 +------------
952 +Fix unsafe global variable usage and password hash failure on gcc 3.3.1
953 +Fix problem reconnecting secondary mounts to same server after session
954 +failure. Fix invalid dentry - race in mkdir when directory gets created
955 +by another client between the lookup and mkdir.
956 +
957 +Version 0.94
958 +------------
959 +Fix to list processing in reopen_files. Fix reconnection when server hung
960 +but tcpip session still alive. Set proper timeout on socket read.
961 +
962 +Version 0.93
963 +------------
964 +Add missing mount options including iocharset. SMP fixes in write and open.
965 +Fix errors in reconnecting after TCP session failure. Fix module unloading
966 +of default nls codepage
967 +
968 +Version 0.92
969 +------------
970 +Active smb transactions should never go negative (fix double FreeXid). Fix
971 +list processing in file routines. Check return code on kmalloc in open.
972 +Fix spinlock usage for SMP.
973 +
974 +Version 0.91
975 +------------
976 +Fix oops in reopen_files when invalid dentry. drop dentry on server rename
977 +and on revalidate errors. Fix cases where pid is now tgid. Fix return code
978 +on create hard link when server does not support them.
979 +
980 +Version 0.90
981 +------------
982 +Fix scheduling while atomic error in getting inode info on newly created file.
983 +Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
984 +
985 +Version 0.89
986 +------------
987 +Fix oops on write to dead tcp session. Remove error log write for case when file open
988 +O_CREAT but not O_EXCL
989 +
990 +Version 0.88
991 +------------
992 +Fix non-POSIX behavior on rename of open file and delete of open file by taking
993 +advantage of trans2 SetFileInfo rename facility if available on target server.
994 +Retry on ENOSPC and EAGAIN socket errors.
995 +
996 +Version 0.87
997 +------------
998 +Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
999 +allocation size miscalculation. After oplock token lost do not read through
1000 +cache.
1001 +
1002 +Version 0.86
1003 +------------
1004 +Fix oops on empty file readahead. Fix for file size handling for locally cached files.
1005 +
1006 +Version 0.85
1007 +------------
1008 +Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
1009 +during auto reconnection to server after server recovered from failure.
1010 +
1011 +Version 0.84
1012 +------------
1013 +Finish support for Linux 2.5 open/create changes, which removes the
1014 +redundant NTCreate/QPathInfo/close that was sent during file create.
1015 +Enable oplock by default. Enable packet signing by default (needed to
1016 +access many recent Windows servers)
1017 +
1018 +Version 0.83
1019 +------------
1020 +Fix oops when mounting to long server names caused by inverted parms to kmalloc.
1021 +Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
1022 +we will choose a cifs user session (smb uid) that better matches the local
1023 +uid if a) the mount uid does not match the current uid and b) we have another
1024 +session to the same server (ip address) for a different mount which
1025 +matches the current local uid.
1026 +
1027 +Version 0.82
1028 +------------
1029 +Add support for mknod of block or character devices. Fix oplock
1030 +code (distributed caching) to properly send response to oplock
1031 +break from server.
1032 +
1033 +Version 0.81
1034 +------------
1035 +Finish up CIFS packet digital signing for the default
1036 +NTLM security case. This should help Windows 2003
1037 +network interoperability since it is common for
1038 +packet signing to be required now. Fix statfs (stat -f)
1039 +which recently started returning errors due to
1040 +invalid value (-1 instead of 0) being set in the
1041 +struct kstatfs f_ffiles field.
1042 +
1043 +Version 0.80
1044 +-----------
1045 +Fix oops on stopping oplock thread when removing cifs when
1046 +built as module.
1047 +
1048 +Version 0.79
1049 +------------
1050 +Fix mount options for ro (readonly), uid, gid and file and directory mode.
1051 +
1052 +Version 0.78
1053 +------------
1054 +Fix errors displayed on failed mounts to be more understandable.
1055 +Fixed various incorrect or misleading smb to posix error code mappings.
1056 +
1057 +Version 0.77
1058 +------------
1059 +Fix display of NTFS DFS junctions to display as symlinks.
1060 +They are the network equivalent. Fix oops in
1061 +cifs_partialpagewrite caused by missing spinlock protection
1062 +of openfile linked list. Allow writebehind caching errors to
1063 +be returned to the application at file close.
1064 +
1065 +Version 0.76
1066 +------------
1067 +Clean up options displayed in /proc/mounts by show_options to
1068 +be more consistent with other filesystems.
1069 +
1070 +Version 0.75
1071 +------------
1072 +Fix delete of readonly file to Windows servers. Reflect
1073 +presence or absence of read only dos attribute in mode
1074 +bits for servers that do not support CIFS Unix extensions.
1075 +Fix shortened results on readdir of large directories to
1076 +servers supporting CIFS Unix extensions (caused by
1077 +incorrect resume key).
1078 +
1079 +Version 0.74
1080 +------------
1081 +Fix truncate bug (set file size) that could cause hangs e.g. running fsx
1082 +
1083 +Version 0.73
1084 +------------
1085 +unload nls if mount fails.
1086 +
1087 +Version 0.72
1088 +------------
1089 +Add resume key support to search (readdir) code to workaround
1090 +Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
1091 +allows disabling caching of attribute information for
1092 +lookups.
1093 +
1094 +Version 0.71
1095 +------------
1096 +Add more oplock handling (distributed caching code). Remove
1097 +dead code. Remove excessive stack space utilization from
1098 +symlink routines.
1099 +
1100 +Version 0.70
1101 +------------
1102 +Fix oops in get dfs referral (triggered when null path sent in to
1103 +mount). Add support for overriding rsize at mount time.
1104 +
1105 +Version 0.69
1106 +------------
1107 +Fix buffer overrun in readdir which caused intermittent kernel oopses.
1108 +Fix writepage code to release kmap on write data. Allow "-ip=" new
1109 +mount option to be passed in on parameter distinct from the first part
1110 +(server name portion of) the UNC name. Allow override of the
1111 +tcp port of the target server via new mount option "-port="
1112 +
1113 +Version 0.68
1114 +------------
1115 +Fix search handle leak on rewind. Fix setuid and gid so that they are
1116 +reflected in the local inode immediately. Cleanup of whitespace
1117 +to make 2.4 and 2.5 versions more consistent.
1118 +
1119 +
1120 +Version 0.67
1121 +------------
1122 +Fix signal sending so that captive thread (cifsd) exits on umount
1123 +(which was causing the warning in kmem_cache_free of the request buffers
1124 +at rmmod time). This had broken as a sideeffect of the recent global
1125 +kernel change to daemonize. Fix memory leak in readdir code which
1126 +showed up in "ls -R" (and applications that did search rewinding).
1127 +
1128 +Version 0.66
1129 +------------
1130 +Reconnect tids and fids after session reconnection (still do not
1131 +reconnect byte range locks though). Fix problem caching
1132 +lookup information for directory inodes, improving performance,
1133 +especially in deep directory trees. Fix various build warnings.
1134 +
1135 +Version 0.65
1136 +------------
1137 +Finish fixes to commit write for caching/readahead consistency. fsx
1138 +now works to Samba servers. Fix oops caused when readahead
1139 +was interrupted by a signal.
1140 +
1141 +Version 0.64
1142 +------------
1143 +Fix data corruption (in partial page after truncate) that caused fsx to
1144 +fail to Windows servers. Cleaned up some extraneous error logging in
1145 +common error paths. Add generic sendfile support.
1146 +
1147 +Version 0.63
1148 +------------
1149 +Fix memory leak in AllocMidQEntry.
1150 +Finish reconnection logic, so connection with server can be dropped
1151 +(or server rebooted) and the cifs client will reconnect.
1152 +
1153 +Version 0.62
1154 +------------
1155 +Fix temporary socket leak when bad userid or password specified
1156 +(or other SMBSessSetup failure). Increase maximum buffer size to slightly
1157 +over 16K to allow negotiation of up to Samba and Windows server default read
1158 +sizes. Add support for readpages
1159 +
1160 +Version 0.61
1161 +------------
1162 +Fix oops when username not passed in on mount. Extensive fixes and improvements
1163 +to error logging (strip redundant newlines, change debug macros to ensure newline
1164 +passed in and to be more consistent). Fix writepage wrong file handle problem,
1165 +a readonly file handle could be incorrectly used to attempt to write out
1166 +file updates through the page cache to multiply open files. This could cause
1167 +the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
1168 +shares to the same Windows server when using different usernames
1169 +(doing this to Samba servers worked but Windows was rejecting it) - now it is
1170 +possible to use different userids when connecting to the same server from a
1171 +Linux client. Fix oops when treeDisconnect called during unmount on
1172 +previously freed socket.
1173 +
1174 +Version 0.60
1175 +------------
1176 +Fix oops in readpages caused by not setting address space operations in inode in
1177 +rare code path.
1178 +
1179 +Version 0.59
1180 +------------
1181 +Includes support for deleting of open files and renaming over existing files (per POSIX
1182 +requirement). Add readlink support for Windows junction points (directory symlinks).
1183 +
1184 +Version 0.58
1185 +------------
1186 +Changed read and write to go through pagecache. Added additional address space operations.
1187 +Memory mapped operations now working.
1188 +
1189 +Version 0.57
1190 +------------
1191 +Added writepage code for additional memory mapping support. Fixed leak in xids causing
1192 +the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on
1193 +every stat call. Additional formatting cleanup.
1194 +
1195 +Version 0.56
1196 +------------
1197 +Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup.
1198 +
1199 +Version 0.55
1200 +------------
1201 +Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
1202 +Also included a modified version of his fix to protect global list manipulation of
1203 +the smb session and tree connection and mid related global variables.
1204 +
1205 +Version 0.54
1206 +------------
1207 +Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre
1208 +changes to superblock layout. Remove wasteful allocation of smb buffers (now the send
1209 +buffer is reused for responses). Add more oplock handling. Additional minor cleanup.
1210 +
1211 +Version 0.53
1212 +------------
1213 +More stylistic updates to better match kernel style. Add additional statistics
1214 +for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2
1215 +and CIFS Packet Signing enablement.
1216 +
1217 +Version 0.52
1218 +------------
1219 +Replace call to sleep_on with safer wait_on_event.
1220 +Make stylistic changes to better match kernel style recommendations.
1221 +Remove most typedef usage (except for the PDUs themselves).
1222 +
1223 +Version 0.51
1224 +------------
1225 +Update mount so the -unc mount option is no longer required (the ip address can be specified
1226 +in a UNC style device name. Implementation of readpage/writepage started.
1227 +
1228 +Version 0.50
1229 +------------
1230 +Fix intermittent problem with incorrect smb header checking on badly
1231 +fragmented tcp responses
1232 +
1233 +Version 0.49
1234 +------------
1235 +Fixes to setting of allocation size and file size.
1236 +
1237 +Version 0.48
1238 +------------
1239 +Various 2.5.38 fixes. Now works on 2.5.38
1240 +
1241 +Version 0.47
1242 +------------
1243 +Prepare for 2.5 kernel merge. Remove ifdefs.
1244 +
1245 +Version 0.46
1246 +------------
1247 +Socket buffer management fixes. Fix dual free.
1248 +
1249 +Version 0.45
1250 +------------
1251 +Various big endian fixes for hardlinks and symlinks and also for dfs.
1252 +
1253 +Version 0.44
1254 +------------
1255 +Various big endian fixes for servers with Unix extensions such as Samba
1256 +
1257 +Version 0.43
1258 +------------
1259 +Various FindNext fixes for incorrect filenames on large directory searches on big endian
1260 +clients. basic posix file i/o tests now work on big endian machines, not just le
1261 +
1262 +Version 0.42
1263 +------------
1264 +SessionSetup and NegotiateProtocol now work from Big Endian machines.
1265 +Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older
1266 +versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
1267 +
1268 +Version 0.41
1269 +------------
1270 +Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
1271 +files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
1272 +
1273 +Version 0.40
1274 +------------
1275 +Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
1276 +session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
1277 +Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
1278 +(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
1279 +
1280 +Version 0.38
1281 +------------
1282 +Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
1283 +it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
1284 +
1285 +Version 0.37
1286 +------------
1287 +Rewrote much of connection and mount/unmount logic to handle bugs with
1288 +multiple uses to same share, multiple users to same server etc.
1289 +
1290 +Version 0.36
1291 +------------
1292 +Fixed major problem with dentry corruption (missing call to dput)
1293 +
1294 +Version 0.35
1295 +------------
1296 +Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
1297 +Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs
1298 +although corresponding function not fully implemented in the vfs yet
1299 +
1300 +Version 0.34
1301 +------------
1302 +Fixed dentry caching bug, misc. cleanup
1303 +
1304 +Version 0.33
1305 +------------
1306 +Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build
1307 +on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
1308 +Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added.
1309 +
1310 +Version 0.32
1311 +------------
1312 +Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
1313 +and tested against Samba 2.2.5
1314 +
1315 +
1316 +Version 0.31
1317 +------------
1318 +1) Fixed lockrange to be correct (it was one byte too short)
1319 +
1320 +2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly
1321 +show range as locked when there is a conflict with an existing lock.
1322 +
1323 +3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
1324 +in most cases. Eventually will offer optional ability to query server for the correct perms.
1325 +
1326 +3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded
1327 +but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
1328 +session)
1329 +
1330 +4) Fixed error logging of valid mount options
1331 +
1332 +5) Removed logging of password field.
1333 +
1334 +6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
1335 +and cleaned them up and made them more consistent with other cifs functions.
1336 +
1337 +7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
1338 +(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
1339 +nor is the symlink support using the Unix extensions
1340 +
1341 +8) Started adding the readlink and follow_link code
1342 +
1343 +Version 0.3
1344 +-----------
1345 +Initial drop
1346 +
1347 Index: linux-2.4.35.4/fs/cifs/cifs_debug.c
1348 ===================================================================
1349 --- /dev/null
1350 +++ linux-2.4.35.4/fs/cifs/cifs_debug.c
1351 @@ -0,0 +1,797 @@
1352 +/*
1353 + * fs/cifs_debug.c
1354 + *
1355 + * Copyright (C) International Business Machines Corp., 2000,2003
1356 + *
1357 + * Modified by Steve French (sfrench@us.ibm.com)
1358 + *
1359 + * This program is free software; you can redistribute it and/or modify
1360 + * it under the terms of the GNU General Public License as published by
1361 + * the Free Software Foundation; either version 2 of the License, or
1362 + * (at your option) any later version.
1363 + *
1364 + * This program is distributed in the hope that it will be useful,
1365 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1366 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1367 + * the GNU General Public License for more details.
1368 + *
1369 + * You should have received a copy of the GNU General Public License
1370 + * along with this program; if not, write to the Free Software
1371 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1372 + */
1373 +#include <linux/fs.h>
1374 +#include <linux/string.h>
1375 +#include <linux/ctype.h>
1376 +#include <linux/module.h>
1377 +#include <linux/proc_fs.h>
1378 +#include <asm/uaccess.h>
1379 +#include "cifspdu.h"
1380 +#include "cifsglob.h"
1381 +#include "cifsproto.h"
1382 +#include "cifs_debug.h"
1383 +
1384 +void
1385 +cifs_dump_mem(char *label, void *data, int length)
1386 +{
1387 + int i, j;
1388 + int *intptr = data;
1389 + char *charptr = data;
1390 + char buf[10], line[80];
1391 +
1392 + printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
1393 + label, length, data);
1394 + for (i = 0; i < length; i += 16) {
1395 + line[0] = 0;
1396 + for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
1397 + sprintf(buf, " %08x", intptr[i / 4 + j]);
1398 + strcat(line, buf);
1399 + }
1400 + buf[0] = ' ';
1401 + buf[2] = 0;
1402 + for (j = 0; (j < 16) && (i + j < length); j++) {
1403 + buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
1404 + strcat(line, buf);
1405 + }
1406 + printk(KERN_DEBUG "%s\n", line);
1407 + }
1408 +}
1409 +
1410 +#ifdef CONFIG_PROC_FS
1411 +int
1412 +cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
1413 + int count, int *eof, void *data)
1414 +{
1415 + struct list_head *tmp;
1416 + struct list_head *tmp1;
1417 + struct mid_q_entry * mid_entry;
1418 + struct cifsSesInfo *ses;
1419 + struct cifsTconInfo *tcon;
1420 + int i;
1421 + int length = 0;
1422 + char * original_buf = buf;
1423 +
1424 + *beginBuffer = buf + offset;
1425 +
1426 +
1427 + length =
1428 + sprintf(buf,
1429 + "Display Internal CIFS Data Structures for Debugging\n"
1430 + "---------------------------------------------------\n");
1431 + buf += length;
1432 +
1433 + length = sprintf(buf, "Servers:\n");
1434 + buf += length;
1435 +
1436 + i = 0;
1437 + read_lock(&GlobalSMBSeslock);
1438 + list_for_each(tmp, &GlobalSMBSessionList) {
1439 + i++;
1440 + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1441 + length =
1442 + sprintf(buf,
1443 + "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d",
1444 + i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
1445 + ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
1446 + buf += length;
1447 + if(ses->server) {
1448 + buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
1449 + atomic_read(&ses->server->socketUseCount),
1450 + ses->server->secMode,
1451 + atomic_read(&ses->server->inFlight));
1452 +
1453 + length = sprintf(buf, "\nMIDs: \n");
1454 + buf += length;
1455 +
1456 + spin_lock(&GlobalMid_Lock);
1457 + list_for_each(tmp1, &ses->server->pending_mid_q) {
1458 + mid_entry = list_entry(tmp1, struct
1459 + mid_q_entry,
1460 + qhead);
1461 + if(mid_entry) {
1462 + 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);
1463 + buf += length;
1464 + }
1465 + }
1466 + spin_unlock(&GlobalMid_Lock);
1467 + }
1468 +
1469 + }
1470 + read_unlock(&GlobalSMBSeslock);
1471 + sprintf(buf, "\n");
1472 + buf++;
1473 +
1474 + length = sprintf(buf, "\nShares:\n");
1475 + buf += length;
1476 +
1477 + i = 0;
1478 + read_lock(&GlobalSMBSeslock);
1479 + list_for_each(tmp, &GlobalTreeConnectionList) {
1480 + i++;
1481 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1482 + length =
1483 + sprintf(buf,
1484 + "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
1485 + i, tcon->treeName,
1486 + atomic_read(&tcon->useCount),
1487 + tcon->nativeFileSystem,
1488 + tcon->fsDevInfo.DeviceCharacteristics,
1489 + tcon->fsAttrInfo.Attributes,
1490 + tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
1491 + buf += length;
1492 + if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
1493 + length = sprintf(buf, " type: DISK ");
1494 + else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
1495 + length = sprintf(buf, " type: CDROM ");
1496 + else
1497 + length =
1498 + sprintf(buf, " type: %d ",
1499 + tcon->fsDevInfo.DeviceType);
1500 + buf += length;
1501 + if(tcon->tidStatus == CifsNeedReconnect) {
1502 + buf += sprintf(buf, "\tDISCONNECTED ");
1503 + length += 14;
1504 + }
1505 + }
1506 + read_unlock(&GlobalSMBSeslock);
1507 +
1508 + length = sprintf(buf, "\n");
1509 + buf += length;
1510 +
1511 + /* BB add code to dump additional info such as TCP session info now */
1512 + /* Now calculate total size of returned data */
1513 + length = buf - original_buf;
1514 +
1515 + if(offset + count >= length)
1516 + *eof = 1;
1517 + if(length < offset) {
1518 + *eof = 1;
1519 + return 0;
1520 + } else {
1521 + length = length - offset;
1522 + }
1523 + if (length > count)
1524 + length = count;
1525 +
1526 + return length;
1527 +}
1528 +
1529 +#ifdef CONFIG_CIFS_STATS
1530 +int
1531 +cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
1532 + int count, int *eof, void *data)
1533 +{
1534 + int item_length,i,length;
1535 + struct list_head *tmp;
1536 + struct cifsTconInfo *tcon;
1537 +
1538 + *beginBuffer = buf + offset;
1539 +
1540 + length = sprintf(buf,
1541 + "Resources in use\nCIFS Session: %d\n",
1542 + sesInfoAllocCount.counter);
1543 + buf += length;
1544 + item_length =
1545 + sprintf(buf,"Share (unique mount targets): %d\n",
1546 + tconInfoAllocCount.counter);
1547 + length += item_length;
1548 + buf += item_length;
1549 + item_length =
1550 + sprintf(buf,"SMB Request/Response Buffer: %d\n",
1551 + bufAllocCount.counter);
1552 + length += item_length;
1553 + buf += item_length;
1554 + item_length =
1555 + sprintf(buf,"Operations (MIDs): %d\n",
1556 + midCount.counter);
1557 + length += item_length;
1558 + buf += item_length;
1559 + item_length = sprintf(buf,
1560 + "\n%d session %d share reconnects\n",
1561 + tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
1562 + length += item_length;
1563 + buf += item_length;
1564 +
1565 + item_length = sprintf(buf,
1566 + "Total vfs operations: %d maximum at one time: %d\n",
1567 + GlobalCurrentXid,GlobalMaxActiveXid);
1568 + length += item_length;
1569 + buf += item_length;
1570 +
1571 + i = 0;
1572 + read_lock(&GlobalSMBSeslock);
1573 + list_for_each(tmp, &GlobalTreeConnectionList) {
1574 + i++;
1575 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1576 + item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
1577 + buf += item_length;
1578 + length += item_length;
1579 + if(tcon->tidStatus == CifsNeedReconnect) {
1580 + buf += sprintf(buf, "\tDISCONNECTED ");
1581 + length += 14;
1582 + }
1583 + item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
1584 + atomic_read(&tcon->num_smbs_sent),
1585 + atomic_read(&tcon->num_oplock_brks));
1586 + buf += item_length;
1587 + length += item_length;
1588 + item_length = sprintf(buf,"\nReads: %d Bytes %lld",
1589 + atomic_read(&tcon->num_reads),
1590 + (long long)(tcon->bytes_read));
1591 + buf += item_length;
1592 + length += item_length;
1593 + item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
1594 + atomic_read(&tcon->num_writes),
1595 + (long long)(tcon->bytes_written));
1596 + buf += item_length;
1597 + length += item_length;
1598 + item_length = sprintf(buf,
1599 + "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
1600 + atomic_read(&tcon->num_opens),
1601 + atomic_read(&tcon->num_deletes),
1602 + atomic_read(&tcon->num_mkdirs),
1603 + atomic_read(&tcon->num_rmdirs));
1604 + buf += item_length;
1605 + length += item_length;
1606 + item_length = sprintf(buf,
1607 + "\nRenames: %d T2 Renames %d",
1608 + atomic_read(&tcon->num_renames),
1609 + atomic_read(&tcon->num_t2renames));
1610 + buf += item_length;
1611 + length += item_length;
1612 + }
1613 + read_unlock(&GlobalSMBSeslock);
1614 +
1615 + buf += sprintf(buf,"\n");
1616 + length++;
1617 +
1618 + if(offset + count >= length)
1619 + *eof = 1;
1620 + if(length < offset) {
1621 + *eof = 1;
1622 + return 0;
1623 + } else {
1624 + length = length - offset;
1625 + }
1626 + if (length > count)
1627 + length = count;
1628 +
1629 + return length;
1630 +}
1631 +#endif
1632 +
1633 +struct proc_dir_entry *proc_fs_cifs;
1634 +read_proc_t cifs_txanchor_read;
1635 +static read_proc_t cifsFYI_read;
1636 +static write_proc_t cifsFYI_write;
1637 +static read_proc_t oplockEnabled_read;
1638 +static write_proc_t oplockEnabled_write;
1639 +static read_proc_t lookupFlag_read;
1640 +static write_proc_t lookupFlag_write;
1641 +static read_proc_t traceSMB_read;
1642 +static write_proc_t traceSMB_write;
1643 +static read_proc_t multiuser_mount_read;
1644 +static write_proc_t multiuser_mount_write;
1645 +static read_proc_t extended_security_read;
1646 +static write_proc_t extended_security_write;
1647 +static read_proc_t ntlmv2_enabled_read;
1648 +static write_proc_t ntlmv2_enabled_write;
1649 +static read_proc_t packet_signing_enabled_read;
1650 +static write_proc_t packet_signing_enabled_write;
1651 +static read_proc_t quotaEnabled_read;
1652 +static write_proc_t quotaEnabled_write;
1653 +static read_proc_t linuxExtensionsEnabled_read;
1654 +static write_proc_t linuxExtensionsEnabled_write;
1655 +
1656 +void
1657 +cifs_proc_init(void)
1658 +{
1659 + struct proc_dir_entry *pde;
1660 +
1661 + proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
1662 + if (proc_fs_cifs == NULL)
1663 + return;
1664 +
1665 + proc_fs_cifs->owner = THIS_MODULE;
1666 + create_proc_read_entry("DebugData", 0, proc_fs_cifs,
1667 + cifs_debug_data_read, NULL);
1668 +
1669 +#ifdef CONFIG_CIFS_STATS
1670 + create_proc_read_entry("Stats", 0, proc_fs_cifs,
1671 + cifs_stats_read, NULL);
1672 +#endif
1673 + pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
1674 + cifsFYI_read, NULL);
1675 + if (pde)
1676 + pde->write_proc = cifsFYI_write;
1677 +
1678 + pde =
1679 + create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
1680 + traceSMB_read, NULL);
1681 + if (pde)
1682 + pde->write_proc = traceSMB_write;
1683 +
1684 + pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
1685 + oplockEnabled_read, NULL);
1686 + if (pde)
1687 + pde->write_proc = oplockEnabled_write;
1688 +
1689 + pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
1690 + quotaEnabled_read, NULL);
1691 + if (pde)
1692 + pde->write_proc = quotaEnabled_write;
1693 +
1694 + pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
1695 + linuxExtensionsEnabled_read, NULL);
1696 + if (pde)
1697 + pde->write_proc = linuxExtensionsEnabled_write;
1698 +
1699 + pde =
1700 + create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
1701 + multiuser_mount_read, NULL);
1702 + if (pde)
1703 + pde->write_proc = multiuser_mount_write;
1704 +
1705 + pde =
1706 + create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
1707 + extended_security_read, NULL);
1708 + if (pde)
1709 + pde->write_proc = extended_security_write;
1710 +
1711 + pde =
1712 + create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
1713 + lookupFlag_read, NULL);
1714 + if (pde)
1715 + pde->write_proc = lookupFlag_write;
1716 +
1717 + pde =
1718 + create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
1719 + ntlmv2_enabled_read, NULL);
1720 + if (pde)
1721 + pde->write_proc = ntlmv2_enabled_write;
1722 +
1723 + pde =
1724 + create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
1725 + packet_signing_enabled_read, NULL);
1726 + if (pde)
1727 + pde->write_proc = packet_signing_enabled_write;
1728 +}
1729 +
1730 +void
1731 +cifs_proc_clean(void)
1732 +{
1733 + if (proc_fs_cifs == NULL)
1734 + return;
1735 +
1736 + remove_proc_entry("DebugData", proc_fs_cifs);
1737 + remove_proc_entry("cifsFYI", proc_fs_cifs);
1738 + remove_proc_entry("traceSMB", proc_fs_cifs);
1739 +#ifdef CONFIG_CIFS_STATS
1740 + remove_proc_entry("Stats", proc_fs_cifs);
1741 +#endif
1742 + remove_proc_entry("MultiuserMount", proc_fs_cifs);
1743 + remove_proc_entry("OplockEnabled", proc_fs_cifs);
1744 + remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
1745 + remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
1746 + remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
1747 + remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
1748 + remove_proc_entry("QuotaEnabled",proc_fs_cifs);
1749 + remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
1750 + remove_proc_entry("cifs", proc_root_fs);
1751 +}
1752 +
1753 +static int
1754 +cifsFYI_read(char *page, char **start, off_t off, int count,
1755 + int *eof, void *data)
1756 +{
1757 + int len;
1758 +
1759 + len = sprintf(page, "%d\n", cifsFYI);
1760 +
1761 + len -= off;
1762 + *start = page + off;
1763 +
1764 + if (len > count)
1765 + len = count;
1766 + else
1767 + *eof = 1;
1768 +
1769 + if (len < 0)
1770 + len = 0;
1771 +
1772 + return len;
1773 +}
1774 +static int
1775 +cifsFYI_write(struct file *file, const char *buffer,
1776 + unsigned long count, void *data)
1777 +{
1778 + char c;
1779 + int rc;
1780 +
1781 + rc = get_user(c, buffer);
1782 + if (rc)
1783 + return rc;
1784 + if (c == '0' || c == 'n' || c == 'N')
1785 + cifsFYI = 0;
1786 + else if (c == '1' || c == 'y' || c == 'Y')
1787 + cifsFYI = 1;
1788 +
1789 + return count;
1790 +}
1791 +
1792 +static int
1793 +oplockEnabled_read(char *page, char **start, off_t off,
1794 + int count, int *eof, void *data)
1795 +{
1796 + int len;
1797 +
1798 + len = sprintf(page, "%d\n", oplockEnabled);
1799 +
1800 + len -= off;
1801 + *start = page + off;
1802 +
1803 + if (len > count)
1804 + len = count;
1805 + else
1806 + *eof = 1;
1807 +
1808 + if (len < 0)
1809 + len = 0;
1810 +
1811 + return len;
1812 +}
1813 +static int
1814 +oplockEnabled_write(struct file *file, const char *buffer,
1815 + unsigned long count, void *data)
1816 +{
1817 + char c;
1818 + int rc;
1819 +
1820 + rc = get_user(c, buffer);
1821 + if (rc)
1822 + return rc;
1823 + if (c == '0' || c == 'n' || c == 'N')
1824 + oplockEnabled = 0;
1825 + else if (c == '1' || c == 'y' || c == 'Y')
1826 + oplockEnabled = 1;
1827 +
1828 + return count;
1829 +}
1830 +
1831 +static int
1832 +quotaEnabled_read(char *page, char **start, off_t off,
1833 + int count, int *eof, void *data)
1834 +{
1835 + int len;
1836 +
1837 + len = sprintf(page, "%d\n", quotaEnabled);
1838 +/* could also check if quotas are enabled in kernel
1839 + as a whole first */
1840 + len -= off;
1841 + *start = page + off;
1842 +
1843 + if (len > count)
1844 + len = count;
1845 + else
1846 + *eof = 1;
1847 +
1848 + if (len < 0)
1849 + len = 0;
1850 +
1851 + return len;
1852 +}
1853 +static int
1854 +quotaEnabled_write(struct file *file, const char *buffer,
1855 + unsigned long count, void *data)
1856 +{
1857 + char c;
1858 + int rc;
1859 +
1860 + rc = get_user(c, buffer);
1861 + if (rc)
1862 + return rc;
1863 + if (c == '0' || c == 'n' || c == 'N')
1864 + quotaEnabled = 0;
1865 + else if (c == '1' || c == 'y' || c == 'Y')
1866 + quotaEnabled = 1;
1867 +
1868 + return count;
1869 +}
1870 +
1871 +static int
1872 +linuxExtensionsEnabled_read(char *page, char **start, off_t off,
1873 + int count, int *eof, void *data)
1874 +{
1875 + int len;
1876 +
1877 + len = sprintf(page, "%d\n", linuxExtEnabled);
1878 +/* could also check if quotas are enabled in kernel
1879 + as a whole first */
1880 + len -= off;
1881 + *start = page + off;
1882 +
1883 + if (len > count)
1884 + len = count;
1885 + else
1886 + *eof = 1;
1887 +
1888 + if (len < 0)
1889 + len = 0;
1890 +
1891 + return len;
1892 +}
1893 +static int
1894 +linuxExtensionsEnabled_write(struct file *file, const char *buffer,
1895 + unsigned long count, void *data)
1896 +{
1897 + char c;
1898 + int rc;
1899 +
1900 + rc = get_user(c, buffer);
1901 + if (rc)
1902 + return rc;
1903 + if (c == '0' || c == 'n' || c == 'N')
1904 + linuxExtEnabled = 0;
1905 + else if (c == '1' || c == 'y' || c == 'Y')
1906 + linuxExtEnabled = 1;
1907 +
1908 + return count;
1909 +}
1910 +
1911 +
1912 +static int
1913 +lookupFlag_read(char *page, char **start, off_t off,
1914 + int count, int *eof, void *data)
1915 +{
1916 + int len;
1917 +
1918 + len = sprintf(page, "%d\n", lookupCacheEnabled);
1919 +
1920 + len -= off;
1921 + *start = page + off;
1922 +
1923 + if (len > count)
1924 + len = count;
1925 + else
1926 + *eof = 1;
1927 +
1928 + if (len < 0)
1929 + len = 0;
1930 +
1931 + return len;
1932 +}
1933 +static int
1934 +lookupFlag_write(struct file *file, const char *buffer,
1935 + unsigned long count, void *data)
1936 +{
1937 + char c;
1938 + int rc;
1939 +
1940 + rc = get_user(c, buffer);
1941 + if (rc)
1942 + return rc;
1943 + if (c == '0' || c == 'n' || c == 'N')
1944 + lookupCacheEnabled = 0;
1945 + else if (c == '1' || c == 'y' || c == 'Y')
1946 + lookupCacheEnabled = 1;
1947 +
1948 + return count;
1949 +}
1950 +static int
1951 +traceSMB_read(char *page, char **start, off_t off, int count,
1952 + int *eof, void *data)
1953 +{
1954 + int len;
1955 +
1956 + len = sprintf(page, "%d\n", traceSMB);
1957 +
1958 + len -= off;
1959 + *start = page + off;
1960 +
1961 + if (len > count)
1962 + len = count;
1963 + else
1964 + *eof = 1;
1965 +
1966 + if (len < 0)
1967 + len = 0;
1968 +
1969 + return len;
1970 +}
1971 +static int
1972 +traceSMB_write(struct file *file, const char *buffer,
1973 + unsigned long count, void *data)
1974 +{
1975 + char c;
1976 + int rc;
1977 +
1978 + rc = get_user(c, buffer);
1979 + if (rc)
1980 + return rc;
1981 + if (c == '0' || c == 'n' || c == 'N')
1982 + traceSMB = 0;
1983 + else if (c == '1' || c == 'y' || c == 'Y')
1984 + traceSMB = 1;
1985 +
1986 + return count;
1987 +}
1988 +
1989 +static int
1990 +multiuser_mount_read(char *page, char **start, off_t off,
1991 + int count, int *eof, void *data)
1992 +{
1993 + int len;
1994 +
1995 + len = sprintf(page, "%d\n", multiuser_mount);
1996 +
1997 + len -= off;
1998 + *start = page + off;
1999 +
2000 + if (len > count)
2001 + len = count;
2002 + else
2003 + *eof = 1;
2004 +
2005 + if (len < 0)
2006 + len = 0;
2007 +
2008 + return len;
2009 +}
2010 +static int
2011 +multiuser_mount_write(struct file *file, const char *buffer,
2012 + unsigned long count, void *data)
2013 +{
2014 + char c;
2015 + int rc;
2016 +
2017 + rc = get_user(c, buffer);
2018 + if (rc)
2019 + return rc;
2020 + if (c == '0' || c == 'n' || c == 'N')
2021 + multiuser_mount = 0;
2022 + else if (c == '1' || c == 'y' || c == 'Y')
2023 + multiuser_mount = 1;
2024 +
2025 + return count;
2026 +}
2027 +
2028 +static int
2029 +extended_security_read(char *page, char **start, off_t off,
2030 + int count, int *eof, void *data)
2031 +{
2032 + int len;
2033 +
2034 + len = sprintf(page, "%d\n", extended_security);
2035 +
2036 + len -= off;
2037 + *start = page + off;
2038 +
2039 + if (len > count)
2040 + len = count;
2041 + else
2042 + *eof = 1;
2043 +
2044 + if (len < 0)
2045 + len = 0;
2046 +
2047 + return len;
2048 +}
2049 +static int
2050 +extended_security_write(struct file *file, const char *buffer,
2051 + unsigned long count, void *data)
2052 +{
2053 + char c;
2054 + int rc;
2055 +
2056 + rc = get_user(c, buffer);
2057 + if (rc)
2058 + return rc;
2059 + if (c == '0' || c == 'n' || c == 'N')
2060 + extended_security = 0;
2061 + else if (c == '1' || c == 'y' || c == 'Y')
2062 + extended_security = 1;
2063 +
2064 + return count;
2065 +}
2066 +
2067 +static int
2068 +ntlmv2_enabled_read(char *page, char **start, off_t off,
2069 + int count, int *eof, void *data)
2070 +{
2071 + int len;
2072 +
2073 + len = sprintf(page, "%d\n", ntlmv2_support);
2074 +
2075 + len -= off;
2076 + *start = page + off;
2077 +
2078 + if (len > count)
2079 + len = count;
2080 + else
2081 + *eof = 1;
2082 +
2083 + if (len < 0)
2084 + len = 0;
2085 +
2086 + return len;
2087 +}
2088 +static int
2089 +ntlmv2_enabled_write(struct file *file, const char *buffer,
2090 + unsigned long count, void *data)
2091 +{
2092 + char c;
2093 + int rc;
2094 +
2095 + rc = get_user(c, buffer);
2096 + if (rc)
2097 + return rc;
2098 + if (c == '0' || c == 'n' || c == 'N')
2099 + ntlmv2_support = 0;
2100 + else if (c == '1' || c == 'y' || c == 'Y')
2101 + ntlmv2_support = 1;
2102 +
2103 + return count;
2104 +}
2105 +
2106 +static int
2107 +packet_signing_enabled_read(char *page, char **start, off_t off,
2108 + int count, int *eof, void *data)
2109 +{
2110 + int len;
2111 +
2112 + len = sprintf(page, "%d\n", sign_CIFS_PDUs);
2113 +
2114 + len -= off;
2115 + *start = page + off;
2116 +
2117 + if (len > count)
2118 + len = count;
2119 + else
2120 + *eof = 1;
2121 +
2122 + if (len < 0)
2123 + len = 0;
2124 +
2125 + return len;
2126 +}
2127 +static int
2128 +packet_signing_enabled_write(struct file *file, const char *buffer,
2129 + unsigned long count, void *data)
2130 +{
2131 + char c;
2132 + int rc;
2133 +
2134 + rc = get_user(c, buffer);
2135 + if (rc)
2136 + return rc;
2137 + if (c == '0' || c == 'n' || c == 'N')
2138 + sign_CIFS_PDUs = 0;
2139 + else if (c == '1' || c == 'y' || c == 'Y')
2140 + sign_CIFS_PDUs = 1;
2141 + else if (c == '2')
2142 + sign_CIFS_PDUs = 2;
2143 +
2144 + return count;
2145 +}
2146 +
2147 +
2148 +#endif
2149 Index: linux-2.4.35.4/fs/cifs/cifs_debug.h
2150 ===================================================================
2151 --- /dev/null
2152 +++ linux-2.4.35.4/fs/cifs/cifs_debug.h
2153 @@ -0,0 +1,66 @@
2154 +/*
2155 + *
2156 + * Copyright (c) International Business Machines Corp., 2000,2002
2157 + * Modified by Steve French (sfrench@us.ibm.com)
2158 + *
2159 + * This program is free software; you can redistribute it and/or modify
2160 + * it under the terms of the GNU General Public License as published by
2161 + * the Free Software Foundation; either version 2 of the License, or
2162 + * (at your option) any later version.
2163 + *
2164 + * This program is distributed in the hope that it will be useful,
2165 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2166 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2167 + * the GNU General Public License for more details.
2168 + *
2169 + * You should have received a copy of the GNU General Public License
2170 + * along with this program; if not, write to the Free Software
2171 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2172 + *
2173 +*/
2174 +#define CIFS_DEBUG /* BB temporary */
2175 +
2176 +#ifndef _H_CIFS_DEBUG
2177 +#define _H_CIFS_DEBUG
2178 +
2179 +void cifs_dump_mem(char *label, void *data, int length);
2180 +extern int traceSMB; /* flag which enables the function below */
2181 +void dump_smb(struct smb_hdr *, int);
2182 +
2183 +/*
2184 + * debug ON
2185 + * --------
2186 + */
2187 +#ifdef CIFS_DEBUG
2188 +
2189 +
2190 +/* information message: e.g., configuration, major event */
2191 +extern int cifsFYI;
2192 +#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
2193 +
2194 +#define cFYI(button,prspec) if (button) cifsfyi prspec
2195 +
2196 +#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
2197 +
2198 +/* debug event message: */
2199 +extern int cifsERROR;
2200 +
2201 +#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
2202 +
2203 +/* error event message: e.g., i/o error */
2204 +#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
2205 +
2206 +#define cERROR(button, prspec) if (button) cifserror prspec
2207 +
2208 +/*
2209 + * debug OFF
2210 + * ---------
2211 + */
2212 +#else /* _CIFS_DEBUG */
2213 +#define cERROR(button,prspec)
2214 +#define cEVENT(format,arg...)
2215 +#define cFYI(button, prspec)
2216 +#define cifserror(format,arg...)
2217 +#endif /* _CIFS_DEBUG */
2218 +
2219 +#endif /* _H_CIFS_DEBUG */
2220 Index: linux-2.4.35.4/fs/cifs/cifsencrypt.c
2221 ===================================================================
2222 --- /dev/null
2223 +++ linux-2.4.35.4/fs/cifs/cifsencrypt.c
2224 @@ -0,0 +1,204 @@
2225 +/*
2226 + * fs/cifs/cifsencrypt.c
2227 + *
2228 + * Copyright (C) International Business Machines Corp., 2003
2229 + * Author(s): Steve French (sfrench@us.ibm.com)
2230 + *
2231 + * This library is free software; you can redistribute it and/or modify
2232 + * it under the terms of the GNU Lesser General Public License as published
2233 + * by the Free Software Foundation; either version 2.1 of the License, or
2234 + * (at your option) any later version.
2235 + *
2236 + * This library is distributed in the hope that it will be useful,
2237 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2238 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2239 + * the GNU Lesser General Public License for more details.
2240 + *
2241 + * You should have received a copy of the GNU Lesser General Public License
2242 + * along with this library; if not, write to the Free Software
2243 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2244 + */
2245 +
2246 +#include <linux/fs.h>
2247 +#include "cifspdu.h"
2248 +#include "cifsglob.h"
2249 +#include "cifs_debug.h"
2250 +#include "md5.h"
2251 +#include "cifs_unicode.h"
2252 +
2253 +/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
2254 +/* the 16 byte signature must be allocated by the caller */
2255 +/* Note we only use the 1st eight bytes */
2256 +/* Note that the smb header signature field on input contains the
2257 + sequence number before this function is called */
2258 +
2259 +extern void mdfour(unsigned char *out, unsigned char *in, int n);
2260 +extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
2261 +
2262 +static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
2263 +{
2264 + struct MD5Context context;
2265 +
2266 + if((cifs_pdu == NULL) || (signature == NULL))
2267 + return -EINVAL;
2268 +
2269 + MD5Init(&context);
2270 + MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
2271 + MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
2272 + MD5Final(signature,&context);
2273 + return 0;
2274 +}
2275 +
2276 +int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
2277 + __u32 * pexpected_response_sequence_number)
2278 +{
2279 + int rc = 0;
2280 + char smb_signature[20];
2281 +
2282 + /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
2283 + /* BB remember to add code to save expected sequence number in midQ entry BB */
2284 +
2285 + if((cifs_pdu == NULL) || (ses == NULL))
2286 + return -EINVAL;
2287 +
2288 + if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
2289 + return rc;
2290 +
2291 + spin_lock(&GlobalMid_Lock);
2292 + cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
2293 + cifs_pdu->Signature.Sequence.Reserved = 0;
2294 +
2295 + *pexpected_response_sequence_number = ses->sequence_number++;
2296 + ses->sequence_number++;
2297 + spin_unlock(&GlobalMid_Lock);
2298 +
2299 + rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
2300 + if(rc)
2301 + memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
2302 + else
2303 + memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
2304 +
2305 + return rc;
2306 +}
2307 +
2308 +int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
2309 + __u32 expected_sequence_number)
2310 +{
2311 + unsigned int rc;
2312 + char server_response_sig[8];
2313 + char what_we_think_sig_should_be[20];
2314 +
2315 + if((cifs_pdu == NULL) || (mac_key == NULL))
2316 + return -EINVAL;
2317 +
2318 + if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
2319 + return 0;
2320 +
2321 + if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
2322 + struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
2323 + if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
2324 + return 0;
2325 + }
2326 +
2327 + /* BB what if signatures are supposed to be on for session but server does not
2328 + send one? BB */
2329 +
2330 + /* Do not need to verify session setups with signature "BSRSPYL " */
2331 + if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
2332 + cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
2333 +
2334 + expected_sequence_number = cpu_to_le32(expected_sequence_number);
2335 +
2336 + /* save off the origiginal signature so we can modify the smb and check
2337 + its signature against what the server sent */
2338 + memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
2339 +
2340 + cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
2341 + cifs_pdu->Signature.Sequence.Reserved = 0;
2342 +
2343 + rc = cifs_calculate_signature(cifs_pdu, mac_key,
2344 + what_we_think_sig_should_be);
2345 +
2346 + if(rc)
2347 + return rc;
2348 +
2349 +
2350 +/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
2351 +
2352 + if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
2353 + return -EACCES;
2354 + else
2355 + return 0;
2356 +
2357 +}
2358 +
2359 +/* We fill in key by putting in 40 byte array which was allocated by caller */
2360 +int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
2361 +{
2362 + char temp_key[16];
2363 + if ((key == NULL) || (rn == NULL))
2364 + return -EINVAL;
2365 +
2366 + E_md4hash(password, temp_key);
2367 + mdfour(key,temp_key,16);
2368 + memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
2369 + return 0;
2370 +}
2371 +
2372 +int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
2373 +{
2374 + char temp_hash[16];
2375 + struct HMACMD5Context ctx;
2376 + char * ucase_buf;
2377 + wchar_t * unicode_buf;
2378 + unsigned int i,user_name_len,dom_name_len;
2379 +
2380 + if(ses)
2381 + return -EINVAL;
2382 +
2383 + E_md4hash(ses->password, temp_hash);
2384 +
2385 + hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
2386 + user_name_len = strlen(ses->userName);
2387 + if(user_name_len > MAX_USERNAME_SIZE)
2388 + return -EINVAL;
2389 + dom_name_len = strlen(ses->domainName);
2390 + if(dom_name_len > MAX_USERNAME_SIZE)
2391 + return -EINVAL;
2392 +
2393 + ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
2394 + unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
2395 +
2396 + for(i=0;i<user_name_len;i++)
2397 + ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
2398 + ucase_buf[i] = 0;
2399 + user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
2400 + unicode_buf[user_name_len] = 0;
2401 + user_name_len++;
2402 +
2403 + for(i=0;i<dom_name_len;i++)
2404 + ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
2405 + ucase_buf[i] = 0;
2406 + dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
2407 +
2408 + unicode_buf[user_name_len + dom_name_len] = 0;
2409 + hmac_md5_update((const unsigned char *) unicode_buf,
2410 + (user_name_len+dom_name_len)*2,&ctx);
2411 +
2412 + hmac_md5_final(ses->mac_signing_key,&ctx);
2413 + kfree(ucase_buf);
2414 + kfree(unicode_buf);
2415 + return 0;
2416 +}
2417 +void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
2418 +{
2419 + struct HMACMD5Context context;
2420 + memcpy(v2_session_response + 8, ses->server->cryptKey,8);
2421 + /* gen_blob(v2_session_response + 16); */
2422 + hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
2423 +
2424 + hmac_md5_update(ses->server->cryptKey,8,&context);
2425 +/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
2426 +
2427 + hmac_md5_final(v2_session_response,&context);
2428 +}
2429 Index: linux-2.4.35.4/fs/cifs/cifserr.c
2430 ===================================================================
2431 --- /dev/null
2432 +++ linux-2.4.35.4/fs/cifs/cifserr.c
2433 @@ -0,0 +1,70 @@
2434 +/*
2435 + * fs/cifserr.c
2436 + *
2437 + * Copyright (c) International Business Machines Corp., 2002
2438 + * Author(s): Steve French (sfrench@us.ibm.com)
2439 + *
2440 + * This library is free software; you can redistribute it and/or modify
2441 + * it under the terms of the GNU Lesser General Public License as published
2442 + * by the Free Software Foundation; either version 2.1 of the License, or
2443 + * (at your option) any later version.
2444 + *
2445 + * This library is distributed in the hope that it will be useful,
2446 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2447 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2448 + * the GNU Lesser General Public License for more details.
2449 + *
2450 + * You should have received a copy of the GNU Lesser General Public License
2451 + * along with this library; if not, write to the Free Software
2452 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2453 + */
2454 +
2455 +#include <linux/errno.h>
2456 +#include <linux/fs.h>
2457 +#include <linux/smbno.h>
2458 +#include "cifsfs.h"
2459 +
2460 +int map_cifs_error(int error_class, int error_code,
2461 + int status_codes_negotiated)
2462 +{
2463 +
2464 +
2465 + if (status_codes_negotiated) {
2466 + switch (error_code) {
2467 + default:
2468 + return EIO;
2469 + }
2470 + } else
2471 + switch (error_class) {
2472 + case SUCCESS:
2473 + return 0;
2474 +
2475 + case ERRDOS:
2476 + switch (error_code) {
2477 + case ERRbadfunc:
2478 + return EINVAL;
2479 + default:
2480 + return EIO;
2481 + }
2482 +
2483 + case ERRSRV:
2484 + switch (error_code) {
2485 + default:
2486 + return EIO;
2487 + }
2488 +
2489 + case ERRHRD:
2490 + switch (error_code) {
2491 + default:
2492 + return EIO;
2493 + }
2494 + default:
2495 + return EIO;
2496 + }
2497 + return 0;
2498 +}
2499 +
2500 +int map_smb_error(int error_class, int error_code)
2501 +{
2502 + return map_cifs_error(error_class, error_code, FALSE);
2503 +}
2504 Index: linux-2.4.35.4/fs/cifs/cifsfs.c
2505 ===================================================================
2506 --- /dev/null
2507 +++ linux-2.4.35.4/fs/cifs/cifsfs.c
2508 @@ -0,0 +1,769 @@
2509 +/*
2510 + * fs/cifs/cifsfs.c
2511 + *
2512 + * Copyright (C) International Business Machines Corp., 2002,2004
2513 + * Author(s): Steve French (sfrench@us.ibm.com)
2514 + *
2515 + * Common Internet FileSystem (CIFS) client
2516 + *
2517 + * This library is free software; you can redistribute it and/or modify
2518 + * it under the terms of the GNU Lesser General Public License as published
2519 + * by the Free Software Foundation; either version 2.1 of the License, or
2520 + * (at your option) any later version.
2521 + *
2522 + * This library is distributed in the hope that it will be useful,
2523 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2524 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2525 + * the GNU Lesser General Public License for more details.
2526 + *
2527 + * You should have received a copy of the GNU Lesser General Public License
2528 + * along with this library; if not, write to the Free Software
2529 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2530 + */
2531 +
2532 +/* Note that BB means BUGBUG (ie something to fix eventually) */
2533 +
2534 +#include <linux/module.h>
2535 +#include <linux/fs.h>
2536 +#include <linux/mount.h>
2537 +#include <linux/slab.h>
2538 +#include <linux/init.h>
2539 +#include <linux/version.h>
2540 +#include <linux/list.h>
2541 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2542 +#include <linux/seq_file.h>
2543 +#endif
2544 +#include <linux/vfs.h>
2545 +#include "cifsfs.h"
2546 +#include "cifspdu.h"
2547 +#define DECLARE_GLOBALS_HERE
2548 +#include "cifsglob.h"
2549 +#include "cifsproto.h"
2550 +#include "cifs_debug.h"
2551 +#include "cifs_fs_sb.h"
2552 +#include <linux/mm.h>
2553 +#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
2554 +/* BB when mempool_resize is added back in, we will resize pool on new mount */
2555 +#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
2556 +
2557 +#ifdef CONFIG_CIFS_QUOTA
2558 +static struct quotactl_ops cifs_quotactl_ops;
2559 +#endif
2560 +
2561 +extern struct file_system_type cifs_fs_type;
2562 +
2563 +int cifsFYI = 0;
2564 +int cifsERROR = 1;
2565 +int traceSMB = 0;
2566 +unsigned int oplockEnabled = 1;
2567 +unsigned int quotaEnabled = 0;
2568 +unsigned int linuxExtEnabled = 1;
2569 +unsigned int lookupCacheEnabled = 1;
2570 +unsigned int multiuser_mount = 0;
2571 +unsigned int extended_security = 0;
2572 +unsigned int ntlmv2_support = 0;
2573 +unsigned int sign_CIFS_PDUs = 1;
2574 +unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
2575 +struct task_struct * oplockThread = NULL;
2576 +
2577 +extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
2578 + const char *);
2579 +extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
2580 +void cifs_proc_init(void);
2581 +void cifs_proc_clean(void);
2582 +
2583 +static DECLARE_COMPLETION(cifs_oplock_exited);
2584 +
2585 +
2586 +struct super_block *
2587 +cifs_read_super(struct super_block *sb, void *data, int silent)
2588 +{
2589 + struct inode *inode;
2590 + struct cifs_sb_info *cifs_sb;
2591 + int rc = 0;
2592 +
2593 + sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
2594 + cifs_sb = CIFS_SB(sb);
2595 + if(cifs_sb == NULL)
2596 + return 0;
2597 + else
2598 + memset(cifs_sb,0,sizeof(struct cifs_sb_info));
2599 +
2600 +
2601 + rc = cifs_mount(sb, cifs_sb, data, NULL);
2602 +
2603 + if (rc) {
2604 + if (!silent)
2605 + cERROR(1,
2606 + ("cifs_mount failed w/return code = %d", rc));
2607 + goto out_mount_failed;
2608 + }
2609 +
2610 + sb->s_magic = CIFS_MAGIC_NUMBER;
2611 + sb->s_op = &cifs_super_ops;
2612 +/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
2613 + sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
2614 +#ifdef CONFIG_CIFS_QUOTA
2615 + sb->s_qcop = &cifs_quotactl_ops;
2616 +#endif
2617 + sb->s_blocksize = CIFS_MAX_MSGSIZE;
2618 + sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
2619 + inode = iget(sb, ROOT_I);
2620 +
2621 + if (!inode) {
2622 + goto out_no_root;
2623 + }
2624 +
2625 + sb->s_root = d_alloc_root(inode);
2626 +
2627 + if (!sb->s_root) {
2628 + goto out_no_root;
2629 + }
2630 +
2631 + return sb;
2632 +
2633 +out_no_root:
2634 + cERROR(1, ("cifs_read_super: get root inode failed"));
2635 + if (inode)
2636 + iput(inode);
2637 +
2638 +out_mount_failed:
2639 + if(cifs_sb->local_nls)
2640 + unload_nls(cifs_sb->local_nls);
2641 + sb->s_dev = 0;
2642 + return 0;
2643 +}
2644 +
2645 +static void
2646 +cifs_put_super(struct super_block *sb)
2647 +{
2648 + int rc = 0;
2649 + struct cifs_sb_info *cifs_sb;
2650 +
2651 + cFYI(1, ("In cifs_put_super"));
2652 + cifs_sb = CIFS_SB(sb);
2653 + if(cifs_sb == NULL) {
2654 + cFYI(1,("Empty cifs superblock info passed to unmount"));
2655 + return;
2656 + }
2657 + rc = cifs_umount(sb, cifs_sb);
2658 + if (rc) {
2659 + cERROR(1, ("cifs_umount failed with return code %d", rc));
2660 + }
2661 + unload_nls(cifs_sb->local_nls);
2662 + return;
2663 +}
2664 +
2665 +static int
2666 +cifs_statfs(struct super_block *sb, struct statfs *buf)
2667 +{
2668 + int xid, rc;
2669 + struct cifs_sb_info *cifs_sb;
2670 + struct cifsTconInfo *pTcon;
2671 +
2672 + xid = GetXid();
2673 +
2674 + cifs_sb = CIFS_SB(sb);
2675 + pTcon = cifs_sb->tcon;
2676 +
2677 + buf->f_type = CIFS_MAGIC_NUMBER;
2678 +
2679 + /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
2680 + buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably
2681 + be length of total path, note that some servers may be
2682 + able to support more than this, but best to be safe
2683 + since Win2k and others can not handle very long filenames */
2684 + buf->f_files = 0; /* undefined */
2685 + buf->f_ffree = 0; /* unlimited */
2686 +
2687 + rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
2688 +
2689 + /*
2690 + int f_type;
2691 + __fsid_t f_fsid;
2692 + int f_namelen; */
2693 + /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
2694 + FreeXid(xid);
2695 + return 0; /* always return success? what if volume is no longer available? */
2696 +}
2697 +
2698 +static int cifs_permission(struct inode * inode, int mask)
2699 +{
2700 + /* the server does permission checks, we do not need to do it here */
2701 + return 0;
2702 +}
2703 +
2704 +kmem_cache_t *cifs_req_cachep;
2705 +kmem_cache_t *cifs_mid_cachep;
2706 +kmem_cache_t *cifs_oplock_cachep;
2707 +
2708 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2709 +static struct inode *
2710 +cifs_alloc_inode(struct super_block *sb)
2711 +{
2712 + struct cifsInodeInfo *cifs_inode;
2713 + cifs_inode =
2714 + (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
2715 + SLAB_KERNEL);
2716 + if (!cifs_inode)
2717 + return NULL;
2718 + cifs_inode->cifsAttrs = 0x20; /* default */
2719 + atomic_set(&cifs_inode->inUse, 0);
2720 + cifs_inode->time = 0;
2721 + /* Until the file is open and we have gotten oplock
2722 + info back from the server, can not assume caching of
2723 + file data or metadata */
2724 + cifs_inode->clientCanCacheRead = FALSE;
2725 + cifs_inode->clientCanCacheAll = FALSE;
2726 + INIT_LIST_HEAD(&cifs_inode->openFileList);
2727 + return &cifs_inode->vfs_inode;
2728 +}
2729 +
2730 +static void
2731 +cifs_destroy_inode(struct inode *inode)
2732 +{
2733 + kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
2734 +}
2735 +#endif
2736 +
2737 +/*
2738 + * cifs_show_options() is for displaying mount options in /proc/mounts.
2739 + * Not all settable options are displayed but most of the important
2740 + * ones are.
2741 + */
2742 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2743 +static int
2744 +cifs_show_options(struct seq_file *s, struct vfsmount *m)
2745 +{
2746 + struct cifs_sb_info *cifs_sb;
2747 +
2748 + cifs_sb = CIFS_SB(m->mnt_sb);
2749 +
2750 + if (cifs_sb) {
2751 + if (cifs_sb->tcon) {
2752 + seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
2753 + if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
2754 + seq_printf(s, ",username=%s",
2755 + cifs_sb->tcon->ses->userName);
2756 + if(cifs_sb->tcon->ses->domainName)
2757 + seq_printf(s, ",domain=%s",
2758 + cifs_sb->tcon->ses->domainName);
2759 + }
2760 + seq_printf(s, ",rsize=%d",cifs_sb->rsize);
2761 + seq_printf(s, ",wsize=%d",cifs_sb->wsize);
2762 + }
2763 + return 0;
2764 +}
2765 +#endif
2766 +
2767 +#ifdef CONFIG_CIFS_QUOTA
2768 +int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
2769 + struct fs_disk_quota * pdquota)
2770 +{
2771 + int xid;
2772 + int rc = 0;
2773 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2774 + struct cifsTconInfo *pTcon;
2775 +
2776 + if(cifs_sb)
2777 + pTcon = cifs_sb->tcon;
2778 + else
2779 + return -EIO;
2780 +
2781 +
2782 + xid = GetXid();
2783 + if(pTcon) {
2784 + cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
2785 + } else {
2786 + return -EIO;
2787 + }
2788 +
2789 + FreeXid(xid);
2790 + return rc;
2791 +}
2792 +
2793 +int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
2794 + struct fs_disk_quota * pdquota)
2795 +{
2796 + int xid;
2797 + int rc = 0;
2798 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2799 + struct cifsTconInfo *pTcon;
2800 +
2801 + if(cifs_sb)
2802 + pTcon = cifs_sb->tcon;
2803 + else
2804 + return -EIO;
2805 +
2806 + xid = GetXid();
2807 + if(pTcon) {
2808 + cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
2809 + } else {
2810 + rc = -EIO;
2811 + }
2812 +
2813 + FreeXid(xid);
2814 + return rc;
2815 +}
2816 +
2817 +int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
2818 +{
2819 + int xid;
2820 + int rc = 0;
2821 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2822 + struct cifsTconInfo *pTcon;
2823 +
2824 + if(cifs_sb)
2825 + pTcon = cifs_sb->tcon;
2826 + else
2827 + return -EIO;
2828 +
2829 + xid = GetXid();
2830 + if(pTcon) {
2831 + cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
2832 + } else {
2833 + rc = -EIO;
2834 + }
2835 +
2836 + FreeXid(xid);
2837 + return rc;
2838 +}
2839 +
2840 +int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
2841 +{
2842 + int xid;
2843 + int rc = 0;
2844 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2845 + struct cifsTconInfo *pTcon;
2846 +
2847 + if(cifs_sb) {
2848 + pTcon = cifs_sb->tcon;
2849 + } else {
2850 + return -EIO;
2851 + }
2852 + xid = GetXid();
2853 + if(pTcon) {
2854 + cFYI(1,("pqstats %p",qstats));
2855 + } else {
2856 + rc = -EIO;
2857 + }
2858 +
2859 + FreeXid(xid);
2860 + return rc;
2861 +}
2862 +
2863 +static struct quotactl_ops cifs_quotactl_ops = {
2864 + .set_xquota = cifs_xquota_set,
2865 + .get_xquota = cifs_xquota_set,
2866 + .set_xstate = cifs_xstate_set,
2867 + .get_xstate = cifs_xstate_get,
2868 +};
2869 +#endif
2870 +
2871 +static int cifs_remount(struct super_block *sb, int *flags, char *data)
2872 +{
2873 + *flags |= MS_NODIRATIME;
2874 + return 0;
2875 +}
2876 +
2877 +struct super_operations cifs_super_ops = {
2878 + .read_inode = cifs_read_inode,
2879 + .put_super = cifs_put_super,
2880 + .statfs = cifs_statfs,
2881 +/* .alloc_inode = cifs_alloc_inode,
2882 + .destroy_inode = cifs_destroy_inode, */
2883 +/* .drop_inode = generic_delete_inode,
2884 + .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
2885 + unless later we add lazy close of inodes or unless the kernel forgets to call
2886 + us with the same number of releases (closes) as opens */
2887 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2888 + .show_options = cifs_show_options,
2889 +#endif
2890 +/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
2891 +};
2892 +
2893 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2894 +static struct super_block *
2895 +cifs_get_sb(struct file_system_type *fs_type,
2896 + int flags, const char *dev_name, void *data)
2897 +{
2898 + int rc;
2899 + struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
2900 +
2901 + cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
2902 +
2903 + if (IS_ERR(sb))
2904 + return sb;
2905 +
2906 + sb->s_flags = flags;
2907 +
2908 + rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
2909 + if (rc) {
2910 + up_write(&sb->s_umount);
2911 + deactivate_super(sb);
2912 + return ERR_PTR(rc);
2913 + }
2914 + sb->s_flags |= MS_ACTIVE;
2915 + return sb;
2916 +}
2917 +#endif
2918 +
2919 +static ssize_t
2920 +cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
2921 + loff_t * poffset)
2922 +{
2923 + if(file == NULL)
2924 + return -EIO;
2925 + else if(file->f_dentry == NULL)
2926 + return -EIO;
2927 + else if(file->f_dentry->d_inode == NULL)
2928 + return -EIO;
2929 +
2930 + if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
2931 + return generic_file_read(file,read_data,read_size,poffset);
2932 + } else {
2933 + /* BB do we need to lock inode from here until after invalidate? */
2934 +/* if(file->f_dentry->d_inode->i_mapping) {
2935 + filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
2936 + filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
2937 + }*/
2938 +/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
2939 +
2940 + /* BB we should make timer configurable - perhaps
2941 + by simply calling cifs_revalidate here */
2942 + /* invalidate_remote_inode(file->f_dentry->d_inode);*/
2943 + return generic_file_read(file,read_data,read_size,poffset);
2944 + }
2945 +}
2946 +
2947 +static ssize_t
2948 +cifs_write_wrapper(struct file * file, const char *write_data,
2949 + size_t write_size, loff_t * poffset)
2950 +{
2951 + ssize_t written;
2952 +
2953 + if(file == NULL)
2954 + return -EIO;
2955 + else if(file->f_dentry == NULL)
2956 + return -EIO;
2957 + else if(file->f_dentry->d_inode == NULL)
2958 + return -EIO;
2959 +
2960 + /* check whether we can cache writes locally */
2961 + written = generic_file_write(file,write_data,write_size,poffset);
2962 + if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
2963 + if(file->f_dentry->d_inode->i_mapping) {
2964 + filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
2965 + }
2966 + }
2967 + return written;
2968 +}
2969 +
2970 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2971 +static struct file_system_type cifs_fs_type = {
2972 + .owner = THIS_MODULE,
2973 + .name = "cifs",
2974 + .get_sb = cifs_get_sb,
2975 + .kill_sb = kill_anon_super,
2976 + /* .fs_flags */
2977 +};
2978 +#endif
2979 +
2980 +static DECLARE_FSTYPE(cifs_fs_type, "cifs", cifs_read_super,0);
2981 +
2982 +
2983 +struct inode_operations cifs_dir_inode_ops = {
2984 + .create = cifs_create,
2985 + .lookup = cifs_lookup,
2986 + .unlink = cifs_unlink,
2987 + .link = cifs_hardlink,
2988 + .mkdir = cifs_mkdir,
2989 + .rmdir = cifs_rmdir,
2990 + .rename = cifs_rename,
2991 + .permission = cifs_permission,
2992 + .revalidate = cifs_revalidate,
2993 + .setattr = cifs_setattr,
2994 + .symlink = cifs_symlink,
2995 + .mknod = cifs_mknod,
2996 +};
2997 +
2998 +struct inode_operations cifs_file_inode_ops = {
2999 + .revalidate = cifs_revalidate,
3000 + .setattr = cifs_setattr,
3001 +/* .getattr = cifs_getattr,*/
3002 + .rename = cifs_rename,
3003 + .permission = cifs_permission,
3004 +#ifdef CONFIG_CIFS_XATTR
3005 + .setxattr = cifs_setxattr,
3006 + .getxattr = cifs_getxattr,
3007 + .listxattr = cifs_listxattr,
3008 + .removexattr = cifs_removexattr,
3009 +#endif
3010 +};
3011 +
3012 +struct inode_operations cifs_symlink_inode_ops = {
3013 + .readlink = cifs_readlink,
3014 + .follow_link = cifs_follow_link,
3015 + .permission = cifs_permission,
3016 + /* BB add the following two eventually */
3017 + /* revalidate: cifs_revalidate,
3018 + setattr: cifs_notify_change, *//* BB do we need notify change */
3019 +#ifdef CONFIG_CIFS_XATTR
3020 + .setxattr = cifs_setxattr,
3021 + .getxattr = cifs_getxattr,
3022 + .listxattr = cifs_listxattr,
3023 + .removexattr = cifs_removexattr,
3024 +#endif
3025 +};
3026 +
3027 +struct file_operations cifs_file_ops = {
3028 + .read = cifs_read_wrapper,
3029 + .write = cifs_write_wrapper,
3030 + .open = cifs_open,
3031 + .release = cifs_close,
3032 + .lock = cifs_lock,
3033 + .fsync = cifs_fsync,
3034 + .flush = cifs_flush,
3035 + .mmap = cifs_file_mmap,
3036 +/* .sendfile = generic_file_sendfile,*/
3037 +#ifdef CONFIG_CIFS_FCNTL
3038 + .fcntl = cifs_fcntl,
3039 +#endif
3040 +};
3041 +
3042 +struct file_operations cifs_dir_ops = {
3043 + .readdir = cifs_readdir,
3044 + .release = cifs_closedir,
3045 + .read = generic_read_dir,
3046 +#ifdef CONFIG_CIFS_FCNTL
3047 + .fcntl = cifs_fcntl,
3048 +#endif
3049 +};
3050 +/*
3051 +static void
3052 +cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
3053 +{
3054 + struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
3055 +
3056 + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
3057 + SLAB_CTOR_CONSTRUCTOR) {
3058 + inode_init_once(&cifsi->vfs_inode);
3059 + INIT_LIST_HEAD(&cifsi->lockList);
3060 + }
3061 +}
3062 +
3063 +static int
3064 +cifs_init_inodecache(void)
3065 +{
3066 + cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
3067 + sizeof (struct cifsInodeInfo),
3068 + 0, SLAB_HWCACHE_ALIGN,
3069 + cifs_init_once, NULL);
3070 + if (cifs_inode_cachep == NULL)
3071 + return -ENOMEM;
3072 +
3073 +
3074 + return 0;
3075 +}
3076 +
3077 +static void
3078 +cifs_destroy_inodecache(void)
3079 +{
3080 + if (kmem_cache_destroy(cifs_inode_cachep))
3081 + printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
3082 +} */
3083 +
3084 +static int
3085 +cifs_init_request_bufs(void)
3086 +{
3087 + cifs_req_cachep = kmem_cache_create("cifs_request",
3088 + CIFS_MAX_MSGSIZE +
3089 + MAX_CIFS_HDR_SIZE, 0,
3090 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3091 + if (cifs_req_cachep == NULL)
3092 + return -ENOMEM;
3093 +
3094 + return 0;
3095 +}
3096 +
3097 +static void
3098 +cifs_destroy_request_bufs(void)
3099 +{
3100 + if (kmem_cache_destroy(cifs_req_cachep))
3101 + printk(KERN_WARNING
3102 + "cifs_destroy_request_cache: error not all structures were freed\n");
3103 +}
3104 +
3105 +static int
3106 +cifs_init_mids(void)
3107 +{
3108 + cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
3109 + sizeof (struct mid_q_entry), 0,
3110 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3111 + if (cifs_mid_cachep == NULL)
3112 + return -ENOMEM;
3113 + cifs_oplock_cachep = kmem_cache_create("cifs_oplock_struct",
3114 + sizeof (struct oplock_q_entry), 0,
3115 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3116 + if (cifs_oplock_cachep == NULL) {
3117 + kmem_cache_destroy(cifs_mid_cachep);
3118 + return -ENOMEM;
3119 + }
3120 +
3121 + return 0;
3122 +}
3123 +
3124 +static void
3125 +cifs_destroy_mids(void)
3126 +{
3127 + if (kmem_cache_destroy(cifs_mid_cachep))
3128 + printk(KERN_WARNING
3129 + "cifs_destroy_mids: error not all structures were freed\n");
3130 + if (kmem_cache_destroy(cifs_oplock_cachep))
3131 + printk(KERN_WARNING
3132 + "error not all oplock structures were freed\n");
3133 +}
3134 +
3135 +static int cifs_oplock_thread(void * dummyarg)
3136 +{
3137 + struct oplock_q_entry * oplock_item;
3138 + struct cifsTconInfo *pTcon;
3139 + struct inode * inode;
3140 + __u16 netfid;
3141 + int rc = 0;
3142 +
3143 + daemonize();
3144 + sprintf(current->comm,"cifsoplockd");
3145 +
3146 + oplockThread = current;
3147 + do {
3148 + set_current_state(TASK_INTERRUPTIBLE);
3149 +
3150 + schedule_timeout(1*HZ);
3151 + spin_lock(&GlobalMid_Lock);
3152 + if(list_empty(&GlobalOplock_Q)) {
3153 + spin_unlock(&GlobalMid_Lock);
3154 + set_current_state(TASK_INTERRUPTIBLE);
3155 + schedule_timeout(39*HZ);
3156 + } else {
3157 + oplock_item = list_entry(GlobalOplock_Q.next,
3158 + struct oplock_q_entry, qhead);
3159 + if(oplock_item) {
3160 + cFYI(1,("found oplock item to write out"));
3161 + pTcon = oplock_item->tcon;
3162 + inode = oplock_item->pinode;
3163 + netfid = oplock_item->netfid;
3164 + spin_unlock(&GlobalMid_Lock);
3165 + DeleteOplockQEntry(oplock_item);
3166 + /* can not grab inode sem here since it would
3167 + deadlock when oplock received on delete
3168 + since vfs_unlink holds the i_sem across
3169 + the call */
3170 + /* down(&inode->i_sem);*/
3171 + if (S_ISREG(inode->i_mode)) {
3172 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
3173 + rc = filemap_fdatasync(inode->i_mapping);
3174 + if(rc)
3175 + CIFS_I(inode)->write_behind_rc = rc;
3176 +#else
3177 + filemap_fdatasync(inode->i_mapping);
3178 +#endif
3179 + if(CIFS_I(inode)->clientCanCacheRead == 0)
3180 + invalidate_inode_pages(inode);
3181 + } else
3182 + rc = 0;
3183 + /* releasing a stale oplock after recent reconnection
3184 + of smb session using a now incorrect file
3185 + handle is not a data integrity issue but do
3186 + not bother sending an oplock release if session
3187 + to server still is disconnected since oplock
3188 + already released by the server in that case */
3189 + if(pTcon->tidStatus != CifsNeedReconnect) {
3190 + rc = CIFSSMBLock(0, pTcon,
3191 + netfid,
3192 + 0 /* len */ , 0 /* offset */, 0,
3193 + 0, LOCKING_ANDX_OPLOCK_RELEASE,
3194 + 0 /* wait flag */);
3195 + cFYI(1,("Oplock release rc = %d ",rc));
3196 + }
3197 + } else
3198 + spin_unlock(&GlobalMid_Lock);
3199 + }
3200 + } while(!signal_pending(current));
3201 + complete_and_exit (&cifs_oplock_exited, 0);
3202 +}
3203 +
3204 +static int __init
3205 +init_cifs(void)
3206 +{
3207 + int rc = 0;
3208 +#if CONFIG_PROC_FS
3209 + cifs_proc_init();
3210 +#endif
3211 + INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
3212 + INIT_LIST_HEAD(&GlobalSMBSessionList);
3213 + INIT_LIST_HEAD(&GlobalTreeConnectionList);
3214 + INIT_LIST_HEAD(&GlobalOplock_Q);
3215 +/*
3216 + * Initialize Global counters
3217 + */
3218 + atomic_set(&sesInfoAllocCount, 0);
3219 + atomic_set(&tconInfoAllocCount, 0);
3220 + atomic_set(&tcpSesReconnectCount, 0);
3221 + atomic_set(&tconInfoReconnectCount, 0);
3222 +
3223 + atomic_set(&bufAllocCount, 0);
3224 + atomic_set(&midCount, 0);
3225 + GlobalCurrentXid = 0;
3226 + GlobalTotalActiveXid = 0;
3227 + GlobalMaxActiveXid = 0;
3228 + GlobalSMBSeslock = RW_LOCK_UNLOCKED;
3229 + GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
3230 +
3231 +/* rc = cifs_init_inodecache();*/
3232 + if (!rc) {
3233 + rc = cifs_init_mids();
3234 + if (!rc) {
3235 + rc = cifs_init_request_bufs();
3236 + if (!rc) {
3237 + rc = register_filesystem(&cifs_fs_type);
3238 + if (!rc) {
3239 + kernel_thread(cifs_oplock_thread, NULL,
3240 + CLONE_FS | CLONE_FILES | CLONE_VM);
3241 + return rc; /* Success */
3242 + } else
3243 + cifs_destroy_request_bufs();
3244 + }
3245 + cifs_destroy_mids();
3246 + }
3247 +/* cifs_destroy_inodecache(); */
3248 + }
3249 +#if CONFIG_PROC_FS
3250 + cifs_proc_clean();
3251 +#endif
3252 + return rc;
3253 +}
3254 +
3255 +static void __exit
3256 +exit_cifs(void)
3257 +{
3258 + cFYI(0, ("In unregister ie exit_cifs"));
3259 +#if CONFIG_PROC_FS
3260 + cifs_proc_clean();
3261 +#endif
3262 + unregister_filesystem(&cifs_fs_type);
3263 +/* cifs_destroy_inodecache();*/
3264 + cifs_destroy_mids();
3265 + cifs_destroy_request_bufs();
3266 + if(oplockThread) {
3267 + send_sig(SIGTERM, oplockThread, 1);
3268 + wait_for_completion(&cifs_oplock_exited);
3269 + }
3270 +}
3271 +
3272 +MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
3273 +MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
3274 +MODULE_DESCRIPTION
3275 + ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
3276 +module_init(init_cifs)
3277 +module_exit(exit_cifs)
3278 Index: linux-2.4.35.4/fs/cifs/cifsfs.h
3279 ===================================================================
3280 --- /dev/null
3281 +++ linux-2.4.35.4/fs/cifs/cifsfs.h
3282 @@ -0,0 +1,97 @@
3283 +/*
3284 + * fs/cifs/cifsfs.h
3285 + *
3286 + * Copyright (c) International Business Machines Corp., 2002
3287 + * Author(s): Steve French (sfrench@us.ibm.com)
3288 + *
3289 + * This library is free software; you can redistribute it and/or modify
3290 + * it under the terms of the GNU Lesser General Public License as published
3291 + * by the Free Software Foundation; either version 2.1 of the License, or
3292 + * (at your option) any later version.
3293 + *
3294 + * This library is distributed in the hope that it will be useful,
3295 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3296 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3297 + * the GNU Lesser General Public License for more details.
3298 + *
3299 + * You should have received a copy of the GNU Lesser General Public License
3300 + * along with this library; if not, write to the Free Software
3301 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3302 + */
3303 +
3304 +#ifndef _CIFSFS_H
3305 +#define _CIFSFS_H
3306 +
3307 +#define ROOT_I 2
3308 +
3309 +#ifndef FALSE
3310 +#define FALSE 0
3311 +#endif
3312 +
3313 +#ifndef TRUE
3314 +#define TRUE 1
3315 +#endif
3316 +
3317 +extern int map_cifs_error(int error_class, int error_code,
3318 + int status_codes_negotiated);
3319 +
3320 +extern struct address_space_operations cifs_addr_ops;
3321 +
3322 +/* Functions related to super block operations */
3323 +extern struct super_operations cifs_super_ops;
3324 +extern void cifs_put_inode(struct inode *);
3325 +extern void cifs_read_inode(struct inode *);
3326 +extern void cifs_delete_inode(struct inode *);
3327 +/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
3328 +
3329 +/* Functions related to inodes */
3330 +extern struct inode_operations cifs_dir_inode_ops;
3331 +extern int cifs_create(struct inode *, struct dentry *, int);
3332 +extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
3333 +extern int cifs_unlink(struct inode *, struct dentry *);
3334 +extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
3335 +extern int cifs_mknod(struct inode *, struct dentry *, int, int);
3336 +extern int cifs_mkdir(struct inode *, struct dentry *, int);
3337 +extern int cifs_rmdir(struct inode *, struct dentry *);
3338 +extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
3339 + struct dentry *);
3340 +extern int cifs_revalidate(struct dentry *);
3341 +extern int cifs_setattr(struct dentry *, struct iattr *);
3342 +
3343 +extern struct inode_operations cifs_file_inode_ops;
3344 +extern void cifs_truncate_file(struct inode *);
3345 +extern struct inode_operations cifs_symlink_inode_ops;
3346 +
3347 +/* Functions related to files and directories */
3348 +extern struct file_operations cifs_file_ops;
3349 +extern int cifs_open(struct inode *inode, struct file *file);
3350 +extern int cifs_close(struct inode *inode, struct file *file);
3351 +extern int cifs_closedir(struct inode *inode, struct file *file);
3352 +extern ssize_t cifs_read(struct file *file, char *read_data,
3353 + size_t read_size, loff_t * poffset);
3354 +extern ssize_t cifs_write(struct file *file, const char *write_data,
3355 + size_t write_size, loff_t * poffset);
3356 +extern int cifs_lock(struct file *, int, struct file_lock *);
3357 +extern int cifs_fsync(struct file *, struct dentry *, int);
3358 +extern int cifs_flush(struct file *);
3359 +extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
3360 +extern struct file_operations cifs_dir_ops;
3361 +extern int cifs_dir_open(struct inode *inode, struct file *file);
3362 +extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
3363 +extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *);
3364 +
3365 +/* Functions related to dir entries */
3366 +extern struct dentry_operations cifs_dentry_ops;
3367 +
3368 +/* Functions related to symlinks */
3369 +extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
3370 +extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
3371 +extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
3372 + const char *symname);
3373 +extern int cifs_removexattr(struct dentry *, const char *);
3374 +extern int cifs_setxattr(struct dentry *, const char *, const void *,
3375 + size_t, int);
3376 +extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
3377 +extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
3378 +#define CIFS_VERSION "1.20"
3379 +#endif /* _CIFSFS_H */
3380 Index: linux-2.4.35.4/fs/cifs/cifs_fs_sb.h
3381 ===================================================================
3382 --- /dev/null
3383 +++ linux-2.4.35.4/fs/cifs/cifs_fs_sb.h
3384 @@ -0,0 +1,32 @@
3385 +/*
3386 + * fs/cifs/cifs_fs_sb.h
3387 + *
3388 + * Copyright (c) International Business Machines Corp., 2002
3389 + * Author(s): Steve French (sfrench@us.ibm.com)
3390 + *
3391 + * This library is free software; you can redistribute it and/or modify
3392 + * it under the terms of the GNU Lesser General Public License as published
3393 + * by the Free Software Foundation; either version 2.1 of the License, or
3394 + * (at your option) any later version.
3395 + *
3396 + * This library is distributed in the hope that it will be useful,
3397 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3398 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3399 + * the GNU Lesser General Public License for more details.
3400 + *
3401 + */
3402 +#ifndef _CIFS_FS_SB_H
3403 +#define _CIFS_FS_SB_H
3404 +
3405 +struct cifs_sb_info {
3406 + struct cifsTconInfo *tcon; /* primary mount */
3407 + struct list_head nested_tcon_q;
3408 + struct nls_table *local_nls;
3409 + unsigned int rsize;
3410 + unsigned int wsize;
3411 + uid_t mnt_uid;
3412 + gid_t mnt_gid;
3413 + mode_t mnt_file_mode;
3414 + mode_t mnt_dir_mode;
3415 +};
3416 +#endif /* _CIFS_FS_SB_H */
3417 Index: linux-2.4.35.4/fs/cifs/cifsglob.h
3418 ===================================================================
3419 --- /dev/null
3420 +++ linux-2.4.35.4/fs/cifs/cifsglob.h
3421 @@ -0,0 +1,413 @@
3422 +/*
3423 + * fs/cifs/cifsglob.h
3424 + *
3425 + * Copyright (C) International Business Machines Corp., 2002,2003
3426 + * Author(s): Steve French (sfrench@us.ibm.com)
3427 + *
3428 + * This library is free software; you can redistribute it and/or modify
3429 + * it under the terms of the GNU Lesser General Public License as published
3430 + * by the Free Software Foundation; either version 2.1 of the License, or
3431 + * (at your option) any later version.
3432 + *
3433 + * This library is distributed in the hope that it will be useful,
3434 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3435 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3436 + * the GNU Lesser General Public License for more details.
3437 + *
3438 + */
3439 +#include <linux/in.h>
3440 +#include <linux/in6.h>
3441 +#include "cifs_fs_sb.h"
3442 +/*
3443 + * The sizes of various internal tables and strings
3444 + */
3445 +#define MAX_UID_INFO 16
3446 +#define MAX_SES_INFO 2
3447 +#define MAX_TCON_INFO 4
3448 +
3449 +#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
3450 +#define MAX_SERVER_SIZE 15
3451 +#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
3452 +#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
3453 + termination then *2 for unicode versions */
3454 +#define MAX_PASSWORD_SIZE 16
3455 +
3456 +/*
3457 + * MAX_REQ is the maximum number of requests that WE will send
3458 + * on one socket concurently. It also matches the most common
3459 + * value of max multiplex returned by servers. We may
3460 + * eventually want to use the negotiated value (in case
3461 + * future servers can handle more) when we are more confident that
3462 + * we will not have problems oveloading the socket with pending
3463 + * write data.
3464 + */
3465 +#define CIFS_MAX_REQ 50
3466 +
3467 +#define SERVER_NAME_LENGTH 15
3468 +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
3469 +
3470 +/* used to define string lengths for reversing unicode strings */
3471 +/* (256+1)*2 = 514 */
3472 +/* (max path length + 1 for null) * 2 for unicode */
3473 +#define MAX_NAME 514
3474 +
3475 +#include "cifspdu.h"
3476 +
3477 +#ifndef FALSE
3478 +#define FALSE 0
3479 +#endif
3480 +
3481 +#ifndef TRUE
3482 +#define TRUE 1
3483 +#endif
3484 +
3485 +#ifndef XATTR_DOS_ATTRIB
3486 +#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
3487 +#endif
3488 +
3489 +/*
3490 + * This information is kept on every Server we know about.
3491 + *
3492 + * Some things to note:
3493 + *
3494 + */
3495 +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
3496 +
3497 +/*
3498 + * CIFS vfs client Status information (based on what we know.)
3499 + */
3500 +
3501 + /* associated with each tcp and smb session */
3502 +enum statusEnum {
3503 + CifsNew = 0,
3504 + CifsGood,
3505 + CifsExiting,
3506 + CifsNeedReconnect
3507 +};
3508 +
3509 +enum securityEnum {
3510 + NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
3511 + NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
3512 + RawNTLMSSP, /* NTLMSSP without SPNEGO */
3513 + NTLMSSP, /* NTLMSSP via SPNEGO */
3514 + Kerberos /* Kerberos via SPNEGO */
3515 +};
3516 +
3517 +enum protocolEnum {
3518 + IPV4 = 0,
3519 + IPV6,
3520 + SCTP
3521 + /* Netbios frames protocol not supported at this time */
3522 +};
3523 +
3524 +/*
3525 + *****************************************************************
3526 + * Except the CIFS PDUs themselves all the
3527 + * globally interesting structs should go here
3528 + *****************************************************************
3529 + */
3530 +
3531 +struct TCP_Server_Info {
3532 + char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
3533 + char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
3534 + struct socket *ssocket;
3535 + union {
3536 + struct sockaddr_in sockAddr;
3537 + struct sockaddr_in6 sockAddr6;
3538 + } addr;
3539 + wait_queue_head_t response_q;
3540 + wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
3541 + struct list_head pending_mid_q;
3542 + void *Server_NlsInfo; /* BB - placeholder for future NLS info */
3543 + unsigned short server_codepage; /* codepage for the server */
3544 + unsigned long ip_address; /* IP addr for the server if known */
3545 + enum protocolEnum protocolType;
3546 + char versionMajor;
3547 + char versionMinor;
3548 + int svlocal:1; /* local server or remote */
3549 + atomic_t socketUseCount; /* number of open cifs sessions on socket */
3550 + atomic_t inFlight; /* number of requests on the wire to server */
3551 + enum statusEnum tcpStatus; /* what we think the status is */
3552 + struct semaphore tcpSem;
3553 + struct task_struct *tsk;
3554 + char server_GUID[16];
3555 + char secMode;
3556 + enum securityEnum secType;
3557 + unsigned int maxReq; /* Clients should submit no more */
3558 + /* than maxReq distinct unanswered SMBs to the server when using */
3559 + /* multiplexed reads or writes */
3560 + unsigned int maxBuf; /* maxBuf specifies the maximum */
3561 + /* message size the server can send or receive for non-raw SMBs */
3562 + unsigned int maxRw; /* maxRw specifies the maximum */
3563 + /* message size the server can send or receive for */
3564 + /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
3565 + char sessid[4]; /* unique token id for this session */
3566 + /* (returned on Negotiate */
3567 + int capabilities; /* allow selective disabling of caps by smb sess */
3568 + __u16 timeZone;
3569 + char cryptKey[CIFS_CRYPTO_KEY_SIZE];
3570 + char workstation_RFC1001_name[16]; /* 16th byte is always zero */
3571 +};
3572 +
3573 +/*
3574 + * The following is our shortcut to user information. We surface the uid,
3575 + * and name. We always get the password on the fly in case it
3576 + * has changed. We also hang a list of sessions owned by this user off here.
3577 + */
3578 +struct cifsUidInfo {
3579 + struct list_head userList;
3580 + struct list_head sessionList; /* SMB sessions for this user */
3581 + uid_t linux_uid;
3582 + char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
3583 + /* BB may need ptr or callback for PAM or WinBind info */
3584 +};
3585 +
3586 +/*
3587 + * Session structure. One of these for each uid session with a particular host
3588 + */
3589 +struct cifsSesInfo {
3590 + struct list_head cifsSessionList;
3591 + struct semaphore sesSem;
3592 + struct cifsUidInfo *uidInfo; /* pointer to user info */
3593 + struct TCP_Server_Info *server; /* pointer to server info */
3594 + atomic_t inUse; /* # of mounts (tree connections) on this ses */
3595 + enum statusEnum status;
3596 + __u32 sequence_number; /* needed for CIFS PDU signature */
3597 + __u16 ipc_tid; /* special tid for connection to IPC share */
3598 + char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
3599 + char *serverOS; /* name of operating system underlying the server */
3600 + char *serverNOS; /* name of network operating system that the server is running */
3601 + char *serverDomain; /* security realm of server */
3602 + int Suid; /* remote smb uid */
3603 + uid_t linux_uid; /* local Linux uid */
3604 + int capabilities;
3605 + char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
3606 + char userName[MAX_USERNAME_SIZE + 1];
3607 + char domainName[MAX_USERNAME_SIZE + 1];
3608 + char * password;
3609 +};
3610 +
3611 +/*
3612 + * there is one of these for each connection to a resource on a particular
3613 + * session
3614 + */
3615 +struct cifsTconInfo {
3616 + struct list_head cifsConnectionList;
3617 + struct list_head openFileList;
3618 + struct semaphore tconSem;
3619 + struct cifsSesInfo *ses; /* pointer to session associated with */
3620 + char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
3621 + char *nativeFileSystem;
3622 + __u16 tid; /* The 2 byte tree id */
3623 + __u16 Flags; /* optional support bits */
3624 + enum statusEnum tidStatus;
3625 + atomic_t useCount; /* how many mounts (explicit or implicit) to this share */
3626 +#ifdef CONFIG_CIFS_STATS
3627 + atomic_t num_smbs_sent;
3628 + atomic_t num_writes;
3629 + atomic_t num_reads;
3630 + atomic_t num_oplock_brks;
3631 + atomic_t num_opens;
3632 + atomic_t num_deletes;
3633 + atomic_t num_mkdirs;
3634 + atomic_t num_rmdirs;
3635 + atomic_t num_renames;
3636 + atomic_t num_t2renames;
3637 + __u64 bytes_read;
3638 + __u64 bytes_written;
3639 + spinlock_t stat_lock;
3640 +#endif
3641 + FILE_SYSTEM_DEVICE_INFO fsDevInfo;
3642 + FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
3643 + FILE_SYSTEM_UNIX_INFO fsUnixInfo;
3644 + int retry:1;
3645 + /* BB add field for back pointer to sb struct? */
3646 +};
3647 +
3648 +/*
3649 + * This info hangs off the cifsFileInfo structure. This is used to track
3650 + * byte stream locks on the file
3651 + */
3652 +struct cifsLockInfo {
3653 + struct cifsLockInfo *next;
3654 + int start;
3655 + int length;
3656 + int type;
3657 +};
3658 +
3659 +/*
3660 + * One of these for each open instance of a file
3661 + */
3662 +struct cifsFileInfo {
3663 + struct list_head tlist; /* pointer to next fid owned by tcon */
3664 + struct list_head flist; /* next fid (file instance) for this inode */
3665 + unsigned int uid; /* allows finding which FileInfo structure */
3666 + __u32 pid; /* process id who opened file */
3667 + __u16 netfid; /* file id from remote */
3668 + /* BB add lock scope info here if needed */ ;
3669 + /* lock scope id (0 if none) */
3670 + struct file * pfile; /* needed for writepage */
3671 + struct inode * pInode; /* needed for oplock break */
3672 + int endOfSearch:1; /* we have reached end of search */
3673 + int closePend:1; /* file is marked to close */
3674 + int emptyDir:1;
3675 + int invalidHandle:1; /* file closed via session abend */
3676 + struct semaphore fh_sem; /* prevents reopen race after dead ses*/
3677 + char * search_resume_name;
3678 + unsigned int resume_name_length;
3679 + __u32 resume_key;
3680 +};
3681 +
3682 +/*
3683 + * One of these for each file inode
3684 + */
3685 +
3686 +struct cifsInodeInfo {
3687 + struct list_head lockList;
3688 + /* BB add in lists for dirty pages - i.e. write caching info for oplock */
3689 + struct list_head openFileList;
3690 + int write_behind_rc;
3691 + __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
3692 + atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
3693 + unsigned long time; /* jiffies of last update/check of inode */
3694 + int clientCanCacheRead:1; /* read oplock */
3695 + int clientCanCacheAll:1; /* read and writebehind oplock */
3696 + int oplockPending:1;
3697 + struct inode vfs_inode;
3698 +};
3699 +
3700 +static inline struct cifsInodeInfo * CIFS_I(struct inode *inode)
3701 +{
3702 + return (struct cifsInodeInfo *)&(inode->u);
3703 +}
3704 +
3705 +static inline struct cifs_sb_info * CIFS_SB(struct super_block *sb)
3706 +{
3707 + return (struct cifs_sb_info *) &(sb->u);
3708 +}
3709 +
3710 +
3711 +/* one of these for every pending CIFS request to the server */
3712 +struct mid_q_entry {
3713 + struct list_head qhead; /* mids waiting on reply from this server */
3714 + __u16 mid; /* multiplex id */
3715 + __u16 pid; /* process id */
3716 + __u32 sequence_number; /* for CIFS signing */
3717 + __u16 command; /* smb command code */
3718 + struct timeval when_sent; /* time when smb sent */
3719 + struct cifsSesInfo *ses; /* smb was sent to this server */
3720 + struct task_struct *tsk; /* task waiting for response */
3721 + struct smb_hdr *resp_buf; /* response buffer */
3722 + int midState; /* wish this were enum but can not pass to wait_event */
3723 +};
3724 +
3725 +struct oplock_q_entry {
3726 + struct list_head qhead;
3727 + struct inode * pinode;
3728 + struct cifsTconInfo * tcon;
3729 + __u16 netfid;
3730 +};
3731 +
3732 +#define MID_FREE 0
3733 +#define MID_REQUEST_ALLOCATED 1
3734 +#define MID_REQUEST_SUBMITTED 2
3735 +#define MID_RESPONSE_RECEIVED 4
3736 +#define MID_RETRY_NEEDED 8 /* session closed while this request out */
3737 +
3738 +/*
3739 + *****************************************************************
3740 + * All constants go here
3741 + *****************************************************************
3742 + */
3743 +
3744 +#define UID_HASH (16)
3745 +
3746 +/*
3747 + * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
3748 + * following to be declared.
3749 + */
3750 +
3751 +/****************************************************************************
3752 + * Locking notes. All updates to global variables and lists should be
3753 + * protected by spinlocks or semaphores.
3754 + *
3755 + * Spinlocks
3756 + * ---------
3757 + * GlobalMid_Lock protects:
3758 + * list operations on pending_mid_q and oplockQ
3759 + * updates to XID counters, multiplex id and SMB sequence numbers
3760 + * GlobalSMBSesLock protects:
3761 + * list operations on tcp and SMB session lists and tCon lists
3762 + * f_owner.lock protects certain per file struct operations
3763 + * mapping->page_lock protects certain per page operations
3764 + *
3765 + * Semaphores
3766 + * ----------
3767 + * sesSem operations on smb session
3768 + * tconSem operations on tree connection
3769 + * fh_sem file handle reconnection operations
3770 + *
3771 + ****************************************************************************/
3772 +
3773 +#ifdef DECLARE_GLOBALS_HERE
3774 +#define GLOBAL_EXTERN
3775 +#else
3776 +#define GLOBAL_EXTERN extern
3777 +#endif
3778 +
3779 +/*
3780 + * The list of servers that did not respond with NT LM 0.12.
3781 + * This list helps improve performance and eliminate the messages indicating
3782 + * that we had a communications error talking to the server in this list.
3783 + */
3784 +GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
3785 +
3786 +/*
3787 + * The following is a hash table of all the users we know about.
3788 + */
3789 +GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
3790 +
3791 +GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
3792 +GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
3793 +GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
3794 +GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
3795 +
3796 +GLOBAL_EXTERN struct list_head GlobalOplock_Q;
3797 +
3798 +/*
3799 + * Global transaction id (XID) information
3800 + */
3801 +GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
3802 +GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
3803 +GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
3804 +GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
3805 + /* on midQ entries */
3806 +GLOBAL_EXTERN char Local_System_Name[15];
3807 +
3808 +/*
3809 + * Global counters, updated atomically
3810 + */
3811 +GLOBAL_EXTERN atomic_t sesInfoAllocCount;
3812 +GLOBAL_EXTERN atomic_t tconInfoAllocCount;
3813 +
3814 +GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
3815 +GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
3816 +
3817 +/* Various Debug counters to remove someday (BB) */
3818 +GLOBAL_EXTERN atomic_t bufAllocCount;
3819 +GLOBAL_EXTERN atomic_t midCount;
3820 +
3821 +/* Misc globals */
3822 +GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
3823 + to be established on existing mount if we
3824 + have the uid/password or Kerberos credential
3825 + or equivalent for current user */
3826 +GLOBAL_EXTERN unsigned int oplockEnabled;
3827 +GLOBAL_EXTERN unsigned int quotaEnabled;
3828 +GLOBAL_EXTERN unsigned int lookupCacheEnabled;
3829 +GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
3830 + with more secure ntlmssp2 challenge/resp */
3831 +GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
3832 +GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
3833 +GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */
3834 +
3835 Index: linux-2.4.35.4/fs/cifs/cifspdu.h
3836 ===================================================================
3837 --- /dev/null
3838 +++ linux-2.4.35.4/fs/cifs/cifspdu.h
3839 @@ -0,0 +1,1793 @@
3840 +/*
3841 + * fs/cifs/cifspdu.h
3842 + *
3843 + * Copyright (c) International Business Machines Corp., 2002
3844 + * Author(s): Steve French (sfrench@us.ibm.com)
3845 + *
3846 + * This library is free software; you can redistribute it and/or modify
3847 + * it under the terms of the GNU Lesser General Public License as published
3848 + * by the Free Software Foundation; either version 2.1 of the License, or
3849 + * (at your option) any later version.
3850 + *
3851 + * This library is distributed in the hope that it will be useful,
3852 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3853 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3854 + * the GNU Lesser General Public License for more details.
3855 + *
3856 + * You should have received a copy of the GNU Lesser General Public License
3857 + * along with this library; if not, write to the Free Software
3858 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3859 + */
3860 +
3861 +#ifndef _CIFSPDU_H
3862 +#define _CIFSPDU_H
3863 +
3864 +#include <net/sock.h>
3865 +
3866 +#define CIFS_PROT 0
3867 +#define BAD_PROT CIFS_PROT+1
3868 +
3869 +/* SMB command codes */
3870 +#define SMB_COM_CREATE_DIRECTORY 0x00
3871 +#define SMB_COM_DELETE_DIRECTORY 0x01
3872 +#define SMB_COM_CLOSE 0x04
3873 +#define SMB_COM_DELETE 0x06
3874 +#define SMB_COM_RENAME 0x07
3875 +#define SMB_COM_LOCKING_ANDX 0x24
3876 +#define SMB_COM_COPY 0x29
3877 +#define SMB_COM_READ_ANDX 0x2E
3878 +#define SMB_COM_WRITE_ANDX 0x2F
3879 +#define SMB_COM_TRANSACTION2 0x32
3880 +#define SMB_COM_TRANSACTION2_SECONDARY 0x33
3881 +#define SMB_COM_FIND_CLOSE2 0x34
3882 +#define SMB_COM_TREE_DISCONNECT 0x71
3883 +#define SMB_COM_NEGOTIATE 0x72
3884 +#define SMB_COM_SESSION_SETUP_ANDX 0x73
3885 +#define SMB_COM_LOGOFF_ANDX 0x74
3886 +#define SMB_COM_TREE_CONNECT_ANDX 0x75
3887 +#define SMB_COM_NT_TRANSACT 0xA0
3888 +#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
3889 +#define SMB_COM_NT_CREATE_ANDX 0xA2
3890 +#define SMB_COM_NT_RENAME 0xA5
3891 +
3892 +/* Transact2 subcommand codes */
3893 +#define TRANS2_OPEN 0x00
3894 +#define TRANS2_FIND_FIRST 0x01
3895 +#define TRANS2_FIND_NEXT 0x02
3896 +#define TRANS2_QUERY_FS_INFORMATION 0x03
3897 +#define TRANS2_QUERY_PATH_INFORMATION 0x05
3898 +#define TRANS2_SET_PATH_INFORMATION 0x06
3899 +#define TRANS2_QUERY_FILE_INFORMATION 0x07
3900 +#define TRANS2_SET_FILE_INFORMATION 0x08
3901 +#define TRANS2_GET_DFS_REFERRAL 0x10
3902 +#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
3903 +
3904 +/* NT Transact subcommand codes */
3905 +#define NT_TRANSACT_CREATE 0x01
3906 +#define NT_TRANSACT_IOCTL 0x02
3907 +#define NT_TRANSACT_SET_SECURITY_DESC 0x03
3908 +#define NT_TRANSACT_NOTIFY_CHANGE 0x04
3909 +#define NT_TRANSACT_RENAME 0x05
3910 +#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
3911 +#define NT_TRANSACT_GET_USER_QUOTA 0x07
3912 +#define NT_TRANSACT_SET_USER_QUOTA 0x08
3913 +
3914 +#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
3915 +
3916 +/* internal cifs vfs structures */
3917 +/*****************************************************************
3918 + * All constants go here
3919 + *****************************************************************
3920 + */
3921 +
3922 +/*
3923 + * Starting value for maximum SMB size negotiation
3924 + */
3925 +#define CIFS_MAX_MSGSIZE (4*4096)
3926 +
3927 +/*
3928 + * Size of encrypted user password in bytes
3929 + */
3930 +#define CIFS_ENCPWD_SIZE (16)
3931 +
3932 +/*
3933 + * Size of the crypto key returned on the negotiate SMB in bytes
3934 + */
3935 +#define CIFS_CRYPTO_KEY_SIZE (8)
3936 +
3937 +/*
3938 + * Size of the session key (crypto key encrypted with the password
3939 + */
3940 +#define CIFS_SESSION_KEY_SIZE (24)
3941 +
3942 +/*
3943 + * Maximum user name length
3944 + */
3945 +#define CIFS_UNLEN (20)
3946 +
3947 +/*
3948 + * Flags on SMB open
3949 + */
3950 +#define SMBOPEN_WRITE_THROUGH 0x4000
3951 +#define SMBOPEN_DENY_ALL 0x0010
3952 +#define SMBOPEN_DENY_WRITE 0x0020
3953 +#define SMBOPEN_DENY_READ 0x0030
3954 +#define SMBOPEN_DENY_NONE 0x0040
3955 +#define SMBOPEN_READ 0x0000
3956 +#define SMBOPEN_WRITE 0x0001
3957 +#define SMBOPEN_READWRITE 0x0002
3958 +#define SMBOPEN_EXECUTE 0x0003
3959 +
3960 +#define SMBOPEN_OCREATE 0x0010
3961 +#define SMBOPEN_OTRUNC 0x0002
3962 +#define SMBOPEN_OAPPEND 0x0001
3963 +
3964 +/*
3965 + * SMB flag definitions
3966 + */
3967 +#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
3968 +#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
3969 +#define SMBFLG_RSVD 0x04
3970 +#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
3971 +#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
3972 +#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
3973 +#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
3974 +#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
3975 +
3976 +/*
3977 + * SMB flag2 definitions
3978 + */
3979 +#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */
3980 +#define SMBFLG2_KNOWS_EAS 0x0002
3981 +#define SMBFLG2_SECURITY_SIGNATURE 0x0004
3982 +#define SMBFLG2_IS_LONG_NAME 0x0040
3983 +#define SMBFLG2_EXT_SEC 0x0800
3984 +#define SMBFLG2_DFS 0x1000
3985 +#define SMBFLG2_PAGING_IO 0x2000
3986 +#define SMBFLG2_ERR_STATUS 0x4000
3987 +#define SMBFLG2_UNICODE 0x8000
3988 +
3989 +/*
3990 + * These are the file access permission bits defined in CIFS for the
3991 + * NTCreateAndX as well as the level 0x107
3992 + * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
3993 + * responds with the AccessFlags.
3994 + * The AccessFlags specifies the access permissions a caller has to the
3995 + * file and can have any suitable combination of the following values:
3996 + */
3997 +
3998 +#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
3999 +#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
4000 +#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
4001 +#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
4002 + /* with the file can be read */
4003 +#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
4004 + /* with the file can be written */
4005 +#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
4006 + /* the file using system paging I/O */
4007 +#define FILE_DELETE_CHILD 0x00000040
4008 +#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
4009 + /* file can be read */
4010 +#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
4011 + /* file can be written */
4012 +#define DELETE 0x00010000 /* The file can be deleted */
4013 +#define READ_CONTROL 0x00020000 /* The access control list and */
4014 + /* ownership associated with the */
4015 + /* file can be read */
4016 +#define WRITE_DAC 0x00040000 /* The access control list and */
4017 + /* ownership associated with the */
4018 + /* file can be written. */
4019 +#define WRITE_OWNER 0x00080000 /* Ownership information associated */
4020 + /* with the file can be written */
4021 +#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
4022 + /* synchronize with the completion */
4023 + /* of an input/output request */
4024 +#define GENERIC_ALL 0x10000000
4025 +#define GENERIC_EXECUTE 0x20000000
4026 +#define GENERIC_WRITE 0x40000000
4027 +#define GENERIC_READ 0x80000000
4028 + /* In summary - Relevant file */
4029 + /* access flags from CIFS are */
4030 + /* file_read_data, file_write_data */
4031 + /* file_execute, file_read_attributes */
4032 + /* write_dac, and delete. */
4033 +
4034 +/*
4035 + * Invalid readdir handle
4036 + */
4037 +#define CIFS_NO_HANDLE 0xFFFF
4038 +
4039 +/* IPC$ in ASCII */
4040 +#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
4041 +
4042 +/* IPC$ in Unicode */
4043 +#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
4044 +
4045 +/* Unicode Null terminate 2 bytes of 0 */
4046 +#define UNICODE_NULL "\x00\x00"
4047 +#define ASCII_NULL 0x00
4048 +
4049 +/*
4050 + * Server type values (returned on EnumServer API
4051 + */
4052 +#define CIFS_SV_TYPE_DC 0x00000008
4053 +#define CIFS_SV_TYPE_BACKDC 0x00000010
4054 +
4055 +/*
4056 + * Alias type flags (From EnumAlias API call
4057 + */
4058 +#define CIFS_ALIAS_TYPE_FILE 0x0001
4059 +#define CIFS_SHARE_TYPE_FILE 0x0000
4060 +
4061 +/*
4062 + * File Attribute flags
4063 + */
4064 +#define ATTR_READONLY 0x0001
4065 +#define ATTR_HIDDEN 0x0002
4066 +#define ATTR_SYSTEM 0x0004
4067 +#define ATTR_VOLUME 0x0008
4068 +#define ATTR_DIRECTORY 0x0010
4069 +#define ATTR_ARCHIVE 0x0020
4070 +#define ATTR_DEVICE 0x0040
4071 +#define ATTR_NORMAL 0x0080
4072 +#define ATTR_TEMPORARY 0x0100
4073 +#define ATTR_SPARSE 0x0200
4074 +#define ATTR_REPARSE 0x0400
4075 +#define ATTR_COMPRESSED 0x0800
4076 +#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
4077 +#define ATTR_NOT_CONTENT_INDEXED 0x2000
4078 +#define ATTR_ENCRYPTED 0x4000
4079 +#define ATTR_POSIX_SEMANTICS 0x01000000
4080 +#define ATTR_BACKUP_SEMANTICS 0x02000000
4081 +#define ATTR_DELETE_ON_CLOSE 0x04000000
4082 +#define ATTR_SEQUENTIAL_SCAN 0x08000000
4083 +#define ATTR_RANDOM_ACCESS 0x10000000
4084 +#define ATTR_NO_BUFFERING 0x20000000
4085 +#define ATTR_WRITE_THROUGH 0x80000000
4086 +
4087 +/* ShareAccess flags */
4088 +#define FILE_NO_SHARE 0x00000000
4089 +#define FILE_SHARE_READ 0x00000001
4090 +#define FILE_SHARE_WRITE 0x00000002
4091 +#define FILE_SHARE_DELETE 0x00000004
4092 +#define FILE_SHARE_ALL 0x00000007
4093 +
4094 +/* CreateDisposition flags */
4095 +#define FILE_SUPERSEDE 0x00000000
4096 +#define FILE_OPEN 0x00000001
4097 +#define FILE_CREATE 0x00000002
4098 +#define FILE_OPEN_IF 0x00000003
4099 +#define FILE_OVERWRITE 0x00000004
4100 +#define FILE_OVERWRITE_IF 0x00000005
4101 +
4102 +/* CreateOptions */
4103 +#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
4104 +#define CREATE_WRITE_THROUGH 0x00000002
4105 +#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
4106 +#define CREATE_RANDOM_ACCESS 0x00000800
4107 +#define CREATE_DELETE_ON_CLOSE 0x00001000
4108 +#define OPEN_REPARSE_POINT 0x00200000
4109 +
4110 +/* ImpersonationLevel flags */
4111 +#define SECURITY_ANONYMOUS 0
4112 +#define SECURITY_IDENTIFICATION 1
4113 +#define SECURITY_IMPERSONATION 2
4114 +#define SECURITY_DELEGATION 3
4115 +
4116 +/* SecurityFlags */
4117 +#define SECURITY_CONTEXT_TRACKING 0x01
4118 +#define SECURITY_EFFECTIVE_ONLY 0x02
4119 +
4120 +/*
4121 + * Default PID value, used in all SMBs where the PID is not important
4122 + */
4123 +#define CIFS_DFT_PID 0x1234
4124 +
4125 +/*
4126 + * We use the same routine for Copy and Move SMBs. This flag is used to
4127 + * distinguish
4128 + */
4129 +#define CIFS_COPY_OP 1
4130 +#define CIFS_RENAME_OP 2
4131 +
4132 +#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
4133 +#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
4134 +
4135 +#pragma pack(1)
4136 +
4137 +struct smb_hdr {
4138 + __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 */
4139 + __u8 Protocol[4];
4140 + __u8 Command;
4141 + union {
4142 + struct {
4143 + __u8 ErrorClass;
4144 + __u8 Reserved;
4145 + __u16 Error; /* note: treated as little endian (le) on wire */
4146 + } DosError;
4147 + __u32 CifsError; /* note: le */
4148 + } Status;
4149 + __u8 Flags;
4150 + __u16 Flags2; /* note: le */
4151 + __u16 PidHigh; /* note: le */
4152 + union {
4153 + struct {
4154 + __u32 SequenceNumber; /* le */
4155 + __u32 Reserved; /* zero */
4156 + } Sequence;
4157 + __u8 SecuritySignature[8]; /* le */
4158 + } Signature;
4159 + __u8 pad[2];
4160 + __u16 Tid;
4161 + __u16 Pid; /* note: le */
4162 + __u16 Uid;
4163 + __u16 Mid;
4164 + __u8 WordCount;
4165 +};
4166 +/* given a pointer to an smb_hdr retrieve the value of byte count */
4167 +#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
4168 +
4169 +/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
4170 +#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
4171 +
4172 +/*
4173 + * Computer Name Length
4174 + */
4175 +#define CNLEN 15
4176 +
4177 +/*
4178 + * Share Name Length @S8A
4179 + * Note: This length is limited by the SMB used to get @S8A
4180 + * the Share info. NetShareEnum only returns 13 @S8A
4181 + * chars, including the null termination. @S8A
4182 + */
4183 +#define SNLEN 12 /*@S8A */
4184 +
4185 +/*
4186 + * Comment Length
4187 + */
4188 +#define MAXCOMMENTLEN 40
4189 +
4190 +/*
4191 + * The OS/2 maximum path name
4192 + */
4193 +#define MAX_PATHCONF 256
4194 +
4195 +/*
4196 + * SMB frame definitions (following must be packed structs)
4197 + * See the SNIA CIFS Specification for details.
4198 + *
4199 + * The Naming convention is the lower case version of the
4200 + * smb command code name for the struct and this is typedef to the
4201 + * uppercase version of the same name with the prefix SMB_ removed
4202 + * for brevity. Although typedefs are not commonly used for
4203 + * structure definitions in the Linux kernel, their use in the
4204 + * CIFS standards document, which this code is based on, may
4205 + * make this one of the cases where typedefs for structures make
4206 + * sense to improve readability for readers of the standards doc.
4207 + * Typedefs can always be removed later if they are too distracting
4208 + * and they are only used for the CIFSs PDUs themselves, not
4209 + * internal cifs vfs structures
4210 + *
4211 + */
4212 +
4213 +typedef struct negotiate_req {
4214 + struct smb_hdr hdr; /* wct = 0 */
4215 + __u16 ByteCount;
4216 + unsigned char DialectsArray[1];
4217 +} NEGOTIATE_REQ;
4218 +
4219 +typedef struct negotiate_rsp {
4220 + struct smb_hdr hdr; /* wct = 17 */
4221 + __u16 DialectIndex;
4222 + __u8 SecurityMode;
4223 + __u16 MaxMpxCount;
4224 + __u16 MaxNumberVcs;
4225 + __u32 MaxBufferSize;
4226 + __u32 MaxRawSize;
4227 + __u32 SessionKey;
4228 + __u32 Capabilities; /* see below */
4229 + __u32 SystemTimeLow;
4230 + __u32 SystemTimeHigh;
4231 + __u16 ServerTimeZone;
4232 + __u8 EncryptionKeyLength;
4233 + __u16 ByteCount;
4234 + union {
4235 + unsigned char EncryptionKey[1]; /* if cap extended security is off */
4236 + /* followed by Domain name - if extended security is off */
4237 + /* followed by 16 bytes of server GUID */
4238 + /* followed by security blob if cap_extended_security negotiated */
4239 + struct {
4240 + unsigned char GUID[16];
4241 + unsigned char SecurityBlob[1];
4242 + } extended_response;
4243 + } u;
4244 +} NEGOTIATE_RSP;
4245 +
4246 +/* SecurityMode bits */
4247 +#define SECMODE_USER 0x01 /* off indicates share level security */
4248 +#define SECMODE_PW_ENCRYPT 0x02
4249 +#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
4250 +#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
4251 +
4252 +/* Negotiate response Capabilities */
4253 +#define CAP_RAW_MODE 0x00000001
4254 +#define CAP_MPX_MODE 0x00000002
4255 +#define CAP_UNICODE 0x00000004
4256 +#define CAP_LARGE_FILES 0x00000008
4257 +#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
4258 +#define CAP_RPC_REMOTE_APIS 0x00000020
4259 +#define CAP_STATUS32 0x00000040
4260 +#define CAP_LEVEL_II_OPLOCKS 0x00000080
4261 +#define CAP_LOCK_AND_READ 0x00000100
4262 +#define CAP_NT_FIND 0x00000200
4263 +#define CAP_DFS 0x00001000
4264 +#define CAP_INFOLEVEL_PASSTHRU 0x00002000
4265 +#define CAP_LARGE_READ_X 0x00004000
4266 +#define CAP_LARGE_WRITE_X 0x00008000
4267 +#define CAP_UNIX 0x00800000
4268 +#define CAP_RESERVED 0x02000000
4269 +#define CAP_BULK_TRANSFER 0x20000000
4270 +#define CAP_COMPRESSED_DATA 0x40000000
4271 +#define CAP_EXTENDED_SECURITY 0x80000000
4272 +
4273 +typedef union smb_com_session_setup_andx {
4274 + struct { /* request format */
4275 + struct smb_hdr hdr; /* wct = 12 */
4276 + __u8 AndXCommand;
4277 + __u8 AndXReserved;
4278 + __u16 AndXOffset;
4279 + __u16 MaxBufferSize;
4280 + __u16 MaxMpxCount;
4281 + __u16 VcNumber;
4282 + __u32 SessionKey;
4283 + __u16 SecurityBlobLength;
4284 + __u32 Reserved;
4285 + __u32 Capabilities; /* see below */
4286 + __u16 ByteCount;
4287 + unsigned char SecurityBlob[1]; /* followed by */
4288 + /* STRING NativeOS */
4289 + /* STRING NativeLanMan */
4290 + } req; /* NTLM request format (with extended security */
4291 +
4292 + struct { /* request format */
4293 + struct smb_hdr hdr; /* wct = 13 */
4294 + __u8 AndXCommand;
4295 + __u8 AndXReserved;
4296 + __u16 AndXOffset;
4297 + __u16 MaxBufferSize;
4298 + __u16 MaxMpxCount;
4299 + __u16 VcNumber;
4300 + __u32 SessionKey;
4301 + __u16 CaseInsensitivePasswordLength; /* ASCII password length */
4302 + __u16 CaseSensitivePasswordLength; /* Unicode password length */
4303 + __u32 Reserved; /* see below */
4304 + __u32 Capabilities;
4305 + __u16 ByteCount;
4306 + unsigned char CaseInsensitivePassword[1]; /* followed by: */
4307 + /* unsigned char * CaseSensitivePassword; */
4308 + /* STRING AccountName */
4309 + /* STRING PrimaryDomain */
4310 + /* STRING NativeOS */
4311 + /* STRING NativeLanMan */
4312 + } req_no_secext; /* NTLM request format (without extended security */
4313 +
4314 + struct { /* default (NTLM) response format */
4315 + struct smb_hdr hdr; /* wct = 4 */
4316 + __u8 AndXCommand;
4317 + __u8 AndXReserved;
4318 + __u16 AndXOffset;
4319 + __u16 Action; /* see below */
4320 + __u16 SecurityBlobLength;
4321 + __u16 ByteCount;
4322 + unsigned char SecurityBlob[1]; /* followed by */
4323 +/* unsigned char * NativeOS; */
4324 +/* unsigned char * NativeLanMan; */
4325 +/* unsigned char * PrimaryDomain; */
4326 + } resp; /* NTLM response format (with or without extended security */
4327 +
4328 + struct { /* request format */
4329 + struct smb_hdr hdr; /* wct = 10 */
4330 + __u8 AndXCommand;
4331 + __u8 AndXReserved;
4332 + __u16 AndXOffset;
4333 + __u16 MaxBufferSize;
4334 + __u16 MaxMpxCount;
4335 + __u16 VcNumber;
4336 + __u32 SessionKey;
4337 + __u16 PassswordLength;
4338 + __u32 Reserved;
4339 + __u16 ByteCount;
4340 + unsigned char AccountPassword[1]; /* followed by */
4341 + /* STRING AccountName */
4342 + /* STRING PrimaryDomain */
4343 + /* STRING NativeOS */
4344 + /* STRING NativeLanMan */
4345 + } old_req; /* pre-NTLM (LANMAN2.1) request format */
4346 +
4347 + struct { /* default (NTLM) response format */
4348 + struct smb_hdr hdr; /* wct = 3 */
4349 + __u8 AndXCommand;
4350 + __u8 AndXReserved;
4351 + __u16 AndXOffset;
4352 + __u16 Action; /* see below */
4353 + __u16 ByteCount;
4354 + unsigned char NativeOS[1]; /* followed by */
4355 +/* unsigned char * NativeLanMan; */
4356 +/* unsigned char * PrimaryDomain; */
4357 + } old_resp; /* pre-NTLM (LANMAN2.1) response format */
4358 +} SESSION_SETUP_ANDX;
4359 +
4360 +#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
4361 +
4362 +/* Capabilities bits (for NTLM SessSetup request) */
4363 +#define CAP_UNICODE 0x00000004
4364 +#define CAP_LARGE_FILES 0x00000008
4365 +#define CAP_NT_SMBS 0x00000010
4366 +#define CAP_STATUS32 0x00000040
4367 +#define CAP_LEVEL_II_OPLOCKS 0x00000080
4368 +#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
4369 +#define CAP_BULK_TRANSFER 0x20000000
4370 +#define CAP_EXTENDED_SECURITY 0x80000000
4371 +
4372 +/* Action bits */
4373 +#define GUEST_LOGIN 1
4374 +
4375 +typedef struct smb_com_tconx_req {
4376 + struct smb_hdr hdr; /* wct = 4 */
4377 + __u8 AndXCommand;
4378 + __u8 AndXReserved;
4379 + __u16 AndXOffset;
4380 + __u16 Flags; /* see below */
4381 + __u16 PasswordLength;
4382 + __u16 ByteCount;
4383 + unsigned char Password[1]; /* followed by */
4384 +/* STRING Path *//* \\server\share name */
4385 + /* STRING Service */
4386 +} TCONX_REQ;
4387 +
4388 +typedef struct smb_com_tconx_rsp {
4389 + struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
4390 + __u8 AndXCommand;
4391 + __u8 AndXReserved;
4392 + __u16 AndXOffset;
4393 + __u16 OptionalSupport; /* see below */
4394 + __u16 ByteCount;
4395 + unsigned char Service[1]; /* always ASCII, not Unicode */
4396 + /* STRING NativeFileSystem */
4397 +} TCONX_RSP;
4398 +
4399 +/* tree connect Flags */
4400 +#define DISCONNECT_TID 0x0001
4401 +#define TCON_EXTENDED_SECINFO 0x0008
4402 +/* OptionalSupport bits */
4403 +#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
4404 +#define SMB_SHARE_IS_IN_DFS 0x0002
4405 +
4406 +typedef struct smb_com_logoff_andx_req {
4407 +
4408 + struct smb_hdr hdr; /* wct = 2 */
4409 + __u8 AndXCommand;
4410 + __u8 AndXReserved;
4411 + __u16 AndXOffset;
4412 + __u16 ByteCount;
4413 +} LOGOFF_ANDX_REQ;
4414 +
4415 +typedef struct smb_com_logoff_andx_rsp {
4416 + struct smb_hdr hdr; /* wct = 2 */
4417 + __u8 AndXCommand;
4418 + __u8 AndXReserved;
4419 + __u16 AndXOffset;
4420 + __u16 ByteCount;
4421 +} LOGOFF_ANDX_RSP;
4422 +
4423 +typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
4424 + struct {
4425 + struct smb_hdr hdr; /* wct = 0 */
4426 + __u16 ByteCount; /* bcc = 0 */
4427 + } req;
4428 + struct {
4429 + struct smb_hdr hdr; /* wct = 0 */
4430 + __u16 ByteCount; /* bcc = 0 */
4431 + } resp;
4432 +} TREE_DISCONNECT;
4433 +
4434 +typedef struct smb_com_close_req {
4435 + struct smb_hdr hdr; /* wct = 3 */
4436 + __u16 FileID;
4437 + __u32 LastWriteTime; /* should be zero */
4438 + __u16 ByteCount; /* 0 */
4439 +} CLOSE_REQ;
4440 +
4441 +typedef struct smb_com_close_rsp {
4442 + struct smb_hdr hdr; /* wct = 0 */
4443 + __u16 ByteCount; /* bct = 0 */
4444 +} CLOSE_RSP;
4445 +
4446 +typedef struct smb_com_findclose_req {
4447 + struct smb_hdr hdr; /* wct = 1 */
4448 + __u16 FileID;
4449 + __u16 ByteCount; /* 0 */
4450 +} FINDCLOSE_REQ;
4451 +
4452 +/* OpenFlags */
4453 +#define REQ_OPLOCK 0x00000002
4454 +#define REQ_BATCHOPLOCK 0x00000004
4455 +#define REQ_OPENDIRONLY 0x00000008
4456 +
4457 +typedef struct smb_com_open_req { /* also handles create */
4458 + struct smb_hdr hdr; /* wct = 24 */
4459 + __u8 AndXCommand;
4460 + __u8 AndXReserved;
4461 + __u16 AndXOffset;
4462 + __u8 Reserved; /* Must Be Zero */
4463 + __u16 NameLength;
4464 + __u32 OpenFlags;
4465 + __u32 RootDirectoryFid;
4466 + __u32 DesiredAccess;
4467 + __u64 AllocationSize;
4468 + __u32 FileAttributes;
4469 + __u32 ShareAccess;
4470 + __u32 CreateDisposition;
4471 + __u32 CreateOptions;
4472 + __u32 ImpersonationLevel;
4473 + __u8 SecurityFlags;
4474 + __u16 ByteCount;
4475 + char fileName[1];
4476 +} OPEN_REQ;
4477 +
4478 +/* open response: oplock levels */
4479 +#define OPLOCK_NONE 0
4480 +#define OPLOCK_EXCLUSIVE 1
4481 +#define OPLOCK_BATCH 2
4482 +#define OPLOCK_READ 3 /* level 2 oplock */
4483 +
4484 +/* open response for CreateAction shifted left */
4485 +#define CIFS_CREATE_ACTION 0x20000 /* file created */
4486 +
4487 +typedef struct smb_com_open_rsp {
4488 + struct smb_hdr hdr; /* wct = 34 BB */
4489 + __u8 AndXCommand;
4490 + __u8 AndXReserved;
4491 + __u16 AndXOffset;
4492 + __u8 OplockLevel;
4493 + __u16 Fid;
4494 + __u32 CreateAction;
4495 + __u64 CreationTime;
4496 + __u64 LastAccessTime;
4497 + __u64 LastWriteTime;
4498 + __u64 ChangeTime;
4499 + __u32 FileAttributes;
4500 + __u64 AllocationSize;
4501 + __u64 EndOfFile;
4502 + __u16 FileType;
4503 + __u16 DeviceState;
4504 + __u8 DirectoryFlag;
4505 + __u16 ByteCount; /* bct = 0 */
4506 +} OPEN_RSP;
4507 +
4508 +typedef struct smb_com_write_req {
4509 + struct smb_hdr hdr; /* wct = 14 */
4510 + __u8 AndXCommand;
4511 + __u8 AndXReserved;
4512 + __u16 AndXOffset;
4513 + __u16 Fid;
4514 + __u32 OffsetLow;
4515 + __u32 Reserved;
4516 + __u16 WriteMode;
4517 + __u16 Remaining;
4518 + __u16 DataLengthHigh;
4519 + __u16 DataLengthLow;
4520 + __u16 DataOffset;
4521 + __u32 OffsetHigh;
4522 + __u16 ByteCount;
4523 + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
4524 + char Data[1];
4525 +} WRITE_REQ;
4526 +
4527 +typedef struct smb_com_write_rsp {
4528 + struct smb_hdr hdr; /* wct = 6 */
4529 + __u8 AndXCommand;
4530 + __u8 AndXReserved;
4531 + __u16 AndXOffset;
4532 + __u16 Count;
4533 + __u16 Remaining;
4534 + __u32 Reserved;
4535 + __u16 ByteCount;
4536 +} WRITE_RSP;
4537 +
4538 +typedef struct smb_com_read_req {
4539 + struct smb_hdr hdr; /* wct = 12 */
4540 + __u8 AndXCommand;
4541 + __u8 AndXReserved;
4542 + __u16 AndXOffset;
4543 + __u16 Fid;
4544 + __u32 OffsetLow;
4545 + __u16 MaxCount;
4546 + __u16 MinCount; /* obsolete */
4547 + __u32 MaxCountHigh;
4548 + __u16 Remaining;
4549 + __u32 OffsetHigh;
4550 + __u16 ByteCount;
4551 +} READ_REQ;
4552 +
4553 +typedef struct smb_com_read_rsp {
4554 + struct smb_hdr hdr; /* wct = 12 */
4555 + __u8 AndXCommand;
4556 + __u8 AndXReserved;
4557 + __u16 AndXOffset;
4558 + __u16 Remaining;
4559 + __u16 DataCompactionMode;
4560 + __u16 Reserved;
4561 + __u16 DataLength;
4562 + __u16 DataOffset;
4563 + __u16 DataLengthHigh;
4564 + __u64 Reserved2;
4565 + __u16 ByteCount;
4566 + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
4567 + char Data[1];
4568 +} READ_RSP;
4569 +
4570 +typedef struct locking_andx_range {
4571 + __u16 Pid;
4572 + __u16 Pad;
4573 + __u32 OffsetHigh;
4574 + __u32 OffsetLow;
4575 + __u32 LengthHigh;
4576 + __u32 LengthLow;
4577 +} LOCKING_ANDX_RANGE;
4578 +
4579 +#define LOCKING_ANDX_SHARED_LOCK 0x01
4580 +#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
4581 +#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
4582 +#define LOCKING_ANDX_CANCEL_LOCK 0x08
4583 +#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
4584 +
4585 +typedef struct smb_com_lock_req {
4586 + struct smb_hdr hdr; /* wct = 8 */
4587 + __u8 AndXCommand;
4588 + __u8 AndXReserved;
4589 + __u16 AndXOffset;
4590 + __u16 Fid;
4591 + __u8 LockType;
4592 + __u8 OplockLevel;
4593 + __u32 Timeout;
4594 + __u16 NumberOfUnlocks;
4595 + __u16 NumberOfLocks;
4596 + __u16 ByteCount;
4597 + LOCKING_ANDX_RANGE Locks[1];
4598 +} LOCK_REQ;
4599 +
4600 +typedef struct smb_com_lock_rsp {
4601 + struct smb_hdr hdr; /* wct = 2 */
4602 + __u8 AndXCommand;
4603 + __u8 AndXReserved;
4604 + __u16 AndXOffset;
4605 + __u16 ByteCount;
4606 +} LOCK_RSP;
4607 +
4608 +typedef struct smb_com_rename_req {
4609 + struct smb_hdr hdr; /* wct = 1 */
4610 + __u16 SearchAttributes; /* target file attributes */
4611 + __u16 ByteCount;
4612 + __u8 BufferFormat; /* 4 = ASCII or Unicode */
4613 + unsigned char OldFileName[1];
4614 + /* followed by __u8 BufferFormat2 */
4615 + /* followed by NewFileName */
4616 +} RENAME_REQ;
4617 +
4618 + /* copy request flags */
4619 +#define COPY_MUST_BE_FILE 0x0001
4620 +#define COPY_MUST_BE_DIR 0x0002
4621 +#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
4622 +#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
4623 +#define COPY_VERIFY_WRITES 0x0010
4624 +#define COPY_TREE 0x0020
4625 +
4626 +typedef struct smb_com_copy_req {
4627 + struct smb_hdr hdr; /* wct = 3 */
4628 + __u16 Tid2;
4629 + __u16 OpenFunction;
4630 + __u16 Flags;
4631 + __u16 ByteCount;
4632 + __u8 BufferFormat; /* 4 = ASCII or Unicode */
4633 + unsigned char OldFileName[1];
4634 + /* followed by __u8 BufferFormat2 */
4635 + /* followed by NewFileName string */
4636 +} COPY_REQ;
4637 +
4638 +typedef struct smb_com_copy_rsp {
4639 + struct smb_hdr hdr; /* wct = 1 */
4640 + __u16 CopyCount; /* number of files copied */
4641 + __u16 ByteCount; /* may be zero */
4642 + __u8 BufferFormat; /* 0x04 - only present if errored file follows */
4643 + unsigned char ErrorFileName[1]; /* only present if error in copy */
4644 +} COPY_RSP;
4645 +
4646 +#define CREATE_HARD_LINK 0x103
4647 +#define MOVEFILE_COPY_ALLOWED 0x0002
4648 +#define MOVEFILE_REPLACE_EXISTING 0x0001
4649 +
4650 +typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
4651 + struct smb_hdr hdr; /* wct = 4 */
4652 + __u16 SearchAttributes; /* target file attributes */
4653 + __u16 Flags; /* spec says Information Level */
4654 + __u32 ClusterCount;
4655 + __u16 ByteCount;
4656 + __u8 BufferFormat; /* 4 = ASCII or Unicode */
4657 + unsigned char OldFileName[1];
4658 + /* followed by __u8 BufferFormat2 */
4659 + /* followed by NewFileName */
4660 +} NT_RENAME_REQ;
4661 +
4662 +typedef struct smb_com_rename_rsp {
4663 + struct smb_hdr hdr; /* wct = 0 */
4664 + __u16 ByteCount; /* bct = 0 */
4665 +} RENAME_RSP;
4666 +
4667 +typedef struct smb_com_delete_file_req {
4668 + struct smb_hdr hdr; /* wct = 1 */
4669 + __u16 SearchAttributes;
4670 + __u16 ByteCount;
4671 + __u8 BufferFormat; /* 4 = ASCII */
4672 + unsigned char fileName[1];
4673 +} DELETE_FILE_REQ;
4674 +
4675 +typedef struct smb_com_delete_file_rsp {
4676 + struct smb_hdr hdr; /* wct = 0 */
4677 + __u16 ByteCount; /* bct = 0 */
4678 +} DELETE_FILE_RSP;
4679 +
4680 +typedef struct smb_com_delete_directory_req {
4681 + struct smb_hdr hdr; /* wct = 0 */
4682 + __u16 ByteCount;
4683 + __u8 BufferFormat; /* 4 = ASCII */
4684 + unsigned char DirName[1];
4685 +} DELETE_DIRECTORY_REQ;
4686 +
4687 +typedef struct smb_com_delete_directory_rsp {
4688 + struct smb_hdr hdr; /* wct = 0 */
4689 + __u16 ByteCount; /* bct = 0 */
4690 +} DELETE_DIRECTORY_RSP;
4691 +
4692 +typedef struct smb_com_create_directory_req {
4693 + struct smb_hdr hdr; /* wct = 0 */
4694 + __u16 ByteCount;
4695 + __u8 BufferFormat; /* 4 = ASCII */
4696 + unsigned char DirName[1];
4697 +} CREATE_DIRECTORY_REQ;
4698 +
4699 +typedef struct smb_com_create_directory_rsp {
4700 + struct smb_hdr hdr; /* wct = 0 */
4701 + __u16 ByteCount; /* bct = 0 */
4702 +} CREATE_DIRECTORY_RSP;
4703 +
4704 +/***************************************************/
4705 +/* NT Transact structure defintions follow */
4706 +/* Currently only ioctl and notify are implemented */
4707 +/***************************************************/
4708 +typedef struct smb_com_transaction_ioctl_req {
4709 + struct smb_hdr hdr; /* wct = 23 */
4710 + __u8 MaxSetupCount;
4711 + __u16 Reserved;
4712 + __u32 TotalParameterCount;
4713 + __u32 TotalDataCount;
4714 + __u32 MaxParameterCount;
4715 + __u32 MaxDataCount;
4716 + __u32 ParameterCount;
4717 + __u32 ParameterOffset;
4718 + __u32 DataCount;
4719 + __u32 DataOffset;
4720 + __u8 SetupCount; /* four setup words follow subcommand */
4721 + /* SNIA spec incorrectly included spurious pad here */
4722 + __u16 SubCommand;/* 2 = IOCTL/FSCTL */
4723 + __u32 FunctionCode;
4724 + __u16 Fid;
4725 + __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
4726 + __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
4727 + __u16 ByteCount;
4728 + __u8 Pad[3];
4729 + __u8 Data[1];
4730 +} TRANSACT_IOCTL_REQ;
4731 +
4732 +typedef struct smb_com_transaction_ioctl_rsp {
4733 + struct smb_hdr hdr; /* wct = 19 */
4734 + __u8 Reserved[3];
4735 + __u32 TotalParameterCount;
4736 + __u32 TotalDataCount;
4737 + __u32 ParameterCount;
4738 + __u32 ParameterOffset;
4739 + __u32 ParameterDisplacement;
4740 + __u32 DataCount;
4741 + __u32 DataOffset;
4742 + __u32 DataDisplacement;
4743 + __u8 SetupCount; /* 1 */
4744 + __u16 ReturnedDataLen;
4745 + __u16 ByteCount;
4746 + __u8 Pad[3];
4747 +} TRANSACT_IOCTL_RSP;
4748 +
4749 +typedef struct smb_com_transaction_change_notify_req {
4750 + struct smb_hdr hdr; /* wct = 23 */
4751 + __u8 MaxSetupCount;
4752 + __u16 Reserved;
4753 + __u32 TotalParameterCount;
4754 + __u32 TotalDataCount;
4755 + __u32 MaxParameterCount;
4756 + __u32 MaxDataCount;
4757 + __u32 ParameterCount;
4758 + __u32 ParameterOffset;
4759 + __u32 DataCount;
4760 + __u32 DataOffset;
4761 + __u8 SetupCount; /* four setup words follow subcommand */
4762 + /* SNIA spec incorrectly included spurious pad here */
4763 + __u16 SubCommand;/* 4 = Change Notify */
4764 + __u32 CompletionFilter; /* operation to monitor */
4765 + __u16 Fid;
4766 + __u8 WatchTree; /* 1 = Monitor subdirectories */
4767 + __u8 Reserved2;
4768 + __u16 ByteCount;
4769 +/* __u8 Pad[3];*/
4770 +/* __u8 Data[1];*/
4771 +} TRANSACT_CHANGE_NOTIFY_REQ;
4772 +
4773 +typedef struct smb_com_transaction_change_notify_rsp {
4774 + struct smb_hdr hdr; /* wct = 18 */
4775 + __u8 Reserved[3];
4776 + __u32 TotalParameterCount;
4777 + __u32 TotalDataCount;
4778 + __u32 ParameterCount;
4779 + __u32 ParameterOffset;
4780 + __u32 ParameterDisplacement;
4781 + __u32 DataCount;
4782 + __u32 DataOffset;
4783 + __u32 DataDisplacement;
4784 + __u8 SetupCount; /* 0 */
4785 + __u16 ByteCount;
4786 + /* __u8 Pad[3]; */
4787 +} TRANSACT_CHANGE_NOTIFY_RSP;
4788 +/* Completion Filter flags for Notify */
4789 +#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
4790 +#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
4791 +#define FILE_NOTIFY_CHANGE_NAME 0x00000003
4792 +#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
4793 +#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
4794 +#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
4795 +#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
4796 +#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
4797 +#define FILE_NOTIFY_CHANGE_EA 0x00000080
4798 +#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
4799 +#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
4800 +#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
4801 +#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
4802 +
4803 +#define FILE_ACTION_ADDED 0x00000001
4804 +#define FILE_ACTION_REMOVED 0x00000002
4805 +#define FILE_ACTION_MODIFIED 0x00000003
4806 +#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
4807 +#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
4808 +#define FILE_ACTION_ADDED_STREAM 0x00000006
4809 +#define FILE_ACTION_REMOVED_STREAM 0x00000007
4810 +#define FILE_ACTION_MODIFIED_STREAM 0x00000008
4811 +
4812 +/* response contains array of the following structures */
4813 +struct file_notify_information {
4814 + __u32 NextEntryOffset;
4815 + __u32 Action;
4816 + __u32 FileNameLength;
4817 + __u8 FileName[1];
4818 +};
4819 +
4820 +struct reparse_data {
4821 + __u32 ReparseTag;
4822 + __u16 ReparseDataLength;
4823 + __u16 Reserved;
4824 + __u16 AltNameOffset;
4825 + __u16 AltNameLen;
4826 + __u16 TargetNameOffset;
4827 + __u16 TargetNameLen;
4828 + char LinkNamesBuf[1];
4829 +};
4830 +
4831 +struct cifs_quota_data {
4832 + __u32 rsrvd1; /* 0 */
4833 + __u32 sid_size;
4834 + __u64 rsrvd2; /* 0 */
4835 + __u64 space_used;
4836 + __u64 soft_limit;
4837 + __u64 hard_limit;
4838 + char sid[1]; /* variable size? */
4839 +};
4840 +
4841 +/* quota sub commands */
4842 +#define QUOTA_LIST_CONTINUE 0
4843 +#define QUOTA_LIST_START 0x100
4844 +#define QUOTA_FOR_SID 0x101
4845 +
4846 +typedef union smb_com_transaction2 {
4847 + struct {
4848 + struct smb_hdr hdr; /* wct = 14+ */
4849 + __u16 TotalParameterCount;
4850 + __u16 TotalDataCount;
4851 + __u16 MaxParameterCount;
4852 + __u16 MaxDataCount;
4853 + __u8 MaxSetupCount;
4854 + __u8 Reserved;
4855 + __u16 Flags;
4856 + __u32 Timeout;
4857 + __u16 Reserved2;
4858 + __u16 ParameterCount;
4859 + __u16 ParameterOffset;
4860 + __u16 DataCount;
4861 + __u16 DataOffset;
4862 + __u8 SetupCount;
4863 + __u8 Reserved3;
4864 + __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */
4865 + __u16 ByteCount; /* careful - setupcount is not always one */
4866 + } req;
4867 + struct {
4868 + struct smb_hdr hdr; /* wct = 0 */
4869 + __u16 TotalParameterCount;
4870 + __u16 TotalDataCount;
4871 + __u16 Reserved;
4872 + __u16 ParameterCount;
4873 + __u16 ParamterOffset;
4874 + __u16 ParameterDisplacement;
4875 + __u16 DataCount;
4876 + __u16 DataOffset;
4877 + __u16 DataDisplacement;
4878 + __u8 SetupCount;
4879 + __u8 Reserved1; /* should be zero setup words following */
4880 + __u16 ByteCount;
4881 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4882 + /* data area follows */
4883 + } resp;
4884 +} TRANSACTION2;
4885 +
4886 +/* PathInfo/FileInfo infolevels */
4887 +#define SMB_INFO_STANDARD 1
4888 +#define SMB_INFO_QUERY_EAS_FROM_LIST 3
4889 +#define SMB_INFO_QUERY_ALL_EAS 4
4890 +#define SMB_INFO_IS_NAME_VALID 6
4891 +#define SMB_QUERY_FILE_BASIC_INFO 0x101
4892 +#define SMB_QUERY_FILE_STANDARD_INFO 0x102
4893 +#define SMB_QUERY_FILE_EA_INFO 0x103
4894 +#define SMB_QUERY_FILE_NAME_INFO 0x104
4895 +#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
4896 +#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
4897 +#define SMB_QUERY_FILE_ALL_INFO 0x107
4898 +#define SMB_QUERY_ALT_NAME_INFO 0x108
4899 +#define SMB_QUERY_FILE_STREAM_INFO 0x109
4900 +#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
4901 +#define SMB_QUERY_FILE_UNIX_BASIC 0x200
4902 +#define SMB_QUERY_FILE_UNIX_LINK 0x201
4903 +
4904 +#define SMB_SET_FILE_BASIC_INFO 0x101
4905 +#define SMB_SET_FILE_DISPOSITION_INFO 0x102
4906 +#define SMB_SET_FILE_ALLOCATION_INFO 0x103
4907 +#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
4908 +#define SMB_SET_FILE_UNIX_BASIC 0x200
4909 +#define SMB_SET_FILE_UNIX_LINK 0x201
4910 +#define SMB_SET_FILE_UNIX_HLINK 0x203
4911 +#define SMB_SET_FILE_BASIC_INFO2 0x3ec
4912 +#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
4913 +#define SMB_FILE_ALL_INFO2 0x3fa
4914 +#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
4915 +#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
4916 +#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
4917 +#define SMB_FILE_QUOTA_INFO 0x408
4918 +#define SMB_FILE_REPARSEPOINT_INFO 0x409
4919 +#define SMB_FILE_MAXIMUM_INFO 0x40d
4920 +
4921 +/* Find File infolevels */
4922 +#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
4923 +#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
4924 +#define SMB_FIND_FILE_NAMES_INFO 0x103
4925 +#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
4926 +#define SMB_FIND_FILE_UNIX 0x202
4927 +
4928 +typedef struct smb_com_transaction2_qpi_req {
4929 + struct smb_hdr hdr; /* wct = 14+ */
4930 + __u16 TotalParameterCount;
4931 + __u16 TotalDataCount;
4932 + __u16 MaxParameterCount;
4933 + __u16 MaxDataCount;
4934 + __u8 MaxSetupCount;
4935 + __u8 Reserved;
4936 + __u16 Flags;
4937 + __u32 Timeout;
4938 + __u16 Reserved2;
4939 + __u16 ParameterCount;
4940 + __u16 ParameterOffset;
4941 + __u16 DataCount;
4942 + __u16 DataOffset;
4943 + __u8 SetupCount;
4944 + __u8 Reserved3;
4945 + __u16 SubCommand; /* one setup word */
4946 + __u16 ByteCount;
4947 + __u8 Pad;
4948 + __u16 InformationLevel;
4949 + __u32 Reserved4;
4950 + char FileName[1];
4951 +} TRANSACTION2_QPI_REQ;
4952 +
4953 +typedef struct smb_com_transaction2_qpi_rsp {
4954 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
4955 + __u16 TotalParameterCount;
4956 + __u16 TotalDataCount;
4957 + __u16 Reserved;
4958 + __u16 ParameterCount;
4959 + __u16 ParameterOffset;
4960 + __u16 ParameterDisplacement;
4961 + __u16 DataCount;
4962 + __u16 DataOffset;
4963 + __u16 DataDisplacement;
4964 + __u8 SetupCount;
4965 + __u8 Reserved1; /* should be zero setup words following */
4966 + __u16 ByteCount;
4967 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4968 +} TRANSACTION2_QPI_RSP;
4969 +
4970 +typedef struct smb_com_transaction2_spi_req {
4971 + struct smb_hdr hdr; /* wct = 15 */
4972 + __u16 TotalParameterCount;
4973 + __u16 TotalDataCount;
4974 + __u16 MaxParameterCount;
4975 + __u16 MaxDataCount;
4976 + __u8 MaxSetupCount;
4977 + __u8 Reserved;
4978 + __u16 Flags;
4979 + __u32 Timeout;
4980 + __u16 Reserved2;
4981 + __u16 ParameterCount;
4982 + __u16 ParameterOffset;
4983 + __u16 DataCount;
4984 + __u16 DataOffset;
4985 + __u8 SetupCount;
4986 + __u8 Reserved3;
4987 + __u16 SubCommand; /* one setup word */
4988 + __u16 ByteCount;
4989 + __u8 Pad;
4990 + __u16 Pad1;
4991 + __u16 InformationLevel;
4992 + __u32 Reserved4;
4993 + char FileName[1];
4994 +} TRANSACTION2_SPI_REQ;
4995 +
4996 +typedef struct smb_com_transaction2_spi_rsp {
4997 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
4998 + __u16 TotalParameterCount;
4999 + __u16 TotalDataCount;
5000 + __u16 Reserved;
5001 + __u16 ParameterCount;
5002 + __u16 ParameterOffset;
5003 + __u16 ParameterDisplacement;
5004 + __u16 DataCount;
5005 + __u16 DataOffset;
5006 + __u16 DataDisplacement;
5007 + __u8 SetupCount;
5008 + __u8 Reserved1; /* should be zero setup words following */
5009 + __u16 ByteCount;
5010 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
5011 +} TRANSACTION2_SPI_RSP;
5012 +
5013 +struct set_file_rename {
5014 + __u32 overwrite; /* 1 = overwrite dest */
5015 + __u32 root_fid; /* zero */
5016 + __u32 target_name_len;
5017 + char target_name[0]; /* Must be unicode */
5018 +};
5019 +
5020 +struct smb_com_transaction2_sfi_req {
5021 + struct smb_hdr hdr; /* wct = 15 */
5022 + __u16 TotalParameterCount;
5023 + __u16 TotalDataCount;
5024 + __u16 MaxParameterCount;
5025 + __u16 MaxDataCount;
5026 + __u8 MaxSetupCount;
5027 + __u8 Reserved;
5028 + __u16 Flags;
5029 + __u32 Timeout;
5030 + __u16 Reserved2;
5031 + __u16 ParameterCount;
5032 + __u16 ParameterOffset;
5033 + __u16 DataCount;
5034 + __u16 DataOffset;
5035 + __u8 SetupCount;
5036 + __u8 Reserved3;
5037 + __u16 SubCommand; /* one setup word */
5038 + __u16 ByteCount;
5039 + __u8 Pad;
5040 + __u16 Pad1;
5041 + __u16 Fid;
5042 + __u16 InformationLevel;
5043 + __u16 Reserved4;
5044 +};
5045 +
5046 +struct smb_com_transaction2_sfi_rsp {
5047 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
5048 + __u16 TotalParameterCount;
5049 + __u16 TotalDataCount;
5050 + __u16 Reserved;
5051 + __u16 ParameterCount;
5052 + __u16 ParameterOffset;
5053 + __u16 ParameterDisplacement;
5054 + __u16 DataCount;
5055 + __u16 DataOffset;
5056 + __u16 DataDisplacement;
5057 + __u8 SetupCount;
5058 + __u8 Reserved1; /* should be zero setup words following */
5059 + __u16 ByteCount;
5060 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
5061 +};
5062 +
5063 +
5064 +/*
5065 + * Flags on T2 FINDFIRST and FINDNEXT
5066 + */
5067 +#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
5068 +#define CIFS_SEARCH_CLOSE_AT_END 0x0002
5069 +#define CIFS_SEARCH_RETURN_RESUME 0x0004
5070 +#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
5071 +#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
5072 +
5073 +/*
5074 + * Size of the resume key on FINDFIRST and FINDNEXT calls
5075 + */
5076 +#define CIFS_SMB_RESUME_KEY_SIZE 4
5077 +
5078 +typedef struct smb_com_transaction2_ffirst_req {
5079 + struct smb_hdr hdr; /* wct = 15 */
5080 + __u16 TotalParameterCount;
5081 + __u16 TotalDataCount;
5082 + __u16 MaxParameterCount;
5083 + __u16 MaxDataCount;
5084 + __u8 MaxSetupCount;
5085 + __u8 Reserved;
5086 + __u16 Flags;
5087 + __u32 Timeout;
5088 + __u16 Reserved2;
5089 + __u16 ParameterCount;
5090 + __u16 ParameterOffset;
5091 + __u16 DataCount;
5092 + __u16 DataOffset;
5093 + __u8 SetupCount; /* one */
5094 + __u8 Reserved3;
5095 + __u16 SubCommand; /* TRANS2_FIND_FIRST */
5096 + __u16 ByteCount;
5097 + __u8 Pad;
5098 + __u16 SearchAttributes;
5099 + __u16 SearchCount;
5100 + __u16 SearchFlags;
5101 + __u16 InformationLevel;
5102 + __u32 SearchStorageType;
5103 + char FileName[1];
5104 +} TRANSACTION2_FFIRST_REQ;
5105 +
5106 +typedef struct smb_com_transaction2_ffirst_rsp {
5107 + struct smb_hdr hdr; /* wct = 10 */
5108 + __u16 TotalParameterCount;
5109 + __u16 TotalDataCount;
5110 + __u16 Reserved;
5111 + __u16 ParameterCount;
5112 + __u16 ParameterOffset;
5113 + __u16 ParameterDisplacement;
5114 + __u16 DataCount;
5115 + __u16 DataOffset;
5116 + __u16 DataDisplacement;
5117 + __u8 SetupCount;
5118 + __u8 Reserved1; /* should be zero setup words following */
5119 + __u16 ByteCount;
5120 +} TRANSACTION2_FFIRST_RSP;
5121 +
5122 +typedef struct smb_com_transaction2_ffirst_rsp_parms {
5123 + __u16 SearchHandle;
5124 + __u16 SearchCount;
5125 + __u16 EndofSearch;
5126 + __u16 EAErrorOffset;
5127 + __u16 LastNameOffset;
5128 +} T2_FFIRST_RSP_PARMS;
5129 +
5130 +typedef struct smb_com_transaction2_fnext_req {
5131 + struct smb_hdr hdr; /* wct = 15 */
5132 + __u16 TotalParameterCount;
5133 + __u16 TotalDataCount;
5134 + __u16 MaxParameterCount;
5135 + __u16 MaxDataCount;
5136 + __u8 MaxSetupCount;
5137 + __u8 Reserved;
5138 + __u16 Flags;
5139 + __u32 Timeout;
5140 + __u16 Reserved2;
5141 + __u16 ParameterCount;
5142 + __u16 ParameterOffset;
5143 + __u16 DataCount;
5144 + __u16 DataOffset;
5145 + __u8 SetupCount; /* one */
5146 + __u8 Reserved3;
5147 + __u16 SubCommand; /* TRANS2_FIND_NEXT */
5148 + __u16 ByteCount;
5149 + __u8 Pad;
5150 + __u16 SearchHandle;
5151 + __u16 SearchCount;
5152 + __u16 InformationLevel;
5153 + __u32 ResumeKey;
5154 + __u16 SearchFlags;
5155 + char ResumeFileName[1];
5156 +} TRANSACTION2_FNEXT_REQ;
5157 +
5158 +typedef struct smb_com_transaction2_fnext_rsp {
5159 + struct smb_hdr hdr; /* wct = 10 */
5160 + __u16 TotalParameterCount;
5161 + __u16 TotalDataCount;
5162 + __u16 Reserved;
5163 + __u16 ParameterCount;
5164 + __u16 ParameterOffset;
5165 + __u16 ParameterDisplacement;
5166 + __u16 DataCount;
5167 + __u16 DataOffset;
5168 + __u16 DataDisplacement;
5169 + __u8 SetupCount;
5170 + __u8 Reserved1; /* should be zero setup words following */
5171 + __u16 ByteCount;
5172 +} TRANSACTION2_FNEXT_RSP;
5173 +
5174 +typedef struct smb_com_transaction2_fnext_rsp_parms {
5175 + __u16 SearchCount;
5176 + __u16 EndofSearch;
5177 + __u16 EAErrorOffset;
5178 + __u16 LastNameOffset;
5179 +} T2_FNEXT_RSP_PARMS;
5180 +
5181 +/* QFSInfo Levels */
5182 +#define SMB_INFO_ALLOCATION 1
5183 +#define SMB_INFO_VOLUME 2
5184 +#define SMB_QUERY_FS_VOLUME_INFO 0x102
5185 +#define SMB_QUERY_FS_SIZE_INFO 0x103
5186 +#define SMB_QUERY_FS_DEVICE_INFO 0x104
5187 +#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
5188 +#define SMB_QUERY_CIFS_UNIX_INFO 0x200
5189 +#define SMB_QUERY_LABEL_INFO 0x3ea
5190 +#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
5191 +
5192 +typedef struct smb_com_transaction2_qfsi_req {
5193 + struct smb_hdr hdr; /* wct = 14+ */
5194 + __u16 TotalParameterCount;
5195 + __u16 TotalDataCount;
5196 + __u16 MaxParameterCount;
5197 + __u16 MaxDataCount;
5198 + __u8 MaxSetupCount;
5199 + __u8 Reserved;
5200 + __u16 Flags;
5201 + __u32 Timeout;
5202 + __u16 Reserved2;
5203 + __u16 ParameterCount;
5204 + __u16 ParameterOffset;
5205 + __u16 DataCount;
5206 + __u16 DataOffset;
5207 + __u8 SetupCount;
5208 + __u8 Reserved3;
5209 + __u16 SubCommand; /* one setup word */
5210 + __u16 ByteCount;
5211 + __u8 Pad;
5212 + __u16 InformationLevel;
5213 +} TRANSACTION2_QFSI_REQ;
5214 +
5215 +typedef struct smb_com_transaction_qfsi_rsp {
5216 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
5217 + __u16 TotalParameterCount;
5218 + __u16 TotalDataCount;
5219 + __u16 Reserved;
5220 + __u16 ParameterCount;
5221 + __u16 ParameterOffset;
5222 + __u16 ParameterDisplacement;
5223 + __u16 DataCount;
5224 + __u16 DataOffset;
5225 + __u16 DataDisplacement;
5226 + __u8 SetupCount;
5227 + __u8 Reserved1; /* should be zero setup words following */
5228 + __u16 ByteCount;
5229 + __u8 Pad; /* may be three bytes *//* followed by data area */
5230 +} TRANSACTION2_QFSI_RSP;
5231 +
5232 +typedef struct smb_com_transaction2_get_dfs_refer_req {
5233 + struct smb_hdr hdr; /* wct = 15 */
5234 + __u16 TotalParameterCount;
5235 + __u16 TotalDataCount;
5236 + __u16 MaxParameterCount;
5237 + __u16 MaxDataCount;
5238 + __u8 MaxSetupCount;
5239 + __u8 Reserved;
5240 + __u16 Flags;
5241 + __u32 Timeout;
5242 + __u16 Reserved2;
5243 + __u16 ParameterCount;
5244 + __u16 ParameterOffset;
5245 + __u16 DataCount;
5246 + __u16 DataOffset;
5247 + __u8 SetupCount;
5248 + __u8 Reserved3;
5249 + __u16 SubCommand; /* one setup word */
5250 + __u16 ByteCount;
5251 + __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
5252 + __u16 MaxReferralLevel;
5253 + char RequestFileName[1];
5254 +} TRANSACTION2_GET_DFS_REFER_REQ;
5255 +
5256 +typedef struct dfs_referral_level_3 {
5257 + __u16 VersionNumber;
5258 + __u16 ReferralSize;
5259 + __u16 ServerType; /* 0x0001 = CIFS server */
5260 + __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 */
5261 + __u16 TimeToLive;
5262 + __u16 Proximity;
5263 + __u16 DfsPathOffset;
5264 + __u16 DfsAlternatePathOffset;
5265 + __u16 NetworkAddressOffset;
5266 +} REFERRAL3;
5267 +
5268 +typedef struct smb_com_transaction_get_dfs_refer_rsp {
5269 + struct smb_hdr hdr; /* wct = 10 */
5270 + __u16 TotalParameterCount;
5271 + __u16 TotalDataCount;
5272 + __u16 Reserved;
5273 + __u16 ParameterCount;
5274 + __u16 ParameterOffset;
5275 + __u16 ParameterDisplacement;
5276 + __u16 DataCount;
5277 + __u16 DataOffset;
5278 + __u16 DataDisplacement;
5279 + __u8 SetupCount;
5280 + __u8 Reserved1; /* zero setup words following */
5281 + __u16 ByteCount;
5282 + __u8 Pad;
5283 + __u16 PathConsumed;
5284 + __u16 NumberOfReferrals;
5285 + __u16 DFSFlags;
5286 + __u16 Pad2;
5287 + REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
5288 + /* followed by the strings pointed to by the referral structures */
5289 +} TRANSACTION2_GET_DFS_REFER_RSP;
5290 +
5291 +/* DFS Flags */
5292 +#define DFSREF_REFERRAL_SERVER 0x0001
5293 +#define DFSREF_STORAGE_SERVER 0x0002
5294 +
5295 +/* IOCTL information */
5296 +/* List of ioctl function codes that look to be of interest to remote clients like this. */
5297 +/* Need to do some experimentation to make sure they all work remotely. */
5298 +/* Some of the following such as the encryption/compression ones would be */
5299 +/* invoked from tools via a specialized hook into the VFS rather than via the */
5300 +/* standard vfs entry points */
5301 +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
5302 +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
5303 +#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
5304 +#define FSCTL_LOCK_VOLUME 0x00090018
5305 +#define FSCTL_UNLOCK_VOLUME 0x0009001C
5306 +#define FSCTL_GET_COMPRESSION 0x0009003C
5307 +#define FSCTL_SET_COMPRESSION 0x0009C040
5308 +#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
5309 +#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
5310 +#define FSCTL_SET_REPARSE_POINT 0x000900A4
5311 +#define FSCTL_GET_REPARSE_POINT 0x000900A8
5312 +#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
5313 +#define FSCTL_SET_SPARSE 0x000900C4
5314 +#define FSCTL_SET_ZERO_DATA 0x000900C8
5315 +#define FSCTL_SET_ENCRYPTION 0x000900D7
5316 +#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
5317 +#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
5318 +#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
5319 +#define FSCTL_SIS_COPYFILE 0x00090100
5320 +#define FSCTL_SIS_LINK_FILES 0x0009C104
5321 +
5322 +#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
5323 +#define IO_REPARSE_TAG_HSM 0xC0000004
5324 +#define IO_REPARSE_TAG_SIS 0x80000007
5325 +
5326 +/*
5327 + ************************************************************************
5328 + * All structs for everything above the SMB PDUs themselves
5329 + * (such as the T2 level specific data) go here
5330 + ************************************************************************
5331 + */
5332 +
5333 +/*
5334 + * Information on a server
5335 + */
5336 +
5337 +struct serverInfo {
5338 + char name[16];
5339 + unsigned char versionMajor;
5340 + unsigned char versionMinor;
5341 + unsigned long type;
5342 + unsigned int commentOffset;
5343 +};
5344 +
5345 +/*
5346 + * The following structure is the format of the data returned on a NetShareEnum
5347 + * with level "90" (x5A)
5348 + */
5349 +
5350 +struct shareInfo {
5351 + char shareName[13];
5352 + char pad;
5353 + unsigned short type;
5354 + unsigned int commentOffset;
5355 +};
5356 +
5357 +struct aliasInfo {
5358 + char aliasName[9];
5359 + char pad;
5360 + unsigned int commentOffset;
5361 + unsigned char type[2];
5362 +};
5363 +
5364 +struct aliasInfo92 {
5365 + int aliasNameOffset;
5366 + int serverNameOffset;
5367 + int shareNameOffset;
5368 +};
5369 +
5370 +typedef struct {
5371 + __u64 TotalAllocationUnits;
5372 + __u64 FreeAllocationUnits;
5373 + __u32 SectorsPerAllocationUnit;
5374 + __u32 BytesPerSector;
5375 +} FILE_SYSTEM_INFO; /* size info, level 0x103 */
5376 +
5377 +typedef struct {
5378 + __u16 MajorVersionNumber;
5379 + __u16 MinorVersionNumber;
5380 + __u64 Capability;
5381 +} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
5382 +/* Linux/Unix extensions capability flags */
5383 +#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
5384 +#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
5385 +
5386 +/* DeviceType Flags */
5387 +#define FILE_DEVICE_CD_ROM 0x00000002
5388 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
5389 +#define FILE_DEVICE_DFS 0x00000006
5390 +#define FILE_DEVICE_DISK 0x00000007
5391 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
5392 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009
5393 +#define FILE_DEVICE_NAMED_PIPE 0x00000011
5394 +#define FILE_DEVICE_NETWORK 0x00000012
5395 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
5396 +#define FILE_DEVICE_NULL 0x00000015
5397 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016
5398 +#define FILE_DEVICE_PRINTER 0x00000018
5399 +#define FILE_DEVICE_SERIAL_PORT 0x0000001b
5400 +#define FILE_DEVICE_STREAMS 0x0000001e
5401 +#define FILE_DEVICE_TAPE 0x0000001f
5402 +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
5403 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
5404 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
5405 +
5406 +typedef struct {
5407 + __u32 DeviceType;
5408 + __u32 DeviceCharacteristics;
5409 +} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
5410 +
5411 +typedef struct {
5412 + __u32 Attributes;
5413 + __u32 MaxPathNameComponentLength;
5414 + __u32 FileSystemNameLen;
5415 + char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
5416 +} FILE_SYSTEM_ATTRIBUTE_INFO;
5417 +
5418 +typedef struct { /* data block encoding of response to level 263 QPathInfo */
5419 + __u64 CreationTime;
5420 + __u64 LastAccessTime;
5421 + __u64 LastWriteTime;
5422 + __u64 ChangeTime;
5423 + __u32 Attributes;
5424 + __u32 Pad1;
5425 + __u64 AllocationSize;
5426 + __u64 EndOfFile; /* size ie offset to first free byte in file */
5427 + __u32 NumberOfLinks; /* hard links */
5428 + __u8 DeletePending;
5429 + __u8 Directory;
5430 + __u16 Pad2;
5431 + __u64 IndexNumber;
5432 + __u32 EASize;
5433 + __u32 AccessFlags;
5434 + __u64 IndexNumber1;
5435 + __u64 CurrentByteOffset;
5436 + __u32 Mode;
5437 + __u32 AlignmentRequirement;
5438 + __u32 FileNameLength;
5439 + char FileName[1];
5440 +} FILE_ALL_INFO; /* level 263 QPathInfo */
5441 +
5442 +typedef struct {
5443 + __u64 EndOfFile;
5444 + __u64 NumOfBytes;
5445 + __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
5446 + __u64 LastAccessTime;
5447 + __u64 LastModificationTime;
5448 + __u64 Uid;
5449 + __u64 Gid;
5450 + __u32 Type;
5451 + __u64 DevMajor;
5452 + __u64 DevMinor;
5453 + __u64 UniqueId;
5454 + __u64 Permissions;
5455 + __u64 Nlinks;
5456 +} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */
5457 +
5458 +typedef struct {
5459 + char LinkDest[1];
5460 +} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */
5461 +
5462 +/* defines for enumerating possible values of the Unix type field below */
5463 +#define UNIX_FILE 0
5464 +#define UNIX_DIR 1
5465 +#define UNIX_SYMLINK 2
5466 +#define UNIX_CHARDEV 3
5467 +#define UNIX_BLOCKDEV 4
5468 +#define UNIX_FIFO 5
5469 +#define UNIX_SOCKET 6
5470 +
5471 +typedef struct {
5472 + __u32 NextEntryOffset;
5473 + __u32 ResumeKey;
5474 + __u64 EndOfFile;
5475 + __u64 NumOfBytes;
5476 + __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
5477 + __u64 LastAccessTime;
5478 + __u64 LastModificationTime;
5479 + __u64 Uid;
5480 + __u64 Gid;
5481 + __u32 Type;
5482 + __u64 DevMajor;
5483 + __u64 DevMinor;
5484 + __u64 UniqueId;
5485 + __u64 Permissions;
5486 + __u64 Nlinks;
5487 + char FileName[1];
5488 +} FILE_UNIX_INFO;
5489 +
5490 +typedef struct {
5491 + __u64 CreationTime;
5492 + __u64 LastAccessTime;
5493 + __u64 LastWriteTime;
5494 + __u64 ChangeTime;
5495 + __u32 Attributes;
5496 + __u32 Pad;
5497 +} FILE_BASIC_INFO; /* size info, level 0x101 */
5498 +
5499 +struct file_allocation_info {
5500 + __u64 AllocationSize;
5501 +}; /* size info, level 0x103 */
5502 +
5503 +struct file_end_of_file_info {
5504 + __u64 FileSize; /* offset to end of file */
5505 +}; /* size info, level 0x104 */
5506 +
5507 +typedef struct {
5508 + __u32 NextEntryOffset;
5509 + __u32 FileIndex;
5510 + __u64 CreationTime;
5511 + __u64 LastAccessTime;
5512 + __u64 LastWriteTime;
5513 + __u64 ChangeTime;
5514 + __u64 EndOfFile;
5515 + __u64 AllocationSize;
5516 + __u32 ExtFileAttributes;
5517 + __u32 FileNameLength;
5518 + char FileName[1];
5519 +} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
5520 +
5521 +struct gea {
5522 + unsigned char cbName;
5523 + char szName[1];
5524 +};
5525 +
5526 +struct gealist {
5527 + unsigned long cbList;
5528 + struct gea list[1];
5529 +};
5530 +
5531 +struct fea {
5532 + unsigned char EA_flags;
5533 + __u8 name_len;
5534 + __u16 value_len;
5535 + char szName[1];
5536 + /* optionally followed by value */
5537 +};
5538 +/* flags for _FEA.fEA */
5539 +#define FEA_NEEDEA 0x80 /* need EA bit */
5540 +
5541 +struct fealist {
5542 + __u32 list_len;
5543 + struct fea list[1];
5544 +};
5545 +
5546 +/* used to hold an arbitrary blob of data */
5547 +struct data_blob {
5548 + __u8 *data;
5549 + size_t length;
5550 + void (*free) (struct data_blob * data_blob);
5551 +};
5552 +
5553 +#ifdef CONFIG_CIFS_POSIX
5554 +/*
5555 + For better POSIX semantics from Linux client, (even better
5556 + than the existing CIFS Unix Extensions) we need updated PDUs for:
5557 +
5558 + 1) PosixCreateX - to set and return the mode, inode#, device info and
5559 + perhaps add a CreateDevice - to create Pipes and other special .inodes
5560 + Also note POSIX open flags
5561 + 2) Close - to return the last write time to do cache across close more safely
5562 + 3) PosixQFSInfo - to return statfs info
5563 + 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
5564 + 5) Mkdir - set mode
5565 +
5566 + And under consideration:
5567 + 6) FindClose2 (return nanosecond timestamp ??)
5568 + 7) Use nanosecond timestamps throughout all time fields if
5569 + corresponding attribute flag is set
5570 + 8) sendfile - handle based copy
5571 + 9) Direct i/o
5572 + 10) "POSIX ACL" support
5573 + 11) Misc fcntls?
5574 +
5575 + what about fixing 64 bit alignment
5576 +
5577 + There are also various legacy SMB/CIFS requests used as is
5578 +
5579 + From existing Lanman and NTLM dialects:
5580 + --------------------------------------
5581 + NEGOTIATE
5582 + SESSION_SETUP_ANDX (BB which?)
5583 + TREE_CONNECT_ANDX (BB which wct?)
5584 + TREE_DISCONNECT (BB add volume timestamp on response)
5585 + LOGOFF_ANDX
5586 + DELETE (note delete open file behavior)
5587 + DELETE_DIRECTORY
5588 + READ_AND_X
5589 + WRITE_AND_X
5590 + LOCKING_AND_X (note posix lock semantics)
5591 + RENAME (note rename across dirs and open file rename posix behaviors)
5592 + NT_RENAME (for hardlinks) Is this good enough for all features?
5593 + FIND_CLOSE2
5594 + TRANSACTION2 (18 cases)
5595 + SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
5596 + (BB verify that never need to set allocation size)
5597 + SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
5598 +
5599 + COPY (note support for copy across directories) - FUTURE, OPTIONAL
5600 + setting/getting OS/2 EAs - FUTURE (BB can this handle
5601 + setting Linux xattrs perfectly) - OPTIONAL
5602 + dnotify - FUTURE, OPTIONAL
5603 + quota - FUTURE, OPTIONAL
5604 +
5605 + Note that various requests implemented for NT interop such as
5606 + NT_TRANSACT (IOCTL) QueryReparseInfo
5607 + are unneeded to servers compliant with the CIFS POSIX extensions
5608 +
5609 + From CIFS Unix Extensions:
5610 + -------------------------
5611 + T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
5612 + T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
5613 + T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
5614 + T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
5615 + Actually need QUERY_FILE_UNIX_INFO since has inode num
5616 + BB what about a) blksize/blkbits/blocks
5617 + b) i_version
5618 + c) i_rdev
5619 + d) notify mask?
5620 + e) generation
5621 + f) size_seqcount
5622 + T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
5623 + TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
5624 + T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
5625 +
5626 +
5627 + */
5628 +#endif
5629 +
5630 +#pragma pack() /* resume default structure packing */
5631 +
5632 +#endif /* _CIFSPDU_H */
5633 Index: linux-2.4.35.4/fs/cifs/cifsproto.h
5634 ===================================================================
5635 --- /dev/null
5636 +++ linux-2.4.35.4/fs/cifs/cifsproto.h
5637 @@ -0,0 +1,254 @@
5638 +/*
5639 + * fs/cifs/cifsproto.h
5640 + *
5641 + * Copyright (c) International Business Machines Corp., 2002
5642 + * Author(s): Steve French (sfrench@us.ibm.com)
5643 + *
5644 + * This library is free software; you can redistribute it and/or modify
5645 + * it under the terms of the GNU Lesser General Public License as published
5646 + * by the Free Software Foundation; either version 2.1 of the License, or
5647 + * (at your option) any later version.
5648 + *
5649 + * This library is distributed in the hope that it will be useful,
5650 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5651 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5652 + * the GNU Lesser General Public License for more details.
5653 + *
5654 + * You should have received a copy of the GNU Lesser General Public License
5655 + * along with this library; if not, write to the Free Software
5656 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5657 + */
5658 +#ifndef _CIFSPROTO_H
5659 +#define _CIFSPROTO_H
5660 +#include <linux/nls.h>
5661 +
5662 +struct statfs;
5663 +
5664 +/*
5665 + *****************************************************************
5666 + * All Prototypes
5667 + *****************************************************************
5668 + */
5669 +
5670 +extern struct smb_hdr *cifs_buf_get(void);
5671 +extern void cifs_buf_release(void *);
5672 +extern int smb_send(struct socket *, struct smb_hdr *,
5673 + unsigned int /* length */ , struct sockaddr *);
5674 +extern unsigned int _GetXid(void);
5675 +extern void _FreeXid(unsigned int);
5676 +#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
5677 +#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
5678 +extern char *build_path_from_dentry(struct dentry *);
5679 +extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
5680 +extern void renew_parental_timestamps(struct dentry *direntry);
5681 +extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
5682 + struct smb_hdr * /* input */ ,
5683 + struct smb_hdr * /* out */ ,
5684 + int * /* bytes returned */ , const int long_op);
5685 +extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
5686 +extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
5687 +extern int is_valid_oplock_break(struct smb_hdr *smb);
5688 +extern unsigned int smbCalcSize(struct smb_hdr *ptr);
5689 +extern int decode_negTokenInit(unsigned char *security_blob, int length,
5690 + enum securityEnum *secType);
5691 +extern int map_smb_to_linux_error(struct smb_hdr *smb);
5692 +extern void header_assemble(struct smb_hdr *, char /* command */ ,
5693 + const struct cifsTconInfo *, int
5694 + /* length of fixed section (word count) in two byte units */
5695 + );
5696 +struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
5697 +void DeleteOplockQEntry(struct oplock_q_entry *);
5698 +extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
5699 +extern u64 cifs_UnixTimeToNT(time_t);
5700 +extern int cifs_get_inode_info(struct inode **pinode,
5701 + const unsigned char *search_path,
5702 + FILE_ALL_INFO * pfile_info,
5703 + struct super_block *sb, int xid);
5704 +extern int cifs_get_inode_info_unix(struct inode **pinode,
5705 + const unsigned char *search_path,
5706 + struct super_block *sb,int xid);
5707 +
5708 +extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
5709 + struct nls_table * nls_info);
5710 +extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
5711 +
5712 +extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
5713 + const char *tree, struct cifsTconInfo *tcon,
5714 + const struct nls_table *);
5715 +
5716 +extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
5717 + const char *searchName,
5718 + FILE_DIRECTORY_INFO * findData,
5719 + T2_FFIRST_RSP_PARMS * findParms,
5720 + const struct nls_table *nls_codepage,
5721 + int *pUnicodeFlag,
5722 + int *pUnixFlag /* if Unix extensions used */ );
5723 +extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
5724 + FILE_DIRECTORY_INFO * findData,
5725 + T2_FNEXT_RSP_PARMS * findParms,
5726 + const __u16 searchHandle, char * resume_name,
5727 + int name_length, __u32 resume_key,
5728 + int *UnicodeFlag, int *pUnixFlag);
5729 +
5730 +extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
5731 + const __u16 search_handle);
5732 +
5733 +extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
5734 + const unsigned char *searchName,
5735 + FILE_ALL_INFO * findData,
5736 + const struct nls_table *nls_codepage);
5737 +
5738 +extern int CIFSSMBUnixQPathInfo(const int xid,
5739 + struct cifsTconInfo *tcon,
5740 + const unsigned char *searchName,
5741 + FILE_UNIX_BASIC_INFO * pFindData,
5742 + const struct nls_table *nls_codepage);
5743 +
5744 +extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
5745 + const unsigned char *searchName,
5746 + unsigned char **targetUNCs,
5747 + unsigned int *number_of_UNC_in_array,
5748 + const struct nls_table *nls_codepage);
5749 +
5750 +extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
5751 + const char *old_path,
5752 + const struct nls_table *nls_codepage);
5753 +extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
5754 + const char *old_path, const struct nls_table *nls_codepage,
5755 + unsigned int *pnum_referrals, unsigned char ** preferrals);
5756 +extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
5757 + struct statfs *FSData,
5758 + const struct nls_table *nls_codepage);
5759 +extern int CIFSSMBQFSAttributeInfo(const int xid,
5760 + struct cifsTconInfo *tcon,
5761 + const struct nls_table *nls_codepage);
5762 +extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
5763 + const struct nls_table *nls_codepage);
5764 +extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
5765 + const struct nls_table *nls_codepage);
5766 +
5767 +extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
5768 + char *fileName, FILE_BASIC_INFO * data,
5769 + const struct nls_table *nls_codepage);
5770 +extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
5771 + char *fileName, __u64 size,int setAllocationSizeFlag,
5772 + const struct nls_table *nls_codepage);
5773 +extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
5774 + __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
5775 +extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
5776 + char *full_path, __u64 mode, __u64 uid,
5777 + __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
5778 +
5779 +extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
5780 + const char *newName,
5781 + const struct nls_table *nls_codepage);
5782 +extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
5783 + const char *name, const struct nls_table *nls_codepage);
5784 +
5785 +extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
5786 + const char *name,
5787 + const struct nls_table *nls_codepage);
5788 +extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
5789 + const char *fromName, const char *toName,
5790 + const struct nls_table *nls_codepage);
5791 +extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
5792 + int netfid, char * target_name, const struct nls_table *nls_codepage);
5793 +extern int CIFSCreateHardLink(const int xid,
5794 + struct cifsTconInfo *tcon,
5795 + const char *fromName, const char *toName,
5796 + const struct nls_table *nls_codepage);
5797 +extern int CIFSUnixCreateHardLink(const int xid,
5798 + struct cifsTconInfo *tcon,
5799 + const char *fromName, const char *toName,
5800 + const struct nls_table *nls_codepage);
5801 +extern int CIFSUnixCreateSymLink(const int xid,
5802 + struct cifsTconInfo *tcon,
5803 + const char *fromName, const char *toName,
5804 + const struct nls_table *nls_codepage);
5805 +extern int CIFSSMBUnixQuerySymLink(const int xid,
5806 + struct cifsTconInfo *tcon,
5807 + const unsigned char *searchName,
5808 + char *syminfo, const int buflen,
5809 + const struct nls_table *nls_codepage);
5810 +extern int CIFSSMBQueryReparseLinkInfo(const int xid,
5811 + struct cifsTconInfo *tcon,
5812 + const unsigned char *searchName,
5813 + char *symlinkinfo, const int buflen, __u16 fid,
5814 + const struct nls_table *nls_codepage);
5815 +
5816 +extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
5817 + const char *fileName, const int disposition,
5818 + const int access_flags, const int omode,
5819 + __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
5820 + const struct nls_table *nls_codepage);
5821 +extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
5822 + const int smb_file_id);
5823 +
5824 +extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
5825 + const int netfid, unsigned int count,
5826 + const __u64 lseek, unsigned int *nbytes, char **buf);
5827 +extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
5828 + const int netfid, const unsigned int count,
5829 + const __u64 lseek, unsigned int *nbytes,
5830 + const char *buf, const int long_op);
5831 +extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
5832 + const __u16 netfid, const __u64 len,
5833 + const __u64 offset, const __u32 numUnlock,
5834 + const __u32 numLock, const __u8 lockType,
5835 + const int waitFlag);
5836 +
5837 +extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
5838 +extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
5839 +
5840 +extern struct cifsSesInfo *sesInfoAlloc(void);
5841 +extern void sesInfoFree(struct cifsSesInfo *);
5842 +extern struct cifsTconInfo *tconInfoAlloc(void);
5843 +extern void tconInfoFree(struct cifsTconInfo *);
5844 +
5845 +extern int cifs_reconnect(struct TCP_Server_Info *server);
5846 +
5847 +extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
5848 +extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
5849 + __u32 expected_sequence_number);
5850 +extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
5851 +extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
5852 +extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
5853 +
5854 +extern int CIFSBuildServerList(int xid, char *serverBufferList,
5855 + int recordlength, int *entries,
5856 + int *totalEntries, int *topoChangedFlag);
5857 +extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
5858 + struct shareInfo *shareList, int bufferLen,
5859 + int *entries, int *totalEntries);
5860 +extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
5861 + struct aliasInfo *aliasList, int bufferLen,
5862 + int *entries, int *totalEntries);
5863 +extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
5864 + char *aliasName, char *serverName,
5865 + char *shareName, char *comment);
5866 +extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
5867 + char *share, char *comment);
5868 +extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
5869 + char *userName, char *searchName, int *perms);
5870 +extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
5871 +
5872 +extern int CIFSSMBSeek(int xid,
5873 + struct cifsTconInfo *tcon,
5874 + int netfid,
5875 + int pid,
5876 + int whence, unsigned long offset, long long *newoffset);
5877 +
5878 +extern int CIFSSMBCopy(int xid,
5879 + struct cifsTconInfo *source_tcon,
5880 + const char *fromName,
5881 + const __u16 target_tid,
5882 + const char *toName, const int flags,
5883 + const struct nls_table *nls_codepage);
5884 +extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5885 + const int notify_subdirs,const __u16 netfid,__u32 filter,
5886 + const struct nls_table *nls_codepage);
5887 +extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5888 + const unsigned char *searchName,
5889 + char * EAData, size_t size,
5890 + const struct nls_table *nls_codepage);
5891 +#endif /* _CIFSPROTO_H */
5892 Index: linux-2.4.35.4/fs/cifs/cifssmb.c
5893 ===================================================================
5894 --- /dev/null
5895 +++ linux-2.4.35.4/fs/cifs/cifssmb.c
5896 @@ -0,0 +1,3016 @@
5897 +/*
5898 + * fs/cifs/cifssmb.c
5899 + *
5900 + * Copyright (C) International Business Machines Corp., 2002,2003
5901 + * Author(s): Steve French (sfrench@us.ibm.com)
5902 + *
5903 + * Contains the routines for constructing the SMB PDUs themselves
5904 + *
5905 + * This library is free software; you can redistribute it and/or modify
5906 + * it under the terms of the GNU Lesser General Public License as published
5907 + * by the Free Software Foundation; either version 2.1 of the License, or
5908 + * (at your option) any later version.
5909 + *
5910 + * This library is distributed in the hope that it will be useful,
5911 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5912 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5913 + * the GNU Lesser General Public License for more details.
5914 + *
5915 + * You should have received a copy of the GNU Lesser General Public License
5916 + * along with this library; if not, write to the Free Software
5917 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5918 + */
5919 +
5920 + /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
5921 + /* These are mostly routines that operate on a pathname, or on a tree id */
5922 + /* (mounted volume), but there are eight handle based routines which must be */
5923 + /* treated slightly different for reconnection purposes since we never want */
5924 + /* to reuse a stale file handle and the caller knows the file handle */
5925 +
5926 +#include <linux/fs.h>
5927 +#include <linux/kernel.h>
5928 +#include <linux/vfs.h>
5929 +#include <asm/uaccess.h>
5930 +#include "cifspdu.h"
5931 +#include "cifsglob.h"
5932 +#include "cifsproto.h"
5933 +#include "cifs_unicode.h"
5934 +#include "cifs_debug.h"
5935 +
5936 +#ifdef CONFIG_CIFS_POSIX
5937 +static struct {
5938 + int index;
5939 + char *name;
5940 +} protocols[] = {
5941 + {CIFS_PROT, "\2NT LM 0.12"},
5942 + {CIFS_PROT, "\2POSIX 2"},
5943 + {BAD_PROT, "\2"}
5944 +};
5945 +#else
5946 +static struct {
5947 + int index;
5948 + char *name;
5949 +} protocols[] = {
5950 + {CIFS_PROT, "\2NT LM 0.12"},
5951 + {BAD_PROT, "\2"}
5952 +};
5953 +#endif
5954 +
5955 +
5956 +/* Mark as invalid, all open files on tree connections since they
5957 + were closed when session to server was lost */
5958 +static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
5959 +{
5960 + struct cifsFileInfo *open_file = NULL;
5961 + struct list_head * tmp;
5962 + struct list_head * tmp1;
5963 +
5964 +/* list all files open on tree connection and mark them invalid */
5965 + write_lock(&GlobalSMBSeslock);
5966 + list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
5967 + open_file = list_entry(tmp,struct cifsFileInfo, tlist);
5968 + if(open_file) {
5969 + open_file->invalidHandle = TRUE;
5970 + }
5971 + }
5972 + write_unlock(&GlobalSMBSeslock);
5973 + /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
5974 +}
5975 +
5976 +static int
5977 +smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
5978 + void **request_buf /* returned */ ,
5979 + void **response_buf /* returned */ )
5980 +{
5981 + int rc = 0;
5982 + int timeout = 10 * HZ;
5983 +
5984 + /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
5985 + check for tcp and smb session status done differently
5986 + for those three - in the calling routine */
5987 + if(tcon) {
5988 + if((tcon->ses) && (tcon->ses->server)){
5989 + struct nls_table *nls_codepage;
5990 + /* Give Demultiplex thread up to 10 seconds to
5991 + reconnect, should be greater than cifs socket
5992 + timeout which is 7 seconds */
5993 + while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
5994 + while ((tcon->ses->server->tcpStatus != CifsGood) && (timeout > 0)){
5995 + timeout = interruptible_sleep_on_timeout(&tcon->ses->server->response_q,timeout);
5996 + }
5997 + if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
5998 + /* on "soft" mounts we wait once */
5999 + if((tcon->retry == FALSE) ||
6000 + (tcon->ses->status == CifsExiting)) {
6001 + cFYI(1,("gave up waiting on reconnect in smb_init"));
6002 + return -EHOSTDOWN;
6003 + } /* else "hard" mount - keep retrying until
6004 + process is killed or server comes back up */
6005 + } else /* TCP session is reestablished now */
6006 + break;
6007 +
6008 + }
6009 +
6010 + nls_codepage = load_nls_default();
6011 + /* need to prevent multiple threads trying to
6012 + simultaneously reconnect the same SMB session */
6013 + down(&tcon->ses->sesSem);
6014 + if(tcon->ses->status == CifsNeedReconnect)
6015 + rc = cifs_setup_session(0, tcon->ses, nls_codepage);
6016 + if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
6017 + mark_open_files_invalid(tcon);
6018 + rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
6019 + nls_codepage);
6020 + up(&tcon->ses->sesSem);
6021 + if(rc == 0)
6022 + atomic_inc(&tconInfoReconnectCount);
6023 +
6024 + cFYI(1, ("reconnect tcon rc = %d", rc));
6025 + /* Removed call to reopen open files here -
6026 + it is safer (and faster) to reopen files
6027 + one at a time as needed in read and write */
6028 +
6029 + /* Check if handle based operation so we
6030 + know whether we can continue or not without
6031 + returning to caller to reset file handle */
6032 + switch(smb_command) {
6033 + case SMB_COM_READ_ANDX:
6034 + case SMB_COM_WRITE_ANDX:
6035 + case SMB_COM_CLOSE:
6036 + case SMB_COM_FIND_CLOSE2:
6037 + case SMB_COM_LOCKING_ANDX: {
6038 + unload_nls(nls_codepage);
6039 + return -EAGAIN;
6040 + }
6041 + }
6042 + } else {
6043 + up(&tcon->ses->sesSem);
6044 + }
6045 + unload_nls(nls_codepage);
6046 +
6047 + } else {
6048 + return -EIO;
6049 + }
6050 + }
6051 + if(rc)
6052 + return rc;
6053 +
6054 + *request_buf = cifs_buf_get();
6055 + if (*request_buf == 0) {
6056 + /* BB should we add a retry in here if not a writepage? */
6057 + return -ENOMEM;
6058 + }
6059 + /* Although the original thought was we needed the response buf for */
6060 + /* potential retries of smb operations it turns out we can determine */
6061 + /* from the mid flags when the request buffer can be resent without */
6062 + /* having to use a second distinct buffer for the response */
6063 + *response_buf = *request_buf;
6064 +
6065 + header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
6066 + wct /*wct */ );
6067 +
6068 +#ifdef CONFIG_CIFS_STATS
6069 + if(tcon != NULL) {
6070 + atomic_inc(&tcon->num_smbs_sent);
6071 + }
6072 +#endif
6073 + return rc;
6074 +}
6075 +
6076 +int
6077 +CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
6078 +{
6079 + NEGOTIATE_REQ *pSMB;
6080 + NEGOTIATE_RSP *pSMBr;
6081 + int rc = 0;
6082 + int bytes_returned;
6083 + struct TCP_Server_Info * server;
6084 +
6085 + if(ses->server)
6086 + server = ses->server;
6087 + else {
6088 + rc = -EIO;
6089 + return rc;
6090 + }
6091 + rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
6092 + (void **) &pSMB, (void **) &pSMBr);
6093 + if (rc)
6094 + return rc;
6095 +
6096 + pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
6097 + if (extended_security)
6098 + pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
6099 +
6100 + pSMB->ByteCount = strlen(protocols[0].name) + 1;
6101 + strncpy(pSMB->DialectsArray, protocols[0].name, 30);
6102 + /* null guaranteed to be at end of source and target buffers anyway */
6103 +
6104 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6105 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6106 +
6107 + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
6108 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6109 + if (rc == 0) {
6110 + server->secMode = pSMBr->SecurityMode;
6111 + server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
6112 + /* one byte - no need to convert this or EncryptionKeyLen from le,*/
6113 + server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
6114 + /* probably no need to store and check maxvcs */
6115 + server->maxBuf =
6116 + min(le32_to_cpu(pSMBr->MaxBufferSize),
6117 + (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
6118 + server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
6119 + cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
6120 + GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
6121 + server->capabilities = le32_to_cpu(pSMBr->Capabilities);
6122 + server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
6123 + /* BB with UTC do we ever need to be using srvr timezone? */
6124 + if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
6125 + memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
6126 + CIFS_CRYPTO_KEY_SIZE);
6127 + } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
6128 + && (pSMBr->EncryptionKeyLength == 0)) {
6129 + /* decode security blob */
6130 + } else
6131 + rc = -EIO;
6132 +
6133 + /* BB might be helpful to save off the domain of server here */
6134 +
6135 + if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
6136 + if (pSMBr->ByteCount < 16)
6137 + rc = -EIO;
6138 + else if (pSMBr->ByteCount == 16) {
6139 + server->secType = RawNTLMSSP;
6140 + if (server->socketUseCount.counter > 1) {
6141 + if (memcmp
6142 + (server->server_GUID,
6143 + pSMBr->u.extended_response.
6144 + GUID, 16) != 0) {
6145 + cFYI(1,
6146 + ("UID of server does not match previous connection to same ip address"));
6147 + memcpy(server->
6148 + server_GUID,
6149 + pSMBr->u.
6150 + extended_response.
6151 + GUID, 16);
6152 + }
6153 + } else
6154 + memcpy(server->server_GUID,
6155 + pSMBr->u.extended_response.
6156 + GUID, 16);
6157 + } else {
6158 + rc = decode_negTokenInit(pSMBr->u.
6159 + extended_response.
6160 + SecurityBlob,
6161 + pSMBr->ByteCount -
6162 + 16, &server->secType);
6163 + }
6164 + } else
6165 + server->capabilities &= ~CAP_EXTENDED_SECURITY;
6166 + if(sign_CIFS_PDUs == FALSE) {
6167 + if(server->secMode & SECMODE_SIGN_REQUIRED)
6168 + cERROR(1,
6169 + ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
6170 + server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
6171 + } else if(sign_CIFS_PDUs == 1) {
6172 + if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
6173 + server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
6174 + }
6175 +
6176 + }
6177 + if (pSMB)
6178 + cifs_buf_release(pSMB);
6179 + return rc;
6180 +}
6181 +
6182 +int
6183 +CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
6184 +{
6185 + struct smb_hdr *smb_buffer;
6186 + struct smb_hdr *smb_buffer_response;
6187 + int rc = 0;
6188 + int length;
6189 +
6190 + cFYI(1, ("In tree disconnect"));
6191 + /*
6192 + * If last user of the connection and
6193 + * connection alive - disconnect it
6194 + * If this is the last connection on the server session disconnect it
6195 + * (and inside session disconnect we should check if tcp socket needs
6196 + * to be freed and kernel thread woken up).
6197 + */
6198 + if (tcon)
6199 + down(&tcon->tconSem);
6200 + else
6201 + return -EIO;
6202 +
6203 + atomic_dec(&tcon->useCount);
6204 + if (atomic_read(&tcon->useCount) > 0) {
6205 + up(&tcon->tconSem);
6206 + return -EBUSY;
6207 + }
6208 +
6209 + /* No need to return error on this operation if tid invalidated and
6210 + closed on server already e.g. due to tcp session crashing */
6211 + if(tcon->tidStatus == CifsNeedReconnect) {
6212 + up(&tcon->tconSem);
6213 + return 0;
6214 + }
6215 +
6216 + if((tcon->ses == 0) || (tcon->ses->server == 0)) {
6217 + up(&tcon->tconSem);
6218 + return -EIO;
6219 + }
6220 +
6221 + rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
6222 + (void **) &smb_buffer, (void **) &smb_buffer_response);
6223 + if (rc) {
6224 + up(&tcon->tconSem);
6225 + return rc;
6226 + }
6227 + rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
6228 + &length, 0);
6229 + if (rc)
6230 + cFYI(1, (" Tree disconnect failed %d", rc));
6231 +
6232 + if (smb_buffer)
6233 + cifs_buf_release(smb_buffer);
6234 + up(&tcon->tconSem);
6235 +
6236 + /* No need to return error on this operation if tid invalidated and
6237 + closed on server already e.g. due to tcp session crashing */
6238 + if (rc == -EAGAIN)
6239 + rc = 0;
6240 +
6241 + return rc;
6242 +}
6243 +
6244 +int
6245 +CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
6246 +{
6247 + struct smb_hdr *smb_buffer_response;
6248 + LOGOFF_ANDX_REQ *pSMB;
6249 + int rc = 0;
6250 + int length;
6251 +
6252 + cFYI(1, ("In SMBLogoff for session disconnect"));
6253 + if (ses)
6254 + down(&ses->sesSem);
6255 + else
6256 + return -EIO;
6257 +
6258 + atomic_dec(&ses->inUse);
6259 + if (atomic_read(&ses->inUse) > 0) {
6260 + up(&ses->sesSem);
6261 + return -EBUSY;
6262 + }
6263 +
6264 + rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
6265 + (void **) &pSMB, (void **) &smb_buffer_response);
6266 +
6267 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
6268 + pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
6269 +
6270 + if (rc) {
6271 + up(&ses->sesSem);
6272 + return rc;
6273 + }
6274 +
6275 + pSMB->hdr.Uid = ses->Suid;
6276 +
6277 + pSMB->AndXCommand = 0xFF;
6278 + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
6279 + smb_buffer_response, &length, 0);
6280 + if (ses->server) {
6281 + atomic_dec(&ses->server->socketUseCount);
6282 + if (atomic_read(&ses->server->socketUseCount) == 0) {
6283 + spin_lock(&GlobalMid_Lock);
6284 + ses->server->tcpStatus = CifsExiting;
6285 + spin_unlock(&GlobalMid_Lock);
6286 + rc = -ESHUTDOWN;
6287 + }
6288 + }
6289 + if (pSMB)
6290 + cifs_buf_release(pSMB);
6291 + up(&ses->sesSem);
6292 +
6293 + /* if session dead then we do not need to do ulogoff,
6294 + since server closed smb session, no sense reporting
6295 + error */
6296 + if (rc == -EAGAIN)
6297 + rc = 0;
6298 + return rc;
6299 +}
6300 +
6301 +int
6302 +CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
6303 + const char *fileName, const struct nls_table *nls_codepage)
6304 +{
6305 + DELETE_FILE_REQ *pSMB = NULL;
6306 + DELETE_FILE_RSP *pSMBr = NULL;
6307 + int rc = 0;
6308 + int bytes_returned;
6309 + int name_len;
6310 +
6311 +DelFileRetry:
6312 + rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
6313 + (void **) &pSMBr);
6314 + if (rc)
6315 + return rc;
6316 +
6317 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6318 + name_len =
6319 + cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
6320 + /* find define for this maxpathcomponent */
6321 + , nls_codepage);
6322 + name_len++; /* trailing null */
6323 + name_len *= 2;
6324 + } else { /* BB improve the check for buffer overruns BB */
6325 + name_len = strnlen(fileName, 530);
6326 + name_len++; /* trailing null */
6327 + strncpy(pSMB->fileName, fileName, name_len);
6328 + }
6329 + pSMB->SearchAttributes =
6330 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
6331 + pSMB->ByteCount = name_len + 1;
6332 + pSMB->BufferFormat = 0x04;
6333 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6334 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6335 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6336 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6337 + if (rc) {
6338 + cFYI(1, ("Error in RMFile = %d", rc));
6339 + }
6340 +#ifdef CONFIG_CIFS_STATS
6341 + else {
6342 + atomic_inc(&tcon->num_deletes);
6343 + }
6344 +#endif
6345 +
6346 + if (pSMB)
6347 + cifs_buf_release(pSMB);
6348 + if (rc == -EAGAIN)
6349 + goto DelFileRetry;
6350 +
6351 + return rc;
6352 +}
6353 +
6354 +int
6355 +CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
6356 + const char *dirName, const struct nls_table *nls_codepage)
6357 +{
6358 + DELETE_DIRECTORY_REQ *pSMB = NULL;
6359 + DELETE_DIRECTORY_RSP *pSMBr = NULL;
6360 + int rc = 0;
6361 + int bytes_returned;
6362 + int name_len;
6363 +
6364 + cFYI(1, ("In CIFSSMBRmDir"));
6365 +RmDirRetry:
6366 + rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
6367 + (void **) &pSMBr);
6368 + if (rc)
6369 + return rc;
6370 +
6371 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6372 + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
6373 + /* find define for this maxpathcomponent */
6374 + , nls_codepage);
6375 + name_len++; /* trailing null */
6376 + name_len *= 2;
6377 + } else { /* BB improve the check for buffer overruns BB */
6378 + name_len = strnlen(dirName, 530);
6379 + name_len++; /* trailing null */
6380 + strncpy(pSMB->DirName, dirName, name_len);
6381 + }
6382 +
6383 + pSMB->ByteCount = name_len + 1;
6384 + pSMB->BufferFormat = 0x04;
6385 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6386 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6387 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6388 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6389 + if (rc) {
6390 + cFYI(1, ("Error in RMDir = %d", rc));
6391 + }
6392 +#ifdef CONFIG_CIFS_STATS
6393 + else {
6394 + atomic_inc(&tcon->num_rmdirs);
6395 + }
6396 +#endif
6397 +
6398 + if (pSMB)
6399 + cifs_buf_release(pSMB);
6400 + if (rc == -EAGAIN)
6401 + goto RmDirRetry;
6402 + return rc;
6403 +}
6404 +
6405 +int
6406 +CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
6407 + const char *name, const struct nls_table *nls_codepage)
6408 +{
6409 + int rc = 0;
6410 + CREATE_DIRECTORY_REQ *pSMB = NULL;
6411 + CREATE_DIRECTORY_RSP *pSMBr = NULL;
6412 + int bytes_returned;
6413 + int name_len;
6414 +
6415 + cFYI(1, ("In CIFSSMBMkDir"));
6416 +MkDirRetry:
6417 + rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
6418 + (void **) &pSMBr);
6419 + if (rc)
6420 + return rc;
6421 +
6422 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6423 + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
6424 + /* find define for this maxpathcomponent */
6425 + , nls_codepage);
6426 + name_len++; /* trailing null */
6427 + name_len *= 2;
6428 + } else { /* BB improve the check for buffer overruns BB */
6429 + name_len = strnlen(name, 530);
6430 + name_len++; /* trailing null */
6431 + strncpy(pSMB->DirName, name, name_len);
6432 + }
6433 +
6434 + pSMB->ByteCount = name_len + 1 /* for buf format */ ;
6435 + pSMB->BufferFormat = 0x04;
6436 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6437 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6438 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6439 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6440 + if (rc) {
6441 + cFYI(1, ("Error in Mkdir = %d", rc));
6442 + }
6443 +#ifdef CONFIG_CIFS_STATS
6444 + else {
6445 + atomic_inc(&tcon->num_mkdirs);
6446 + }
6447 +#endif
6448 + if (pSMB)
6449 + cifs_buf_release(pSMB);
6450 + if (rc == -EAGAIN)
6451 + goto MkDirRetry;
6452 + return rc;
6453 +}
6454 +
6455 +int
6456 +CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
6457 + const char *fileName, const int openDisposition,
6458 + const int access_flags, const int create_options, __u16 * netfid,
6459 + int *pOplock, FILE_ALL_INFO * pfile_info,
6460 + const struct nls_table *nls_codepage)
6461 +{
6462 + int rc = -EACCES;
6463 + OPEN_REQ *pSMB = NULL;
6464 + OPEN_RSP *pSMBr = NULL;
6465 + int bytes_returned;
6466 + int name_len;
6467 +
6468 +openRetry:
6469 + rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
6470 + (void **) &pSMBr);
6471 + if (rc)
6472 + return rc;
6473 +
6474 + pSMB->AndXCommand = 0xFF; /* none */
6475 +
6476 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6477 + pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
6478 + name_len =
6479 + cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
6480 + fileName, 530
6481 + /* find define for this maxpathcomponent */
6482 + , nls_codepage);
6483 + name_len++; /* trailing null */
6484 + name_len *= 2;
6485 + pSMB->NameLength = cpu_to_le16(name_len);
6486 + } else { /* BB improve the check for buffer overruns BB */
6487 + pSMB->ByteCount = 0; /* no pad */
6488 + name_len = strnlen(fileName, 530);
6489 + name_len++; /* trailing null */
6490 + pSMB->NameLength = cpu_to_le16(name_len);
6491 + strncpy(pSMB->fileName, fileName, name_len);
6492 + }
6493 + if (*pOplock & REQ_OPLOCK)
6494 + pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
6495 + else if (*pOplock & REQ_BATCHOPLOCK) {
6496 + pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
6497 + }
6498 + pSMB->DesiredAccess = cpu_to_le32(access_flags);
6499 + pSMB->AllocationSize = 0;
6500 + pSMB->FileAttributes = ATTR_NORMAL;
6501 + /* XP does not handle ATTR_POSIX_SEMANTICS */
6502 + /* but it helps speed up case sensitive checks for other
6503 + servers such as Samba */
6504 + if (tcon->ses->capabilities & CAP_UNIX)
6505 + pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
6506 +
6507 + /* if ((omode & S_IWUGO) == 0)
6508 + pSMB->FileAttributes |= ATTR_READONLY;*/
6509 + /* Above line causes problems due to vfs splitting create into two
6510 + pieces - need to set mode after file created not while it is
6511 + being created */
6512 + pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
6513 + pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
6514 + pSMB->CreateDisposition = cpu_to_le32(openDisposition);
6515 + pSMB->CreateOptions = cpu_to_le32(create_options);
6516 + pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
6517 + pSMB->SecurityFlags =
6518 + cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
6519 +
6520 + pSMB->ByteCount += name_len;
6521 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6522 +
6523 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6524 + /* long_op set to 1 to allow for oplock break timeouts */
6525 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6526 + (struct smb_hdr *) pSMBr, &bytes_returned, 1);
6527 + if (rc) {
6528 + cFYI(1, ("Error in Open = %d", rc));
6529 + } else {
6530 + *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
6531 + *netfid = pSMBr->Fid; /* cifs fid stays in le */
6532 + /* Let caller know file was created so we can set the mode. */
6533 + /* Do we care about the CreateAction in any other cases? */
6534 + if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
6535 + *pOplock |= CIFS_CREATE_ACTION;
6536 + if(pfile_info) {
6537 + memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
6538 + 36 /* CreationTime to Attributes */);
6539 + /* the file_info buf is endian converted by caller */
6540 + pfile_info->AllocationSize = pSMBr->AllocationSize;
6541 + pfile_info->EndOfFile = pSMBr->EndOfFile;
6542 + pfile_info->NumberOfLinks = cpu_to_le32(1);
6543 + }
6544 +
6545 +#ifdef CONFIG_CIFS_STATS
6546 + atomic_inc(&tcon->num_opens);
6547 +#endif
6548 + }
6549 + if (pSMB)
6550 + cifs_buf_release(pSMB);
6551 + if (rc == -EAGAIN)
6552 + goto openRetry;
6553 + return rc;
6554 +}
6555 +
6556 +/* If no buffer passed in, then caller wants to do the copy
6557 + as in the case of readpages so the SMB buffer must be
6558 + freed by the caller */
6559 +
6560 +int
6561 +CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
6562 + const int netfid, const unsigned int count,
6563 + const __u64 lseek, unsigned int *nbytes, char **buf)
6564 +{
6565 + int rc = -EACCES;
6566 + READ_REQ *pSMB = NULL;
6567 + READ_RSP *pSMBr = NULL;
6568 + char *pReadData = NULL;
6569 + int bytes_returned;
6570 +
6571 + *nbytes = 0;
6572 + rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
6573 + (void **) &pSMBr);
6574 + if (rc)
6575 + return rc;
6576 +
6577 + /* tcon and ses pointer are checked in smb_init */
6578 + if (tcon->ses->server == NULL)
6579 + return -ECONNABORTED;
6580 +
6581 + pSMB->AndXCommand = 0xFF; /* none */
6582 + pSMB->Fid = netfid;
6583 + pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
6584 + pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
6585 + pSMB->Remaining = 0;
6586 + pSMB->MaxCount = cpu_to_le16(count);
6587 + pSMB->MaxCountHigh = 0;
6588 + pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
6589 +
6590 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6591 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6592 + if (rc) {
6593 + cERROR(1, ("Send error in read = %d", rc));
6594 + } else {
6595 + pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
6596 + *nbytes = pSMBr->DataLength;
6597 + /*check that DataLength would not go beyond end of SMB */
6598 + if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
6599 + || (pSMBr->DataLength > count)) {
6600 + cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
6601 + rc = -EIO;
6602 + *nbytes = 0;
6603 + } else {
6604 + pReadData =
6605 + (char *) (&pSMBr->hdr.Protocol) +
6606 + le16_to_cpu(pSMBr->DataOffset);
6607 +/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
6608 + cERROR(1,("Faulting on read rc = %d",rc));
6609 + rc = -EFAULT;
6610 + }*/ /* can not use copy_to_user when using page cache*/
6611 + if(*buf)
6612 + memcpy(*buf,pReadData,pSMBr->DataLength);
6613 + }
6614 + }
6615 + if (pSMB) {
6616 + if(*buf)
6617 + cifs_buf_release(pSMB);
6618 + else
6619 + *buf = (char *)pSMB;
6620 + }
6621 +
6622 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6623 + since file handle passed in no longer valid */
6624 + return rc;
6625 +}
6626 +
6627 +int
6628 +CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
6629 + const int netfid, const unsigned int count,
6630 + const __u64 offset, unsigned int *nbytes, const char *buf,
6631 + const int long_op)
6632 +{
6633 + int rc = -EACCES;
6634 + WRITE_REQ *pSMB = NULL;
6635 + WRITE_RSP *pSMBr = NULL;
6636 + int bytes_returned;
6637 +
6638 + rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
6639 + (void **) &pSMBr);
6640 + if (rc)
6641 + return rc;
6642 + /* tcon and ses pointer are checked in smb_init */
6643 + if (tcon->ses->server == NULL)
6644 + return -ECONNABORTED;
6645 +
6646 + pSMB->AndXCommand = 0xFF; /* none */
6647 + pSMB->Fid = netfid;
6648 + pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
6649 + pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
6650 + pSMB->Remaining = 0;
6651 + if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
6652 + pSMB->DataLengthLow =
6653 + (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
6654 + else
6655 + pSMB->DataLengthLow = count;
6656 + pSMB->DataLengthHigh = 0;
6657 + pSMB->DataOffset =
6658 + cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
6659 +
6660 + memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
6661 +
6662 + pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
6663 + pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
6664 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6665 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6666 +
6667 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6668 + (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
6669 + if (rc) {
6670 + cFYI(1, ("Send error in write = %d", rc));
6671 + *nbytes = 0;
6672 + } else
6673 + *nbytes = le16_to_cpu(pSMBr->Count);
6674 +
6675 + if (pSMB)
6676 + cifs_buf_release(pSMB);
6677 +
6678 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6679 + since file handle passed in no longer valid */
6680 +
6681 + return rc;
6682 +}
6683 +
6684 +int
6685 +CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
6686 + const __u16 smb_file_id, const __u64 len,
6687 + const __u64 offset, const __u32 numUnlock,
6688 + const __u32 numLock, const __u8 lockType, const int waitFlag)
6689 +{
6690 + int rc = 0;
6691 + LOCK_REQ *pSMB = NULL;
6692 + LOCK_RSP *pSMBr = NULL;
6693 + int bytes_returned;
6694 + int timeout = 0;
6695 + __u64 temp;
6696 +
6697 + cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
6698 + rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
6699 + (void **) &pSMBr);
6700 + if (rc)
6701 + return rc;
6702 +
6703 + if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
6704 + timeout = -1; /* no response expected */
6705 + pSMB->Timeout = 0;
6706 + } else if (waitFlag == TRUE) {
6707 + timeout = 3; /* blocking operation, no timeout */
6708 + pSMB->Timeout = -1; /* blocking - do not time out */
6709 + } else {
6710 + pSMB->Timeout = 0;
6711 + }
6712 +
6713 + pSMB->NumberOfLocks = cpu_to_le32(numLock);
6714 + pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
6715 + pSMB->LockType = lockType;
6716 + pSMB->AndXCommand = 0xFF; /* none */
6717 + pSMB->Fid = smb_file_id; /* netfid stays le */
6718 +
6719 + if(numLock != 0) {
6720 + pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
6721 + /* BB where to store pid high? */
6722 + temp = cpu_to_le64(len);
6723 + pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
6724 + pSMB->Locks[0].LengthHigh = (__u32)(temp>>32);
6725 + temp = cpu_to_le64(offset);
6726 + pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
6727 + pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
6728 + pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
6729 + } else {
6730 + /* oplock break */
6731 + pSMB->ByteCount = 0;
6732 + }
6733 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6734 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6735 +
6736 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6737 + (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
6738 +
6739 + if (rc) {
6740 + cFYI(1, ("Send error in Lock = %d", rc));
6741 + }
6742 + if (pSMB)
6743 + cifs_buf_release(pSMB);
6744 +
6745 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6746 + since file handle passed in no longer valid */
6747 + return rc;
6748 +}
6749 +
6750 +int
6751 +CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
6752 +{
6753 + int rc = 0;
6754 + CLOSE_REQ *pSMB = NULL;
6755 + CLOSE_RSP *pSMBr = NULL;
6756 + int bytes_returned;
6757 + cFYI(1, ("In CIFSSMBClose"));
6758 +
6759 +/* do not retry on dead session on close */
6760 + rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
6761 + (void **) &pSMBr);
6762 + if(rc == -EAGAIN)
6763 + return 0;
6764 + if (rc)
6765 + return rc;
6766 +
6767 + pSMB->FileID = (__u16) smb_file_id;
6768 + pSMB->LastWriteTime = 0;
6769 + pSMB->ByteCount = 0;
6770 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6771 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6772 + if (rc) {
6773 + if(rc!=-EINTR) {
6774 + /* EINTR is expected when user ctl-c to kill app */
6775 + cERROR(1, ("Send error in Close = %d", rc));
6776 + }
6777 + }
6778 + if (pSMB)
6779 + cifs_buf_release(pSMB);
6780 +
6781 + /* Since session is dead, file will be closed on server already */
6782 + if(rc == -EAGAIN)
6783 + rc = 0;
6784 +
6785 + return rc;
6786 +}
6787 +
6788 +int
6789 +CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
6790 + const char *fromName, const char *toName,
6791 + const struct nls_table *nls_codepage)
6792 +{
6793 + int rc = 0;
6794 + RENAME_REQ *pSMB = NULL;
6795 + RENAME_RSP *pSMBr = NULL;
6796 + int bytes_returned;
6797 + int name_len, name_len2;
6798 +
6799 + cFYI(1, ("In CIFSSMBRename"));
6800 +renameRetry:
6801 + rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
6802 + (void **) &pSMBr);
6803 + if (rc)
6804 + return rc;
6805 +
6806 + pSMB->BufferFormat = 0x04;
6807 + pSMB->SearchAttributes =
6808 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
6809 + ATTR_DIRECTORY);
6810 +
6811 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6812 + name_len =
6813 + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
6814 + /* find define for this maxpathcomponent */
6815 + , nls_codepage);
6816 + name_len++; /* trailing null */
6817 + name_len *= 2;
6818 + pSMB->OldFileName[name_len] = 0x04; /* pad */
6819 + /* protocol requires ASCII signature byte on Unicode string */
6820 + pSMB->OldFileName[name_len + 1] = 0x00;
6821 + name_len2 =
6822 + cifs_strtoUCS((wchar_t *) & pSMB->
6823 + OldFileName[name_len + 2], toName, 530,
6824 + nls_codepage);
6825 + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
6826 + name_len2 *= 2; /* convert to bytes */
6827 + } else { /* BB improve the check for buffer overruns BB */
6828 + name_len = strnlen(fromName, 530);
6829 + name_len++; /* trailing null */
6830 + strncpy(pSMB->OldFileName, fromName, name_len);
6831 + name_len2 = strnlen(toName, 530);
6832 + name_len2++; /* trailing null */
6833 + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
6834 + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
6835 + name_len2++; /* trailing null */
6836 + name_len2++; /* signature byte */
6837 + }
6838 +
6839 + pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
6840 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6841 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6842 +
6843 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6844 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6845 + if (rc) {
6846 + cFYI(1, ("Send error in rename = %d", rc));
6847 + }
6848 +
6849 +#ifdef CONFIG_CIFS_STATS
6850 + else {
6851 + atomic_inc(&tcon->num_renames);
6852 + }
6853 +#endif
6854 +
6855 + if (pSMB)
6856 + cifs_buf_release(pSMB);
6857 +
6858 + if (rc == -EAGAIN)
6859 + goto renameRetry;
6860 +
6861 + return rc;
6862 +}
6863 +
6864 +int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
6865 + int netfid, char * target_name, const struct nls_table * nls_codepage)
6866 +{
6867 + struct smb_com_transaction2_sfi_req *pSMB = NULL;
6868 + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
6869 + struct set_file_rename * rename_info;
6870 + char *data_offset;
6871 + char dummy_string[30];
6872 + int rc = 0;
6873 + int bytes_returned = 0;
6874 + int len_of_str;
6875 +
6876 + cFYI(1, ("Rename to File by handle"));
6877 + rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
6878 + (void **) &pSMBr);
6879 + if (rc)
6880 + return rc;
6881 +
6882 + pSMB->ParameterCount = 6;
6883 + pSMB->MaxSetupCount = 0;
6884 + pSMB->Reserved = 0;
6885 + pSMB->Flags = 0;
6886 + pSMB->Timeout = 0;
6887 + pSMB->Reserved2 = 0;
6888 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
6889 + Fid) - 4;
6890 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
6891 +
6892 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
6893 + rename_info = (struct set_file_rename *) data_offset;
6894 + pSMB->MaxParameterCount = cpu_to_le16(2);
6895 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
6896 + pSMB->SetupCount = 1;
6897 + pSMB->Reserved3 = 0;
6898 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6899 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
6900 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
6901 + pSMB->TotalParameterCount = pSMB->ParameterCount;
6902 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
6903 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
6904 + /* construct random name ".cifs_tmp<inodenum><mid>" */
6905 + rename_info->overwrite = cpu_to_le32(1);
6906 + rename_info->root_fid = 0;
6907 + /* unicode only call */
6908 + if(target_name == NULL) {
6909 + sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
6910 + len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
6911 + } else {
6912 + len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
6913 + }
6914 + rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
6915 + pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
6916 + pSMB->ByteCount += pSMB->DataCount;
6917 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
6918 + pSMB->TotalDataCount = pSMB->DataCount;
6919 + pSMB->Fid = netfid;
6920 + pSMB->InformationLevel =
6921 + cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
6922 + pSMB->Reserved4 = 0;
6923 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6924 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6925 + rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
6926 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6927 + if (rc) {
6928 + cFYI(1,("Send error in Rename (by file handle) = %d", rc));
6929 + }
6930 +#ifdef CONFIG_CIFS_STATS
6931 + else {
6932 + atomic_inc(&pTcon->num_t2renames);
6933 + }
6934 +#endif
6935 + if (pSMB)
6936 + cifs_buf_release(pSMB);
6937 +
6938 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6939 + since file handle passed in no longer valid */
6940 +
6941 + return rc;
6942 +}
6943 +
6944 +int
6945 +CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
6946 + const __u16 target_tid, const char *toName, const int flags,
6947 + const struct nls_table *nls_codepage)
6948 +{
6949 + int rc = 0;
6950 + COPY_REQ *pSMB = NULL;
6951 + COPY_RSP *pSMBr = NULL;
6952 + int bytes_returned;
6953 + int name_len, name_len2;
6954 +
6955 + cFYI(1, ("In CIFSSMBCopy"));
6956 +copyRetry:
6957 + rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
6958 + (void **) &pSMBr);
6959 + if (rc)
6960 + return rc;
6961 +
6962 + pSMB->BufferFormat = 0x04;
6963 + pSMB->Tid2 = target_tid;
6964 +
6965 + if(flags & COPY_TREE)
6966 + pSMB->Flags |= COPY_TREE;
6967 + pSMB->Flags = cpu_to_le16(pSMB->Flags);
6968 +
6969 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6970 + name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
6971 + fromName,
6972 + 530 /* find define for this maxpathcomponent */,
6973 + nls_codepage);
6974 + name_len++; /* trailing null */
6975 + name_len *= 2;
6976 + pSMB->OldFileName[name_len] = 0x04; /* pad */
6977 + /* protocol requires ASCII signature byte on Unicode string */
6978 + pSMB->OldFileName[name_len + 1] = 0x00;
6979 + name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
6980 + OldFileName[name_len + 2], toName, 530,
6981 + nls_codepage);
6982 + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
6983 + name_len2 *= 2; /* convert to bytes */
6984 + } else { /* BB improve the check for buffer overruns BB */
6985 + name_len = strnlen(fromName, 530);
6986 + name_len++; /* trailing null */
6987 + strncpy(pSMB->OldFileName, fromName, name_len);
6988 + name_len2 = strnlen(toName, 530);
6989 + name_len2++; /* trailing null */
6990 + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
6991 + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
6992 + name_len2++; /* trailing null */
6993 + name_len2++; /* signature byte */
6994 + }
6995 +
6996 + pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
6997 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6998 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6999 +
7000 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7001 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7002 + if (rc) {
7003 + cFYI(1, ("Send error in copy = %d with %d files copied",
7004 + rc, pSMBr->CopyCount));
7005 + }
7006 + if (pSMB)
7007 + cifs_buf_release(pSMB);
7008 +
7009 + if (rc == -EAGAIN)
7010 + goto copyRetry;
7011 +
7012 + return rc;
7013 +}
7014 +
7015 +int
7016 +CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
7017 + const char *fromName, const char *toName,
7018 + const struct nls_table *nls_codepage)
7019 +{
7020 + TRANSACTION2_SPI_REQ *pSMB = NULL;
7021 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
7022 + char *data_offset;
7023 + int name_len;
7024 + int name_len_target;
7025 + int rc = 0;
7026 + int bytes_returned = 0;
7027 +
7028 + cFYI(1, ("In Symlink Unix style"));
7029 +createSymLinkRetry:
7030 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7031 + (void **) &pSMBr);
7032 + if (rc)
7033 + return rc;
7034 +
7035 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7036 + name_len =
7037 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
7038 + /* find define for this maxpathcomponent */
7039 + , nls_codepage);
7040 + name_len++; /* trailing null */
7041 + name_len *= 2;
7042 +
7043 + } else { /* BB improve the check for buffer overruns BB */
7044 + name_len = strnlen(fromName, 530);
7045 + name_len++; /* trailing null */
7046 + strncpy(pSMB->FileName, fromName, name_len);
7047 + }
7048 + pSMB->ParameterCount = 6 + name_len;
7049 + pSMB->MaxSetupCount = 0;
7050 + pSMB->Reserved = 0;
7051 + pSMB->Flags = 0;
7052 + pSMB->Timeout = 0;
7053 + pSMB->Reserved2 = 0;
7054 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
7055 + InformationLevel) - 4;
7056 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
7057 +
7058 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
7059 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7060 + name_len_target =
7061 + cifs_strtoUCS((wchar_t *) data_offset, toName, 530
7062 + /* find define for this maxpathcomponent */
7063 + , nls_codepage);
7064 + name_len_target++; /* trailing null */
7065 + name_len_target *= 2;
7066 + } else { /* BB improve the check for buffer overruns BB */
7067 + name_len_target = strnlen(toName, 530);
7068 + name_len_target++; /* trailing null */
7069 + strncpy(data_offset, toName, name_len_target);
7070 + }
7071 +
7072 + pSMB->DataCount = name_len_target;
7073 + pSMB->MaxParameterCount = cpu_to_le16(2);
7074 + /* BB find exact max on data count below from sess */
7075 + pSMB->MaxDataCount = cpu_to_le16(1000);
7076 + pSMB->SetupCount = 1;
7077 + pSMB->Reserved3 = 0;
7078 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
7079 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
7080 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
7081 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7082 + pSMB->TotalDataCount = pSMB->DataCount;
7083 + pSMB->TotalParameterCount = pSMB->ParameterCount;
7084 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
7085 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
7086 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
7087 + pSMB->Reserved4 = 0;
7088 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7089 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7090 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7091 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7092 + if (rc) {
7093 + cFYI(1,
7094 + ("Send error in SetPathInfo (create symlink) = %d",
7095 + rc));
7096 + }
7097 +
7098 + if (pSMB)
7099 + cifs_buf_release(pSMB);
7100 +
7101 + if (rc == -EAGAIN)
7102 + goto createSymLinkRetry;
7103 +
7104 + return rc;
7105 +}
7106 +
7107 +int
7108 +CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
7109 + const char *fromName, const char *toName,
7110 + const struct nls_table *nls_codepage)
7111 +{
7112 + TRANSACTION2_SPI_REQ *pSMB = NULL;
7113 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
7114 + char *data_offset;
7115 + int name_len;
7116 + int name_len_target;
7117 + int rc = 0;
7118 + int bytes_returned = 0;
7119 +
7120 + cFYI(1, ("In Create Hard link Unix style"));
7121 +createHardLinkRetry:
7122 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7123 + (void **) &pSMBr);
7124 + if (rc)
7125 + return rc;
7126 +
7127 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7128 + name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
7129 + /* find define for this maxpathcomponent */
7130 + , nls_codepage);
7131 + name_len++; /* trailing null */
7132 + name_len *= 2;
7133 +
7134 + } else { /* BB improve the check for buffer overruns BB */
7135 + name_len = strnlen(toName, 530);
7136 + name_len++; /* trailing null */
7137 + strncpy(pSMB->FileName, toName, name_len);
7138 + }
7139 + pSMB->ParameterCount = 6 + name_len;
7140 + pSMB->MaxSetupCount = 0;
7141 + pSMB->Reserved = 0;
7142 + pSMB->Flags = 0;
7143 + pSMB->Timeout = 0;
7144 + pSMB->Reserved2 = 0;
7145 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
7146 + InformationLevel) - 4;
7147 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
7148 +
7149 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
7150 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7151 + name_len_target =
7152 + cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
7153 + /* find define for this maxpathcomponent */
7154 + , nls_codepage);
7155 + name_len_target++; /* trailing null */
7156 + name_len_target *= 2;
7157 + } else { /* BB improve the check for buffer overruns BB */
7158 + name_len_target = strnlen(fromName, 530);
7159 + name_len_target++; /* trailing null */
7160 + strncpy(data_offset, fromName, name_len_target);
7161 + }
7162 +
7163 + pSMB->DataCount = name_len_target;
7164 + pSMB->MaxParameterCount = cpu_to_le16(2);
7165 + /* BB find exact max on data count below from sess*/
7166 + pSMB->MaxDataCount = cpu_to_le16(1000);
7167 + pSMB->SetupCount = 1;
7168 + pSMB->Reserved3 = 0;
7169 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
7170 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
7171 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7172 + pSMB->TotalParameterCount = pSMB->ParameterCount;
7173 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
7174 + pSMB->TotalDataCount = pSMB->DataCount;
7175 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
7176 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
7177 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
7178 + pSMB->Reserved4 = 0;
7179 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7180 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7181 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7182 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7183 + if (rc) {
7184 + cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
7185 + }
7186 +
7187 + if (pSMB)
7188 + cifs_buf_release(pSMB);
7189 + if (rc == -EAGAIN)
7190 + goto createHardLinkRetry;
7191 +
7192 + return rc;
7193 +}
7194 +
7195 +int
7196 +CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
7197 + const char *fromName, const char *toName,
7198 + const struct nls_table *nls_codepage)
7199 +{
7200 + int rc = 0;
7201 + NT_RENAME_REQ *pSMB = NULL;
7202 + RENAME_RSP *pSMBr = NULL;
7203 + int bytes_returned;
7204 + int name_len, name_len2;
7205 +
7206 + cFYI(1, ("In CIFSCreateHardLink"));
7207 +winCreateHardLinkRetry:
7208 +
7209 + rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
7210 + (void **) &pSMBr);
7211 + if (rc)
7212 + return rc;
7213 +
7214 + pSMB->SearchAttributes =
7215 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7216 + ATTR_DIRECTORY);
7217 + pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
7218 + pSMB->ClusterCount = 0;
7219 +
7220 + pSMB->BufferFormat = 0x04;
7221 +
7222 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7223 + name_len =
7224 + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
7225 + /* find define for this maxpathcomponent */
7226 + , nls_codepage);
7227 + name_len++; /* trailing null */
7228 + name_len *= 2;
7229 + pSMB->OldFileName[name_len] = 0; /* pad */
7230 + pSMB->OldFileName[name_len + 1] = 0x04;
7231 + name_len2 =
7232 + cifs_strtoUCS((wchar_t *) & pSMB->
7233 + OldFileName[name_len + 2], toName, 530,
7234 + nls_codepage);
7235 + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
7236 + name_len2 *= 2; /* convert to bytes */
7237 + } else { /* BB improve the check for buffer overruns BB */
7238 + name_len = strnlen(fromName, 530);
7239 + name_len++; /* trailing null */
7240 + strncpy(pSMB->OldFileName, fromName, name_len);
7241 + name_len2 = strnlen(toName, 530);
7242 + name_len2++; /* trailing null */
7243 + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
7244 + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
7245 + name_len2++; /* trailing null */
7246 + name_len2++; /* signature byte */
7247 + }
7248 +
7249 + pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
7250 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7251 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7252 +
7253 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7254 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7255 + if (rc) {
7256 + cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
7257 + }
7258 + if (pSMB)
7259 + cifs_buf_release(pSMB);
7260 + if (rc == -EAGAIN)
7261 + goto winCreateHardLinkRetry;
7262 +
7263 + return rc;
7264 +}
7265 +
7266 +int
7267 +CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
7268 + const unsigned char *searchName,
7269 + char *symlinkinfo, const int buflen,
7270 + const struct nls_table *nls_codepage)
7271 +{
7272 +/* SMB_QUERY_FILE_UNIX_LINK */
7273 + TRANSACTION2_QPI_REQ *pSMB = NULL;
7274 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
7275 + int rc = 0;
7276 + int bytes_returned;
7277 + int name_len;
7278 +
7279 + cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
7280 +
7281 +querySymLinkRetry:
7282 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7283 + (void **) &pSMBr);
7284 + if (rc)
7285 + return rc;
7286 +
7287 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7288 + name_len =
7289 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7290 + /* find define for this maxpathcomponent */
7291 + , nls_codepage);
7292 + name_len++; /* trailing null */
7293 + name_len *= 2;
7294 + } else { /* BB improve the check for buffer overruns BB */
7295 + name_len = strnlen(searchName, 530);
7296 + name_len++; /* trailing null */
7297 + strncpy(pSMB->FileName, searchName, name_len);
7298 + }
7299 +
7300 + pSMB->TotalParameterCount =
7301 + 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
7302 + pSMB->TotalDataCount = 0;
7303 + pSMB->MaxParameterCount = cpu_to_le16(2);
7304 + /* BB find exact max data count below from sess structure BB */
7305 + pSMB->MaxDataCount = cpu_to_le16(4000);
7306 + pSMB->MaxSetupCount = 0;
7307 + pSMB->Reserved = 0;
7308 + pSMB->Flags = 0;
7309 + pSMB->Timeout = 0;
7310 + pSMB->Reserved2 = 0;
7311 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7312 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7313 + pSMB->DataCount = 0;
7314 + pSMB->DataOffset = 0;
7315 + pSMB->SetupCount = 1;
7316 + pSMB->Reserved3 = 0;
7317 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7318 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7319 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7320 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7321 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
7322 + pSMB->Reserved4 = 0;
7323 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7324 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7325 +
7326 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7327 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7328 + if (rc) {
7329 + cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
7330 + } else { /* decode response */
7331 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7332 + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
7333 + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
7334 + /* BB also check enough total bytes returned */
7335 + rc = -EIO; /* bad smb */
7336 + else {
7337 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
7338 + name_len = UniStrnlen((wchar_t *) ((char *)
7339 + &pSMBr->hdr.Protocol +pSMBr->DataOffset),
7340 + min_t(const int, buflen,pSMBr->DataCount) / 2);
7341 + cifs_strfromUCS_le(symlinkinfo,
7342 + (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
7343 + pSMBr->DataOffset),
7344 + name_len, nls_codepage);
7345 + } else {
7346 + strncpy(symlinkinfo,
7347 + (char *) &pSMBr->hdr.Protocol +
7348 + pSMBr->DataOffset,
7349 + min_t(const int, buflen, pSMBr->DataCount));
7350 + }
7351 + symlinkinfo[buflen] = 0;
7352 + /* just in case so calling code does not go off the end of buffer */
7353 + }
7354 + }
7355 + if (pSMB)
7356 + cifs_buf_release(pSMB);
7357 + if (rc == -EAGAIN)
7358 + goto querySymLinkRetry;
7359 + return rc;
7360 +}
7361 +
7362 +
7363 +
7364 +int
7365 +CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
7366 + const unsigned char *searchName,
7367 + char *symlinkinfo, const int buflen,__u16 fid,
7368 + const struct nls_table *nls_codepage)
7369 +{
7370 + int rc = 0;
7371 + int bytes_returned;
7372 + int name_len;
7373 + struct smb_com_transaction_ioctl_req * pSMB;
7374 + struct smb_com_transaction_ioctl_rsp * pSMBr;
7375 +
7376 + cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
7377 + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
7378 + (void **) &pSMBr);
7379 + if (rc)
7380 + return rc;
7381 +
7382 + pSMB->TotalParameterCount = 0 ;
7383 + pSMB->TotalDataCount = 0;
7384 + pSMB->MaxParameterCount = cpu_to_le32(2);
7385 + /* BB find exact data count max from sess structure BB */
7386 + pSMB->MaxDataCount = cpu_to_le32(4000);
7387 + pSMB->MaxSetupCount = 4;
7388 + pSMB->Reserved = 0;
7389 + pSMB->ParameterOffset = 0;
7390 + pSMB->DataCount = 0;
7391 + pSMB->DataOffset = 0;
7392 + pSMB->SetupCount = 4;
7393 + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
7394 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7395 + pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
7396 + pSMB->IsFsctl = 1; /* FSCTL */
7397 + pSMB->IsRootFlag = 0;
7398 + pSMB->Fid = fid; /* file handle always le */
7399 + pSMB->ByteCount = 0;
7400 +
7401 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7402 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7403 + if (rc) {
7404 + cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
7405 + } else { /* decode response */
7406 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7407 + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
7408 + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
7409 + /* BB also check enough total bytes returned */
7410 + rc = -EIO; /* bad smb */
7411 + else {
7412 + if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
7413 + /* could also validate reparse tag && better check name length */
7414 + struct reparse_data * reparse_buf = (struct reparse_data *)
7415 + ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
7416 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
7417 + name_len = UniStrnlen((wchar_t *)
7418 + (reparse_buf->LinkNamesBuf +
7419 + reparse_buf->TargetNameOffset),
7420 + min(buflen/2, reparse_buf->TargetNameLen / 2));
7421 + cifs_strfromUCS_le(symlinkinfo,
7422 + (wchar_t *) (reparse_buf->LinkNamesBuf +
7423 + reparse_buf->TargetNameOffset),
7424 + name_len, nls_codepage);
7425 + } else { /* ASCII names */
7426 + strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
7427 + reparse_buf->TargetNameOffset,
7428 + min_t(const int, buflen, reparse_buf->TargetNameLen));
7429 + }
7430 + } else {
7431 + rc = -EIO;
7432 + cFYI(1,("Invalid return data count on get reparse info ioctl"));
7433 + }
7434 + symlinkinfo[buflen] = 0; /* just in case so the caller
7435 + does not go off the end of the buffer */
7436 + cFYI(1,("readlink result - %s ",symlinkinfo));
7437 + }
7438 + }
7439 + if (pSMB)
7440 + cifs_buf_release(pSMB);
7441 +
7442 + /* Note: On -EAGAIN error only caller can retry on handle based calls
7443 + since file handle passed in no longer valid */
7444 +
7445 + return rc;
7446 +}
7447 +
7448 +int
7449 +CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
7450 + const unsigned char *searchName,
7451 + FILE_ALL_INFO * pFindData,
7452 + const struct nls_table *nls_codepage)
7453 +{
7454 +/* level 263 SMB_QUERY_FILE_ALL_INFO */
7455 + TRANSACTION2_QPI_REQ *pSMB = NULL;
7456 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
7457 + int rc = 0;
7458 + int bytes_returned;
7459 + int name_len;
7460 +
7461 + cFYI(1, ("In QPathInfo path %s", searchName));
7462 +QPathInfoRetry:
7463 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7464 + (void **) &pSMBr);
7465 + if (rc)
7466 + return rc;
7467 +
7468 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7469 + name_len =
7470 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7471 + /* find define for this maxpathcomponent */
7472 + , nls_codepage);
7473 + name_len++; /* trailing null */
7474 + name_len *= 2;
7475 + } else { /* BB improve the check for buffer overruns BB */
7476 + name_len = strnlen(searchName, 530);
7477 + name_len++; /* trailing null */
7478 + strncpy(pSMB->FileName, searchName, name_len);
7479 + }
7480 +
7481 + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
7482 + name_len /* includes null */ ;
7483 + pSMB->TotalDataCount = 0;
7484 + pSMB->MaxParameterCount = cpu_to_le16(2);
7485 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7486 + pSMB->MaxSetupCount = 0;
7487 + pSMB->Reserved = 0;
7488 + pSMB->Flags = 0;
7489 + pSMB->Timeout = 0;
7490 + pSMB->Reserved2 = 0;
7491 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7492 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7493 + pSMB->DataCount = 0;
7494 + pSMB->DataOffset = 0;
7495 + pSMB->SetupCount = 1;
7496 + pSMB->Reserved3 = 0;
7497 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7498 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7499 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7500 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7501 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
7502 + pSMB->Reserved4 = 0;
7503 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7504 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7505 +
7506 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7507 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7508 + if (rc) {
7509 + cFYI(1, ("Send error in QPathInfo = %d", rc));
7510 + } else { /* decode response */
7511 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7512 + /* BB also check enough total bytes returned */
7513 + /* BB we need to improve the validity checking
7514 + of these trans2 responses */
7515 + if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
7516 + rc = -EIO; /* bad smb */
7517 + else if (pFindData){
7518 + memcpy((char *) pFindData,
7519 + (char *) &pSMBr->hdr.Protocol +
7520 + pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
7521 + } else
7522 + rc = -ENOMEM;
7523 + }
7524 + if (pSMB)
7525 + cifs_buf_release(pSMB);
7526 + if (rc == -EAGAIN)
7527 + goto QPathInfoRetry;
7528 +
7529 + return rc;
7530 +}
7531 +
7532 +int
7533 +CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
7534 + const unsigned char *searchName,
7535 + FILE_UNIX_BASIC_INFO * pFindData,
7536 + const struct nls_table *nls_codepage)
7537 +{
7538 +/* SMB_QUERY_FILE_UNIX_BASIC */
7539 + TRANSACTION2_QPI_REQ *pSMB = NULL;
7540 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
7541 + int rc = 0;
7542 + int bytes_returned = 0;
7543 + int name_len;
7544 +
7545 + cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
7546 +UnixQPathInfoRetry:
7547 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7548 + (void **) &pSMBr);
7549 + if (rc)
7550 + return rc;
7551 +
7552 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7553 + name_len =
7554 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7555 + /* find define for this maxpathcomponent */
7556 + , nls_codepage);
7557 + name_len++; /* trailing null */
7558 + name_len *= 2;
7559 + } else { /* BB improve the check for buffer overruns BB */
7560 + name_len = strnlen(searchName, 530);
7561 + name_len++; /* trailing null */
7562 + strncpy(pSMB->FileName, searchName, name_len);
7563 + }
7564 +
7565 + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
7566 + name_len /* includes null */ ;
7567 + pSMB->TotalDataCount = 0;
7568 + pSMB->MaxParameterCount = cpu_to_le16(2);
7569 + /* BB find exact max SMB PDU from sess structure BB */
7570 + pSMB->MaxDataCount = cpu_to_le16(4000);
7571 + pSMB->MaxSetupCount = 0;
7572 + pSMB->Reserved = 0;
7573 + pSMB->Flags = 0;
7574 + pSMB->Timeout = 0;
7575 + pSMB->Reserved2 = 0;
7576 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7577 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7578 + pSMB->DataCount = 0;
7579 + pSMB->DataOffset = 0;
7580 + pSMB->SetupCount = 1;
7581 + pSMB->Reserved3 = 0;
7582 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7583 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7584 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7585 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7586 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
7587 + pSMB->Reserved4 = 0;
7588 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7589 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7590 +
7591 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7592 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7593 + if (rc) {
7594 + cFYI(1, ("Send error in QPathInfo = %d", rc));
7595 + } else { /* decode response */
7596 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7597 + /* BB also check if enough total bytes returned */
7598 + if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
7599 + (pSMBr->DataOffset > 512) ||
7600 + (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
7601 + cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
7602 + (int)pSMBr->DataOffset,bytes_returned));
7603 + rc = -EIO; /* bad smb */
7604 + } else {
7605 + memcpy((char *) pFindData,
7606 + (char *) &pSMBr->hdr.Protocol +
7607 + pSMBr->DataOffset,
7608 + sizeof (FILE_UNIX_BASIC_INFO));
7609 + }
7610 + }
7611 + if (pSMB)
7612 + cifs_buf_release(pSMB);
7613 + if (rc == -EAGAIN)
7614 + goto UnixQPathInfoRetry;
7615 +
7616 + return rc;
7617 +}
7618 +
7619 +int
7620 +CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
7621 + const char *searchName, FILE_ALL_INFO * findData,
7622 + const struct nls_table *nls_codepage)
7623 +{
7624 +/* level 257 SMB_ */
7625 + TRANSACTION2_FFIRST_REQ *pSMB = NULL;
7626 + TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
7627 + int rc = 0;
7628 + int bytes_returned;
7629 + int name_len;
7630 +
7631 + cFYI(1, ("In FindUnique"));
7632 +findUniqueRetry:
7633 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7634 + (void **) &pSMBr);
7635 + if (rc)
7636 + return rc;
7637 +
7638 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7639 + name_len =
7640 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7641 + /* find define for this maxpathcomponent */
7642 + , nls_codepage);
7643 + name_len++; /* trailing null */
7644 + name_len *= 2;
7645 + } else { /* BB improve the check for buffer overruns BB */
7646 + name_len = strnlen(searchName, 530);
7647 + name_len++; /* trailing null */
7648 + strncpy(pSMB->FileName, searchName, name_len);
7649 + }
7650 +
7651 + pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
7652 + pSMB->TotalDataCount = 0; /* no EAs */
7653 + pSMB->MaxParameterCount = cpu_to_le16(2);
7654 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7655 + pSMB->MaxSetupCount = 0;
7656 + pSMB->Reserved = 0;
7657 + pSMB->Flags = 0;
7658 + pSMB->Timeout = 0;
7659 + pSMB->Reserved2 = 0;
7660 + pSMB->ParameterOffset = cpu_to_le16(
7661 + offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
7662 + pSMB->DataCount = 0;
7663 + pSMB->DataOffset = 0;
7664 + pSMB->SetupCount = 1; /* one byte, no need to le convert */
7665 + pSMB->Reserved3 = 0;
7666 + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
7667 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7668 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
7669 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7670 + pSMB->SearchAttributes =
7671 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7672 + ATTR_DIRECTORY);
7673 + pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
7674 + pSMB->SearchFlags = cpu_to_le16(1);
7675 + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7676 + pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
7677 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7678 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7679 +
7680 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7681 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7682 +
7683 + if (rc) {
7684 + cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
7685 + } else { /* decode response */
7686 +
7687 + /* BB fill in */
7688 + }
7689 + if (pSMB)
7690 + cifs_buf_release(pSMB);
7691 + if (rc == -EAGAIN)
7692 + goto findUniqueRetry;
7693 +
7694 + return rc;
7695 +}
7696 +
7697 +int
7698 +CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
7699 + const char *searchName, FILE_DIRECTORY_INFO * findData,
7700 + T2_FFIRST_RSP_PARMS * findParms,
7701 + const struct nls_table *nls_codepage, int *pUnicodeFlag,
7702 + int *pUnixFlag)
7703 +{
7704 +/* level 257 SMB_ */
7705 + TRANSACTION2_FFIRST_REQ *pSMB = NULL;
7706 + TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
7707 + char *response_data;
7708 + int rc = 0;
7709 + int bytes_returned;
7710 + int name_len;
7711 +
7712 + cFYI(1, ("In FindFirst"));
7713 +findFirstRetry:
7714 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7715 + (void **) &pSMBr);
7716 + if (rc)
7717 + return rc;
7718 +
7719 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7720 + name_len =
7721 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7722 + /* find define for this maxpathcomponent */
7723 + , nls_codepage);
7724 + name_len++; /* trailing null */
7725 + name_len *= 2;
7726 + } else { /* BB improve the check for buffer overruns BB */
7727 + name_len = strnlen(searchName, 530);
7728 + name_len++; /* trailing null */
7729 + strncpy(pSMB->FileName, searchName, name_len);
7730 + }
7731 +
7732 + pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
7733 + pSMB->TotalDataCount = 0; /* no EAs */
7734 + pSMB->MaxParameterCount = cpu_to_le16(10);
7735 + pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
7736 + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
7737 + pSMB->MaxSetupCount = 0;
7738 + pSMB->Reserved = 0;
7739 + pSMB->Flags = 0;
7740 + pSMB->Timeout = 0;
7741 + pSMB->Reserved2 = 0;
7742 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7743 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7744 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7745 + pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
7746 + smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
7747 + pSMB->DataCount = 0;
7748 + pSMB->DataOffset = 0;
7749 + pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
7750 + pSMB->Reserved3 = 0;
7751 + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
7752 + pSMB->SearchAttributes =
7753 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7754 + ATTR_DIRECTORY);
7755 + pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
7756 + pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
7757 +
7758 + /* test for Unix extensions */
7759 + if (tcon->ses->capabilities & CAP_UNIX) {
7760 + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
7761 + *pUnixFlag = TRUE;
7762 + } else {
7763 + pSMB->InformationLevel =
7764 + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7765 + *pUnixFlag = FALSE;
7766 + }
7767 + pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
7768 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7769 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7770 +
7771 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7772 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7773 +
7774 + if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
7775 + cFYI(1, ("Error in FindFirst = %d", rc));
7776 + } else { /* decode response */
7777 + /* BB add safety checks for these memcpys */
7778 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
7779 + *pUnicodeFlag = TRUE;
7780 + else
7781 + *pUnicodeFlag = FALSE;
7782 + memcpy(findParms,
7783 + (char *) &pSMBr->hdr.Protocol +
7784 + le16_to_cpu(pSMBr->ParameterOffset),
7785 + sizeof (T2_FFIRST_RSP_PARMS));
7786 + /* search handle can stay LE and EAoffset not needed so not converted */
7787 + findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
7788 + findParms->LastNameOffset =
7789 + le16_to_cpu(findParms->LastNameOffset);
7790 + findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
7791 + response_data =
7792 + (char *) &pSMBr->hdr.Protocol +
7793 + le16_to_cpu(pSMBr->DataOffset);
7794 + memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
7795 + }
7796 + if (pSMB)
7797 + cifs_buf_release(pSMB);
7798 +
7799 + if (rc == -EAGAIN)
7800 + goto findFirstRetry;
7801 +
7802 + return rc;
7803 +}
7804 +
7805 +int
7806 +CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
7807 + FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
7808 + const __u16 searchHandle, char * resume_file_name, int name_len,
7809 + __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
7810 +{
7811 +/* level 257 SMB_ */
7812 + TRANSACTION2_FNEXT_REQ *pSMB = NULL;
7813 + TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
7814 + char *response_data;
7815 + int rc = 0;
7816 + int bytes_returned;
7817 +
7818 + cFYI(1, ("In FindNext"));
7819 +
7820 + if(resume_file_name == NULL) {
7821 + return -EIO;
7822 + }
7823 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7824 + (void **) &pSMBr);
7825 + if (rc)
7826 + return rc;
7827 +
7828 + pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
7829 + pSMB->TotalDataCount = 0; /* no EAs */
7830 + pSMB->MaxParameterCount = cpu_to_le16(8);
7831 + pSMB->MaxDataCount =
7832 + cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
7833 + pSMB->MaxSetupCount = 0;
7834 + pSMB->Reserved = 0;
7835 + pSMB->Flags = 0;
7836 + pSMB->Timeout = 0;
7837 + pSMB->Reserved2 = 0;
7838 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7839 + struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
7840 + pSMB->DataCount = 0;
7841 + pSMB->DataOffset = 0;
7842 + pSMB->SetupCount = 1;
7843 + pSMB->Reserved3 = 0;
7844 + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
7845 + pSMB->SearchHandle = searchHandle; /* always kept as le */
7846 + findParms->SearchCount = 0; /* set to zero in case of error */
7847 + pSMB->SearchCount =
7848 + cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
7849 + /* test for Unix extensions */
7850 + if (tcon->ses->capabilities & CAP_UNIX) {
7851 + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
7852 + *pUnixFlag = TRUE;
7853 + } else {
7854 + pSMB->InformationLevel =
7855 + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7856 + *pUnixFlag = FALSE;
7857 + }
7858 + pSMB->ResumeKey = resume_key;
7859 + pSMB->SearchFlags =
7860 + cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
7861 + /* BB add check to make sure we do not cross end of smb */
7862 + if(name_len < CIFS_MAX_MSGSIZE) {
7863 + memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
7864 + pSMB->ByteCount += name_len;
7865 + }
7866 + pSMB->TotalParameterCount += name_len;
7867 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7868 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7869 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7870 + /* BB improve error handling here */
7871 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7872 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7873 +
7874 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7875 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7876 +
7877 + if (rc) {
7878 + if (rc == -EBADF)
7879 + rc = 0; /* search probably was closed at end of search above */
7880 + else
7881 + cFYI(1, ("FindNext returned = %d", rc));
7882 + } else { /* decode response */
7883 + /* BB add safety checks for these memcpys */
7884 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
7885 + *pUnicodeFlag = TRUE;
7886 + else
7887 + *pUnicodeFlag = FALSE;
7888 + memcpy(findParms,
7889 + (char *) &pSMBr->hdr.Protocol +
7890 + le16_to_cpu(pSMBr->ParameterOffset),
7891 + sizeof (T2_FNEXT_RSP_PARMS));
7892 + findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
7893 + findParms->LastNameOffset =
7894 + le16_to_cpu(findParms->LastNameOffset);
7895 + findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
7896 + response_data =
7897 + (char *) &pSMBr->hdr.Protocol +
7898 + le16_to_cpu(pSMBr->DataOffset);
7899 + memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
7900 + }
7901 + if (pSMB)
7902 + cifs_buf_release(pSMB);
7903 +
7904 + /* Note: On -EAGAIN error only caller can retry on handle based calls
7905 + since file handle passed in no longer valid */
7906 +
7907 + return rc;
7908 +}
7909 +
7910 +int
7911 +CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
7912 +{
7913 + int rc = 0;
7914 + FINDCLOSE_REQ *pSMB = NULL;
7915 + CLOSE_RSP *pSMBr = NULL;
7916 + int bytes_returned;
7917 +
7918 + cFYI(1, ("In CIFSSMBFindClose"));
7919 + rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
7920 + (void **) &pSMBr);
7921 + /* no sense returning error if session restarted
7922 + file handle has been closed */
7923 + if(rc == -EAGAIN)
7924 + return 0;
7925 + if (rc)
7926 + return rc;
7927 +
7928 + pSMB->FileID = searchHandle;
7929 + pSMB->ByteCount = 0;
7930 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7931 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7932 + if (rc) {
7933 + cERROR(1, ("Send error in FindClose = %d", rc));
7934 + }
7935 + if (pSMB)
7936 + cifs_buf_release(pSMB);
7937 +
7938 + /* Since session is dead, search handle closed on server already */
7939 + if (rc == -EAGAIN)
7940 + rc = 0;
7941 +
7942 + return rc;
7943 +}
7944 +
7945 +int
7946 +CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
7947 + const unsigned char *searchName,
7948 + unsigned char **targetUNCs,
7949 + unsigned int *number_of_UNC_in_array,
7950 + const struct nls_table *nls_codepage)
7951 +{
7952 +/* TRANS2_GET_DFS_REFERRAL */
7953 + TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
7954 + TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
7955 + struct dfs_referral_level_3 * referrals = NULL;
7956 + int rc = 0;
7957 + int bytes_returned;
7958 + int name_len;
7959 + unsigned int i;
7960 + char * temp;
7961 + *number_of_UNC_in_array = 0;
7962 + *targetUNCs = NULL;
7963 +
7964 + cFYI(1, ("In GetDFSRefer the path %s", searchName));
7965 + if (ses == NULL)
7966 + return -ENODEV;
7967 +getDFSRetry:
7968 + rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
7969 + (void **) &pSMBr);
7970 + if (rc)
7971 + return rc;
7972 +
7973 + pSMB->hdr.Tid = ses->ipc_tid;
7974 + pSMB->hdr.Uid = ses->Suid;
7975 + if (ses->capabilities & CAP_STATUS32) {
7976 + pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
7977 + }
7978 + if (ses->capabilities & CAP_DFS) {
7979 + pSMB->hdr.Flags2 |= SMBFLG2_DFS;
7980 + }
7981 +
7982 + if (ses->capabilities & CAP_UNICODE) {
7983 + pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
7984 + name_len =
7985 + cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
7986 + searchName, 530
7987 + /* find define for this maxpathcomponent */
7988 + , nls_codepage);
7989 + name_len++; /* trailing null */
7990 + name_len *= 2;
7991 + } else { /* BB improve the check for buffer overruns BB */
7992 + name_len = strnlen(searchName, 530);
7993 + name_len++; /* trailing null */
7994 + strncpy(pSMB->RequestFileName, searchName, name_len);
7995 + }
7996 +
7997 + pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
7998 + pSMB->TotalDataCount = 0;
7999 + pSMB->DataCount = 0;
8000 + pSMB->DataOffset = 0;
8001 + pSMB->MaxParameterCount = 0;
8002 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
8003 + pSMB->MaxSetupCount = 0;
8004 + pSMB->Reserved = 0;
8005 + pSMB->Flags = 0;
8006 + pSMB->Timeout = 0;
8007 + pSMB->Reserved2 = 0;
8008 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8009 + struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
8010 + pSMB->SetupCount = 1;
8011 + pSMB->Reserved3 = 0;
8012 + pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
8013 + pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
8014 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8015 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8016 + pSMB->MaxReferralLevel = cpu_to_le16(3);
8017 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8018 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8019 +
8020 + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
8021 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8022 + if (rc) {
8023 + cFYI(1, ("Send error in GetDFSRefer = %d", rc));
8024 + } else { /* decode response */
8025 +/* BB Add logic to parse referrals here */
8026 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8027 + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
8028 + cFYI(1,
8029 + ("Decoding GetDFSRefer response. BCC: %d Offset %d",
8030 + pSMBr->ByteCount, pSMBr->DataOffset));
8031 + if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
8032 + rc = -EIO; /* bad smb */
8033 + else {
8034 + referrals =
8035 + (struct dfs_referral_level_3 *)
8036 + (8 /* sizeof start of data block */ +
8037 + pSMBr->DataOffset +
8038 + (char *) &pSMBr->hdr.Protocol);
8039 + 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));
8040 + /* BB This field is actually two bytes in from start of
8041 + data block so we could do safety check that DataBlock
8042 + begins at address of pSMBr->NumberOfReferrals */
8043 + *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
8044 +
8045 + /* BB Fix below so can return more than one referral */
8046 + if(*number_of_UNC_in_array > 1)
8047 + *number_of_UNC_in_array = 1;
8048 +
8049 + /* get the length of the strings describing refs */
8050 + name_len = 0;
8051 + for(i=0;i<*number_of_UNC_in_array;i++) {
8052 + /* make sure that DfsPathOffset not past end */
8053 + referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
8054 + if(referrals->DfsPathOffset > pSMBr->DataCount) {
8055 + /* if invalid referral, stop here and do
8056 + not try to copy any more */
8057 + *number_of_UNC_in_array = i;
8058 + break;
8059 + }
8060 + temp = ((char *)referrals) + referrals->DfsPathOffset;
8061 +
8062 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
8063 + name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
8064 + } else {
8065 + name_len += strnlen(temp,pSMBr->DataCount);
8066 + }
8067 + referrals++;
8068 + /* BB add check that referral pointer does not fall off end PDU */
8069 +
8070 + }
8071 + /* BB add check for name_len bigger than bcc */
8072 + *targetUNCs =
8073 + kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
8074 + /* copy the ref strings */
8075 + referrals =
8076 + (struct dfs_referral_level_3 *)
8077 + (8 /* sizeof data hdr */ +
8078 + pSMBr->DataOffset +
8079 + (char *) &pSMBr->hdr.Protocol);
8080 +
8081 + for(i=0;i<*number_of_UNC_in_array;i++) {
8082 + temp = ((char *)referrals) + referrals->DfsPathOffset;
8083 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
8084 + cifs_strfromUCS_le(*targetUNCs,
8085 + (wchar_t *) temp, name_len, nls_codepage);
8086 + } else {
8087 + strncpy(*targetUNCs,temp,name_len);
8088 + }
8089 + /* BB update target_uncs pointers */
8090 + referrals++;
8091 + }
8092 + temp = *targetUNCs;
8093 + temp[name_len] = 0;
8094 + }
8095 +
8096 + }
8097 + if (pSMB)
8098 + cifs_buf_release(pSMB);
8099 +
8100 + if (rc == -EAGAIN)
8101 + goto getDFSRetry;
8102 +
8103 + return rc;
8104 +}
8105 +
8106 +int
8107 +CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
8108 + struct statfs *FSData, const struct nls_table *nls_codepage)
8109 +{
8110 +/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
8111 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8112 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8113 + FILE_SYSTEM_INFO *response_data;
8114 + int rc = 0;
8115 + int bytes_returned = 0;
8116 +
8117 + cFYI(1, ("In QFSInfo"));
8118 +QFSInfoRetry:
8119 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8120 + (void **) &pSMBr);
8121 + if (rc)
8122 + return rc;
8123 +
8124 + pSMB->TotalParameterCount = 2; /* level */
8125 + pSMB->TotalDataCount = 0;
8126 + pSMB->MaxParameterCount = cpu_to_le16(2);
8127 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8128 + pSMB->MaxSetupCount = 0;
8129 + pSMB->Reserved = 0;
8130 + pSMB->Flags = 0;
8131 + pSMB->Timeout = 0;
8132 + pSMB->Reserved2 = 0;
8133 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8134 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8135 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8136 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8137 + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8138 + pSMB->DataCount = 0;
8139 + pSMB->DataOffset = 0;
8140 + pSMB->SetupCount = 1;
8141 + pSMB->Reserved3 = 0;
8142 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8143 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
8144 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8145 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8146 +
8147 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8148 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8149 + if (rc) {
8150 + cERROR(1, ("Send error in QFSInfo = %d", rc));
8151 + } else { /* decode response */
8152 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8153 + cFYI(1,
8154 + ("Decoding qfsinfo response. BCC: %d Offset %d",
8155 + pSMBr->ByteCount, pSMBr->DataOffset));
8156 + if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
8157 + rc = -EIO; /* bad smb */
8158 + else {
8159 + response_data =
8160 + (FILE_SYSTEM_INFO
8161 + *) (((char *) &pSMBr->hdr.Protocol) +
8162 + pSMBr->DataOffset);
8163 + FSData->f_bsize =
8164 + le32_to_cpu(response_data->BytesPerSector) *
8165 + le32_to_cpu(response_data->
8166 + SectorsPerAllocationUnit);
8167 + FSData->f_blocks =
8168 + le64_to_cpu(response_data->TotalAllocationUnits);
8169 + FSData->f_bfree = FSData->f_bavail =
8170 + le64_to_cpu(response_data->FreeAllocationUnits);
8171 + cFYI(1,
8172 + ("Blocks: %lld Free: %lld Block size %ld",
8173 + (unsigned long long)FSData->f_blocks,
8174 + (unsigned long long)FSData->f_bfree,
8175 + FSData->f_bsize));
8176 + }
8177 + }
8178 + if (pSMB)
8179 + cifs_buf_release(pSMB);
8180 +
8181 + if (rc == -EAGAIN)
8182 + goto QFSInfoRetry;
8183 +
8184 + return rc;
8185 +}
8186 +
8187 +int
8188 +CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
8189 + const struct nls_table *nls_codepage)
8190 +{
8191 +/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
8192 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8193 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8194 + FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
8195 + int rc = 0;
8196 + int bytes_returned = 0;
8197 +
8198 + cFYI(1, ("In QFSAttributeInfo"));
8199 +QFSAttributeRetry:
8200 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8201 + (void **) &pSMBr);
8202 + if (rc)
8203 + return rc;
8204 +
8205 + pSMB->TotalParameterCount = 2; /* level */
8206 + pSMB->TotalDataCount = 0;
8207 + pSMB->MaxParameterCount = cpu_to_le16(2);
8208 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8209 + pSMB->MaxSetupCount = 0;
8210 + pSMB->Reserved = 0;
8211 + pSMB->Flags = 0;
8212 + pSMB->Timeout = 0;
8213 + pSMB->Reserved2 = 0;
8214 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8215 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8216 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8217 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8218 + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8219 + pSMB->DataCount = 0;
8220 + pSMB->DataOffset = 0;
8221 + pSMB->SetupCount = 1;
8222 + pSMB->Reserved3 = 0;
8223 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8224 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
8225 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8226 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8227 +
8228 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8229 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8230 + if (rc) {
8231 + cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
8232 + } else { /* decode response */
8233 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8234 + if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
8235 + rc = -EIO; /* bad smb */
8236 + } else {
8237 + response_data =
8238 + (FILE_SYSTEM_ATTRIBUTE_INFO
8239 + *) (((char *) &pSMBr->hdr.Protocol) +
8240 + pSMBr->DataOffset);
8241 + response_data->Attributes = le32_to_cpu(response_data->Attributes);
8242 + response_data->MaxPathNameComponentLength =
8243 + le32_to_cpu(response_data->MaxPathNameComponentLength);
8244 + response_data->FileSystemNameLen =
8245 + le32_to_cpu(response_data->FileSystemNameLen);
8246 + memcpy(&tcon->fsAttrInfo, response_data,
8247 + sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
8248 + }
8249 + }
8250 + if (pSMB)
8251 + cifs_buf_release(pSMB);
8252 +
8253 + if (rc == -EAGAIN)
8254 + goto QFSAttributeRetry;
8255 +
8256 + return rc;
8257 +}
8258 +
8259 +int
8260 +CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
8261 + const struct nls_table *nls_codepage)
8262 +{
8263 +/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
8264 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8265 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8266 + FILE_SYSTEM_DEVICE_INFO *response_data;
8267 + int rc = 0;
8268 + int bytes_returned = 0;
8269 +
8270 + cFYI(1, ("In QFSDeviceInfo"));
8271 +QFSDeviceRetry:
8272 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8273 + (void **) &pSMBr);
8274 + if (rc)
8275 + return rc;
8276 +
8277 + pSMB->TotalParameterCount = 2; /* level */
8278 + pSMB->TotalDataCount = 0;
8279 + pSMB->MaxParameterCount = cpu_to_le16(2);
8280 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8281 + pSMB->MaxSetupCount = 0;
8282 + pSMB->Reserved = 0;
8283 + pSMB->Flags = 0;
8284 + pSMB->Timeout = 0;
8285 + pSMB->Reserved2 = 0;
8286 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8287 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8288 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8289 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8290 + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8291 +
8292 + pSMB->DataCount = 0;
8293 + pSMB->DataOffset = 0;
8294 + pSMB->SetupCount = 1;
8295 + pSMB->Reserved3 = 0;
8296 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8297 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
8298 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8299 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8300 +
8301 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8302 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8303 + if (rc) {
8304 + cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
8305 + } else { /* decode response */
8306 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8307 + if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
8308 + || (pSMBr->DataOffset > 512))
8309 + rc = -EIO; /* bad smb */
8310 + else {
8311 + response_data =
8312 + (FILE_SYSTEM_DEVICE_INFO
8313 + *) (((char *) &pSMBr->hdr.Protocol) +
8314 + pSMBr->DataOffset);
8315 + response_data->DeviceType =
8316 + le32_to_cpu(response_data->DeviceType);
8317 + response_data->DeviceCharacteristics =
8318 + le32_to_cpu(response_data->DeviceCharacteristics);
8319 + memcpy(&tcon->fsDevInfo, response_data,
8320 + sizeof (FILE_SYSTEM_DEVICE_INFO));
8321 + }
8322 + }
8323 + if (pSMB)
8324 + cifs_buf_release(pSMB);
8325 +
8326 + if (rc == -EAGAIN)
8327 + goto QFSDeviceRetry;
8328 +
8329 + return rc;
8330 +}
8331 +
8332 +int
8333 +CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
8334 + const struct nls_table *nls_codepage)
8335 +{
8336 +/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
8337 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8338 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8339 + FILE_SYSTEM_UNIX_INFO *response_data;
8340 + int rc = 0;
8341 + int bytes_returned = 0;
8342 +
8343 + cFYI(1, ("In QFSUnixInfo"));
8344 +QFSUnixRetry:
8345 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8346 + (void **) &pSMBr);
8347 + if (rc)
8348 + return rc;
8349 +
8350 + pSMB->ParameterCount = 2; /* level */
8351 + pSMB->TotalDataCount = 0;
8352 + pSMB->DataCount = 0;
8353 + pSMB->DataOffset = 0;
8354 + pSMB->MaxParameterCount = cpu_to_le16(2);
8355 + pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
8356 + pSMB->MaxSetupCount = 0;
8357 + pSMB->Reserved = 0;
8358 + pSMB->Flags = 0;
8359 + pSMB->Timeout = 0;
8360 + pSMB->Reserved2 = 0;
8361 + pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
8362 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8363 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8364 + pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
8365 + smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8366 + pSMB->SetupCount = 1;
8367 + pSMB->Reserved3 = 0;
8368 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8369 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
8370 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8371 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8372 +
8373 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8374 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8375 + if (rc) {
8376 + cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
8377 + } else { /* decode response */
8378 + pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
8379 + if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
8380 + rc = -EIO; /* bad smb */
8381 + } else {
8382 + response_data =
8383 + (FILE_SYSTEM_UNIX_INFO
8384 + *) (((char *) &pSMBr->hdr.Protocol) +
8385 + pSMBr->DataOffset);
8386 + response_data->MajorVersionNumber =
8387 + le16_to_cpu(response_data->MajorVersionNumber);
8388 + response_data->MinorVersionNumber =
8389 + le16_to_cpu(response_data->MinorVersionNumber);
8390 + response_data->Capability =
8391 + le64_to_cpu(response_data->Capability);
8392 + memcpy(&tcon->fsUnixInfo, response_data,
8393 + sizeof (FILE_SYSTEM_UNIX_INFO));
8394 + }
8395 + }
8396 + if (pSMB)
8397 + cifs_buf_release(pSMB);
8398 +
8399 + if (rc == -EAGAIN)
8400 + goto QFSUnixRetry;
8401 +
8402 +
8403 + return rc;
8404 +}
8405 +
8406 +/* We can not use write of zero bytes trick to
8407 + set file size due to need for large file support. Also note that
8408 + this SetPathInfo is preferred to SetFileInfo based method in next
8409 + routine which is only needed to work around a sharing violation bug
8410 + in Samba which this routine can run into */
8411 +
8412 +int
8413 +CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
8414 + __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
8415 +{
8416 + struct smb_com_transaction2_spi_req *pSMB = NULL;
8417 + struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
8418 + struct file_end_of_file_info *parm_data;
8419 + int name_len;
8420 + int rc = 0;
8421 + int bytes_returned = 0;
8422 +
8423 + cFYI(1, ("In SetEOF"));
8424 +SetEOFRetry:
8425 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8426 + (void **) &pSMBr);
8427 + if (rc)
8428 + return rc;
8429 +
8430 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8431 + name_len =
8432 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8433 + /* find define for this maxpathcomponent */
8434 + , nls_codepage);
8435 + name_len++; /* trailing null */
8436 + name_len *= 2;
8437 + } else { /* BB improve the check for buffer overruns BB */
8438 + name_len = strnlen(fileName, 530);
8439 + name_len++; /* trailing null */
8440 + strncpy(pSMB->FileName, fileName, name_len);
8441 + }
8442 + pSMB->ParameterCount = 6 + name_len;
8443 + pSMB->DataCount = sizeof (struct file_end_of_file_info);
8444 + pSMB->MaxParameterCount = cpu_to_le16(2);
8445 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
8446 + pSMB->MaxSetupCount = 0;
8447 + pSMB->Reserved = 0;
8448 + pSMB->Flags = 0;
8449 + pSMB->Timeout = 0;
8450 + pSMB->Reserved2 = 0;
8451 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8452 + InformationLevel) - 4;
8453 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8454 + if(SetAllocation) {
8455 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8456 + pSMB->InformationLevel =
8457 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
8458 + else
8459 + pSMB->InformationLevel =
8460 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
8461 + } else /* Set File Size */ {
8462 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8463 + pSMB->InformationLevel =
8464 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
8465 + else
8466 + pSMB->InformationLevel =
8467 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
8468 + }
8469 +
8470 + parm_data =
8471 + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
8472 + pSMB->DataOffset);
8473 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8474 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8475 + pSMB->SetupCount = 1;
8476 + pSMB->Reserved3 = 0;
8477 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8478 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8479 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8480 + pSMB->TotalDataCount = pSMB->DataCount;
8481 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8482 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8483 + pSMB->Reserved4 = 0;
8484 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8485 + parm_data->FileSize = cpu_to_le64(size);
8486 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8487 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8488 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8489 + if (rc) {
8490 + cFYI(1, ("SetPathInfo (file size) returned %d", rc));
8491 + }
8492 +
8493 + if (pSMB)
8494 + cifs_buf_release(pSMB);
8495 +
8496 + if (rc == -EAGAIN)
8497 + goto SetEOFRetry;
8498 +
8499 + return rc;
8500 +}
8501 +
8502 +int
8503 +CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
8504 + __u16 fid, __u32 pid_of_opener, int SetAllocation)
8505 +{
8506 + struct smb_com_transaction2_sfi_req *pSMB = NULL;
8507 + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
8508 + char *data_offset;
8509 + struct file_end_of_file_info *parm_data;
8510 + int rc = 0;
8511 + int bytes_returned = 0;
8512 + __u32 tmp;
8513 +
8514 + cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
8515 + (long long)size));
8516 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8517 + (void **) &pSMBr);
8518 + if (rc)
8519 + return rc;
8520 +
8521 + tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
8522 + so network fid will be valid */
8523 + pSMB->hdr.Pid = tmp & 0xFFFF;
8524 + tmp >>= 16;
8525 + pSMB->hdr.PidHigh = tmp & 0xFFFF;
8526 +
8527 + pSMB->ParameterCount = 6;
8528 + pSMB->MaxSetupCount = 0;
8529 + pSMB->Reserved = 0;
8530 + pSMB->Flags = 0;
8531 + pSMB->Timeout = 0;
8532 + pSMB->Reserved2 = 0;
8533 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
8534 + Fid) - 4;
8535 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8536 +
8537 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
8538 +
8539 + pSMB->DataCount = sizeof(struct file_end_of_file_info);
8540 + pSMB->MaxParameterCount = cpu_to_le16(2);
8541 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
8542 + pSMB->SetupCount = 1;
8543 + pSMB->Reserved3 = 0;
8544 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
8545 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8546 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8547 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8548 + pSMB->TotalDataCount = pSMB->DataCount;
8549 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8550 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8551 + parm_data =
8552 + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
8553 + pSMB->DataOffset);
8554 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
8555 + parm_data->FileSize = cpu_to_le64(size);
8556 + pSMB->Fid = fid;
8557 + if(SetAllocation) {
8558 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8559 + pSMB->InformationLevel =
8560 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
8561 + else
8562 + pSMB->InformationLevel =
8563 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
8564 + } else /* Set File Size */ {
8565 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8566 + pSMB->InformationLevel =
8567 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
8568 + else
8569 + pSMB->InformationLevel =
8570 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
8571 + }
8572 + pSMB->Reserved4 = 0;
8573 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8574 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8575 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8576 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8577 + if (rc) {
8578 + cFYI(1,
8579 + ("Send error in SetFileInfo (SetFileSize) = %d",
8580 + rc));
8581 + }
8582 +
8583 + if (pSMB)
8584 + cifs_buf_release(pSMB);
8585 +
8586 + /* Note: On -EAGAIN error only caller can retry on handle based calls
8587 + since file handle passed in no longer valid */
8588 +
8589 + return rc;
8590 +}
8591 +
8592 +int
8593 +CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
8594 + FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
8595 +{
8596 + TRANSACTION2_SPI_REQ *pSMB = NULL;
8597 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
8598 + int name_len;
8599 + int rc = 0;
8600 + int bytes_returned = 0;
8601 + char *data_offset;
8602 +
8603 + cFYI(1, ("In SetTimes"));
8604 +
8605 +SetTimesRetry:
8606 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8607 + (void **) &pSMBr);
8608 + if (rc)
8609 + return rc;
8610 +
8611 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8612 + name_len =
8613 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8614 + /* find define for this maxpathcomponent */
8615 + , nls_codepage);
8616 + name_len++; /* trailing null */
8617 + name_len *= 2;
8618 + } else { /* BB improve the check for buffer overruns BB */
8619 + name_len = strnlen(fileName, 530);
8620 + name_len++; /* trailing null */
8621 + strncpy(pSMB->FileName, fileName, name_len);
8622 + }
8623 +
8624 + pSMB->ParameterCount = 6 + name_len;
8625 + pSMB->DataCount = sizeof (FILE_BASIC_INFO);
8626 + pSMB->MaxParameterCount = cpu_to_le16(2);
8627 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8628 + pSMB->MaxSetupCount = 0;
8629 + pSMB->Reserved = 0;
8630 + pSMB->Flags = 0;
8631 + pSMB->Timeout = 0;
8632 + pSMB->Reserved2 = 0;
8633 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8634 + InformationLevel) - 4;
8635 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8636 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
8637 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8638 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8639 + pSMB->SetupCount = 1;
8640 + pSMB->Reserved3 = 0;
8641 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8642 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8643 +
8644 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8645 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8646 + pSMB->TotalDataCount = pSMB->DataCount;
8647 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8648 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8649 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
8650 + else
8651 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
8652 + pSMB->Reserved4 = 0;
8653 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8654 + memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
8655 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8656 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8657 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8658 + if (rc) {
8659 + cFYI(1, ("SetPathInfo (times) returned %d", rc));
8660 + }
8661 +
8662 + if (pSMB)
8663 + cifs_buf_release(pSMB);
8664 +
8665 + if (rc == -EAGAIN)
8666 + goto SetTimesRetry;
8667 +
8668 + return rc;
8669 +}
8670 +
8671 +int
8672 +CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
8673 + char *fileName, __u64 mode, __u64 uid, __u64 gid,
8674 + dev_t device, const struct nls_table *nls_codepage)
8675 +{
8676 + TRANSACTION2_SPI_REQ *pSMB = NULL;
8677 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
8678 + int name_len;
8679 + int rc = 0;
8680 + int bytes_returned = 0;
8681 + FILE_UNIX_BASIC_INFO *data_offset;
8682 +
8683 + cFYI(1, ("In SetUID/GID/Mode"));
8684 +setPermsRetry:
8685 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8686 + (void **) &pSMBr);
8687 + if (rc)
8688 + return rc;
8689 +
8690 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8691 + name_len =
8692 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8693 + /* find define for this maxpathcomponent */
8694 + , nls_codepage);
8695 + name_len++; /* trailing null */
8696 + name_len *= 2;
8697 + } else { /* BB improve the check for buffer overruns BB */
8698 + name_len = strnlen(fileName, 530);
8699 + name_len++; /* trailing null */
8700 + strncpy(pSMB->FileName, fileName, name_len);
8701 + }
8702 +
8703 + pSMB->ParameterCount = 6 + name_len;
8704 + pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
8705 + pSMB->MaxParameterCount = cpu_to_le16(2);
8706 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8707 + pSMB->MaxSetupCount = 0;
8708 + pSMB->Reserved = 0;
8709 + pSMB->Flags = 0;
8710 + pSMB->Timeout = 0;
8711 + pSMB->Reserved2 = 0;
8712 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8713 + InformationLevel) - 4;
8714 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8715 + data_offset =
8716 + (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
8717 + pSMB->DataOffset);
8718 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8719 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8720 + pSMB->SetupCount = 1;
8721 + pSMB->Reserved3 = 0;
8722 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8723 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8724 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8725 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8726 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8727 + pSMB->TotalDataCount = pSMB->DataCount;
8728 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
8729 + pSMB->Reserved4 = 0;
8730 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8731 + data_offset->Uid = cpu_to_le64(uid);
8732 + data_offset->Gid = cpu_to_le64(gid);
8733 + /* better to leave device as zero when it is */
8734 + data_offset->DevMajor = cpu_to_le64(MAJOR(device));
8735 + data_offset->DevMinor = cpu_to_le64(MINOR(device));
8736 + data_offset->Permissions = cpu_to_le64(mode);
8737 +
8738 + if(S_ISREG(mode))
8739 + data_offset->Type = cpu_to_le32(UNIX_FILE);
8740 + else if(S_ISDIR(mode))
8741 + data_offset->Type = cpu_to_le32(UNIX_DIR);
8742 + else if(S_ISLNK(mode))
8743 + data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
8744 + else if(S_ISCHR(mode))
8745 + data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
8746 + else if(S_ISBLK(mode))
8747 + data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
8748 + else if(S_ISFIFO(mode))
8749 + data_offset->Type = cpu_to_le32(UNIX_FIFO);
8750 + else if(S_ISSOCK(mode))
8751 + data_offset->Type = cpu_to_le32(UNIX_SOCKET);
8752 +
8753 +
8754 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8755 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8756 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8757 + if (rc) {
8758 + cFYI(1, ("SetPathInfo (perms) returned %d", rc));
8759 + }
8760 +
8761 + if (pSMB)
8762 + cifs_buf_release(pSMB);
8763 + if (rc == -EAGAIN)
8764 + goto setPermsRetry;
8765 + return rc;
8766 +}
8767 +
8768 +int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
8769 + const int notify_subdirs, const __u16 netfid,
8770 + __u32 filter, const struct nls_table *nls_codepage)
8771 +{
8772 + int rc = 0;
8773 + struct smb_com_transaction_change_notify_req * pSMB = NULL;
8774 + struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
8775 + int bytes_returned;
8776 +
8777 + cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
8778 + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
8779 + (void **) &pSMBr);
8780 + if (rc)
8781 + return rc;
8782 +
8783 + pSMB->TotalParameterCount = 0 ;
8784 + pSMB->TotalDataCount = 0;
8785 + pSMB->MaxParameterCount = cpu_to_le32(2);
8786 + /* BB find exact data count max from sess structure BB */
8787 + pSMB->MaxDataCount = 0; /* same in little endian or be */
8788 + pSMB->MaxSetupCount = 4;
8789 + pSMB->Reserved = 0;
8790 + pSMB->ParameterOffset = 0;
8791 + pSMB->DataCount = 0;
8792 + pSMB->DataOffset = 0;
8793 + pSMB->SetupCount = 4; /* single byte does not need le conversion */
8794 + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
8795 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8796 + if(notify_subdirs)
8797 + pSMB->WatchTree = 1; /* one byte - no le conversion needed */
8798 + pSMB->Reserved2 = 0;
8799 + pSMB->CompletionFilter = cpu_to_le32(filter);
8800 + pSMB->Fid = netfid; /* file handle always le */
8801 + pSMB->ByteCount = 0;
8802 +
8803 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8804 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8805 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8806 + if (rc) {
8807 + cFYI(1, ("Error in Notify = %d", rc));
8808 + }
8809 + if (pSMB)
8810 + cifs_buf_release(pSMB);
8811 +/* if (rc == -EAGAIN)
8812 + goto NotifyRetry; */
8813 + return rc;
8814 +}
8815 +#ifdef CONFIG_CIFS_XATTR
8816 +int
8817 +CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
8818 + const unsigned char *searchName,
8819 + char * EAData, size_t size,
8820 + const struct nls_table *nls_codepage)
8821 +{
8822 + /* BB assumes one setup word */
8823 + TRANSACTION2_QPI_REQ *pSMB = NULL;
8824 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
8825 + int rc = 0;
8826 + int bytes_returned;
8827 + int name_len;
8828 +
8829 + cFYI(1, ("In Query All EAs path %s", searchName));
8830 +QAllEAsRetry:
8831 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8832 + (void **) &pSMBr);
8833 + if (rc)
8834 + return rc;
8835 +
8836 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8837 + name_len =
8838 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
8839 + /* find define for this maxpathcomponent */
8840 + , nls_codepage);
8841 + name_len++; /* trailing null */
8842 + name_len *= 2;
8843 + } else { /* BB improve the check for buffer overruns BB */
8844 + name_len = strnlen(searchName, 530);
8845 + name_len++; /* trailing null */
8846 + strncpy(pSMB->FileName, searchName, name_len);
8847 + }
8848 +
8849 + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
8850 + name_len /* includes null */ ;
8851 + pSMB->TotalDataCount = 0;
8852 + pSMB->MaxParameterCount = cpu_to_le16(2);
8853 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
8854 + pSMB->MaxSetupCount = 0;
8855 + pSMB->Reserved = 0;
8856 + pSMB->Flags = 0;
8857 + pSMB->Timeout = 0;
8858 + pSMB->Reserved2 = 0;
8859 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8860 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
8861 + pSMB->DataCount = 0;
8862 + pSMB->DataOffset = 0;
8863 + pSMB->SetupCount = 1;
8864 + pSMB->Reserved3 = 0;
8865 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
8866 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8867 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8868 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8869 + pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
8870 + pSMB->Reserved4 = 0;
8871 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8872 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8873 +
8874 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8875 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8876 + if (rc) {
8877 + cFYI(1, ("Send error in QueryAllEAs = %d", rc));
8878 + } else { /* decode response */
8879 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8880 + /* BB also check enough total bytes returned */
8881 + /* BB we need to improve the validity checking
8882 + of these trans2 responses */
8883 + if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
8884 + rc = -EIO; /* bad smb */
8885 + /* else if (pFindData){
8886 + memcpy((char *) pFindData,
8887 + (char *) &pSMBr->hdr.Protocol +
8888 + pSMBr->DataOffset, kl);
8889 + }*/ else {
8890 + /* check that length of list is not more than bcc */
8891 + /* check that each entry does not go beyond length
8892 + of list */
8893 + /* check that each element of each entry does not
8894 + go beyond end of list */
8895 + struct fealist * ea_response_data;
8896 + rc = 0;
8897 + /* validate_trans2_offsets() */
8898 + /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
8899 + ea_response_data = (struct fealist *)
8900 + (((char *) &pSMBr->hdr.Protocol) +
8901 + pSMBr->DataOffset);
8902 + cFYI(1,("ea length %d",ea_response_data->list_len));
8903 + }
8904 + }
8905 + if (pSMB)
8906 + cifs_buf_release(pSMB);
8907 + if (rc == -EAGAIN)
8908 + goto QAllEAsRetry;
8909 +
8910 + return rc;
8911 +}
8912 +#endif
8913 Index: linux-2.4.35.4/fs/cifs/cifs_unicode.c
8914 ===================================================================
8915 --- /dev/null
8916 +++ linux-2.4.35.4/fs/cifs/cifs_unicode.c
8917 @@ -0,0 +1,87 @@
8918 +/*
8919 + * fs/cifs/cifs_unicode.c
8920 + *
8921 + * Copyright (c) International Business Machines Corp., 2000,2002
8922 + * Modified by Steve French (sfrench@us.ibm.com)
8923 + *
8924 + * This program is free software; you can redistribute it and/or modify
8925 + * it under the terms of the GNU General Public License as published by
8926 + * the Free Software Foundation; either version 2 of the License, or
8927 + * (at your option) any later version.
8928 + *
8929 + * This program is distributed in the hope that it will be useful,
8930 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8931 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8932 + * the GNU General Public License for more details.
8933 + *
8934 + * You should have received a copy of the GNU General Public License
8935 + * along with this program; if not, write to the Free Software
8936 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8937 + */
8938 +#include <linux/fs.h>
8939 +#include "cifs_unicode.h"
8940 +#include "cifs_uniupr.h"
8941 +#include "cifspdu.h"
8942 +#include "cifs_debug.h"
8943 +
8944 +/*
8945 + * NAME: cifs_strfromUCS()
8946 + *
8947 + * FUNCTION: Convert little-endian unicode string to character string
8948 + *
8949 + */
8950 +int
8951 +cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
8952 + int len, const struct nls_table *codepage)
8953 +{
8954 + int i;
8955 + int outlen = 0;
8956 +
8957 + for (i = 0; (i < len) && from[i]; i++) {
8958 + int charlen;
8959 + /* 2.4.0 kernel or greater */
8960 + charlen =
8961 + codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
8962 + NLS_MAX_CHARSET_SIZE);
8963 + if (charlen > 0) {
8964 + outlen += charlen;
8965 + } else {
8966 + to[outlen++] = '?';
8967 + }
8968 + }
8969 + to[outlen] = 0;
8970 + return outlen;
8971 +}
8972 +
8973 +/*
8974 + * NAME: cifs_strtoUCS()
8975 + *
8976 + * FUNCTION: Convert character string to unicode string
8977 + *
8978 + */
8979 +int
8980 +cifs_strtoUCS(wchar_t * to, const char *from, int len,
8981 + const struct nls_table *codepage)
8982 +{
8983 + int charlen;
8984 + int i;
8985 +
8986 + for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
8987 +
8988 + /* works for 2.4.0 kernel or later */
8989 + charlen = codepage->char2uni(from, len, &to[i]);
8990 + if (charlen < 1) {
8991 + cERROR(1,
8992 + ("cifs_strtoUCS: char2uni returned %d",
8993 + charlen));
8994 + to[i] = cpu_to_le16(0x003f); /* a question mark */
8995 + charlen = 1;
8996 + }
8997 + to[i] = cpu_to_le16(to[i]);
8998 +
8999 + }
9000 +
9001 + to[i] = 0;
9002 + return i;
9003 +}
9004 +
9005 Index: linux-2.4.35.4/fs/cifs/cifs_unicode.h
9006 ===================================================================
9007 --- /dev/null
9008 +++ linux-2.4.35.4/fs/cifs/cifs_unicode.h
9009 @@ -0,0 +1,353 @@
9010 +/*
9011 + * cifs_unicode: Unicode kernel case support
9012 + *
9013 + * Function:
9014 + * Convert a unicode character to upper or lower case using
9015 + * compressed tables.
9016 + *
9017 + * Copyright (c) International Business Machines Corp., 2000,2002
9018 + *
9019 + * This program is free software; you can redistribute it and/or modify
9020 + * it under the terms of the GNU General Public License as published by
9021 + * the Free Software Foundation; either version 2 of the License, or
9022 + * (at your option) any later version.
9023 + *
9024 + * This program is distributed in the hope that it will be useful,
9025 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9026 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9027 + * the GNU General Public License for more details.
9028 + *
9029 + * You should have received a copy of the GNU General Public License
9030 + * along with this program; if not, write to the Free Software
9031 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9032 + *
9033 + *
9034 + * Notes:
9035 + * These APIs are based on the C library functions. The semantics
9036 + * should match the C functions but with expanded size operands.
9037 + *
9038 + * The upper/lower functions are based on a table created by mkupr.
9039 + * This is a compressed table of upper and lower case conversion.
9040 + *
9041 + */
9042 +
9043 +#include <asm/byteorder.h>
9044 +#include <linux/types.h>
9045 +#include <linux/nls.h>
9046 +
9047 +#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
9048 +
9049 +/* Just define what we want from uniupr.h. We don't want to define the tables
9050 + * in each source file.
9051 + */
9052 +#ifndef UNICASERANGE_DEFINED
9053 +struct UniCaseRange {
9054 + wchar_t start;
9055 + wchar_t end;
9056 + signed char *table;
9057 +};
9058 +#endif /* UNICASERANGE_DEFINED */
9059 +
9060 +#ifndef UNIUPR_NOUPPER
9061 +extern signed char CifsUniUpperTable[512];
9062 +extern const struct UniCaseRange CifsUniUpperRange[];
9063 +#endif /* UNIUPR_NOUPPER */
9064 +
9065 +#ifndef UNIUPR_NOLOWER
9066 +extern signed char UniLowerTable[512];
9067 +extern struct UniCaseRange UniLowerRange[];
9068 +#endif /* UNIUPR_NOLOWER */
9069 +
9070 +#ifdef __KERNEL__
9071 +int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
9072 +int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
9073 +#endif
9074 +
9075 +/*
9076 + * UniStrcat: Concatenate the second string to the first
9077 + *
9078 + * Returns:
9079 + * Address of the first string
9080 + */
9081 +static inline wchar_t *
9082 +UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
9083 +{
9084 + wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
9085 +
9086 + while (*ucs1++) ; /* To end of first string */
9087 + ucs1--; /* Return to the null */
9088 + while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
9089 + return anchor;
9090 +}
9091 +
9092 +/*
9093 + * UniStrchr: Find a character in a string
9094 + *
9095 + * Returns:
9096 + * Address of first occurrence of character in string
9097 + * or NULL if the character is not in the string
9098 + */
9099 +static inline wchar_t *
9100 +UniStrchr(const wchar_t * ucs, wchar_t uc)
9101 +{
9102 + while ((*ucs != uc) && *ucs)
9103 + ucs++;
9104 +
9105 + if (*ucs == uc)
9106 + return (wchar_t *) ucs;
9107 + return NULL;
9108 +}
9109 +
9110 +/*
9111 + * UniStrcmp: Compare two strings
9112 + *
9113 + * Returns:
9114 + * < 0: First string is less than second
9115 + * = 0: Strings are equal
9116 + * > 0: First string is greater than second
9117 + */
9118 +static inline int
9119 +UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
9120 +{
9121 + while ((*ucs1 == *ucs2) && *ucs1) {
9122 + ucs1++;
9123 + ucs2++;
9124 + }
9125 + return (int) *ucs1 - (int) *ucs2;
9126 +}
9127 +
9128 +/*
9129 + * UniStrcpy: Copy a string
9130 + */
9131 +static inline wchar_t *
9132 +UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
9133 +{
9134 + wchar_t *anchor = ucs1; /* save the start of result string */
9135 +
9136 + while ((*ucs1++ = *ucs2++)) ;
9137 + return anchor;
9138 +}
9139 +
9140 +/*
9141 + * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
9142 + */
9143 +static inline size_t
9144 +UniStrlen(const wchar_t * ucs1)
9145 +{
9146 + int i = 0;
9147 +
9148 + while (*ucs1++)
9149 + i++;
9150 + return i;
9151 +}
9152 +
9153 +/*
9154 + * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
9155 + */
9156 +static inline size_t
9157 +UniStrnlen(const wchar_t * ucs1, int maxlen)
9158 +{
9159 + int i = 0;
9160 +
9161 + while (*ucs1++) {
9162 + i++;
9163 + if (i >= maxlen)
9164 + break;
9165 + }
9166 + return i;
9167 +}
9168 +
9169 +/*
9170 + * UniStrncat: Concatenate length limited string
9171 + */
9172 +static inline wchar_t *
9173 +UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9174 +{
9175 + wchar_t *anchor = ucs1; /* save pointer to string 1 */
9176 +
9177 + while (*ucs1++) ;
9178 + ucs1--; /* point to null terminator of s1 */
9179 + while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
9180 + ucs1++;
9181 + ucs2++;
9182 + }
9183 + *ucs1 = 0; /* Null terminate the result */
9184 + return (anchor);
9185 +}
9186 +
9187 +/*
9188 + * UniStrncmp: Compare length limited string
9189 + */
9190 +static inline int
9191 +UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9192 +{
9193 + if (!n)
9194 + return 0; /* Null strings are equal */
9195 + while ((*ucs1 == *ucs2) && *ucs1 && --n) {
9196 + ucs1++;
9197 + ucs2++;
9198 + }
9199 + return (int) *ucs1 - (int) *ucs2;
9200 +}
9201 +
9202 +/*
9203 + * UniStrncmp_le: Compare length limited string - native to little-endian
9204 + */
9205 +static inline int
9206 +UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9207 +{
9208 + if (!n)
9209 + return 0; /* Null strings are equal */
9210 + while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
9211 + ucs1++;
9212 + ucs2++;
9213 + }
9214 + return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
9215 +}
9216 +
9217 +/*
9218 + * UniStrncpy: Copy length limited string with pad
9219 + */
9220 +static inline wchar_t *
9221 +UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9222 +{
9223 + wchar_t *anchor = ucs1;
9224 +
9225 + while (n-- && *ucs2) /* Copy the strings */
9226 + *ucs1++ = *ucs2++;
9227 +
9228 + n++;
9229 + while (n--) /* Pad with nulls */
9230 + *ucs1++ = 0;
9231 + return anchor;
9232 +}
9233 +
9234 +/*
9235 + * UniStrncpy_le: Copy length limited string with pad to little-endian
9236 + */
9237 +static inline wchar_t *
9238 +UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9239 +{
9240 + wchar_t *anchor = ucs1;
9241 +
9242 + while (n-- && *ucs2) /* Copy the strings */
9243 + *ucs1++ = __le16_to_cpu(*ucs2++);
9244 +
9245 + n++;
9246 + while (n--) /* Pad with nulls */
9247 + *ucs1++ = 0;
9248 + return anchor;
9249 +}
9250 +
9251 +/*
9252 + * UniStrstr: Find a string in a string
9253 + *
9254 + * Returns:
9255 + * Address of first match found
9256 + * NULL if no matching string is found
9257 + */
9258 +static inline wchar_t *
9259 +UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
9260 +{
9261 + const wchar_t *anchor1 = ucs1;
9262 + const wchar_t *anchor2 = ucs2;
9263 +
9264 + while (*ucs1) {
9265 + if (*ucs1 == *ucs2) { /* Partial match found */
9266 + ucs1++;
9267 + ucs2++;
9268 + } else {
9269 + if (!*ucs2) /* Match found */
9270 + return (wchar_t *) anchor1;
9271 + ucs1 = ++anchor1; /* No match */
9272 + ucs2 = anchor2;
9273 + }
9274 + }
9275 +
9276 + if (!*ucs2) /* Both end together */
9277 + return (wchar_t *) anchor1; /* Match found */
9278 + return NULL; /* No match */
9279 +}
9280 +
9281 +#ifndef UNIUPR_NOUPPER
9282 +/*
9283 + * UniToupper: Convert a unicode character to upper case
9284 + */
9285 +static inline wchar_t
9286 +UniToupper(register wchar_t uc)
9287 +{
9288 + register const struct UniCaseRange *rp;
9289 +
9290 + if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */
9291 + return uc + CifsUniUpperTable[uc]; /* Use base tables */
9292 + } else {
9293 + rp = CifsUniUpperRange; /* Use range tables */
9294 + while (rp->start) {
9295 + if (uc < rp->start) /* Before start of range */
9296 + return uc; /* Uppercase = input */
9297 + if (uc <= rp->end) /* In range */
9298 + return uc + rp->table[uc - rp->start];
9299 + rp++; /* Try next range */
9300 + }
9301 + }
9302 + return uc; /* Past last range */
9303 +}
9304 +
9305 +/*
9306 + * UniStrupr: Upper case a unicode string
9307 + */
9308 +static inline wchar_t *
9309 +UniStrupr(register wchar_t * upin)
9310 +{
9311 + register wchar_t *up;
9312 +
9313 + up = upin;
9314 + while (*up) { /* For all characters */
9315 + *up = UniToupper(*up);
9316 + up++;
9317 + }
9318 + return upin; /* Return input pointer */
9319 +}
9320 +#endif /* UNIUPR_NOUPPER */
9321 +
9322 +#ifndef UNIUPR_NOLOWER
9323 +/*
9324 + * UniTolower: Convert a unicode character to lower case
9325 + */
9326 +static inline wchar_t
9327 +UniTolower(wchar_t uc)
9328 +{
9329 + register struct UniCaseRange *rp;
9330 +
9331 + if (uc < sizeof (UniLowerTable)) { /* Latin characters */
9332 + return uc + UniLowerTable[uc]; /* Use base tables */
9333 + } else {
9334 + rp = UniLowerRange; /* Use range tables */
9335 + while (rp->start) {
9336 + if (uc < rp->start) /* Before start of range */
9337 + return uc; /* Uppercase = input */
9338 + if (uc <= rp->end) /* In range */
9339 + return uc + rp->table[uc - rp->start];
9340 + rp++; /* Try next range */
9341 + }
9342 + }
9343 + return uc; /* Past last range */
9344 +}
9345 +
9346 +/*
9347 + * UniStrlwr: Lower case a unicode string
9348 + */
9349 +static inline wchar_t *
9350 +UniStrlwr(register wchar_t * upin)
9351 +{
9352 + register wchar_t *up;
9353 +
9354 + up = upin;
9355 + while (*up) { /* For all characters */
9356 + *up = UniTolower(*up);
9357 + up++;
9358 + }
9359 + return upin; /* Return input pointer */
9360 +}
9361 +
9362 +#endif
9363 Index: linux-2.4.35.4/fs/cifs/cifs_uniupr.h
9364 ===================================================================
9365 --- /dev/null
9366 +++ linux-2.4.35.4/fs/cifs/cifs_uniupr.h
9367 @@ -0,0 +1,253 @@
9368 +/*
9369 + * Copyright (c) International Business Machines Corp., 2000,2002
9370 + *
9371 + * This program is free software; you can redistribute it and/or modify
9372 + * it under the terms of the GNU General Public License as published by
9373 + * the Free Software Foundation; either version 2 of the License, or
9374 + * (at your option) any later version.
9375 + *
9376 + * This program is distributed in the hope that it will be useful,
9377 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9378 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9379 + * the GNU General Public License for more details.
9380 + *
9381 + * You should have received a copy of the GNU General Public License
9382 + * along with this program; if not, write to the Free Software
9383 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9384 + *
9385 + * uniupr.h - Unicode compressed case ranges
9386 + *
9387 +*/
9388 +
9389 +#ifndef UNIUPR_NOUPPER
9390 +/*
9391 + * Latin upper case
9392 + */
9393 +signed char CifsUniUpperTable[512] = {
9394 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
9395 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
9396 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
9397 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
9398 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
9399 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
9400 + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
9401 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
9402 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
9403 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
9404 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
9405 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
9406 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
9407 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
9408 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
9409 + -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
9410 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
9411 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
9412 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
9413 + 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
9414 + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
9415 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
9416 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
9417 + 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
9418 + 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
9419 + 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
9420 + 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
9421 + -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
9422 + 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
9423 + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
9424 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
9425 + 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
9426 +};
9427 +
9428 +/* Upper case range - Greek */
9429 +static signed char UniCaseRangeU03a0[47] = {
9430 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
9431 + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
9432 + -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
9433 + -63, -63,
9434 +};
9435 +
9436 +/* Upper case range - Cyrillic */
9437 +static signed char UniCaseRangeU0430[48] = {
9438 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
9439 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
9440 + 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
9441 +};
9442 +
9443 +/* Upper case range - Extended cyrillic */
9444 +static signed char UniCaseRangeU0490[61] = {
9445 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
9446 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
9447 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
9448 + 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
9449 +};
9450 +
9451 +/* Upper case range - Extended latin and greek */
9452 +static signed char UniCaseRangeU1e00[509] = {
9453 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
9454 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
9455 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
9456 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
9457 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
9458 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
9459 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
9460 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
9461 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
9462 + 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
9463 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
9464 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
9465 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
9466 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
9467 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
9468 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
9469 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
9470 + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
9471 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
9472 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
9473 + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
9474 + 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
9475 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
9476 + 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
9477 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
9478 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
9479 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
9480 + 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
9481 + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
9482 + 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
9483 + 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
9484 + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9485 +};
9486 +
9487 +/* Upper case range - Wide latin */
9488 +static signed char UniCaseRangeUff40[27] = {
9489 + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
9490 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
9491 +};
9492 +
9493 +/*
9494 + * Upper Case Range
9495 + */
9496 +const struct UniCaseRange CifsUniUpperRange[] = {
9497 + {0x03a0, 0x03ce, UniCaseRangeU03a0},
9498 + {0x0430, 0x045f, UniCaseRangeU0430},
9499 + {0x0490, 0x04cc, UniCaseRangeU0490},
9500 + {0x1e00, 0x1ffc, UniCaseRangeU1e00},
9501 + {0xff40, 0xff5a, UniCaseRangeUff40},
9502 + {0, 0, NULL}
9503 +};
9504 +#endif
9505 +
9506 +#ifndef UNIUPR_NOLOWER
9507 +/*
9508 + * Latin lower case
9509 + */
9510 +static signed char CifsUniLowerTable[512] = {
9511 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
9512 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
9513 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
9514 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
9515 + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
9516 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
9517 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
9518 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
9519 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
9520 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
9521 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
9522 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
9523 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
9524 + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
9525 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
9526 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
9527 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
9528 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
9529 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
9530 + 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
9531 + 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
9532 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
9533 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
9534 + 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
9535 + 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
9536 + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
9537 + 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
9538 + 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
9539 + 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
9540 + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
9541 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
9542 + 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
9543 +};
9544 +
9545 +/* Lower case range - Greek */
9546 +static signed char UniCaseRangeL0380[44] = {
9547 + 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
9548 + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
9549 + 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
9550 +};
9551 +
9552 +/* Lower case range - Cyrillic */
9553 +static signed char UniCaseRangeL0400[48] = {
9554 + 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
9555 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
9556 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
9557 +};
9558 +
9559 +/* Lower case range - Extended cyrillic */
9560 +static signed char UniCaseRangeL0490[60] = {
9561 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
9562 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
9563 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
9564 + 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
9565 +};
9566 +
9567 +/* Lower case range - Extended latin and greek */
9568 +static signed char UniCaseRangeL1e00[504] = {
9569 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
9570 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
9571 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
9572 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
9573 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
9574 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
9575 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
9576 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
9577 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
9578 + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
9579 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
9580 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
9581 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
9582 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
9583 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
9584 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
9585 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
9586 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
9587 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
9588 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
9589 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
9590 + 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
9591 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
9592 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
9593 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
9594 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
9595 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
9596 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
9597 + 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
9598 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
9599 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
9600 + 0, 0, 0, 0, 0, 0, 0, 0,
9601 +};
9602 +
9603 +/* Lower case range - Wide latin */
9604 +static signed char UniCaseRangeLff20[27] = {
9605 + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
9606 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
9607 +};
9608 +
9609 +/*
9610 + * Lower Case Range
9611 + */
9612 +const static struct UniCaseRange CifsUniLowerRange[] = {
9613 + 0x0380, 0x03ab, UniCaseRangeL0380,
9614 + 0x0400, 0x042f, UniCaseRangeL0400,
9615 + 0x0490, 0x04cb, UniCaseRangeL0490,
9616 + 0x1e00, 0x1ff7, UniCaseRangeL1e00,
9617 + 0xff20, 0xff3a, UniCaseRangeLff20,
9618 + 0, 0, 0
9619 +};
9620 +#endif
9621 Index: linux-2.4.35.4/fs/cifs/connect.c
9622 ===================================================================
9623 --- /dev/null
9624 +++ linux-2.4.35.4/fs/cifs/connect.c
9625 @@ -0,0 +1,2924 @@
9626 +/*
9627 + * fs/cifs/connect.c
9628 + *
9629 + * Copyright (C) International Business Machines Corp., 2002,2004
9630 + * Author(s): Steve French (sfrench@us.ibm.com)
9631 + *
9632 + * This library is free software; you can redistribute it and/or modify
9633 + * it under the terms of the GNU Lesser General Public License as published
9634 + * by the Free Software Foundation; either version 2.1 of the License, or
9635 + * (at your option) any later version.
9636 + *
9637 + * This library is distributed in the hope that it will be useful,
9638 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9639 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9640 + * the GNU Lesser General Public License for more details.
9641 + *
9642 + * You should have received a copy of the GNU Lesser General Public License
9643 + * along with this library; if not, write to the Free Software
9644 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9645 + */
9646 +#include <linux/fs.h>
9647 +#include <linux/net.h>
9648 +#include <linux/string.h>
9649 +#include <linux/list.h>
9650 +#include <linux/wait.h>
9651 +#include <linux/version.h>
9652 +#include <linux/ipv6.h>
9653 +#include <linux/pagemap.h>
9654 +#include <linux/ctype.h>
9655 +#include <linux/utsname.h>
9656 +#include <asm/uaccess.h>
9657 +#include <asm/processor.h>
9658 +#include "cifspdu.h"
9659 +#include "cifsglob.h"
9660 +#include "cifsproto.h"
9661 +#include "cifs_unicode.h"
9662 +#include "cifs_debug.h"
9663 +#include "cifs_fs_sb.h"
9664 +#include "ntlmssp.h"
9665 +#include "nterr.h"
9666 +#include "rfc1002pdu.h"
9667 +
9668 +#define CIFS_PORT 445
9669 +#define RFC1001_PORT 139
9670 +
9671 +extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
9672 + unsigned char *p24);
9673 +extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
9674 + unsigned char *p24);
9675 +extern int cifs_inet_pton(int, const char *, void *dst);
9676 +
9677 +struct smb_vol {
9678 + char *username;
9679 + char *password;
9680 + char *domainname;
9681 + char *UNC;
9682 + char *UNCip;
9683 + char *iocharset; /* local code page for mapping to and from Unicode */
9684 + char source_rfc1001_name[16]; /* netbios name of client */
9685 + uid_t linux_uid;
9686 + gid_t linux_gid;
9687 + mode_t file_mode;
9688 + mode_t dir_mode;
9689 + int rw:1;
9690 + int retry:1;
9691 + int intr:1;
9692 + unsigned int rsize;
9693 + unsigned int wsize;
9694 + unsigned int sockopt;
9695 + unsigned short int port;
9696 +};
9697 +
9698 +static int ipv4_connect(struct sockaddr_in *psin_server,
9699 + struct socket **csocket,
9700 + char * netb_name);
9701 +static int ipv6_connect(struct sockaddr_in6 *psin_server,
9702 + struct socket **csocket);
9703 +
9704 +
9705 + /*
9706 + * cifs tcp session reconnection
9707 + *
9708 + * mark tcp session as reconnecting so temporarily locked
9709 + * mark all smb sessions as reconnecting for tcp session
9710 + * reconnect tcp session
9711 + * wake up waiters on reconnection? - (not needed currently)
9712 + */
9713 +
9714 +int
9715 +cifs_reconnect(struct TCP_Server_Info *server)
9716 +{
9717 + int rc = 0;
9718 + struct list_head *tmp;
9719 + struct cifsSesInfo *ses;
9720 + struct cifsTconInfo *tcon;
9721 + struct mid_q_entry * mid_entry;
9722 +
9723 + spin_lock(&GlobalMid_Lock);
9724 + if(server->tcpStatus == CifsExiting) {
9725 + /* the demux thread will exit normally
9726 + next time through the loop */
9727 + spin_unlock(&GlobalMid_Lock);
9728 + return rc;
9729 + } else
9730 + server->tcpStatus = CifsNeedReconnect;
9731 + spin_unlock(&GlobalMid_Lock);
9732 + server->maxBuf = 0;
9733 +
9734 + cFYI(1, ("Reconnecting tcp session "));
9735 +
9736 + /* before reconnecting the tcp session, mark the smb session (uid)
9737 + and the tid bad so they are not used until reconnected */
9738 + read_lock(&GlobalSMBSeslock);
9739 + list_for_each(tmp, &GlobalSMBSessionList) {
9740 + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
9741 + if (ses->server) {
9742 + if (ses->server == server) {
9743 + ses->status = CifsNeedReconnect;
9744 + ses->ipc_tid = 0;
9745 + }
9746 + }
9747 + /* else tcp and smb sessions need reconnection */
9748 + }
9749 + list_for_each(tmp, &GlobalTreeConnectionList) {
9750 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
9751 + if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
9752 + tcon->tidStatus = CifsNeedReconnect;
9753 + }
9754 + }
9755 + read_unlock(&GlobalSMBSeslock);
9756 + /* do not want to be sending data on a socket we are freeing */
9757 + down(&server->tcpSem);
9758 + if(server->ssocket) {
9759 + cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
9760 + server->ssocket->flags));
9761 + server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
9762 + cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
9763 + server->ssocket->flags));
9764 + sock_release(server->ssocket);
9765 + server->ssocket = NULL;
9766 + }
9767 +
9768 + spin_lock(&GlobalMid_Lock);
9769 + list_for_each(tmp, &server->pending_mid_q) {
9770 + mid_entry = list_entry(tmp, struct
9771 + mid_q_entry,
9772 + qhead);
9773 + if(mid_entry) {
9774 + if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
9775 + /* Mark other intransit requests as needing retry so
9776 + we do not immediately mark the session bad again
9777 + (ie after we reconnect below) as they timeout too */
9778 + mid_entry->midState = MID_RETRY_NEEDED;
9779 + }
9780 + }
9781 + }
9782 + spin_unlock(&GlobalMid_Lock);
9783 + up(&server->tcpSem);
9784 +
9785 + while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
9786 + {
9787 + if(server->protocolType == IPV6) {
9788 + rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
9789 + } else {
9790 + rc = ipv4_connect(&server->addr.sockAddr,
9791 + &server->ssocket,
9792 + server->workstation_RFC1001_name);
9793 + }
9794 + if(rc) {
9795 + set_current_state(TASK_INTERRUPTIBLE);
9796 + schedule_timeout(3 * HZ);
9797 + } else {
9798 + atomic_inc(&tcpSesReconnectCount);
9799 + spin_lock(&GlobalMid_Lock);
9800 + if(server->tcpStatus != CifsExiting)
9801 + server->tcpStatus = CifsGood;
9802 + spin_unlock(&GlobalMid_Lock);
9803 + /* atomic_set(&server->inFlight,0);*/
9804 + wake_up(&server->response_q);
9805 + }
9806 + }
9807 + return rc;
9808 +}
9809 +
9810 +static int
9811 +cifs_demultiplex_thread(struct TCP_Server_Info *server)
9812 +{
9813 + int length;
9814 + unsigned int pdu_length, total_read;
9815 + struct smb_hdr *smb_buffer = NULL;
9816 + struct msghdr smb_msg;
9817 + mm_segment_t temp_fs;
9818 + struct iovec iov;
9819 + struct socket *csocket = server->ssocket;
9820 + struct list_head *tmp;
9821 + struct cifsSesInfo *ses;
9822 + struct task_struct *task_to_wake = NULL;
9823 + struct mid_q_entry *mid_entry;
9824 + char *temp;
9825 +
9826 + daemonize();
9827 + sprintf(current->comm,"cifsd");
9828 + /* allow_signal(SIGKILL);*/
9829 + current->flags |= PF_MEMALLOC;
9830 + server->tsk = current; /* save process info to wake at shutdown */
9831 + cFYI(1, ("Demultiplex PID: %d", current->pid));
9832 +
9833 + temp_fs = get_fs(); /* we must turn off socket api parm checking */
9834 + set_fs(get_ds());
9835 +
9836 + while (server->tcpStatus != CifsExiting) {
9837 + if (smb_buffer == NULL)
9838 + smb_buffer = cifs_buf_get();
9839 + else
9840 + memset(smb_buffer, 0, sizeof (struct smb_hdr));
9841 +
9842 + if (smb_buffer == NULL) {
9843 + cERROR(1,("Can not get memory for SMB response"));
9844 + set_current_state(TASK_INTERRUPTIBLE);
9845 + schedule_timeout(HZ * 3); /* give system time to free memory */
9846 + continue;
9847 + }
9848 + iov.iov_base = smb_buffer;
9849 + iov.iov_len = sizeof (struct smb_hdr) - 1;
9850 + /* 1 byte less above since wct is not always returned in error cases */
9851 + smb_msg.msg_iov = &iov;
9852 + smb_msg.msg_iovlen = 1;
9853 + smb_msg.msg_control = NULL;
9854 + smb_msg.msg_controllen = 0;
9855 +
9856 + length =
9857 + sock_recvmsg(csocket, &smb_msg,
9858 + sizeof (struct smb_hdr) -
9859 + 1 /* RFC1001 header and SMB header */ ,
9860 + MSG_PEEK /* flags see socket.h */ );
9861 +
9862 + if(server->tcpStatus == CifsExiting) {
9863 + break;
9864 + } else if (server->tcpStatus == CifsNeedReconnect) {
9865 + cFYI(1,("Reconnecting after server stopped responding"));
9866 + cifs_reconnect(server);
9867 + cFYI(1,("call to reconnect done"));
9868 + csocket = server->ssocket;
9869 + continue;
9870 + } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
9871 + set_current_state(TASK_INTERRUPTIBLE);
9872 + schedule_timeout(1); /* minimum sleep to prevent looping
9873 + allowing socket to clear and app threads to set
9874 + tcpStatus CifsNeedReconnect if server hung */
9875 + continue;
9876 + } else if (length <= 0) {
9877 + if(server->tcpStatus == CifsNew) {
9878 + cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
9879 + /* some servers kill tcp session rather than returning
9880 + smb negprot error in which case reconnecting here is
9881 + not going to help - return error to mount */
9882 + break;
9883 + }
9884 + if(length == -EINTR) {
9885 + cFYI(1,("cifsd thread killed"));
9886 + break;
9887 + }
9888 + cFYI(1,("Reconnecting after unexpected peek error %d",length));
9889 + cifs_reconnect(server);
9890 + csocket = server->ssocket;
9891 + wake_up(&server->response_q);
9892 + continue;
9893 + }
9894 +
9895 + pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
9896 + /* Ony read pdu_length after below checks for too short (due
9897 + to e.g. int overflow) and too long ie beyond end of buf */
9898 + cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
9899 +
9900 + temp = (char *) smb_buffer;
9901 + if (length > 3) {
9902 + if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
9903 + iov.iov_base = smb_buffer;
9904 + iov.iov_len = 4;
9905 + length = sock_recvmsg(csocket, &smb_msg, 4, 0);
9906 + cFYI(0,("Received 4 byte keep alive packet"));
9907 + } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
9908 + iov.iov_base = smb_buffer;
9909 + iov.iov_len = 4;
9910 + length = sock_recvmsg(csocket, &smb_msg, 4, 0);
9911 + cFYI(1,("Good RFC 1002 session rsp"));
9912 + } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
9913 + && (length == 5)) {
9914 + /* we get this from Windows 98 instead of error on SMB negprot response */
9915 + cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
9916 + if(server->tcpStatus == CifsNew) {
9917 + /* if nack on negprot (rather than
9918 + ret of smb negprot error) reconnecting
9919 + not going to help, ret error to mount */
9920 + break;
9921 + } else {
9922 + /* give server a second to
9923 + clean up before reconnect attempt */
9924 + set_current_state(TASK_INTERRUPTIBLE);
9925 + schedule_timeout(HZ);
9926 + /* always try 445 first on reconnect
9927 + since we get NACK on some if we ever
9928 + connected to port 139 (the NACK is
9929 + since we do not begin with RFC1001
9930 + session initialize frame) */
9931 + server->addr.sockAddr.sin_port = CIFS_PORT;
9932 + cifs_reconnect(server);
9933 + csocket = server->ssocket;
9934 + wake_up(&server->response_q);
9935 + continue;
9936 + }
9937 + } else if (temp[0] != (char) 0) {
9938 + cERROR(1,("Unknown RFC 1002 frame"));
9939 + cifs_dump_mem(" Received Data: ", temp, length);
9940 + cifs_reconnect(server);
9941 + csocket = server->ssocket;
9942 + continue;
9943 + } else {
9944 + if ((length != sizeof (struct smb_hdr) - 1)
9945 + || (pdu_length >
9946 + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
9947 + || (pdu_length <
9948 + sizeof (struct smb_hdr) - 1)
9949 + ||
9950 + (checkSMBhdr
9951 + (smb_buffer, smb_buffer->Mid))) {
9952 + cERROR(1,
9953 + ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
9954 + length, pdu_length));
9955 + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
9956 + /* could we fix this network corruption by finding next
9957 + smb header (instead of killing the session) and
9958 + restart reading from next valid SMB found? */
9959 + cifs_reconnect(server);
9960 + csocket = server->ssocket;
9961 + continue;
9962 + } else { /* length ok */
9963 +
9964 + length = 0;
9965 + iov.iov_base = smb_buffer;
9966 + iov.iov_len = pdu_length;
9967 + for (total_read = 0;
9968 + total_read < pdu_length;
9969 + total_read += length) {
9970 + length = sock_recvmsg(csocket, &smb_msg,
9971 + pdu_length - total_read, 0);
9972 + if (length == 0) {
9973 + cERROR(1,
9974 + ("Zero length receive when expecting %d ",
9975 + pdu_length - total_read));
9976 + cifs_reconnect(server);
9977 + csocket = server->ssocket;
9978 + continue;
9979 + }
9980 + }
9981 + }
9982 +
9983 + dump_smb(smb_buffer, length);
9984 + if (checkSMB
9985 + (smb_buffer, smb_buffer->Mid, total_read)) {
9986 + cERROR(1, ("Bad SMB Received "));
9987 + continue;
9988 + }
9989 +
9990 + task_to_wake = NULL;
9991 + spin_lock(&GlobalMid_Lock);
9992 + list_for_each(tmp, &server->pending_mid_q) {
9993 + mid_entry = list_entry(tmp, struct
9994 + mid_q_entry,
9995 + qhead);
9996 +
9997 + if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
9998 + cFYI(1,
9999 + (" Mid 0x%x matched - waking up ",mid_entry->mid));
10000 + task_to_wake = mid_entry->tsk;
10001 + mid_entry->resp_buf =
10002 + smb_buffer;
10003 + mid_entry->midState =
10004 + MID_RESPONSE_RECEIVED;
10005 + }
10006 + }
10007 + spin_unlock(&GlobalMid_Lock);
10008 + if (task_to_wake) {
10009 + smb_buffer = NULL; /* will be freed by users thread after he is done */
10010 + wake_up_process(task_to_wake);
10011 + } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
10012 + cERROR(1, ("No task to wake, unknown frame rcvd!"));
10013 + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
10014 + }
10015 + }
10016 + } else {
10017 + cFYI(0,
10018 + ("Frame less than four bytes received %d bytes long.",
10019 + length));
10020 + if (length > 0) {
10021 + length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
10022 + cFYI(1,
10023 + (" with junk 0x%x in it ",
10024 + *(__u32 *) smb_buffer));
10025 + }
10026 + }
10027 + }
10028 + spin_lock(&GlobalMid_Lock);
10029 + server->tcpStatus = CifsExiting;
10030 + server->tsk = NULL;
10031 + atomic_set(&server->inFlight, 0);
10032 + spin_unlock(&GlobalMid_Lock);
10033 + /* Although there should not be any requests blocked on
10034 + this queue it can not hurt to be paranoid and try to wake up requests
10035 + that may haven been blocked when more than 50 at time were on the wire
10036 + to the same server - they now will see the session is in exit state
10037 + and get out of SendReceive. */
10038 + wake_up_all(&server->request_q);
10039 + /* give those requests time to exit */
10040 + set_current_state(TASK_INTERRUPTIBLE);
10041 + schedule_timeout(HZ/8);
10042 +
10043 + if(server->ssocket) {
10044 + sock_release(csocket);
10045 + server->ssocket = NULL;
10046 + }
10047 + set_fs(temp_fs);
10048 + if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
10049 + cifs_buf_release(smb_buffer);
10050 +
10051 + read_lock(&GlobalSMBSeslock);
10052 + if (list_empty(&server->pending_mid_q)) {
10053 + /* loop through server session structures attached to this and mark them dead */
10054 + list_for_each(tmp, &GlobalSMBSessionList) {
10055 + ses =
10056 + list_entry(tmp, struct cifsSesInfo,
10057 + cifsSessionList);
10058 + if (ses->server == server) {
10059 + ses->status = CifsExiting;
10060 + ses->server = NULL;
10061 + }
10062 + }
10063 + read_unlock(&GlobalSMBSeslock);
10064 + } else {
10065 + spin_lock(&GlobalMid_Lock);
10066 + list_for_each(tmp, &server->pending_mid_q) {
10067 + mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
10068 + if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
10069 + cFYI(1,
10070 + (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
10071 + task_to_wake = mid_entry->tsk;
10072 + if(task_to_wake) {
10073 + wake_up_process(task_to_wake);
10074 + }
10075 + }
10076 + }
10077 + spin_unlock(&GlobalMid_Lock);
10078 + read_unlock(&GlobalSMBSeslock);
10079 + set_current_state(TASK_INTERRUPTIBLE);
10080 + /* 1/8th of sec is more than enough time for them to exit */
10081 + schedule_timeout(HZ/8);
10082 + }
10083 +
10084 + if (list_empty(&server->pending_mid_q)) {
10085 + /* mpx threads have not exited yet give them
10086 + at least the smb send timeout time for long ops */
10087 + cFYI(1, ("Wait for exit from demultiplex thread"));
10088 + set_current_state(TASK_INTERRUPTIBLE);
10089 + schedule_timeout(46 * HZ);
10090 + /* if threads still have not exited they are probably never
10091 + coming home not much else we can do but free the memory */
10092 + }
10093 + kfree(server);
10094 +
10095 + set_current_state(TASK_INTERRUPTIBLE);
10096 + schedule_timeout(HZ/4);
10097 + return 0;
10098 +}
10099 +
10100 +static void *
10101 +cifs_kcalloc(size_t size, int type)
10102 +{
10103 + void *addr;
10104 + addr = kmalloc(size, type);
10105 + if (addr)
10106 + memset(addr, 0, size);
10107 + return addr;
10108 +}
10109 +
10110 +static int
10111 +cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
10112 +{
10113 + char *value;
10114 + char *data;
10115 + unsigned int temp_len, i, j;
10116 + char separator[2];
10117 +
10118 + separator[0] = ',';
10119 + separator[1] = 0;
10120 +
10121 + memset(vol->source_rfc1001_name,0x20,15);
10122 + for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
10123 + /* does not have to be a perfect mapping since the field is
10124 + informational, only used for servers that do not support
10125 + port 445 and it can be overridden at mount time */
10126 + vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
10127 + }
10128 + vol->source_rfc1001_name[15] = 0;
10129 +
10130 + vol->linux_uid = current->uid; /* current->euid instead? */
10131 + vol->linux_gid = current->gid;
10132 + vol->dir_mode = S_IRWXUGO;
10133 + /* 2767 perms indicate mandatory locking support */
10134 + vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
10135 +
10136 + /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
10137 + vol->rw = TRUE;
10138 +
10139 + if (!options)
10140 + return 1;
10141 +
10142 + if(strncmp(options,"sep=",4) == 0) {
10143 + if(options[4] != 0) {
10144 + separator[0] = options[4];
10145 + options += 5;
10146 + } else {
10147 + cFYI(1,("Null separator not allowed"));
10148 + }
10149 + }
10150 +
10151 + while ((data = strsep(&options, separator)) != NULL) {
10152 + if (!*data)
10153 + continue;
10154 + if ((value = strchr(data, '=')) != NULL)
10155 + *value++ = '\0';
10156 + if (strnicmp(data, "user", 4) == 0) {
10157 + if (!value || !*value) {
10158 + printk(KERN_WARNING
10159 + "CIFS: invalid or missing username\n");
10160 + return 1; /* needs_arg; */
10161 + }
10162 + if (strnlen(value, 200) < 200) {
10163 + vol->username = value;
10164 + } else {
10165 + printk(KERN_WARNING "CIFS: username too long\n");
10166 + return 1;
10167 + }
10168 + } else if (strnicmp(data, "pass", 4) == 0) {
10169 + if (!value || !*value) {
10170 + vol->password = NULL;
10171 + continue;
10172 + }
10173 + temp_len = strlen(value);
10174 + /* removed password length check, NTLM passwords
10175 + can be arbitrarily long */
10176 +
10177 + /* if comma in password, the string will be
10178 + prematurely null terminated. Commas in password are
10179 + specified across the cifs mount interface by a double
10180 + comma ie ,, and a comma used as in other cases ie ','
10181 + as a parameter delimiter/separator is single and due
10182 + to the strsep above is temporarily zeroed. */
10183 +
10184 + /* NB: password legally can have multiple commas and
10185 + the only illegal character in a password is null */
10186 +
10187 + if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
10188 + /* reinsert comma */
10189 + value[temp_len] = separator[0];
10190 + temp_len+=2; /* move after the second comma */
10191 + while(value[temp_len] != 0) {
10192 + if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
10193 + /* single comma indicating start of next parm */
10194 + break;
10195 + }
10196 + temp_len++;
10197 + }
10198 + if(value[temp_len] == 0) {
10199 + options = NULL;
10200 + } else {
10201 + value[temp_len] = 0;
10202 + /* move options to point to start of next parm */
10203 + options = value + temp_len + 1;
10204 + }
10205 + /* go from value to (value + temp_len) condensing double commas to singles */
10206 + vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
10207 + for(i=0,j=0;i<temp_len;i++,j++) {
10208 + vol->password[j] = value[i];
10209 + if(value[i] == separator[0] && value[i+1] == separator[0]) {
10210 + /* skip second comma */
10211 + i++;
10212 + }
10213 + }
10214 + /* value[temp_len] is zeroed above so
10215 + vol->password[temp_len] guaranteed to be null */
10216 + } else {
10217 + vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
10218 + strcpy(vol->password, value);
10219 + }
10220 + } else if (strnicmp(data, "ip", 2) == 0) {
10221 + if (!value || !*value) {
10222 + vol->UNCip = NULL;
10223 + } else if (strnlen(value, 35) < 35) {
10224 + vol->UNCip = value;
10225 + } else {
10226 + printk(KERN_WARNING "CIFS: ip address too long\n");
10227 + return 1;
10228 + }
10229 + } else if ((strnicmp(data, "unc", 3) == 0)
10230 + || (strnicmp(data, "target", 6) == 0)
10231 + || (strnicmp(data, "path", 4) == 0)) {
10232 + if (!value || !*value) {
10233 + printk(KERN_WARNING
10234 + "CIFS: invalid path to network resource\n");
10235 + return 1; /* needs_arg; */
10236 + }
10237 + if ((temp_len = strnlen(value, 300)) < 300) {
10238 + vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
10239 + if(vol->UNC == NULL)
10240 + return 1;
10241 + strcpy(vol->UNC,value);
10242 + if (strncmp(vol->UNC, "//", 2) == 0) {
10243 + vol->UNC[0] = '\\';
10244 + vol->UNC[1] = '\\';
10245 + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
10246 + printk(KERN_WARNING
10247 + "CIFS: UNC Path does not begin with // or \\\\ \n");
10248 + return 1;
10249 + }
10250 + } else {
10251 + printk(KERN_WARNING "CIFS: UNC name too long\n");
10252 + return 1;
10253 + }
10254 + } else if ((strnicmp(data, "domain", 3) == 0)
10255 + || (strnicmp(data, "workgroup", 5) == 0)) {
10256 + if (!value || !*value) {
10257 + printk(KERN_WARNING "CIFS: invalid domain name\n");
10258 + return 1; /* needs_arg; */
10259 + }
10260 + /* BB are there cases in which a comma can be valid in
10261 + a domain name and need special handling? */
10262 + if (strnlen(value, 65) < 65) {
10263 + vol->domainname = value;
10264 + cFYI(1, ("Domain name set"));
10265 + } else {
10266 + printk(KERN_WARNING "CIFS: domain name too long\n");
10267 + return 1;
10268 + }
10269 + } else if (strnicmp(data, "iocharset", 9) == 0) {
10270 + if (!value || !*value) {
10271 + printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
10272 + return 1; /* needs_arg; */
10273 + }
10274 + if (strnlen(value, 65) < 65) {
10275 + if(strnicmp(value,"default",7))
10276 + vol->iocharset = value;
10277 + /* if iocharset not set load_nls_default used by caller */
10278 + cFYI(1, ("iocharset set to %s",value));
10279 + } else {
10280 + printk(KERN_WARNING "CIFS: iocharset name too long.\n");
10281 + return 1;
10282 + }
10283 + } else if (strnicmp(data, "uid", 3) == 0) {
10284 + if (value && *value) {
10285 + vol->linux_uid =
10286 + simple_strtoul(value, &value, 0);
10287 + }
10288 + } else if (strnicmp(data, "gid", 3) == 0) {
10289 + if (value && *value) {
10290 + vol->linux_gid =
10291 + simple_strtoul(value, &value, 0);
10292 + }
10293 + } else if (strnicmp(data, "file_mode", 4) == 0) {
10294 + if (value && *value) {
10295 + vol->file_mode =
10296 + simple_strtoul(value, &value, 0);
10297 + }
10298 + } else if (strnicmp(data, "dir_mode", 3) == 0) {
10299 + if (value && *value) {
10300 + vol->dir_mode =
10301 + simple_strtoul(value, &value, 0);
10302 + }
10303 + } else if (strnicmp(data, "port", 4) == 0) {
10304 + if (value && *value) {
10305 + vol->port =
10306 + simple_strtoul(value, &value, 0);
10307 + }
10308 + } else if (strnicmp(data, "rsize", 5) == 0) {
10309 + if (value && *value) {
10310 + vol->rsize =
10311 + simple_strtoul(value, &value, 0);
10312 + }
10313 + } else if (strnicmp(data, "wsize", 5) == 0) {
10314 + if (value && *value) {
10315 + vol->wsize =
10316 + simple_strtoul(value, &value, 0);
10317 + }
10318 + } else if (strnicmp(data, "sockopt", 5) == 0) {
10319 + if (value && *value) {
10320 + vol->sockopt =
10321 + simple_strtoul(value, &value, 0);
10322 + }
10323 + } else if (strnicmp(data, "netbiosname", 4) == 0) {
10324 + if (!value || !*value || (*value == ' ')) {
10325 + cFYI(1,("invalid (empty) netbiosname specified"));
10326 + } else {
10327 + memset(vol->source_rfc1001_name,0x20,15);
10328 + for(i=0;i<15;i++) {
10329 + /* BB are there cases in which a comma can be
10330 + valid in this workstation netbios name (and need
10331 + special handling)? */
10332 +
10333 + /* We do not uppercase netbiosname for user */
10334 + if (value[i]==0)
10335 + break;
10336 + else
10337 + vol->source_rfc1001_name[i] = value[i];
10338 + }
10339 + /* The string has 16th byte zero still from
10340 + set at top of the function */
10341 + if((i==15) && (value[i] != 0))
10342 + printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
10343 + }
10344 + } else if (strnicmp(data, "credentials", 4) == 0) {
10345 + /* ignore */
10346 + } else if (strnicmp(data, "version", 3) == 0) {
10347 + /* ignore */
10348 + } else if (strnicmp(data, "rw", 2) == 0) {
10349 + vol->rw = TRUE;
10350 + } else if ((strnicmp(data, "suid", 4) == 0) ||
10351 + (strnicmp(data, "nosuid", 6) == 0) ||
10352 + (strnicmp(data, "exec", 4) == 0) ||
10353 + (strnicmp(data, "noexec", 6) == 0) ||
10354 + (strnicmp(data, "nodev", 5) == 0) ||
10355 + (strnicmp(data, "noauto", 6) == 0) ||
10356 + (strnicmp(data, "dev", 3) == 0)) {
10357 + /* The mount tool or mount.cifs helper (if present)
10358 + uses these opts to set flags, and the flags are read
10359 + by the kernel vfs layer before we get here (ie
10360 + before read super) so there is no point trying to
10361 + parse these options again and set anything and it
10362 + is ok to just ignore them */
10363 + continue;
10364 + } else if (strnicmp(data, "ro", 2) == 0) {
10365 + vol->rw = FALSE;
10366 + } else if (strnicmp(data, "hard", 4) == 0) {
10367 + vol->retry = 1;
10368 + } else if (strnicmp(data, "soft", 4) == 0) {
10369 + vol->retry = 0;
10370 + } else if (strnicmp(data, "nohard", 6) == 0) {
10371 + vol->retry = 0;
10372 + } else if (strnicmp(data, "nosoft", 6) == 0) {
10373 + vol->retry = 1;
10374 + } else if (strnicmp(data, "nointr", 6) == 0) {
10375 + vol->intr = 0;
10376 + } else if (strnicmp(data, "intr", 4) == 0) {
10377 + vol->intr = 1;
10378 + } else if (strnicmp(data, "noac", 4) == 0) {
10379 + printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
10380 + } else
10381 + printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
10382 + }
10383 + if (vol->UNC == NULL) {
10384 + if(devname == NULL) {
10385 + printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
10386 + return 1;
10387 + }
10388 + if ((temp_len = strnlen(devname, 300)) < 300) {
10389 + vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
10390 + if(vol->UNC == NULL)
10391 + return 1;
10392 + strcpy(vol->UNC,devname);
10393 + if (strncmp(vol->UNC, "//", 2) == 0) {
10394 + vol->UNC[0] = '\\';
10395 + vol->UNC[1] = '\\';
10396 + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
10397 + printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
10398 + return 1;
10399 + }
10400 + } else {
10401 + printk(KERN_WARNING "CIFS: UNC name too long\n");
10402 + return 1;
10403 + }
10404 + }
10405 + if(vol->UNCip == 0)
10406 + vol->UNCip = &vol->UNC[2];
10407 +
10408 + return 0;
10409 +}
10410 +
10411 +static struct cifsSesInfo *
10412 +cifs_find_tcp_session(__u32 new_target_ip_addr,
10413 + char *userName, struct TCP_Server_Info **psrvTcp)
10414 +{
10415 + struct list_head *tmp;
10416 + struct cifsSesInfo *ses;
10417 +
10418 + *psrvTcp = NULL;
10419 + read_lock(&GlobalSMBSeslock);
10420 + list_for_each(tmp, &GlobalSMBSessionList) {
10421 + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
10422 + if (ses->server) {
10423 + if (ses->server->addr.sockAddr.sin_addr.s_addr ==
10424 + new_target_ip_addr) {
10425 + /* BB lock server and tcp session and increment use count here?? */
10426 + *psrvTcp = ses->server; /* found a match on the TCP session */
10427 + /* BB check if reconnection needed */
10428 + if (strncmp
10429 + (ses->userName, userName,
10430 + MAX_USERNAME_SIZE) == 0){
10431 + read_unlock(&GlobalSMBSeslock);
10432 + return ses; /* found exact match on both tcp and SMB sessions */
10433 + }
10434 + }
10435 + }
10436 + /* else tcp and smb sessions need reconnection */
10437 + }
10438 + read_unlock(&GlobalSMBSeslock);
10439 + return NULL;
10440 +}
10441 +
10442 +static struct cifsTconInfo *
10443 +find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
10444 +{
10445 + struct list_head *tmp;
10446 + struct cifsTconInfo *tcon;
10447 +
10448 + read_lock(&GlobalSMBSeslock);
10449 + list_for_each(tmp, &GlobalTreeConnectionList) {
10450 + cFYI(1, ("Next tcon - "));
10451 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
10452 + if (tcon->ses) {
10453 + if (tcon->ses->server) {
10454 + cFYI(1,
10455 + (" old ip addr: %x == new ip %x ?",
10456 + tcon->ses->server->addr.sockAddr.sin_addr.
10457 + s_addr, new_target_ip_addr));
10458 + if (tcon->ses->server->addr.sockAddr.sin_addr.
10459 + s_addr == new_target_ip_addr) {
10460 + /* BB lock tcon and server and tcp session and increment use count here? */
10461 + /* found a match on the TCP session */
10462 + /* BB check if reconnection needed */
10463 + cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
10464 + tcon->treeName, uncName));
10465 + if (strncmp
10466 + (tcon->treeName, uncName,
10467 + MAX_TREE_SIZE) == 0) {
10468 + cFYI(1,
10469 + ("Matched UNC, old user: %s == new: %s ?",
10470 + tcon->treeName, uncName));
10471 + if (strncmp
10472 + (tcon->ses->userName,
10473 + userName,
10474 + MAX_USERNAME_SIZE) == 0) {
10475 + read_unlock(&GlobalSMBSeslock);
10476 + return tcon;/* also matched user (smb session)*/
10477 + }
10478 + }
10479 + }
10480 + }
10481 + }
10482 + }
10483 + read_unlock(&GlobalSMBSeslock);
10484 + return NULL;
10485 +}
10486 +
10487 +int
10488 +connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
10489 + const char *old_path, const struct nls_table *nls_codepage)
10490 +{
10491 + unsigned char *referrals = NULL;
10492 + unsigned int num_referrals;
10493 + int rc = 0;
10494 +
10495 + rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
10496 + &num_referrals, &referrals);
10497 +
10498 + /* BB Add in code to: if valid refrl, if not ip address contact
10499 + the helper that resolves tcp names, mount to it, try to
10500 + tcon to it unmount it if fail */
10501 +
10502 + if(referrals)
10503 + kfree(referrals);
10504 +
10505 + return rc;
10506 +}
10507 +
10508 +int
10509 +get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
10510 + const char *old_path, const struct nls_table *nls_codepage,
10511 + unsigned int *pnum_referrals, unsigned char ** preferrals)
10512 +{
10513 + char *temp_unc;
10514 + int rc = 0;
10515 +
10516 + *pnum_referrals = 0;
10517 +
10518 + if (pSesInfo->ipc_tid == 0) {
10519 + temp_unc = kmalloc(2 /* for slashes */ +
10520 + strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
10521 + + 1 + 4 /* slash IPC$ */ + 2,
10522 + GFP_KERNEL);
10523 + if (temp_unc == NULL)
10524 + return -ENOMEM;
10525 + temp_unc[0] = '\\';
10526 + temp_unc[1] = '\\';
10527 + strcpy(temp_unc + 2, pSesInfo->serverName);
10528 + strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
10529 + rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
10530 + cFYI(1,
10531 + ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
10532 + kfree(temp_unc);
10533 + }
10534 + if (rc == 0)
10535 + rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
10536 + pnum_referrals, nls_codepage);
10537 +
10538 + return rc;
10539 +}
10540 +
10541 +/* See RFC1001 section 14 on representation of Netbios names */
10542 +static void rfc1002mangle(char * target,char * source, unsigned int length)
10543 +{
10544 + unsigned int i,j;
10545 +
10546 + for(i=0,j=0;i<(length);i++) {
10547 + /* mask a nibble at a time and encode */
10548 + target[j] = 'A' + (0x0F & (source[i] >> 4));
10549 + target[j+1] = 'A' + (0x0F & source[i]);
10550 + j+=2;
10551 + }
10552 +
10553 +}
10554 +
10555 +
10556 +static int
10557 +ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
10558 + char * netbios_name)
10559 +{
10560 + int rc = 0;
10561 + int connected = 0;
10562 + unsigned short int orig_port = 0;
10563 +
10564 + if(*csocket == NULL) {
10565 + rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
10566 + if (rc < 0) {
10567 + cERROR(1, ("Error %d creating socket",rc));
10568 + *csocket = NULL;
10569 + return rc;
10570 + } else {
10571 + /* BB other socket options to set KEEPALIVE, NODELAY? */
10572 + cFYI(1,("Socket created"));
10573 + (*csocket)->sk->allocation = GFP_NOFS;
10574 + }
10575 + }
10576 +
10577 + psin_server->sin_family = AF_INET;
10578 + if(psin_server->sin_port) { /* user overrode default port */
10579 + rc = (*csocket)->ops->connect(*csocket,
10580 + (struct sockaddr *) psin_server,
10581 + sizeof (struct sockaddr_in),0);
10582 + if (rc >= 0)
10583 + connected = 1;
10584 + }
10585 +
10586 + if(!connected) {
10587 + /* save original port so we can retry user specified port
10588 + later if fall back ports fail this time */
10589 + orig_port = psin_server->sin_port;
10590 +
10591 + /* do not retry on the same port we just failed on */
10592 + if(psin_server->sin_port != htons(CIFS_PORT)) {
10593 + psin_server->sin_port = htons(CIFS_PORT);
10594 +
10595 + rc = (*csocket)->ops->connect(*csocket,
10596 + (struct sockaddr *) psin_server,
10597 + sizeof (struct sockaddr_in),0);
10598 + if (rc >= 0)
10599 + connected = 1;
10600 + }
10601 + }
10602 + if (!connected) {
10603 + psin_server->sin_port = htons(RFC1001_PORT);
10604 + rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
10605 + psin_server, sizeof (struct sockaddr_in),0);
10606 + if (rc >= 0)
10607 + connected = 1;
10608 + }
10609 +
10610 + /* give up here - unless we want to retry on different
10611 + protocol families some day */
10612 + if (!connected) {
10613 + if(orig_port)
10614 + psin_server->sin_port = orig_port;
10615 + cFYI(1,("Error %d connecting to server via ipv4",rc));
10616 + sock_release(*csocket);
10617 + *csocket = NULL;
10618 + return rc;
10619 + }
10620 + /* Eventually check for other socket options to change from
10621 + the default. sock_setsockopt not used because it expects
10622 + user space buffer */
10623 + (*csocket)->sk->rcvtimeo = 7 * HZ;
10624 +
10625 + /* send RFC1001 sessinit */
10626 +
10627 + if(psin_server->sin_port == htons(139)) {
10628 + /* some servers require RFC1001 sessinit before sending
10629 + negprot - BB check reconnection in case where second
10630 + sessinit is sent but no second negprot */
10631 + struct rfc1002_session_packet * ses_init_buf;
10632 + struct smb_hdr * smb_buf;
10633 + ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
10634 + if(ses_init_buf) {
10635 + ses_init_buf->trailer.session_req.called_len = 32;
10636 + rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
10637 + DEFAULT_CIFS_CALLED_NAME,16);
10638 + ses_init_buf->trailer.session_req.calling_len = 32;
10639 + /* calling name ends in null (byte 16) from old smb
10640 + convention. */
10641 + if(netbios_name && (netbios_name[0] !=0)) {
10642 + rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
10643 + netbios_name,16);
10644 + } else {
10645 + rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
10646 + "LINUX_CIFS_CLNT",16);
10647 + }
10648 + ses_init_buf->trailer.session_req.scope1 = 0;
10649 + ses_init_buf->trailer.session_req.scope2 = 0;
10650 + smb_buf = (struct smb_hdr *)ses_init_buf;
10651 + /* sizeof RFC1002_SESSION_REQUEST with no scope */
10652 + smb_buf->smb_buf_length = 0x81000044;
10653 + rc = smb_send(*csocket, smb_buf, 0x44,
10654 + (struct sockaddr *)psin_server);
10655 + kfree(ses_init_buf);
10656 + }
10657 + /* else the negprot may still work without this
10658 + even though malloc failed */
10659 +
10660 + }
10661 +
10662 + return rc;
10663 +}
10664 +
10665 +static int
10666 +ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
10667 +{
10668 + int rc = 0;
10669 + int connected = 0;
10670 +
10671 + if(*csocket == NULL) {
10672 + rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
10673 + if (rc < 0) {
10674 + cERROR(1, ("Error %d creating ipv6 socket",rc));
10675 + *csocket = NULL;
10676 + return rc;
10677 + } else {
10678 + /* BB other socket options to set KEEPALIVE, NODELAY? */
10679 + cFYI(1,("ipv6 Socket created"));
10680 + (*csocket)->sk->allocation = GFP_NOFS;
10681 + }
10682 + }
10683 +
10684 + psin_server->sin6_family = AF_INET6;
10685 +
10686 + if(psin_server->sin6_port) { /* user overrode default port */
10687 + rc = (*csocket)->ops->connect(*csocket,
10688 + (struct sockaddr *) psin_server,
10689 + sizeof (struct sockaddr_in6),0);
10690 + if (rc >= 0)
10691 + connected = 1;
10692 + }
10693 +
10694 + if(!connected) {
10695 + /* do not retry on the same port we just failed on */
10696 + if(psin_server->sin6_port != htons(CIFS_PORT)) {
10697 + psin_server->sin6_port = htons(CIFS_PORT);
10698 +
10699 + rc = (*csocket)->ops->connect(*csocket,
10700 + (struct sockaddr *) psin_server,
10701 + sizeof (struct sockaddr_in6),0);
10702 + if (rc >= 0)
10703 + connected = 1;
10704 + }
10705 + }
10706 + if (!connected) {
10707 + psin_server->sin6_port = htons(RFC1001_PORT);
10708 + rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
10709 + psin_server, sizeof (struct sockaddr_in6),0);
10710 + if (rc >= 0)
10711 + connected = 1;
10712 + }
10713 +
10714 + /* give up here - unless we want to retry on different
10715 + protocol families some day */
10716 + if (!connected) {
10717 + cFYI(1,("Error %d connecting to server via ipv6",rc));
10718 + sock_release(*csocket);
10719 + *csocket = NULL;
10720 + return rc;
10721 + }
10722 + /* Eventually check for other socket options to change from
10723 + the default. sock_setsockopt not used because it expects
10724 + user space buffer */
10725 + (*csocket)->sk->rcvtimeo = 7 * HZ;
10726 +
10727 + return rc;
10728 +}
10729 +
10730 +int
10731 +cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
10732 + char *mount_data, const char *devname)
10733 +{
10734 + int rc = 0;
10735 + int xid;
10736 + struct socket *csocket = NULL;
10737 + struct sockaddr_in sin_server;
10738 + struct sockaddr_in6 sin_server6;
10739 + struct smb_vol volume_info;
10740 + struct cifsSesInfo *pSesInfo = NULL;
10741 + struct cifsSesInfo *existingCifsSes = NULL;
10742 + struct cifsTconInfo *tcon = NULL;
10743 + struct TCP_Server_Info *srvTcp = NULL;
10744 +
10745 + xid = GetXid();
10746 +
10747 + cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); /* BB removeme BB fixme */
10748 +
10749 + memset(&volume_info,0,sizeof(struct smb_vol));
10750 + if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
10751 + if(volume_info.UNC)
10752 + kfree(volume_info.UNC);
10753 + if(volume_info.password)
10754 + kfree(volume_info.password);
10755 + FreeXid(xid);
10756 + return -EINVAL;
10757 + }
10758 +
10759 + if (volume_info.username) {
10760 + cFYI(1, ("Username: %s ", volume_info.username));
10761 +
10762 + } else {
10763 + cifserror("No username specified ");
10764 + /* In userspace mount helper we can get user name from alternate
10765 + locations such as env variables and files on disk */
10766 + if(volume_info.UNC)
10767 + kfree(volume_info.UNC);
10768 + if(volume_info.password)
10769 + kfree(volume_info.password);
10770 + FreeXid(xid);
10771 + return -EINVAL;
10772 + }
10773 +
10774 + if (volume_info.UNCip && volume_info.UNC) {
10775 + rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
10776 +
10777 + if(rc == 0) {
10778 + /* not ipv4 address, try ipv6 */
10779 + rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
10780 + }
10781 +
10782 + if(rc != 1) {
10783 + /* we failed translating address */
10784 + if(volume_info.UNC)
10785 + kfree(volume_info.UNC);
10786 + if(volume_info.password)
10787 + kfree(volume_info.password);
10788 + FreeXid(xid);
10789 + return -EINVAL;
10790 + }
10791 +
10792 + cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
10793 + /* success */
10794 + rc = 0;
10795 + } else if (volume_info.UNCip){
10796 + /* BB using ip addr as server name connect to the DFS root below */
10797 + cERROR(1,("Connecting to DFS root not implemented yet"));
10798 + if(volume_info.UNC)
10799 + kfree(volume_info.UNC);
10800 + if(volume_info.password)
10801 + kfree(volume_info.password);
10802 + FreeXid(xid);
10803 + return -EINVAL;
10804 + } else /* which servers DFS root would we conect to */ {
10805 + cERROR(1,
10806 + ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
10807 + if(volume_info.UNC)
10808 + kfree(volume_info.UNC);
10809 + if(volume_info.password)
10810 + kfree(volume_info.password);
10811 + FreeXid(xid);
10812 + return -EINVAL;
10813 + }
10814 +
10815 + /* this is needed for ASCII cp to Unicode converts */
10816 + if(volume_info.iocharset == NULL) {
10817 + cifs_sb->local_nls = load_nls_default();
10818 + /* load_nls_default can not return null */
10819 + } else {
10820 + cifs_sb->local_nls = load_nls(volume_info.iocharset);
10821 + if(cifs_sb->local_nls == NULL) {
10822 + cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
10823 + if(volume_info.UNC)
10824 + kfree(volume_info.UNC);
10825 + if(volume_info.password)
10826 + kfree(volume_info.password);
10827 + FreeXid(xid);
10828 + return -ELIBACC;
10829 + }
10830 + }
10831 +
10832 + existingCifsSes =
10833 + cifs_find_tcp_session(sin_server.sin_addr.s_addr,
10834 + volume_info.username, &srvTcp);
10835 + if (srvTcp) {
10836 + cFYI(1, ("Existing tcp session with server found "));
10837 + } else { /* create socket */
10838 + if(volume_info.port)
10839 + sin_server.sin_port = htons(volume_info.port);
10840 + else
10841 + sin_server.sin_port = 0;
10842 + rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
10843 + if (rc < 0) {
10844 + cERROR(1,
10845 + ("Error connecting to IPv4 socket. Aborting operation"));
10846 + if(csocket != NULL)
10847 + sock_release(csocket);
10848 + if(volume_info.UNC)
10849 + kfree(volume_info.UNC);
10850 + if(volume_info.password)
10851 + kfree(volume_info.password);
10852 + FreeXid(xid);
10853 + return rc;
10854 + }
10855 +
10856 + srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
10857 + if (srvTcp == NULL) {
10858 + rc = -ENOMEM;
10859 + sock_release(csocket);
10860 + if(volume_info.UNC)
10861 + kfree(volume_info.UNC);
10862 + if(volume_info.password)
10863 + kfree(volume_info.password);
10864 + FreeXid(xid);
10865 + return rc;
10866 + } else {
10867 + memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
10868 + memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
10869 + atomic_set(&srvTcp->inFlight,0);
10870 + /* BB Add code for ipv6 case too */
10871 + srvTcp->ssocket = csocket;
10872 + srvTcp->protocolType = IPV4;
10873 + init_waitqueue_head(&srvTcp->response_q);
10874 + init_waitqueue_head(&srvTcp->request_q);
10875 + INIT_LIST_HEAD(&srvTcp->pending_mid_q);
10876 + /* at this point we are the only ones with the pointer
10877 + to the struct since the kernel thread not created yet
10878 + so no need to spinlock this init of tcpStatus */
10879 + srvTcp->tcpStatus = CifsNew;
10880 + init_MUTEX(&srvTcp->tcpSem);
10881 + kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
10882 + CLONE_FS | CLONE_FILES | CLONE_VM);
10883 + memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
10884 + }
10885 + }
10886 +
10887 + if (existingCifsSes) {
10888 + pSesInfo = existingCifsSes;
10889 + cFYI(1, ("Existing smb sess found "));
10890 + if(volume_info.password)
10891 + kfree(volume_info.password);
10892 + /* volume_info.UNC freed at end of function */
10893 + } else if (!rc) {
10894 + cFYI(1, ("Existing smb sess not found "));
10895 + pSesInfo = sesInfoAlloc();
10896 + if (pSesInfo == NULL)
10897 + rc = -ENOMEM;
10898 + else {
10899 + pSesInfo->server = srvTcp;
10900 + sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
10901 + NIPQUAD(sin_server.sin_addr.s_addr));
10902 + }
10903 +
10904 + if (!rc){
10905 + /* volume_info.password freed at unmount */
10906 + if (volume_info.password)
10907 + pSesInfo->password = volume_info.password;
10908 + if (volume_info.username)
10909 + strncpy(pSesInfo->userName,
10910 + volume_info.username,MAX_USERNAME_SIZE);
10911 + if (volume_info.domainname)
10912 + strncpy(pSesInfo->domainName,
10913 + volume_info.domainname,MAX_USERNAME_SIZE);
10914 + pSesInfo->linux_uid = volume_info.linux_uid;
10915 + down(&pSesInfo->sesSem);
10916 + rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
10917 + up(&pSesInfo->sesSem);
10918 + if(!rc)
10919 + atomic_inc(&srvTcp->socketUseCount);
10920 + } else
10921 + if(volume_info.password)
10922 + kfree(volume_info.password);
10923 + }
10924 +
10925 + /* search for existing tcon to this server share */
10926 + if (!rc) {
10927 + if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
10928 + cifs_sb->rsize = volume_info.rsize;
10929 + else
10930 + cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
10931 + if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
10932 + cifs_sb->wsize = volume_info.wsize;
10933 + else
10934 + cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
10935 + if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
10936 + cifs_sb->rsize = PAGE_CACHE_SIZE;
10937 + cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
10938 + }
10939 + cifs_sb->mnt_uid = volume_info.linux_uid;
10940 + cifs_sb->mnt_gid = volume_info.linux_gid;
10941 + cifs_sb->mnt_file_mode = volume_info.file_mode;
10942 + cifs_sb->mnt_dir_mode = volume_info.dir_mode;
10943 + cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
10944 + tcon =
10945 + find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
10946 + volume_info.username);
10947 + if (tcon) {
10948 + cFYI(1, ("Found match on UNC path "));
10949 + /* we can have only one retry value for a connection
10950 + to a share so for resources mounted more than once
10951 + to the same server share the last value passed in
10952 + for the retry flag is used */
10953 + tcon->retry = volume_info.retry;
10954 + } else {
10955 + tcon = tconInfoAlloc();
10956 + if (tcon == NULL)
10957 + rc = -ENOMEM;
10958 + else {
10959 + /* check for null share name ie connect to dfs root */
10960 +
10961 + /* BB check if this works for exactly length three strings */
10962 + if ((strchr(volume_info.UNC + 3, '\\') == NULL)
10963 + && (strchr(volume_info.UNC + 3, '/') ==
10964 + NULL)) {
10965 + rc = connect_to_dfs_path(xid,
10966 + pSesInfo,
10967 + "",
10968 + cifs_sb->
10969 + local_nls);
10970 + if(volume_info.UNC)
10971 + kfree(volume_info.UNC);
10972 + FreeXid(xid);
10973 + return -ENODEV;
10974 + } else {
10975 + rc = CIFSTCon(xid, pSesInfo,
10976 + volume_info.UNC,
10977 + tcon, cifs_sb->local_nls);
10978 + cFYI(1, ("CIFS Tcon rc = %d", rc));
10979 + }
10980 + if (!rc) {
10981 + atomic_inc(&pSesInfo->inUse);
10982 + tcon->retry = volume_info.retry;
10983 + }
10984 + }
10985 + }
10986 + }
10987 + if(pSesInfo) {
10988 + if (pSesInfo->capabilities & CAP_LARGE_FILES) {
10989 + sb->s_maxbytes = (u64) 1 << 63;
10990 + } else
10991 + sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
10992 + }
10993 +
10994 +/* on error free sesinfo and tcon struct if needed */
10995 + if (rc) {
10996 + /* if session setup failed, use count is zero but
10997 + we still need to free cifsd thread */
10998 + if(atomic_read(&srvTcp->socketUseCount) == 0) {
10999 + spin_lock(&GlobalMid_Lock);
11000 + srvTcp->tcpStatus = CifsExiting;
11001 + spin_unlock(&GlobalMid_Lock);
11002 + if(srvTcp->tsk)
11003 + send_sig(SIGKILL,srvTcp->tsk,1);
11004 + }
11005 + /* If find_unc succeeded then rc == 0 so we can not end */
11006 + if (tcon) /* up accidently freeing someone elses tcon struct */
11007 + tconInfoFree(tcon);
11008 + if (existingCifsSes == 0) {
11009 + if (pSesInfo) {
11010 + if ((pSesInfo->server) &&
11011 + (pSesInfo->status == CifsGood)) {
11012 + int temp_rc;
11013 + temp_rc = CIFSSMBLogoff(xid, pSesInfo);
11014 + /* if the socketUseCount is now zero */
11015 + if((temp_rc == -ESHUTDOWN) &&
11016 + (pSesInfo->server->tsk))
11017 + send_sig(SIGKILL,pSesInfo->server->tsk,1);
11018 + } else
11019 + cFYI(1, ("No session or bad tcon"));
11020 + sesInfoFree(pSesInfo);
11021 + /* pSesInfo = NULL; */
11022 + }
11023 + }
11024 + } else {
11025 + atomic_inc(&tcon->useCount);
11026 + cifs_sb->tcon = tcon;
11027 + tcon->ses = pSesInfo;
11028 +
11029 + /* do not care if following two calls succeed - informational only */
11030 + CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
11031 + CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
11032 + if (tcon->ses->capabilities & CAP_UNIX)
11033 + CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
11034 + }
11035 +
11036 + /* volume_info.password is freed above when existing session found
11037 + (in which case it is not needed anymore) but when new sesion is created
11038 + the password ptr is put in the new session structure (in which case the
11039 + password will be freed at unmount time) */
11040 + if(volume_info.UNC)
11041 + kfree(volume_info.UNC);
11042 + FreeXid(xid);
11043 + return rc;
11044 +}
11045 +
11046 +static int
11047 +CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11048 + char session_key[CIFS_SESSION_KEY_SIZE],
11049 + const struct nls_table *nls_codepage)
11050 +{
11051 + struct smb_hdr *smb_buffer;
11052 + struct smb_hdr *smb_buffer_response;
11053 + SESSION_SETUP_ANDX *pSMB;
11054 + SESSION_SETUP_ANDX *pSMBr;
11055 + char *bcc_ptr;
11056 + char *user = ses->userName;
11057 + char *domain = ses->domainName;
11058 + int rc = 0;
11059 + int remaining_words = 0;
11060 + int bytes_returned = 0;
11061 + int len;
11062 +
11063 + cFYI(1, ("In sesssetup "));
11064 +
11065 + smb_buffer = cifs_buf_get();
11066 + if (smb_buffer == 0) {
11067 + return -ENOMEM;
11068 + }
11069 + smb_buffer_response = smb_buffer;
11070 + pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11071 +
11072 + /* send SMBsessionSetup here */
11073 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11074 + NULL /* no tCon exists yet */ , 13 /* wct */ );
11075 +
11076 + pSMB->req_no_secext.AndXCommand = 0xFF;
11077 + pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11078 + pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11079 +
11080 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11081 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11082 +
11083 + pSMB->req_no_secext.Capabilities =
11084 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
11085 + if (ses->capabilities & CAP_UNICODE) {
11086 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11087 + pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
11088 + }
11089 + if (ses->capabilities & CAP_STATUS32) {
11090 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11091 + pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
11092 + }
11093 + if (ses->capabilities & CAP_DFS) {
11094 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11095 + pSMB->req_no_secext.Capabilities |= CAP_DFS;
11096 + }
11097 + pSMB->req_no_secext.Capabilities =
11098 + cpu_to_le32(pSMB->req_no_secext.Capabilities);
11099 + /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
11100 + CIFS_SESSION_KEY_SIZE; */
11101 + pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
11102 + pSMB->req_no_secext.CaseSensitivePasswordLength =
11103 + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11104 + bcc_ptr = pByteArea(smb_buffer);
11105 + /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
11106 + bcc_ptr += CIFS_SESSION_KEY_SIZE; */
11107 + memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
11108 + bcc_ptr += CIFS_SESSION_KEY_SIZE;
11109 +
11110 + if (ses->capabilities & CAP_UNICODE) {
11111 + if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
11112 + *bcc_ptr = 0;
11113 + bcc_ptr++;
11114 + }
11115 + if(user == NULL)
11116 + bytes_returned = 0; /* skill null user */
11117 + else
11118 + bytes_returned =
11119 + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
11120 + nls_codepage);
11121 + bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
11122 + bcc_ptr += 2; /* trailing null */
11123 + if (domain == NULL)
11124 + bytes_returned =
11125 + cifs_strtoUCS((wchar_t *) bcc_ptr,
11126 + "CIFS_LINUX_DOM", 32, nls_codepage);
11127 + else
11128 + bytes_returned =
11129 + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11130 + nls_codepage);
11131 + bcc_ptr += 2 * bytes_returned;
11132 + bcc_ptr += 2;
11133 + bytes_returned =
11134 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11135 + 32, nls_codepage);
11136 + bcc_ptr += 2 * bytes_returned;
11137 + bytes_returned =
11138 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11139 + nls_codepage);
11140 + bcc_ptr += 2 * bytes_returned;
11141 + bcc_ptr += 2;
11142 + bytes_returned =
11143 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11144 + 64, nls_codepage);
11145 + bcc_ptr += 2 * bytes_returned;
11146 + bcc_ptr += 2;
11147 + } else {
11148 + if(user != NULL) {
11149 + strncpy(bcc_ptr, user, 200);
11150 + bcc_ptr += strnlen(user, 200);
11151 + }
11152 + *bcc_ptr = 0;
11153 + bcc_ptr++;
11154 + if (domain == NULL) {
11155 + strcpy(bcc_ptr, "CIFS_LINUX_DOM");
11156 + bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
11157 + } else {
11158 + strncpy(bcc_ptr, domain, 64);
11159 + bcc_ptr += strnlen(domain, 64);
11160 + *bcc_ptr = 0;
11161 + bcc_ptr++;
11162 + }
11163 + strcpy(bcc_ptr, "Linux version ");
11164 + bcc_ptr += strlen("Linux version ");
11165 + strcpy(bcc_ptr, UTS_RELEASE);
11166 + bcc_ptr += strlen(UTS_RELEASE) + 1;
11167 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11168 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11169 + }
11170 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11171 + smb_buffer->smb_buf_length += BCC(smb_buffer);
11172 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11173 +
11174 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11175 + &bytes_returned, 1);
11176 + if (rc) {
11177 +/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
11178 + } else if ((smb_buffer_response->WordCount == 3)
11179 + || (smb_buffer_response->WordCount == 4)) {
11180 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11181 + if (pSMBr->resp.Action & GUEST_LOGIN)
11182 + cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
11183 + if (ses) {
11184 + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
11185 + cFYI(1, ("UID = %d ", ses->Suid));
11186 + /* response can have either 3 or 4 word count - Samba sends 3 */
11187 + bcc_ptr = pByteArea(smb_buffer_response);
11188 + if ((pSMBr->resp.hdr.WordCount == 3)
11189 + || ((pSMBr->resp.hdr.WordCount == 4)
11190 + && (pSMBr->resp.SecurityBlobLength <
11191 + pSMBr->resp.ByteCount))) {
11192 + if (pSMBr->resp.hdr.WordCount == 4)
11193 + bcc_ptr +=
11194 + pSMBr->resp.SecurityBlobLength;
11195 +
11196 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11197 + if ((long) (bcc_ptr) % 2) {
11198 + remaining_words =
11199 + (BCC(smb_buffer_response)
11200 + - 1) / 2;
11201 + bcc_ptr++; /* Unicode strings must be word aligned */
11202 + } else {
11203 + remaining_words =
11204 + BCC
11205 + (smb_buffer_response) / 2;
11206 + }
11207 + len =
11208 + UniStrnlen((wchar_t *) bcc_ptr,
11209 + remaining_words - 1);
11210 +/* We look for obvious messed up bcc or strings in response so we do not go off
11211 + the end since (at least) WIN2K and Windows XP have a major bug in not null
11212 + terminating last Unicode string in response */
11213 + ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11214 + cifs_strfromUCS_le(ses->serverOS,
11215 + (wchar_t *)bcc_ptr, len,nls_codepage);
11216 + bcc_ptr += 2 * (len + 1);
11217 + remaining_words -= len + 1;
11218 + ses->serverOS[2 * len] = 0;
11219 + ses->serverOS[1 + (2 * len)] = 0;
11220 + if (remaining_words > 0) {
11221 + len = UniStrnlen((wchar_t *)bcc_ptr,
11222 + remaining_words
11223 + - 1);
11224 + ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
11225 + cifs_strfromUCS_le(ses->serverNOS,
11226 + (wchar_t *)bcc_ptr,len,nls_codepage);
11227 + bcc_ptr += 2 * (len + 1);
11228 + ses->serverNOS[2 * len] = 0;
11229 + ses->serverNOS[1 + (2 * len)] = 0;
11230 + remaining_words -= len + 1;
11231 + if (remaining_words > 0) {
11232 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11233 + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11234 + ses->serverDomain =
11235 + cifs_kcalloc(2*(len+1),GFP_KERNEL);
11236 + cifs_strfromUCS_le(ses->serverDomain,
11237 + (wchar_t *)bcc_ptr,len,nls_codepage);
11238 + bcc_ptr += 2 * (len + 1);
11239 + ses->serverDomain[2*len] = 0;
11240 + ses->serverDomain[1+(2*len)] = 0;
11241 + } /* else no more room so create dummy domain string */
11242 + else
11243 + ses->serverDomain =
11244 + cifs_kcalloc(2,
11245 + GFP_KERNEL);
11246 + } else { /* no room so create dummy domain and NOS string */
11247 + ses->serverDomain =
11248 + cifs_kcalloc(2, GFP_KERNEL);
11249 + ses->serverNOS =
11250 + cifs_kcalloc(2, GFP_KERNEL);
11251 + }
11252 + } else { /* ASCII */
11253 + len = strnlen(bcc_ptr, 1024);
11254 + if (((long) bcc_ptr + len) - (long)
11255 + pByteArea(smb_buffer_response)
11256 + <= BCC(smb_buffer_response)) {
11257 + ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11258 + strncpy(ses->serverOS,bcc_ptr, len);
11259 +
11260 + bcc_ptr += len;
11261 + bcc_ptr[0] = 0; /* null terminate the string */
11262 + bcc_ptr++;
11263 +
11264 + len = strnlen(bcc_ptr, 1024);
11265 + ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11266 + strncpy(ses->serverNOS, bcc_ptr, len);
11267 + bcc_ptr += len;
11268 + bcc_ptr[0] = 0;
11269 + bcc_ptr++;
11270 +
11271 + len = strnlen(bcc_ptr, 1024);
11272 + ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
11273 + strncpy(ses->serverDomain, bcc_ptr, len);
11274 + bcc_ptr += len;
11275 + bcc_ptr[0] = 0;
11276 + bcc_ptr++;
11277 + } else
11278 + cFYI(1,
11279 + ("Variable field of length %d extends beyond end of smb ",
11280 + len));
11281 + }
11282 + } else {
11283 + cERROR(1,
11284 + (" Security Blob Length extends beyond end of SMB"));
11285 + }
11286 + } else {
11287 + cERROR(1, ("No session structure passed in."));
11288 + }
11289 + } else {
11290 + cERROR(1,
11291 + (" Invalid Word count %d: ",
11292 + smb_buffer_response->WordCount));
11293 + rc = -EIO;
11294 + }
11295 +
11296 + if (smb_buffer)
11297 + cifs_buf_release(smb_buffer);
11298 +
11299 + return rc;
11300 +}
11301 +
11302 +static int
11303 +CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11304 + char *SecurityBlob,int SecurityBlobLength,
11305 + const struct nls_table *nls_codepage)
11306 +{
11307 + struct smb_hdr *smb_buffer;
11308 + struct smb_hdr *smb_buffer_response;
11309 + SESSION_SETUP_ANDX *pSMB;
11310 + SESSION_SETUP_ANDX *pSMBr;
11311 + char *bcc_ptr;
11312 + char *user = ses->userName;
11313 + char *domain = ses->domainName;
11314 + int rc = 0;
11315 + int remaining_words = 0;
11316 + int bytes_returned = 0;
11317 + int len;
11318 +
11319 + cFYI(1, ("In spnego sesssetup "));
11320 +
11321 + smb_buffer = cifs_buf_get();
11322 + if (smb_buffer == 0) {
11323 + return -ENOMEM;
11324 + }
11325 + smb_buffer_response = smb_buffer;
11326 + pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11327 +
11328 + /* send SMBsessionSetup here */
11329 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11330 + NULL /* no tCon exists yet */ , 12 /* wct */ );
11331 + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11332 + pSMB->req.AndXCommand = 0xFF;
11333 + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11334 + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11335 +
11336 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11337 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11338 +
11339 + pSMB->req.Capabilities =
11340 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11341 + CAP_EXTENDED_SECURITY;
11342 + if (ses->capabilities & CAP_UNICODE) {
11343 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11344 + pSMB->req.Capabilities |= CAP_UNICODE;
11345 + }
11346 + if (ses->capabilities & CAP_STATUS32) {
11347 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11348 + pSMB->req.Capabilities |= CAP_STATUS32;
11349 + }
11350 + if (ses->capabilities & CAP_DFS) {
11351 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11352 + pSMB->req.Capabilities |= CAP_DFS;
11353 + }
11354 + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11355 +
11356 + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
11357 + bcc_ptr = pByteArea(smb_buffer);
11358 + memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
11359 + bcc_ptr += SecurityBlobLength;
11360 +
11361 + if (ses->capabilities & CAP_UNICODE) {
11362 + if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
11363 + *bcc_ptr = 0;
11364 + bcc_ptr++;
11365 + }
11366 + bytes_returned =
11367 + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
11368 + bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
11369 + bcc_ptr += 2; /* trailing null */
11370 + if (domain == NULL)
11371 + bytes_returned =
11372 + cifs_strtoUCS((wchar_t *) bcc_ptr,
11373 + "CIFS_LINUX_DOM", 32, nls_codepage);
11374 + else
11375 + bytes_returned =
11376 + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11377 + nls_codepage);
11378 + bcc_ptr += 2 * bytes_returned;
11379 + bcc_ptr += 2;
11380 + bytes_returned =
11381 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11382 + 32, nls_codepage);
11383 + bcc_ptr += 2 * bytes_returned;
11384 + bytes_returned =
11385 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11386 + nls_codepage);
11387 + bcc_ptr += 2 * bytes_returned;
11388 + bcc_ptr += 2;
11389 + bytes_returned =
11390 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11391 + 64, nls_codepage);
11392 + bcc_ptr += 2 * bytes_returned;
11393 + bcc_ptr += 2;
11394 + } else {
11395 + strncpy(bcc_ptr, user, 200);
11396 + bcc_ptr += strnlen(user, 200);
11397 + *bcc_ptr = 0;
11398 + bcc_ptr++;
11399 + if (domain == NULL) {
11400 + strcpy(bcc_ptr, "CIFS_LINUX_DOM");
11401 + bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
11402 + } else {
11403 + strncpy(bcc_ptr, domain, 64);
11404 + bcc_ptr += strnlen(domain, 64);
11405 + *bcc_ptr = 0;
11406 + bcc_ptr++;
11407 + }
11408 + strcpy(bcc_ptr, "Linux version ");
11409 + bcc_ptr += strlen("Linux version ");
11410 + strcpy(bcc_ptr, UTS_RELEASE);
11411 + bcc_ptr += strlen(UTS_RELEASE) + 1;
11412 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11413 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11414 + }
11415 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11416 + smb_buffer->smb_buf_length += BCC(smb_buffer);
11417 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11418 +
11419 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11420 + &bytes_returned, 1);
11421 + if (rc) {
11422 +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
11423 + } else if ((smb_buffer_response->WordCount == 3)
11424 + || (smb_buffer_response->WordCount == 4)) {
11425 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11426 + pSMBr->resp.SecurityBlobLength =
11427 + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
11428 + if (pSMBr->resp.Action & GUEST_LOGIN)
11429 + cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
11430 + if (ses) {
11431 + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
11432 + cFYI(1, ("UID = %d ", ses->Suid));
11433 + bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
11434 +
11435 + /* BB Fix below to make endian neutral !! */
11436 +
11437 + if ((pSMBr->resp.hdr.WordCount == 3)
11438 + || ((pSMBr->resp.hdr.WordCount == 4)
11439 + && (pSMBr->resp.SecurityBlobLength <
11440 + pSMBr->resp.ByteCount))) {
11441 + if (pSMBr->resp.hdr.WordCount == 4) {
11442 + bcc_ptr +=
11443 + pSMBr->resp.SecurityBlobLength;
11444 + cFYI(1,
11445 + ("Security Blob Length %d ",
11446 + pSMBr->resp.SecurityBlobLength));
11447 + }
11448 +
11449 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11450 + if ((long) (bcc_ptr) % 2) {
11451 + remaining_words =
11452 + (BCC(smb_buffer_response)
11453 + - 1) / 2;
11454 + bcc_ptr++; /* Unicode strings must be word aligned */
11455 + } else {
11456 + remaining_words =
11457 + BCC
11458 + (smb_buffer_response) / 2;
11459 + }
11460 + len =
11461 + UniStrnlen((wchar_t *) bcc_ptr,
11462 + remaining_words - 1);
11463 +/* We look for obvious messed up bcc or strings in response so we do not go off
11464 + the end since (at least) WIN2K and Windows XP have a major bug in not null
11465 + terminating last Unicode string in response */
11466 + ses->serverOS =
11467 + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11468 + cifs_strfromUCS_le(ses->serverOS,
11469 + (wchar_t *)
11470 + bcc_ptr, len,
11471 + nls_codepage);
11472 + bcc_ptr += 2 * (len + 1);
11473 + remaining_words -= len + 1;
11474 + ses->serverOS[2 * len] = 0;
11475 + ses->serverOS[1 + (2 * len)] = 0;
11476 + if (remaining_words > 0) {
11477 + len = UniStrnlen((wchar_t *)bcc_ptr,
11478 + remaining_words
11479 + - 1);
11480 + ses->serverNOS =
11481 + cifs_kcalloc(2 * (len + 1),
11482 + GFP_KERNEL);
11483 + cifs_strfromUCS_le(ses->serverNOS,
11484 + (wchar_t *)bcc_ptr,
11485 + len,
11486 + nls_codepage);
11487 + bcc_ptr += 2 * (len + 1);
11488 + ses->serverNOS[2 * len] = 0;
11489 + ses->serverNOS[1 + (2 * len)] = 0;
11490 + remaining_words -= len + 1;
11491 + if (remaining_words > 0) {
11492 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11493 + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11494 + ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
11495 + cifs_strfromUCS_le(ses->serverDomain,
11496 + (wchar_t *)bcc_ptr,
11497 + len,
11498 + nls_codepage);
11499 + bcc_ptr += 2*(len+1);
11500 + ses->serverDomain[2*len] = 0;
11501 + ses->serverDomain[1+(2*len)] = 0;
11502 + } /* else no more room so create dummy domain string */
11503 + else
11504 + ses->serverDomain =
11505 + cifs_kcalloc(2,GFP_KERNEL);
11506 + } else { /* no room so create dummy domain and NOS string */
11507 + ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
11508 + ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
11509 + }
11510 + } else { /* ASCII */
11511 +
11512 + len = strnlen(bcc_ptr, 1024);
11513 + if (((long) bcc_ptr + len) - (long)
11514 + pByteArea(smb_buffer_response)
11515 + <= BCC(smb_buffer_response)) {
11516 + ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
11517 + strncpy(ses->serverOS, bcc_ptr, len);
11518 +
11519 + bcc_ptr += len;
11520 + bcc_ptr[0] = 0; /* null terminate the string */
11521 + bcc_ptr++;
11522 +
11523 + len = strnlen(bcc_ptr, 1024);
11524 + ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11525 + strncpy(ses->serverNOS, bcc_ptr, len);
11526 + bcc_ptr += len;
11527 + bcc_ptr[0] = 0;
11528 + bcc_ptr++;
11529 +
11530 + len = strnlen(bcc_ptr, 1024);
11531 + ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
11532 + strncpy(ses->serverDomain, bcc_ptr, len);
11533 + bcc_ptr += len;
11534 + bcc_ptr[0] = 0;
11535 + bcc_ptr++;
11536 + } else
11537 + cFYI(1,
11538 + ("Variable field of length %d extends beyond end of smb ",
11539 + len));
11540 + }
11541 + } else {
11542 + cERROR(1,
11543 + (" Security Blob Length extends beyond end of SMB"));
11544 + }
11545 + } else {
11546 + cERROR(1, ("No session structure passed in."));
11547 + }
11548 + } else {
11549 + cERROR(1,
11550 + (" Invalid Word count %d: ",
11551 + smb_buffer_response->WordCount));
11552 + rc = -EIO;
11553 + }
11554 +
11555 + if (smb_buffer)
11556 + cifs_buf_release(smb_buffer);
11557 +
11558 + return rc;
11559 +}
11560 +
11561 +static int
11562 +CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
11563 + struct cifsSesInfo *ses, int * pNTLMv2_flag,
11564 + const struct nls_table *nls_codepage)
11565 +{
11566 + struct smb_hdr *smb_buffer;
11567 + struct smb_hdr *smb_buffer_response;
11568 + SESSION_SETUP_ANDX *pSMB;
11569 + SESSION_SETUP_ANDX *pSMBr;
11570 + char *bcc_ptr;
11571 + char *domain = ses->domainName;
11572 + int rc = 0;
11573 + int remaining_words = 0;
11574 + int bytes_returned = 0;
11575 + int len;
11576 + int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
11577 + PNEGOTIATE_MESSAGE SecurityBlob;
11578 + PCHALLENGE_MESSAGE SecurityBlob2;
11579 +
11580 + cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
11581 + *pNTLMv2_flag = FALSE;
11582 + smb_buffer = cifs_buf_get();
11583 + if (smb_buffer == 0) {
11584 + return -ENOMEM;
11585 + }
11586 + smb_buffer_response = smb_buffer;
11587 + pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11588 + pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
11589 +
11590 + /* send SMBsessionSetup here */
11591 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11592 + NULL /* no tCon exists yet */ , 12 /* wct */ );
11593 + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11594 + pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
11595 +
11596 + pSMB->req.AndXCommand = 0xFF;
11597 + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11598 + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11599 +
11600 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11601 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11602 +
11603 + pSMB->req.Capabilities =
11604 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11605 + CAP_EXTENDED_SECURITY;
11606 + if (ses->capabilities & CAP_UNICODE) {
11607 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11608 + pSMB->req.Capabilities |= CAP_UNICODE;
11609 + }
11610 + if (ses->capabilities & CAP_STATUS32) {
11611 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11612 + pSMB->req.Capabilities |= CAP_STATUS32;
11613 + }
11614 + if (ses->capabilities & CAP_DFS) {
11615 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11616 + pSMB->req.Capabilities |= CAP_DFS;
11617 + }
11618 + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11619 +
11620 + bcc_ptr = (char *) &pSMB->req.SecurityBlob;
11621 + SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
11622 + strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
11623 + SecurityBlob->MessageType = NtLmNegotiate;
11624 + SecurityBlob->NegotiateFlags =
11625 + NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
11626 + NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
11627 + /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
11628 + if(sign_CIFS_PDUs)
11629 + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
11630 + if(ntlmv2_support)
11631 + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
11632 + /* setup pointers to domain name and workstation name */
11633 + bcc_ptr += SecurityBlobLength;
11634 +
11635 + SecurityBlob->WorkstationName.Buffer = 0;
11636 + SecurityBlob->WorkstationName.Length = 0;
11637 + SecurityBlob->WorkstationName.MaximumLength = 0;
11638 +
11639 + if (domain == NULL) {
11640 + SecurityBlob->DomainName.Buffer = 0;
11641 + SecurityBlob->DomainName.Length = 0;
11642 + SecurityBlob->DomainName.MaximumLength = 0;
11643 + } else {
11644 + SecurityBlob->NegotiateFlags |=
11645 + NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
11646 + strncpy(bcc_ptr, domain, 63);
11647 + SecurityBlob->DomainName.Length = strnlen(domain, 64);
11648 + SecurityBlob->DomainName.MaximumLength =
11649 + cpu_to_le16(SecurityBlob->DomainName.Length);
11650 + SecurityBlob->DomainName.Buffer =
11651 + cpu_to_le32((long) &SecurityBlob->
11652 + DomainString -
11653 + (long) &SecurityBlob->Signature);
11654 + bcc_ptr += SecurityBlob->DomainName.Length;
11655 + SecurityBlobLength += SecurityBlob->DomainName.Length;
11656 + SecurityBlob->DomainName.Length =
11657 + cpu_to_le16(SecurityBlob->DomainName.Length);
11658 + }
11659 + if (ses->capabilities & CAP_UNICODE) {
11660 + if ((long) bcc_ptr % 2) {
11661 + *bcc_ptr = 0;
11662 + bcc_ptr++;
11663 + }
11664 +
11665 + bytes_returned =
11666 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11667 + 32, nls_codepage);
11668 + bcc_ptr += 2 * bytes_returned;
11669 + bytes_returned =
11670 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11671 + nls_codepage);
11672 + bcc_ptr += 2 * bytes_returned;
11673 + bcc_ptr += 2; /* null terminate Linux version */
11674 + bytes_returned =
11675 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11676 + 64, nls_codepage);
11677 + bcc_ptr += 2 * bytes_returned;
11678 + *(bcc_ptr + 1) = 0;
11679 + *(bcc_ptr + 2) = 0;
11680 + bcc_ptr += 2; /* null terminate network opsys string */
11681 + *(bcc_ptr + 1) = 0;
11682 + *(bcc_ptr + 2) = 0;
11683 + bcc_ptr += 2; /* null domain */
11684 + } else { /* ASCII */
11685 + strcpy(bcc_ptr, "Linux version ");
11686 + bcc_ptr += strlen("Linux version ");
11687 + strcpy(bcc_ptr, UTS_RELEASE);
11688 + bcc_ptr += strlen(UTS_RELEASE) + 1;
11689 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11690 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11691 + bcc_ptr++; /* empty domain field */
11692 + *bcc_ptr = 0;
11693 + }
11694 + SecurityBlob->NegotiateFlags =
11695 + cpu_to_le32(SecurityBlob->NegotiateFlags);
11696 + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
11697 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11698 + smb_buffer->smb_buf_length += BCC(smb_buffer);
11699 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11700 +
11701 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11702 + &bytes_returned, 1);
11703 +
11704 + if (smb_buffer_response->Status.CifsError ==
11705 + (NT_STATUS_MORE_PROCESSING_REQUIRED))
11706 + rc = 0;
11707 +
11708 + if (rc) {
11709 +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
11710 + } else if ((smb_buffer_response->WordCount == 3)
11711 + || (smb_buffer_response->WordCount == 4)) {
11712 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11713 + pSMBr->resp.SecurityBlobLength =
11714 + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
11715 + if (pSMBr->resp.Action & GUEST_LOGIN)
11716 + cFYI(1, (" Guest login"));
11717 + /* Do we want to set anything in SesInfo struct when guest login? */
11718 +
11719 + bcc_ptr = pByteArea(smb_buffer_response);
11720 + /* response can have either 3 or 4 word count - Samba sends 3 */
11721 +
11722 + SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
11723 + if (SecurityBlob2->MessageType != NtLmChallenge) {
11724 + cFYI(1,
11725 + ("Unexpected NTLMSSP message type received %d",
11726 + SecurityBlob2->MessageType));
11727 + } else if (ses) {
11728 + ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
11729 + cFYI(1, ("UID = %d ", ses->Suid));
11730 + if ((pSMBr->resp.hdr.WordCount == 3)
11731 + || ((pSMBr->resp.hdr.WordCount == 4)
11732 + && (pSMBr->resp.SecurityBlobLength <
11733 + pSMBr->resp.ByteCount))) {
11734 + if (pSMBr->resp.hdr.WordCount == 4) {
11735 + bcc_ptr +=
11736 + pSMBr->resp.SecurityBlobLength;
11737 + cFYI(1,
11738 + ("Security Blob Length %d ",
11739 + pSMBr->resp.SecurityBlobLength));
11740 + }
11741 +
11742 + cFYI(1, ("NTLMSSP Challenge rcvd "));
11743 +
11744 + memcpy(ses->server->cryptKey,
11745 + SecurityBlob2->Challenge,
11746 + CIFS_CRYPTO_KEY_SIZE);
11747 + if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
11748 + *pNTLMv2_flag = TRUE;
11749 +
11750 + if((SecurityBlob2->NegotiateFlags &
11751 + NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
11752 + || (sign_CIFS_PDUs > 1))
11753 + ses->server->secMode |=
11754 + SECMODE_SIGN_REQUIRED;
11755 + if ((SecurityBlob2->NegotiateFlags &
11756 + NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
11757 + ses->server->secMode |=
11758 + SECMODE_SIGN_ENABLED;
11759 +
11760 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11761 + if ((long) (bcc_ptr) % 2) {
11762 + remaining_words =
11763 + (BCC(smb_buffer_response)
11764 + - 1) / 2;
11765 + bcc_ptr++; /* Unicode strings must be word aligned */
11766 + } else {
11767 + remaining_words =
11768 + BCC
11769 + (smb_buffer_response) / 2;
11770 + }
11771 + len =
11772 + UniStrnlen((wchar_t *) bcc_ptr,
11773 + remaining_words - 1);
11774 +/* We look for obvious messed up bcc or strings in response so we do not go off
11775 + the end since (at least) WIN2K and Windows XP have a major bug in not null
11776 + terminating last Unicode string in response */
11777 + ses->serverOS =
11778 + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11779 + cifs_strfromUCS_le(ses->serverOS,
11780 + (wchar_t *)
11781 + bcc_ptr, len,
11782 + nls_codepage);
11783 + bcc_ptr += 2 * (len + 1);
11784 + remaining_words -= len + 1;
11785 + ses->serverOS[2 * len] = 0;
11786 + ses->serverOS[1 + (2 * len)] = 0;
11787 + if (remaining_words > 0) {
11788 + len = UniStrnlen((wchar_t *)
11789 + bcc_ptr,
11790 + remaining_words
11791 + - 1);
11792 + ses->serverNOS =
11793 + cifs_kcalloc(2 * (len + 1),
11794 + GFP_KERNEL);
11795 + cifs_strfromUCS_le(ses->
11796 + serverNOS,
11797 + (wchar_t *)
11798 + bcc_ptr,
11799 + len,
11800 + nls_codepage);
11801 + bcc_ptr += 2 * (len + 1);
11802 + ses->serverNOS[2 * len] = 0;
11803 + ses->serverNOS[1 +
11804 + (2 * len)] = 0;
11805 + remaining_words -= len + 1;
11806 + if (remaining_words > 0) {
11807 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11808 + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11809 + ses->serverDomain =
11810 + cifs_kcalloc(2 *
11811 + (len +
11812 + 1),
11813 + GFP_KERNEL);
11814 + cifs_strfromUCS_le
11815 + (ses->
11816 + serverDomain,
11817 + (wchar_t *)
11818 + bcc_ptr, len,
11819 + nls_codepage);
11820 + bcc_ptr +=
11821 + 2 * (len + 1);
11822 + ses->
11823 + serverDomain[2
11824 + * len]
11825 + = 0;
11826 + ses->
11827 + serverDomain[1
11828 + +
11829 + (2
11830 + *
11831 + len)]
11832 + = 0;
11833 + } /* else no more room so create dummy domain string */
11834 + else
11835 + ses->serverDomain =
11836 + cifs_kcalloc(2,
11837 + GFP_KERNEL);
11838 + } else { /* no room so create dummy domain and NOS string */
11839 + ses->serverDomain =
11840 + cifs_kcalloc(2, GFP_KERNEL);
11841 + ses->serverNOS =
11842 + cifs_kcalloc(2, GFP_KERNEL);
11843 + }
11844 + } else { /* ASCII */
11845 + len = strnlen(bcc_ptr, 1024);
11846 + if (((long) bcc_ptr + len) - (long)
11847 + pByteArea(smb_buffer_response)
11848 + <= BCC(smb_buffer_response)) {
11849 + ses->serverOS =
11850 + cifs_kcalloc(len + 1,
11851 + GFP_KERNEL);
11852 + strncpy(ses->serverOS,
11853 + bcc_ptr, len);
11854 +
11855 + bcc_ptr += len;
11856 + bcc_ptr[0] = 0; /* null terminate string */
11857 + bcc_ptr++;
11858 +
11859 + len = strnlen(bcc_ptr, 1024);
11860 + ses->serverNOS =
11861 + cifs_kcalloc(len + 1,
11862 + GFP_KERNEL);
11863 + strncpy(ses->serverNOS, bcc_ptr, len);
11864 + bcc_ptr += len;
11865 + bcc_ptr[0] = 0;
11866 + bcc_ptr++;
11867 +
11868 + len = strnlen(bcc_ptr, 1024);
11869 + ses->serverDomain =
11870 + cifs_kcalloc(len + 1,
11871 + GFP_KERNEL);
11872 + strncpy(ses->serverDomain, bcc_ptr, len);
11873 + bcc_ptr += len;
11874 + bcc_ptr[0] = 0;
11875 + bcc_ptr++;
11876 + } else
11877 + cFYI(1,
11878 + ("Variable field of length %d extends beyond end of smb ",
11879 + len));
11880 + }
11881 + } else {
11882 + cERROR(1,
11883 + (" Security Blob Length extends beyond end of SMB"));
11884 + }
11885 + } else {
11886 + cERROR(1, ("No session structure passed in."));
11887 + }
11888 + } else {
11889 + cERROR(1,
11890 + (" Invalid Word count %d: ",
11891 + smb_buffer_response->WordCount));
11892 + rc = -EIO;
11893 + }
11894 +
11895 + if (smb_buffer)
11896 + cifs_buf_release(smb_buffer);
11897 +
11898 + return rc;
11899 +}
11900 +
11901 +static int
11902 +CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11903 + char *ntlm_session_key, int ntlmv2_flag,
11904 + const struct nls_table *nls_codepage)
11905 +{
11906 + struct smb_hdr *smb_buffer;
11907 + struct smb_hdr *smb_buffer_response;
11908 + SESSION_SETUP_ANDX *pSMB;
11909 + SESSION_SETUP_ANDX *pSMBr;
11910 + char *bcc_ptr;
11911 + char *user = ses->userName;
11912 + char *domain = ses->domainName;
11913 + int rc = 0;
11914 + int remaining_words = 0;
11915 + int bytes_returned = 0;
11916 + int len;
11917 + int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
11918 + PAUTHENTICATE_MESSAGE SecurityBlob;
11919 +
11920 + cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
11921 +
11922 + smb_buffer = cifs_buf_get();
11923 + if (smb_buffer == 0) {
11924 + return -ENOMEM;
11925 + }
11926 + smb_buffer_response = smb_buffer;
11927 + pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11928 + pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
11929 +
11930 + /* send SMBsessionSetup here */
11931 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11932 + NULL /* no tCon exists yet */ , 12 /* wct */ );
11933 + pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
11934 + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11935 + pSMB->req.AndXCommand = 0xFF;
11936 + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11937 + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11938 +
11939 + pSMB->req.hdr.Uid = ses->Suid;
11940 +
11941 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11942 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11943 +
11944 + pSMB->req.Capabilities =
11945 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11946 + CAP_EXTENDED_SECURITY;
11947 + if (ses->capabilities & CAP_UNICODE) {
11948 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11949 + pSMB->req.Capabilities |= CAP_UNICODE;
11950 + }
11951 + if (ses->capabilities & CAP_STATUS32) {
11952 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11953 + pSMB->req.Capabilities |= CAP_STATUS32;
11954 + }
11955 + if (ses->capabilities & CAP_DFS) {
11956 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11957 + pSMB->req.Capabilities |= CAP_DFS;
11958 + }
11959 + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11960 +
11961 + bcc_ptr = (char *) &pSMB->req.SecurityBlob;
11962 + SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
11963 + strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
11964 + SecurityBlob->MessageType = NtLmAuthenticate;
11965 + bcc_ptr += SecurityBlobLength;
11966 + SecurityBlob->NegotiateFlags =
11967 + NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
11968 + NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
11969 + 0x80000000 | NTLMSSP_NEGOTIATE_128;
11970 + if(sign_CIFS_PDUs)
11971 + SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
11972 + if(ntlmv2_flag)
11973 + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
11974 +
11975 +/* setup pointers to domain name and workstation name */
11976 +
11977 + SecurityBlob->WorkstationName.Buffer = 0;
11978 + SecurityBlob->WorkstationName.Length = 0;
11979 + SecurityBlob->WorkstationName.MaximumLength = 0;
11980 + SecurityBlob->SessionKey.Length = 0;
11981 + SecurityBlob->SessionKey.MaximumLength = 0;
11982 + SecurityBlob->SessionKey.Buffer = 0;
11983 +
11984 + SecurityBlob->LmChallengeResponse.Length = 0;
11985 + SecurityBlob->LmChallengeResponse.MaximumLength = 0;
11986 + SecurityBlob->LmChallengeResponse.Buffer = 0;
11987 +
11988 + SecurityBlob->NtChallengeResponse.Length =
11989 + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11990 + SecurityBlob->NtChallengeResponse.MaximumLength =
11991 + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11992 + memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
11993 + SecurityBlob->NtChallengeResponse.Buffer =
11994 + cpu_to_le32(SecurityBlobLength);
11995 + SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
11996 + bcc_ptr += CIFS_SESSION_KEY_SIZE;
11997 +
11998 + if (ses->capabilities & CAP_UNICODE) {
11999 + if (domain == NULL) {
12000 + SecurityBlob->DomainName.Buffer = 0;
12001 + SecurityBlob->DomainName.Length = 0;
12002 + SecurityBlob->DomainName.MaximumLength = 0;
12003 + } else {
12004 + SecurityBlob->DomainName.Length =
12005 + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
12006 + nls_codepage);
12007 + SecurityBlob->DomainName.Length *= 2;
12008 + SecurityBlob->DomainName.MaximumLength =
12009 + cpu_to_le16(SecurityBlob->DomainName.Length);
12010 + SecurityBlob->DomainName.Buffer =
12011 + cpu_to_le32(SecurityBlobLength);
12012 + bcc_ptr += SecurityBlob->DomainName.Length;
12013 + SecurityBlobLength += SecurityBlob->DomainName.Length;
12014 + SecurityBlob->DomainName.Length =
12015 + cpu_to_le16(SecurityBlob->DomainName.Length);
12016 + }
12017 + if (user == NULL) {
12018 + SecurityBlob->UserName.Buffer = 0;
12019 + SecurityBlob->UserName.Length = 0;
12020 + SecurityBlob->UserName.MaximumLength = 0;
12021 + } else {
12022 + SecurityBlob->UserName.Length =
12023 + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
12024 + nls_codepage);
12025 + SecurityBlob->UserName.Length *= 2;
12026 + SecurityBlob->UserName.MaximumLength =
12027 + cpu_to_le16(SecurityBlob->UserName.Length);
12028 + SecurityBlob->UserName.Buffer =
12029 + cpu_to_le32(SecurityBlobLength);
12030 + bcc_ptr += SecurityBlob->UserName.Length;
12031 + SecurityBlobLength += SecurityBlob->UserName.Length;
12032 + SecurityBlob->UserName.Length =
12033 + cpu_to_le16(SecurityBlob->UserName.Length);
12034 + }
12035 +
12036 + /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
12037 + SecurityBlob->WorkstationName.Length *= 2;
12038 + SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
12039 + SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
12040 + bcc_ptr += SecurityBlob->WorkstationName.Length;
12041 + SecurityBlobLength += SecurityBlob->WorkstationName.Length;
12042 + SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
12043 +
12044 + if ((long) bcc_ptr % 2) {
12045 + *bcc_ptr = 0;
12046 + bcc_ptr++;
12047 + }
12048 + bytes_returned =
12049 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
12050 + 32, nls_codepage);
12051 + bcc_ptr += 2 * bytes_returned;
12052 + bytes_returned =
12053 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
12054 + nls_codepage);
12055 + bcc_ptr += 2 * bytes_returned;
12056 + bcc_ptr += 2; /* null term version string */
12057 + bytes_returned =
12058 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
12059 + 64, nls_codepage);
12060 + bcc_ptr += 2 * bytes_returned;
12061 + *(bcc_ptr + 1) = 0;
12062 + *(bcc_ptr + 2) = 0;
12063 + bcc_ptr += 2; /* null terminate network opsys string */
12064 + *(bcc_ptr + 1) = 0;
12065 + *(bcc_ptr + 2) = 0;
12066 + bcc_ptr += 2; /* null domain */
12067 + } else { /* ASCII */
12068 + if (domain == NULL) {
12069 + SecurityBlob->DomainName.Buffer = 0;
12070 + SecurityBlob->DomainName.Length = 0;
12071 + SecurityBlob->DomainName.MaximumLength = 0;
12072 + } else {
12073 + SecurityBlob->NegotiateFlags |=
12074 + NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
12075 + strncpy(bcc_ptr, domain, 63);
12076 + SecurityBlob->DomainName.Length = strnlen(domain, 64);
12077 + SecurityBlob->DomainName.MaximumLength =
12078 + cpu_to_le16(SecurityBlob->DomainName.Length);
12079 + SecurityBlob->DomainName.Buffer =
12080 + cpu_to_le32(SecurityBlobLength);
12081 + bcc_ptr += SecurityBlob->DomainName.Length;
12082 + SecurityBlobLength += SecurityBlob->DomainName.Length;
12083 + SecurityBlob->DomainName.Length =
12084 + cpu_to_le16(SecurityBlob->DomainName.Length);
12085 + }
12086 + if (user == NULL) {
12087 + SecurityBlob->UserName.Buffer = 0;
12088 + SecurityBlob->UserName.Length = 0;
12089 + SecurityBlob->UserName.MaximumLength = 0;
12090 + } else {
12091 + strncpy(bcc_ptr, user, 63);
12092 + SecurityBlob->UserName.Length = strnlen(user, 64);
12093 + SecurityBlob->UserName.MaximumLength =
12094 + cpu_to_le16(SecurityBlob->UserName.Length);
12095 + SecurityBlob->UserName.Buffer =
12096 + cpu_to_le32(SecurityBlobLength);
12097 + bcc_ptr += SecurityBlob->UserName.Length;
12098 + SecurityBlobLength += SecurityBlob->UserName.Length;
12099 + SecurityBlob->UserName.Length =
12100 + cpu_to_le16(SecurityBlob->UserName.Length);
12101 + }
12102 + /* BB fill in our workstation name if known BB */
12103 +
12104 + strcpy(bcc_ptr, "Linux version ");
12105 + bcc_ptr += strlen("Linux version ");
12106 + strcpy(bcc_ptr, UTS_RELEASE);
12107 + bcc_ptr += strlen(UTS_RELEASE) + 1;
12108 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
12109 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
12110 + bcc_ptr++; /* null domain */
12111 + *bcc_ptr = 0;
12112 + }
12113 + SecurityBlob->NegotiateFlags =
12114 + cpu_to_le32(SecurityBlob->NegotiateFlags);
12115 + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
12116 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
12117 + smb_buffer->smb_buf_length += BCC(smb_buffer);
12118 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
12119 +
12120 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
12121 + &bytes_returned, 1);
12122 + if (rc) {
12123 +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
12124 + } else if ((smb_buffer_response->WordCount == 3)
12125 + || (smb_buffer_response->WordCount == 4)) {
12126 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
12127 + pSMBr->resp.SecurityBlobLength =
12128 + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
12129 + if (pSMBr->resp.Action & GUEST_LOGIN)
12130 + cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
12131 +/* if(SecurityBlob2->MessageType != NtLm??){
12132 + cFYI("Unexpected message type on auth response is %d "));
12133 + } */
12134 + if (ses) {
12135 + cFYI(1,
12136 + ("Does UID on challenge %d match auth response UID %d ",
12137 + ses->Suid, smb_buffer_response->Uid));
12138 + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
12139 + bcc_ptr = pByteArea(smb_buffer_response);
12140 + /* response can have either 3 or 4 word count - Samba sends 3 */
12141 + if ((pSMBr->resp.hdr.WordCount == 3)
12142 + || ((pSMBr->resp.hdr.WordCount == 4)
12143 + && (pSMBr->resp.SecurityBlobLength <
12144 + pSMBr->resp.ByteCount))) {
12145 + if (pSMBr->resp.hdr.WordCount == 4) {
12146 + bcc_ptr +=
12147 + pSMBr->resp.SecurityBlobLength;
12148 + cFYI(1,
12149 + ("Security Blob Length %d ",
12150 + pSMBr->resp.SecurityBlobLength));
12151 + }
12152 +
12153 + cFYI(1,
12154 + ("NTLMSSP response to Authenticate "));
12155 +
12156 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
12157 + if ((long) (bcc_ptr) % 2) {
12158 + remaining_words =
12159 + (BCC(smb_buffer_response)
12160 + - 1) / 2;
12161 + bcc_ptr++; /* Unicode strings must be word aligned */
12162 + } else {
12163 + remaining_words = BCC(smb_buffer_response) / 2;
12164 + }
12165 + len =
12166 + UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
12167 +/* We look for obvious messed up bcc or strings in response so we do not go off
12168 + the end since (at least) WIN2K and Windows XP have a major bug in not null
12169 + terminating last Unicode string in response */
12170 + ses->serverOS =
12171 + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
12172 + cifs_strfromUCS_le(ses->serverOS,
12173 + (wchar_t *)
12174 + bcc_ptr, len,
12175 + nls_codepage);
12176 + bcc_ptr += 2 * (len + 1);
12177 + remaining_words -= len + 1;
12178 + ses->serverOS[2 * len] = 0;
12179 + ses->serverOS[1 + (2 * len)] = 0;
12180 + if (remaining_words > 0) {
12181 + len = UniStrnlen((wchar_t *)
12182 + bcc_ptr,
12183 + remaining_words
12184 + - 1);
12185 + ses->serverNOS =
12186 + cifs_kcalloc(2 * (len + 1),
12187 + GFP_KERNEL);
12188 + cifs_strfromUCS_le(ses->
12189 + serverNOS,
12190 + (wchar_t *)
12191 + bcc_ptr,
12192 + len,
12193 + nls_codepage);
12194 + bcc_ptr += 2 * (len + 1);
12195 + ses->serverNOS[2 * len] = 0;
12196 + ses->serverNOS[1+(2*len)] = 0;
12197 + remaining_words -= len + 1;
12198 + if (remaining_words > 0) {
12199 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
12200 + /* last string not always null terminated (e.g. for Windows XP & 2000) */
12201 + ses->serverDomain =
12202 + cifs_kcalloc(2 *
12203 + (len +
12204 + 1),
12205 + GFP_KERNEL);
12206 + cifs_strfromUCS_le
12207 + (ses->
12208 + serverDomain,
12209 + (wchar_t *)
12210 + bcc_ptr, len,
12211 + nls_codepage);
12212 + bcc_ptr +=
12213 + 2 * (len + 1);
12214 + ses->
12215 + serverDomain[2
12216 + * len]
12217 + = 0;
12218 + ses->
12219 + serverDomain[1
12220 + +
12221 + (2
12222 + *
12223 + len)]
12224 + = 0;
12225 + } /* else no more room so create dummy domain string */
12226 + else
12227 + ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
12228 + } else { /* no room so create dummy domain and NOS string */
12229 + ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
12230 + ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
12231 + }
12232 + } else { /* ASCII */
12233 + len = strnlen(bcc_ptr, 1024);
12234 + if (((long) bcc_ptr + len) -
12235 + (long) pByteArea(smb_buffer_response)
12236 + <= BCC(smb_buffer_response)) {
12237 + ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
12238 + strncpy(ses->serverOS,bcc_ptr, len);
12239 +
12240 + bcc_ptr += len;
12241 + bcc_ptr[0] = 0; /* null terminate the string */
12242 + bcc_ptr++;
12243 +
12244 + len = strnlen(bcc_ptr, 1024);
12245 + ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
12246 + strncpy(ses->serverNOS, bcc_ptr, len);
12247 + bcc_ptr += len;
12248 + bcc_ptr[0] = 0;
12249 + bcc_ptr++;
12250 +
12251 + len = strnlen(bcc_ptr, 1024);
12252 + ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
12253 + strncpy(ses->serverDomain, bcc_ptr, len);
12254 + bcc_ptr += len;
12255 + bcc_ptr[0] = 0;
12256 + bcc_ptr++;
12257 + } else
12258 + cFYI(1,
12259 + ("Variable field of length %d extends beyond end of smb ",
12260 + len));
12261 + }
12262 + } else {
12263 + cERROR(1,
12264 + (" Security Blob Length extends beyond end of SMB"));
12265 + }
12266 + } else {
12267 + cERROR(1, ("No session structure passed in."));
12268 + }
12269 + } else {
12270 + cERROR(1,
12271 + (" Invalid Word count %d: ",
12272 + smb_buffer_response->WordCount));
12273 + rc = -EIO;
12274 + }
12275 +
12276 + if (smb_buffer)
12277 + cifs_buf_release(smb_buffer);
12278 +
12279 + return rc;
12280 +}
12281 +
12282 +int
12283 +CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
12284 + const char *tree, struct cifsTconInfo *tcon,
12285 + const struct nls_table *nls_codepage)
12286 +{
12287 + struct smb_hdr *smb_buffer;
12288 + struct smb_hdr *smb_buffer_response;
12289 + TCONX_REQ *pSMB;
12290 + TCONX_RSP *pSMBr;
12291 + char *bcc_ptr;
12292 + int rc = 0;
12293 + int length;
12294 +
12295 + if (ses == NULL)
12296 + return -EIO;
12297 +
12298 + smb_buffer = cifs_buf_get();
12299 + if (smb_buffer == 0) {
12300 + return -ENOMEM;
12301 + }
12302 + smb_buffer_response = smb_buffer;
12303 +
12304 + header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
12305 + NULL /*no tid */ , 4 /*wct */ );
12306 + smb_buffer->Uid = ses->Suid;
12307 + pSMB = (TCONX_REQ *) smb_buffer;
12308 + pSMBr = (TCONX_RSP *) smb_buffer_response;
12309 +
12310 + pSMB->AndXCommand = 0xFF;
12311 + pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
12312 + pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
12313 + bcc_ptr = &(pSMB->Password[0]);
12314 + bcc_ptr++; /* skip password */
12315 +
12316 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
12317 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
12318 +
12319 + if (ses->capabilities & CAP_STATUS32) {
12320 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
12321 + }
12322 + if (ses->capabilities & CAP_DFS) {
12323 + smb_buffer->Flags2 |= SMBFLG2_DFS;
12324 + }
12325 + if (ses->capabilities & CAP_UNICODE) {
12326 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
12327 + length =
12328 + cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
12329 + bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
12330 + bcc_ptr += 2; /* skip trailing null */
12331 + } else { /* ASCII */
12332 +
12333 + strcpy(bcc_ptr, tree);
12334 + bcc_ptr += strlen(tree) + 1;
12335 + }
12336 + strcpy(bcc_ptr, "?????");
12337 + bcc_ptr += strlen("?????");
12338 + bcc_ptr += 1;
12339 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
12340 + smb_buffer->smb_buf_length += BCC(smb_buffer);
12341 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
12342 +
12343 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
12344 +
12345 + /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
12346 + /* above now done in SendReceive */
12347 + if ((rc == 0) && (tcon != NULL)) {
12348 + tcon->tidStatus = CifsGood;
12349 + tcon->tid = smb_buffer_response->Tid;
12350 + bcc_ptr = pByteArea(smb_buffer_response);
12351 + length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
12352 + /* skip service field (NB: this field is always ASCII) */
12353 + bcc_ptr += length + 1;
12354 + strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
12355 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
12356 + length = UniStrnlen((wchar_t *) bcc_ptr, 512);
12357 + if (((long) bcc_ptr + (2 * length)) -
12358 + (long) pByteArea(smb_buffer_response) <=
12359 + BCC(smb_buffer_response)) {
12360 + if(tcon->nativeFileSystem)
12361 + kfree(tcon->nativeFileSystem);
12362 + tcon->nativeFileSystem =
12363 + cifs_kcalloc(length + 2, GFP_KERNEL);
12364 + cifs_strfromUCS_le(tcon->nativeFileSystem,
12365 + (wchar_t *) bcc_ptr,
12366 + length, nls_codepage);
12367 + bcc_ptr += 2 * length;
12368 + bcc_ptr[0] = 0; /* null terminate the string */
12369 + bcc_ptr[1] = 0;
12370 + bcc_ptr += 2;
12371 + }
12372 + /* else do not bother copying these informational fields */
12373 + } else {
12374 + length = strnlen(bcc_ptr, 1024);
12375 + if (((long) bcc_ptr + length) -
12376 + (long) pByteArea(smb_buffer_response) <=
12377 + BCC(smb_buffer_response)) {
12378 + if(tcon->nativeFileSystem)
12379 + kfree(tcon->nativeFileSystem);
12380 + tcon->nativeFileSystem =
12381 + cifs_kcalloc(length + 1, GFP_KERNEL);
12382 + strncpy(tcon->nativeFileSystem, bcc_ptr,
12383 + length);
12384 + }
12385 + /* else do not bother copying these informational fields */
12386 + }
12387 + tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
12388 + cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
12389 + } else if ((rc == 0) && tcon == NULL) {
12390 + /* all we need to save for IPC$ connection */
12391 + ses->ipc_tid = smb_buffer_response->Tid;
12392 + }
12393 +
12394 + if (smb_buffer)
12395 + cifs_buf_release(smb_buffer);
12396 + return rc;
12397 +}
12398 +
12399 +int
12400 +cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
12401 +{
12402 + int rc = 0;
12403 + int xid;
12404 + struct cifsSesInfo *ses = NULL;
12405 + struct task_struct *cifsd_task;
12406 +
12407 + xid = GetXid();
12408 +
12409 + if (cifs_sb->tcon) {
12410 + ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
12411 + rc = CIFSSMBTDis(xid, cifs_sb->tcon);
12412 + if (rc == -EBUSY) {
12413 + FreeXid(xid);
12414 + return 0;
12415 + }
12416 + tconInfoFree(cifs_sb->tcon);
12417 + if ((ses) && (ses->server)) {
12418 + /* save off task so we do not refer to ses later */
12419 + cifsd_task = ses->server->tsk;
12420 + cFYI(1, ("About to do SMBLogoff "));
12421 + rc = CIFSSMBLogoff(xid, ses);
12422 + if (rc == -EBUSY) {
12423 + FreeXid(xid);
12424 + return 0;
12425 + } else if (rc == -ESHUTDOWN) {
12426 + cFYI(1,("Waking up socket by sending it signal"));
12427 + send_sig(SIGKILL,cifsd_task,1);
12428 + rc = 0;
12429 + } /* else - we have an smb session
12430 + left on this socket do not kill cifsd */
12431 + } else
12432 + cFYI(1, ("No session or bad tcon"));
12433 + }
12434 +
12435 + cifs_sb->tcon = NULL;
12436 + if (ses) {
12437 + set_current_state(TASK_INTERRUPTIBLE);
12438 + schedule_timeout(HZ / 2);
12439 + }
12440 + if (ses)
12441 + sesInfoFree(ses);
12442 +
12443 + FreeXid(xid);
12444 + return rc; /* BB check if we should always return zero here */
12445 +}
12446 +
12447 +int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
12448 + struct nls_table * nls_info)
12449 +{
12450 + int rc = 0;
12451 + char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
12452 + int ntlmv2_flag = FALSE;
12453 +
12454 + /* what if server changes its buffer size after dropping the session? */
12455 + if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
12456 + rc = CIFSSMBNegotiate(xid, pSesInfo);
12457 + if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
12458 + rc = CIFSSMBNegotiate(xid, pSesInfo);
12459 + if(rc == -EAGAIN)
12460 + rc = -EHOSTDOWN;
12461 + }
12462 + if(rc == 0) {
12463 + spin_lock(&GlobalMid_Lock);
12464 + if(pSesInfo->server->tcpStatus != CifsExiting)
12465 + pSesInfo->server->tcpStatus = CifsGood;
12466 + else
12467 + rc = -EHOSTDOWN;
12468 + spin_unlock(&GlobalMid_Lock);
12469 +
12470 + }
12471 + }
12472 + if (!rc) {
12473 + pSesInfo->capabilities = pSesInfo->server->capabilities;
12474 + if(linuxExtEnabled == 0)
12475 + pSesInfo->capabilities &= (~CAP_UNIX);
12476 + pSesInfo->sequence_number = 0;
12477 + cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
12478 + pSesInfo->server->secMode,
12479 + pSesInfo->server->capabilities,
12480 + pSesInfo->server->timeZone));
12481 + if (extended_security
12482 + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
12483 + && (pSesInfo->server->secType == NTLMSSP)) {
12484 + cFYI(1, ("New style sesssetup "));
12485 + rc = CIFSSpnegoSessSetup(xid, pSesInfo,
12486 + NULL /* security blob */,
12487 + 0 /* blob length */,
12488 + nls_info);
12489 + } else if (extended_security
12490 + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
12491 + && (pSesInfo->server->secType == RawNTLMSSP)) {
12492 + cFYI(1, ("NTLMSSP sesssetup "));
12493 + rc = CIFSNTLMSSPNegotiateSessSetup(xid,
12494 + pSesInfo,
12495 + &ntlmv2_flag,
12496 + nls_info);
12497 + if (!rc) {
12498 + if(ntlmv2_flag) {
12499 + char * v2_response;
12500 + cFYI(1,("Can use more secure NTLM version 2 password hash"));
12501 + CalcNTLMv2_partial_mac_key(pSesInfo,
12502 + nls_info);
12503 + v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
12504 + if(v2_response) {
12505 + CalcNTLMv2_response(pSesInfo,v2_response);
12506 +/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
12507 + kfree(v2_response);
12508 + /* BB Put dummy sig in SessSetup PDU? */
12509 + } else
12510 + rc = -ENOMEM;
12511 +
12512 + } else {
12513 + SMBNTencrypt(pSesInfo->password,
12514 + pSesInfo->server->cryptKey,
12515 + ntlm_session_key);
12516 +
12517 + cifs_calculate_mac_key(pSesInfo->mac_signing_key,
12518 + ntlm_session_key,
12519 + pSesInfo->password);
12520 + }
12521 + /* for better security the weaker lanman hash not sent
12522 + in AuthSessSetup so we no longer calculate it */
12523 +
12524 + rc = CIFSNTLMSSPAuthSessSetup(xid,
12525 + pSesInfo,
12526 + ntlm_session_key,
12527 + ntlmv2_flag,
12528 + nls_info);
12529 + }
12530 + } else { /* old style NTLM 0.12 session setup */
12531 + SMBNTencrypt(pSesInfo->password,
12532 + pSesInfo->server->cryptKey,
12533 + ntlm_session_key);
12534 +
12535 + cifs_calculate_mac_key(pSesInfo->mac_signing_key,
12536 + ntlm_session_key, pSesInfo->password);
12537 + rc = CIFSSessSetup(xid, pSesInfo,
12538 + ntlm_session_key, nls_info);
12539 + }
12540 + if (rc) {
12541 + cERROR(1,("Send error in SessSetup = %d",rc));
12542 + } else {
12543 + cFYI(1,("CIFS Session Established successfully"));
12544 + pSesInfo->status = CifsGood;
12545 + }
12546 + }
12547 + return rc;
12548 +}
12549 +
12550 Index: linux-2.4.35.4/fs/cifs/dir.c
12551 ===================================================================
12552 --- /dev/null
12553 +++ linux-2.4.35.4/fs/cifs/dir.c
12554 @@ -0,0 +1,425 @@
12555 +/*
12556 + * fs/cifs/dir.c
12557 + *
12558 + * vfs operations that deal with dentries
12559 + *
12560 + * Copyright (C) International Business Machines Corp., 2002,2003
12561 + * Author(s): Steve French (sfrench@us.ibm.com)
12562 + *
12563 + * This library is free software; you can redistribute it and/or modify
12564 + * it under the terms of the GNU Lesser General Public License as published
12565 + * by the Free Software Foundation; either version 2.1 of the License, or
12566 + * (at your option) any later version.
12567 + *
12568 + * This library is distributed in the hope that it will be useful,
12569 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12570 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12571 + * the GNU Lesser General Public License for more details.
12572 + *
12573 + * You should have received a copy of the GNU Lesser General Public License
12574 + * along with this library; if not, write to the Free Software
12575 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12576 + */
12577 +#include <linux/fs.h>
12578 +#include <linux/stat.h>
12579 +#include <linux/slab.h>
12580 +#include "cifsfs.h"
12581 +#include "cifspdu.h"
12582 +#include "cifsglob.h"
12583 +#include "cifsproto.h"
12584 +#include "cifs_debug.h"
12585 +#include "cifs_fs_sb.h"
12586 +
12587 +void
12588 +renew_parental_timestamps(struct dentry *direntry)
12589 +{
12590 + /* BB check if there is a way to get the kernel to do this or if we really need this */
12591 + do {
12592 + direntry->d_time = jiffies;
12593 + direntry = direntry->d_parent;
12594 + } while (!IS_ROOT(direntry));
12595 +}
12596 +
12597 +/* Note: caller must free return buffer */
12598 +char *
12599 +build_path_from_dentry(struct dentry *direntry)
12600 +{
12601 + struct dentry *temp;
12602 + int namelen = 0;
12603 + char *full_path;
12604 +
12605 + if(direntry == NULL)
12606 + return NULL; /* not much we can do if dentry is freed and
12607 + we need to reopen the file after it was closed implicitly
12608 + when the server crashed */
12609 +
12610 +cifs_bp_rename_retry:
12611 + for (temp = direntry; !IS_ROOT(temp);) {
12612 + namelen += (1 + temp->d_name.len);
12613 + temp = temp->d_parent;
12614 + if(temp == NULL) {
12615 + cERROR(1,("corrupt dentry"));
12616 + return NULL;
12617 + }
12618 + }
12619 +
12620 + full_path = kmalloc(namelen+1, GFP_KERNEL);
12621 + if(full_path == NULL)
12622 + return full_path;
12623 + full_path[namelen] = 0; /* trailing null */
12624 +
12625 + for (temp = direntry; !IS_ROOT(temp);) {
12626 + namelen -= 1 + temp->d_name.len;
12627 + if (namelen < 0) {
12628 + break;
12629 + } else {
12630 + full_path[namelen] = '\\';
12631 + strncpy(full_path + namelen + 1, temp->d_name.name,
12632 + temp->d_name.len);
12633 + cFYI(0, (" name: %s ", full_path + namelen));
12634 + }
12635 + temp = temp->d_parent;
12636 + if(temp == NULL) {
12637 + cERROR(1,("corrupt dentry"));
12638 + kfree(full_path);
12639 + return NULL;
12640 + }
12641 + }
12642 + if (namelen != 0) {
12643 + cERROR(1,
12644 + ("We did not end path lookup where we expected namelen is %d",
12645 + namelen));
12646 + /* presumably this is only possible if we were racing with a rename
12647 + of one of the parent directories (we can not lock the dentries
12648 + above us to prevent this, but retrying should be harmless) */
12649 + kfree(full_path);
12650 + namelen = 0;
12651 + goto cifs_bp_rename_retry;
12652 + }
12653 +
12654 + return full_path;
12655 +}
12656 +
12657 +/* Note: caller must free return buffer */
12658 +char *
12659 +build_wildcard_path_from_dentry(struct dentry *direntry)
12660 +{
12661 + struct dentry *temp;
12662 + int namelen = 0;
12663 + char *full_path;
12664 +
12665 + if(direntry == NULL)
12666 + return NULL; /* not much we can do if dentry is freed and
12667 + we need to reopen the file after it was closed implicitly
12668 + when the server crashed */
12669 +
12670 +cifs_bwp_rename_retry:
12671 + for (temp = direntry; !IS_ROOT(temp);) {
12672 + namelen += (1 + temp->d_name.len);
12673 + temp = temp->d_parent;
12674 + if(temp == NULL) {
12675 + cERROR(1,("corrupt dentry"));
12676 + return NULL;
12677 + }
12678 + }
12679 +
12680 + full_path = kmalloc(namelen+3, GFP_KERNEL);
12681 + if(full_path == NULL)
12682 + return full_path;
12683 +
12684 + full_path[namelen] = '\\';
12685 + full_path[namelen+1] = '*';
12686 + full_path[namelen+2] = 0; /* trailing null */
12687 +
12688 + for (temp = direntry; !IS_ROOT(temp);) {
12689 + namelen -= 1 + temp->d_name.len;
12690 + if (namelen < 0) {
12691 + break;
12692 + } else {
12693 + full_path[namelen] = '\\';
12694 + strncpy(full_path + namelen + 1, temp->d_name.name,
12695 + temp->d_name.len);
12696 + cFYI(0, (" name: %s ", full_path + namelen));
12697 + }
12698 + temp = temp->d_parent;
12699 + if(temp == NULL) {
12700 + cERROR(1,("corrupt dentry"));
12701 + kfree(full_path);
12702 + return NULL;
12703 + }
12704 + }
12705 + if (namelen != 0) {
12706 + cERROR(1,
12707 + ("We did not end path lookup where we expected namelen is %d",
12708 + namelen));
12709 + /* presumably this is only possible if we were racing with a rename
12710 + of one of the parent directories (we can not lock the dentries
12711 + above us to prevent this, but retrying should be harmless) */
12712 + kfree(full_path);
12713 + namelen = 0;
12714 + goto cifs_bwp_rename_retry;
12715 + }
12716 +
12717 + return full_path;
12718 +}
12719 +
12720 +/* Inode operations in similar order to how they appear in the Linux file fs.h */
12721 +
12722 +int
12723 +cifs_create(struct inode *inode, struct dentry *direntry, int mode)
12724 +{
12725 + int rc = -ENOENT;
12726 + int xid;
12727 + int oplock = 0; /* no sense requested oplock if we are just going to
12728 + immediately close the file */
12729 + __u16 fileHandle;
12730 + struct cifs_sb_info *cifs_sb;
12731 + struct cifsTconInfo *pTcon;
12732 + char *full_path = NULL;
12733 + FILE_ALL_INFO * buf = NULL;
12734 + struct inode *newinode = NULL;
12735 +
12736 + xid = GetXid();
12737 +
12738 + cifs_sb = CIFS_SB(inode->i_sb);
12739 + pTcon = cifs_sb->tcon;
12740 +
12741 + down(&direntry->d_sb->s_vfs_rename_sem);
12742 + full_path = build_path_from_dentry(direntry);
12743 + up(&direntry->d_sb->s_vfs_rename_sem);
12744 + if(full_path == NULL) {
12745 + FreeXid(xid);
12746 + return -ENOMEM;
12747 + }
12748 +
12749 + /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
12750 +
12751 + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
12752 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
12753 + GENERIC_WRITE, CREATE_NOT_DIR,
12754 + &fileHandle, &oplock, buf, cifs_sb->local_nls);
12755 + if (rc) {
12756 + cFYI(1, ("cifs_create returned 0x%x ", rc));
12757 + } else {
12758 + /* BB for case of overwriting existing file can we use the inode that was
12759 + passed in rather than creating new one?? */
12760 + if (pTcon->ses->capabilities & CAP_UNIX)
12761 + rc = cifs_get_inode_info_unix(&newinode, full_path,
12762 + inode->i_sb,xid);
12763 + else
12764 + rc = cifs_get_inode_info(&newinode, full_path,
12765 + buf, inode->i_sb,xid);
12766 +
12767 + if (rc != 0) {
12768 + cFYI(1,("Create worked but get_inode_info failed with rc = %d",
12769 + rc));
12770 + } else {
12771 + direntry->d_op = &cifs_dentry_ops;
12772 + d_instantiate(direntry, newinode);
12773 + }
12774 + CIFSSMBClose(xid, pTcon, fileHandle);
12775 +
12776 + if(newinode) {
12777 + newinode->i_mode = mode;
12778 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
12779 + CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
12780 + (__u64)-1,
12781 + (__u64)-1,
12782 + 0 /* dev */,
12783 + cifs_sb->local_nls);
12784 + else { /* BB implement via Windows security descriptors */
12785 + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
12786 + /* in the meantime could set r/o dos attribute when perms are eg:
12787 + mode & 0222 == 0 */
12788 + }
12789 + }
12790 + }
12791 +
12792 + if (buf)
12793 + kfree(buf);
12794 + if (full_path)
12795 + kfree(full_path);
12796 + FreeXid(xid);
12797 +
12798 + return rc;
12799 +}
12800 +
12801 +int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number)
12802 +{
12803 + int rc = -EPERM;
12804 + int xid;
12805 + struct cifs_sb_info *cifs_sb;
12806 + struct cifsTconInfo *pTcon;
12807 + char *full_path = NULL;
12808 + struct inode * newinode = NULL;
12809 +
12810 + xid = GetXid();
12811 +
12812 + cifs_sb = CIFS_SB(inode->i_sb);
12813 + pTcon = cifs_sb->tcon;
12814 +
12815 + down(&direntry->d_sb->s_vfs_rename_sem);
12816 + full_path = build_path_from_dentry(direntry);
12817 + up(&direntry->d_sb->s_vfs_rename_sem);
12818 + if(full_path == NULL)
12819 + rc = -ENOMEM;
12820 +
12821 + if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
12822 + rc = CIFSSMBUnixSetPerms(xid, pTcon,
12823 + full_path, mode, current->euid, current->egid,
12824 + device_number, cifs_sb->local_nls);
12825 + if(!rc) {
12826 + rc = cifs_get_inode_info_unix(&newinode, full_path,
12827 + inode->i_sb,xid);
12828 + direntry->d_op = &cifs_dentry_ops;
12829 + if(rc == 0)
12830 + d_instantiate(direntry, newinode);
12831 + }
12832 + }
12833 +
12834 + if (full_path)
12835 + kfree(full_path);
12836 + FreeXid(xid);
12837 +
12838 + return rc;
12839 +}
12840 +
12841 +
12842 +struct dentry *
12843 +cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
12844 +{
12845 + int xid;
12846 + int rc = 0; /* to get around spurious gcc warning, set to zero here */
12847 + struct cifs_sb_info *cifs_sb;
12848 + struct cifsTconInfo *pTcon;
12849 + struct inode *newInode = NULL;
12850 + char *full_path = NULL;
12851 +
12852 + xid = GetXid();
12853 +
12854 + cFYI(1,
12855 + (" parent inode = 0x%p name is: %s and dentry = 0x%p",
12856 + parent_dir_inode, direntry->d_name.name, direntry));
12857 +
12858 + /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
12859 +
12860 + /* check whether path exists */
12861 +
12862 + cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
12863 + pTcon = cifs_sb->tcon;
12864 +
12865 + /* can not grab the rename sem here since it would
12866 + deadlock in the cases (beginning of sys_rename itself)
12867 + in which we already have the sb rename sem */
12868 + full_path = build_path_from_dentry(direntry);
12869 + if(full_path == NULL) {
12870 + FreeXid(xid);
12871 + return ERR_PTR(-ENOMEM);
12872 + }
12873 +
12874 + if (direntry->d_inode != NULL) {
12875 + cFYI(1, (" non-NULL inode in lookup"));
12876 + } else {
12877 + cFYI(1, (" NULL inode in lookup"));
12878 + }
12879 + cFYI(1,
12880 + (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
12881 +
12882 + if (pTcon->ses->capabilities & CAP_UNIX)
12883 + rc = cifs_get_inode_info_unix(&newInode, full_path,
12884 + parent_dir_inode->i_sb,xid);
12885 + else
12886 + rc = cifs_get_inode_info(&newInode, full_path, NULL,
12887 + parent_dir_inode->i_sb,xid);
12888 +
12889 + if ((rc == 0) && (newInode != NULL)) {
12890 + direntry->d_op = &cifs_dentry_ops;
12891 + d_add(direntry, newInode);
12892 +
12893 + /* since paths are not looked up by component - the parent directories are presumed to be good here */
12894 + renew_parental_timestamps(direntry);
12895 +
12896 + } else if (rc == -ENOENT) {
12897 + rc = 0;
12898 + d_add(direntry, NULL);
12899 + } else {
12900 + cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
12901 + /* BB special case check for Access Denied - watch security
12902 + exposure of returning dir info implicitly via different rc
12903 + if file exists or not but no access BB */
12904 + }
12905 +
12906 + if (full_path)
12907 + kfree(full_path);
12908 + FreeXid(xid);
12909 + return ERR_PTR(rc);
12910 +}
12911 +
12912 +int
12913 +cifs_dir_open(struct inode *inode, struct file *file)
12914 +{ /* NB: currently unused since searches are opened in readdir */
12915 + int rc = 0;
12916 + int xid;
12917 + struct cifs_sb_info *cifs_sb;
12918 + struct cifsTconInfo *pTcon;
12919 + char *full_path = NULL;
12920 +
12921 + xid = GetXid();
12922 +
12923 + cifs_sb = CIFS_SB(inode->i_sb);
12924 + pTcon = cifs_sb->tcon;
12925 +
12926 + if(file->f_dentry) {
12927 + down(&file->f_dentry->d_sb->s_vfs_rename_sem);
12928 + full_path = build_wildcard_path_from_dentry(file->f_dentry);
12929 + up(&file->f_dentry->d_sb->s_vfs_rename_sem);
12930 + } else {
12931 + FreeXid(xid);
12932 + return -EIO;
12933 + }
12934 +
12935 + cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
12936 +
12937 + if (full_path)
12938 + kfree(full_path);
12939 + FreeXid(xid);
12940 + return rc;
12941 +}
12942 +
12943 +static int
12944 +cifs_d_revalidate(struct dentry *direntry, int flags)
12945 +{
12946 + int isValid = 1;
12947 +
12948 +/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
12949 +
12950 + if (direntry->d_inode) {
12951 + if (cifs_revalidate(direntry)) {
12952 + /* unlock_kernel(); */
12953 + return 0;
12954 + }
12955 + } else {
12956 + cFYI(1,
12957 + ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
12958 + direntry->d_name.name, direntry));
12959 + }
12960 +
12961 +/* unlock_kernel(); */
12962 +
12963 + return isValid;
12964 +}
12965 +
12966 +/* static int cifs_d_delete(struct dentry *direntry)
12967 +{
12968 + int rc = 0;
12969 +
12970 + cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
12971 +
12972 + return rc;
12973 +} */
12974 +
12975 +struct dentry_operations cifs_dentry_ops = {
12976 + .d_revalidate = cifs_d_revalidate,
12977 +/* d_delete: cifs_d_delete, *//* not needed except for debugging */
12978 + /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
12979 +};
12980 Index: linux-2.4.35.4/fs/cifs/file.c
12981 ===================================================================
12982 --- /dev/null
12983 +++ linux-2.4.35.4/fs/cifs/file.c
12984 @@ -0,0 +1,2185 @@
12985 +/*
12986 + * fs/cifs/file.c
12987 + *
12988 + * vfs operations that deal with files
12989 + *
12990 + * Copyright (C) International Business Machines Corp., 2002,2003
12991 + * Author(s): Steve French (sfrench@us.ibm.com)
12992 + *
12993 + * This library is free software; you can redistribute it and/or modify
12994 + * it under the terms of the GNU Lesser General Public License as published
12995 + * by the Free Software Foundation; either version 2.1 of the License, or
12996 + * (at your option) any later version.
12997 + *
12998 + * This library is distributed in the hope that it will be useful,
12999 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13000 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13001 + * the GNU Lesser General Public License for more details.
13002 + *
13003 + * You should have received a copy of the GNU Lesser General Public License
13004 + * along with this library; if not, write to the Free Software
13005 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13006 + */
13007 +#include <linux/fs.h>
13008 +#include <linux/stat.h>
13009 +#include <linux/fcntl.h>
13010 +#include <linux/version.h>
13011 +#include <linux/pagemap.h>
13012 +#include <linux/smp_lock.h>
13013 +#include <linux/list.h>
13014 +#include <asm/div64.h>
13015 +#include <linux/mm.h>
13016 +#include <linux/types.h>
13017 +#include "cifsfs.h"
13018 +#include "cifspdu.h"
13019 +#include "cifsglob.h"
13020 +#include "cifsproto.h"
13021 +#include "cifs_unicode.h"
13022 +#include "cifs_debug.h"
13023 +#include "cifs_fs_sb.h"
13024 +
13025 +int
13026 +cifs_open(struct inode *inode, struct file *file)
13027 +{
13028 + int rc = -EACCES;
13029 + int xid, oplock;
13030 + struct cifs_sb_info *cifs_sb;
13031 + struct cifsTconInfo *pTcon;
13032 + struct cifsFileInfo *pCifsFile;
13033 + struct cifsInodeInfo *pCifsInode;
13034 + char *full_path = NULL;
13035 + int desiredAccess = 0x20197;
13036 + int disposition;
13037 + __u16 netfid;
13038 + FILE_ALL_INFO * buf = NULL;
13039 + time_t temp;
13040 +
13041 + xid = GetXid();
13042 +
13043 + cifs_sb = CIFS_SB(inode->i_sb);
13044 + pTcon = cifs_sb->tcon;
13045 +
13046 + down(&inode->i_sb->s_vfs_rename_sem);
13047 + full_path = build_path_from_dentry(file->f_dentry);
13048 + up(&inode->i_sb->s_vfs_rename_sem);
13049 + if(full_path == NULL) {
13050 + FreeXid(xid);
13051 + return -ENOMEM;
13052 + }
13053 +
13054 + cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
13055 + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
13056 + desiredAccess = GENERIC_READ;
13057 + else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
13058 + desiredAccess = GENERIC_WRITE;
13059 + else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
13060 + /* GENERIC_ALL is too much permission to request */
13061 + /* can cause unnecessary access denied on create */
13062 + /* desiredAccess = GENERIC_ALL; */
13063 + desiredAccess = GENERIC_READ | GENERIC_WRITE;
13064 + }
13065 +
13066 +/*********************************************************************
13067 + * open flag mapping table:
13068 + *
13069 + * POSIX Flag CIFS Disposition
13070 + * ---------- ----------------
13071 + * O_CREAT FILE_OPEN_IF
13072 + * O_CREAT | O_EXCL FILE_CREATE
13073 + * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
13074 + * O_TRUNC FILE_OVERWRITE
13075 + * none of the above FILE_OPEN
13076 + *
13077 + * Note that there is not a direct match between disposition
13078 + * FILE_SUPERSEDE (ie create whether or not file exists although
13079 + * O_CREAT | O_TRUNC is similar but truncates the existing
13080 + * file rather than creating a new file as FILE_SUPERSEDE does
13081 + * (which uses the attributes / metadata passed in on open call)
13082 + *?
13083 + *? O_SYNC is a reasonable match to CIFS writethrough flag
13084 + *? and the read write flags match reasonably. O_LARGEFILE
13085 + *? is irrelevant because largefile support is always used
13086 + *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
13087 + * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
13088 + *********************************************************************/
13089 +
13090 + /* For 2.4 case, file was already checked for existence
13091 + before create by vfs lookup and created in create
13092 + entry point, we are now just opening the newly
13093 + created file with the right desiredAccess flags */
13094 +
13095 + if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
13096 + disposition = FILE_OPEN_IF;
13097 + else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
13098 + disposition = FILE_OVERWRITE_IF;
13099 + else if((file->f_flags & O_CREAT) == O_CREAT)
13100 + disposition = FILE_OPEN_IF;
13101 + else
13102 + disposition = FILE_OPEN;
13103 +
13104 + if (oplockEnabled)
13105 + oplock = REQ_OPLOCK;
13106 + else
13107 + oplock = FALSE;
13108 +
13109 + /* BB pass O_SYNC flag through on file attributes .. BB */
13110 +
13111 + /* Also refresh inode by passing in file_info buf returned by SMBOpen
13112 + and calling get_inode_info with returned buf (at least
13113 + helps non-Unix server case */
13114 +
13115 + /* BB we can not do this if this is the second open of a file
13116 + and the first handle has writebehind data, we might be
13117 + able to simply do a filemap_fdatawrite/filemap_fdatawait first */
13118 + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
13119 + if(buf==0) {
13120 + if (full_path)
13121 + kfree(full_path);
13122 + FreeXid(xid);
13123 + return -ENOMEM;
13124 + }
13125 + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
13126 + CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
13127 + if (rc) {
13128 + cFYI(1, ("cifs_open returned 0x%x ", rc));
13129 + cFYI(1, ("oplock: %d ", oplock));
13130 + } else {
13131 + file->private_data =
13132 + kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
13133 + if (file->private_data) {
13134 + memset(file->private_data, 0, sizeof(struct cifsFileInfo));
13135 + pCifsFile = (struct cifsFileInfo *) file->private_data;
13136 + pCifsFile->netfid = netfid;
13137 + pCifsFile->pid = current->pid;
13138 + init_MUTEX(&pCifsFile->fh_sem);
13139 + pCifsFile->pfile = file; /* needed for writepage */
13140 + pCifsFile->pInode = inode;
13141 + pCifsFile->invalidHandle = FALSE;
13142 + pCifsFile->closePend = FALSE;
13143 + write_lock(&GlobalSMBSeslock);
13144 + spin_lock(&files_lock);
13145 + list_add(&pCifsFile->tlist,&pTcon->openFileList);
13146 + pCifsInode = CIFS_I(file->f_dentry->d_inode);
13147 + if(pCifsInode) {
13148 + /* want handles we can use to read with first */
13149 + /* in the list so we do not have to walk the */
13150 + /* list to search for one in prepare_write */
13151 + if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
13152 + list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
13153 + } else {
13154 + list_add(&pCifsFile->flist,&pCifsInode->openFileList);
13155 + }
13156 + spin_unlock(&files_lock);
13157 + write_unlock(&GlobalSMBSeslock);
13158 + if(pCifsInode->clientCanCacheRead) {
13159 + /* we have the inode open somewhere else
13160 + no need to discard cache data */
13161 + } else {
13162 + if(buf) {
13163 + /* BB need same check in cifs_create too? */
13164 +
13165 + /* if not oplocked, invalidate inode pages if mtime
13166 + or file size changed */
13167 + temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
13168 + if((file->f_dentry->d_inode->i_mtime == temp) &&
13169 + (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
13170 + cFYI(1,("inode unchanged on server"));
13171 + } else {
13172 + if(file->f_dentry->d_inode->i_mapping) {
13173 + /* BB no need to lock inode until after invalidate*/
13174 + /* since namei code should already have it locked?*/
13175 + filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
13176 + }
13177 + cFYI(1,("invalidating remote inode since open detected it changed"));
13178 + invalidate_inode_pages(file->f_dentry->d_inode);
13179 + }
13180 + }
13181 + }
13182 + if (pTcon->ses->capabilities & CAP_UNIX)
13183 + rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
13184 + full_path, inode->i_sb,xid);
13185 + else
13186 + rc = cifs_get_inode_info(&file->f_dentry->d_inode,
13187 + full_path, buf, inode->i_sb,xid);
13188 +
13189 + if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
13190 + pCifsInode->clientCanCacheAll = TRUE;
13191 + pCifsInode->clientCanCacheRead = TRUE;
13192 + cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
13193 + } else if((oplock & 0xF) == OPLOCK_READ)
13194 + pCifsInode->clientCanCacheRead = TRUE;
13195 + } else {
13196 + spin_unlock(&files_lock);
13197 + write_unlock(&GlobalSMBSeslock);
13198 + }
13199 + if(oplock & CIFS_CREATE_ACTION) {
13200 + /* time to set mode which we can not set earlier due
13201 + to problems creating new read-only files */
13202 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
13203 + CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
13204 + (__u64)-1,
13205 + (__u64)-1,
13206 + 0 /* dev */,
13207 + cifs_sb->local_nls);
13208 + else {/* BB implement via Windows security descriptors */
13209 + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
13210 + /* in the meantime could set r/o dos attribute when perms are eg:
13211 + mode & 0222 == 0 */
13212 + }
13213 + }
13214 + }
13215 + }
13216 +
13217 + if (buf)
13218 + kfree(buf);
13219 + if (full_path)
13220 + kfree(full_path);
13221 + FreeXid(xid);
13222 + return rc;
13223 +}
13224 +
13225 +/* Try to reaquire byte range locks that were released when session */
13226 +/* to server was lost */
13227 +static int cifs_relock_file(struct cifsFileInfo * cifsFile)
13228 +{
13229 + int rc = 0;
13230 +
13231 +/* BB list all locks open on this file and relock */
13232 +
13233 + return rc;
13234 +}
13235 +
13236 +static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
13237 +{
13238 + int rc = -EACCES;
13239 + int xid, oplock;
13240 + struct cifs_sb_info *cifs_sb;
13241 + struct cifsTconInfo *pTcon;
13242 + struct cifsFileInfo *pCifsFile;
13243 + struct cifsInodeInfo *pCifsInode;
13244 + char *full_path = NULL;
13245 + int desiredAccess = 0x20197;
13246 + int disposition = FILE_OPEN;
13247 + __u16 netfid;
13248 +
13249 + if(inode == NULL)
13250 + return -EBADF;
13251 + if (file->private_data) {
13252 + pCifsFile = (struct cifsFileInfo *) file->private_data;
13253 + } else
13254 + return -EBADF;
13255 +
13256 + xid = GetXid();
13257 + down(&pCifsFile->fh_sem);
13258 + if(pCifsFile->invalidHandle == FALSE) {
13259 + up(&pCifsFile->fh_sem);
13260 + FreeXid(xid);
13261 + return 0;
13262 + }
13263 +
13264 + if(file->f_dentry == NULL) {
13265 + up(&pCifsFile->fh_sem);
13266 + cFYI(1,("failed file reopen, no valid name if dentry freed"));
13267 + FreeXid(xid);
13268 + return -EBADF;
13269 + }
13270 + cifs_sb = CIFS_SB(inode->i_sb);
13271 + pTcon = cifs_sb->tcon;
13272 +/* can not grab rename sem here because various ops, including
13273 +those that already have the rename sem can end up causing writepage
13274 +to get called and if the server was down that means we end up here,
13275 +and we can never tell if the caller already has the rename_sem */
13276 + full_path = build_path_from_dentry(file->f_dentry);
13277 + if(full_path == NULL) {
13278 + up(&pCifsFile->fh_sem);
13279 + FreeXid(xid);
13280 + return -ENOMEM;
13281 + }
13282 +
13283 + cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
13284 + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
13285 + desiredAccess = GENERIC_READ;
13286 + else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
13287 + desiredAccess = GENERIC_WRITE;
13288 + else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
13289 + /* GENERIC_ALL is too much permission to request */
13290 + /* can cause unnecessary access denied on create */
13291 + /* desiredAccess = GENERIC_ALL; */
13292 + desiredAccess = GENERIC_READ | GENERIC_WRITE;
13293 + }
13294 +
13295 + if (oplockEnabled)
13296 + oplock = REQ_OPLOCK;
13297 + else
13298 + oplock = FALSE;
13299 +
13300 +
13301 + /* Can not refresh inode by passing in file_info buf to be returned
13302 + by SMBOpen and then calling get_inode_info with returned buf
13303 + since file might have write behind data that needs to be flushed
13304 + and server version of file size can be stale. If we
13305 + knew for sure that inode was not dirty locally we could do this */
13306 +
13307 +/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
13308 + if(buf==0) {
13309 + up(&pCifsFile->fh_sem);
13310 + if (full_path)
13311 + kfree(full_path);
13312 + FreeXid(xid);
13313 + return -ENOMEM;
13314 + }*/
13315 + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
13316 + CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
13317 + if (rc) {
13318 + up(&pCifsFile->fh_sem);
13319 + cFYI(1, ("cifs_open returned 0x%x ", rc));
13320 + cFYI(1, ("oplock: %d ", oplock));
13321 + } else {
13322 + pCifsFile->netfid = netfid;
13323 + pCifsFile->invalidHandle = FALSE;
13324 + up(&pCifsFile->fh_sem);
13325 + pCifsInode = CIFS_I(inode);
13326 + if(pCifsInode) {
13327 + if(can_flush) {
13328 + filemap_fdatasync(inode->i_mapping);
13329 + filemap_fdatawait(inode->i_mapping);
13330 + /* temporarily disable caching while we
13331 + go to server to get inode info */
13332 + pCifsInode->clientCanCacheAll = FALSE;
13333 + pCifsInode->clientCanCacheRead = FALSE;
13334 + if (pTcon->ses->capabilities & CAP_UNIX)
13335 + rc = cifs_get_inode_info_unix(&inode,
13336 + full_path, inode->i_sb,xid);
13337 + else
13338 + rc = cifs_get_inode_info(&inode,
13339 + full_path, NULL, inode->i_sb,xid);
13340 + } /* else we are writing out data to server already
13341 + and could deadlock if we tried to flush data, and
13342 + since we do not know if we have data that would
13343 + invalidate the current end of file on the server
13344 + we can not go to the server to get the new
13345 + inod info */
13346 + if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
13347 + pCifsInode->clientCanCacheAll = TRUE;
13348 + pCifsInode->clientCanCacheRead = TRUE;
13349 + cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
13350 + } else if((oplock & 0xF) == OPLOCK_READ) {
13351 + pCifsInode->clientCanCacheRead = TRUE;
13352 + pCifsInode->clientCanCacheAll = FALSE;
13353 + } else {
13354 + pCifsInode->clientCanCacheRead = FALSE;
13355 + pCifsInode->clientCanCacheAll = FALSE;
13356 + }
13357 + cifs_relock_file(pCifsFile);
13358 + }
13359 + }
13360 +
13361 + if (full_path)
13362 + kfree(full_path);
13363 + FreeXid(xid);
13364 + return rc;
13365 +}
13366 +
13367 +int
13368 +cifs_close(struct inode *inode, struct file *file)
13369 +{
13370 + int rc = 0;
13371 + int xid;
13372 + struct cifs_sb_info *cifs_sb;
13373 + struct cifsTconInfo *pTcon;
13374 + struct cifsFileInfo *pSMBFile =
13375 + (struct cifsFileInfo *) file->private_data;
13376 +
13377 + xid = GetXid();
13378 +
13379 + cifs_sb = CIFS_SB(inode->i_sb);
13380 + pTcon = cifs_sb->tcon;
13381 + if (pSMBFile) {
13382 + pSMBFile->closePend = TRUE;
13383 + spin_lock(&files_lock);
13384 + if(pTcon) {
13385 + /* no sense reconnecting to close a file that is
13386 + already closed */
13387 + if (pTcon->tidStatus != CifsNeedReconnect) {
13388 + spin_unlock(&files_lock);
13389 + rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
13390 + spin_lock(&files_lock);
13391 + }
13392 + }
13393 + list_del(&pSMBFile->flist);
13394 + list_del(&pSMBFile->tlist);
13395 + spin_unlock(&files_lock);
13396 + if(pSMBFile->search_resume_name)
13397 + kfree(pSMBFile->search_resume_name);
13398 + kfree(file->private_data);
13399 + file->private_data = NULL;
13400 + } else
13401 + rc = -EBADF;
13402 +
13403 + if(list_empty(&(CIFS_I(inode)->openFileList))) {
13404 + cFYI(1,("closing last open instance for inode %p",inode));
13405 + /* if the file is not open we do not know if we can cache
13406 + info on this inode, much less write behind and read ahead */
13407 + CIFS_I(inode)->clientCanCacheRead = FALSE;
13408 + CIFS_I(inode)->clientCanCacheAll = FALSE;
13409 + }
13410 + if((rc ==0) && CIFS_I(inode)->write_behind_rc)
13411 + rc = CIFS_I(inode)->write_behind_rc;
13412 + FreeXid(xid);
13413 + return rc;
13414 +}
13415 +
13416 +int
13417 +cifs_closedir(struct inode *inode, struct file *file)
13418 +{
13419 + int rc = 0;
13420 + int xid;
13421 + struct cifsFileInfo *pSMBFileStruct =
13422 + (struct cifsFileInfo *) file->private_data;
13423 +
13424 + cFYI(1, ("Closedir inode = 0x%p with ", inode));
13425 +
13426 + xid = GetXid();
13427 +
13428 + if (pSMBFileStruct) {
13429 + cFYI(1, ("Freeing private data in close dir"));
13430 + kfree(file->private_data);
13431 + file->private_data = NULL;
13432 + }
13433 + FreeXid(xid);
13434 + return rc;
13435 +}
13436 +
13437 +int
13438 +cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
13439 +{
13440 + int rc, xid;
13441 + __u32 lockType = LOCKING_ANDX_LARGE_FILES;
13442 + __u32 numLock = 0;
13443 + __u32 numUnlock = 0;
13444 + __u64 length;
13445 + int wait_flag = FALSE;
13446 + struct cifs_sb_info *cifs_sb;
13447 + struct cifsTconInfo *pTcon;
13448 + length = 1 + pfLock->fl_end - pfLock->fl_start;
13449 +
13450 + rc = -EACCES;
13451 +
13452 + xid = GetXid();
13453 +
13454 + cFYI(1,
13455 + ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
13456 + cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
13457 + pfLock->fl_end));
13458 +
13459 + if (pfLock->fl_flags & FL_POSIX)
13460 + cFYI(1, ("Posix "));
13461 + if (pfLock->fl_flags & FL_FLOCK)
13462 + cFYI(1, ("Flock "));
13463 +/* if (pfLock->fl_flags & FL_SLEEP) {
13464 + cFYI(1, ("Blocking lock "));
13465 + wait_flag = TRUE;
13466 + } */
13467 + if (pfLock->fl_flags & FL_ACCESS)
13468 + cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
13469 + if (pfLock->fl_flags & FL_LEASE)
13470 + cFYI(1, ("Lease on file - not implemented yet"));
13471 + if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_ACCESS | FL_LEASE)))
13472 + cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
13473 +
13474 + if (pfLock->fl_type == F_WRLCK) {
13475 + cFYI(1, ("F_WRLCK "));
13476 + numLock = 1;
13477 + } else if (pfLock->fl_type == F_UNLCK) {
13478 + cFYI(1, ("F_UNLCK "));
13479 + numUnlock = 1;
13480 + } else if (pfLock->fl_type == F_RDLCK) {
13481 + cFYI(1, ("F_RDLCK "));
13482 + lockType |= LOCKING_ANDX_SHARED_LOCK;
13483 + numLock = 1;
13484 + } else if (pfLock->fl_type == F_EXLCK) {
13485 + cFYI(1, ("F_EXLCK "));
13486 + numLock = 1;
13487 + } else if (pfLock->fl_type == F_SHLCK) {
13488 + cFYI(1, ("F_SHLCK "));
13489 + lockType |= LOCKING_ANDX_SHARED_LOCK;
13490 + numLock = 1;
13491 + } else
13492 + cFYI(1, ("Unknown type of lock "));
13493 +
13494 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13495 + pTcon = cifs_sb->tcon;
13496 +
13497 + if (file->private_data == NULL) {
13498 + FreeXid(xid);
13499 + return -EBADF;
13500 + }
13501 +
13502 + if (IS_GETLK(cmd)) {
13503 + rc = CIFSSMBLock(xid, pTcon,
13504 + ((struct cifsFileInfo *) file->
13505 + private_data)->netfid,
13506 + length,
13507 + pfLock->fl_start, 0, 1, lockType,
13508 + 0 /* wait flag */ );
13509 + if (rc == 0) {
13510 + rc = CIFSSMBLock(xid, pTcon,
13511 + ((struct cifsFileInfo *) file->
13512 + private_data)->netfid,
13513 + length,
13514 + pfLock->fl_start, 1 /* numUnlock */ ,
13515 + 0 /* numLock */ , lockType,
13516 + 0 /* wait flag */ );
13517 + pfLock->fl_type = F_UNLCK;
13518 + if (rc != 0)
13519 + cERROR(1,
13520 + ("Error unlocking previously locked range %d during test of lock ",
13521 + rc));
13522 + rc = 0;
13523 +
13524 + } else {
13525 + /* if rc == ERR_SHARING_VIOLATION ? */
13526 + rc = 0; /* do not change lock type to unlock since range in use */
13527 + }
13528 +
13529 + FreeXid(xid);
13530 + return rc;
13531 + }
13532 +
13533 + rc = CIFSSMBLock(xid, pTcon,
13534 + ((struct cifsFileInfo *) file->private_data)->
13535 + netfid, length,
13536 + pfLock->fl_start, numUnlock, numLock, lockType,
13537 + wait_flag);
13538 + FreeXid(xid);
13539 + return rc;
13540 +}
13541 +
13542 +ssize_t
13543 +cifs_write(struct file * file, const char *write_data,
13544 + size_t write_size, loff_t * poffset)
13545 +{
13546 + int rc = 0;
13547 + unsigned int bytes_written = 0;
13548 + unsigned int total_written;
13549 + struct cifs_sb_info *cifs_sb;
13550 + struct cifsTconInfo *pTcon;
13551 + int xid, long_op;
13552 + struct cifsFileInfo * open_file;
13553 +
13554 + if(file->f_dentry == NULL)
13555 + return -EBADF;
13556 +
13557 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13558 + if(cifs_sb == NULL) {
13559 + return -EBADF;
13560 + }
13561 + pTcon = cifs_sb->tcon;
13562 +
13563 + /*cFYI(1,
13564 + (" write %d bytes to offset %lld of %s", write_size,
13565 + *poffset, file->f_dentry->d_name.name)); */
13566 +
13567 + if (file->private_data == NULL) {
13568 + return -EBADF;
13569 + } else {
13570 + open_file = (struct cifsFileInfo *) file->private_data;
13571 + }
13572 +
13573 + xid = GetXid();
13574 + if(file->f_dentry->d_inode == NULL) {
13575 + FreeXid(xid);
13576 + return -EBADF;
13577 + }
13578 +
13579 + if (*poffset > file->f_dentry->d_inode->i_size)
13580 + long_op = 2; /* writes past end of file can take a long time */
13581 + else
13582 + long_op = 1;
13583 +
13584 + for (total_written = 0; write_size > total_written;
13585 + total_written += bytes_written) {
13586 + rc = -EAGAIN;
13587 + while(rc == -EAGAIN) {
13588 + if(file->private_data == NULL) {
13589 + /* file has been closed on us */
13590 + FreeXid(xid);
13591 + /* if we have gotten here we have written some data
13592 + and blocked, and the file has been freed on us
13593 + while we blocked so return what we managed to write */
13594 + return total_written;
13595 + }
13596 + if(open_file->closePend) {
13597 + FreeXid(xid);
13598 + if(total_written)
13599 + return total_written;
13600 + else
13601 + return -EBADF;
13602 + }
13603 + if (open_file->invalidHandle) {
13604 + if((file->f_dentry == NULL) ||
13605 + (file->f_dentry->d_inode == NULL)) {
13606 + FreeXid(xid);
13607 + return total_written;
13608 + }
13609 + /* we could deadlock if we called
13610 + filemap_fdatawait from here so tell
13611 + reopen_file not to flush data to server now */
13612 + rc = cifs_reopen_file(file->f_dentry->d_inode,
13613 + file,FALSE);
13614 + if(rc != 0)
13615 + break;
13616 + }
13617 +
13618 + rc = CIFSSMBWrite(xid, pTcon,
13619 + open_file->netfid,
13620 + write_size - total_written, *poffset,
13621 + &bytes_written,
13622 + write_data + total_written, long_op);
13623 + }
13624 + if (rc || (bytes_written == 0)) {
13625 + if (total_written)
13626 + break;
13627 + else {
13628 + FreeXid(xid);
13629 + return rc;
13630 + }
13631 + } else
13632 + *poffset += bytes_written;
13633 + long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
13634 + }
13635 +
13636 +#ifdef CONFIG_CIFS_STATS
13637 + if(total_written > 0) {
13638 + atomic_inc(&pTcon->num_writes);
13639 + spin_lock(&pTcon->stat_lock);
13640 + pTcon->bytes_written += total_written;
13641 + spin_unlock(&pTcon->stat_lock);
13642 + }
13643 +#endif
13644 +
13645 + /* since the write may have blocked check these pointers again */
13646 + if(file->f_dentry) {
13647 + if(file->f_dentry->d_inode) {
13648 + file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
13649 + CURRENT_TIME;
13650 + if (total_written > 0) {
13651 + if (*poffset > file->f_dentry->d_inode->i_size)
13652 + file->f_dentry->d_inode->i_size = *poffset;
13653 + }
13654 + mark_inode_dirty_sync(file->f_dentry->d_inode);
13655 + }
13656 + }
13657 + FreeXid(xid);
13658 + return total_written;
13659 +}
13660 +
13661 +static int
13662 +cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
13663 +{
13664 + struct address_space *mapping = page->mapping;
13665 + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
13666 + char * write_data;
13667 + int rc = -EFAULT;
13668 + int bytes_written = 0;
13669 + struct cifs_sb_info *cifs_sb;
13670 + struct cifsTconInfo *pTcon;
13671 + struct inode *inode;
13672 + struct cifsInodeInfo *cifsInode;
13673 + struct cifsFileInfo *open_file = NULL;
13674 + struct list_head *tmp;
13675 + struct list_head *tmp1;
13676 +
13677 + if (!mapping) {
13678 + return -EFAULT;
13679 + } else if(!mapping->host) {
13680 + return -EFAULT;
13681 + }
13682 +
13683 + inode = page->mapping->host;
13684 + cifs_sb = CIFS_SB(inode->i_sb);
13685 + pTcon = cifs_sb->tcon;
13686 +
13687 + offset += (loff_t)from;
13688 + write_data = kmap(page);
13689 + write_data += from;
13690 +
13691 + if((to > PAGE_CACHE_SIZE) || (from > to)) {
13692 + kunmap(page);
13693 + return -EIO;
13694 + }
13695 +
13696 + /* racing with truncate? */
13697 + if(offset > mapping->host->i_size) {
13698 + kunmap(page);
13699 + return 0; /* don't care */
13700 + }
13701 +
13702 + /* check to make sure that we are not extending the file */
13703 + if(mapping->host->i_size - offset < (loff_t)to)
13704 + to = (unsigned)(mapping->host->i_size - offset);
13705 +
13706 +
13707 + cifsInode = CIFS_I(mapping->host);
13708 + read_lock(&GlobalSMBSeslock);
13709 + /* BB we should start at the end */
13710 + list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
13711 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
13712 + if(open_file->closePend)
13713 + continue;
13714 + /* We check if file is open for writing first */
13715 + if((open_file->pfile) &&
13716 + ((open_file->pfile->f_flags & O_RDWR) ||
13717 + (open_file->pfile->f_flags & O_WRONLY))) {
13718 + read_unlock(&GlobalSMBSeslock);
13719 + bytes_written = cifs_write(open_file->pfile, write_data,
13720 + to-from, &offset);
13721 + read_lock(&GlobalSMBSeslock);
13722 + /* Does mm or vfs already set times? */
13723 + inode->i_atime = inode->i_mtime = CURRENT_TIME;
13724 + if ((bytes_written > 0) && (offset)) {
13725 + rc = 0;
13726 + } else if(bytes_written < 0) {
13727 + if(rc == -EBADF) {
13728 + /* have seen a case in which
13729 + kernel seemed to have closed/freed a file
13730 + even with writes active so we might as well
13731 + see if there are other file structs to try
13732 + for the same inode before giving up */
13733 + continue;
13734 + } else
13735 + rc = bytes_written;
13736 + }
13737 + break; /* now that we found a valid file handle
13738 + and tried to write to it we are done, no
13739 + sense continuing to loop looking for another */
13740 + }
13741 + if(tmp->next == NULL) {
13742 + cFYI(1,("File instance %p removed",tmp));
13743 + break;
13744 + }
13745 + }
13746 + read_unlock(&GlobalSMBSeslock);
13747 + if(open_file == NULL) {
13748 + cFYI(1,("No writeable filehandles for inode"));
13749 + rc = -EIO;
13750 + }
13751 +
13752 + kunmap(page);
13753 + return rc;
13754 +}
13755 +
13756 +#if 0
13757 +static int
13758 +cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
13759 +{
13760 + int rc = -EFAULT;
13761 + int xid;
13762 +
13763 + xid = GetXid();
13764 +/* call 16K write then Setpageuptodate */
13765 + FreeXid(xid);
13766 + return rc;
13767 +}
13768 +#endif
13769 +
13770 +static int
13771 +cifs_writepage(struct page* page)
13772 +{
13773 + int rc = -EFAULT;
13774 + int xid;
13775 +
13776 + xid = GetXid();
13777 +/* BB add check for wbc flags */
13778 + page_cache_get(page);
13779 + if (!Page_Uptodate(page)) {
13780 + cFYI(1,("ppw - page not up to date"));
13781 + }
13782 +
13783 + rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
13784 + SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
13785 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
13786 + unlock_page(page);
13787 +#else
13788 + UnlockPage(page);
13789 +#endif
13790 + page_cache_release(page);
13791 + FreeXid(xid);
13792 + return rc;
13793 +}
13794 +
13795 +static int
13796 +cifs_commit_write(struct file *file, struct page *page, unsigned offset,
13797 + unsigned to)
13798 +{
13799 + int xid;
13800 + int rc = 0;
13801 + struct inode *inode = page->mapping->host;
13802 + loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
13803 + char * page_data;
13804 +
13805 + xid = GetXid();
13806 + cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
13807 + if (position > inode->i_size){
13808 + inode->i_size = position;
13809 + /*if (file->private_data == NULL) {
13810 + rc = -EBADF;
13811 + } else {
13812 + open_file = (struct cifsFileInfo *)file->private_data;
13813 + cifs_sb = CIFS_SB(inode->i_sb);
13814 + rc = -EAGAIN;
13815 + while(rc == -EAGAIN) {
13816 + if((open_file->invalidHandle) &&
13817 + (!open_file->closePend)) {
13818 + rc = cifs_reopen_file(file->f_dentry->d_inode,file);
13819 + if(rc != 0)
13820 + break;
13821 + }
13822 + if(!open_file->closePend) {
13823 + rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
13824 + position, open_file->netfid,
13825 + open_file->pid,FALSE);
13826 + } else {
13827 + rc = -EBADF;
13828 + break;
13829 + }
13830 + }
13831 + cFYI(1,(" SetEOF (commit write) rc = %d",rc));
13832 + }*/
13833 + }
13834 + if (!Page_Uptodate(page)) {
13835 + position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
13836 + /* can not rely on (or let) writepage write this data */
13837 + if(to < offset) {
13838 + cFYI(1,("Illegal offsets, can not copy from %d to %d",
13839 + offset,to));
13840 + FreeXid(xid);
13841 + return rc;
13842 + }
13843 + /* this is probably better than directly calling
13844 + partialpage_write since in this function
13845 + the file handle is known which we might as well
13846 + leverage */
13847 + /* BB check if anything else missing out of ppw */
13848 + /* such as updating last write time */
13849 + page_data = kmap(page);
13850 + rc = cifs_write(file, page_data+offset,to-offset,
13851 + &position);
13852 + if(rc > 0)
13853 + rc = 0;
13854 + /* else if rc < 0 should we set writebehind rc? */
13855 + kunmap(page);
13856 + } else {
13857 + set_page_dirty(page);
13858 + }
13859 +
13860 + FreeXid(xid);
13861 + return rc;
13862 +}
13863 +
13864 +int
13865 +cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
13866 +{
13867 + int xid;
13868 + int rc = 0;
13869 + struct inode * inode = file->f_dentry->d_inode;
13870 +
13871 + xid = GetXid();
13872 +
13873 + cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
13874 + dentry->d_name.name, datasync));
13875 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
13876 + rc = filemap_fdatasync(inode->i_mapping);
13877 +#else
13878 + filemap_fdatasync(inode->i_mapping);
13879 +#endif
13880 + if(rc == 0)
13881 + CIFS_I(inode)->write_behind_rc = 0;
13882 + FreeXid(xid);
13883 + return rc;
13884 +}
13885 +
13886 +static int
13887 +cifs_sync_page(struct page *page)
13888 +{
13889 + struct address_space *mapping;
13890 + struct inode *inode;
13891 + unsigned long index = page->index;
13892 + unsigned int rpages = 0;
13893 + int rc = 0;
13894 +
13895 + cFYI(1,("sync page %p",page));
13896 + mapping = page->mapping;
13897 + if (!mapping)
13898 + return 0;
13899 + inode = mapping->host;
13900 + if (!inode)
13901 + return 0;
13902 +
13903 +/* fill in rpages then
13904 + result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
13905 +
13906 + cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
13907 +
13908 + if (rc < 0)
13909 + return rc;
13910 + return 0;
13911 +}
13912 +
13913 +/*
13914 + * As file closes, flush all cached write data for this inode checking
13915 + * for write behind errors.
13916 + *
13917 + */
13918 +int cifs_flush(struct file *file)
13919 +{
13920 + struct inode * inode = file->f_dentry->d_inode;
13921 + int rc = 0;
13922 +
13923 + /* Rather than do the steps manually: */
13924 + /* lock the inode for writing */
13925 + /* loop through pages looking for write behind data (dirty pages) */
13926 + /* coalesce into contiguous 16K (or smaller) chunks to write to server */
13927 + /* send to server (prefer in parallel) */
13928 + /* deal with writebehind errors */
13929 + /* unlock inode for writing */
13930 + /* filemapfdatawrite appears easier for the time being */
13931 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
13932 + rc = filemap_fdatasync(inode->i_mapping);
13933 +#else
13934 + filemap_fdatasync(inode->i_mapping);
13935 +#endif
13936 + if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
13937 + CIFS_I(inode)->write_behind_rc = 0;
13938 +
13939 + cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
13940 +
13941 + return rc;
13942 +}
13943 +
13944 +
13945 +ssize_t
13946 +cifs_read(struct file * file, char *read_data, size_t read_size,
13947 + loff_t * poffset)
13948 +{
13949 + int rc = -EACCES;
13950 + unsigned int bytes_read = 0;
13951 + unsigned int total_read;
13952 + unsigned int current_read_size;
13953 + struct cifs_sb_info *cifs_sb;
13954 + struct cifsTconInfo *pTcon;
13955 + int xid;
13956 + char * current_offset;
13957 + struct cifsFileInfo * open_file;
13958 +
13959 + xid = GetXid();
13960 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13961 + pTcon = cifs_sb->tcon;
13962 +
13963 + if (file->private_data == NULL) {
13964 + FreeXid(xid);
13965 + return -EBADF;
13966 + }
13967 + open_file = (struct cifsFileInfo *)file->private_data;
13968 +
13969 + if((file->f_flags & O_ACCMODE) == O_WRONLY) {
13970 + cFYI(1,("attempting read on write only file instance"));
13971 + }
13972 +
13973 + for (total_read = 0,current_offset=read_data; read_size > total_read;
13974 + total_read += bytes_read,current_offset+=bytes_read) {
13975 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
13976 + current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
13977 +#else
13978 + current_read_size = min(read_size - total_read,cifs_sb->rsize);
13979 +#endif
13980 + rc = -EAGAIN;
13981 + while(rc == -EAGAIN) {
13982 + if ((open_file->invalidHandle) && (!open_file->closePend)) {
13983 + rc = cifs_reopen_file(file->f_dentry->d_inode,
13984 + file,TRUE);
13985 + if(rc != 0)
13986 + break;
13987 + }
13988 +
13989 + rc = CIFSSMBRead(xid, pTcon,
13990 + open_file->netfid,
13991 + current_read_size, *poffset,
13992 + &bytes_read, &current_offset);
13993 + }
13994 + if (rc || (bytes_read == 0)) {
13995 + if (total_read) {
13996 + break;
13997 + } else {
13998 + FreeXid(xid);
13999 + return rc;
14000 + }
14001 + } else {
14002 +#ifdef CONFIG_CIFS_STATS
14003 + atomic_inc(&pTcon->num_reads);
14004 + spin_lock(&pTcon->stat_lock);
14005 + pTcon->bytes_read += total_read;
14006 + spin_unlock(&pTcon->stat_lock);
14007 +#endif
14008 + *poffset += bytes_read;
14009 + }
14010 + }
14011 + FreeXid(xid);
14012 + return total_read;
14013 +}
14014 +
14015 +int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
14016 +{
14017 + struct dentry * dentry = file->f_dentry;
14018 + int rc, xid;
14019 +
14020 + xid = GetXid();
14021 + rc = cifs_revalidate(dentry);
14022 + if (rc) {
14023 + cFYI(1,("Validation prior to mmap failed, error=%d", rc));
14024 + FreeXid(xid);
14025 + return rc;
14026 + }
14027 + rc = generic_file_mmap(file, vma);
14028 + FreeXid(xid);
14029 + return rc;
14030 +}
14031 +
14032 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
14033 +static void cifs_copy_cache_pages(struct address_space *mapping,
14034 + struct list_head *pages, int bytes_read,
14035 + char *data,struct pagevec * plru_pvec)
14036 +{
14037 + struct page *page;
14038 + char * target;
14039 +
14040 + while (bytes_read > 0) {
14041 + if(list_empty(pages))
14042 + break;
14043 +
14044 + page = list_entry(pages->prev, struct page, lru);
14045 + list_del(&page->lru);
14046 +
14047 + if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
14048 + page_cache_release(page);
14049 + cFYI(1,("Add page cache failed"));
14050 + continue;
14051 + }
14052 +
14053 + target = kmap_atomic(page,KM_USER0);
14054 +
14055 + if(PAGE_CACHE_SIZE > bytes_read) {
14056 + memcpy(target,data,bytes_read);
14057 + /* zero the tail end of this partial page */
14058 + memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
14059 + bytes_read = 0;
14060 + } else {
14061 + memcpy(target,data,PAGE_CACHE_SIZE);
14062 + bytes_read -= PAGE_CACHE_SIZE;
14063 + }
14064 + kunmap_atomic(target,KM_USER0);
14065 +
14066 + flush_dcache_page(page);
14067 + SetPageUptodate(page);
14068 + unlock_page(page);
14069 + if (!pagevec_add(plru_pvec, page))
14070 + __pagevec_lru_add(plru_pvec);
14071 + data += PAGE_CACHE_SIZE;
14072 + }
14073 + return;
14074 +}
14075 +
14076 +
14077 +static int
14078 +cifs_readpages(struct file *file, struct address_space *mapping,
14079 + struct list_head *page_list, unsigned num_pages)
14080 +{
14081 + int rc = -EACCES;
14082 + int xid;
14083 + loff_t offset;
14084 + struct page * page;
14085 + struct cifs_sb_info *cifs_sb;
14086 + struct cifsTconInfo *pTcon;
14087 + int bytes_read = 0;
14088 + unsigned int read_size,i;
14089 + char * smb_read_data = NULL;
14090 + struct smb_com_read_rsp * pSMBr;
14091 + struct pagevec lru_pvec;
14092 + struct cifsFileInfo * open_file;
14093 +
14094 + xid = GetXid();
14095 + if (file->private_data == NULL) {
14096 + FreeXid(xid);
14097 + return -EBADF;
14098 + }
14099 + open_file = (struct cifsFileInfo *)file->private_data;
14100 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14101 + pTcon = cifs_sb->tcon;
14102 +
14103 + pagevec_init(&lru_pvec, 0);
14104 +
14105 + for(i = 0;i<num_pages;) {
14106 + unsigned contig_pages;
14107 + struct page * tmp_page;
14108 + unsigned long expected_index;
14109 +
14110 + if(list_empty(page_list)) {
14111 + break;
14112 + }
14113 + page = list_entry(page_list->prev, struct page, lru);
14114 + offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
14115 +
14116 + /* count adjacent pages that we will read into */
14117 + contig_pages = 0;
14118 + expected_index = list_entry(page_list->prev,struct page,lru)->index;
14119 + list_for_each_entry_reverse(tmp_page,page_list,lru) {
14120 + if(tmp_page->index == expected_index) {
14121 + contig_pages++;
14122 + expected_index++;
14123 + } else {
14124 + break;
14125 + }
14126 + }
14127 + if(contig_pages + i > num_pages) {
14128 + contig_pages = num_pages - i;
14129 + }
14130 +
14131 + /* for reads over a certain size could initiate async read ahead */
14132 +
14133 + read_size = contig_pages * PAGE_CACHE_SIZE;
14134 + /* Read size needs to be in multiples of one page */
14135 + read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
14136 +
14137 + rc = -EAGAIN;
14138 + while(rc == -EAGAIN) {
14139 + if ((open_file->invalidHandle) && (!open_file->closePend)) {
14140 + rc = cifs_reopen_file(file->f_dentry->d_inode,
14141 + file, TRUE);
14142 + if(rc != 0)
14143 + break;
14144 + }
14145 +
14146 + rc = CIFSSMBRead(xid, pTcon,
14147 + open_file->netfid,
14148 + read_size, offset,
14149 + &bytes_read, &smb_read_data);
14150 + /* BB need to check return code here */
14151 + if(rc== -EAGAIN) {
14152 + if(smb_read_data) {
14153 + cifs_buf_release(smb_read_data);
14154 + smb_read_data = NULL;
14155 + }
14156 + }
14157 + }
14158 + if ((rc < 0) || (smb_read_data == NULL)) {
14159 + cFYI(1,("Read error in readpages: %d",rc));
14160 + /* clean up remaing pages off list */
14161 + while (!list_empty(page_list) && (i < num_pages)) {
14162 + page = list_entry(page_list->prev, struct page, lru);
14163 + list_del(&page->lru);
14164 + page_cache_release(page);
14165 + }
14166 + break;
14167 + } else if (bytes_read > 0) {
14168 + pSMBr = (struct smb_com_read_rsp *)smb_read_data;
14169 + cifs_copy_cache_pages(mapping, page_list, bytes_read,
14170 + smb_read_data + 4 /* RFC1001 hdr */ +
14171 + le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
14172 +
14173 + i += bytes_read >> PAGE_CACHE_SHIFT;
14174 +#ifdef CONFIG_CIFS_STATS
14175 + atomic_inc(&pTcon->num_reads);
14176 + spin_lock(&pTcon->stat_lock);
14177 + pTcon->bytes_read += bytes_read;
14178 + spin_unlock(&pTcon->stat_lock);
14179 +#endif
14180 + if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
14181 + cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
14182 +
14183 + i++; /* account for partial page */
14184 +
14185 + /* server copy of file can have smaller size than client */
14186 + /* BB do we need to verify this common case ? this case is ok -
14187 + if we are at server EOF we will hit it on next read */
14188 +
14189 + /* while(!list_empty(page_list) && (i < num_pages)) {
14190 + page = list_entry(page_list->prev,struct page, list);
14191 + list_del(&page->list);
14192 + page_cache_release(page);
14193 + }
14194 + break; */
14195 + }
14196 + } else {
14197 + cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
14198 + /* BB turn off caching and do new lookup on file size at server? */
14199 + while (!list_empty(page_list) && (i < num_pages)) {
14200 + page = list_entry(page_list->prev, struct page, lru);
14201 + list_del(&page->lru);
14202 + page_cache_release(page); /* BB removeme - replace with zero of page? */
14203 + }
14204 + break;
14205 + }
14206 + if(smb_read_data) {
14207 + cifs_buf_release(smb_read_data);
14208 + smb_read_data = NULL;
14209 + }
14210 + bytes_read = 0;
14211 + }
14212 +
14213 + pagevec_lru_add(&lru_pvec);
14214 +
14215 +/* need to free smb_read_data buf before exit */
14216 + if(smb_read_data) {
14217 + cifs_buf_release(smb_read_data);
14218 + smb_read_data = NULL;
14219 + }
14220 +
14221 + FreeXid(xid);
14222 + return rc;
14223 +}
14224 +#endif
14225 +
14226 +static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
14227 +{
14228 + char * read_data;
14229 + int rc;
14230 +
14231 + page_cache_get(page);
14232 + read_data = kmap(page);
14233 + /* for reads over a certain size could initiate async read ahead */
14234 +
14235 + rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
14236 +
14237 + if (rc < 0)
14238 + goto io_error;
14239 + else {
14240 + cFYI(1,("Bytes read %d ",rc));
14241 + }
14242 +
14243 + file->f_dentry->d_inode->i_atime = CURRENT_TIME;
14244 +
14245 + if(PAGE_CACHE_SIZE > rc) {
14246 + memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
14247 + }
14248 + flush_dcache_page(page);
14249 + SetPageUptodate(page);
14250 + rc = 0;
14251 +
14252 +io_error:
14253 + kunmap(page);
14254 + page_cache_release(page);
14255 + return rc;
14256 +}
14257 +
14258 +static int
14259 +cifs_readpage(struct file *file, struct page *page)
14260 +{
14261 + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
14262 + int rc = -EACCES;
14263 + int xid;
14264 +
14265 + xid = GetXid();
14266 +
14267 + if (file->private_data == NULL) {
14268 + FreeXid(xid);
14269 + return -EBADF;
14270 + }
14271 +
14272 + cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
14273 +
14274 + rc = cifs_readpage_worker(file,page,&offset);
14275 +
14276 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
14277 + unlock_page(page);
14278 +#else
14279 + UnlockPage(page);
14280 +#endif
14281 +
14282 + FreeXid(xid);
14283 + return rc;
14284 +}
14285 +
14286 +/* We do not want to update the file size from server for inodes
14287 + open for write - to avoid races with writepage extending
14288 + the file - in the future we could consider allowing
14289 + refreshing the inode only on increases in the file size
14290 + but this is tricky to do without racing with writebehind
14291 + page caching in the current Linux kernel design */
14292 +
14293 +int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
14294 +{
14295 + struct list_head *tmp;
14296 + struct list_head *tmp1;
14297 + struct cifsFileInfo *open_file = NULL;
14298 + int rc = TRUE;
14299 +
14300 + if(cifsInode == NULL)
14301 + return rc;
14302 +
14303 + read_lock(&GlobalSMBSeslock);
14304 + list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
14305 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
14306 + if(open_file == NULL)
14307 + break;
14308 + if(open_file->closePend)
14309 + continue;
14310 + /* We check if file is open for writing,
14311 + BB we could supplement this with a check to see if file size
14312 + changes have been flushed to server - ie inode metadata dirty */
14313 + if((open_file->pfile) &&
14314 + ((open_file->pfile->f_flags & O_RDWR) ||
14315 + (open_file->pfile->f_flags & O_WRONLY))) {
14316 + rc = FALSE;
14317 + break;
14318 + }
14319 + if(tmp->next == NULL) {
14320 + cFYI(1,("File instance %p removed",tmp));
14321 + break;
14322 + }
14323 + }
14324 + read_unlock(&GlobalSMBSeslock);
14325 + return rc;
14326 +}
14327 +
14328 +
14329 +void
14330 +fill_in_inode(struct inode *tmp_inode,
14331 + FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
14332 +{
14333 + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
14334 + struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
14335 +
14336 + pfindData->ExtFileAttributes =
14337 + le32_to_cpu(pfindData->ExtFileAttributes);
14338 + pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
14339 + pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
14340 + cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
14341 + cifsInfo->time = jiffies;
14342 +
14343 + /* Linux can not store file creation time unfortunately so ignore it */
14344 + tmp_inode->i_atime =
14345 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
14346 + tmp_inode->i_mtime =
14347 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
14348 + tmp_inode->i_ctime =
14349 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
14350 + /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
14351 + /* 2767 perms - indicate mandatory locking */
14352 + /* BB fill in uid and gid here? with help from winbind?
14353 + or retrieve from NTFS stream extended attribute */
14354 + if(atomic_read(&cifsInfo->inUse) == 0) {
14355 + tmp_inode->i_uid = cifs_sb->mnt_uid;
14356 + tmp_inode->i_gid = cifs_sb->mnt_gid;
14357 + /* set default mode. will override for dirs below */
14358 + tmp_inode->i_mode = cifs_sb->mnt_file_mode;
14359 + }
14360 +
14361 + cFYI(0,
14362 + ("CIFS FFIRST: Attributes came in as 0x%x",
14363 + pfindData->ExtFileAttributes));
14364 + if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
14365 + *pobject_type = DT_LNK;
14366 + /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
14367 + tmp_inode->i_mode |= S_IFLNK;
14368 + } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
14369 + *pobject_type = DT_DIR;
14370 + /* override default perms since we do not lock dirs */
14371 + if(atomic_read(&cifsInfo->inUse) == 0) {
14372 + tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
14373 + }
14374 + tmp_inode->i_mode |= S_IFDIR;
14375 + } else {
14376 + *pobject_type = DT_REG;
14377 + tmp_inode->i_mode |= S_IFREG;
14378 + if(pfindData->ExtFileAttributes & ATTR_READONLY)
14379 + tmp_inode->i_mode &= ~(S_IWUGO);
14380 +
14381 + }/* could add code here - to validate if device or weird share type? */
14382 +
14383 + /* can not fill in nlink here as in qpathinfo version and Unx search */
14384 + if(atomic_read(&cifsInfo->inUse) == 0) {
14385 + atomic_set(&cifsInfo->inUse,1);
14386 + }
14387 + if(is_size_safe_to_change(cifsInfo)) {
14388 + /* can not safely change the file size here if the
14389 + client is writing to it due to potential races */
14390 + tmp_inode->i_size = pfindData->EndOfFile;
14391 +
14392 + /* 512 bytes (2**9) is the fake blocksize that must be used */
14393 + /* for this calculation, even though the reported blocksize is larger */
14394 + tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
14395 + }
14396 +
14397 + if (pfindData->AllocationSize < pfindData->EndOfFile)
14398 + cFYI(1, ("Possible sparse file: allocation size less than end of file "));
14399 + cFYI(1,
14400 + ("File Size %ld and blocks %ld and blocksize %ld",
14401 + (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
14402 + tmp_inode->i_blksize));
14403 + if (S_ISREG(tmp_inode->i_mode)) {
14404 + cFYI(1, (" File inode "));
14405 + tmp_inode->i_op = &cifs_file_inode_ops;
14406 + tmp_inode->i_fop = &cifs_file_ops;
14407 + tmp_inode->i_data.a_ops = &cifs_addr_ops;
14408 + } else if (S_ISDIR(tmp_inode->i_mode)) {
14409 + cFYI(1, (" Directory inode"));
14410 + tmp_inode->i_op = &cifs_dir_inode_ops;
14411 + tmp_inode->i_fop = &cifs_dir_ops;
14412 + } else if (S_ISLNK(tmp_inode->i_mode)) {
14413 + cFYI(1, (" Symbolic Link inode "));
14414 + tmp_inode->i_op = &cifs_symlink_inode_ops;
14415 + } else {
14416 + cFYI(1, (" Init special inode "));
14417 + init_special_inode(tmp_inode, tmp_inode->i_mode,
14418 + kdev_t_to_nr(tmp_inode->i_rdev));
14419 + }
14420 +}
14421 +
14422 +void
14423 +unix_fill_in_inode(struct inode *tmp_inode,
14424 + FILE_UNIX_INFO * pfindData, int *pobject_type)
14425 +{
14426 + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
14427 + cifsInfo->time = jiffies;
14428 + atomic_inc(&cifsInfo->inUse);
14429 +
14430 + tmp_inode->i_atime =
14431 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
14432 + tmp_inode->i_mtime =
14433 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
14434 + tmp_inode->i_ctime =
14435 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
14436 +
14437 + tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
14438 + pfindData->Type = le32_to_cpu(pfindData->Type);
14439 + if (pfindData->Type == UNIX_FILE) {
14440 + *pobject_type = DT_REG;
14441 + tmp_inode->i_mode |= S_IFREG;
14442 + } else if (pfindData->Type == UNIX_SYMLINK) {
14443 + *pobject_type = DT_LNK;
14444 + tmp_inode->i_mode |= S_IFLNK;
14445 + } else if (pfindData->Type == UNIX_DIR) {
14446 + *pobject_type = DT_DIR;
14447 + tmp_inode->i_mode |= S_IFDIR;
14448 + } else if (pfindData->Type == UNIX_CHARDEV) {
14449 + *pobject_type = DT_CHR;
14450 + tmp_inode->i_mode |= S_IFCHR;
14451 + tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
14452 + le64_to_cpu(pfindData->DevMinor) & MINORMASK);
14453 + } else if (pfindData->Type == UNIX_BLOCKDEV) {
14454 + *pobject_type = DT_BLK;
14455 + tmp_inode->i_mode |= S_IFBLK;
14456 + tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
14457 + le64_to_cpu(pfindData->DevMinor) & MINORMASK);
14458 + } else if (pfindData->Type == UNIX_FIFO) {
14459 + *pobject_type = DT_FIFO;
14460 + tmp_inode->i_mode |= S_IFIFO;
14461 + } else if (pfindData->Type == UNIX_SOCKET) {
14462 + *pobject_type = DT_SOCK;
14463 + tmp_inode->i_mode |= S_IFSOCK;
14464 + }
14465 +
14466 + tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
14467 + tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
14468 + tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
14469 +
14470 + pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
14471 + if(is_size_safe_to_change(cifsInfo)) {
14472 + /* can not safely change the file size here if the
14473 + client is writing to it due to potential races */
14474 + pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
14475 + tmp_inode->i_size = pfindData->EndOfFile;
14476 +
14477 + /* 512 bytes (2**9) is the fake blocksize that must be used */
14478 + /* for this calculation, not the real blocksize */
14479 + tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
14480 + }
14481 +
14482 + if (S_ISREG(tmp_inode->i_mode)) {
14483 + cFYI(1, ("File inode"));
14484 + tmp_inode->i_op = &cifs_file_inode_ops;
14485 + tmp_inode->i_fop = &cifs_file_ops;
14486 + tmp_inode->i_data.a_ops = &cifs_addr_ops;
14487 + } else if (S_ISDIR(tmp_inode->i_mode)) {
14488 + cFYI(1, ("Directory inode"));
14489 + tmp_inode->i_op = &cifs_dir_inode_ops;
14490 + tmp_inode->i_fop = &cifs_dir_ops;
14491 + } else if (S_ISLNK(tmp_inode->i_mode)) {
14492 + cFYI(1, ("Symbolic Link inode"));
14493 + tmp_inode->i_op = &cifs_symlink_inode_ops;
14494 +/* tmp_inode->i_fop = *//* do not need to set to anything */
14495 + } else {
14496 + cFYI(1, ("Special inode"));
14497 + init_special_inode(tmp_inode, tmp_inode->i_mode,
14498 + kdev_t_to_nr(tmp_inode->i_rdev));
14499 + }
14500 +}
14501 +
14502 +static void
14503 +construct_dentry(struct qstr *qstring, struct file *file,
14504 + struct inode **ptmp_inode, struct dentry **pnew_dentry)
14505 +{
14506 + struct dentry *tmp_dentry;
14507 + struct cifs_sb_info *cifs_sb;
14508 + struct cifsTconInfo *pTcon;
14509 + struct cifsInodeInfo *pCifsI;
14510 +
14511 + cFYI(1, ("For %s ", qstring->name));
14512 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14513 + pTcon = cifs_sb->tcon;
14514 +
14515 + qstring->hash = full_name_hash(qstring->name, qstring->len);
14516 + tmp_dentry = d_lookup(file->f_dentry, qstring);
14517 + if (tmp_dentry) {
14518 + cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
14519 + *ptmp_inode = tmp_dentry->d_inode;
14520 + /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
14521 + if(*ptmp_inode == NULL) {
14522 + *ptmp_inode = new_inode(file->f_dentry->d_sb);
14523 + if(*ptmp_inode == NULL)
14524 + return;
14525 + d_instantiate(tmp_dentry, *ptmp_inode);
14526 + insert_inode_hash(*ptmp_inode);
14527 + pCifsI = CIFS_I(*ptmp_inode);
14528 + INIT_LIST_HEAD(&pCifsI->openFileList);
14529 + /* can not enable caching for this inode
14530 + until a file instance is open and we
14531 + can check the oplock flag on the open
14532 + response */
14533 + (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
14534 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
14535 + (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
14536 +#endif
14537 + pCifsI->clientCanCacheRead = FALSE;
14538 + pCifsI->clientCanCacheAll = FALSE;
14539 + pCifsI->time = 0;
14540 + /* do not need to set cifs Attrs since
14541 + they are about to be overwritten
14542 + in fill_in_inode */
14543 + atomic_set(&pCifsI->inUse, 0);
14544 + }
14545 + } else {
14546 + tmp_dentry = d_alloc(file->f_dentry, qstring);
14547 + if(tmp_dentry == NULL) {
14548 + cERROR(1,("Failed allocating dentry"));
14549 + return;
14550 + }
14551 +
14552 + if(ptmp_inode) {
14553 + *ptmp_inode = new_inode(file->f_dentry->d_sb);
14554 + if(*ptmp_inode == NULL)
14555 + return;
14556 + pCifsI = CIFS_I(*ptmp_inode);
14557 + insert_inode_hash(*ptmp_inode);
14558 + INIT_LIST_HEAD(&pCifsI->openFileList);
14559 + /* can not enable caching for this inode
14560 + until a file instance is open and we
14561 + can check the oplock flag on the open
14562 + response */
14563 + (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
14564 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
14565 + (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
14566 +#endif
14567 + pCifsI->clientCanCacheRead = FALSE;
14568 + pCifsI->clientCanCacheAll = FALSE;
14569 + pCifsI->time = 0;
14570 + /* do not need to set cifs Attrs since
14571 + they are about to be overwritten
14572 + in fill_in_inode */
14573 + atomic_set(&pCifsI->inUse, 0);
14574 + }
14575 + tmp_dentry->d_op = &cifs_dentry_ops;
14576 + d_instantiate(tmp_dentry, *ptmp_inode);
14577 + d_rehash(tmp_dentry);
14578 + }
14579 +
14580 + tmp_dentry->d_time = jiffies;
14581 + *pnew_dentry = tmp_dentry;
14582 +}
14583 +
14584 +static void reset_resume_key(struct file * dir_file,
14585 + unsigned char * filename,
14586 + unsigned int len,int Unicode,struct nls_table * nls_tab) {
14587 + struct cifsFileInfo *cifsFile;
14588 +
14589 + cifsFile = (struct cifsFileInfo *)dir_file->private_data;
14590 + if(cifsFile == NULL)
14591 + return;
14592 + if(cifsFile->search_resume_name) {
14593 + kfree(cifsFile->search_resume_name);
14594 + }
14595 +
14596 + if(Unicode)
14597 + len *= 2;
14598 + cifsFile->resume_name_length = len;
14599 +
14600 + cifsFile->search_resume_name =
14601 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14602 +
14603 + if(cifsFile->search_resume_name == NULL) {
14604 + cERROR(1,("failed new resume key allocate, length %d",
14605 + cifsFile->resume_name_length));
14606 + return;
14607 + }
14608 + if(Unicode)
14609 + cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
14610 + filename, len, nls_tab);
14611 + else
14612 + memcpy(cifsFile->search_resume_name, filename,
14613 + cifsFile->resume_name_length);
14614 + cFYI(1,("Reset resume key to: %s with len %d",filename,len));
14615 + return;
14616 +}
14617 +
14618 +
14619 +
14620 +static int
14621 +cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
14622 + struct file *file, filldir_t filldir, void *direntry)
14623 +{
14624 + struct inode *tmp_inode;
14625 + struct dentry *tmp_dentry;
14626 + int object_type,rc;
14627 +
14628 + pqstring->name = pfindData->FileName;
14629 + pqstring->len = pfindData->FileNameLength;
14630 +
14631 + construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
14632 + if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
14633 + return -ENOMEM;
14634 + }
14635 + fill_in_inode(tmp_inode, pfindData, &object_type);
14636 + rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
14637 + tmp_inode->i_ino, object_type);
14638 + if(rc) {
14639 + /* due to readdir error we need to recalculate resume
14640 + key so next readdir will restart on right entry */
14641 + cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
14642 + }
14643 + dput(tmp_dentry);
14644 + return rc;
14645 +}
14646 +
14647 +static int
14648 +cifs_filldir_unix(struct qstr *pqstring,
14649 + FILE_UNIX_INFO * pUnixFindData, struct file *file,
14650 + filldir_t filldir, void *direntry)
14651 +{
14652 + struct inode *tmp_inode;
14653 + struct dentry *tmp_dentry;
14654 + int object_type, rc;
14655 +
14656 + pqstring->name = pUnixFindData->FileName;
14657 + pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
14658 +
14659 + construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
14660 + if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
14661 + return -ENOMEM;
14662 + }
14663 +
14664 + unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
14665 + rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
14666 + file->f_pos, tmp_inode->i_ino, object_type);
14667 + if(rc) {
14668 + /* due to readdir error we need to recalculate resume
14669 + key so next readdir will restart on right entry */
14670 + cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
14671 + }
14672 + dput(tmp_dentry);
14673 + return rc;
14674 +}
14675 +
14676 +int
14677 +cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
14678 +{
14679 + int rc = 0;
14680 + int xid;
14681 + int Unicode = FALSE;
14682 + int UnixSearch = FALSE;
14683 + unsigned int bufsize, i;
14684 + __u16 searchHandle;
14685 + struct cifs_sb_info *cifs_sb;
14686 + struct cifsTconInfo *pTcon;
14687 + struct cifsFileInfo *cifsFile = NULL;
14688 + char *full_path = NULL;
14689 + char *data;
14690 + struct qstr qstring;
14691 + T2_FFIRST_RSP_PARMS findParms;
14692 + T2_FNEXT_RSP_PARMS findNextParms;
14693 + FILE_DIRECTORY_INFO *pfindData;
14694 + FILE_DIRECTORY_INFO *lastFindData;
14695 + FILE_UNIX_INFO *pfindDataUnix;
14696 +
14697 + xid = GetXid();
14698 +
14699 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14700 + pTcon = cifs_sb->tcon;
14701 + bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
14702 + if(bufsize > CIFS_MAX_MSGSIZE) {
14703 + FreeXid(xid);
14704 + return -EIO;
14705 + }
14706 + data = kmalloc(bufsize, GFP_KERNEL);
14707 + pfindData = (FILE_DIRECTORY_INFO *) data;
14708 +
14709 + if(file->f_dentry == NULL) {
14710 + FreeXid(xid);
14711 + return -EIO;
14712 + }
14713 + down(&file->f_dentry->d_sb->s_vfs_rename_sem);
14714 + full_path = build_wildcard_path_from_dentry(file->f_dentry);
14715 + up(&file->f_dentry->d_sb->s_vfs_rename_sem);
14716 +
14717 +
14718 + cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
14719 +
14720 + switch ((int) file->f_pos) {
14721 + case 0:
14722 + if (filldir(direntry, ".", 1, file->f_pos,
14723 + file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
14724 + cERROR(1, ("Filldir for current dir failed "));
14725 + break;
14726 + }
14727 + file->f_pos++;
14728 + /* fallthrough */
14729 + case 1:
14730 + if (filldir(direntry, "..", 2, file->f_pos,
14731 + file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
14732 + cERROR(1, ("Filldir for parent dir failed "));
14733 + break;
14734 + }
14735 + file->f_pos++;
14736 + /* fallthrough */
14737 + case 2:
14738 + if (file->private_data != NULL) {
14739 + cifsFile =
14740 + (struct cifsFileInfo *) file->private_data;
14741 + if (cifsFile->endOfSearch) {
14742 + if(cifsFile->emptyDir) {
14743 + cFYI(1, ("End of search, empty dir"));
14744 + rc = 0;
14745 + break;
14746 + }
14747 + } else {
14748 + cifsFile->invalidHandle = TRUE;
14749 + CIFSFindClose(xid, pTcon, cifsFile->netfid);
14750 + }
14751 + if(cifsFile->search_resume_name) {
14752 + kfree(cifsFile->search_resume_name);
14753 + cifsFile->search_resume_name = NULL;
14754 + }
14755 + }
14756 + rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
14757 + &findParms, cifs_sb->local_nls,
14758 + &Unicode, &UnixSearch);
14759 + cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
14760 + findParms.EndofSearch));
14761 +
14762 + if (rc == 0) {
14763 + searchHandle = findParms.SearchHandle;
14764 + if(file->private_data == NULL)
14765 + file->private_data =
14766 + kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
14767 + if (file->private_data) {
14768 + memset(file->private_data, 0,
14769 + sizeof (struct cifsFileInfo));
14770 + cifsFile =
14771 + (struct cifsFileInfo *) file->private_data;
14772 + cifsFile->netfid = searchHandle;
14773 + cifsFile->invalidHandle = FALSE;
14774 + init_MUTEX(&cifsFile->fh_sem);
14775 + } else {
14776 + rc = -ENOMEM;
14777 + break;
14778 + }
14779 +
14780 + renew_parental_timestamps(file->f_dentry);
14781 + lastFindData =
14782 + (FILE_DIRECTORY_INFO *) ((char *) pfindData +
14783 + findParms.LastNameOffset);
14784 + if((char *)lastFindData > (char *)pfindData + bufsize) {
14785 + cFYI(1,("last search entry past end of packet"));
14786 + rc = -EIO;
14787 + break;
14788 + }
14789 + /* Offset of resume key same for levels 257 and 514 */
14790 + cifsFile->resume_key = lastFindData->FileIndex;
14791 + if(UnixSearch == FALSE) {
14792 + cifsFile->resume_name_length =
14793 + le32_to_cpu(lastFindData->FileNameLength);
14794 + if(cifsFile->resume_name_length > bufsize - 64) {
14795 + cFYI(1,("Illegal resume file name length %d",
14796 + cifsFile->resume_name_length));
14797 + rc = -ENOMEM;
14798 + break;
14799 + }
14800 + cifsFile->search_resume_name =
14801 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14802 + cFYI(1,("Last file: %s with name %d bytes long",
14803 + lastFindData->FileName,
14804 + cifsFile->resume_name_length));
14805 + memcpy(cifsFile->search_resume_name,
14806 + lastFindData->FileName,
14807 + cifsFile->resume_name_length);
14808 + } else {
14809 + pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
14810 + if (Unicode == TRUE) {
14811 + for(i=0;(pfindDataUnix->FileName[i]
14812 + | pfindDataUnix->FileName[i+1]);
14813 + i+=2) {
14814 + if(i > bufsize-64)
14815 + break;
14816 + }
14817 + cifsFile->resume_name_length = i + 2;
14818 + } else {
14819 + cifsFile->resume_name_length =
14820 + strnlen(pfindDataUnix->FileName,
14821 + bufsize-63);
14822 + }
14823 + if(cifsFile->resume_name_length > bufsize - 64) {
14824 + cFYI(1,("Illegal resume file name length %d",
14825 + cifsFile->resume_name_length));
14826 + rc = -ENOMEM;
14827 + break;
14828 + }
14829 + cifsFile->search_resume_name =
14830 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14831 + cFYI(1,("Last file: %s with name %d bytes long",
14832 + pfindDataUnix->FileName,
14833 + cifsFile->resume_name_length));
14834 + memcpy(cifsFile->search_resume_name,
14835 + pfindDataUnix->FileName,
14836 + cifsFile->resume_name_length);
14837 + }
14838 + for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
14839 + if (UnixSearch == FALSE) {
14840 + pfindData->FileNameLength =
14841 + le32_to_cpu(pfindData->FileNameLength);
14842 + if (Unicode == TRUE)
14843 + pfindData->FileNameLength =
14844 + cifs_strfromUCS_le
14845 + (pfindData->FileName,
14846 + (wchar_t *)
14847 + pfindData->FileName,
14848 + (pfindData->
14849 + FileNameLength) / 2,
14850 + cifs_sb->local_nls);
14851 + qstring.len = pfindData->FileNameLength;
14852 + if (((qstring.len != 1)
14853 + || (pfindData->FileName[0] != '.'))
14854 + && ((qstring.len != 2)
14855 + || (pfindData->
14856 + FileName[0] != '.')
14857 + || (pfindData->
14858 + FileName[1] != '.'))) {
14859 + if(cifs_filldir(&qstring,
14860 + pfindData,
14861 + file, filldir,
14862 + direntry)) {
14863 + /* do not end search if
14864 + kernel not ready to take
14865 + remaining entries yet */
14866 + reset_resume_key(file, pfindData->FileName,qstring.len,
14867 + Unicode, cifs_sb->local_nls);
14868 + findParms.EndofSearch = 0;
14869 + break;
14870 + }
14871 + file->f_pos++;
14872 + }
14873 + } else { /* UnixSearch */
14874 + pfindDataUnix =
14875 + (FILE_UNIX_INFO *) pfindData;
14876 + if (Unicode == TRUE)
14877 + qstring.len =
14878 + cifs_strfromUCS_le
14879 + (pfindDataUnix->FileName,
14880 + (wchar_t *)
14881 + pfindDataUnix->FileName,
14882 + MAX_PATHCONF,
14883 + cifs_sb->local_nls);
14884 + else
14885 + qstring.len =
14886 + strnlen(pfindDataUnix->
14887 + FileName,
14888 + MAX_PATHCONF);
14889 + if (((qstring.len != 1)
14890 + || (pfindDataUnix->
14891 + FileName[0] != '.'))
14892 + && ((qstring.len != 2)
14893 + || (pfindDataUnix->
14894 + FileName[0] != '.')
14895 + || (pfindDataUnix->
14896 + FileName[1] != '.'))) {
14897 + if(cifs_filldir_unix(&qstring,
14898 + pfindDataUnix,
14899 + file,
14900 + filldir,
14901 + direntry)) {
14902 + /* do not end search if
14903 + kernel not ready to take
14904 + remaining entries yet */
14905 + findParms.EndofSearch = 0;
14906 + reset_resume_key(file, pfindDataUnix->FileName,
14907 + qstring.len,Unicode,cifs_sb->local_nls);
14908 + break;
14909 + }
14910 + file->f_pos++;
14911 + }
14912 + }
14913 + /* works also for Unix ff struct since first field of both */
14914 + pfindData =
14915 + (FILE_DIRECTORY_INFO *) ((char *) pfindData
14916 + + le32_to_cpu(pfindData->NextEntryOffset));
14917 + /* BB also should check to make sure that pointer is not beyond the end of the SMB */
14918 + /* if(pfindData > lastFindData) rc = -EIO; break; */
14919 + } /* end for loop */
14920 + if ((findParms.EndofSearch != 0) && cifsFile) {
14921 + cifsFile->endOfSearch = TRUE;
14922 + if(findParms.SearchCount == 2)
14923 + cifsFile->emptyDir = TRUE;
14924 + }
14925 + } else {
14926 + if (cifsFile)
14927 + cifsFile->endOfSearch = TRUE;
14928 + /* unless parent directory gone do not return error */
14929 + rc = 0;
14930 + }
14931 + break;
14932 + default:
14933 + if (file->private_data == NULL) {
14934 + rc = -EBADF;
14935 + cFYI(1,
14936 + ("Readdir on closed srch, pos = %lld",
14937 + file->f_pos));
14938 + } else {
14939 + cifsFile = (struct cifsFileInfo *) file->private_data;
14940 + if (cifsFile->endOfSearch) {
14941 + rc = 0;
14942 + cFYI(1, ("End of search "));
14943 + break;
14944 + }
14945 + searchHandle = cifsFile->netfid;
14946 + rc = CIFSFindNext(xid, pTcon, pfindData,
14947 + &findNextParms, searchHandle,
14948 + cifsFile->search_resume_name,
14949 + cifsFile->resume_name_length,
14950 + cifsFile->resume_key,
14951 + &Unicode, &UnixSearch);
14952 + cFYI(1,("Count: %d End: %d ",
14953 + findNextParms.SearchCount,
14954 + findNextParms.EndofSearch));
14955 + if ((rc == 0) && (findNextParms.SearchCount != 0)) {
14956 + /* BB save off resume key, key name and name length */
14957 + lastFindData =
14958 + (FILE_DIRECTORY_INFO *) ((char *) pfindData
14959 + + findNextParms.LastNameOffset);
14960 + if((char *)lastFindData > (char *)pfindData + bufsize) {
14961 + cFYI(1,("last search entry past end of packet"));
14962 + rc = -EIO;
14963 + break;
14964 + }
14965 + /* Offset of resume key same for levels 257 and 514 */
14966 + cifsFile->resume_key = lastFindData->FileIndex;
14967 +
14968 + if(UnixSearch == FALSE) {
14969 + cifsFile->resume_name_length =
14970 + le32_to_cpu(lastFindData->FileNameLength);
14971 + if(cifsFile->resume_name_length > bufsize - 64) {
14972 + cFYI(1,("Illegal resume file name length %d",
14973 + cifsFile->resume_name_length));
14974 + rc = -ENOMEM;
14975 + break;
14976 + }
14977 + /* Free the memory allocated by previous findfirst
14978 + or findnext call - we can not reuse the memory since
14979 + the resume name may not be same string length */
14980 + if(cifsFile->search_resume_name)
14981 + kfree(cifsFile->search_resume_name);
14982 + cifsFile->search_resume_name =
14983 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14984 + cFYI(1,("Last file: %s with name %d bytes long",
14985 + lastFindData->FileName,
14986 + cifsFile->resume_name_length));
14987 + memcpy(cifsFile->search_resume_name,
14988 + lastFindData->FileName,
14989 + cifsFile->resume_name_length);
14990 + } else {
14991 + pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
14992 + if (Unicode == TRUE) {
14993 + for(i=0;(pfindDataUnix->FileName[i]
14994 + | pfindDataUnix->FileName[i+1]);
14995 + i+=2) {
14996 + if(i > bufsize-64)
14997 + break;
14998 + }
14999 + cifsFile->resume_name_length = i + 2;
15000 + } else {
15001 + cifsFile->resume_name_length =
15002 + strnlen(pfindDataUnix->
15003 + FileName,
15004 + MAX_PATHCONF);
15005 + }
15006 + if(cifsFile->resume_name_length > bufsize - 64) {
15007 + cFYI(1,("Illegal resume file name length %d",
15008 + cifsFile->resume_name_length));
15009 + rc = -ENOMEM;
15010 + break;
15011 + }
15012 + /* Free the memory allocated by previous findfirst
15013 + or findnext call - we can not reuse the memory since
15014 + the resume name may not be same string length */
15015 + if(cifsFile->search_resume_name)
15016 + kfree(cifsFile->search_resume_name);
15017 + cifsFile->search_resume_name =
15018 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
15019 + cFYI(1,("fnext last file: %s with name %d bytes long",
15020 + pfindDataUnix->FileName,
15021 + cifsFile->resume_name_length));
15022 + memcpy(cifsFile->search_resume_name,
15023 + pfindDataUnix->FileName,
15024 + cifsFile->resume_name_length);
15025 + }
15026 +
15027 + for (i = 0; i < findNextParms.SearchCount; i++) {
15028 + pfindData->FileNameLength =
15029 + le32_to_cpu(pfindData->
15030 + FileNameLength);
15031 + if (UnixSearch == FALSE) {
15032 + if (Unicode == TRUE)
15033 + pfindData->FileNameLength =
15034 + cifs_strfromUCS_le
15035 + (pfindData->FileName,
15036 + (wchar_t *)
15037 + pfindData->FileName,
15038 + (pfindData->FileNameLength)/ 2,
15039 + cifs_sb->local_nls);
15040 + qstring.len =
15041 + pfindData->FileNameLength;
15042 + if (((qstring.len != 1)
15043 + || (pfindData->FileName[0] != '.'))
15044 + && ((qstring.len != 2)
15045 + || (pfindData->FileName[0] != '.')
15046 + || (pfindData->FileName[1] !=
15047 + '.'))) {
15048 + if(cifs_filldir
15049 + (&qstring,
15050 + pfindData,
15051 + file, filldir,
15052 + direntry)) {
15053 + /* do not end search if
15054 + kernel not ready to take
15055 + remaining entries yet */
15056 + findNextParms.EndofSearch = 0;
15057 + reset_resume_key(file, pfindData->FileName,qstring.len,
15058 + Unicode,cifs_sb->local_nls);
15059 + break;
15060 + }
15061 + file->f_pos++;
15062 + }
15063 + } else { /* UnixSearch */
15064 + pfindDataUnix =
15065 + (FILE_UNIX_INFO *)
15066 + pfindData;
15067 + if (Unicode == TRUE)
15068 + qstring.len =
15069 + cifs_strfromUCS_le
15070 + (pfindDataUnix->FileName,
15071 + (wchar_t *)
15072 + pfindDataUnix->FileName,
15073 + MAX_PATHCONF,
15074 + cifs_sb->local_nls);
15075 + else
15076 + qstring.len =
15077 + strnlen
15078 + (pfindDataUnix->
15079 + FileName,
15080 + MAX_PATHCONF);
15081 + if (((qstring.len != 1)
15082 + || (pfindDataUnix->
15083 + FileName[0] != '.'))
15084 + && ((qstring.len != 2)
15085 + || (pfindDataUnix->
15086 + FileName[0] != '.')
15087 + || (pfindDataUnix->
15088 + FileName[1] !=
15089 + '.'))) {
15090 + if(cifs_filldir_unix
15091 + (&qstring,
15092 + pfindDataUnix,
15093 + file, filldir,
15094 + direntry)) {
15095 + /* do not end search if
15096 + kernel not ready to take
15097 + remaining entries yet */
15098 + findNextParms.EndofSearch = 0;
15099 + reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
15100 + Unicode,cifs_sb->local_nls);
15101 + break;
15102 + }
15103 + file->f_pos++;
15104 + }
15105 + }
15106 + 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 */
15107 + /* BB also should check to make sure that pointer is not beyond the end of the SMB */
15108 + } /* end for loop */
15109 + if (findNextParms.EndofSearch != 0) {
15110 + cifsFile->endOfSearch = TRUE;
15111 + }
15112 + } else {
15113 + cifsFile->endOfSearch = TRUE;
15114 + rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */
15115 + }
15116 + }
15117 + } /* end switch */
15118 + if (data)
15119 + kfree(data);
15120 + if (full_path)
15121 + kfree(full_path);
15122 + FreeXid(xid);
15123 +
15124 + return rc;
15125 +}
15126 +int cifs_prepare_write(struct file *file, struct page *page,
15127 + unsigned from, unsigned to)
15128 +{
15129 + int rc = 0;
15130 + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
15131 + cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
15132 + if (!Page_Uptodate(page)) {
15133 + /* if (to - from != PAGE_CACHE_SIZE) {
15134 + void *kaddr = kmap_atomic(page, KM_USER0);
15135 + memset(kaddr, 0, from);
15136 + memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
15137 + flush_dcache_page(page);
15138 + kunmap_atomic(kaddr, KM_USER0);
15139 + } */
15140 + /* If we are writing a full page it will be up to date,
15141 + no need to read from the server */
15142 + if((to==PAGE_CACHE_SIZE) && (from == 0))
15143 + SetPageUptodate(page);
15144 +
15145 + /* might as well read a page, it is fast enough */
15146 + if((file->f_flags & O_ACCMODE) != O_WRONLY) {
15147 + rc = cifs_readpage_worker(file,page,&offset);
15148 + } else {
15149 + /* should we try using another
15150 + file handle if there is one - how would we lock it
15151 + to prevent close of that handle racing with this read? */
15152 + /* In any case this will be written out by commit_write */
15153 + }
15154 + }
15155 +
15156 + /* BB should we pass any errors back? e.g. if we do not have read access to the file */
15157 + return 0;
15158 +}
15159 +
15160 +
15161 +struct address_space_operations cifs_addr_ops = {
15162 + .readpage = cifs_readpage,
15163 +/* .readpages = cifs_readpages, */
15164 + .writepage = cifs_writepage,
15165 + .prepare_write = cifs_prepare_write,
15166 + .commit_write = cifs_commit_write,
15167 + .sync_page = cifs_sync_page,
15168 + /*.direct_IO = */
15169 +};
15170 Index: linux-2.4.35.4/fs/cifs/inode.c
15171 ===================================================================
15172 --- /dev/null
15173 +++ linux-2.4.35.4/fs/cifs/inode.c
15174 @@ -0,0 +1,1079 @@
15175 +/*
15176 + * fs/cifs/inode.c
15177 + *
15178 + * Copyright (C) International Business Machines Corp., 2002,2003
15179 + * Author(s): Steve French (sfrench@us.ibm.com)
15180 + *
15181 + * This library is free software; you can redistribute it and/or modify
15182 + * it under the terms of the GNU Lesser General Public License as published
15183 + * by the Free Software Foundation; either version 2.1 of the License, or
15184 + * (at your option) any later version.
15185 + *
15186 + * This library is distributed in the hope that it will be useful,
15187 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15188 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15189 + * the GNU Lesser General Public License for more details.
15190 + *
15191 + * You should have received a copy of the GNU Lesser General Public License
15192 + * along with this library; if not, write to the Free Software
15193 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15194 + */
15195 +#include <linux/fs.h>
15196 +#include <linux/stat.h>
15197 +#include <linux/pagemap.h>
15198 +#include <linux/version.h>
15199 +#include <asm/div64.h>
15200 +#include "cifsfs.h"
15201 +#include "cifspdu.h"
15202 +#include "cifsglob.h"
15203 +#include "cifsproto.h"
15204 +#include "cifs_debug.h"
15205 +#include "cifs_fs_sb.h"
15206 +
15207 +extern int is_size_safe_to_change(struct cifsInodeInfo *);
15208 +
15209 +struct inode * get_cifs_inode(struct super_block * sb)
15210 +{
15211 + struct inode * newinode;
15212 + newinode = new_inode(sb);
15213 + cFYI(1,("got new inode %p",newinode));
15214 + if(newinode) {
15215 + struct cifsInodeInfo * cifsInfo = CIFS_I(newinode);
15216 + cifsInfo->clientCanCacheRead = FALSE;
15217 + cifsInfo->clientCanCacheAll = FALSE;
15218 + INIT_LIST_HEAD(&cifsInfo->openFileList);
15219 + cifsInfo->cifsAttrs = 0x20; /* default */
15220 + newinode->i_blksize = CIFS_MAX_MSGSIZE;
15221 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
15222 + newinode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
15223 +#endif
15224 + atomic_set(&cifsInfo->inUse, 0);
15225 + cifsInfo->time = 0;
15226 + insert_inode_hash(newinode);
15227 + }
15228 + return newinode;
15229 +
15230 +}
15231 +
15232 +int
15233 +cifs_get_inode_info_unix(struct inode **pinode,
15234 + const unsigned char *search_path,
15235 + struct super_block *sb,int xid)
15236 +{
15237 + int rc = 0;
15238 + FILE_UNIX_BASIC_INFO findData;
15239 + struct cifsTconInfo *pTcon;
15240 + struct inode *inode;
15241 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
15242 + char *tmp_path;
15243 +
15244 + pTcon = cifs_sb->tcon;
15245 + cFYI(1, (" Getting info on %s ", search_path));
15246 + /* we could have done a find first instead but this returns more info */
15247 + rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
15248 + cifs_sb->local_nls);
15249 + /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
15250 + if (rc) {
15251 + if (rc == -EREMOTE) {
15252 + tmp_path =
15253 + kmalloc(strnlen
15254 + (pTcon->treeName,
15255 + MAX_TREE_SIZE + 1) +
15256 + strnlen(search_path, MAX_PATHCONF) + 1,
15257 + GFP_KERNEL);
15258 + if (tmp_path == NULL) {
15259 + return -ENOMEM;
15260 + }
15261 + /* have to skip first of the double backslash of UNC name */
15262 + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
15263 + strncat(tmp_path, search_path, MAX_PATHCONF);
15264 + rc = connect_to_dfs_path(xid, pTcon->ses,
15265 + /* treename + */ tmp_path,
15266 + cifs_sb->local_nls);
15267 + kfree(tmp_path);
15268 +
15269 + /* BB fix up inode etc. */
15270 + } else if (rc) {
15271 + return rc;
15272 + }
15273 +
15274 + } else {
15275 + struct cifsInodeInfo *cifsInfo;
15276 +
15277 + /* get new inode */
15278 + if (*pinode == NULL) {
15279 + *pinode = get_cifs_inode(sb);
15280 + }
15281 + if(*pinode == NULL) {
15282 + return -ENOMEM;
15283 + }
15284 +
15285 + inode = *pinode;
15286 + cifsInfo = CIFS_I(inode);
15287 +
15288 + cFYI(1, (" Old time %ld ", cifsInfo->time));
15289 + cifsInfo->time = jiffies;
15290 + cFYI(1, (" New time %ld ", cifsInfo->time));
15291 + atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
15292 +
15293 + inode->i_atime =
15294 + cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
15295 + inode->i_mtime =
15296 + cifs_NTtimeToUnix(le64_to_cpu
15297 + (findData.LastModificationTime));
15298 + inode->i_ctime =
15299 + cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
15300 + inode->i_mode = le64_to_cpu(findData.Permissions);
15301 + findData.Type = le32_to_cpu(findData.Type);
15302 + if (findData.Type == UNIX_FILE) {
15303 + inode->i_mode |= S_IFREG;
15304 + } else if (findData.Type == UNIX_SYMLINK) {
15305 + inode->i_mode |= S_IFLNK;
15306 + } else if (findData.Type == UNIX_DIR) {
15307 + inode->i_mode |= S_IFDIR;
15308 + } else if (findData.Type == UNIX_CHARDEV) {
15309 + inode->i_mode |= S_IFCHR;
15310 + inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
15311 + le64_to_cpu(findData.DevMinor) & MINORMASK);
15312 + } else if (findData.Type == UNIX_BLOCKDEV) {
15313 + inode->i_mode |= S_IFBLK;
15314 + inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
15315 + le64_to_cpu(findData.DevMinor) & MINORMASK);
15316 + } else if (findData.Type == UNIX_FIFO) {
15317 + inode->i_mode |= S_IFIFO;
15318 + } else if (findData.Type == UNIX_SOCKET) {
15319 + inode->i_mode |= S_IFSOCK;
15320 + }
15321 + inode->i_uid = le64_to_cpu(findData.Uid);
15322 + inode->i_gid = le64_to_cpu(findData.Gid);
15323 + inode->i_nlink = le64_to_cpu(findData.Nlinks);
15324 + findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
15325 + findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
15326 +
15327 + if(is_size_safe_to_change(cifsInfo)) {
15328 + /* can not safely change the file size here if the
15329 + client is writing to it due to potential races */
15330 + inode->i_size = findData.EndOfFile;
15331 +/* blksize needs to be multiple of two. So safer to default to blksize
15332 + and blkbits set in superblock so 2**blkbits and blksize will match */
15333 +/* inode->i_blksize =
15334 + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
15335 +
15336 + /* This seems incredibly stupid but it turns out that
15337 + i_blocks is not related to (i_size / i_blksize), instead a
15338 + size of 512 is required to be used for calculating num blocks */
15339 +
15340 +
15341 +/* inode->i_blocks =
15342 + (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
15343 +
15344 + /* 512 bytes (2**9) is the fake blocksize that must be used */
15345 + /* for this calculation */
15346 + inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
15347 + }
15348 +
15349 + if (findData.NumOfBytes < findData.EndOfFile)
15350 + cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
15351 + cFYI(1,
15352 + ("Size %ld and blocks %ld ",
15353 + (unsigned long) inode->i_size, inode->i_blocks));
15354 + if (S_ISREG(inode->i_mode)) {
15355 + cFYI(1, (" File inode "));
15356 + inode->i_op = &cifs_file_inode_ops;
15357 + inode->i_fop = &cifs_file_ops;
15358 + inode->i_data.a_ops = &cifs_addr_ops;
15359 + } else if (S_ISDIR(inode->i_mode)) {
15360 + cFYI(1, (" Directory inode"));
15361 + inode->i_op = &cifs_dir_inode_ops;
15362 + inode->i_fop = &cifs_dir_ops;
15363 + } else if (S_ISLNK(inode->i_mode)) {
15364 + cFYI(1, (" Symbolic Link inode "));
15365 + inode->i_op = &cifs_symlink_inode_ops;
15366 +/* tmp_inode->i_fop = *//* do not need to set to anything */
15367 + } else {
15368 + cFYI(1, (" Init special inode "));
15369 + init_special_inode(inode, inode->i_mode,
15370 + kdev_t_to_nr(inode->i_rdev));
15371 + }
15372 + }
15373 + return rc;
15374 +}
15375 +
15376 +int
15377 +cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
15378 + FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
15379 +{
15380 + int rc = 0;
15381 + struct cifsTconInfo *pTcon;
15382 + struct inode *inode;
15383 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
15384 + char *tmp_path;
15385 + char *buf = NULL;
15386 +
15387 + pTcon = cifs_sb->tcon;
15388 + cFYI(1,("Getting info on %s ", search_path));
15389 +
15390 + if((pfindData == NULL) && (*pinode != NULL)) {
15391 + if(CIFS_I(*pinode)->clientCanCacheRead) {
15392 + cFYI(1,("No need to revalidate inode sizes on cached file "));
15393 + return rc;
15394 + }
15395 + }
15396 +
15397 + /* if file info not passed in then get it from server */
15398 + if(pfindData == NULL) {
15399 + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
15400 + pfindData = (FILE_ALL_INFO *)buf;
15401 + /* could do find first instead but this returns more info */
15402 + rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
15403 + cifs_sb->local_nls);
15404 + }
15405 + /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
15406 + if (rc) {
15407 + if (rc == -EREMOTE) {
15408 + tmp_path =
15409 + kmalloc(strnlen
15410 + (pTcon->treeName,
15411 + MAX_TREE_SIZE + 1) +
15412 + strnlen(search_path, MAX_PATHCONF) + 1,
15413 + GFP_KERNEL);
15414 + if (tmp_path == NULL) {
15415 + if(buf)
15416 + kfree(buf);
15417 + return -ENOMEM;
15418 + }
15419 +
15420 + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
15421 + strncat(tmp_path, search_path, MAX_PATHCONF);
15422 + rc = connect_to_dfs_path(xid, pTcon->ses,
15423 + /* treename + */ tmp_path,
15424 + cifs_sb->local_nls);
15425 + kfree(tmp_path);
15426 + /* BB fix up inode etc. */
15427 + } else if (rc) {
15428 + if(buf)
15429 + kfree(buf);
15430 + return rc;
15431 + }
15432 + } else {
15433 + struct cifsInodeInfo *cifsInfo;
15434 +
15435 + /* get new inode */
15436 + if (*pinode == NULL) {
15437 + *pinode = get_cifs_inode(sb);
15438 + }
15439 + if(*pinode == NULL)
15440 + return -ENOMEM;
15441 + inode = *pinode;
15442 + cifsInfo = CIFS_I(inode);
15443 + pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
15444 + cifsInfo->cifsAttrs = pfindData->Attributes;
15445 + cFYI(1, (" Old time %ld ", cifsInfo->time));
15446 + cifsInfo->time = jiffies;
15447 + cFYI(1, (" New time %ld ", cifsInfo->time));
15448 +
15449 +/* blksize needs to be multiple of two. So safer to default to blksize
15450 + and blkbits set in superblock so 2**blkbits and blksize will match */
15451 +/* inode->i_blksize =
15452 + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
15453 +
15454 + /* Linux can not store file creation time unfortunately so we ignore it */
15455 + inode->i_atime =
15456 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
15457 + inode->i_mtime =
15458 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
15459 + inode->i_ctime =
15460 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
15461 + cFYI(0,
15462 + (" Attributes came in as 0x%x ", pfindData->Attributes));
15463 +
15464 + /* set default mode. will override for dirs below */
15465 + if(atomic_read(&cifsInfo->inUse) == 0)
15466 + /* new inode, can safely set these fields */
15467 + inode->i_mode = cifs_sb->mnt_file_mode;
15468 +
15469 + if (pfindData->Attributes & ATTR_REPARSE) {
15470 + /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
15471 + inode->i_mode |= S_IFLNK;
15472 + } else if (pfindData->Attributes & ATTR_DIRECTORY) {
15473 + /* override default perms since we do not do byte range locking on dirs */
15474 + inode->i_mode = cifs_sb->mnt_dir_mode;
15475 + inode->i_mode |= S_IFDIR;
15476 + } else {
15477 + inode->i_mode |= S_IFREG;
15478 + /* treat the dos attribute of read-only as read-only mode e.g. 555 */
15479 + if(cifsInfo->cifsAttrs & ATTR_READONLY)
15480 + inode->i_mode &= ~(S_IWUGO);
15481 + /* BB add code here - validate if device or weird share or device type? */
15482 + }
15483 + if(is_size_safe_to_change(cifsInfo)) {
15484 + /* can not safely change the file size here if the
15485 + client is writing to it due to potential races */
15486 + inode->i_size = le64_to_cpu(pfindData->EndOfFile);
15487 +
15488 + /* 512 bytes (2**9) is the fake blocksize that must be used */
15489 + /* for this calculation */
15490 + inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
15491 + >> 9;
15492 + }
15493 + pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
15494 +
15495 + cFYI(1,
15496 + (" Size %ld and blocks %ld ",
15497 + (unsigned long) inode->i_size, inode->i_blocks));
15498 + inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
15499 +
15500 + /* BB fill in uid and gid here? with help from winbind?
15501 + or retrieve from NTFS stream extended attribute */
15502 + if(atomic_read(&cifsInfo->inUse) == 0) {
15503 + inode->i_uid = cifs_sb->mnt_uid;
15504 + inode->i_gid = cifs_sb->mnt_gid;
15505 + /* set so we do not keep refreshing these fields with
15506 + bad data after user has changed them in memory */
15507 + atomic_set(&cifsInfo->inUse,1);
15508 + }
15509 +
15510 + if (S_ISREG(inode->i_mode)) {
15511 + cFYI(1, (" File inode "));
15512 + inode->i_op = &cifs_file_inode_ops;
15513 + inode->i_fop = &cifs_file_ops;
15514 + inode->i_data.a_ops = &cifs_addr_ops;
15515 + } else if (S_ISDIR(inode->i_mode)) {
15516 + cFYI(1, (" Directory inode "));
15517 + inode->i_op = &cifs_dir_inode_ops;
15518 + inode->i_fop = &cifs_dir_ops;
15519 + } else if (S_ISLNK(inode->i_mode)) {
15520 + cFYI(1, (" Symbolic Link inode "));
15521 + inode->i_op = &cifs_symlink_inode_ops;
15522 + } else {
15523 + init_special_inode(inode, inode->i_mode,
15524 + kdev_t_to_nr(inode->i_rdev));
15525 + }
15526 + }
15527 + if(buf)
15528 + kfree(buf);
15529 + return rc;
15530 +}
15531 +
15532 +void
15533 +cifs_read_inode(struct inode *inode)
15534 +{ /* gets root inode */
15535 + int xid;
15536 + struct cifs_sb_info *cifs_sb;
15537 + struct cifsInodeInfo *cifs_inode;
15538 +
15539 + cifs_sb = CIFS_SB(inode->i_sb);
15540 + xid = GetXid();
15541 +
15542 + cifs_inode = CIFS_I(inode);
15543 + cifs_inode->cifsAttrs = ATTR_DIRECTORY;
15544 + atomic_set(&cifs_inode->inUse, 0);
15545 + cifs_inode->time = 0;
15546 + inode->i_blksize = CIFS_MAX_MSGSIZE;
15547 + inode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
15548 +
15549 + INIT_LIST_HEAD(&cifs_inode->openFileList);
15550 +
15551 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
15552 + cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
15553 + else
15554 + cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
15555 + /* can not call macro FreeXid here since in a void func */
15556 + _FreeXid(xid);
15557 +}
15558 +
15559 +int
15560 +cifs_unlink(struct inode *inode, struct dentry *direntry)
15561 +{
15562 + int rc = 0;
15563 + int xid;
15564 + struct cifs_sb_info *cifs_sb;
15565 + struct cifsTconInfo *pTcon;
15566 + char *full_path = NULL;
15567 + struct cifsInodeInfo *cifsInode;
15568 + FILE_BASIC_INFO * pinfo_buf;
15569 +
15570 + cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
15571 +
15572 + xid = GetXid();
15573 +
15574 + cifs_sb = CIFS_SB(inode->i_sb);
15575 + pTcon = cifs_sb->tcon;
15576 +
15577 +/* Unlink can be called from rename so we can not grab
15578 + the sem here since we deadlock otherwise */
15579 +/* down(&direntry->d_sb->s_vfs_rename_sem);*/
15580 + full_path = build_path_from_dentry(direntry);
15581 +/* up(&direntry->d_sb->s_vfs_rename_sem);*/
15582 + if(full_path == NULL) {
15583 + FreeXid(xid);
15584 + return -ENOMEM;
15585 + }
15586 + rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
15587 +
15588 + if (!rc) {
15589 + direntry->d_inode->i_nlink--;
15590 + } else if (rc == -ENOENT) {
15591 + d_drop(direntry);
15592 + } else if (rc == -ETXTBSY) {
15593 + int oplock = FALSE;
15594 + __u16 netfid;
15595 +
15596 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
15597 + CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
15598 + &netfid, &oplock, NULL, cifs_sb->local_nls);
15599 + if(rc==0) {
15600 + CIFSSMBRenameOpenFile(xid,pTcon,netfid,
15601 + NULL, cifs_sb->local_nls);
15602 + CIFSSMBClose(xid, pTcon, netfid);
15603 + direntry->d_inode->i_nlink--;
15604 + }
15605 + } else if (rc == -EACCES) {
15606 + /* try only if r/o attribute set in local lookup data? */
15607 + pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
15608 + if(pinfo_buf) {
15609 + memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
15610 + /* ATTRS set to normal clears r/o bit */
15611 + pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
15612 + rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
15613 + cifs_sb->local_nls);
15614 + kfree(pinfo_buf);
15615 + }
15616 + if(rc==0) {
15617 + rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
15618 + if (!rc) {
15619 + direntry->d_inode->i_nlink--;
15620 + } else if (rc == -ETXTBSY) {
15621 + int oplock = FALSE;
15622 + __u16 netfid;
15623 +
15624 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
15625 + CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
15626 + &netfid, &oplock, NULL, cifs_sb->local_nls);
15627 + if(rc==0) {
15628 + CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
15629 + CIFSSMBClose(xid, pTcon, netfid);
15630 + direntry->d_inode->i_nlink--;
15631 + }
15632 + /* BB if rc = -ETXTBUSY goto the rename logic BB */
15633 + }
15634 + }
15635 + }
15636 + cifsInode = CIFS_I(direntry->d_inode);
15637 + cifsInode->time = 0; /* will force revalidate to get info when needed */
15638 + direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
15639 + CURRENT_TIME;
15640 + cifsInode = CIFS_I(inode);
15641 + cifsInode->time = 0; /* force revalidate of dir as well */
15642 +
15643 + if (full_path)
15644 + kfree(full_path);
15645 + FreeXid(xid);
15646 + return rc;
15647 +}
15648 +
15649 +int
15650 +cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
15651 +{
15652 + int rc = 0;
15653 + int xid;
15654 + struct cifs_sb_info *cifs_sb;
15655 + struct cifsTconInfo *pTcon;
15656 + char *full_path = NULL;
15657 + struct inode *newinode = NULL;
15658 +
15659 + cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
15660 +
15661 + xid = GetXid();
15662 +
15663 + cifs_sb = CIFS_SB(inode->i_sb);
15664 + pTcon = cifs_sb->tcon;
15665 +
15666 + down(&inode->i_sb->s_vfs_rename_sem);
15667 + full_path = build_path_from_dentry(direntry);
15668 + up(&inode->i_sb->s_vfs_rename_sem);
15669 + if(full_path == NULL) {
15670 + FreeXid(xid);
15671 + return -ENOMEM;
15672 + }
15673 + /* BB add setting the equivalent of mode via CreateX w/ACLs */
15674 + rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
15675 + if (rc) {
15676 + cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
15677 + d_drop(direntry);
15678 + } else {
15679 + inode->i_nlink++;
15680 + if (pTcon->ses->capabilities & CAP_UNIX)
15681 + rc = cifs_get_inode_info_unix(&newinode, full_path,
15682 + inode->i_sb,xid);
15683 + else
15684 + rc = cifs_get_inode_info(&newinode, full_path,NULL,
15685 + inode->i_sb,xid);
15686 +
15687 + direntry->d_op = &cifs_dentry_ops;
15688 + d_instantiate(direntry, newinode);
15689 + if(direntry->d_inode)
15690 + direntry->d_inode->i_nlink = 2;
15691 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
15692 + CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
15693 + (__u64)-1,
15694 + (__u64)-1,
15695 + 0 /* dev_t */,
15696 + cifs_sb->local_nls);
15697 + else { /* BB to be implemented via Windows secrty descriptors*/
15698 + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
15699 + }
15700 + }
15701 + if (full_path)
15702 + kfree(full_path);
15703 + FreeXid(xid);
15704 +
15705 + return rc;
15706 +}
15707 +
15708 +int
15709 +cifs_rmdir(struct inode *inode, struct dentry *direntry)
15710 +{
15711 + int rc = 0;
15712 + int xid;
15713 + struct cifs_sb_info *cifs_sb;
15714 + struct cifsTconInfo *pTcon;
15715 + char *full_path = NULL;
15716 + struct cifsInodeInfo *cifsInode;
15717 +
15718 + cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
15719 +
15720 + xid = GetXid();
15721 +
15722 + cifs_sb = CIFS_SB(inode->i_sb);
15723 + pTcon = cifs_sb->tcon;
15724 +
15725 + down(&inode->i_sb->s_vfs_rename_sem);
15726 + full_path = build_path_from_dentry(direntry);
15727 + up(&inode->i_sb->s_vfs_rename_sem);
15728 + if(full_path == NULL) {
15729 + FreeXid(xid);
15730 + return -ENOMEM;
15731 + }
15732 +
15733 + rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
15734 +
15735 + if (!rc) {
15736 + inode->i_nlink--;
15737 + direntry->d_inode->i_size = 0;
15738 + direntry->d_inode->i_nlink = 0;
15739 + }
15740 +
15741 + cifsInode = CIFS_I(direntry->d_inode);
15742 + cifsInode->time = 0; /* force revalidate to go get info when needed */
15743 + direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
15744 + CURRENT_TIME;
15745 +
15746 + if (full_path)
15747 + kfree(full_path);
15748 + FreeXid(xid);
15749 + return rc;
15750 +}
15751 +
15752 +int
15753 +cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
15754 + struct inode *target_inode, struct dentry *target_direntry)
15755 +{
15756 + char *fromName;
15757 + char *toName;
15758 + struct cifs_sb_info *cifs_sb_source;
15759 + struct cifs_sb_info *cifs_sb_target;
15760 + struct cifsTconInfo *pTcon;
15761 + int xid;
15762 + int rc = 0;
15763 +
15764 + xid = GetXid();
15765 +
15766 + cifs_sb_target = CIFS_SB(target_inode->i_sb);
15767 + cifs_sb_source = CIFS_SB(source_inode->i_sb);
15768 + pTcon = cifs_sb_source->tcon;
15769 +
15770 + if (pTcon != cifs_sb_target->tcon) {
15771 + FreeXid(xid);
15772 + return -EXDEV; /* BB actually could be allowed if same server, but
15773 + different share. Might eventually add support for this */
15774 + }
15775 +
15776 + /* we already have the rename sem so we do not need
15777 + to grab it again here to protect the path integrity */
15778 + fromName = build_path_from_dentry(source_direntry);
15779 + toName = build_path_from_dentry(target_direntry);
15780 + if((fromName == NULL) || (toName == NULL)) {
15781 + rc = -ENOMEM;
15782 + goto cifs_rename_exit;
15783 + }
15784 +
15785 + rc = CIFSSMBRename(xid, pTcon, fromName, toName,
15786 + cifs_sb_source->local_nls);
15787 + if(rc == -EEXIST) {
15788 + /* check if they are the same file
15789 + because rename of hardlinked files is a noop */
15790 + FILE_UNIX_BASIC_INFO * info_buf_source;
15791 + FILE_UNIX_BASIC_INFO * info_buf_target;
15792 +
15793 + info_buf_source =
15794 + kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
15795 + if(info_buf_source != NULL) {
15796 + info_buf_target = info_buf_source+1;
15797 + rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
15798 + info_buf_source, cifs_sb_source->local_nls);
15799 + if(rc == 0) {
15800 + rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
15801 + info_buf_target,
15802 + cifs_sb_target->local_nls);
15803 + }
15804 + if((rc == 0) &&
15805 + (info_buf_source->UniqueId ==
15806 + info_buf_target->UniqueId)) {
15807 + /* do not rename since the files are hardlinked
15808 + which is a noop */
15809 + } else {
15810 + /* we either can not tell the files are hardlinked
15811 + (as with Windows servers) or files are not hardlinked
15812 + so delete the target manually before renaming to
15813 + follow POSIX rather than Windows semantics */
15814 + cifs_unlink(target_inode, target_direntry);
15815 + rc = CIFSSMBRename(xid, pTcon, fromName, toName,
15816 + cifs_sb_source->local_nls);
15817 + }
15818 + kfree(info_buf_source);
15819 + } /* if we can not get memory just leave rc as EEXIST */
15820 + }
15821 +
15822 + if((rc == -EIO)||(rc == -EEXIST)) {
15823 + int oplock = FALSE;
15824 + __u16 netfid;
15825 +
15826 + rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
15827 + CREATE_NOT_DIR,
15828 + &netfid, &oplock, NULL, cifs_sb_source->local_nls);
15829 + if(rc==0) {
15830 + CIFSSMBRenameOpenFile(xid,pTcon,netfid,
15831 + toName, cifs_sb_source->local_nls);
15832 + CIFSSMBClose(xid, pTcon, netfid);
15833 + }
15834 + }
15835 +
15836 +cifs_rename_exit:
15837 + if (fromName)
15838 + kfree(fromName);
15839 + if (toName)
15840 + kfree(toName);
15841 +
15842 + FreeXid(xid);
15843 + return rc;
15844 +}
15845 +
15846 +int
15847 +cifs_revalidate(struct dentry *direntry)
15848 +{
15849 + int xid;
15850 + int rc = 0;
15851 + char *full_path;
15852 + struct cifs_sb_info *cifs_sb;
15853 + struct cifsInodeInfo *cifsInode;
15854 + loff_t local_size;
15855 + time_t local_mtime;
15856 + int invalidate_inode = FALSE;
15857 +
15858 + if(direntry->d_inode == NULL)
15859 + return -ENOENT;
15860 +
15861 + cifsInode = CIFS_I(direntry->d_inode);
15862 +
15863 + if(cifsInode == NULL)
15864 + return -ENOENT;
15865 +
15866 + /* no sense revalidating inode info on file that no one can write */
15867 + if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
15868 + return rc;
15869 +
15870 + xid = GetXid();
15871 +
15872 + cifs_sb = CIFS_SB(direntry->d_sb);
15873 +
15874 + /* can not safely grab the rename sem here if
15875 + rename calls revalidate since that would deadlock */
15876 + full_path = build_path_from_dentry(direntry);
15877 + if(full_path == NULL) {
15878 + FreeXid(xid);
15879 + return -ENOMEM;
15880 + }
15881 + cFYI(1,
15882 + ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
15883 + full_path, direntry->d_inode,
15884 + direntry->d_inode->i_count.counter, direntry,
15885 + direntry->d_time, jiffies));
15886 +
15887 + if (cifsInode->time == 0){
15888 + /* was set to zero previously to force revalidate */
15889 + } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
15890 + if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
15891 + (direntry->d_inode->i_nlink == 1)) {
15892 + if (full_path)
15893 + kfree(full_path);
15894 + FreeXid(xid);
15895 + return rc;
15896 + } else {
15897 + cFYI(1,("Have to revalidate file due to hardlinks"));
15898 + }
15899 + }
15900 +
15901 + /* save mtime and size */
15902 + local_mtime = direntry->d_inode->i_mtime;
15903 + local_size = direntry->d_inode->i_size;
15904 +
15905 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
15906 + rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
15907 + direntry->d_sb,xid);
15908 + if(rc) {
15909 + cFYI(1,("error on getting revalidate info %d",rc));
15910 +/* if(rc != -ENOENT)
15911 + rc = 0; */ /* BB should we cache info on certain errors? */
15912 + }
15913 + } else {
15914 + rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
15915 + direntry->d_sb,xid);
15916 + if(rc) {
15917 + cFYI(1,("error on getting revalidate info %d",rc));
15918 +/* if(rc != -ENOENT)
15919 + rc = 0; */ /* BB should we cache info on certain errors? */
15920 + }
15921 + }
15922 + /* should we remap certain errors, access denied?, to zero */
15923 +
15924 + /* if not oplocked, we invalidate inode pages if mtime
15925 + or file size had changed on server */
15926 +
15927 + if((local_mtime == direntry->d_inode->i_mtime) &&
15928 + (local_size == direntry->d_inode->i_size)) {
15929 + cFYI(1,("cifs_revalidate - inode unchanged"));
15930 + } else {
15931 + /* file may have changed on server */
15932 + if(cifsInode->clientCanCacheRead) {
15933 + /* no need to invalidate inode pages since we were
15934 + the only ones who could have modified the file and
15935 + the server copy is staler than ours */
15936 + } else {
15937 + invalidate_inode = TRUE;
15938 + }
15939 + }
15940 +
15941 + /* can not grab this sem since kernel filesys locking
15942 + documentation indicates i_sem may be taken by the kernel
15943 + on lookup and rename which could deadlock if we grab
15944 + the i_sem here as well */
15945 +/* down(&direntry->d_inode->i_sem);*/
15946 + /* need to write out dirty pages here */
15947 + if(direntry->d_inode->i_mapping) {
15948 + /* do we need to lock inode until after invalidate completes below? */
15949 + filemap_fdatasync(direntry->d_inode->i_mapping);
15950 + }
15951 + if(invalidate_inode) {
15952 + filemap_fdatawait(direntry->d_inode->i_mapping);
15953 + /* may eventually have to do this for open files too */
15954 + if(list_empty(&(cifsInode->openFileList))) {
15955 + /* Has changed on server - flush read ahead pages */
15956 + cFYI(1,("Invalidating read ahead data on closed file"));
15957 + invalidate_inode_pages(direntry->d_inode);
15958 + }
15959 + }
15960 +/* up(&direntry->d_inode->i_sem);*/
15961 +
15962 + if (full_path)
15963 + kfree(full_path);
15964 + FreeXid(xid);
15965 +
15966 + return rc;
15967 +}
15968 +
15969 +/* int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
15970 +{
15971 + int err = cifs_revalidate(dentry);
15972 + if (!err)
15973 + generic_fillattr(dentry->d_inode, stat);
15974 + return err;
15975 +} */
15976 +
15977 +void
15978 +cifs_truncate_file(struct inode *inode)
15979 +{ /* BB remove - may not need this function after all BB */
15980 + int xid;
15981 + int rc = -EIO;
15982 + int found = FALSE;
15983 + struct cifsFileInfo *open_file = NULL;
15984 + struct cifs_sb_info *cifs_sb;
15985 + struct cifsTconInfo *pTcon;
15986 + struct cifsInodeInfo *cifsInode;
15987 + struct dentry *dirent;
15988 + struct list_head * tmp;
15989 + char *full_path = NULL;
15990 +
15991 + xid = GetXid();
15992 +
15993 + cifs_sb = CIFS_SB(inode->i_sb);
15994 + pTcon = cifs_sb->tcon;
15995 +
15996 + /* To avoid spurious oplock breaks from server, in the case
15997 + of inodes that we already have open, avoid doing path
15998 + based setting of file size if we can do it by handle.
15999 + This keeps our caching token (oplock) and avoids
16000 + timeouts when the local oplock break takes longer to flush
16001 + writebehind data than the SMB timeout for the SetPathInfo
16002 + request would allow */
16003 + read_lock(&GlobalSMBSeslock);
16004 + cifsInode = CIFS_I(inode);
16005 + list_for_each(tmp, &cifsInode->openFileList) {
16006 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
16007 + /* We check if file is open for writing first */
16008 + if((open_file->pfile) && (!open_file->invalidHandle) &&
16009 + ((open_file->pfile->f_flags & O_RDWR) ||
16010 + (open_file->pfile->f_flags & O_WRONLY))) {
16011 + read_unlock(&GlobalSMBSeslock);
16012 + found = TRUE;
16013 + rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
16014 + open_file->netfid,open_file->pid,FALSE);
16015 + if(rc == 0) {
16016 + FreeXid(xid);
16017 + return;
16018 + }
16019 + /* Do not need reopen and retry on EAGAIN since we will
16020 + retry by pathname below */
16021 + if(rc == -EAGAIN)
16022 + rc = -EHOSTDOWN;
16023 +
16024 + break; /* now that we found one valid file handle no
16025 + sense continuing to loop trying others */
16026 + }
16027 + }
16028 + if(found == FALSE)
16029 + read_unlock(&GlobalSMBSeslock);
16030 +
16031 + if (list_empty(&inode->i_dentry)) {
16032 + cERROR(1,
16033 + ("Can not get pathname from empty dentry in inode 0x%p ",
16034 + inode));
16035 + FreeXid(xid);
16036 + return;
16037 + }
16038 +
16039 + dirent = list_entry(inode->i_dentry.next, struct dentry, d_alias);
16040 + if (dirent) {
16041 + full_path = build_path_from_dentry(dirent);
16042 + rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
16043 + cifs_sb->local_nls);
16044 + cFYI(1,(" SetEOF (truncate) rc = %d",rc));
16045 + if (!rc)
16046 + CIFSSMBSetEOF(xid,pTcon,full_path,inode->i_size,TRUE,cifs_sb->local_nls);
16047 + /* allocation size setting seems optional so ignore return code */
16048 + }
16049 + if (full_path)
16050 + kfree(full_path);
16051 + FreeXid(xid);
16052 + return;
16053 +}
16054 +
16055 +static int cifs_truncate_page(struct address_space *mapping, loff_t from)
16056 +{
16057 + unsigned long index = from >> PAGE_CACHE_SHIFT;
16058 + unsigned offset = from & (PAGE_CACHE_SIZE-1);
16059 + struct page *page;
16060 + char *kaddr;
16061 + int rc = 0;
16062 +
16063 + page = grab_cache_page(mapping, index);
16064 + if (!page)
16065 + return -ENOMEM;
16066 +
16067 + kaddr = kmap_atomic(page, KM_USER0);
16068 + memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
16069 + flush_dcache_page(page);
16070 + kunmap_atomic(kaddr, KM_USER0);
16071 + unlock_page(page);
16072 + page_cache_release(page);
16073 + return rc;
16074 +}
16075 +
16076 +int
16077 +cifs_setattr(struct dentry *direntry, struct iattr *attrs)
16078 +{
16079 + int xid;
16080 + struct cifs_sb_info *cifs_sb;
16081 + struct cifsTconInfo *pTcon;
16082 + char *full_path = NULL;
16083 + int rc = -EACCES;
16084 + int found = FALSE;
16085 + struct cifsFileInfo *open_file = NULL;
16086 + FILE_BASIC_INFO time_buf;
16087 + int set_time = FALSE;
16088 + __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
16089 + __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
16090 + __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
16091 + struct cifsInodeInfo *cifsInode;
16092 + struct list_head * tmp;
16093 +
16094 + xid = GetXid();
16095 +
16096 + cFYI(1,
16097 + (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
16098 + direntry->d_name.name, attrs->ia_valid));
16099 + cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
16100 + pTcon = cifs_sb->tcon;
16101 +
16102 + down(&direntry->d_sb->s_vfs_rename_sem);
16103 + full_path = build_path_from_dentry(direntry);
16104 + up(&direntry->d_sb->s_vfs_rename_sem);
16105 + if(full_path == NULL) {
16106 + FreeXid(xid);
16107 + return -ENOMEM;
16108 + }
16109 + cifsInode = CIFS_I(direntry->d_inode);
16110 +
16111 + /* BB check if we need to refresh inode from server now ? BB */
16112 +
16113 + /* need to flush data before changing file size on server */
16114 + filemap_fdatasync(direntry->d_inode->i_mapping);
16115 +
16116 + if (attrs->ia_valid & ATTR_SIZE) {
16117 + read_lock(&GlobalSMBSeslock);
16118 + /* To avoid spurious oplock breaks from server, in the case
16119 + of inodes that we already have open, avoid doing path
16120 + based setting of file size if we can do it by handle.
16121 + This keeps our caching token (oplock) and avoids
16122 + timeouts when the local oplock break takes longer to flush
16123 + writebehind data than the SMB timeout for the SetPathInfo
16124 + request would allow */
16125 + list_for_each(tmp, &cifsInode->openFileList) {
16126 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
16127 + /* We check if file is open for writing first */
16128 + if((open_file->pfile) &&
16129 + ((open_file->pfile->f_flags & O_RDWR) ||
16130 + (open_file->pfile->f_flags & O_WRONLY))) {
16131 + if(open_file->invalidHandle == FALSE) {
16132 + /* we found a valid, writeable network file
16133 + handle to use to try to set the file size */
16134 + __u16 nfid = open_file->netfid;
16135 + __u32 npid = open_file->pid;
16136 + read_unlock(&GlobalSMBSeslock);
16137 + found = TRUE;
16138 + rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
16139 + nfid,npid,FALSE);
16140 + cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
16141 + /* Do not need reopen and retry on EAGAIN since we will
16142 + retry by pathname below */
16143 +
16144 + break; /* now that we found one valid file handle no
16145 + sense continuing to loop trying others */
16146 + }
16147 + }
16148 + }
16149 + if(found == FALSE) {
16150 + read_unlock(&GlobalSMBSeslock);
16151 + }
16152 +
16153 +
16154 + if(rc != 0) {
16155 + /* Set file size by pathname rather than by handle either
16156 + because no valid, writeable file handle for it was found or
16157 + because there was an error setting it by handle */
16158 + rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
16159 + cifs_sb->local_nls);
16160 + cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
16161 + }
16162 +
16163 + /* Server is ok setting allocation size implicitly - no need to call: */
16164 + /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
16165 +
16166 + if (rc == 0) {
16167 + rc = vmtruncate(direntry->d_inode, attrs->ia_size);
16168 + cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
16169 + }
16170 + }
16171 + if (attrs->ia_valid & ATTR_UID) {
16172 + cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
16173 + uid = attrs->ia_uid;
16174 + /* entry->uid = cpu_to_le16(attr->ia_uid); */
16175 + }
16176 + if (attrs->ia_valid & ATTR_GID) {
16177 + cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
16178 + gid = attrs->ia_gid;
16179 + /* entry->gid = cpu_to_le16(attr->ia_gid); */
16180 + }
16181 +
16182 + time_buf.Attributes = 0;
16183 + if (attrs->ia_valid & ATTR_MODE) {
16184 + cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
16185 + mode = attrs->ia_mode;
16186 + /* entry->mode = cpu_to_le16(attr->ia_mode); */
16187 + }
16188 +
16189 + if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16190 + && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
16191 + rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
16192 + 0 /* dev_t */, cifs_sb->local_nls);
16193 + else if (attrs->ia_valid & ATTR_MODE) {
16194 + if((mode & S_IWUGO) == 0) /* not writeable */ {
16195 + if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
16196 + time_buf.Attributes =
16197 + cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
16198 + } else if((mode & S_IWUGO) == S_IWUGO) {
16199 + if(cifsInode->cifsAttrs & ATTR_READONLY)
16200 + time_buf.Attributes =
16201 + cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
16202 + }
16203 + /* BB to be implemented - via Windows security descriptors or streams */
16204 + /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
16205 + }
16206 +
16207 + if (attrs->ia_valid & ATTR_ATIME) {
16208 + set_time = TRUE;
16209 + time_buf.LastAccessTime =
16210 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
16211 + } else
16212 + time_buf.LastAccessTime = 0;
16213 +
16214 + if (attrs->ia_valid & ATTR_MTIME) {
16215 + set_time = TRUE;
16216 + time_buf.LastWriteTime =
16217 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
16218 + } else
16219 + time_buf.LastWriteTime = 0;
16220 +
16221 + if (attrs->ia_valid & ATTR_CTIME) {
16222 + set_time = TRUE;
16223 + time_buf.ChangeTime =
16224 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
16225 + } else
16226 + time_buf.ChangeTime = 0;
16227 +
16228 + if (set_time | time_buf.Attributes) {
16229 + /* BB what if setting one attribute fails
16230 + (such as size) but time setting works */
16231 + time_buf.CreationTime = 0; /* do not change */
16232 + /* In the future we should experiment - try setting timestamps
16233 + via Handle (SetFileInfo) instead of by path */
16234 + rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
16235 + cifs_sb->local_nls);
16236 + }
16237 +
16238 + /* do not need local check to inode_check_ok since the server does that */
16239 + if (!rc)
16240 + rc = inode_setattr(direntry->d_inode, attrs);
16241 + if (full_path)
16242 + kfree(full_path);
16243 + FreeXid(xid);
16244 + return rc;
16245 +}
16246 +
16247 +void
16248 +cifs_delete_inode(struct inode *inode)
16249 +{
16250 + cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
16251 + /* may have to add back in if and when safe distributed caching of
16252 + directories added e.g. via FindNotify */
16253 +}
16254 Index: linux-2.4.35.4/fs/cifs/link.c
16255 ===================================================================
16256 --- /dev/null
16257 +++ linux-2.4.35.4/fs/cifs/link.c
16258 @@ -0,0 +1,328 @@
16259 +/*
16260 + * fs/cifs/link.c
16261 + *
16262 + * Copyright (C) International Business Machines Corp., 2002,2003
16263 + * Author(s): Steve French (sfrench@us.ibm.com)
16264 + *
16265 + * This library is free software; you can redistribute it and/or modify
16266 + * it under the terms of the GNU Lesser General Public License as published
16267 + * by the Free Software Foundation; either version 2.1 of the License, or
16268 + * (at your option) any later version.
16269 + *
16270 + * This library is distributed in the hope that it will be useful,
16271 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16272 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16273 + * the GNU Lesser General Public License for more details.
16274 + *
16275 + * You should have received a copy of the GNU Lesser General Public License
16276 + * along with this library; if not, write to the Free Software
16277 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16278 + */
16279 +#include <linux/fs.h>
16280 +#include <linux/stat.h>
16281 +#include "cifsfs.h"
16282 +#include "cifspdu.h"
16283 +#include "cifsglob.h"
16284 +#include "cifsproto.h"
16285 +#include "cifs_debug.h"
16286 +#include "cifs_fs_sb.h"
16287 +
16288 +int
16289 +cifs_hardlink(struct dentry *old_file, struct inode *inode,
16290 + struct dentry *direntry)
16291 +{
16292 + int rc = -EACCES;
16293 + int xid;
16294 + char *fromName = NULL;
16295 + char *toName = NULL;
16296 + struct cifs_sb_info *cifs_sb_target;
16297 + struct cifsTconInfo *pTcon;
16298 + struct cifsInodeInfo *cifsInode;
16299 +
16300 + xid = GetXid();
16301 +
16302 + cifs_sb_target = CIFS_SB(inode->i_sb);
16303 + pTcon = cifs_sb_target->tcon;
16304 +
16305 +/* No need to check for cross device links since server will do that
16306 + BB note DFS case in future though (when we may have to check) */
16307 +
16308 + down(&inode->i_sb->s_vfs_rename_sem);
16309 + fromName = build_path_from_dentry(old_file);
16310 + toName = build_path_from_dentry(direntry);
16311 + up(&inode->i_sb->s_vfs_rename_sem);
16312 + if((fromName == NULL) || (toName == NULL)) {
16313 + rc = -ENOMEM;
16314 + goto cifs_hl_exit;
16315 + }
16316 +
16317 + if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
16318 + rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
16319 + cifs_sb_target->local_nls);
16320 + else {
16321 + rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
16322 + cifs_sb_target->local_nls);
16323 + if(rc == -EIO)
16324 + rc = -EOPNOTSUPP;
16325 + }
16326 +
16327 +/* if (!rc) */
16328 + {
16329 + /* renew_parental_timestamps(old_file);
16330 + inode->i_nlink++;
16331 + mark_inode_dirty(inode);
16332 + d_instantiate(direntry, inode); */
16333 + /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
16334 + }
16335 + d_drop(direntry); /* force new lookup from server */
16336 + cifsInode = CIFS_I(old_file->d_inode);
16337 + cifsInode->time = 0; /* will force revalidate to go get info when needed */
16338 +
16339 +cifs_hl_exit:
16340 + if (fromName)
16341 + kfree(fromName);
16342 + if (toName)
16343 + kfree(toName);
16344 + FreeXid(xid);
16345 + return rc;
16346 +}
16347 +
16348 +int
16349 +cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
16350 +{
16351 + struct inode *inode = direntry->d_inode;
16352 + int rc = -EACCES;
16353 + int xid;
16354 + char *full_path = NULL;
16355 + char * target_path;
16356 + struct cifs_sb_info *cifs_sb;
16357 + struct cifsTconInfo *pTcon;
16358 +
16359 + xid = GetXid();
16360 +
16361 + down(&direntry->d_sb->s_vfs_rename_sem);
16362 + full_path = build_path_from_dentry(direntry);
16363 + up(&direntry->d_sb->s_vfs_rename_sem);
16364 +
16365 + if(full_path == NULL) {
16366 + FreeXid(xid);
16367 + return -ENOMEM;
16368 + }
16369 + cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
16370 + cifs_sb = CIFS_SB(inode->i_sb);
16371 + pTcon = cifs_sb->tcon;
16372 + target_path = kmalloc(PATH_MAX, GFP_KERNEL);
16373 + if(target_path == NULL) {
16374 + if (full_path)
16375 + kfree(full_path);
16376 + FreeXid(xid);
16377 + return -ENOMEM;
16378 + }
16379 + /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
16380 + /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
16381 +
16382 +/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
16383 + if (pTcon->ses->capabilities & CAP_UNIX)
16384 + rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
16385 + target_path,
16386 + PATH_MAX-1,
16387 + cifs_sb->local_nls);
16388 + else {
16389 + /* rc = CIFSSMBQueryReparseLinkInfo */
16390 + /* BB Add code to Query ReparsePoint info */
16391 + }
16392 + /* BB Anything else to do to handle recursive links? */
16393 + /* BB Should we be using page symlink ops here? */
16394 +
16395 + if (rc == 0) {
16396 +
16397 +/* BB Add special case check for Samba DFS symlinks */
16398 +
16399 + target_path[PATH_MAX-1] = 0;
16400 + rc = vfs_follow_link(nd, target_path);
16401 + }
16402 + /* else EACCESS */
16403 +
16404 + if (target_path)
16405 + kfree(target_path);
16406 + if (full_path)
16407 + kfree(full_path);
16408 + FreeXid(xid);
16409 + return rc;
16410 +}
16411 +
16412 +int
16413 +cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
16414 +{
16415 + int rc = -EOPNOTSUPP;
16416 + int xid;
16417 + struct cifs_sb_info *cifs_sb;
16418 + struct cifsTconInfo *pTcon;
16419 + char *full_path = NULL;
16420 + struct inode *newinode = NULL;
16421 +
16422 + xid = GetXid();
16423 +
16424 + cifs_sb = CIFS_SB(inode->i_sb);
16425 + pTcon = cifs_sb->tcon;
16426 +
16427 + down(&inode->i_sb->s_vfs_rename_sem);
16428 + full_path = build_path_from_dentry(direntry);
16429 + up(&inode->i_sb->s_vfs_rename_sem);
16430 +
16431 + if(full_path == NULL) {
16432 + FreeXid(xid);
16433 + return -ENOMEM;
16434 + }
16435 +
16436 + cFYI(1, ("Full path: %s ", full_path));
16437 + cFYI(1, ("symname is %s", symname));
16438 +
16439 + /* BB what if DFS and this volume is on different share? BB */
16440 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16441 + rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
16442 + cifs_sb->local_nls);
16443 + /* else
16444 + rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
16445 +
16446 + if (rc == 0) {
16447 + if (pTcon->ses->capabilities & CAP_UNIX)
16448 + rc = cifs_get_inode_info_unix(&newinode, full_path,
16449 + inode->i_sb,xid);
16450 + else
16451 + rc = cifs_get_inode_info(&newinode, full_path, NULL,
16452 + inode->i_sb,xid);
16453 +
16454 + if (rc != 0) {
16455 + cFYI(1,
16456 + ("Create symlink worked but get_inode_info failed with rc = %d ",
16457 + rc));
16458 + } else {
16459 + direntry->d_op = &cifs_dentry_ops;
16460 + d_instantiate(direntry, newinode);
16461 + }
16462 + }
16463 +
16464 + if (full_path)
16465 + kfree(full_path);
16466 + FreeXid(xid);
16467 + return rc;
16468 +}
16469 +
16470 +int
16471 +cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
16472 +{
16473 + struct inode *inode = direntry->d_inode;
16474 + int rc = -EACCES;
16475 + int xid;
16476 + int oplock = FALSE;
16477 + struct cifs_sb_info *cifs_sb;
16478 + struct cifsTconInfo *pTcon;
16479 + char *full_path = NULL;
16480 + char *tmp_path = NULL;
16481 + char * tmpbuffer;
16482 + unsigned char * referrals = NULL;
16483 + int num_referrals = 0;
16484 + int len;
16485 + __u16 fid;
16486 +
16487 + xid = GetXid();
16488 + cifs_sb = CIFS_SB(inode->i_sb);
16489 + pTcon = cifs_sb->tcon;
16490 +
16491 +/* BB would it be safe against deadlock to grab this sem
16492 + even though rename itself grabs the sem and calls lookup? */
16493 +/* down(&inode->i_sb->s_vfs_rename_sem);*/
16494 + full_path = build_path_from_dentry(direntry);
16495 +/* up(&inode->i_sb->s_vfs_rename_sem);*/
16496 +
16497 + if(full_path == NULL) {
16498 + FreeXid(xid);
16499 + return -ENOMEM;
16500 + }
16501 +
16502 + cFYI(1,
16503 + ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
16504 + full_path, inode, pBuffer, buflen));
16505 + if(buflen > PATH_MAX)
16506 + len = PATH_MAX;
16507 + else
16508 + len = buflen;
16509 + tmpbuffer = kmalloc(len,GFP_KERNEL);
16510 + if(tmpbuffer == NULL) {
16511 + if (full_path)
16512 + kfree(full_path);
16513 + FreeXid(xid);
16514 + return -ENOMEM;
16515 + }
16516 +
16517 +/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
16518 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16519 + rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
16520 + tmpbuffer,
16521 + len - 1,
16522 + cifs_sb->local_nls);
16523 + else {
16524 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
16525 + OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
16526 + if(!rc) {
16527 + rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
16528 + tmpbuffer,
16529 + len - 1,
16530 + fid,
16531 + cifs_sb->local_nls);
16532 + if(CIFSSMBClose(xid, pTcon, fid)) {
16533 + cFYI(1,("Error closing junction point (open for ioctl)"));
16534 + }
16535 + if(rc == -EIO) {
16536 + /* Query if DFS Junction */
16537 + tmp_path =
16538 + kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
16539 + GFP_KERNEL);
16540 + if (tmp_path) {
16541 + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
16542 + strncat(tmp_path, full_path, MAX_PATHCONF);
16543 + rc = get_dfs_path(xid, pTcon->ses, tmp_path,
16544 + cifs_sb->local_nls, &num_referrals, &referrals);
16545 + cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
16546 + if((num_referrals == 0) && (rc == 0))
16547 + rc = -EACCES;
16548 + else {
16549 + cFYI(1,("num referral: %d",num_referrals));
16550 + if(referrals) {
16551 + cFYI(1,("referral string: %s ",referrals));
16552 + strncpy(tmpbuffer, referrals, len-1);
16553 + }
16554 + }
16555 + if(referrals)
16556 + kfree(referrals);
16557 + kfree(tmp_path);
16558 + if(referrals) {
16559 + kfree(referrals);
16560 + }
16561 + }
16562 + /* BB add code like else decode referrals then memcpy to
16563 + tmpbuffer and free referrals string array BB */
16564 + }
16565 + }
16566 + }
16567 + /* BB Anything else to do to handle recursive links? */
16568 + /* BB Should we be using page ops here? */
16569 +
16570 + /* BB null terminate returned string in pBuffer? BB */
16571 + if (rc == 0) {
16572 + rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
16573 + cFYI(1,
16574 + ("vfs_readlink called from cifs_readlink returned %d",
16575 + rc));
16576 + }
16577 +
16578 + if (tmpbuffer) {
16579 + kfree(tmpbuffer);
16580 + }
16581 + if (full_path) {
16582 + kfree(full_path);
16583 + }
16584 + FreeXid(xid);
16585 + return rc;
16586 +}
16587 Index: linux-2.4.35.4/fs/cifs/Makefile
16588 ===================================================================
16589 --- /dev/null
16590 +++ linux-2.4.35.4/fs/cifs/Makefile
16591 @@ -0,0 +1,10 @@
16592 +#
16593 +# Makefile for Linux CIFS VFS client
16594 +#
16595 +O_TARGET := cifs.o
16596 +
16597 +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
16598 +
16599 +obj-m := $(O_TARGET)
16600 +
16601 +include $(TOPDIR)/Rules.make
16602 Index: linux-2.4.35.4/fs/cifs/md4.c
16603 ===================================================================
16604 --- /dev/null
16605 +++ linux-2.4.35.4/fs/cifs/md4.c
16606 @@ -0,0 +1,203 @@
16607 +/*
16608 + Unix SMB/Netbios implementation.
16609 + Version 1.9.
16610 + a implementation of MD4 designed for use in the SMB authentication protocol
16611 + Copyright (C) Andrew Tridgell 1997-1998.
16612 + Modified by Steve French (sfrench@us.ibm.com) 2002-2003
16613 +
16614 + This program is free software; you can redistribute it and/or modify
16615 + it under the terms of the GNU General Public License as published by
16616 + the Free Software Foundation; either version 2 of the License, or
16617 + (at your option) any later version.
16618 +
16619 + This program is distributed in the hope that it will be useful,
16620 + but WITHOUT ANY WARRANTY; without even the implied warranty of
16621 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16622 + GNU General Public License for more details.
16623 +
16624 + You should have received a copy of the GNU General Public License
16625 + along with this program; if not, write to the Free Software
16626 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16627 +*/
16628 +#include <linux/module.h>
16629 +#include <linux/fs.h>
16630 +/* NOTE: This code makes no attempt to be fast! */
16631 +
16632 +static __u32
16633 +F(__u32 X, __u32 Y, __u32 Z)
16634 +{
16635 + return (X & Y) | ((~X) & Z);
16636 +}
16637 +
16638 +static __u32
16639 +G(__u32 X, __u32 Y, __u32 Z)
16640 +{
16641 + return (X & Y) | (X & Z) | (Y & Z);
16642 +}
16643 +
16644 +static __u32
16645 +H(__u32 X, __u32 Y, __u32 Z)
16646 +{
16647 + return X ^ Y ^ Z;
16648 +}
16649 +
16650 +static __u32
16651 +lshift(__u32 x, int s)
16652 +{
16653 + x &= 0xFFFFFFFF;
16654 + return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
16655 +}
16656 +
16657 +#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
16658 +#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
16659 +#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
16660 +
16661 +/* this applies md4 to 64 byte chunks */
16662 +static void
16663 +mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
16664 +{
16665 + int j;
16666 + __u32 AA, BB, CC, DD;
16667 + __u32 X[16];
16668 +
16669 +
16670 + for (j = 0; j < 16; j++)
16671 + X[j] = M[j];
16672 +
16673 + AA = *A;
16674 + BB = *B;
16675 + CC = *C;
16676 + DD = *D;
16677 +
16678 + ROUND1(A, B, C, D, 0, 3);
16679 + ROUND1(D, A, B, C, 1, 7);
16680 + ROUND1(C, D, A, B, 2, 11);
16681 + ROUND1(B, C, D, A, 3, 19);
16682 + ROUND1(A, B, C, D, 4, 3);
16683 + ROUND1(D, A, B, C, 5, 7);
16684 + ROUND1(C, D, A, B, 6, 11);
16685 + ROUND1(B, C, D, A, 7, 19);
16686 + ROUND1(A, B, C, D, 8, 3);
16687 + ROUND1(D, A, B, C, 9, 7);
16688 + ROUND1(C, D, A, B, 10, 11);
16689 + ROUND1(B, C, D, A, 11, 19);
16690 + ROUND1(A, B, C, D, 12, 3);
16691 + ROUND1(D, A, B, C, 13, 7);
16692 + ROUND1(C, D, A, B, 14, 11);
16693 + ROUND1(B, C, D, A, 15, 19);
16694 +
16695 + ROUND2(A, B, C, D, 0, 3);
16696 + ROUND2(D, A, B, C, 4, 5);
16697 + ROUND2(C, D, A, B, 8, 9);
16698 + ROUND2(B, C, D, A, 12, 13);
16699 + ROUND2(A, B, C, D, 1, 3);
16700 + ROUND2(D, A, B, C, 5, 5);
16701 + ROUND2(C, D, A, B, 9, 9);
16702 + ROUND2(B, C, D, A, 13, 13);
16703 + ROUND2(A, B, C, D, 2, 3);
16704 + ROUND2(D, A, B, C, 6, 5);
16705 + ROUND2(C, D, A, B, 10, 9);
16706 + ROUND2(B, C, D, A, 14, 13);
16707 + ROUND2(A, B, C, D, 3, 3);
16708 + ROUND2(D, A, B, C, 7, 5);
16709 + ROUND2(C, D, A, B, 11, 9);
16710 + ROUND2(B, C, D, A, 15, 13);
16711 +
16712 + ROUND3(A, B, C, D, 0, 3);
16713 + ROUND3(D, A, B, C, 8, 9);
16714 + ROUND3(C, D, A, B, 4, 11);
16715 + ROUND3(B, C, D, A, 12, 15);
16716 + ROUND3(A, B, C, D, 2, 3);
16717 + ROUND3(D, A, B, C, 10, 9);
16718 + ROUND3(C, D, A, B, 6, 11);
16719 + ROUND3(B, C, D, A, 14, 15);
16720 + ROUND3(A, B, C, D, 1, 3);
16721 + ROUND3(D, A, B, C, 9, 9);
16722 + ROUND3(C, D, A, B, 5, 11);
16723 + ROUND3(B, C, D, A, 13, 15);
16724 + ROUND3(A, B, C, D, 3, 3);
16725 + ROUND3(D, A, B, C, 11, 9);
16726 + ROUND3(C, D, A, B, 7, 11);
16727 + ROUND3(B, C, D, A, 15, 15);
16728 +
16729 + *A += AA;
16730 + *B += BB;
16731 + *C += CC;
16732 + *D += DD;
16733 +
16734 + *A &= 0xFFFFFFFF;
16735 + *B &= 0xFFFFFFFF;
16736 + *C &= 0xFFFFFFFF;
16737 + *D &= 0xFFFFFFFF;
16738 +
16739 + for (j = 0; j < 16; j++)
16740 + X[j] = 0;
16741 +}
16742 +
16743 +static void
16744 +copy64(__u32 * M, unsigned char *in)
16745 +{
16746 + int i;
16747 +
16748 + for (i = 0; i < 16; i++)
16749 + M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
16750 + (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
16751 +}
16752 +
16753 +static void
16754 +copy4(unsigned char *out, __u32 x)
16755 +{
16756 + out[0] = x & 0xFF;
16757 + out[1] = (x >> 8) & 0xFF;
16758 + out[2] = (x >> 16) & 0xFF;
16759 + out[3] = (x >> 24) & 0xFF;
16760 +}
16761 +
16762 +/* produce a md4 message digest from data of length n bytes */
16763 +void
16764 +mdfour(unsigned char *out, unsigned char *in, int n)
16765 +{
16766 + unsigned char buf[128];
16767 + __u32 M[16];
16768 + __u32 b = n * 8;
16769 + int i;
16770 + __u32 A = 0x67452301;
16771 + __u32 B = 0xefcdab89;
16772 + __u32 C = 0x98badcfe;
16773 + __u32 D = 0x10325476;
16774 +
16775 + while (n > 64) {
16776 + copy64(M, in);
16777 + mdfour64(M,&A,&B, &C, &D);
16778 + in += 64;
16779 + n -= 64;
16780 + }
16781 +
16782 + for (i = 0; i < 128; i++)
16783 + buf[i] = 0;
16784 + memcpy(buf, in, n);
16785 + buf[n] = 0x80;
16786 +
16787 + if (n <= 55) {
16788 + copy4(buf + 56, b);
16789 + copy64(M, buf);
16790 + mdfour64(M, &A, &B, &C, &D);
16791 + } else {
16792 + copy4(buf + 120, b);
16793 + copy64(M, buf);
16794 + mdfour64(M, &A, &B, &C, &D);
16795 + copy64(M, buf + 64);
16796 + mdfour64(M, &A, &B, &C, &D);
16797 + }
16798 +
16799 + for (i = 0; i < 128; i++)
16800 + buf[i] = 0;
16801 + copy64(M, buf);
16802 +
16803 + copy4(out, A);
16804 + copy4(out + 4, B);
16805 + copy4(out + 8, C);
16806 + copy4(out + 12, D);
16807 +
16808 + A = B = C = D = 0;
16809 +}
16810 Index: linux-2.4.35.4/fs/cifs/md5.c
16811 ===================================================================
16812 --- /dev/null
16813 +++ linux-2.4.35.4/fs/cifs/md5.c
16814 @@ -0,0 +1,363 @@
16815 +/*
16816 + * This code implements the MD5 message-digest algorithm.
16817 + * The algorithm is due to Ron Rivest. This code was
16818 + * written by Colin Plumb in 1993, no copyright is claimed.
16819 + * This code is in the public domain; do with it what you wish.
16820 + *
16821 + * Equivalent code is available from RSA Data Security, Inc.
16822 + * This code has been tested against that, and is equivalent,
16823 + * except that you don't need to include two pages of legalese
16824 + * with every copy.
16825 + *
16826 + * To compute the message digest of a chunk of bytes, declare an
16827 + * MD5Context structure, pass it to MD5Init, call MD5Update as
16828 + * needed on buffers full of bytes, and then call MD5Final, which
16829 + * will fill a supplied 16-byte array with the digest.
16830 + */
16831 +
16832 +/* This code slightly modified to fit into Samba by
16833 + abartlet@samba.org Jun 2001
16834 + and to fit the cifs vfs by
16835 + Steve French sfrench@us.ibm.com */
16836 +
16837 +#include <linux/string.h>
16838 +#include "md5.h"
16839 +
16840 +static void MD5Transform(__u32 buf[4], __u32 const in[16]);
16841 +
16842 +/*
16843 + * Note: this code is harmless on little-endian machines.
16844 + */
16845 +static void
16846 +byteReverse(unsigned char *buf, unsigned longs)
16847 +{
16848 + __u32 t;
16849 + do {
16850 + t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
16851 + ((unsigned) buf[1] << 8 | buf[0]);
16852 + *(__u32 *) buf = t;
16853 + buf += 4;
16854 + } while (--longs);
16855 +}
16856 +
16857 +/*
16858 + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
16859 + * initialization constants.
16860 + */
16861 +void
16862 +MD5Init(struct MD5Context *ctx)
16863 +{
16864 + ctx->buf[0] = 0x67452301;
16865 + ctx->buf[1] = 0xefcdab89;
16866 + ctx->buf[2] = 0x98badcfe;
16867 + ctx->buf[3] = 0x10325476;
16868 +
16869 + ctx->bits[0] = 0;
16870 + ctx->bits[1] = 0;
16871 +}
16872 +
16873 +/*
16874 + * Update context to reflect the concatenation of another buffer full
16875 + * of bytes.
16876 + */
16877 +void
16878 +MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
16879 +{
16880 + register __u32 t;
16881 +
16882 + /* Update bitcount */
16883 +
16884 + t = ctx->bits[0];
16885 + if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
16886 + ctx->bits[1]++; /* Carry from low to high */
16887 + ctx->bits[1] += len >> 29;
16888 +
16889 + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
16890 +
16891 + /* Handle any leading odd-sized chunks */
16892 +
16893 + if (t) {
16894 + unsigned char *p = (unsigned char *) ctx->in + t;
16895 +
16896 + t = 64 - t;
16897 + if (len < t) {
16898 + memmove(p, buf, len);
16899 + return;
16900 + }
16901 + memmove(p, buf, t);
16902 + byteReverse(ctx->in, 16);
16903 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16904 + buf += t;
16905 + len -= t;
16906 + }
16907 + /* Process data in 64-byte chunks */
16908 +
16909 + while (len >= 64) {
16910 + memmove(ctx->in, buf, 64);
16911 + byteReverse(ctx->in, 16);
16912 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16913 + buf += 64;
16914 + len -= 64;
16915 + }
16916 +
16917 + /* Handle any remaining bytes of data. */
16918 +
16919 + memmove(ctx->in, buf, len);
16920 +}
16921 +
16922 +/*
16923 + * Final wrapup - pad to 64-byte boundary with the bit pattern
16924 + * 1 0* (64-bit count of bits processed, MSB-first)
16925 + */
16926 +void
16927 +MD5Final(unsigned char digest[16], struct MD5Context *ctx)
16928 +{
16929 + unsigned int count;
16930 + unsigned char *p;
16931 +
16932 + /* Compute number of bytes mod 64 */
16933 + count = (ctx->bits[0] >> 3) & 0x3F;
16934 +
16935 + /* Set the first char of padding to 0x80. This is safe since there is
16936 + always at least one byte free */
16937 + p = ctx->in + count;
16938 + *p++ = 0x80;
16939 +
16940 + /* Bytes of padding needed to make 64 bytes */
16941 + count = 64 - 1 - count;
16942 +
16943 + /* Pad out to 56 mod 64 */
16944 + if (count < 8) {
16945 + /* Two lots of padding: Pad the first block to 64 bytes */
16946 + memset(p, 0, count);
16947 + byteReverse(ctx->in, 16);
16948 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16949 +
16950 + /* Now fill the next block with 56 bytes */
16951 + memset(ctx->in, 0, 56);
16952 + } else {
16953 + /* Pad block to 56 bytes */
16954 + memset(p, 0, count - 8);
16955 + }
16956 + byteReverse(ctx->in, 14);
16957 +
16958 + /* Append length in bits and transform */
16959 + ((__u32 *) ctx->in)[14] = ctx->bits[0];
16960 + ((__u32 *) ctx->in)[15] = ctx->bits[1];
16961 +
16962 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16963 + byteReverse((unsigned char *) ctx->buf, 4);
16964 + memmove(digest, ctx->buf, 16);
16965 + memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
16966 +}
16967 +
16968 +/* The four core functions - F1 is optimized somewhat */
16969 +
16970 +/* #define F1(x, y, z) (x & y | ~x & z) */
16971 +#define F1(x, y, z) (z ^ (x & (y ^ z)))
16972 +#define F2(x, y, z) F1(z, x, y)
16973 +#define F3(x, y, z) (x ^ y ^ z)
16974 +#define F4(x, y, z) (y ^ (x | ~z))
16975 +
16976 +/* This is the central step in the MD5 algorithm. */
16977 +#define MD5STEP(f, w, x, y, z, data, s) \
16978 + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
16979 +
16980 +/*
16981 + * The core of the MD5 algorithm, this alters an existing MD5 hash to
16982 + * reflect the addition of 16 longwords of new data. MD5Update blocks
16983 + * the data and converts bytes into longwords for this routine.
16984 + */
16985 +static void
16986 +MD5Transform(__u32 buf[4], __u32 const in[16])
16987 +{
16988 + register __u32 a, b, c, d;
16989 +
16990 + a = buf[0];
16991 + b = buf[1];
16992 + c = buf[2];
16993 + d = buf[3];
16994 +
16995 + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
16996 + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
16997 + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
16998 + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
16999 + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
17000 + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
17001 + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
17002 + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
17003 + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
17004 + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
17005 + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
17006 + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
17007 + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
17008 + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
17009 + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
17010 + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
17011 +
17012 + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
17013 + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
17014 + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
17015 + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
17016 + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
17017 + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
17018 + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
17019 + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
17020 + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
17021 + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
17022 + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
17023 + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
17024 + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
17025 + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
17026 + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
17027 + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
17028 +
17029 + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
17030 + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
17031 + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
17032 + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
17033 + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
17034 + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
17035 + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
17036 + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
17037 + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
17038 + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
17039 + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
17040 + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
17041 + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
17042 + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
17043 + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
17044 + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
17045 +
17046 + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
17047 + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
17048 + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
17049 + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
17050 + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
17051 + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
17052 + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
17053 + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
17054 + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
17055 + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
17056 + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
17057 + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
17058 + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
17059 + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
17060 + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
17061 + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
17062 +
17063 + buf[0] += a;
17064 + buf[1] += b;
17065 + buf[2] += c;
17066 + buf[3] += d;
17067 +}
17068 +
17069 +/***********************************************************************
17070 + the rfc 2104 version of hmac_md5 initialisation.
17071 +***********************************************************************/
17072 +void
17073 +hmac_md5_init_rfc2104(unsigned char *key, int key_len,
17074 + struct HMACMD5Context *ctx)
17075 +{
17076 + int i;
17077 +
17078 + /* if key is longer than 64 bytes reset it to key=MD5(key) */
17079 + if (key_len > 64) {
17080 + unsigned char tk[16];
17081 + struct MD5Context tctx;
17082 +
17083 + MD5Init(&tctx);
17084 + MD5Update(&tctx, key, key_len);
17085 + MD5Final(tk, &tctx);
17086 +
17087 + key = tk;
17088 + key_len = 16;
17089 + }
17090 +
17091 + /* start out by storing key in pads */
17092 + memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
17093 + memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
17094 + memcpy(ctx->k_ipad, key, key_len);
17095 + memcpy(ctx->k_opad, key, key_len);
17096 +
17097 + /* XOR key with ipad and opad values */
17098 + for (i = 0; i < 64; i++) {
17099 + ctx->k_ipad[i] ^= 0x36;
17100 + ctx->k_opad[i] ^= 0x5c;
17101 + }
17102 +
17103 + MD5Init(&ctx->ctx);
17104 + MD5Update(&ctx->ctx, ctx->k_ipad, 64);
17105 +}
17106 +
17107 +/***********************************************************************
17108 + the microsoft version of hmac_md5 initialisation.
17109 +***********************************************************************/
17110 +void
17111 +hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
17112 + struct HMACMD5Context *ctx)
17113 +{
17114 + int i;
17115 +
17116 + /* if key is longer than 64 bytes truncate it */
17117 + if (key_len > 64) {
17118 + key_len = 64;
17119 + }
17120 +
17121 + /* start out by storing key in pads */
17122 + memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
17123 + memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
17124 + memcpy(ctx->k_ipad, key, key_len);
17125 + memcpy(ctx->k_opad, key, key_len);
17126 +
17127 + /* XOR key with ipad and opad values */
17128 + for (i = 0; i < 64; i++) {
17129 + ctx->k_ipad[i] ^= 0x36;
17130 + ctx->k_opad[i] ^= 0x5c;
17131 + }
17132 +
17133 + MD5Init(&ctx->ctx);
17134 + MD5Update(&ctx->ctx, ctx->k_ipad, 64);
17135 +}
17136 +
17137 +/***********************************************************************
17138 + update hmac_md5 "inner" buffer
17139 +***********************************************************************/
17140 +void
17141 +hmac_md5_update(const unsigned char *text, int text_len,
17142 + struct HMACMD5Context *ctx)
17143 +{
17144 + MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
17145 +}
17146 +
17147 +/***********************************************************************
17148 + finish off hmac_md5 "inner" buffer and generate outer one.
17149 +***********************************************************************/
17150 +void
17151 +hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
17152 +{
17153 + struct MD5Context ctx_o;
17154 +
17155 + MD5Final(digest, &ctx->ctx);
17156 +
17157 + MD5Init(&ctx_o);
17158 + MD5Update(&ctx_o, ctx->k_opad, 64);
17159 + MD5Update(&ctx_o, digest, 16);
17160 + MD5Final(digest, &ctx_o);
17161 +}
17162 +
17163 +/***********************************************************
17164 + single function to calculate an HMAC MD5 digest from data.
17165 + use the microsoft hmacmd5 init method because the key is 16 bytes.
17166 +************************************************************/
17167 +void
17168 +hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
17169 + unsigned char *digest)
17170 +{
17171 + struct HMACMD5Context ctx;
17172 + hmac_md5_init_limK_to_64(key, 16, &ctx);
17173 + if (data_len != 0) {
17174 + hmac_md5_update(data, data_len, &ctx);
17175 + }
17176 + hmac_md5_final(digest, &ctx);
17177 +}
17178 Index: linux-2.4.35.4/fs/cifs/md5.h
17179 ===================================================================
17180 --- /dev/null
17181 +++ linux-2.4.35.4/fs/cifs/md5.h
17182 @@ -0,0 +1,38 @@
17183 +#ifndef MD5_H
17184 +#define MD5_H
17185 +#ifndef HEADER_MD5_H
17186 +/* Try to avoid clashes with OpenSSL */
17187 +#define HEADER_MD5_H
17188 +#endif
17189 +
17190 +struct MD5Context {
17191 + __u32 buf[4];
17192 + __u32 bits[2];
17193 + unsigned char in[64];
17194 +};
17195 +#endif /* !MD5_H */
17196 +
17197 +#ifndef _HMAC_MD5_H
17198 +struct HMACMD5Context {
17199 + struct MD5Context ctx;
17200 + unsigned char k_ipad[65];
17201 + unsigned char k_opad[65];
17202 +};
17203 +#endif /* _HMAC_MD5_H */
17204 +
17205 +void MD5Init(struct MD5Context *context);
17206 +void MD5Update(struct MD5Context *context, unsigned char const *buf,
17207 + unsigned len);
17208 +void MD5Final(unsigned char digest[16], struct MD5Context *context);
17209 +
17210 +/* The following definitions come from lib/hmacmd5.c */
17211 +
17212 +void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
17213 + struct HMACMD5Context *ctx);
17214 +void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
17215 + struct HMACMD5Context *ctx);
17216 +void hmac_md5_update(const unsigned char *text, int text_len,
17217 + struct HMACMD5Context *ctx);
17218 +void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
17219 +void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
17220 + unsigned char *digest);
17221 Index: linux-2.4.35.4/fs/cifs/misc.c
17222 ===================================================================
17223 --- /dev/null
17224 +++ linux-2.4.35.4/fs/cifs/misc.c
17225 @@ -0,0 +1,463 @@
17226 +/*
17227 + * fs/cifs/misc.c
17228 + *
17229 + * Copyright (C) International Business Machines Corp., 2002,2003
17230 + * Author(s): Steve French (sfrench@us.ibm.com)
17231 + *
17232 + * This library is free software; you can redistribute it and/or modify
17233 + * it under the terms of the GNU Lesser General Public License as published
17234 + * by the Free Software Foundation; either version 2.1 of the License, or
17235 + * (at your option) any later version.
17236 + *
17237 + * This library is distributed in the hope that it will be useful,
17238 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17239 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17240 + * the GNU Lesser General Public License for more details.
17241 + *
17242 + * You should have received a copy of the GNU Lesser General Public License
17243 + * along with this library; if not, write to the Free Software
17244 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17245 + */
17246 +
17247 +#include <linux/slab.h>
17248 +#include <linux/ctype.h>
17249 +#include "cifspdu.h"
17250 +#include "cifsglob.h"
17251 +#include "cifsproto.h"
17252 +#include "cifs_debug.h"
17253 +#include "smberr.h"
17254 +#include "nterr.h"
17255 +
17256 +extern kmem_cache_t *cifs_req_cachep;
17257 +extern struct task_struct * oplockThread;
17258 +
17259 +__u16 GlobalMid; /* multiplex id - rotating counter */
17260 +
17261 +/* The xid serves as a useful identifier for each incoming vfs request,
17262 + in a similar way to the mid which is useful to track each sent smb,
17263 + and CurrentXid can also provide a running counter (although it
17264 + will eventually wrap past zero) of the total vfs operations handled
17265 + since the cifs fs was mounted */
17266 +
17267 +unsigned int
17268 +_GetXid(void)
17269 +{
17270 + unsigned int xid;
17271 +
17272 + spin_lock(&GlobalMid_Lock);
17273 + GlobalTotalActiveXid++;
17274 + if (GlobalTotalActiveXid > GlobalMaxActiveXid)
17275 + GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
17276 + xid = GlobalCurrentXid++;
17277 + spin_unlock(&GlobalMid_Lock);
17278 + return xid;
17279 +}
17280 +
17281 +void
17282 +_FreeXid(unsigned int xid)
17283 +{
17284 + spin_lock(&GlobalMid_Lock);
17285 + /* if(GlobalTotalActiveXid == 0)
17286 + BUG(); */
17287 + GlobalTotalActiveXid--;
17288 + spin_unlock(&GlobalMid_Lock);
17289 +}
17290 +
17291 +struct cifsSesInfo *
17292 +sesInfoAlloc(void)
17293 +{
17294 + struct cifsSesInfo *ret_buf;
17295 +
17296 + ret_buf =
17297 + (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
17298 + GFP_KERNEL);
17299 + if (ret_buf) {
17300 + memset(ret_buf, 0, sizeof (struct cifsSesInfo));
17301 + write_lock(&GlobalSMBSeslock);
17302 + atomic_inc(&sesInfoAllocCount);
17303 + ret_buf->status = CifsNew;
17304 + list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
17305 + init_MUTEX(&ret_buf->sesSem);
17306 + write_unlock(&GlobalSMBSeslock);
17307 + }
17308 + return ret_buf;
17309 +}
17310 +
17311 +void
17312 +sesInfoFree(struct cifsSesInfo *buf_to_free)
17313 +{
17314 + if (buf_to_free == NULL) {
17315 + cFYI(1, ("Null buffer passed to sesInfoFree"));
17316 + return;
17317 + }
17318 +
17319 + write_lock(&GlobalSMBSeslock);
17320 + atomic_dec(&sesInfoAllocCount);
17321 + list_del(&buf_to_free->cifsSessionList);
17322 + write_unlock(&GlobalSMBSeslock);
17323 + if (buf_to_free->serverOS)
17324 + kfree(buf_to_free->serverOS);
17325 + if (buf_to_free->serverDomain)
17326 + kfree(buf_to_free->serverDomain);
17327 + if (buf_to_free->serverNOS)
17328 + kfree(buf_to_free->serverNOS);
17329 + if (buf_to_free->password)
17330 + kfree(buf_to_free->password);
17331 + kfree(buf_to_free);
17332 +}
17333 +
17334 +struct cifsTconInfo *
17335 +tconInfoAlloc(void)
17336 +{
17337 + struct cifsTconInfo *ret_buf;
17338 + ret_buf =
17339 + (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
17340 + GFP_KERNEL);
17341 + if (ret_buf) {
17342 + memset(ret_buf, 0, sizeof (struct cifsTconInfo));
17343 + write_lock(&GlobalSMBSeslock);
17344 + atomic_inc(&tconInfoAllocCount);
17345 + list_add(&ret_buf->cifsConnectionList,
17346 + &GlobalTreeConnectionList);
17347 + ret_buf->tidStatus = CifsNew;
17348 + INIT_LIST_HEAD(&ret_buf->openFileList);
17349 + init_MUTEX(&ret_buf->tconSem);
17350 +#ifdef CONFIG_CIFS_STATS
17351 + ret_buf->stat_lock = SPIN_LOCK_UNLOCKED;
17352 +#endif
17353 + write_unlock(&GlobalSMBSeslock);
17354 + }
17355 + return ret_buf;
17356 +}
17357 +
17358 +void
17359 +tconInfoFree(struct cifsTconInfo *buf_to_free)
17360 +{
17361 + if (buf_to_free == NULL) {
17362 + cFYI(1, ("Null buffer passed to tconInfoFree"));
17363 + return;
17364 + }
17365 + write_lock(&GlobalSMBSeslock);
17366 + atomic_dec(&tconInfoAllocCount);
17367 + list_del(&buf_to_free->cifsConnectionList);
17368 + write_unlock(&GlobalSMBSeslock);
17369 + if (buf_to_free->nativeFileSystem)
17370 + kfree(buf_to_free->nativeFileSystem);
17371 + kfree(buf_to_free);
17372 +}
17373 +
17374 +struct smb_hdr *
17375 +cifs_buf_get(void)
17376 +{
17377 + struct smb_hdr *ret_buf = NULL;
17378 +
17379 +/* We could use negotiated size instead of max_msgsize -
17380 + but it may be more efficient to always alloc same size
17381 + albeit slightly larger than necessary and maxbuffersize
17382 + defaults to this and can not be bigger */
17383 + ret_buf =
17384 + (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
17385 +
17386 + /* clear the first few header bytes */
17387 + if (ret_buf) {
17388 + memset(ret_buf, 0, sizeof (struct smb_hdr));
17389 + atomic_inc(&bufAllocCount);
17390 + }
17391 +
17392 + return ret_buf;
17393 +}
17394 +
17395 +void
17396 +cifs_buf_release(void *buf_to_free)
17397 +{
17398 +
17399 + if (buf_to_free == NULL) {
17400 + cFYI(1, ("Null buffer passed to cifs_buf_release"));
17401 + return;
17402 + }
17403 + kmem_cache_free(cifs_req_cachep, buf_to_free);
17404 +
17405 + atomic_dec(&bufAllocCount);
17406 + return;
17407 +}
17408 +
17409 +void
17410 +header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
17411 + const struct cifsTconInfo *treeCon, int word_count
17412 + /* length of fixed section (word count) in two byte units */
17413 + )
17414 +{
17415 + int i;
17416 + __u32 tmp;
17417 + struct list_head* temp_item;
17418 + struct cifsSesInfo * ses;
17419 + char *temp = (char *) buffer;
17420 +
17421 + for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) {
17422 + temp[i] = 0; /* BB is this needed ?? */
17423 + }
17424 +
17425 + buffer->smb_buf_length =
17426 + (2 * word_count) + sizeof (struct smb_hdr) -
17427 + 4 /* RFC 1001 length field does not count */ +
17428 + 2 /* for bcc field itself */ ;
17429 + /* 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 */
17430 +
17431 + buffer->Protocol[0] = 0xFF;
17432 + buffer->Protocol[1] = 'S';
17433 + buffer->Protocol[2] = 'M';
17434 + buffer->Protocol[3] = 'B';
17435 + buffer->Command = smb_command;
17436 + buffer->Flags = 0x00; /* case sensitive */
17437 + buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
17438 + tmp = cpu_to_le32(current->pid);
17439 + buffer->Pid = tmp & 0xFFFF;
17440 + tmp >>= 16;
17441 + buffer->PidHigh = tmp & 0xFFFF;
17442 + spin_lock(&GlobalMid_Lock);
17443 + GlobalMid++;
17444 + buffer->Mid = GlobalMid;
17445 + spin_unlock(&GlobalMid_Lock);
17446 + if (treeCon) {
17447 + buffer->Tid = treeCon->tid;
17448 + if (treeCon->ses) {
17449 + if (treeCon->ses->capabilities & CAP_UNICODE)
17450 + buffer->Flags2 |= SMBFLG2_UNICODE;
17451 + if (treeCon->ses->capabilities & CAP_STATUS32) {
17452 + buffer->Flags2 |= SMBFLG2_ERR_STATUS;
17453 + }
17454 +
17455 + buffer->Uid = treeCon->ses->Suid; /* always in LE format */
17456 + if(multiuser_mount != 0) {
17457 + /* For the multiuser case, there are few obvious technically */
17458 + /* possible mechanisms to match the local linux user (uid) */
17459 + /* to a valid remote smb user (smb_uid): */
17460 + /* 1) Query Winbind (or other local pam/nss daemon */
17461 + /* for userid/password/logon_domain or credential */
17462 + /* 2) Query Winbind for uid to sid to username mapping */
17463 + /* and see if we have a matching password for existing*/
17464 + /* session for that user perhas getting password by */
17465 + /* adding a new pam_cifs module that stores passwords */
17466 + /* so that the cifs vfs can get at that for all logged*/
17467 + /* on users */
17468 + /* 3) (Which is the mechanism we have chosen) */
17469 + /* Search through sessions to the same server for a */
17470 + /* a match on the uid that was passed in on mount */
17471 + /* with the current processes uid (or euid?) and use */
17472 + /* that smb uid. If no existing smb session for */
17473 + /* that uid found, use the default smb session ie */
17474 + /* the smb session for the volume mounted which is */
17475 + /* the same as would be used if the multiuser mount */
17476 + /* flag were disabled. */
17477 +
17478 + /* BB Add support for establishing new tCon and SMB Session */
17479 + /* with userid/password pairs found on the smb session */
17480 + /* for other target tcp/ip addresses BB */
17481 + if(current->uid != treeCon->ses->linux_uid) {
17482 + cFYI(1,("Multiuser mode and UID did not match tcon uid "));
17483 + read_lock(&GlobalSMBSeslock);
17484 + list_for_each(temp_item, &GlobalSMBSessionList) {
17485 + ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
17486 + if(ses->linux_uid == current->uid) {
17487 + if(ses->server == treeCon->ses->server) {
17488 + cFYI(1,("found matching uid substitute right smb_uid"));
17489 + buffer->Uid = ses->Suid;
17490 + break;
17491 + } else {
17492 + /* BB eventually call cifs_setup_session here */
17493 + cFYI(1,("local UID found but smb sess with this server does not exist"));
17494 + }
17495 + }
17496 + }
17497 + read_unlock(&GlobalSMBSeslock);
17498 + }
17499 + }
17500 + }
17501 + if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
17502 + buffer->Flags2 |= SMBFLG2_DFS;
17503 + if(treeCon->ses->server)
17504 + if(treeCon->ses->server->secMode &
17505 + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
17506 + buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
17507 + }
17508 +
17509 +/* endian conversion of flags is now done just before sending */
17510 + buffer->WordCount = (char) word_count;
17511 + return;
17512 +}
17513 +
17514 +int
17515 +checkSMBhdr(struct smb_hdr *smb, __u16 mid)
17516 +{
17517 + /* Make sure that this really is an SMB, that it is a response,
17518 + and that the message ids match */
17519 + if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
17520 + (mid == smb->Mid)) {
17521 + if(smb->Flags & SMBFLG_RESPONSE)
17522 + return 0;
17523 + else {
17524 + /* only one valid case where server sends us request */
17525 + if(smb->Command == SMB_COM_LOCKING_ANDX)
17526 + return 0;
17527 + else
17528 + cERROR(1, ("Rcvd Request not response "));
17529 + }
17530 + } else { /* bad signature or mid */
17531 + if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
17532 + cERROR(1,
17533 + ("Bad protocol string signature header %x ",
17534 + *(unsigned int *) smb->Protocol));
17535 + if (mid != smb->Mid)
17536 + cERROR(1, ("Mids do not match"));
17537 + }
17538 + cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
17539 + return 1;
17540 +}
17541 +
17542 +int
17543 +checkSMB(struct smb_hdr *smb, __u16 mid, int length)
17544 +{
17545 + cFYI(0,
17546 + ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
17547 + length, ntohl(smb->smb_buf_length)));
17548 + if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
17549 + || (ntohl(smb->smb_buf_length) >
17550 + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
17551 + if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
17552 + cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
17553 + if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
17554 + && (smb->Status.CifsError != 0))
17555 + return 0; /* some error cases do not return wct and bcc */
17556 +
17557 + }
17558 + if (ntohl(smb->smb_buf_length) >
17559 + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
17560 + cERROR(1,
17561 + ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
17562 + cERROR(1,
17563 + ("bad smb detected. Illegal length. The mid=%d",
17564 + smb->Mid));
17565 + return 1;
17566 + }
17567 +
17568 + if (checkSMBhdr(smb, mid))
17569 + return 1;
17570 +
17571 + if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
17572 + || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
17573 + return 0;
17574 + } else {
17575 + cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
17576 + cERROR(1,
17577 + ("bad smb size detected. The Mid=%d", smb->Mid));
17578 + return 1;
17579 + }
17580 +}
17581 +int
17582 +is_valid_oplock_break(struct smb_hdr *buf)
17583 +{
17584 + struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
17585 + struct list_head *tmp;
17586 + struct list_head *tmp1;
17587 + struct cifsTconInfo *tcon;
17588 + struct cifsFileInfo *netfile;
17589 +
17590 + /* could add check for smb response flag 0x80 */
17591 + cFYI(1,("Checking for oplock break"));
17592 + if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
17593 + return FALSE;
17594 + if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
17595 + /* no sense logging error on invalid handle on oplock
17596 + break - harmless race between close request and oplock
17597 + break response is expected from time to time writing out
17598 + large dirty files cached on the client */
17599 + if ((NT_STATUS_INVALID_HANDLE) ==
17600 + le32_to_cpu(pSMB->hdr.Status.CifsError)) {
17601 + cFYI(1,("invalid handle on oplock break"));
17602 + return TRUE;
17603 + } else if (ERRbadfid ==
17604 + le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
17605 + return TRUE;
17606 + } else {
17607 + return FALSE; /* on valid oplock brk we get "request" */
17608 + }
17609 + }
17610 + if(pSMB->hdr.WordCount != 8)
17611 + return FALSE;
17612 +
17613 + cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
17614 + if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
17615 + return FALSE;
17616 +
17617 + /* look up tcon based on tid & uid */
17618 + read_lock(&GlobalSMBSeslock);
17619 + list_for_each(tmp, &GlobalTreeConnectionList) {
17620 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
17621 + if (tcon->tid == buf->Tid) {
17622 +#ifdef CONFIG_CIFS_STATS
17623 + atomic_inc(&tcon->num_oplock_brks);
17624 +#endif
17625 + list_for_each(tmp1,&tcon->openFileList){
17626 + netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
17627 + if(pSMB->Fid == netfile->netfid) {
17628 + struct cifsInodeInfo *pCifsInode;
17629 + read_unlock(&GlobalSMBSeslock);
17630 + cFYI(1,("Matching file id, processing oplock break"));
17631 + pCifsInode =
17632 + CIFS_I(netfile->pInode);
17633 + pCifsInode->clientCanCacheAll = FALSE;
17634 + if(pSMB->OplockLevel == 0)
17635 + pCifsInode->clientCanCacheRead = FALSE;
17636 + pCifsInode->oplockPending = TRUE;
17637 + AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
17638 + cFYI(1,("about to wake up oplock thd"));
17639 + wake_up_process(oplockThread);
17640 + return TRUE;
17641 + }
17642 + }
17643 + read_unlock(&GlobalSMBSeslock);
17644 + cFYI(1,("No matching file for oplock break on connection"));
17645 + return TRUE;
17646 + }
17647 + }
17648 + read_unlock(&GlobalSMBSeslock);
17649 + cFYI(1,("Can not process oplock break for non-existent connection"));
17650 + return TRUE;
17651 +}
17652 +
17653 +void
17654 +dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
17655 +{
17656 + int i, j;
17657 + char debug_line[17];
17658 + unsigned char *buffer;
17659 +
17660 + if (traceSMB == 0)
17661 + return;
17662 +
17663 + buffer = (unsigned char *) smb_buf;
17664 + for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
17665 + if (i % 8 == 0) { /* we have reached the beginning of line */
17666 + printk(KERN_DEBUG "| ");
17667 + j = 0;
17668 + }
17669 + printk("%0#4x ", buffer[i]);
17670 + debug_line[2 * j] = ' ';
17671 + if (isprint(buffer[i]))
17672 + debug_line[1 + (2 * j)] = buffer[i];
17673 + else
17674 + debug_line[1 + (2 * j)] = '_';
17675 +
17676 + if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
17677 + debug_line[16] = 0;
17678 + printk(" | %s\n", debug_line);
17679 + }
17680 + }
17681 + for (; j < 8; j++) {
17682 + printk(" ");
17683 + debug_line[2 * j] = ' ';
17684 + debug_line[1 + (2 * j)] = ' ';
17685 + }
17686 + printk( " | %s\n", debug_line);
17687 + return;
17688 +}
17689 Index: linux-2.4.35.4/fs/cifs/netmisc.c
17690 ===================================================================
17691 --- /dev/null
17692 +++ linux-2.4.35.4/fs/cifs/netmisc.c
17693 @@ -0,0 +1,905 @@
17694 +/*
17695 + * fs/cifs/netmisc.c
17696 + *
17697 + * Copyright (c) International Business Machines Corp., 2002
17698 + * Author(s): Steve French (sfrench@us.ibm.com)
17699 + *
17700 + * Error mapping routines from Samba libsmb/errormap.c
17701 + * Copyright (C) Andrew Tridgell 2001
17702 + *
17703 + *
17704 + * This program is free software; you can redistribute it and/or modify
17705 + * it under the terms of the GNU General Public License as published by
17706 + * the Free Software Foundation; either version 2 of the License, or
17707 + * (at your option) any later version.
17708 + *
17709 + * This program is distributed in the hope that it will be useful,
17710 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17711 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17712 + * the GNU General Public License for more details.
17713 + *
17714 + * You should have received a copy of the GNU General Public License
17715 + * along with this program; if not, write to the Free Software
17716 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17717 + */
17718 +
17719 +#include <linux/net.h>
17720 +#include <linux/string.h>
17721 +#include <linux/in.h>
17722 +#include <linux/ctype.h>
17723 +#include <linux/fs.h>
17724 +#include <asm/div64.h>
17725 +#include <asm/byteorder.h>
17726 +#include "cifsfs.h"
17727 +#include "cifspdu.h"
17728 +#include "cifsglob.h"
17729 +#include "cifsproto.h"
17730 +#include "smberr.h"
17731 +#include "cifs_debug.h"
17732 +#include "nterr.h"
17733 +
17734 +struct smb_to_posix_error {
17735 + __u16 smb_err;
17736 + int posix_code;
17737 +};
17738 +
17739 +const struct smb_to_posix_error mapping_table_ERRDOS[] = {
17740 + {ERRbadfunc, -EINVAL},
17741 + {ERRbadfile, -ENOENT},
17742 + {ERRbadpath, -ENOTDIR},
17743 + {ERRnofids, -EMFILE},
17744 + {ERRnoaccess, -EACCES},
17745 + {ERRbadfid, -EBADF},
17746 + {ERRbadmcb, -EIO},
17747 + {ERRnomem, -ENOMEM},
17748 + {ERRbadmem, -EFAULT},
17749 + {ERRbadenv, -EFAULT},
17750 + {ERRbadformat, -EINVAL},
17751 + {ERRbadaccess, -EACCES},
17752 + {ERRbaddata, -EIO},
17753 + {ERRbaddrive, -ENXIO},
17754 + {ERRremcd, -EACCES},
17755 + {ERRdiffdevice, -EXDEV},
17756 + {ERRnofiles, -ENOENT},
17757 + {ERRbadshare, -ETXTBSY},
17758 + {ERRlock, -EACCES},
17759 + {ERRunsup, -EINVAL},
17760 + {ERRnosuchshare,-ENXIO},
17761 + {ERRfilexists, -EEXIST},
17762 + {ERRinvparm, -EINVAL},
17763 + {ERRdiskfull, -ENOSPC},
17764 + {ERRinvname, -ENOENT},
17765 + {ERRdirnotempty, -ENOTEMPTY},
17766 + {ERRnotlocked, -ENOLCK},
17767 + {ERRalreadyexists, -EEXIST},
17768 + {ERRmoredata, -EOVERFLOW},
17769 + {ErrQuota, -EDQUOT},
17770 + {ErrNotALink, -ENOLINK},
17771 + {ERRnetlogonNotStarted,-ENOPROTOOPT},
17772 + {0, 0}
17773 +};
17774 +
17775 +const struct smb_to_posix_error mapping_table_ERRSRV[] = {
17776 + {ERRerror, -EIO},
17777 + {ERRbadpw, -EPERM},
17778 + {ERRbadtype, -EREMOTE},
17779 + {ERRaccess, -EACCES},
17780 + {ERRinvtid, -ENXIO},
17781 + {ERRinvnetname, -ENODEV},
17782 + {ERRinvdevice, -ENXIO},
17783 + {ERRqfull, -ENOSPC},
17784 + {ERRqtoobig, -ENOSPC},
17785 + {ERRqeof, -EIO},
17786 + {ERRinvpfid, -EBADF},
17787 + {ERRsmbcmd, -EBADRQC},
17788 + {ERRsrverror, -EIO},
17789 + {ERRbadBID, -EIO},
17790 + {ERRfilespecs, -EINVAL},
17791 + {ERRbadLink, -EIO},
17792 + {ERRbadpermits, -EINVAL},
17793 + {ERRbadPID, -ESRCH},
17794 + {ERRsetattrmode, -EINVAL},
17795 + {ERRpaused, -EHOSTDOWN},
17796 + {ERRmsgoff, -EHOSTDOWN},
17797 + {ERRnoroom, -ENOSPC},
17798 + {ERRrmuns, -EUSERS},
17799 + {ERRtimeout, -ETIME},
17800 + {ERRnoresource, -ENOBUFS},
17801 + {ERRtoomanyuids, -EUSERS},
17802 + {ERRbaduid, -EACCES},
17803 + {ERRusempx, -EIO},
17804 + {ERRusestd, -EIO},
17805 + {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
17806 + {ERRaccountexpired, -EACCES},
17807 + {ERRbadclient, -EACCES},
17808 + {ERRbadLogonTime, -EACCES},
17809 + {ERRpasswordExpired, -EACCES},
17810 + {ERRnosupport, -EINVAL},
17811 + {0, 0}
17812 +};
17813 +
17814 +const struct smb_to_posix_error mapping_table_ERRHRD[] = {
17815 + {0, 0}
17816 +};
17817 +
17818 +/* Convert string containing dotted ip address to binary form */
17819 +/* returns 0 if invalid address */
17820 +
17821 +/* BB add address family, change rc to status flag and return union or for ipv6 */
17822 +/* will need parent to call something like inet_pton to convert ipv6 address BB */
17823 +int
17824 +cifs_inet_pton(int address_family, char *cp,void *dst)
17825 +{
17826 + struct in_addr address;
17827 + int value;
17828 + int digit;
17829 + int i;
17830 + char temp;
17831 + char bytes[4];
17832 + char *end = bytes;
17833 + static const int addr_class_max[4] =
17834 + { 0xffffffff, 0xffffff, 0xffff, 0xff };
17835 +
17836 + if(address_family != AF_INET)
17837 + return -EAFNOSUPPORT;
17838 +
17839 + for (i = 0; i < 4; i++) {
17840 + bytes[i] = 0;
17841 + }
17842 +
17843 + temp = *cp;
17844 +
17845 + while (TRUE) {
17846 + if (!isdigit(temp))
17847 + return 0;
17848 +
17849 + value = 0;
17850 + digit = 0;
17851 + for (;;) {
17852 + if (isascii(temp) && isdigit(temp)) {
17853 + value = (value * 10) + temp - '0';
17854 + temp = *++cp;
17855 + digit = 1;
17856 + } else
17857 + break;
17858 + }
17859 +
17860 + if (temp == '.') {
17861 + if ((end > bytes + 2) || (value > 255))
17862 + return 0;
17863 + *end++ = value;
17864 + temp = *++cp;
17865 + } else if (temp == ':') {
17866 + cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
17867 + return -1;
17868 + } else
17869 + break;
17870 + }
17871 +
17872 + /* check for last characters */
17873 + if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
17874 + if (temp != '\\') {
17875 + if (temp != '/')
17876 + return 0;
17877 + else
17878 + (*cp = '\\'); /* switch the slash the expected way */
17879 + }
17880 + if (value > addr_class_max[end - bytes])
17881 + return 0;
17882 +
17883 + address.s_addr = *((int *) bytes) | htonl(value);
17884 + *((int *)dst) = address.s_addr;
17885 + return 1; /* success */
17886 +}
17887 +
17888 +/*****************************************************************************
17889 +convert a NT status code to a dos class/code
17890 + *****************************************************************************/
17891 +/* NT status -> dos error map */
17892 +static const struct {
17893 + __u8 dos_class;
17894 + __u16 dos_code;
17895 + __u32 ntstatus;
17896 +} ntstatus_to_dos_map[] = {
17897 + {
17898 + ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
17899 + ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
17900 + ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
17901 + ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
17902 + ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
17903 + ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
17904 + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
17905 + ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
17906 + ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
17907 + ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
17908 + ERRDOS, 87, NT_STATUS_INVALID_CID}, {
17909 + ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
17910 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
17911 + ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
17912 + ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
17913 + ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
17914 + ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
17915 + ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
17916 + ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
17917 + ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
17918 + ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
17919 +/* { This NT error code was 'sqashed'
17920 + from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
17921 + during the session setup } */
17922 + {
17923 + ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
17924 + ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
17925 + ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
17926 + ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
17927 + ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
17928 + ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
17929 + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
17930 + ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
17931 + ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
17932 + ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
17933 + ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
17934 +/* { This NT error code was 'sqashed'
17935 + from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
17936 + during the session setup } */
17937 + {
17938 + ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
17939 + ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
17940 + ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
17941 + ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
17942 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
17943 + ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
17944 + ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
17945 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
17946 + ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
17947 + ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
17948 + ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
17949 + ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
17950 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
17951 + ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
17952 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
17953 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
17954 + ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
17955 + ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */
17956 + ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
17957 + ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
17958 + ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
17959 + ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
17960 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
17961 + ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
17962 + ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
17963 + ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
17964 + ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
17965 + ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
17966 + ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
17967 + ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
17968 + ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
17969 + ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
17970 + ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
17971 + ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
17972 + ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
17973 + ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
17974 + ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
17975 + ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
17976 + ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
17977 + ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
17978 + ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
17979 + ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
17980 + ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
17981 + ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
17982 + ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
17983 + ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, {
17984 + ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
17985 + ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
17986 + ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
17987 + ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
17988 + ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
17989 + ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
17990 + ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
17991 + ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
17992 + ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
17993 + ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
17994 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
17995 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
17996 + ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
17997 + ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
17998 + ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
17999 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
18000 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
18001 + ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
18002 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
18003 + ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
18004 +/* { This NT error code was 'sqashed'
18005 + from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
18006 + during the session setup } */
18007 + {
18008 + ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
18009 + ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
18010 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
18011 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
18012 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
18013 + ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
18014 +/* { This NT error code was 'sqashed'
18015 + from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
18016 + during the session setup } */
18017 + {
18018 + ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
18019 + ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
18020 + ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
18021 + ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
18022 + ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
18023 + ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
18024 + ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
18025 + ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
18026 + ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
18027 + ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
18028 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
18029 + ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
18030 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
18031 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
18032 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
18033 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
18034 + ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
18035 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
18036 + ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
18037 + ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
18038 + ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
18039 + ERRDOS, 112, NT_STATUS_DISK_FULL}, {
18040 + ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
18041 + ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
18042 + ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
18043 + ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
18044 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
18045 + ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
18046 + ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
18047 + ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
18048 + ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
18049 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
18050 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
18051 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
18052 + ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
18053 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
18054 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
18055 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
18056 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
18057 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
18058 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
18059 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
18060 + ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
18061 + ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
18062 + ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
18063 + ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
18064 + ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
18065 + ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
18066 +/* { This NT error code was 'sqashed'
18067 + from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
18068 + during the session setup } */
18069 + {
18070 + ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
18071 + ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
18072 + ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
18073 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
18074 + ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
18075 + ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
18076 + ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
18077 + ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
18078 + ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
18079 + ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
18080 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
18081 + ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
18082 + ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
18083 + ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
18084 + ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
18085 + ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
18086 + ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
18087 + ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
18088 + ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
18089 + ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
18090 + ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
18091 + ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
18092 + ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
18093 + ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
18094 + ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
18095 + ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
18096 + ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
18097 + ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
18098 + ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
18099 + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
18100 + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
18101 + ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
18102 + ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
18103 + ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
18104 + ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
18105 + ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
18106 + ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
18107 + ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
18108 + ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
18109 + ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
18110 + ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
18111 + ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
18112 + ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
18113 + ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
18114 + ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
18115 + ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
18116 + ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
18117 + ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
18118 + ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
18119 + ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
18120 + ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
18121 + ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
18122 + ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
18123 + ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
18124 + ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
18125 + ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
18126 + ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
18127 + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
18128 + ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
18129 + ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
18130 + ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
18131 + ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
18132 + ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
18133 + ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
18134 + ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
18135 + ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
18136 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
18137 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
18138 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
18139 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
18140 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
18141 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
18142 + ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
18143 + ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
18144 + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
18145 + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
18146 + ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
18147 + ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
18148 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
18149 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
18150 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
18151 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
18152 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
18153 + ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
18154 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
18155 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
18156 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
18157 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
18158 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
18159 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
18160 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
18161 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
18162 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
18163 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
18164 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
18165 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
18166 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
18167 + ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
18168 + ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
18169 + ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
18170 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
18171 + ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
18172 + ERRDOS, 203, 0xc0000100}, {
18173 + ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
18174 + ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
18175 + ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
18176 + ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
18177 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
18178 + ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
18179 + ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
18180 + ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
18181 + ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
18182 + ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
18183 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
18184 + ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
18185 + ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
18186 + ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
18187 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
18188 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
18189 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
18190 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
18191 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
18192 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
18193 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
18194 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
18195 + ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
18196 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
18197 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
18198 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
18199 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
18200 + ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
18201 + ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
18202 + ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
18203 + ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
18204 + ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
18205 + ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
18206 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
18207 + ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
18208 + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
18209 + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
18210 + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
18211 + ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
18212 + ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
18213 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
18214 + ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
18215 + ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
18216 + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
18217 + ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
18218 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
18219 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
18220 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
18221 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
18222 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
18223 + ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
18224 + ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
18225 + ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
18226 + ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
18227 + ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
18228 + ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
18229 + ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
18230 + ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
18231 + ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
18232 + ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
18233 + ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
18234 + ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
18235 + ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
18236 + ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
18237 + ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
18238 + ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
18239 + ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
18240 + ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
18241 + ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
18242 + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
18243 + ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
18244 + ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
18245 + ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
18246 + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
18247 + ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
18248 + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
18249 + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
18250 + ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
18251 + ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
18252 + ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
18253 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
18254 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
18255 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
18256 + ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
18257 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
18258 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
18259 + ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
18260 + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
18261 + ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
18262 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
18263 + ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
18264 + ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
18265 + ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
18266 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
18267 + ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
18268 + ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
18269 + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
18270 + ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
18271 + ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
18272 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
18273 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
18274 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
18275 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
18276 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
18277 + ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
18278 + ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
18279 + ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
18280 + ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
18281 + ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
18282 + ERRHRD, ERRgeneral, 0xc000016e}, {
18283 + ERRHRD, ERRgeneral, 0xc000016f}, {
18284 + ERRHRD, ERRgeneral, 0xc0000170}, {
18285 + ERRHRD, ERRgeneral, 0xc0000171}, {
18286 + ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
18287 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
18288 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
18289 + ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
18290 + ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
18291 + ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
18292 + ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
18293 + ERRHRD, ERRgeneral, 0xc0000179}, {
18294 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
18295 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
18296 + ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
18297 + ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
18298 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
18299 + ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
18300 + ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
18301 + ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
18302 + ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
18303 + ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
18304 + ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
18305 + ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
18306 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
18307 + ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
18308 + ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
18309 + ERRDOS, 19, NT_STATUS_TOO_LATE}, {
18310 + ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
18311 +/* { This NT error code was 'sqashed'
18312 + from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
18313 + during the session setup } */
18314 + {
18315 + ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
18316 + ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
18317 + ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
18318 + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
18319 + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
18320 + ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
18321 + ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
18322 + ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
18323 + ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
18324 + ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
18325 + ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
18326 + ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
18327 + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
18328 + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
18329 + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
18330 + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
18331 +/* { This NT error code was 'sqashed'
18332 + from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
18333 + during the session setup } */
18334 + {
18335 + ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
18336 + ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
18337 + ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
18338 + ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
18339 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
18340 + ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
18341 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
18342 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
18343 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
18344 + ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
18345 + ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
18346 + ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
18347 + ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
18348 + ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
18349 + ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
18350 + ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
18351 + ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
18352 + ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
18353 + ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
18354 + ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
18355 + ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
18356 + ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
18357 + ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
18358 + ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
18359 + ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
18360 + ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
18361 + ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
18362 + ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
18363 + ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
18364 + ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
18365 + ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
18366 + ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
18367 + ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
18368 + ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
18369 + ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
18370 + ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
18371 + ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
18372 + ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
18373 + ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
18374 + ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
18375 + ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
18376 + ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
18377 + ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
18378 + ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
18379 + ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
18380 + ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
18381 + ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
18382 + ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
18383 + ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
18384 + ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
18385 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
18386 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
18387 + ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
18388 + ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
18389 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
18390 + ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
18391 + ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
18392 + ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
18393 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
18394 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
18395 + ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
18396 + ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
18397 + ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
18398 + ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
18399 + ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
18400 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
18401 + ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
18402 + ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
18403 + ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
18404 + ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
18405 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
18406 + ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
18407 + ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
18408 + ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
18409 + ERRHRD, ERRgeneral, 0xc000024a}, {
18410 + ERRHRD, ERRgeneral, 0xc000024b}, {
18411 + ERRHRD, ERRgeneral, 0xc000024c}, {
18412 + ERRHRD, ERRgeneral, 0xc000024d}, {
18413 + ERRHRD, ERRgeneral, 0xc000024e}, {
18414 + ERRHRD, ERRgeneral, 0xc000024f}, {
18415 + ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
18416 + ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
18417 + ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
18418 + ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
18419 + ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
18420 + ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
18421 + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
18422 + ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
18423 + ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
18424 + ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
18425 + ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
18426 + ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
18427 + ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
18428 + ERRHRD, ERRgeneral, 0xc000025d}, {
18429 + ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
18430 + ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
18431 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
18432 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
18433 + ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
18434 + ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
18435 + ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
18436 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
18437 + ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
18438 + ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
18439 + ERRDOS, 21, 0xc000026e}, {
18440 + ERRDOS, 161, 0xc0000281}, {
18441 + ERRDOS, ERRnoaccess, 0xc000028a}, {
18442 + ERRDOS, ERRnoaccess, 0xc000028b}, {
18443 + ERRHRD, ERRgeneral, 0xc000028c}, {
18444 + ERRDOS, ERRnoaccess, 0xc000028d}, {
18445 + ERRDOS, ERRnoaccess, 0xc000028e}, {
18446 + ERRDOS, ERRnoaccess, 0xc000028f}, {
18447 + ERRDOS, ERRnoaccess, 0xc0000290}, {
18448 +ERRDOS, ERRbadfunc, 0xc000029c},};
18449 +
18450 +/*****************************************************************************
18451 + Print an error message from the status code
18452 + *****************************************************************************/
18453 +static void
18454 +cifs_print_status(__u32 status_code)
18455 +{
18456 + int idx = 0;
18457 +
18458 + while (nt_errs[idx].nt_errstr != NULL) {
18459 + if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
18460 + (status_code & 0xFFFFFF)) {
18461 + printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
18462 + status_code,nt_errs[idx].nt_errstr);
18463 + }
18464 + idx++;
18465 + }
18466 + return;
18467 +}
18468 +
18469 +
18470 +static void
18471 +ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
18472 +{
18473 + int i;
18474 + if (ntstatus == 0) {
18475 + *eclass = 0;
18476 + *ecode = 0;
18477 + return;
18478 + }
18479 + for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
18480 + if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
18481 + *eclass = ntstatus_to_dos_map[i].dos_class;
18482 + *ecode = ntstatus_to_dos_map[i].dos_code;
18483 + return;
18484 + }
18485 + }
18486 + *eclass = ERRHRD;
18487 + *ecode = ERRgeneral;
18488 +}
18489 +
18490 +int
18491 +map_smb_to_linux_error(struct smb_hdr *smb)
18492 +{
18493 + unsigned int i;
18494 + int rc = -EIO; /* if transport error smb error may not be set */
18495 + __u8 smberrclass;
18496 + __u16 smberrcode;
18497 +
18498 + /* BB if NT Status codes - map NT BB */
18499 +
18500 + /* old style smb error codes */
18501 + if (smb->Status.CifsError == 0)
18502 + return 0;
18503 +
18504 + if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
18505 + /* translate the newer STATUS codes to old style errors and then to POSIX errors */
18506 + smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
18507 + if(cifsFYI)
18508 + cifs_print_status(smb->Status.CifsError);
18509 + ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
18510 + &smberrcode);
18511 + } else {
18512 + smberrclass = smb->Status.DosError.ErrorClass;
18513 + smb->Status.DosError.Error =
18514 + le16_to_cpu(smb->Status.DosError.Error);
18515 + smberrcode = smb->Status.DosError.Error;
18516 + }
18517 +
18518 + /* old style errors */
18519 +
18520 + /* DOS class smb error codes - map DOS */
18521 + if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
18522 + for (i = 0;
18523 + i <
18524 + sizeof (mapping_table_ERRDOS) /
18525 + sizeof (struct smb_to_posix_error); i++) {
18526 + if (mapping_table_ERRDOS[i].smb_err == 0)
18527 + break;
18528 + else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
18529 + rc = mapping_table_ERRDOS[i].posix_code;
18530 + break;
18531 + }
18532 + /* else try the next error mapping one to see if it will match */
18533 + }
18534 + } else if (smberrclass == ERRSRV) { /* server class of error codes */
18535 + for (i = 0;
18536 + i <
18537 + sizeof (mapping_table_ERRSRV) /
18538 + sizeof (struct smb_to_posix_error); i++) {
18539 + if (mapping_table_ERRSRV[i].smb_err == 0)
18540 + break;
18541 + else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
18542 + rc = mapping_table_ERRSRV[i].posix_code;
18543 + break;
18544 + }
18545 + /* else try the next error mapping one to see if it will match */
18546 + }
18547 + }
18548 + /* else ERRHRD class errors or junk - return EIO */
18549 +
18550 + cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
18551 +
18552 + /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
18553 +
18554 + return rc;
18555 +}
18556 +
18557 +/*
18558 + * calculate the size of the SMB message based on the fixed header
18559 + * portion, the number of word parameters and the data portion of the message
18560 + */
18561 +unsigned int
18562 +smbCalcSize(struct smb_hdr *ptr)
18563 +{
18564 + return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
18565 + BCC(ptr));
18566 +}
18567 +
18568 +/* The following are taken from fs/ntfs/util.c */
18569 +
18570 +#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
18571 +
18572 + /*
18573 + * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
18574 + * into Unix UTC (based 1970-01-01, in seconds).
18575 + */
18576 +time_t
18577 +cifs_NTtimeToUnix(__u64 ntutc)
18578 +{
18579 + /* BB what about the timezone? BB */
18580 +
18581 + /* Subtract the NTFS time offset, then convert to 1s intervals. */
18582 + u64 t;
18583 +
18584 + t = ntutc - NTFS_TIME_OFFSET;
18585 + do_div(t, 10000000);
18586 + return (time_t)t;
18587 +}
18588 +
18589 +/* Convert the Unix UTC into NT UTC. */
18590 +__u64
18591 +cifs_UnixTimeToNT(time_t t)
18592 +{
18593 + __u64 dce_time;
18594 + /* Convert to 100ns intervals and then add the NTFS time offset. */
18595 + dce_time = (__u64) t * 10000000;
18596 + dce_time += NTFS_TIME_OFFSET;
18597 + return dce_time;
18598 +}
18599 Index: linux-2.4.35.4/fs/cifs/nterr.c
18600 ===================================================================
18601 --- /dev/null
18602 +++ linux-2.4.35.4/fs/cifs/nterr.c
18603 @@ -0,0 +1,687 @@
18604 +/*
18605 + * Unix SMB/Netbios implementation.
18606 + * Version 1.9.
18607 + * RPC Pipe client / server routines
18608 + * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
18609 + *
18610 + * This program is free software; you can redistribute it and/or modify
18611 + * it under the terms of the GNU General Public License as published by
18612 + * the Free Software Foundation; either version 2 of the License, or
18613 + * (at your option) any later version.
18614 + *
18615 + * This program is distributed in the hope that it will be useful,
18616 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18617 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18618 + * GNU General Public License for more details.
18619 + *
18620 + * You should have received a copy of the GNU General Public License
18621 + * along with this program; if not, write to the Free Software
18622 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18623 + */
18624 +
18625 +/* NT error codes - see nterr.h */
18626 +#include <linux/types.h>
18627 +#include <linux/fs.h>
18628 +#include "nterr.h"
18629 +
18630 +const struct nt_err_code_struct nt_errs[] = {
18631 + {"NT_STATUS_OK", NT_STATUS_OK},
18632 + {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
18633 + {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
18634 + {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
18635 + {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
18636 + {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
18637 + {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
18638 + {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
18639 + {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
18640 + {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
18641 + {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
18642 + {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
18643 + {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
18644 + {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
18645 + {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
18646 + {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
18647 + {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
18648 + {"NT_STATUS_INVALID_DEVICE_REQUEST",
18649 + NT_STATUS_INVALID_DEVICE_REQUEST},
18650 + {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
18651 + {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
18652 + {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
18653 + {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
18654 + {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
18655 + {"NT_STATUS_MORE_PROCESSING_REQUIRED",
18656 + NT_STATUS_MORE_PROCESSING_REQUIRED},
18657 + {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
18658 + {"NT_STATUS_CONFLICTING_ADDRESSES",
18659 + NT_STATUS_CONFLICTING_ADDRESSES},
18660 + {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
18661 + {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
18662 + {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
18663 + NT_STATUS_UNABLE_TO_DELETE_SECTION},
18664 + {"NT_STATUS_INVALID_SYSTEM_SERVICE",
18665 + NT_STATUS_INVALID_SYSTEM_SERVICE},
18666 + {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
18667 + {"NT_STATUS_INVALID_LOCK_SEQUENCE",
18668 + NT_STATUS_INVALID_LOCK_SEQUENCE},
18669 + {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
18670 + {"NT_STATUS_INVALID_FILE_FOR_SECTION",
18671 + NT_STATUS_INVALID_FILE_FOR_SECTION},
18672 + {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
18673 + {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
18674 + {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
18675 + {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
18676 + {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
18677 + NT_STATUS_NONCONTINUABLE_EXCEPTION},
18678 + {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
18679 + {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
18680 + {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
18681 + {"NT_STATUS_INVALID_UNWIND_TARGET",
18682 + NT_STATUS_INVALID_UNWIND_TARGET},
18683 + {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
18684 + {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
18685 + {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
18686 + NT_STATUS_UNABLE_TO_DECOMMIT_VM},
18687 + {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
18688 + {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
18689 + NT_STATUS_INVALID_PORT_ATTRIBUTES},
18690 + {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
18691 + NT_STATUS_PORT_MESSAGE_TOO_LONG},
18692 + {"NT_STATUS_INVALID_PARAMETER_MIX",
18693 + NT_STATUS_INVALID_PARAMETER_MIX},
18694 + {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
18695 + {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
18696 + {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
18697 + {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
18698 + NT_STATUS_OBJECT_NAME_NOT_FOUND},
18699 + {"NT_STATUS_OBJECT_NAME_COLLISION",
18700 + NT_STATUS_OBJECT_NAME_COLLISION},
18701 + {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
18702 + {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
18703 + {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
18704 + NT_STATUS_DEVICE_ALREADY_ATTACHED},
18705 + {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
18706 + {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
18707 + NT_STATUS_OBJECT_PATH_NOT_FOUND},
18708 + {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
18709 + NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
18710 + {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
18711 + {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
18712 + {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
18713 + {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
18714 + {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
18715 + {"NT_STATUS_PORT_CONNECTION_REFUSED",
18716 + NT_STATUS_PORT_CONNECTION_REFUSED},
18717 + {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
18718 + {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
18719 + {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
18720 + {"NT_STATUS_INVALID_PAGE_PROTECTION",
18721 + NT_STATUS_INVALID_PAGE_PROTECTION},
18722 + {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
18723 + {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
18724 + NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
18725 + {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
18726 + {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
18727 + {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
18728 + NT_STATUS_SUSPEND_COUNT_EXCEEDED},
18729 + {"NT_STATUS_THREAD_IS_TERMINATING",
18730 + NT_STATUS_THREAD_IS_TERMINATING},
18731 + {"NT_STATUS_BAD_WORKING_SET_LIMIT",
18732 + NT_STATUS_BAD_WORKING_SET_LIMIT},
18733 + {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
18734 + NT_STATUS_INCOMPATIBLE_FILE_MAP},
18735 + {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
18736 + {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
18737 + {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
18738 + {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
18739 + {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
18740 + {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
18741 + {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
18742 + {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
18743 + {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
18744 + {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
18745 + NT_STATUS_CTL_FILE_NOT_SUPPORTED},
18746 + {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
18747 + {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
18748 + {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
18749 + {"NT_STATUS_INVALID_PRIMARY_GROUP",
18750 + NT_STATUS_INVALID_PRIMARY_GROUP},
18751 + {"NT_STATUS_NO_IMPERSONATION_TOKEN",
18752 + NT_STATUS_NO_IMPERSONATION_TOKEN},
18753 + {"NT_STATUS_CANT_DISABLE_MANDATORY",
18754 + NT_STATUS_CANT_DISABLE_MANDATORY},
18755 + {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
18756 + {"NT_STATUS_NO_SUCH_LOGON_SESSION",
18757 + NT_STATUS_NO_SUCH_LOGON_SESSION},
18758 + {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
18759 + {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
18760 + {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
18761 + {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
18762 + {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
18763 + {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
18764 + {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
18765 + {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
18766 + {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
18767 + {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
18768 + {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
18769 + {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
18770 + {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
18771 + {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
18772 + {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
18773 + {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
18774 + {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
18775 + {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
18776 + {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
18777 + {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
18778 + {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
18779 + NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
18780 + {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
18781 + {"NT_STATUS_INVALID_SUB_AUTHORITY",
18782 + NT_STATUS_INVALID_SUB_AUTHORITY},
18783 + {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
18784 + {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
18785 + {"NT_STATUS_INVALID_SECURITY_DESCR",
18786 + NT_STATUS_INVALID_SECURITY_DESCR},
18787 + {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
18788 + {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
18789 + {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
18790 + {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
18791 + {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
18792 + {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
18793 + {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
18794 + {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
18795 + {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
18796 + NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
18797 + {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
18798 + {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
18799 + {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
18800 + {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
18801 + {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
18802 + {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
18803 + {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
18804 + NT_STATUS_RESOURCE_DATA_NOT_FOUND},
18805 + {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
18806 + NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
18807 + {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
18808 + NT_STATUS_RESOURCE_NAME_NOT_FOUND},
18809 + {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
18810 + NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
18811 + {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
18812 + NT_STATUS_FLOAT_DENORMAL_OPERAND},
18813 + {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
18814 + {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
18815 + {"NT_STATUS_FLOAT_INVALID_OPERATION",
18816 + NT_STATUS_FLOAT_INVALID_OPERATION},
18817 + {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
18818 + {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
18819 + {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
18820 + {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
18821 + NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
18822 + {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
18823 + {"NT_STATUS_PRIVILEGED_INSTRUCTION",
18824 + NT_STATUS_PRIVILEGED_INSTRUCTION},
18825 + {"NT_STATUS_TOO_MANY_PAGING_FILES",
18826 + NT_STATUS_TOO_MANY_PAGING_FILES},
18827 + {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
18828 + {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
18829 + NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
18830 + {"NT_STATUS_INSUFFICIENT_RESOURCES",
18831 + NT_STATUS_INSUFFICIENT_RESOURCES},
18832 + {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
18833 + {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
18834 + {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
18835 + {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
18836 + {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
18837 + {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
18838 + {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
18839 + {"NT_STATUS_MEDIA_WRITE_PROTECTED",
18840 + NT_STATUS_MEDIA_WRITE_PROTECTED},
18841 + {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
18842 + {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
18843 + NT_STATUS_INVALID_GROUP_ATTRIBUTES},
18844 + {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
18845 + NT_STATUS_BAD_IMPERSONATION_LEVEL},
18846 + {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
18847 + {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
18848 + {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
18849 + {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
18850 + NT_STATUS_BAD_MASTER_BOOT_RECORD},
18851 + {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
18852 + NT_STATUS_INSTRUCTION_MISALIGNMENT},
18853 + {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
18854 + NT_STATUS_INSTANCE_NOT_AVAILABLE},
18855 + {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
18856 + {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
18857 + {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
18858 + {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
18859 + {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
18860 + {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
18861 + {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
18862 + {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
18863 + {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
18864 + {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
18865 + {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
18866 + {"NT_STATUS_PROFILING_NOT_STARTED",
18867 + NT_STATUS_PROFILING_NOT_STARTED},
18868 + {"NT_STATUS_PROFILING_NOT_STOPPED",
18869 + NT_STATUS_PROFILING_NOT_STOPPED},
18870 + {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
18871 + {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
18872 + {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
18873 + {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
18874 + {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
18875 + {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
18876 + {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
18877 + {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
18878 + NT_STATUS_DEVICE_DOES_NOT_EXIST},
18879 + {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
18880 + {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
18881 + NT_STATUS_ADAPTER_HARDWARE_ERROR},
18882 + {"NT_STATUS_INVALID_NETWORK_RESPONSE",
18883 + NT_STATUS_INVALID_NETWORK_RESPONSE},
18884 + {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
18885 + NT_STATUS_UNEXPECTED_NETWORK_ERROR},
18886 + {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
18887 + {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
18888 + {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
18889 + {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
18890 + {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
18891 + {"NT_STATUS_NETWORK_ACCESS_DENIED",
18892 + NT_STATUS_NETWORK_ACCESS_DENIED},
18893 + {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
18894 + {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
18895 + {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
18896 + {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
18897 + {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
18898 + {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
18899 + {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
18900 + {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
18901 + {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
18902 + {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
18903 + {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
18904 + {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
18905 + NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
18906 + {"NT_STATUS_NO_SECURITY_ON_OBJECT",
18907 + NT_STATUS_NO_SECURITY_ON_OBJECT},
18908 + {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
18909 + {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
18910 + {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
18911 + NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
18912 + {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
18913 + {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
18914 + {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
18915 + {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
18916 + {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
18917 + {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
18918 + {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
18919 + NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
18920 + {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
18921 + {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
18922 + NT_STATUS_INVALID_OPLOCK_PROTOCOL},
18923 + {"NT_STATUS_INTERNAL_DB_CORRUPTION",
18924 + NT_STATUS_INTERNAL_DB_CORRUPTION},
18925 + {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
18926 + {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
18927 + {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
18928 + NT_STATUS_BAD_DESCRIPTOR_FORMAT},
18929 + {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
18930 + {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
18931 + {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
18932 + NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
18933 + {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
18934 + NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
18935 + {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
18936 + NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
18937 + {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
18938 + {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
18939 + {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
18940 + {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
18941 + {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
18942 + {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
18943 + {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
18944 + {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
18945 + {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
18946 + {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
18947 + {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
18948 + {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
18949 + {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
18950 + {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
18951 + {"NT_STATUS_REDIRECTOR_NOT_STARTED",
18952 + NT_STATUS_REDIRECTOR_NOT_STARTED},
18953 + {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
18954 + {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
18955 + {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
18956 + {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
18957 + {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
18958 + {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
18959 + {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
18960 + {"NT_STATUS_BAD_LOGON_SESSION_STATE",
18961 + NT_STATUS_BAD_LOGON_SESSION_STATE},
18962 + {"NT_STATUS_LOGON_SESSION_COLLISION",
18963 + NT_STATUS_LOGON_SESSION_COLLISION},
18964 + {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
18965 + {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
18966 + {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
18967 + {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
18968 + {"NT_STATUS_PROCESS_IS_TERMINATING",
18969 + NT_STATUS_PROCESS_IS_TERMINATING},
18970 + {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
18971 + {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
18972 + {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
18973 + {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
18974 + {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
18975 + {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
18976 + {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
18977 + NT_STATUS_ABIOS_LID_ALREADY_OWNED},
18978 + {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
18979 + {"NT_STATUS_ABIOS_INVALID_COMMAND",
18980 + NT_STATUS_ABIOS_INVALID_COMMAND},
18981 + {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
18982 + {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
18983 + NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
18984 + {"NT_STATUS_ABIOS_INVALID_SELECTOR",
18985 + NT_STATUS_ABIOS_INVALID_SELECTOR},
18986 + {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
18987 + {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
18988 + {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
18989 + {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
18990 + NT_STATUS_INVALID_LDT_DESCRIPTOR},
18991 + {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
18992 + NT_STATUS_INVALID_IMAGE_NE_FORMAT},
18993 + {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
18994 + {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
18995 + {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
18996 + NT_STATUS_MAPPED_FILE_SIZE_ZERO},
18997 + {"NT_STATUS_TOO_MANY_OPENED_FILES",
18998 + NT_STATUS_TOO_MANY_OPENED_FILES},
18999 + {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
19000 + {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
19001 + {"NT_STATUS_INVALID_COMPUTER_NAME",
19002 + NT_STATUS_INVALID_COMPUTER_NAME},
19003 + {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
19004 + {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
19005 + {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
19006 + {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
19007 + {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
19008 + NT_STATUS_MEMBERS_PRIMARY_GROUP},
19009 + {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
19010 + {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
19011 + {"NT_STATUS_THREAD_NOT_IN_PROCESS",
19012 + NT_STATUS_THREAD_NOT_IN_PROCESS},
19013 + {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
19014 + {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
19015 + NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
19016 + {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
19017 + {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
19018 + NT_STATUS_INVALID_IMAGE_LE_FORMAT},
19019 + {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
19020 + {"NT_STATUS_INVALID_IMAGE_PROTECT",
19021 + NT_STATUS_INVALID_IMAGE_PROTECT},
19022 + {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
19023 + {"NT_STATUS_LOGON_SERVER_CONFLICT",
19024 + NT_STATUS_LOGON_SERVER_CONFLICT},
19025 + {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
19026 + NT_STATUS_TIME_DIFFERENCE_AT_DC},
19027 + {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
19028 + NT_STATUS_SYNCHRONIZATION_REQUIRED},
19029 + {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
19030 + {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
19031 + {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
19032 + {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
19033 + {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
19034 + {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
19035 + {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
19036 + {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
19037 + {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
19038 + {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
19039 + {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
19040 + {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
19041 + {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
19042 + {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
19043 + {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
19044 + {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
19045 + {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
19046 + {"NT_STATUS_PAGEFILE_CREATE_FAILED",
19047 + NT_STATUS_PAGEFILE_CREATE_FAILED},
19048 + {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
19049 + {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
19050 + {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
19051 + {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
19052 + NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
19053 + {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
19054 + {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
19055 + {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
19056 + {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
19057 + {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
19058 + {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
19059 + NT_STATUS_SERIAL_NO_DEVICE_INITED},
19060 + {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
19061 + {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
19062 + {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
19063 + {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
19064 + {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
19065 + {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
19066 + {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
19067 + {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
19068 + {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
19069 + {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
19070 + {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
19071 + NT_STATUS_LOGON_TYPE_NOT_GRANTED},
19072 + {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
19073 + {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
19074 + NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
19075 + {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
19076 + NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
19077 + {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
19078 + {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
19079 + NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
19080 + {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
19081 + {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
19082 + {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
19083 + {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
19084 + {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
19085 + NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
19086 + {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
19087 + NT_STATUS_FLOPPY_WRONG_CYLINDER},
19088 + {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
19089 + {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
19090 + {"NT_STATUS_DISK_RECALIBRATE_FAILED",
19091 + NT_STATUS_DISK_RECALIBRATE_FAILED},
19092 + {"NT_STATUS_DISK_OPERATION_FAILED",
19093 + NT_STATUS_DISK_OPERATION_FAILED},
19094 + {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
19095 + {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
19096 + {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
19097 + {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
19098 + {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
19099 + {"NT_STATUS_DEVICE_NOT_PARTITIONED",
19100 + NT_STATUS_DEVICE_NOT_PARTITIONED},
19101 + {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
19102 + {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
19103 + NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
19104 + {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
19105 + {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
19106 + {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
19107 + {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
19108 + {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
19109 + {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
19110 + {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
19111 + {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
19112 + NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
19113 + {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
19114 + {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
19115 + NT_STATUS_CHILD_MUST_BE_VOLATILE},
19116 + {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
19117 + NT_STATUS_DEVICE_CONFIGURATION_ERROR},
19118 + {"NT_STATUS_DRIVER_INTERNAL_ERROR",
19119 + NT_STATUS_DRIVER_INTERNAL_ERROR},
19120 + {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
19121 + {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
19122 + {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
19123 + NT_STATUS_DEVICE_PROTOCOL_ERROR},
19124 + {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
19125 + {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
19126 + {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
19127 + {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
19128 + {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
19129 + {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
19130 + NT_STATUS_TRUSTED_DOMAIN_FAILURE},
19131 + {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
19132 + NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
19133 + {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
19134 + NT_STATUS_EVENTLOG_FILE_CORRUPT},
19135 + {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
19136 + {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
19137 + {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
19138 + NT_STATUS_MUTANT_LIMIT_EXCEEDED},
19139 + {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
19140 + {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
19141 + {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
19142 + {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
19143 + NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
19144 + {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
19145 + {"NT_STATUS_EVENTLOG_FILE_CHANGED",
19146 + NT_STATUS_EVENTLOG_FILE_CHANGED},
19147 + {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
19148 + NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
19149 + {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
19150 + NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
19151 + {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
19152 + NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
19153 + {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
19154 + NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
19155 + {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
19156 + {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
19157 + {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
19158 + {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
19159 + NT_STATUS_RESOURCE_LANG_NOT_FOUND},
19160 + {"NT_STATUS_INSUFF_SERVER_RESOURCES",
19161 + NT_STATUS_INSUFF_SERVER_RESOURCES},
19162 + {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
19163 + {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
19164 + NT_STATUS_INVALID_ADDRESS_COMPONENT},
19165 + {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
19166 + NT_STATUS_INVALID_ADDRESS_WILDCARD},
19167 + {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
19168 + {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
19169 + NT_STATUS_ADDRESS_ALREADY_EXISTS},
19170 + {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
19171 + {"NT_STATUS_CONNECTION_DISCONNECTED",
19172 + NT_STATUS_CONNECTION_DISCONNECTED},
19173 + {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
19174 + {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
19175 + {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
19176 + {"NT_STATUS_TRANSACTION_TIMED_OUT",
19177 + NT_STATUS_TRANSACTION_TIMED_OUT},
19178 + {"NT_STATUS_TRANSACTION_NO_RELEASE",
19179 + NT_STATUS_TRANSACTION_NO_RELEASE},
19180 + {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
19181 + {"NT_STATUS_TRANSACTION_RESPONDED",
19182 + NT_STATUS_TRANSACTION_RESPONDED},
19183 + {"NT_STATUS_TRANSACTION_INVALID_ID",
19184 + NT_STATUS_TRANSACTION_INVALID_ID},
19185 + {"NT_STATUS_TRANSACTION_INVALID_TYPE",
19186 + NT_STATUS_TRANSACTION_INVALID_TYPE},
19187 + {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
19188 + {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
19189 + {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
19190 + NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
19191 + {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
19192 + {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
19193 + NT_STATUS_SYSTEM_PROCESS_TERMINATED},
19194 + {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
19195 + {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
19196 + NT_STATUS_NO_BROWSER_SERVERS_FOUND},
19197 + {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
19198 + {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
19199 + NT_STATUS_DRIVER_CANCEL_TIMEOUT},
19200 + {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
19201 + NT_STATUS_REPLY_MESSAGE_MISMATCH},
19202 + {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
19203 + {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
19204 + NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
19205 + {"NT_STATUS_LOST_WRITEBEHIND_DATA",
19206 + NT_STATUS_LOST_WRITEBEHIND_DATA},
19207 + {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
19208 + NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
19209 + {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
19210 + {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
19211 + {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
19212 + {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
19213 + {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
19214 + {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
19215 + {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
19216 + {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
19217 + {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
19218 + {"NT_STATUS_RETRY", NT_STATUS_RETRY},
19219 + {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
19220 + {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
19221 + {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
19222 + {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
19223 + {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
19224 + {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
19225 + NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
19226 + {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
19227 + {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
19228 + {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
19229 + {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
19230 + {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
19231 + NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
19232 + {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
19233 + NT_STATUS_ADDRESS_NOT_ASSOCIATED},
19234 + {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
19235 + {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
19236 + {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
19237 + {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
19238 + {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
19239 + {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
19240 + {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
19241 + {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
19242 + {"NT_STATUS_BAD_COMPRESSION_BUFFER",
19243 + NT_STATUS_BAD_COMPRESSION_BUFFER},
19244 + {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
19245 + {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
19246 + {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
19247 + NT_STATUS_TIMER_RESOLUTION_NOT_SET},
19248 + {"NT_STATUS_CONNECTION_COUNT_LIMIT",
19249 + NT_STATUS_CONNECTION_COUNT_LIMIT},
19250 + {"NT_STATUS_LOGIN_TIME_RESTRICTION",
19251 + NT_STATUS_LOGIN_TIME_RESTRICTION},
19252 + {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
19253 + NT_STATUS_LOGIN_WKSTA_RESTRICTION},
19254 + {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
19255 + {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
19256 + NT_STATUS_INSUFFICIENT_LOGON_INFO},
19257 + {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
19258 + {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
19259 + NT_STATUS_BAD_SERVICE_ENTRYPOINT},
19260 + {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
19261 + {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
19262 + {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
19263 + {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
19264 + {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
19265 + {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
19266 + {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
19267 + NT_STATUS_LICENSE_QUOTA_EXCEEDED},
19268 + {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
19269 + {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
19270 + {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
19271 + {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
19272 + {"NT_STATUS_UNSUPPORTED_COMPRESSION",
19273 + NT_STATUS_UNSUPPORTED_COMPRESSION},
19274 + {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
19275 + {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
19276 + NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
19277 + {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
19278 + NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
19279 + {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
19280 + NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
19281 + {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
19282 + {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
19283 + {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
19284 + NT_STATUS_QUOTA_LIST_INCONSISTENT},
19285 + {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
19286 + {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
19287 + {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
19288 + {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
19289 + {NULL, 0}
19290 +};
19291 Index: linux-2.4.35.4/fs/cifs/nterr.h
19292 ===================================================================
19293 --- /dev/null
19294 +++ linux-2.4.35.4/fs/cifs/nterr.h
19295 @@ -0,0 +1,556 @@
19296 +/*
19297 + Unix SMB/Netbios implementation.
19298 + Version 1.9.
19299 + NT error code constants
19300 + Copyright (C) Andrew Tridgell 1992-2000
19301 + Copyright (C) John H Terpstra 1996-2000
19302 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000
19303 + Copyright (C) Paul Ashton 1998-2000
19304 +
19305 + This program is free software; you can redistribute it and/or modify
19306 + it under the terms of the GNU General Public License as published by
19307 + the Free Software Foundation; either version 2 of the License, or
19308 + (at your option) any later version.
19309 +
19310 + This program is distributed in the hope that it will be useful,
19311 + but WITHOUT ANY WARRANTY; without even the implied warranty of
19312 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19313 + GNU General Public License for more details.
19314 +
19315 + You should have received a copy of the GNU General Public License
19316 + along with this program; if not, write to the Free Software
19317 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19318 +*/
19319 +
19320 +
19321 +
19322 +#ifndef _NTERR_H
19323 +#define _NTERR_H
19324 +
19325 +struct nt_err_code_struct {
19326 + char *nt_errstr;
19327 + __u32 nt_errcode;
19328 +};
19329 +
19330 +extern const struct nt_err_code_struct nt_errs[];
19331 +
19332 +/* Win32 Status codes. */
19333 +
19334 +#define STATUS_BUFFER_OVERFLOW 0x80000005
19335 +#define STATUS_MORE_ENTRIES 0x0105
19336 +#define ERROR_INVALID_PARAMETER 0x0057
19337 +#define ERROR_INSUFFICIENT_BUFFER 0x007a
19338 +#define STATUS_1804 0x070c
19339 +#define STATUS_NOTIFY_ENUM_DIR 0x010c
19340 +
19341 +/* Win32 Error codes extracted using a loop in smbclient then printing a
19342 + netmon sniff to a file. */
19343 +
19344 +#define NT_STATUS_OK 0x0000
19345 +#define STATUS_SOME_UNMAPPED 0x0107
19346 +#define STATUS_BUFFER_OVERFLOW 0x80000005
19347 +#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
19348 +#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
19349 +#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
19350 +#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
19351 +#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
19352 +#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
19353 +#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
19354 +#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
19355 +#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
19356 +#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
19357 +#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
19358 +#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
19359 +#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
19360 +#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
19361 +#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
19362 +#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
19363 +#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
19364 +#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
19365 +#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
19366 +#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
19367 +#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
19368 +#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
19369 +#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
19370 +#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
19371 +#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
19372 +#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
19373 +#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
19374 +#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
19375 +#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
19376 +#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
19377 +#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
19378 +#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
19379 +#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
19380 +#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
19381 +#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
19382 +#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
19383 +#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
19384 +#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
19385 +#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
19386 +#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
19387 +#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
19388 +#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
19389 +#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
19390 +#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
19391 +#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
19392 +#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
19393 +#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
19394 +#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
19395 +#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
19396 +#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
19397 +#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
19398 +#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
19399 +#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
19400 +#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
19401 +#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
19402 +#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
19403 +#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
19404 +#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
19405 +#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
19406 +#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
19407 +#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
19408 +#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
19409 +#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
19410 +#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
19411 +#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
19412 +#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
19413 +#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
19414 +#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
19415 +#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
19416 +#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
19417 +#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
19418 +#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
19419 +#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
19420 +#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
19421 +#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
19422 +#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
19423 +#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
19424 +#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
19425 +#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
19426 +#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
19427 +#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
19428 +#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
19429 +#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
19430 +#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
19431 +#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
19432 +#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
19433 +#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
19434 +#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
19435 +#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
19436 +#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
19437 +#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
19438 +#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
19439 +#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
19440 +#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
19441 +#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
19442 +#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
19443 +#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
19444 +#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
19445 +#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
19446 +#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
19447 +#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
19448 +#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
19449 +#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
19450 +#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
19451 +#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
19452 +#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
19453 +#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
19454 +#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
19455 +#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
19456 +#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
19457 +#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
19458 +#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
19459 +#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
19460 +#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
19461 +#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
19462 +#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
19463 +#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
19464 +#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
19465 +#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
19466 +#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
19467 +#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
19468 +#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
19469 +#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
19470 +#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
19471 +#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
19472 +#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
19473 +#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
19474 +#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
19475 +#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
19476 +#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
19477 +#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
19478 +#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
19479 +#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
19480 +#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
19481 +#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
19482 +#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
19483 +#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
19484 +#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
19485 +#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
19486 +#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
19487 +#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
19488 +#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
19489 +#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
19490 +#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
19491 +#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
19492 +#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
19493 +#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
19494 +#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
19495 +#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
19496 +#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
19497 +#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
19498 +#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
19499 +#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
19500 +#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
19501 +#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
19502 +#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
19503 +#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
19504 +#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
19505 +#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
19506 +#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
19507 +#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
19508 +#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
19509 +#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
19510 +#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
19511 +#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
19512 +#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
19513 +#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
19514 +#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
19515 +#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
19516 +#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
19517 +#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
19518 +#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
19519 +#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
19520 +#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
19521 +#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
19522 +#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
19523 +#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
19524 +#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
19525 +#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
19526 +#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
19527 +#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
19528 +#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
19529 +#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
19530 +#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
19531 +#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
19532 +#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
19533 +#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
19534 +#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
19535 +#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
19536 +#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
19537 +#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
19538 +#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
19539 +#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
19540 +#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
19541 +#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
19542 +#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
19543 +#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
19544 +#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
19545 +#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
19546 +#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
19547 +#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
19548 +#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
19549 +#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
19550 +#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
19551 +#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
19552 +#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
19553 +#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
19554 +#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
19555 +#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
19556 +#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
19557 +#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
19558 +#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
19559 +#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
19560 +#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
19561 +#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
19562 +#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
19563 +#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
19564 +#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
19565 +#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
19566 +#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
19567 +#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
19568 +#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
19569 +#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
19570 +#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
19571 +#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
19572 +#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
19573 +#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
19574 +#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
19575 +#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
19576 +#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
19577 +#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
19578 +#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
19579 +#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
19580 +#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
19581 +#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
19582 +#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
19583 +#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
19584 +#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
19585 +#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
19586 +#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
19587 +#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
19588 +#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
19589 +#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
19590 +#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
19591 +#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
19592 +#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
19593 +#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
19594 +#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
19595 +#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
19596 +#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
19597 +#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
19598 +#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
19599 +#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
19600 +#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
19601 +#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
19602 +#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
19603 +#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
19604 +#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
19605 +#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
19606 +#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
19607 +#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
19608 +#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
19609 +#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
19610 +#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
19611 +#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
19612 +#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
19613 +#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
19614 +#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
19615 +#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
19616 +#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
19617 +#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
19618 +#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
19619 +#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
19620 +#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
19621 +#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
19622 +#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
19623 +#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
19624 +#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
19625 +#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
19626 +#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
19627 +#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
19628 +#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
19629 +#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
19630 +#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
19631 +#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
19632 +#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
19633 +#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
19634 +#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
19635 +#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
19636 +#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
19637 +#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
19638 +#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
19639 +#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
19640 +#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
19641 +#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
19642 +#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
19643 +#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
19644 +#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
19645 +#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
19646 +#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
19647 +#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
19648 +#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
19649 +#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
19650 +#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
19651 +#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
19652 +#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
19653 +#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
19654 +#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
19655 +#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
19656 +#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
19657 +#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
19658 +#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
19659 +#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
19660 +#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
19661 +#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
19662 +#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
19663 +#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
19664 +#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
19665 +#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
19666 +#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
19667 +#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
19668 +#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
19669 +#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
19670 +#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
19671 +#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
19672 +#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
19673 +#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
19674 +#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
19675 +#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
19676 +#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
19677 +#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
19678 +#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
19679 +#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
19680 +#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
19681 +#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
19682 +#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
19683 +#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
19684 +#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
19685 +#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
19686 +#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
19687 +#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
19688 +#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
19689 +#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
19690 +#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
19691 +#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
19692 +#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
19693 +#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
19694 +#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
19695 +#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
19696 +#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
19697 +#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
19698 +#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
19699 +#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
19700 +#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
19701 +#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
19702 +#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
19703 +#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
19704 +#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
19705 +#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
19706 +#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
19707 +#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
19708 +#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
19709 +#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
19710 +#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
19711 +#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
19712 +#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
19713 +#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
19714 +#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
19715 +#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
19716 +#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
19717 +#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
19718 +#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
19719 +#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
19720 +#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
19721 +#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
19722 +#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
19723 +#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
19724 +#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
19725 +#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
19726 +#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
19727 +#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
19728 +#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
19729 +#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
19730 +#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
19731 +#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
19732 +#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
19733 +#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
19734 +#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
19735 +#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
19736 +#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
19737 +#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
19738 +#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
19739 +#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
19740 +#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
19741 +#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
19742 +#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
19743 +#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
19744 +#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
19745 +#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
19746 +#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
19747 +#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
19748 +#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
19749 +#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
19750 +#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
19751 +#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
19752 +#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
19753 +#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
19754 +#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
19755 +#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
19756 +#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
19757 +#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
19758 +#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
19759 +#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
19760 +#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
19761 +#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
19762 +#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
19763 +#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
19764 +#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
19765 +#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
19766 +#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
19767 +#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
19768 +#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
19769 +#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
19770 +#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
19771 +#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
19772 +#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
19773 +#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
19774 +#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
19775 +#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
19776 +#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
19777 +#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
19778 +#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
19779 +#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
19780 +#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
19781 +#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
19782 +#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
19783 +#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
19784 +#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
19785 +#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
19786 +#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
19787 +#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
19788 +#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
19789 +#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
19790 +#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
19791 +#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
19792 +#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
19793 +#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
19794 +#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
19795 +#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
19796 +#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
19797 +#define NT_STATUS_RETRY 0xC0000000 | 0x022d
19798 +#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
19799 +#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
19800 +#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
19801 +#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
19802 +#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
19803 +#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
19804 +#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
19805 +#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
19806 +#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
19807 +#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
19808 +#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
19809 +#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
19810 +#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
19811 +#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
19812 +#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
19813 +#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
19814 +#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
19815 +#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
19816 +#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
19817 +#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
19818 +#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
19819 +#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
19820 +#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
19821 +#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
19822 +#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
19823 +#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
19824 +#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
19825 +#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
19826 +#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
19827 +#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
19828 +#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
19829 +#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
19830 +#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
19831 +#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
19832 +#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
19833 +#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
19834 +#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
19835 +#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
19836 +#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
19837 +#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
19838 +#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
19839 +#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
19840 +#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
19841 +#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
19842 +#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
19843 +#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
19844 +#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
19845 +#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
19846 +#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
19847 +#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
19848 +#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
19849 +#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
19850 +
19851 +#endif /* _NTERR_H */
19852 Index: linux-2.4.35.4/fs/cifs/ntlmssp.h
19853 ===================================================================
19854 --- /dev/null
19855 +++ linux-2.4.35.4/fs/cifs/ntlmssp.h
19856 @@ -0,0 +1,101 @@
19857 +/*
19858 + * fs/cifs/ntlmssp.h
19859 + *
19860 + * Copyright (c) International Business Machines Corp., 2002
19861 + * Author(s): Steve French (sfrench@us.ibm.com)
19862 + *
19863 + * This library is free software; you can redistribute it and/or modify
19864 + * it under the terms of the GNU Lesser General Public License as published
19865 + * by the Free Software Foundation; either version 2.1 of the License, or
19866 + * (at your option) any later version.
19867 + *
19868 + * This library is distributed in the hope that it will be useful,
19869 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19870 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19871 + * the GNU Lesser General Public License for more details.
19872 + *
19873 + * You should have received a copy of the GNU Lesser General Public License
19874 + * along with this library; if not, write to the Free Software
19875 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19876 + */
19877 +
19878 +#pragma pack(1)
19879 +
19880 +#define NTLMSSP_SIGNATURE "NTLMSSP"
19881 +/* Message Types */
19882 +#define NtLmNegotiate 1
19883 +#define NtLmChallenge 2
19884 +#define NtLmAuthenticate 3
19885 +#define UnknownMessage 8
19886 +
19887 +/* Negotiate Flags */
19888 +#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
19889 +#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
19890 +#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
19891 +#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
19892 +#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
19893 +#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
19894 +#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
19895 +#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
19896 +#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
19897 +#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
19898 +#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
19899 +#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
19900 +#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
19901 +#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
19902 +#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
19903 +#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
19904 +#define NTLMSSP_REQUEST_INIT_RESP 0x100000
19905 +#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
19906 +#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
19907 +#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
19908 +#define NTLMSSP_NEGOTIATE_128 0x20000000
19909 +#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
19910 +#define NTLMSSP_NEGOTIATE_56 0x80000000
19911 +
19912 +/* Although typedefs are not commonly used for structure definitions */
19913 +/* in the Linux kernel, in this particular case they are useful */
19914 +/* to more closely match the standards document for NTLMSSP from */
19915 +/* OpenGroup and to make the code more closely match the standard in */
19916 +/* appearance */
19917 +
19918 +typedef struct _SECURITY_BUFFER {
19919 + __u16 Length;
19920 + __u16 MaximumLength;
19921 + __u32 Buffer; /* offset to buffer */
19922 +} SECURITY_BUFFER;
19923 +
19924 +typedef struct _NEGOTIATE_MESSAGE {
19925 + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19926 + __u32 MessageType; /* 1 */
19927 + __u32 NegotiateFlags;
19928 + SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
19929 + SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
19930 + char DomainString[0];
19931 + /* followed by WorkstationString */
19932 +} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
19933 +
19934 +typedef struct _CHALLENGE_MESSAGE {
19935 + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19936 + __u32 MessageType; /* 2 */
19937 + SECURITY_BUFFER TargetName;
19938 + __u32 NegotiateFlags;
19939 + __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
19940 + __u8 Reserved[8];
19941 + SECURITY_BUFFER TargetInfoArray;
19942 +} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
19943 +
19944 +typedef struct _AUTHENTICATE_MESSAGE {
19945 + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19946 + __u32 MessageType; /* 3 */
19947 + SECURITY_BUFFER LmChallengeResponse;
19948 + SECURITY_BUFFER NtChallengeResponse;
19949 + SECURITY_BUFFER DomainName;
19950 + SECURITY_BUFFER UserName;
19951 + SECURITY_BUFFER WorkstationName;
19952 + SECURITY_BUFFER SessionKey;
19953 + __u32 NegotiateFlags;
19954 + char UserString[0];
19955 +} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
19956 +
19957 +#pragma pack() /* resume default structure packing */
19958 Index: linux-2.4.35.4/fs/cifs/README
19959 ===================================================================
19960 --- /dev/null
19961 +++ linux-2.4.35.4/fs/cifs/README
19962 @@ -0,0 +1,356 @@
19963 +The CIFS VFS support for Linux supports many advanced network filesystem
19964 +features such as heirarchical dfs like namespace, hardlinks, locking and more.
19965 +It was designed to comply with the SNIA CIFS Technical Reference (which
19966 +supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
19967 +practical interoperability with Windows 2000, Windows XP, Samba and equivalent
19968 +servers.
19969 +
19970 +For questions or bug reports please contact:
19971 + sfrench@samba.org (sfrench@us.ibm.com)
19972 +
19973 +Build instructions:
19974 +==================
19975 +For Linux 2.4:
19976 +1) Get the kernel source (e.g.from http://www.kernel.org)
19977 +and download the cifs vfs source (see the project page
19978 +at http://us1.samba.org/samba/Linux_CIFS_client.html)
19979 +and change directory into the top of the kernel directory
19980 +then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
19981 +to add the cifs vfs to your kernel configure options if
19982 +it has not already been added (e.g. current SuSE and UL
19983 +users do not need to apply the cifs_24.patch since the cifs vfs is
19984 +already in the kernel configure menu) and then
19985 +mkdir linux/fs/cifs and then copy the current cifs vfs files from
19986 +the cifs download to your kernel build directory e.g.
19987 +
19988 + cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
19989 +
19990 +2) make menuconfig (or make xconfig)
19991 +3) select cifs from within the network filesystem choices
19992 +4) save and exit
19993 +5) make dep
19994 +6) make modules (or "make" if CIFS VFS not to be built as a module)
19995 +
19996 +For Linux 2.5:
19997 +1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
19998 +at bk://linux.bkbits.net/linux-2.5) and change directory into the top
19999 +of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
20000 +2) make menuconfig (or make xconfig)
20001 +3) select cifs from within the network filesystem choices
20002 +4) save and exit
20003 +5) make
20004 +
20005 +
20006 +Installation instructions:
20007 +=========================
20008 +If you have built the CIFS vfs as module (successfully) simply
20009 +type "make modules_install" (or if you prefer, manually copy the file to
20010 +the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
20011 +
20012 +If you have built the CIFS vfs into the kernel itself, follow the instructions
20013 +for your distribution on how to install a new kernel (usually you
20014 +would simply type "make install").
20015 +
20016 +If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
20017 +the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
20018 +similar files reside (usually /sbin). Although the helper software is not
20019 +required, mount.cifs is recommended. Eventually the Samba 3.0 utility program
20020 +"net" may also be helpful since it may someday provide easier mount syntax for
20021 +users who are used to Windows e.g. net use <mount point> <UNC name or cifs URL>
20022 +Note that running the Winbind pam/nss module (logon service) on all of your
20023 +Linux clients is useful in mapping Uids and Gids consistently across the
20024 +domain to the proper network user. The mount.cifs mount helper can be
20025 +trivially built from Samba 3.0 or later source e.g. by executing:
20026 +
20027 + gcc samba/source/client/mount.cifs.c -o mount.cifs
20028 +
20029 +Note that when the mount.cifs utility is run suid (allowing user mounts),
20030 +in order to reduce risks, the "nosuid" mount flag is passed in on mount to
20031 +disallow execution of an suid program mounted on the remote target.
20032 +When mount is executed as root, nosuid is not passed in by default,
20033 +and execution of suid programs on the remote target would be enabled
20034 +by default. This can be changed, as with nfs and other filesystems,
20035 +by simply specifying "nosuid" among the mount options. For user mounts
20036 +though to be able to pass the suid flag to mount requires rebuilding
20037 +mount.cifs with the following flag:
20038 +
20039 + gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
20040 +
20041 +There is a corresponding manual page for cifs mounting in the Samba 3.0 and
20042 +later source tree in docs/manpages/mount.cifs.8
20043 +
20044 +Samba Considerations
20045 +====================
20046 +To get the maximum benefit from the CIFS VFS, we recommend using a server that
20047 +supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
20048 +Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
20049 +Note that uid, gid and file permissions will display default values if you do
20050 +not have a server that supports the Unix extensions for CIFS (such as Samba
20051 +2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
20052 +the line:
20053 +
20054 + unix extensions = yes
20055 +
20056 +to your smb.conf file on the server. Note that the following smb.conf settings
20057 +are also useful (on the Samba server) when the majority of clients are Unix or
20058 +Linux:
20059 +
20060 + case sensitive = yes
20061 + delete readonly = yes
20062 + ea support = yes
20063 +
20064 +Note that ea support is required for supporting Linux xattrs.
20065 +Some administrators also change the "map archive" and the "create mask"
20066 +parameters from their default values. Creating special devices (mknod)
20067 +remotely may require specifying a mkdev function to Samba if you are not using
20068 +Samba 3.0.5 or later. For more information on these see the manual pages
20069 +("man smb.conf") on the Samba server system. Note that the cifs vfs,
20070 +unlike the smbfs vfs, does not read the smb.conf on the client system
20071 +(the few optional settings are passed in on mount via -o parameters instead).
20072 +Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
20073 +open files (required for strict POSIX compliance). Windows Servers already
20074 +supported this feature. Samba server does not allow symlinks that refer to files
20075 +outside of the share, so in Samba versions prior to 3.0.5, most symlinks to
20076 +files with absolute paths (ie beginning with slash) such as:
20077 + ln -s /mnt/foo bar
20078 +would be forbidden. Samba 3.0.5 server or later includes the ability to create
20079 +such symlinks safely by converting unsafe symlinks (ie symlinks to server
20080 +files that are outside of the share) to a samba specific format on the server
20081 +that is ignored by local server applications and non-cifs clients and that will
20082 +not be traversed by the Samba server). This is opaque to the Linux client
20083 +application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
20084 +later, but only for remote clients using the CIFS Unix extensions, and will
20085 +be invisbile to Windows clients and typically will not affect local
20086 +applications running on the same server as Samba.
20087 +
20088 +Use instructions:
20089 +================
20090 +Once the CIFS VFS support is built into the kernel or installed as a module
20091 +(cifs.o), you can use mount syntax like the following to access Samba or Windows
20092 +servers:
20093 +
20094 + mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
20095 +
20096 +Before -o the option -v may be specified to make the mount.cifs
20097 +mount helper display the mount steps more verbosely.
20098 +After -o the following commonly used cifs vfs specific options
20099 +are supported:
20100 +
20101 + user=<username>
20102 + pass=<password>
20103 + domain=<domain name>
20104 +
20105 +Other cifs mount options are described below. Use of TCP names (in addition to
20106 +ip addresses) is available if the mount helper (mount.cifs) is installed. If
20107 +you do not trust the server to which are mounted, or if you do not have
20108 +cifs signing enabled (and the physical network is insecure), consider use
20109 +of the standard mount options "noexec" and "nosuid" to reduce the risk of
20110 +running an altered binary on your local system (downloaded from a hostile server
20111 +or altered by a hostile router).
20112 +
20113 +When using the mount helper mount.cifs, passwords may be specified via alternate
20114 +mechanisms, instead of specifying it after -o using the normal "pass=" syntax
20115 +on the command line:
20116 +1) By including it in a credential file. Specify credentials=filename as one
20117 +of the mount options. Credential files contain two lines
20118 + username=someuser
20119 + password=your_password
20120 +2) By specifying the password in the PASSWD environment variable (similarly
20121 +the user name can be taken from the USER environment variable).
20122 +3) By specifying the password in a file by name via PASSWD_FILE
20123 +4) By specifying the password in a file by file descriptor via PASSWD_FD
20124 +
20125 +If no password is provided, mount.cifs will prompt for password entry
20126 +
20127 +Restrictions
20128 +============
20129 +Servers must support the NTLM SMB dialect (which is the most recent, supported
20130 +by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
20131 +Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
20132 +1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
20133 +problem as most servers support this. IPv6 support is planned for the future.
20134 +
20135 +CIFS VFS Mount Options
20136 +======================
20137 +A partial list of the supported mount options follows:
20138 + user The user name to use when trying to establish
20139 + the CIFS session.
20140 + password The user password. If the mount helper is
20141 + installed, the user will be prompted for password
20142 + if it is not supplied.
20143 + ip The ip address of the target server
20144 + unc The target server Universal Network Name (export) to
20145 + mount.
20146 + domain Set the SMB/CIFS workgroup name prepended to the
20147 + username during CIFS session establishment
20148 + uid If CIFS Unix extensions are not supported by the server
20149 + this overrides the default uid for inodes. For mounts to
20150 + servers which do support the CIFS Unix extensions, such
20151 + as a properly configured Samba server, the server provides
20152 + the uid, gid and mode. For servers which do not support
20153 + the Unix extensions, the default uid (and gid) returned on
20154 + lookup of existing files is the uid (gid) of the person
20155 + who executed the mount (root, except when mount.cifs
20156 + is configured setuid for user mounts) unless the "uid="
20157 + (gid) mount option is specified. For the uid (gid) of newly
20158 + created files and directories, ie files created since
20159 + the last mount of the server share, the expected uid
20160 + (gid) is cached as as long as the inode remains in
20161 + memory on the client. Also note that permission
20162 + checks (authorization checks) on accesses to a file occur
20163 + at the server, but there are cases in which an administrator
20164 + may want to restrict at the client as well. For those
20165 + servers which do not report a uid/gid owner
20166 + (such as Windows), permissions can also be checked at the
20167 + client, and a crude form of client side permission checking
20168 + can be enabled by specifying file_mode and dir_mode on
20169 + the client
20170 + gid If CIFS Unix extensions are not supported by the server
20171 + this overrides the default gid for inodes.
20172 + file_mode If CIFS Unix extensions are not supported by the server
20173 + this overrides the default mode for file inodes.
20174 + dir_mode If CIFS Unix extensions are not supported by the server
20175 + this overrides the default mode for directory inodes.
20176 + port attempt to contact the server on this tcp port, before
20177 + trying the usual ports (port 445, then 139).
20178 + iocharset Codepage used to convert local path names to and from
20179 + Unicode. Unicode is used by default for network path
20180 + names if the server supports it. If iocharset is
20181 + not specified then the nls_default specified
20182 + during the local client kernel build will be used.
20183 + If server does not support Unicode, this parameter is
20184 + unused.
20185 + rsize default read size
20186 + wsize default write size
20187 + rw mount the network share read-write (note that the
20188 + server may still consider the share read-only)
20189 + ro mount network share read-only
20190 + version used to distinguish different versions of the
20191 + mount helper utility (not typically needed)
20192 + sep if first mount option (after the -o), overrides
20193 + the comma as the separator between the mount
20194 + parms. e.g.
20195 + -o user=myname,password=mypassword,domain=mydom
20196 + could be passed instead with period as the separator by
20197 + -o sep=.user=myname.password=mypassword.domain=mydom
20198 + this might be useful when comma is contained within username
20199 + or password or domain. This option is less important
20200 + when the cifs mount helper cifs.mount (version 1.1 or later)
20201 + is used.
20202 + nosuid Do not allow remote executables with the suid bit
20203 + program to be executed. This is only meaningful for mounts
20204 + to servers such as Samba which support the CIFS Unix Extensions.
20205 + If you do not trust the servers in your network (your mount
20206 + targets) it is recommended that you specify this option for
20207 + greater security.
20208 + suid Allow remote files on this mountpoint with suid enabled to
20209 + be executed (default for mounts when executed as root,
20210 + nosuid is default for user mounts).
20211 + credentials Although ignored by the cifs kernel component, it is used by
20212 + the mount helper, mount.cifs. When mount.cifs is installed it
20213 + opens and reads the credential file specified in order
20214 + to obtain the userid and password arguments which are passed to
20215 + the cifs vfs.
20216 + guest Although ignored by the kernel component, the mount.cifs
20217 + mount helper will not prompt the user for a password
20218 + if guest is specified on the mount options. If no
20219 + password is specified a null password will be used.
20220 +
20221 +The mount.cifs mount helper also accepts a few mount options before -o
20222 +including:
20223 +
20224 + -S take password from stdin (equivalent to setting the environment
20225 + variable "PASSWD_FD=0"
20226 + -V print mount.cifs version
20227 + -? display simple usage information
20228 +
20229 +With recent 2.6 kernel versions of modutils, the version of the cifs kernel
20230 +module can be displayed via modinfo.
20231 +
20232 +Misc /proc/fs/cifs Flags and Debug Info
20233 +=======================================
20234 +Informational pseudo-files:
20235 +DebugData Displays information about active CIFS sessions
20236 + and shares.
20237 +Stats Lists summary resource usage information as well as per
20238 + share statistics, if CONFIG_CIFS_STATS in enabled
20239 + in the kernel configuration.
20240 +
20241 +Configuration pseudo-files:
20242 +MultiuserMount If set to one, more than one CIFS session to
20243 + the same server ip address can be established
20244 + if more than one uid accesses the same mount
20245 + point and if the uids user/password mapping
20246 + information is available. (default is 0)
20247 +PacketSigningEnabled If set to one, cifs packet signing is enabled
20248 + and will be used if the server requires
20249 + it. If set to two, cifs packet signing is
20250 + required even if the server considers packet
20251 + signing optional. (default 1)
20252 +cifsFYI If set to one, additional debug information is
20253 + logged to the system error log. (default 0)
20254 +ExtendedSecurity If set to one, SPNEGO session establishment
20255 + is allowed which enables more advanced
20256 + secure CIFS session establishment (default 0)
20257 +NTLMV2Enabled If set to one, more secure password hashes
20258 + are used when the server supports them and
20259 + when kerberos is not negotiated (default 0)
20260 +traceSMB If set to one, debug information is logged to the
20261 + system error log with the start of smb requests
20262 + and responses (default 0)
20263 +LookupCacheEnable If set to one, inode information is kept cached
20264 + for one second improving performance of lookups
20265 + (default 1)
20266 +OplockEnabled If set to one, safe distributed caching enabled.
20267 + (default 1)
20268 +LinuxExtensionsEnabled If set to one then the client will attempt to
20269 + use the CIFS "UNIX" extensions which are optional
20270 + protocol enhancements that allow CIFS servers
20271 + to return accurate UID/GID information as well
20272 + as support symbolic links. If you use servers
20273 + such as Samba that support the CIFS Unix
20274 + extensions but do not want to use symbolic link
20275 + support and want to map the uid and gid fields
20276 + to values supplied at mount (rather than the
20277 + actual values, then set this to zero. (default 1)
20278 +
20279 +These experimental features and tracing can be enabled by changing flags in
20280 +/proc/fs/cifs (after the cifs module has been installed or built into the
20281 +kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
20282 +tracing to the kernel message log type:
20283 +
20284 + echo 1 > /proc/fs/cifs/cifsFYI
20285 +
20286 +and for more extensive tracing including the start of smb requests and responses
20287 +
20288 + echo 1 > /proc/fs/cifs/traceSMB
20289 +
20290 +Three other experimental features are under development and to test
20291 +require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
20292 +
20293 + CONFIG_CIFS_QUOTA
20294 +
20295 + CONFIG_CIFS_XATTR
20296 +
20297 + CONFIG_CIFS_FCNTL (fcntl needed for support of directory change
20298 + notification and perhaps later for file leases)
20299 +
20300 +Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData
20301 +if the kernel was configured with cifs statistics enabled. The statistics
20302 +represent the number of successful (ie non-zero return code from the server)
20303 +SMB responses to some of the more common commands (open, delete, mkdir etc.).
20304 +Also recorded is the total bytes read and bytes written to the server for
20305 +that share. Note that due to client caching effects this can be less than the
20306 +number of bytes read and written by the application running on the client.
20307 +The statistics for the number of total SMBs and oplock breaks are different in
20308 +that they represent all for that share, not just those for which the server
20309 +returned success.
20310 +
20311 +Also note that "cat /proc/fs/cifs/DebugData" will display information about
20312 +the active sessions and the shares that are mounted. Note: NTLMv2 enablement
20313 +will not work since they its implementation is not quite complete yet.
20314 +Do not alter these configuration values unless you are doing specific testing.
20315 +Enabling extended security works to Windows 2000 Workstations and XP but not to
20316 +Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
20317 +(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
20318 +complete in the CIFS VFS yet).
20319 Index: linux-2.4.35.4/fs/cifs/rfc1002pdu.h
20320 ===================================================================
20321 --- /dev/null
20322 +++ linux-2.4.35.4/fs/cifs/rfc1002pdu.h
20323 @@ -0,0 +1,79 @@
20324 +/*
20325 + * fs/cifs/rfc1002pdu.h
20326 + *
20327 + * Protocol Data Unit definitions for RFC 1001/1002 support
20328 + *
20329 + * Copyright (c) International Business Machines Corp., 2004
20330 + * Author(s): Steve French (sfrench@us.ibm.com)
20331 + *
20332 + * This library is free software; you can redistribute it and/or modify
20333 + * it under the terms of the GNU Lesser General Public License as published
20334 + * by the Free Software Foundation; either version 2.1 of the License, or
20335 + * (at your option) any later version.
20336 + *
20337 + * This library is distributed in the hope that it will be useful,
20338 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20339 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20340 + * the GNU Lesser General Public License for more details.
20341 + *
20342 + * You should have received a copy of the GNU Lesser General Public License
20343 + * along with this library; if not, write to the Free Software
20344 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20345 + */
20346 +
20347 +#pragma pack(1)
20348 +
20349 +/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
20350 +
20351 + /* RFC 1002 session packet types */
20352 +#define RFC1002_SESSION_MESASAGE 0x00
20353 +#define RFC1002_SESSION_REQUEST 0x81
20354 +#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
20355 +#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
20356 +#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
20357 +#define RFC1002_SESSION_KEEP_ALIVE 0x85
20358 +
20359 + /* RFC 1002 flags (only one defined */
20360 +#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
20361 +
20362 +struct rfc1002_session_packet {
20363 + __u8 type;
20364 + __u8 flags;
20365 + __u16 length;
20366 + union {
20367 + struct {
20368 + __u8 called_len;
20369 + __u8 called_name[32];
20370 + __u8 scope1; /* null */
20371 + __u8 calling_len;
20372 + __u8 calling_name[32];
20373 + __u8 scope2; /* null */
20374 + } session_req;
20375 + struct {
20376 + __u32 retarget_ip_addr;
20377 + __u16 port;
20378 + } retarget_resp;
20379 + __u8 neg_ses_resp_error_code;
20380 + /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
20381 + SESSION_KEEP_ALIVE packet also does not include a trailer.
20382 + Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
20383 + } trailer;
20384 +};
20385 +
20386 +/* Negative Session Response error codes */
20387 +#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
20388 +#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
20389 +#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
20390 +#define RFC1002_INSUFFICIENT_RESOURCE 0x83
20391 +#define RFC1002_UNSPECIFIED_ERROR 0x8F
20392 +
20393 +/* RFC 1002 Datagram service packets are not defined here as they
20394 +are not needed for the network filesystem client unless we plan on
20395 +implementing broadcast resolution of the server ip address (from
20396 +server netbios name). Currently server names are resolved only via DNS
20397 +(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
20398 +
20399 +#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
20400 +
20401 +#pragma pack() /* resume default structure packing */
20402 +
20403 Index: linux-2.4.35.4/fs/cifs/smbdes.c
20404 ===================================================================
20405 --- /dev/null
20406 +++ linux-2.4.35.4/fs/cifs/smbdes.c
20407 @@ -0,0 +1,408 @@
20408 +/*
20409 + Unix SMB/Netbios implementation.
20410 + Version 1.9.
20411 +
20412 + a partial implementation of DES designed for use in the
20413 + SMB authentication protocol
20414 +
20415 + Copyright (C) Andrew Tridgell 1998
20416 + Modified by Steve French (sfrench@us.ibm.com) 2002,2004
20417 +
20418 + This program is free software; you can redistribute it and/or modify
20419 + it under the terms of the GNU General Public License as published by
20420 + the Free Software Foundation; either version 2 of the License, or
20421 + (at your option) any later version.
20422 +
20423 + This program is distributed in the hope that it will be useful,
20424 + but WITHOUT ANY WARRANTY; without even the implied warranty of
20425 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20426 + GNU General Public License for more details.
20427 +
20428 + You should have received a copy of the GNU General Public License
20429 + along with this program; if not, write to the Free Software
20430 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20431 +*/
20432 +
20433 +/* NOTES:
20434 +
20435 + This code makes no attempt to be fast! In fact, it is a very
20436 + slow implementation
20437 +
20438 + This code is NOT a complete DES implementation. It implements only
20439 + the minimum necessary for SMB authentication, as used by all SMB
20440 + products (including every copy of Microsoft Windows95 ever sold)
20441 +
20442 + In particular, it can only do a unchained forward DES pass. This
20443 + means it is not possible to use this code for encryption/decryption
20444 + of data, instead it is only useful as a "hash" algorithm.
20445 +
20446 + There is no entry point into this code that allows normal DES operation.
20447 +
20448 + I believe this means that this code does not come under ITAR
20449 + regulations but this is NOT a legal opinion. If you are concerned
20450 + about the applicability of ITAR regulations to this code then you
20451 + should confirm it for yourself (and maybe let me know if you come
20452 + up with a different answer to the one above)
20453 +*/
20454 +#include <linux/slab.h>
20455 +#define uchar unsigned char
20456 +
20457 +static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
20458 + 1, 58, 50, 42, 34, 26, 18,
20459 + 10, 2, 59, 51, 43, 35, 27,
20460 + 19, 11, 3, 60, 52, 44, 36,
20461 + 63, 55, 47, 39, 31, 23, 15,
20462 + 7, 62, 54, 46, 38, 30, 22,
20463 + 14, 6, 61, 53, 45, 37, 29,
20464 + 21, 13, 5, 28, 20, 12, 4
20465 +};
20466 +
20467 +static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
20468 + 3, 28, 15, 6, 21, 10,
20469 + 23, 19, 12, 4, 26, 8,
20470 + 16, 7, 27, 20, 13, 2,
20471 + 41, 52, 31, 37, 47, 55,
20472 + 30, 40, 51, 45, 33, 48,
20473 + 44, 49, 39, 56, 34, 53,
20474 + 46, 42, 50, 36, 29, 32
20475 +};
20476 +
20477 +static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
20478 + 60, 52, 44, 36, 28, 20, 12, 4,
20479 + 62, 54, 46, 38, 30, 22, 14, 6,
20480 + 64, 56, 48, 40, 32, 24, 16, 8,
20481 + 57, 49, 41, 33, 25, 17, 9, 1,
20482 + 59, 51, 43, 35, 27, 19, 11, 3,
20483 + 61, 53, 45, 37, 29, 21, 13, 5,
20484 + 63, 55, 47, 39, 31, 23, 15, 7
20485 +};
20486 +
20487 +static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
20488 + 4, 5, 6, 7, 8, 9,
20489 + 8, 9, 10, 11, 12, 13,
20490 + 12, 13, 14, 15, 16, 17,
20491 + 16, 17, 18, 19, 20, 21,
20492 + 20, 21, 22, 23, 24, 25,
20493 + 24, 25, 26, 27, 28, 29,
20494 + 28, 29, 30, 31, 32, 1
20495 +};
20496 +
20497 +static uchar perm5[32] = { 16, 7, 20, 21,
20498 + 29, 12, 28, 17,
20499 + 1, 15, 23, 26,
20500 + 5, 18, 31, 10,
20501 + 2, 8, 24, 14,
20502 + 32, 27, 3, 9,
20503 + 19, 13, 30, 6,
20504 + 22, 11, 4, 25
20505 +};
20506 +
20507 +static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
20508 + 39, 7, 47, 15, 55, 23, 63, 31,
20509 + 38, 6, 46, 14, 54, 22, 62, 30,
20510 + 37, 5, 45, 13, 53, 21, 61, 29,
20511 + 36, 4, 44, 12, 52, 20, 60, 28,
20512 + 35, 3, 43, 11, 51, 19, 59, 27,
20513 + 34, 2, 42, 10, 50, 18, 58, 26,
20514 + 33, 1, 41, 9, 49, 17, 57, 25
20515 +};
20516 +
20517 +static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
20518 +
20519 +static uchar sbox[8][4][16] = {
20520 + {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
20521 + {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
20522 + {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
20523 + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
20524 +
20525 + {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
20526 + {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
20527 + {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
20528 + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
20529 +
20530 + {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
20531 + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
20532 + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
20533 + {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
20534 +
20535 + {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
20536 + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
20537 + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
20538 + {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
20539 +
20540 + {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
20541 + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
20542 + {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
20543 + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
20544 +
20545 + {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
20546 + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
20547 + {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
20548 + {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
20549 +
20550 + {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
20551 + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
20552 + {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
20553 + {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
20554 +
20555 + {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
20556 + {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
20557 + {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
20558 + {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
20559 +};
20560 +
20561 +static void
20562 +permute(char *out, char *in, uchar * p, int n)
20563 +{
20564 + int i;
20565 + for (i = 0; i < n; i++)
20566 + out[i] = in[p[i] - 1];
20567 +}
20568 +
20569 +static void
20570 +lshift(char *d, int count, int n)
20571 +{
20572 + char out[64];
20573 + int i;
20574 + for (i = 0; i < n; i++)
20575 + out[i] = d[(i + count) % n];
20576 + for (i = 0; i < n; i++)
20577 + d[i] = out[i];
20578 +}
20579 +
20580 +static void
20581 +concat(char *out, char *in1, char *in2, int l1, int l2)
20582 +{
20583 + while (l1--)
20584 + *out++ = *in1++;
20585 + while (l2--)
20586 + *out++ = *in2++;
20587 +}
20588 +
20589 +static void
20590 +xor(char *out, char *in1, char *in2, int n)
20591 +{
20592 + int i;
20593 + for (i = 0; i < n; i++)
20594 + out[i] = in1[i] ^ in2[i];
20595 +}
20596 +
20597 +static void
20598 +dohash(char *out, char *in, char *key, int forw)
20599 +{
20600 + int i, j, k;
20601 + char *pk1;
20602 + char c[28];
20603 + char d[28];
20604 + char *cd;
20605 + char ki[16][48];
20606 + char *pd1;
20607 + char l[32], r[32];
20608 + char *rl;
20609 +
20610 + /* Have to reduce stack usage */
20611 + pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
20612 + if(pk1 == NULL)
20613 + return;
20614 +
20615 + cd = pk1 + 56;
20616 + pd1= cd + 56;
20617 + rl = pd1 + 64;
20618 +
20619 + permute(pk1, key, perm1, 56);
20620 +
20621 + for (i = 0; i < 28; i++)
20622 + c[i] = pk1[i];
20623 + for (i = 0; i < 28; i++)
20624 + d[i] = pk1[i + 28];
20625 +
20626 + for (i = 0; i < 16; i++) {
20627 + lshift(c, sc[i], 28);
20628 + lshift(d, sc[i], 28);
20629 +
20630 + concat(cd, c, d, 28, 28);
20631 + permute(ki[i], cd, perm2, 48);
20632 + }
20633 +
20634 + permute(pd1, in, perm3, 64);
20635 +
20636 + for (j = 0; j < 32; j++) {
20637 + l[j] = pd1[j];
20638 + r[j] = pd1[j + 32];
20639 + }
20640 +
20641 + for (i = 0; i < 16; i++) {
20642 + char *er; /* er[48] */
20643 + char *erk; /* erk[48] */
20644 + char b[8][6];
20645 + char *cb; /* cb[32] */
20646 + char *pcb; /* pcb[32] */
20647 + char *r2; /* r2[32] */
20648 +
20649 + er = kmalloc(48+48+32+32+32, GFP_KERNEL);
20650 + if(er == NULL) {
20651 + kfree(pk1);
20652 + return;
20653 + }
20654 + erk = er+48;
20655 + cb = erk+48;
20656 + pcb = cb+32;
20657 + r2 = pcb+32;
20658 +
20659 + permute(er, r, perm4, 48);
20660 +
20661 + xor(erk, er, ki[forw ? i : 15 - i], 48);
20662 +
20663 + for (j = 0; j < 8; j++)
20664 + for (k = 0; k < 6; k++)
20665 + b[j][k] = erk[j * 6 + k];
20666 +
20667 + for (j = 0; j < 8; j++) {
20668 + int m, n;
20669 + m = (b[j][0] << 1) | b[j][5];
20670 +
20671 + n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
20672 + 1) | b[j][4];
20673 +
20674 + for (k = 0; k < 4; k++)
20675 + b[j][k] =
20676 + (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
20677 + }
20678 +
20679 + for (j = 0; j < 8; j++)
20680 + for (k = 0; k < 4; k++)
20681 + cb[j * 4 + k] = b[j][k];
20682 + permute(pcb, cb, perm5, 32);
20683 +
20684 + xor(r2, l, pcb, 32);
20685 +
20686 + for (j = 0; j < 32; j++)
20687 + l[j] = r[j];
20688 +
20689 + for (j = 0; j < 32; j++)
20690 + r[j] = r2[j];
20691 +
20692 + kfree(er);
20693 + }
20694 +
20695 + concat(rl, r, l, 32, 32);
20696 +
20697 + permute(out, rl, perm6, 64);
20698 + kfree(pk1);
20699 +}
20700 +
20701 +static void
20702 +str_to_key(unsigned char *str, unsigned char *key)
20703 +{
20704 + int i;
20705 +
20706 + key[0] = str[0] >> 1;
20707 + key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
20708 + key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
20709 + key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
20710 + key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
20711 + key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
20712 + key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
20713 + key[7] = str[6] & 0x7F;
20714 + for (i = 0; i < 8; i++) {
20715 + key[i] = (key[i] << 1);
20716 + }
20717 +}
20718 +
20719 +static void
20720 +smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
20721 +{
20722 + int i;
20723 + char *outb; /* outb[64] */
20724 + char *inb; /* inb[64] */
20725 + char *keyb; /* keyb[64] */
20726 + unsigned char key2[8];
20727 +
20728 + outb = kmalloc(64 * 3,GFP_KERNEL);
20729 + if(outb == NULL)
20730 + return;
20731 +
20732 + inb = outb + 64;
20733 + keyb = inb + 64;
20734 +
20735 + str_to_key(key, key2);
20736 +
20737 + for (i = 0; i < 64; i++) {
20738 + inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
20739 + keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
20740 + outb[i] = 0;
20741 + }
20742 +
20743 + dohash(outb, inb, keyb, forw);
20744 +
20745 + for (i = 0; i < 8; i++) {
20746 + out[i] = 0;
20747 + }
20748 +
20749 + for (i = 0; i < 64; i++) {
20750 + if (outb[i])
20751 + out[i / 8] |= (1 << (7 - (i % 8)));
20752 + }
20753 + kfree(outb);
20754 +}
20755 +
20756 +void
20757 +E_P16(unsigned char *p14, unsigned char *p16)
20758 +{
20759 + unsigned char sp8[8] =
20760 + { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
20761 + smbhash(p16, sp8, p14, 1);
20762 + smbhash(p16 + 8, sp8, p14 + 7, 1);
20763 +}
20764 +
20765 +void
20766 +E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
20767 +{
20768 + smbhash(p24, c8, p21, 1);
20769 + smbhash(p24 + 8, c8, p21 + 7, 1);
20770 + smbhash(p24 + 16, c8, p21 + 14, 1);
20771 +}
20772 +
20773 +void
20774 +D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
20775 +{
20776 + smbhash(out, in, p14, 0);
20777 + smbhash(out + 8, in + 8, p14 + 7, 0);
20778 +}
20779 +
20780 +void
20781 +E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
20782 +{
20783 + smbhash(out, in, p14, 1);
20784 + smbhash(out + 8, in + 8, p14 + 7, 1);
20785 +}
20786 +
20787 +void
20788 +cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
20789 +{
20790 + unsigned char buf[8];
20791 +
20792 + smbhash(buf, in, key, 1);
20793 + smbhash(out, buf, key + 9, 1);
20794 +}
20795 +
20796 +void
20797 +cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
20798 +{
20799 + unsigned char buf[8];
20800 + static unsigned char key2[8];
20801 +
20802 + smbhash(buf, in, key, 1);
20803 + key2[0] = key[7];
20804 + smbhash(out, buf, key2, 1);
20805 +}
20806 +
20807 +void
20808 +cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
20809 +{
20810 + static unsigned char key2[8];
20811 +
20812 + smbhash(out, in, key, forw);
20813 + key2[0] = key[7];
20814 + smbhash(out + 8, in + 8, key2, forw);
20815 +}
20816 Index: linux-2.4.35.4/fs/cifs/smbencrypt.c
20817 ===================================================================
20818 --- /dev/null
20819 +++ linux-2.4.35.4/fs/cifs/smbencrypt.c
20820 @@ -0,0 +1,295 @@
20821 +/*
20822 + Unix SMB/Netbios implementation.
20823 + Version 1.9.
20824 + SMB parameters and setup
20825 + Copyright (C) Andrew Tridgell 1992-2000
20826 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000
20827 + Modified by Jeremy Allison 1995.
20828 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
20829 + Modified by Steve French (sfrench@us.ibm.com) 2002-2003
20830 +
20831 + This program is free software; you can redistribute it and/or modify
20832 + it under the terms of the GNU General Public License as published by
20833 + the Free Software Foundation; either version 2 of the License, or
20834 + (at your option) any later version.
20835 +
20836 + This program is distributed in the hope that it will be useful,
20837 + but WITHOUT ANY WARRANTY; without even the implied warranty of
20838 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20839 + GNU General Public License for more details.
20840 +
20841 + You should have received a copy of the GNU General Public License
20842 + along with this program; if not, write to the Free Software
20843 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20844 +*/
20845 +
20846 +#include <linux/module.h>
20847 +#include <linux/fs.h>
20848 +#include <linux/string.h>
20849 +#include <linux/kernel.h>
20850 +#include <linux/random.h>
20851 +#include "cifs_unicode.h"
20852 +#include "cifspdu.h"
20853 +#include "md5.h"
20854 +#include "cifs_debug.h"
20855 +
20856 +#ifndef FALSE
20857 +#define FALSE 0
20858 +#endif
20859 +#ifndef TRUE
20860 +#define TRUE 1
20861 +#endif
20862 +
20863 +/* following came from the other byteorder.h to avoid include conflicts */
20864 +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
20865 +#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
20866 +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
20867 +
20868 +/*The following definitions come from lib/md4.c */
20869 +
20870 +void mdfour(unsigned char *out, unsigned char *in, int n);
20871 +
20872 +/*The following definitions come from libsmb/smbdes.c */
20873 +
20874 +void E_P16(unsigned char *p14, unsigned char *p16);
20875 +void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
20876 +void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
20877 +void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
20878 +void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
20879 +void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
20880 +void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
20881 + int forw);
20882 +
20883 +/*The following definitions come from libsmb/smbencrypt.c */
20884 +
20885 +void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
20886 +void E_md4hash(const unsigned char *passwd, unsigned char *p16);
20887 +void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
20888 +void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
20889 + unsigned char p24[24]);
20890 +void NTLMSSPOWFencrypt(unsigned char passwd[8],
20891 + unsigned char *ntlmchalresp, unsigned char p24[24]);
20892 +void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
20893 +int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
20894 + int new_pwrd_size, __u32 * new_pw_len);
20895 +
20896 +/*
20897 + This implements the X/Open SMB password encryption
20898 + It takes a password, a 8 byte "crypt key" and puts 24 bytes of
20899 + encrypted password into p24 */
20900 +/* Note that password must be uppercased and null terminated */
20901 +void
20902 +SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
20903 +{
20904 + unsigned char p14[15], p21[21];
20905 +
20906 + memset(p21, '\0', 21);
20907 + memset(p14, '\0', 14);
20908 + strncpy((char *) p14, (char *) passwd, 14);
20909 +
20910 +/* strupper((char *)p14); *//* BB at least uppercase the easy range */
20911 + E_P16(p14, p21);
20912 +
20913 + SMBOWFencrypt(p21, c8, p24);
20914 +
20915 + memset(p14,0,15);
20916 + memset(p21,0,21);
20917 +}
20918 +
20919 +/* Routines for Windows NT MD4 Hash functions. */
20920 +static int
20921 +_my_wcslen(__u16 * str)
20922 +{
20923 + int len = 0;
20924 + while (*str++ != 0)
20925 + len++;
20926 + return len;
20927 +}
20928 +
20929 +/*
20930 + * Convert a string into an NT UNICODE string.
20931 + * Note that regardless of processor type
20932 + * this must be in intel (little-endian)
20933 + * format.
20934 + */
20935 +
20936 +static int
20937 +_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
20938 +{ /* not a very good conversion routine - change/fix */
20939 + int i;
20940 + __u16 val;
20941 +
20942 + for (i = 0; i < len; i++) {
20943 + val = *src;
20944 + SSVAL(dst, 0, val);
20945 + dst++;
20946 + src++;
20947 + if (val == 0)
20948 + break;
20949 + }
20950 + return i;
20951 +}
20952 +
20953 +/*
20954 + * Creates the MD4 Hash of the users password in NT UNICODE.
20955 + */
20956 +
20957 +void
20958 +E_md4hash(const unsigned char *passwd, unsigned char *p16)
20959 +{
20960 + int len;
20961 + __u16 wpwd[129];
20962 +
20963 + /* Password cannot be longer than 128 characters */
20964 + if(passwd) {
20965 + len = strlen((char *) passwd);
20966 + if (len > 128) {
20967 + len = 128;
20968 + }
20969 + /* Password must be converted to NT unicode */
20970 + _my_mbstowcs(wpwd, passwd, len);
20971 + } else
20972 + len = 0;
20973 +
20974 + wpwd[len] = 0; /* Ensure string is null terminated */
20975 + /* Calculate length in bytes */
20976 + len = _my_wcslen(wpwd) * sizeof (__u16);
20977 +
20978 + mdfour(p16, (unsigned char *) wpwd, len);
20979 + memset(wpwd,0,129 * 2);
20980 +}
20981 +
20982 +/* Does both the NT and LM owfs of a user's password */
20983 +void
20984 +nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
20985 +{
20986 + char passwd[514];
20987 +
20988 + memset(passwd, '\0', 514);
20989 + if (strlen(pwd) < 513)
20990 + strcpy(passwd, pwd);
20991 + else
20992 + memcpy(passwd, pwd, 512);
20993 + /* Calculate the MD4 hash (NT compatible) of the password */
20994 + memset(nt_p16, '\0', 16);
20995 + E_md4hash(passwd, nt_p16);
20996 +
20997 + /* Mangle the passwords into Lanman format */
20998 + passwd[14] = '\0';
20999 +/* strupper(passwd); */
21000 +
21001 + /* Calculate the SMB (lanman) hash functions of the password */
21002 +
21003 + memset(p16, '\0', 16);
21004 + E_P16((unsigned char *) passwd, (unsigned char *) p16);
21005 +
21006 + /* clear out local copy of user's password (just being paranoid). */
21007 + memset(passwd, '\0', sizeof (passwd));
21008 +}
21009 +
21010 +/* Does the NTLMv2 owfs of a user's password */
21011 +void
21012 +ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
21013 + const char *domain_n, unsigned char kr_buf[16],
21014 + const struct nls_table *nls_codepage)
21015 +{
21016 + wchar_t * user_u;
21017 + wchar_t * dom_u;
21018 + int user_l, domain_l;
21019 + struct HMACMD5Context ctx;
21020 +
21021 + /* might as well do one alloc to hold both (user_u and dom_u) */
21022 + user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
21023 + if(user_u == NULL)
21024 + return;
21025 + dom_u = user_u + 1024;
21026 +
21027 + /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
21028 + push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
21029 +
21030 + /* BB user and domain may need to be uppercased */
21031 + user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
21032 + domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
21033 +
21034 + user_l++; /* trailing null */
21035 + domain_l++;
21036 +
21037 + hmac_md5_init_limK_to_64(owf, 16, &ctx);
21038 + hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
21039 + hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
21040 + hmac_md5_final(kr_buf, &ctx);
21041 +
21042 + kfree(user_u);
21043 +}
21044 +
21045 +/* Does the des encryption from the NT or LM MD4 hash. */
21046 +void
21047 +SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
21048 + unsigned char p24[24])
21049 +{
21050 + unsigned char p21[21];
21051 +
21052 + memset(p21, '\0', 21);
21053 +
21054 + memcpy(p21, passwd, 16);
21055 + E_P24(p21, c8, p24);
21056 +}
21057 +
21058 +/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
21059 +void
21060 +NTLMSSPOWFencrypt(unsigned char passwd[8],
21061 + unsigned char *ntlmchalresp, unsigned char p24[24])
21062 +{
21063 + unsigned char p21[21];
21064 +
21065 + memset(p21, '\0', 21);
21066 + memcpy(p21, passwd, 8);
21067 + memset(p21 + 8, 0xbd, 8);
21068 +
21069 + E_P24(p21, ntlmchalresp, p24);
21070 +}
21071 +
21072 +/* Does the NT MD4 hash then des encryption. */
21073 +
21074 +void
21075 +SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
21076 +{
21077 + unsigned char p21[21];
21078 +
21079 + memset(p21, '\0', 21);
21080 +
21081 + E_md4hash(passwd, p21);
21082 + SMBOWFencrypt(p21, c8, p24);
21083 +}
21084 +
21085 +/* Does the md5 encryption from the NT hash for NTLMv2. */
21086 +void
21087 +SMBOWFencrypt_ntv2(const unsigned char kr[16],
21088 + const struct data_blob * srv_chal,
21089 + const struct data_blob * cli_chal, unsigned char resp_buf[16])
21090 +{
21091 + struct HMACMD5Context ctx;
21092 +
21093 + hmac_md5_init_limK_to_64(kr, 16, &ctx);
21094 + hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
21095 + hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
21096 + hmac_md5_final(resp_buf, &ctx);
21097 +}
21098 +
21099 +void
21100 +SMBsesskeygen_ntv2(const unsigned char kr[16],
21101 + const unsigned char *nt_resp, __u8 sess_key[16])
21102 +{
21103 + struct HMACMD5Context ctx;
21104 +
21105 + hmac_md5_init_limK_to_64(kr, 16, &ctx);
21106 + hmac_md5_update(nt_resp, 16, &ctx);
21107 + hmac_md5_final((unsigned char *) sess_key, &ctx);
21108 +}
21109 +
21110 +void
21111 +SMBsesskeygen_ntv1(const unsigned char kr[16],
21112 + const unsigned char *nt_resp, __u8 sess_key[16])
21113 +{
21114 + mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
21115 +}
21116 Index: linux-2.4.35.4/fs/cifs/smberr.c
21117 ===================================================================
21118 --- /dev/null
21119 +++ linux-2.4.35.4/fs/cifs/smberr.c
21120 @@ -0,0 +1,240 @@
21121 +/*
21122 + Unix SMB/Netbios implementation.
21123 + Version 1.9.
21124 + Copyright (C) Andrew Tridgell 1998
21125 + Copyright (C) Steve French (sfrench@us.ibm.com) 2002
21126 + This program is free software; you can redistribute it and/or modify
21127 + it under the terms of the GNU General Public License as published by
21128 + the Free Software Foundation; either version 2 of the License, or
21129 + (at your option) any later version.
21130 +
21131 + This program is distributed in the hope that it will be useful,
21132 + but WITHOUT ANY WARRANTY; without even the implied warranty of
21133 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21134 + GNU General Public License for more details.
21135 +
21136 + You should have received a copy of the GNU General Public License
21137 + along with this program; if not, write to the Free Software
21138 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21139 +*/
21140 +include "smberr.h"
21141 +#define NO_SYSLOG
21142 +/* error code stuff - put together by Merik Karman
21143 + merik@blackadder.dsh.oz.au */
21144 + typedef const struct {
21145 + char *name;
21146 + int code;
21147 + char *message;
21148 + int posix_code;
21149 +} err_code_struct;
21150 +
21151 +/* Dos Error Messages */
21152 +err_code_struct dos_msgs[] = {
21153 + {"ERRbadfunc", ERRbadfunc, "Invalid function.", -EINVAL},
21154 + {"ERRbadfile", ERRbadfile, "File not found.", -ENOENT},
21155 + {"ERRbadpath", ERRbadpath, "Directory invalid.", -ENOENT},
21156 + {"ERRnofids", ERRnofids, "No file descriptors available", -EMFILE},
21157 + {"ERRnoaccess", ERRnoaccess, "Access denied.", -EACCES},
21158 + {"ERRbadfid", ERRbadfid, "Invalid file handle.", -EBADF},
21159 + {"ERRbadmcb", 7, "Memory control blocks destroyed.", -EIO},
21160 + {"ERRnomem", ERRnomem,
21161 + "Insufficient server memory to perform the requested function.",
21162 + -ENOMEM},
21163 + {"ERRbadmem", ERRbadmem, "Invalid memory block address.", -EFAULT},
21164 + {"ERRbadenv", ERRbadenv, "Invalid environment.", -EFAULT},
21165 + {"ERRbadformat", 11, "Invalid format.", -EINVAL},
21166 + {"ERRbadaccess", ERRbadaccess, "Invalid open mode." - EACCES},
21167 + {"ERRbaddata", ERRbaddata, "Invalid data.", -EIO},
21168 + {"ERR", ERRres, "reserved.", -EIO},
21169 + {"ERRbaddrive", ERRbaddrive, "Invalid drive specified.", -ENXIO},
21170 + {"ERRremcd", ERRremcd,
21171 + "A Delete Directory request attempted to remove the server's current directory.",
21172 + -EIO},
21173 + {"ERRdiffdevice", ERRdiffdevice, "Not same device.", -EXDEV},
21174 + {"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 */
21175 + {"ERRbadshare", ERRbadshare,
21176 + "The sharing mode specified for an Open conflicts with existing FIDs on the file.",
21177 + -EXTBSY},
21178 + {"ERRlock", ERRlock,
21179 + "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.",
21180 + -EACCES},
21181 + {"ERRunsup", ERRunsup, "The operation is unsupported", -EINVAL},
21182 + {"ERRnosuchshare", ERRnosuchshare,
21183 + "You specified an invalid share name", -ENXIO},
21184 + {"ERRfilexists", ERRfilexists,
21185 + "The file named in a Create Directory, Make New File or Link request already exists.",
21186 + -EEXIST},
21187 + {"ERRinvalidname", ERRinvalidname, "Invalid name", -ENOENT},
21188 + {"ERRdiskfull", ERRdiskfull, "Disk full", -ENOSPC}
21189 +
21190 + {"ERRmoredata", ERRmoredata,
21191 + "There is more data to be returned.",},
21192 + {"ERRinvgroup", 2455, "Invalid workgroup (try the -W option)"},
21193 + {NULL, -1, NULL, -EIO}
21194 +};
21195 +
21196 +/* Server Error Messages */
21197 +err_code_struct server_msgs[] = {
21198 + {"ERRerror", 1, "Non-specific error code."},
21199 + {"ERRbadpw", 2,
21200 + "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
21201 + {"ERRbadtype", 3, "reserved."},
21202 + {"ERRaccess", 4,
21203 + "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."},
21204 + {"ERRinvnid", 5,
21205 + "The tree ID (TID) specified in a command was invalid."},
21206 + {"ERRinvnetname", 6, "Invalid network name in tree connect."},
21207 + {"ERRinvdevice", 7,
21208 + "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
21209 + {"ERRqfull", 49,
21210 + "Print queue full (files) -- returned by open print file."},
21211 + {"ERRqtoobig", 50, "Print queue full -- no space."},
21212 + {"ERRqeof", 51, "EOF on print queue dump."},
21213 + {"ERRinvpfid", 52, "Invalid print file FID."},
21214 + {"ERRsmbcmd", 64,
21215 + "The server did not recognize the command received."},
21216 + {"ERRsrverror", 65,
21217 + "The server encountered an internal error, e.g., system file unavailable."},
21218 + {"ERRfilespecs", 67,
21219 + "The file handle (FID) and pathname parameters contained an invalid combination of values."},
21220 + {"ERRreserved", 68, "reserved."},
21221 + {"ERRbadpermits", 69,
21222 + "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
21223 + {"ERRreserved", 70, "reserved."},
21224 + {"ERRsetattrmode", 71,
21225 + "The attribute mode in the Set File Attribute request is invalid."},
21226 + {"ERRpaused", 81, "Server is paused."},
21227 + {"ERRmsgoff", 82, "Not receiving messages."},
21228 + {"ERRnoroom", 83, "No room to buffer message."},
21229 + {"ERRrmuns", 87, "Too many remote user names."},
21230 + {"ERRtimeout", 88, "Operation timed out."},
21231 + {"ERRnoresource", 89,
21232 + "No resources currently available for request."},
21233 + {"ERRtoomanyuids", 90, "Too many UIDs active on this session."},
21234 + {"ERRbaduid", 91,
21235 + "The UID is not known as a valid ID on this session."},
21236 + {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode."},
21237 + {"ERRusestd", 251,
21238 + "Temp unable to support Raw, use standard read/write."},
21239 + {"ERRcontmpx", 252, "Continue in MPX mode."},
21240 + {"ERRreserved", 253, "reserved."},
21241 + {"ERRreserved", 254, "reserved."},
21242 + {"ERRnosupport", 0xFFFF, "Function not supported."},
21243 + {NULL, -1, NULL}
21244 +};
21245 +
21246 +/* Hard Error Messages */
21247 +err_code_struct hard_msgs[] = {
21248 + {"ERRnowrite", 19,
21249 + "Attempt to write on write-protected diskette."},
21250 + {"ERRbadunit", 20, "Unknown unit."},
21251 + {"ERRnotready", 21, "Drive not ready."},
21252 + {"ERRbadcmd", 22, "Unknown command."},
21253 + {"ERRdata", 23, "Data error (CRC)."},
21254 + {"ERRbadreq", 24, "Bad request structure length."},
21255 + {"ERRseek", 25, "Seek error."},
21256 + {"ERRbadmedia", 26, "Unknown media type."},
21257 + {"ERRbadsector", 27, "Sector not found."},
21258 + {"ERRnopaper", 28, "Printer out of paper."},
21259 + {"ERRwrite", 29, "Write fault."},
21260 + {"ERRread", 30, "Read fault."},
21261 + {"ERRgeneral", 31, "General failure."},
21262 + {"ERRbadshare", 32, "An open conflicts with an existing open."},
21263 + {"ERRlock", 33,
21264 + "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."},
21265 + {"ERRwrongdisk", 34, "The wrong disk was found in a drive."},
21266 + {"ERRFCBUnavail", 35, "No FCBs are available to process request."},
21267 + {"ERRsharebufexc", 36, "A sharing buffer has been exceeded."},
21268 + {NULL, -1, NULL}
21269 +};
21270 +
21271 +
21272 +const struct {
21273 + int code;
21274 + char *class;
21275 + err_code_struct *err_msgs;
21276 +} err_classes[] = {
21277 + {
21278 + 0, "SUCCESS", NULL}, {
21279 + 0x01, "ERRDOS", dos_msgs}, {
21280 + 0x02, "ERRSRV", server_msgs}, {
21281 + 0x03, "ERRHRD", hard_msgs}, {
21282 + 0x04, "ERRXOS", NULL}, {
21283 + 0xE1, "ERRRMX1", NULL}, {
21284 + 0xE2, "ERRRMX2", NULL}, {
21285 + 0xE3, "ERRRMX3", NULL}, {
21286 + 0xFF, "ERRCMD", NULL}, {
21287 +-1, NULL, NULL}};
21288 +
21289 +
21290 +/****************************************************************************
21291 +return a SMB error string from a SMB buffer
21292 +****************************************************************************/
21293 +char *smb_dos_errstr(char *inbuf)
21294 +{
21295 + static pstring ret;
21296 + int class = CVAL(inbuf, smb_rcls);
21297 + int num = SVAL(inbuf, smb_err);
21298 + int i, j;
21299 +
21300 + for (i = 0; err_classes[i].class; i++)
21301 + if (err_classes[i].code == class) {
21302 + if (err_classes[i].err_msgs) {
21303 + err_code_struct *err =
21304 + err_classes[i].err_msgs;
21305 + for (j = 0; err[j].name; j++)
21306 + if (num == err[j].code) {
21307 + if (DEBUGLEVEL > 0)
21308 + slprintf(ret,
21309 + sizeof
21310 + (ret) - 1,
21311 + "%s - %s (%s)",
21312 + err_classes
21313 + [i].class,
21314 + err[j].
21315 + name,
21316 + err[j].
21317 + message);
21318 + else
21319 + slprintf(ret,
21320 + sizeof
21321 + (ret) - 1,
21322 + "%s - %s",
21323 + err_classes
21324 + [i].class,
21325 + err[j].
21326 + name);
21327 + return ret;
21328 + }
21329 + }
21330 +
21331 + slprintf(ret, sizeof(ret) - 1, "%s - %d",
21332 + err_classes[i].class, num);
21333 + return ret;
21334 + }
21335 +
21336 + slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",
21337 + class, num);
21338 + return (ret);
21339 +}
21340 +
21341 +
21342 +/*****************************************************************************
21343 + returns an WERROR error message.
21344 + *****************************************************************************/
21345 +char *werror_str(WERROR status)
21346 +{
21347 + static fstring msg;
21348 + slprintf(msg, sizeof(msg), "WIN32 code 0x%08x", W_ERROR_V(status));
21349 + return msg;
21350 +}
21351 +
21352 +
21353 +/*****************************************************************************
21354 +map a unix errno to a win32 error
21355 + *****************************************************************************/
21356 +WERROR map_werror_from_unix(int error)
21357 +{
21358 + NTSTATUS status = map_nt_error_from_unix(error);
21359 + return ntstatus_to_werror(status);
21360 +}
21361 Index: linux-2.4.35.4/fs/cifs/smberr.h
21362 ===================================================================
21363 --- /dev/null
21364 +++ linux-2.4.35.4/fs/cifs/smberr.h
21365 @@ -0,0 +1,113 @@
21366 +/*
21367 + * fs/cifs/smberr.h
21368 + *
21369 + * Copyright (c) International Business Machines Corp., 2002
21370 + * Author(s): Steve French (sfrench@us.ibm.com)
21371 + *
21372 + * See Error Codes section of the SNIA CIFS Specification
21373 + * for more information
21374 + *
21375 + * This library is free software; you can redistribute it and/or modify
21376 + * it under the terms of the GNU Lesser General Public License as published
21377 + * by the Free Software Foundation; either version 2.1 of the License, or
21378 + * (at your option) any later version.
21379 + *
21380 + * This library is distributed in the hope that it will be useful,
21381 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21382 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21383 + * the GNU Lesser General Public License for more details.
21384 + *
21385 + * You should have received a copy of the GNU Lesser General Public License
21386 + * along with this library; if not, write to the Free Software
21387 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21388 + */
21389 +
21390 +#define SUCCESS 0 /* The request was successful. */
21391 +#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
21392 +#define ERRSRV 0x02 /* Error is generated by the file server daemon */
21393 +#define ERRHRD 0x03 /* Error is a hardware error. */
21394 +#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
21395 +
21396 +/* The following error codes may be generated with the SUCCESS error class.*/
21397 +
21398 +#define SUCCESS 0 /* The request was successful. */
21399 +
21400 +/* The following error codes may be generated with the ERRDOS error class.*/
21401 +
21402 +#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. */
21403 +#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */
21404 +#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */
21405 +#define ERRnofids 4 /* Too many open files. The server has no file handles available. */
21406 +#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 */
21407 +#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */
21408 +#define ERRbadmcb 7 /* Memory control blocks destroyed. */
21409 +#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */
21410 +#define ERRbadmem 9 /* Invalid memory block address. */
21411 +#define ERRbadenv 10 /* Invalid environment. */
21412 +#define ERRbadformat 11 /* Invalid format. */
21413 +#define ERRbadaccess 12 /* Invalid open mode. */
21414 +#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */
21415 +#define ERRbaddrive 15 /* Invalid drive specified. */
21416 +#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */
21417 +#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */
21418 +#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */
21419 +#define ERRgeneral 31
21420 +#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
21421 +#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. */
21422 +#define ERRunsup 50
21423 +#define ERRnosuchshare 67
21424 +#define ERRfilexists 80 /* The file named in the request already exists. */
21425 +#define ERRinvparm 87
21426 +#define ERRdiskfull 112
21427 +#define ERRinvname 123
21428 +#define ERRdirnotempty 145
21429 +#define ERRnotlocked 158
21430 +#define ERRalreadyexists 183
21431 +#define ERRbadpipe 230
21432 +#define ERRpipebusy 231
21433 +#define ERRpipeclosing 232
21434 +#define ERRnotconnected 233
21435 +#define ERRmoredata 234
21436 +#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
21437 +#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
21438 + was not a link. */
21439 +
21440 +/* Following error codes may be generated with the ERRSRV error
21441 +class.*/
21442 +
21443 +#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. */
21444 +#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
21445 +#define ERRbadtype 3 /* used for indicating DFS referral needed */
21446 +#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */
21447 +#define ERRinvtid 5 /* The Tid specified in a command was invalid. */
21448 +#define ERRinvnetname 6 /* Invalid network name in tree connect. */
21449 +#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
21450 +#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */
21451 +#define ERRqtoobig 50 /* Print queue full -- no space. */
21452 +#define ERRqeof 51 /* EOF on print queue dump */
21453 +#define ERRinvpfid 52 /* Invalid print file FID. */
21454 +#define ERRsmbcmd 64 /* The server did not recognize the command received. */
21455 +#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */
21456 +#define ERRbadBID 66 /* (obsolete) */
21457 +#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */
21458 +#define ERRbadLink 68 /* (obsolete) */
21459 +#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */
21460 +#define ERRbadPID 70
21461 +#define ERRsetattrmode 71 /* attribute (mode) is invalid */
21462 +#define ERRpaused 81 /* Server is paused */
21463 +#define ERRmsgoff 82 /* reserved - messaging off */
21464 +#define ERRnoroom 83 /* reserved - no room for message */
21465 +#define ERRrmuns 87 /* reserved - too many remote names */
21466 +#define ERRtimeout 88 /* operation timed out */
21467 +#define ERRnoresource 89 /* No resources available for request */
21468 +#define ERRtoomanyuids 90 /* Too many UIDs active on this session */
21469 +#define ERRbaduid 91 /* The UID is not known as a valid user */
21470 +#define ERRusempx 250 /* temporarily unable to use raw */
21471 +#define ERRusestd 251 /* temporarily unable to use either raw or mpx */
21472 +#define ERR_NOTIFY_ENUM_DIR 1024
21473 +#define ERRaccountexpired 2239
21474 +#define ERRbadclient 2240
21475 +#define ERRbadLogonTime 2241
21476 +#define ERRpasswordExpired 2242
21477 +#define ERRnetlogonNotStarted 2455
21478 +#define ERRnosupport 0xFFFF
21479 Index: linux-2.4.35.4/fs/cifs/TODO
21480 ===================================================================
21481 --- /dev/null
21482 +++ linux-2.4.35.4/fs/cifs/TODO
21483 @@ -0,0 +1,106 @@
21484 +version 1.16 May 27, 2004
21485 +
21486 +A Partial List of Missing Features
21487 +==================================
21488 +
21489 +Contributions are welcome. There are plenty of opportunities
21490 +for visible, important contributions to this module. Here
21491 +is a partial list of the known problems and missing features:
21492 +
21493 +a) Support for SecurityDescriptors for chmod/chgrp/chown so
21494 +these can be supported for Windows servers
21495 +
21496 +b) Better pam/winbind integration
21497 +
21498 +c) multi-user mounts - multiplexed sessionsetups over single vc
21499 +(ie tcp session) - prettying up needed
21500 +
21501 +d) Kerberos/SPNEGO session setup support - (started)
21502 +
21503 +e) NTLMv2 authentication (mostly implemented)
21504 +
21505 +f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
21506 +used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
21507 +and raw NTLMSSP already. This is important when enabling
21508 +extended security and mounting to Windows 2003 Servers
21509 +
21510 +f) Directory entry caching relies on a 1 second timer, rather than
21511 +using FindNotify or equivalent. - (started)
21512 +
21513 +g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
21514 +style byte range lock differences
21515 +
21516 +h) quota support
21517 +
21518 +i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
21519 +which will allow us to expose dos attributes as well as real
21520 +ACLs. This support has been started in the current code, but is
21521 +ifdeffed out.
21522 +
21523 +k) finish writepages support (multi-page write behind for improved
21524 +performance) and syncpage
21525 +
21526 +l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
21527 +extra copy in/out of the socket buffers in some cases.
21528 +
21529 +m) finish support for IPv6. This is mostly complete but
21530 +needs a simple inet_pton like function to convert ipv6
21531 +addresses in string representation.
21532 +
21533 +o) Better optimize open (and pathbased setfilesize) to reduce the
21534 +oplock breaks coming from windows srv. Piggyback identical file
21535 +opens on top of each other by incrementing reference count rather
21536 +than resending (helps reduce server resource utilization and avoid
21537 +spurious oplock breaks).
21538 +
21539 +p) Improve performance of readpages by sending more than one read
21540 +at a time when 8 pages or more are requested. Evaluate whether
21541 +reads larger than 16K would be helpful.
21542 +
21543 +q) For support of Windows9x/98 we need to retry failed mounts
21544 +to *SMBSERVER (default server name) with the uppercase hostname
21545 +in the RFC1001 session_init request.
21546 +
21547 +r) Add Extended Attributed support (for storing UID/GID info
21548 +to Windows servers)
21549 +
21550 +s) Finish fcntl D_NOTIFY support so kde and gnome file list windows
21551 +will autorefresh
21552 +
21553 +t) Add GUI tool to configure /proc/fs/cifs settings and for display of
21554 +the CIFS statistics
21555 +
21556 +KNOWN BUGS (updated May 27, 2004)
21557 +====================================
21558 +1) existing symbolic links (Windows reparse points) are recognized but
21559 +can not be created remotely. They are implemented for Samba and those that
21560 +support the CIFS Unix extensions but Samba has a bug currently handling
21561 +symlink text beginning with slash
21562 +2) follow_link and readdir code does not follow dfs junctions
21563 +but recognizes them
21564 +3) create of new files to FAT partitions on Windows servers can
21565 +succeed but still return access denied (appears to be Windows
21566 +server not cifs client problem) and has not been reproduced recently.
21567 +NTFS partitions do not have this problem.
21568 +4) debug connectathon lock test case 10 which fails against
21569 +Samba (may be unmappable due to POSIX to Windows lock model
21570 +differences but worth investigating). Also debug Samba to
21571 +see why lock test case 7 takes longer to complete to Samba
21572 +than to Windows.
21573 +
21574 +Misc testing to do
21575 +==================
21576 +1) check out max path names and max path name components against various server
21577 +types. Try nested symlinks. Return max path name in stat -f information
21578 +
21579 +2) Modify file portion of ltp so it can run against a mounted network
21580 +share and run it against cifs vfs.
21581 +
21582 +3) Additional performance testing and optimization using iozone and similar -
21583 +there are some easy changes that can be done to parallelize sequential writes,
21584 +and when signing is disabled to request larger read sizes (larger than
21585 +negotiated size) and send larger write sizes to modern servers.
21586 +
21587 +4) More exhaustively test the recently added NT4 support against various
21588 +NT4 service pack levels.
21589 +
21590 Index: linux-2.4.35.4/fs/cifs/transport.c
21591 ===================================================================
21592 --- /dev/null
21593 +++ linux-2.4.35.4/fs/cifs/transport.c
21594 @@ -0,0 +1,434 @@
21595 +/*
21596 + * fs/cifs/transport.c
21597 + *
21598 + * Copyright (C) International Business Machines Corp., 2002,2004
21599 + * Author(s): Steve French (sfrench@us.ibm.com)
21600 + *
21601 + * This library is free software; you can redistribute it and/or modify
21602 + * it under the terms of the GNU Lesser General Public License as published
21603 + * by the Free Software Foundation; either version 2.1 of the License, or
21604 + * (at your option) any later version.
21605 + *
21606 + * This library is distributed in the hope that it will be useful,
21607 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21608 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21609 + * the GNU Lesser General Public License for more details.
21610 + *
21611 + * You should have received a copy of the GNU Lesser General Public License
21612 + * along with this library; if not, write to the Free Software
21613 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21614 + */
21615 +
21616 +#include <linux/fs.h>
21617 +#include <linux/list.h>
21618 +#include <linux/wait.h>
21619 +#include <linux/net.h>
21620 +#include <linux/version.h>
21621 +#include <asm/uaccess.h>
21622 +#include <asm/processor.h>
21623 +#include "cifspdu.h"
21624 +#include "cifsglob.h"
21625 +#include "cifsproto.h"
21626 +#include "cifs_debug.h"
21627 +
21628 +extern kmem_cache_t *cifs_mid_cachep;
21629 +extern kmem_cache_t *cifs_oplock_cachep;
21630 +
21631 +struct mid_q_entry *
21632 +AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
21633 +{
21634 + struct mid_q_entry *temp;
21635 +
21636 + if (ses == NULL) {
21637 + cERROR(1, ("Null session passed in to AllocMidQEntry "));
21638 + return NULL;
21639 + }
21640 + if (ses->server == NULL) {
21641 + cERROR(1, ("Null TCP session in AllocMidQEntry"));
21642 + return NULL;
21643 + }
21644 +
21645 + temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
21646 + SLAB_KERNEL);
21647 + if (temp == NULL)
21648 + return temp;
21649 + else {
21650 + memset(temp, 0, sizeof (struct mid_q_entry));
21651 + temp->mid = smb_buffer->Mid; /* always LE */
21652 + temp->pid = current->pid;
21653 + temp->command = smb_buffer->Command;
21654 + cFYI(1, ("For smb_command %d", temp->command));
21655 + do_gettimeofday(&temp->when_sent);
21656 + temp->ses = ses;
21657 + temp->tsk = current;
21658 + }
21659 +
21660 + spin_lock(&GlobalMid_Lock);
21661 + list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
21662 + atomic_inc(&midCount);
21663 + temp->midState = MID_REQUEST_ALLOCATED;
21664 + spin_unlock(&GlobalMid_Lock);
21665 + return temp;
21666 +}
21667 +
21668 +void
21669 +DeleteMidQEntry(struct mid_q_entry *midEntry)
21670 +{
21671 + spin_lock(&GlobalMid_Lock);
21672 + midEntry->midState = MID_FREE;
21673 + list_del(&midEntry->qhead);
21674 + atomic_dec(&midCount);
21675 + spin_unlock(&GlobalMid_Lock);
21676 + cifs_buf_release(midEntry->resp_buf);
21677 + kmem_cache_free(cifs_mid_cachep, midEntry);
21678 +}
21679 +
21680 +struct oplock_q_entry *
21681 +AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
21682 +{
21683 + struct oplock_q_entry *temp;
21684 + if ((pinode== NULL) || (tcon == NULL)) {
21685 + cERROR(1, ("Null parms passed to AllocOplockQEntry"));
21686 + return NULL;
21687 + }
21688 + temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
21689 + SLAB_KERNEL);
21690 + if (temp == NULL)
21691 + return temp;
21692 + else {
21693 + temp->pinode = pinode;
21694 + temp->tcon = tcon;
21695 + temp->netfid = fid;
21696 + spin_lock(&GlobalMid_Lock);
21697 + list_add_tail(&temp->qhead, &GlobalOplock_Q);
21698 + spin_unlock(&GlobalMid_Lock);
21699 + }
21700 + return temp;
21701 +
21702 +}
21703 +
21704 +void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
21705 +{
21706 + spin_lock(&GlobalMid_Lock);
21707 + /* should we check if list empty first? */
21708 + list_del(&oplockEntry->qhead);
21709 + spin_unlock(&GlobalMid_Lock);
21710 + kmem_cache_free(cifs_oplock_cachep, oplockEntry);
21711 +}
21712 +
21713 +int
21714 +smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
21715 + unsigned int smb_buf_length, struct sockaddr *sin)
21716 +{
21717 + int rc = 0;
21718 + int i = 0;
21719 + struct msghdr smb_msg;
21720 + struct iovec iov;
21721 + mm_segment_t temp_fs;
21722 +
21723 + if(ssocket == NULL)
21724 + return -ENOTSOCK; /* BB eventually add reconnect code here */
21725 + iov.iov_base = smb_buffer;
21726 + iov.iov_len = smb_buf_length + 4;
21727 +
21728 + smb_msg.msg_name = sin;
21729 + smb_msg.msg_namelen = sizeof (struct sockaddr);
21730 + smb_msg.msg_iov = &iov;
21731 + smb_msg.msg_iovlen = 1;
21732 + smb_msg.msg_control = NULL;
21733 + smb_msg.msg_controllen = 0;
21734 + smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
21735 +
21736 + /* smb header is converted in header_assemble. bcc and rest of SMB word
21737 + area, and byte area if necessary, is converted to littleendian in
21738 + cifssmb.c and RFC1001 len is converted to bigendian in smb_send
21739 + Flags2 is converted in SendReceive */
21740 +
21741 + smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
21742 + cFYI(1, ("Sending smb of length %d ", smb_buf_length));
21743 + dump_smb(smb_buffer, smb_buf_length + 4);
21744 +
21745 + temp_fs = get_fs(); /* we must turn off socket api parm checking */
21746 + set_fs(get_ds());
21747 + while(iov.iov_len > 0) {
21748 + rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
21749 + if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
21750 + i++;
21751 + if(i > 60) {
21752 + cERROR(1,
21753 + ("sends on sock %p stuck for 30 seconds",
21754 + ssocket));
21755 + rc = -EAGAIN;
21756 + break;
21757 + }
21758 + set_current_state(TASK_INTERRUPTIBLE);
21759 + schedule_timeout(HZ/2);
21760 + continue;
21761 + }
21762 + if (rc < 0)
21763 + break;
21764 + iov.iov_base += rc;
21765 + iov.iov_len -= rc;
21766 + }
21767 + set_fs(temp_fs);
21768 +
21769 + if (rc < 0) {
21770 + cERROR(1,("Error %d sending data on socket to server.", rc));
21771 + } else {
21772 + rc = 0;
21773 + }
21774 +
21775 + return rc;
21776 +}
21777 +
21778 +int
21779 +SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
21780 + struct smb_hdr *in_buf, struct smb_hdr *out_buf,
21781 + int *pbytes_returned, const int long_op)
21782 +{
21783 + int rc = 0;
21784 + unsigned int receive_len;
21785 + long timeout;
21786 + struct mid_q_entry *midQ;
21787 +
21788 + if (ses == NULL) {
21789 + cERROR(1,("Null smb session"));
21790 + return -EIO;
21791 + }
21792 + if(ses->server == NULL) {
21793 + cERROR(1,("Null tcp session"));
21794 + return -EIO;
21795 + }
21796 +
21797 + /* Ensure that we do not send more than 50 overlapping requests
21798 + to the same server. We may make this configurable later or
21799 + use ses->maxReq */
21800 + if(long_op == -1) {
21801 + /* oplock breaks must not be held up */
21802 + atomic_inc(&ses->server->inFlight);
21803 + } else {
21804 + spin_lock(&GlobalMid_Lock);
21805 + while(1) {
21806 + if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){
21807 + spin_unlock(&GlobalMid_Lock);
21808 + wait_event(ses->server->request_q,
21809 + atomic_read(&ses->server->inFlight)
21810 + < CIFS_MAX_REQ);
21811 + spin_lock(&GlobalMid_Lock);
21812 + } else {
21813 + if(ses->server->tcpStatus == CifsExiting) {
21814 + spin_unlock(&GlobalMid_Lock);
21815 + return -ENOENT;
21816 + }
21817 +
21818 + /* can not count locking commands against total since
21819 + they are allowed to block on server */
21820 +
21821 + if(long_op < 3) {
21822 + /* update # of requests on the wire to server */
21823 + atomic_inc(&ses->server->inFlight);
21824 + }
21825 + spin_unlock(&GlobalMid_Lock);
21826 + break;
21827 + }
21828 + }
21829 + }
21830 + /* make sure that we sign in the same order that we send on this socket
21831 + and avoid races inside tcp sendmsg code that could cause corruption
21832 + of smb data */
21833 +
21834 + down(&ses->server->tcpSem);
21835 +
21836 + if (ses->server->tcpStatus == CifsExiting) {
21837 + rc = -ENOENT;
21838 + goto out_unlock;
21839 + } else if (ses->server->tcpStatus == CifsNeedReconnect) {
21840 + cFYI(1,("tcp session dead - return to caller to retry"));
21841 + rc = -EAGAIN;
21842 + goto out_unlock;
21843 + } else if (ses->status != CifsGood) {
21844 + /* check if SMB session is bad because we are setting it up */
21845 + if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
21846 + (in_buf->Command != SMB_COM_NEGOTIATE)) {
21847 + rc = -EAGAIN;
21848 + goto out_unlock;
21849 + } /* else ok - we are setting up session */
21850 + }
21851 + midQ = AllocMidQEntry(in_buf, ses);
21852 + if (midQ == NULL) {
21853 + up(&ses->server->tcpSem);
21854 + /* If not lock req, update # of requests on wire to server */
21855 + if(long_op < 3) {
21856 + atomic_dec(&ses->server->inFlight);
21857 + wake_up(&ses->server->request_q);
21858 + }
21859 + return -ENOMEM;
21860 + }
21861 +
21862 + if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
21863 + up(&ses->server->tcpSem);
21864 + cERROR(1,
21865 + ("Illegal length, greater than maximum frame, %d ",
21866 + in_buf->smb_buf_length));
21867 + DeleteMidQEntry(midQ);
21868 + /* If not lock req, update # of requests on wire to server */
21869 + if(long_op < 3) {
21870 + atomic_dec(&ses->server->inFlight);
21871 + wake_up(&ses->server->request_q);
21872 + }
21873 + return -EIO;
21874 + }
21875 +
21876 + if (in_buf->smb_buf_length > 12)
21877 + in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
21878 +
21879 + rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
21880 +
21881 + midQ->midState = MID_REQUEST_SUBMITTED;
21882 + rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
21883 + (struct sockaddr *) &(ses->server->addr.sockAddr));
21884 + if(rc < 0) {
21885 + DeleteMidQEntry(midQ);
21886 + up(&ses->server->tcpSem);
21887 + /* If not lock req, update # of requests on wire to server */
21888 + if(long_op < 3) {
21889 + atomic_dec(&ses->server->inFlight);
21890 + wake_up(&ses->server->request_q);
21891 + }
21892 + return rc;
21893 + } else
21894 + up(&ses->server->tcpSem);
21895 + if (long_op == -1)
21896 + goto cifs_no_response_exit;
21897 + else if (long_op == 2) /* writes past end of file can take looooong time */
21898 + timeout = 300 * HZ;
21899 + else if (long_op == 1)
21900 + timeout = 45 * HZ; /* should be greater than
21901 + servers oplock break timeout (about 43 seconds) */
21902 + else if (long_op > 2) {
21903 + timeout = MAX_SCHEDULE_TIMEOUT;
21904 + } else
21905 + timeout = 15 * HZ;
21906 + /* wait for 15 seconds or until woken up due to response arriving or
21907 + due to last connection to this server being unmounted */
21908 + if (signal_pending(current)) {
21909 + /* if signal pending do not hold up user for full smb timeout
21910 + but we still give response a change to complete */
21911 + if(midQ->midState & MID_REQUEST_SUBMITTED) {
21912 + set_current_state(TASK_UNINTERRUPTIBLE);
21913 + timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
21914 + }
21915 + } else { /* using normal timeout */
21916 + /* timeout = wait_event_interruptible_timeout(ses->server->response_q,
21917 + (midQ->midState & MID_RESPONSE_RECEIVED) ||
21918 + ((ses->server->tcpStatus != CifsGood) &&
21919 + (ses->server->tcpStatus != CifsNew)),
21920 + timeout); */
21921 + /* Can not allow user interrupts- wreaks havoc with performance */
21922 + if(midQ->midState & MID_REQUEST_SUBMITTED) {
21923 + set_current_state(TASK_UNINTERRUPTIBLE);
21924 + timeout = sleep_on_timeout(&ses->server->response_q,timeout);
21925 + }
21926 + }
21927 +
21928 + spin_lock(&GlobalMid_Lock);
21929 + if (midQ->resp_buf) {
21930 + spin_unlock(&GlobalMid_Lock);
21931 + receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
21932 + } else {
21933 + cERROR(1,("No response buffer"));
21934 + if(midQ->midState == MID_REQUEST_SUBMITTED) {
21935 + if(ses->server->tcpStatus == CifsExiting)
21936 + rc = -EHOSTDOWN;
21937 + else {
21938 + ses->server->tcpStatus = CifsNeedReconnect;
21939 + midQ->midState = MID_RETRY_NEEDED;
21940 + }
21941 + }
21942 +
21943 + if (rc != -EHOSTDOWN) {
21944 + if(midQ->midState == MID_RETRY_NEEDED) {
21945 + rc = -EAGAIN;
21946 + cFYI(1,("marking request for retry"));
21947 + } else {
21948 + rc = -EIO;
21949 + }
21950 + }
21951 + spin_unlock(&GlobalMid_Lock);
21952 + DeleteMidQEntry(midQ);
21953 + /* If not lock req, update # of requests on wire to server */
21954 + if(long_op < 3) {
21955 + atomic_dec(&ses->server->inFlight);
21956 + wake_up(&ses->server->request_q);
21957 + }
21958 + return rc;
21959 + }
21960 +
21961 + if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
21962 + cERROR(1,
21963 + ("Frame too large received. Length: %d Xid: %d",
21964 + receive_len, xid));
21965 + rc = -EIO;
21966 + } else { /* rcvd frame is ok */
21967 +
21968 + if (midQ->resp_buf && out_buf
21969 + && (midQ->midState == MID_RESPONSE_RECEIVED)) {
21970 + memcpy(out_buf, midQ->resp_buf,
21971 + receive_len +
21972 + 4 /* include 4 byte RFC1001 header */ );
21973 +
21974 + dump_smb(out_buf, 92);
21975 + /* convert the length into a more usable form */
21976 + out_buf->smb_buf_length =
21977 + be32_to_cpu(out_buf->smb_buf_length);
21978 + if((out_buf->smb_buf_length > 24) &&
21979 + (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
21980 + rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
21981 + if(rc)
21982 + cFYI(1,("Unexpected signature received from server"));
21983 + }
21984 +
21985 + if (out_buf->smb_buf_length > 12)
21986 + out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
21987 + if (out_buf->smb_buf_length > 28)
21988 + out_buf->Pid = le16_to_cpu(out_buf->Pid);
21989 + if (out_buf->smb_buf_length > 28)
21990 + out_buf->PidHigh =
21991 + le16_to_cpu(out_buf->PidHigh);
21992 +
21993 + *pbytes_returned = out_buf->smb_buf_length;
21994 +
21995 + /* BB special case reconnect tid and reconnect uid here? */
21996 + rc = map_smb_to_linux_error(out_buf);
21997 +
21998 + /* convert ByteCount if necessary */
21999 + if (receive_len >=
22000 + sizeof (struct smb_hdr) -
22001 + 4 /* do not count RFC1001 header */ +
22002 + (2 * out_buf->WordCount) + 2 /* bcc */ )
22003 + BCC(out_buf) = le16_to_cpu(BCC(out_buf));
22004 + } else {
22005 + rc = -EIO;
22006 + cFYI(1,("Bad MID state? "));
22007 + }
22008 + }
22009 +cifs_no_response_exit:
22010 + DeleteMidQEntry(midQ);
22011 +
22012 + if(long_op < 3) {
22013 + atomic_dec(&ses->server->inFlight);
22014 + wake_up(&ses->server->request_q);
22015 + }
22016 +
22017 + return rc;
22018 +
22019 +out_unlock:
22020 + up(&ses->server->tcpSem);
22021 + /* If not lock req, update # of requests on wire to server */
22022 + if(long_op < 3) {
22023 + atomic_dec(&ses->server->inFlight);
22024 + wake_up(&ses->server->request_q);
22025 + }
22026 +
22027 + return rc;
22028 +}
22029 Index: linux-2.4.35.4/fs/Config.in
22030 ===================================================================
22031 --- linux-2.4.35.4.orig/fs/Config.in
22032 +++ linux-2.4.35.4/fs/Config.in
22033 @@ -153,6 +153,10 @@ if [ "$CONFIG_NET" = "y" ]; then
22034 define_bool CONFIG_LOCKD_V4 y
22035 fi
22036
22037 + dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)' CONFIG_CIFS $CONFIG_INET
22038 + dep_mbool ' CIFS statistics' CONFIG_CIFS_STATS $CONFIG_CIFS
22039 + dep_mbool ' CIFS POSIX Protocol Extensions' CONFIG_CIFS_POSIX $CONFIG_CIFS
22040 +
22041 dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
22042 if [ "$CONFIG_SMB_FS" != "n" ]; then
22043 bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT
22044 Index: linux-2.4.35.4/fs/Makefile
22045 ===================================================================
22046 --- linux-2.4.35.4.orig/fs/Makefile
22047 +++ linux-2.4.35.4/fs/Makefile
22048 @@ -37,6 +37,7 @@ subdir-$(CONFIG_MSDOS_FS) += msdos
22049 subdir-$(CONFIG_VFAT_FS) += vfat
22050 subdir-$(CONFIG_BFS_FS) += bfs
22051 subdir-$(CONFIG_ISO9660_FS) += isofs
22052 +subdir-$(CONFIG_CIFS) += cifs
22053 subdir-$(CONFIG_DEVFS_FS) += devfs
22054 subdir-$(CONFIG_HFSPLUS_FS) += hfsplus # Before hfs to find wrapped HFS+
22055 subdir-$(CONFIG_HFS_FS) += hfs
22056 Index: linux-2.4.35.4/fs/nls/Config.in
22057 ===================================================================
22058 --- linux-2.4.35.4.orig/fs/nls/Config.in
22059 +++ linux-2.4.35.4/fs/nls/Config.in
22060 @@ -11,6 +11,7 @@ fi
22061
22062 # msdos and Joliet want NLS
22063 if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
22064 + -o "$CONFIG_CIFS" != "n" \
22065 -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
22066 -o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \
22067 -o "$CONFIG_BEFS_FS" != "n" -o "$CONFIG_HFSPLUS_FS" != "n" ]; then