finally move buildroot-ng to trunk
[openwrt/openwrt.git] / target / linux / generic-2.4 / patches / 107-cifs.patch
1 diff -urN linux-2.4.29.old/Documentation/Configure.help linux-2.4.29/Documentation/Configure.help
2 --- linux-2.4.29.old/Documentation/Configure.help 2005-03-21 19:30:22.000000000 +0100
3 +++ linux-2.4.29/Documentation/Configure.help 2005-03-21 19:36:51.000000000 +0100
4 @@ -17943,6 +17943,34 @@
5
6 If you don't know what all this is about, say N.
7
8 +CIFS (Common Internet File System) support
9 +CONFIG_CIFS
10 + This is the client VFS module for the Common Internet File System
11 + (CIFS) protocol which is the successor to the Server Message Block
12 + (SMB) protocol, the native file sharing mechanism for most early
13 + PC operating systems. CIFS is fully supported by current network
14 + file servers such as Windows 2000, Windows 2003 (including
15 + Windows XP) as well by Samba (which provides excellent CIFS
16 + server support for Linux and many other operating systems).
17 + The smbfs module should be used instead of this cifs module for
18 + mounting to older SMB servers such as OS/2. The smbfs and cifs
19 + modules can coexist and do not conflict.
20 +
21 + The intent of this module is to provide the most advanced network
22 + file system function for CIFS compliant servers, including better
23 + POSIX compliance, secure per-user session establishment, high
24 + performance safe distributed caching (oplock), optional packet
25 + signing, Unicode support and other internationalization improvements
26 + For more information see the project page at
27 + http://us1.samba.org/samba/Linux_CIFS_client.html
28 +
29 +CIFS Debugging
30 +CONFIG_CIFS_DEBUG
31 + If you are experiencing any problems with the CIFS filesystem, say
32 + Y here. This will result in additional debugging messages to be
33 + written to the system log. Under normal circumstances, this
34 + results in very little overhead.
35 +
36 SMB file system support (to mount Windows shares etc.)
37 CONFIG_SMB_FS
38 SMB (Server Message Block) is the protocol Windows for Workgroups
39 diff -urN linux-2.4.29.old/Documentation/filesystems/00-INDEX linux-2.4.29/Documentation/filesystems/00-INDEX
40 --- linux-2.4.29.old/Documentation/filesystems/00-INDEX 2004-02-18 14:36:30.000000000 +0100
41 +++ linux-2.4.29/Documentation/filesystems/00-INDEX 2005-03-21 19:36:51.000000000 +0100
42 @@ -10,6 +10,8 @@
43 - info for the BeOS file system (BFS)
44 bfs.txt
45 - info for the SCO UnixWare Boot Filesystem (BFS).
46 +cifs.txt
47 + - info on the Common Internet File System (CIFS)
48 coda.txt
49 - description of the CODA filesystem.
50 cramfs.txt
51 diff -urN linux-2.4.29.old/Documentation/filesystems/cifs.txt linux-2.4.29/Documentation/filesystems/cifs.txt
52 --- linux-2.4.29.old/Documentation/filesystems/cifs.txt 1970-01-01 01:00:00.000000000 +0100
53 +++ linux-2.4.29/Documentation/filesystems/cifs.txt 2005-03-21 19:36:51.000000000 +0100
54 @@ -0,0 +1,51 @@
55 + This is the client VFS module for the Common Internet File System
56 + (CIFS) protocol which is the successor to the Server Message Block
57 + (SMB) protocol, the native file sharing mechanism for most early
58 + PC operating systems. CIFS is fully supported by current network
59 + file servers such as Windows 2000, Windows 2003 (including
60 + Windows XP) as well by Samba (which provides excellent CIFS
61 + server support for Linux and many other operating systems), so
62 + this network filesystem client can mount to a wide variety of
63 + servers. The smbfs module should be used instead of this cifs module
64 + for mounting to older SMB servers such as OS/2. The smbfs and cifs
65 + modules can coexist and do not conflict. The CIFS VFS filesystem
66 + module is designed to work well with servers that implement the
67 + newer versions (dialects) of the SMB/CIFS protocol such as Samba,
68 + the program written by Andrew Tridgell that turns any Unix host
69 + into a SMB/CIFS file server.
70 +
71 + The intent of this module is to provide the most advanced network
72 + file system function for CIFS compliant servers, including better
73 + POSIX compliance, secure per-user session establishment, high
74 + performance safe distributed caching (oplock), optional packet
75 + signing, large files, Unicode support and other internationalization
76 + improvements. Since both Samba server and this filesystem client support
77 + the CIFS Unix extensions, the combination can provide a reasonable
78 + alternative to NFSv4 for fileserving in some Linux to Linux environments,
79 + not just in Linux to Windows environments.
80 +
81 + This filesystem has an optional mount utility (mount.cifs) that can
82 + be obtained from the project page and installed in the path in the same
83 + directory with the other mount helpers (such as mount.smbfs).
84 + Mounting using the cifs filesystem without installing the mount helper
85 + requires specifying the server's ip address.
86 +
87 + For Linux 2.4:
88 + mount //anything/here /mnt_target -o
89 + user=username,pass=password,unc=//ip_address_of_server/sharename
90 +
91 + For Linux 2.5:
92 + mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
93 +
94 +
95 + For more information on the module see the project page at
96 +
97 + http://us1.samba.org/samba/Linux_CIFS_client.html
98 +
99 + For more information on CIFS see:
100 +
101 + http://www.snia.org/tech_activities/CIFS
102 +
103 + or the Samba site:
104 +
105 + http://www.samba.org
106 diff -urN linux-2.4.29.old/fs/cifs/asn1.c linux-2.4.29/fs/cifs/asn1.c
107 --- linux-2.4.29.old/fs/cifs/asn1.c 1970-01-01 01:00:00.000000000 +0100
108 +++ linux-2.4.29/fs/cifs/asn1.c 2004-07-14 00:25:04.000000000 +0200
109 @@ -0,0 +1,614 @@
110 +/*
111 + * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
112 + * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
113 + *
114 + * Copyright (c) 2000 RP Internet (www.rpi.net.au).
115 + *
116 + * This program is free software; you can redistribute it and/or modify
117 + * it under the terms of the GNU General Public License as published by
118 + * the Free Software Foundation; either version 2 of the License, or
119 + * (at your option) any later version.
120 + * This program is distributed in the hope that it will be useful,
121 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
122 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
123 + * GNU General Public License for more details.
124 + * You should have received a copy of the GNU General Public License
125 + * along with this program; if not, write to the Free Software
126 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
127 + */
128 +
129 +#include <linux/config.h>
130 +#include <linux/module.h>
131 +#include <linux/types.h>
132 +#include <linux/kernel.h>
133 +#include <linux/mm.h>
134 +#include <linux/slab.h>
135 +#include "cifspdu.h"
136 +#include "cifsglob.h"
137 +#include "cifs_debug.h"
138 +
139 +/*****************************************************************************
140 + *
141 + * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
142 + *
143 + *****************************************************************************/
144 +
145 +/* Class */
146 +#define ASN1_UNI 0 /* Universal */
147 +#define ASN1_APL 1 /* Application */
148 +#define ASN1_CTX 2 /* Context */
149 +#define ASN1_PRV 3 /* Private */
150 +
151 +/* Tag */
152 +#define ASN1_EOC 0 /* End Of Contents or N/A */
153 +#define ASN1_BOL 1 /* Boolean */
154 +#define ASN1_INT 2 /* Integer */
155 +#define ASN1_BTS 3 /* Bit String */
156 +#define ASN1_OTS 4 /* Octet String */
157 +#define ASN1_NUL 5 /* Null */
158 +#define ASN1_OJI 6 /* Object Identifier */
159 +#define ASN1_OJD 7 /* Object Description */
160 +#define ASN1_EXT 8 /* External */
161 +#define ASN1_SEQ 16 /* Sequence */
162 +#define ASN1_SET 17 /* Set */
163 +#define ASN1_NUMSTR 18 /* Numerical String */
164 +#define ASN1_PRNSTR 19 /* Printable String */
165 +#define ASN1_TEXSTR 20 /* Teletext String */
166 +#define ASN1_VIDSTR 21 /* Video String */
167 +#define ASN1_IA5STR 22 /* IA5 String */
168 +#define ASN1_UNITIM 23 /* Universal Time */
169 +#define ASN1_GENTIM 24 /* General Time */
170 +#define ASN1_GRASTR 25 /* Graphical String */
171 +#define ASN1_VISSTR 26 /* Visible String */
172 +#define ASN1_GENSTR 27 /* General String */
173 +
174 +/* Primitive / Constructed methods*/
175 +#define ASN1_PRI 0 /* Primitive */
176 +#define ASN1_CON 1 /* Constructed */
177 +
178 +/*
179 + * Error codes.
180 + */
181 +#define ASN1_ERR_NOERROR 0
182 +#define ASN1_ERR_DEC_EMPTY 2
183 +#define ASN1_ERR_DEC_EOC_MISMATCH 3
184 +#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
185 +#define ASN1_ERR_DEC_BADVALUE 5
186 +
187 +#define SPNEGO_OID_LEN 7
188 +#define NTLMSSP_OID_LEN 10
189 +unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
190 +unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
191 +
192 +/*
193 + * ASN.1 context.
194 + */
195 +struct asn1_ctx {
196 + int error; /* Error condition */
197 + unsigned char *pointer; /* Octet just to be decoded */
198 + unsigned char *begin; /* First octet */
199 + unsigned char *end; /* Octet after last octet */
200 +};
201 +
202 +/*
203 + * Octet string (not null terminated)
204 + */
205 +struct asn1_octstr {
206 + unsigned char *data;
207 + unsigned int len;
208 +};
209 +
210 +static void
211 +asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
212 +{
213 + ctx->begin = buf;
214 + ctx->end = buf + len;
215 + ctx->pointer = buf;
216 + ctx->error = ASN1_ERR_NOERROR;
217 +}
218 +
219 +static unsigned char
220 +asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
221 +{
222 + if (ctx->pointer >= ctx->end) {
223 + ctx->error = ASN1_ERR_DEC_EMPTY;
224 + return 0;
225 + }
226 + *ch = *(ctx->pointer)++;
227 + return 1;
228 +}
229 +
230 +static unsigned char
231 +asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
232 +{
233 + unsigned char ch;
234 +
235 + *tag = 0;
236 +
237 + do {
238 + if (!asn1_octet_decode(ctx, &ch))
239 + return 0;
240 + *tag <<= 7;
241 + *tag |= ch & 0x7F;
242 + } while ((ch & 0x80) == 0x80);
243 + return 1;
244 +}
245 +
246 +static unsigned char
247 +asn1_id_decode(struct asn1_ctx *ctx,
248 + unsigned int *cls, unsigned int *con, unsigned int *tag)
249 +{
250 + unsigned char ch;
251 +
252 + if (!asn1_octet_decode(ctx, &ch))
253 + return 0;
254 +
255 + *cls = (ch & 0xC0) >> 6;
256 + *con = (ch & 0x20) >> 5;
257 + *tag = (ch & 0x1F);
258 +
259 + if (*tag == 0x1F) {
260 + if (!asn1_tag_decode(ctx, tag))
261 + return 0;
262 + }
263 + return 1;
264 +}
265 +
266 +static unsigned char
267 +asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
268 +{
269 + unsigned char ch, cnt;
270 +
271 + if (!asn1_octet_decode(ctx, &ch))
272 + return 0;
273 +
274 + if (ch == 0x80)
275 + *def = 0;
276 + else {
277 + *def = 1;
278 +
279 + if (ch < 0x80)
280 + *len = ch;
281 + else {
282 + cnt = (unsigned char) (ch & 0x7F);
283 + *len = 0;
284 +
285 + while (cnt > 0) {
286 + if (!asn1_octet_decode(ctx, &ch))
287 + return 0;
288 + *len <<= 8;
289 + *len |= ch;
290 + cnt--;
291 + }
292 + }
293 + }
294 + return 1;
295 +}
296 +
297 +static unsigned char
298 +asn1_header_decode(struct asn1_ctx *ctx,
299 + unsigned char **eoc,
300 + unsigned int *cls, unsigned int *con, unsigned int *tag)
301 +{
302 + unsigned int def, len;
303 +
304 + if (!asn1_id_decode(ctx, cls, con, tag))
305 + return 0;
306 +
307 + if (!asn1_length_decode(ctx, &def, &len))
308 + return 0;
309 +
310 + if (def)
311 + *eoc = ctx->pointer + len;
312 + else
313 + *eoc = NULL;
314 + return 1;
315 +}
316 +
317 +static unsigned char
318 +asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
319 +{
320 + unsigned char ch;
321 +
322 + if (eoc == 0) {
323 + if (!asn1_octet_decode(ctx, &ch))
324 + return 0;
325 +
326 + if (ch != 0x00) {
327 + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
328 + return 0;
329 + }
330 +
331 + if (!asn1_octet_decode(ctx, &ch))
332 + return 0;
333 +
334 + if (ch != 0x00) {
335 + ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
336 + return 0;
337 + }
338 + return 1;
339 + } else {
340 + if (ctx->pointer != eoc) {
341 + ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
342 + return 0;
343 + }
344 + return 1;
345 + }
346 +}
347 +
348 +/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
349 + unsigned char *eoc)
350 +{
351 + ctx->pointer = eoc;
352 + return 1;
353 +}
354 +
355 +static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
356 + unsigned char *eoc, long *integer)
357 +{
358 + unsigned char ch;
359 + unsigned int len;
360 +
361 + if (!asn1_octet_decode(ctx, &ch))
362 + return 0;
363 +
364 + *integer = (signed char) ch;
365 + len = 1;
366 +
367 + while (ctx->pointer < eoc) {
368 + if (++len > sizeof(long)) {
369 + ctx->error = ASN1_ERR_DEC_BADVALUE;
370 + return 0;
371 + }
372 +
373 + if (!asn1_octet_decode(ctx, &ch))
374 + return 0;
375 +
376 + *integer <<= 8;
377 + *integer |= ch;
378 + }
379 + return 1;
380 +}
381 +
382 +static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
383 + unsigned char *eoc,
384 + unsigned int *integer)
385 +{
386 + unsigned char ch;
387 + unsigned int len;
388 +
389 + if (!asn1_octet_decode(ctx, &ch))
390 + return 0;
391 +
392 + *integer = ch;
393 + if (ch == 0)
394 + len = 0;
395 + else
396 + len = 1;
397 +
398 + while (ctx->pointer < eoc) {
399 + if (++len > sizeof(unsigned int)) {
400 + ctx->error = ASN1_ERR_DEC_BADVALUE;
401 + return 0;
402 + }
403 +
404 + if (!asn1_octet_decode(ctx, &ch))
405 + return 0;
406 +
407 + *integer <<= 8;
408 + *integer |= ch;
409 + }
410 + return 1;
411 +}
412 +
413 +static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
414 + unsigned char *eoc,
415 + unsigned long *integer)
416 +{
417 + unsigned char ch;
418 + unsigned int len;
419 +
420 + if (!asn1_octet_decode(ctx, &ch))
421 + return 0;
422 +
423 + *integer = ch;
424 + if (ch == 0)
425 + len = 0;
426 + else
427 + len = 1;
428 +
429 + while (ctx->pointer < eoc) {
430 + if (++len > sizeof(unsigned long)) {
431 + ctx->error = ASN1_ERR_DEC_BADVALUE;
432 + return 0;
433 + }
434 +
435 + if (!asn1_octet_decode(ctx, &ch))
436 + return 0;
437 +
438 + *integer <<= 8;
439 + *integer |= ch;
440 + }
441 + return 1;
442 +}
443 +
444 +static unsigned char
445 +asn1_octets_decode(struct asn1_ctx *ctx,
446 + unsigned char *eoc,
447 + unsigned char **octets, unsigned int *len)
448 +{
449 + unsigned char *ptr;
450 +
451 + *len = 0;
452 +
453 + *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
454 + if (*octets == NULL) {
455 + return 0;
456 + }
457 +
458 + ptr = *octets;
459 + while (ctx->pointer < eoc) {
460 + if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
461 + kfree(*octets);
462 + *octets = NULL;
463 + return 0;
464 + }
465 + (*len)++;
466 + }
467 + return 1;
468 +} */
469 +
470 +static unsigned char
471 +asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
472 +{
473 + unsigned char ch;
474 +
475 + *subid = 0;
476 +
477 + do {
478 + if (!asn1_octet_decode(ctx, &ch))
479 + return 0;
480 +
481 + *subid <<= 7;
482 + *subid |= ch & 0x7F;
483 + } while ((ch & 0x80) == 0x80);
484 + return 1;
485 +}
486 +
487 +static unsigned char
488 +asn1_oid_decode(struct asn1_ctx *ctx,
489 + unsigned char *eoc, unsigned long **oid, unsigned int *len)
490 +{
491 + unsigned long subid;
492 + unsigned int size;
493 + unsigned long *optr;
494 +
495 + size = eoc - ctx->pointer + 1;
496 + *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
497 + if (*oid == NULL) {
498 + return 0;
499 + }
500 +
501 + optr = *oid;
502 +
503 + if (!asn1_subid_decode(ctx, &subid)) {
504 + kfree(*oid);
505 + *oid = NULL;
506 + return 0;
507 + }
508 +
509 + if (subid < 40) {
510 + optr[0] = 0;
511 + optr[1] = subid;
512 + } else if (subid < 80) {
513 + optr[0] = 1;
514 + optr[1] = subid - 40;
515 + } else {
516 + optr[0] = 2;
517 + optr[1] = subid - 80;
518 + }
519 +
520 + *len = 2;
521 + optr += 2;
522 +
523 + while (ctx->pointer < eoc) {
524 + if (++(*len) > size) {
525 + ctx->error = ASN1_ERR_DEC_BADVALUE;
526 + kfree(*oid);
527 + *oid = NULL;
528 + return 0;
529 + }
530 +
531 + if (!asn1_subid_decode(ctx, optr++)) {
532 + kfree(*oid);
533 + *oid = NULL;
534 + return 0;
535 + }
536 + }
537 + return 1;
538 +}
539 +
540 +static int
541 +compare_oid(unsigned long *oid1, unsigned int oid1len,
542 + unsigned long *oid2, unsigned int oid2len)
543 +{
544 + unsigned int i;
545 +
546 + if (oid1len != oid2len)
547 + return 0;
548 + else {
549 + for (i = 0; i < oid1len; i++) {
550 + if (oid1[i] != oid2[i])
551 + return 0;
552 + }
553 + return 1;
554 + }
555 +}
556 +
557 + /* BB check for endian conversion issues here */
558 +
559 +int
560 +decode_negTokenInit(unsigned char *security_blob, int length,
561 + enum securityEnum *secType)
562 +{
563 + struct asn1_ctx ctx;
564 + unsigned char *end;
565 + unsigned char *sequence_end;
566 + unsigned long *oid;
567 + unsigned int cls, con, tag, oidlen, rc;
568 + int use_ntlmssp = FALSE;
569 +
570 + *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
571 +
572 + /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
573 +
574 + asn1_open(&ctx, security_blob, length);
575 +
576 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
577 + cFYI(1, ("Error decoding negTokenInit header "));
578 + return 0;
579 + } else if ((cls != ASN1_APL) || (con != ASN1_CON)
580 + || (tag != ASN1_EOC)) {
581 + cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
582 + return 0;
583 + } else {
584 + /* remember to free obj->oid */
585 + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
586 + if (rc) {
587 + if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
588 + rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
589 + if (rc) {
590 + rc = compare_oid(oid, oidlen,
591 + SPNEGO_OID,
592 + SPNEGO_OID_LEN);
593 + kfree(oid);
594 + }
595 + } else
596 + rc = 0;
597 + }
598 +
599 + if (!rc) {
600 + cFYI(1, ("Error decoding negTokenInit header"));
601 + return 0;
602 + }
603 +
604 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
605 + cFYI(1, ("Error decoding negTokenInit "));
606 + return 0;
607 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
608 + || (tag != ASN1_EOC)) {
609 + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
610 + cls, con, tag, end, *end));
611 + return 0;
612 + }
613 +
614 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
615 + cFYI(1, ("Error decoding negTokenInit "));
616 + return 0;
617 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
618 + || (tag != ASN1_SEQ)) {
619 + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
620 + cls, con, tag, end, *end));
621 + return 0;
622 + }
623 +
624 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
625 + cFYI(1, ("Error decoding 2nd part of negTokenInit "));
626 + return 0;
627 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
628 + || (tag != ASN1_EOC)) {
629 + cFYI(1,
630 + ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
631 + cls, con, tag, end, *end));
632 + return 0;
633 + }
634 +
635 + if (asn1_header_decode
636 + (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
637 + cFYI(1, ("Error decoding 2nd part of negTokenInit "));
638 + return 0;
639 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
640 + || (tag != ASN1_SEQ)) {
641 + cFYI(1,
642 + ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
643 + cls, con, tag, end, *end));
644 + return 0;
645 + }
646 +
647 + while (!asn1_eoc_decode(&ctx, sequence_end)) {
648 + rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
649 + if (!rc) {
650 + cFYI(1,
651 + ("Error 1 decoding negTokenInit header exit 2"));
652 + return 0;
653 + }
654 + if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
655 + asn1_oid_decode(&ctx, end, &oid, &oidlen);
656 + cFYI(1,
657 + ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
658 + oidlen, *oid, *(oid + 1), *(oid + 2),
659 + *(oid + 3)));
660 + rc = compare_oid(oid, oidlen, NTLMSSP_OID,
661 + NTLMSSP_OID_LEN);
662 + kfree(oid);
663 + if (rc)
664 + use_ntlmssp = TRUE;
665 + } else {
666 + cFYI(1,("This should be an oid what is going on? "));
667 + }
668 + }
669 +
670 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
671 + cFYI(1,
672 + ("Error decoding last part of negTokenInit exit 3"));
673 + return 0;
674 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
675 + cFYI(1,
676 + ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
677 + cls, con, tag, end, *end));
678 + return 0;
679 + }
680 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
681 + cFYI(1,
682 + ("Error decoding last part of negTokenInit exit 5"));
683 + return 0;
684 + } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
685 + || (tag != ASN1_SEQ)) {
686 + cFYI(1,
687 + ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
688 + cls, con, tag, end, *end));
689 + }
690 +
691 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
692 + cFYI(1,
693 + ("Error decoding last part of negTokenInit exit 7"));
694 + return 0;
695 + } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
696 + cFYI(1,
697 + ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
698 + cls, con, tag, end, *end));
699 + return 0;
700 + }
701 + if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
702 + cFYI(1,
703 + ("Error decoding last part of negTokenInit exit 9"));
704 + return 0;
705 + } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
706 + || (tag != ASN1_GENSTR)) {
707 + cFYI(1,
708 + ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
709 + cls, con, tag, end, *end));
710 + return 0;
711 + }
712 + cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
713 + }
714 +
715 + /* if (use_kerberos)
716 + *secType = Kerberos
717 + else */
718 + if (use_ntlmssp) {
719 + *secType = NTLMSSP;
720 + }
721 +
722 + return 1;
723 +}
724 diff -urN linux-2.4.29.old/fs/cifs/AUTHORS linux-2.4.29/fs/cifs/AUTHORS
725 --- linux-2.4.29.old/fs/cifs/AUTHORS 1970-01-01 01:00:00.000000000 +0100
726 +++ linux-2.4.29/fs/cifs/AUTHORS 2004-07-14 00:25:04.000000000 +0200
727 @@ -0,0 +1,37 @@
728 +Original Author
729 +===============
730 +Steve French (sfrench@samba.org)
731 +
732 +The author wishes to express his appreciation and thanks to:
733 +Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
734 +improvements. Thanks to IBM for allowing me the time and test resources to pursue
735 +this project. Jim McDonough from IBM (and the Samba Team) for his help.
736 +The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
737 +Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
738 +for proving years ago that a very good smb/cifs client could be done on a Unix like
739 +operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
740 +and others for their work on the Linux smbfs module over the years. Thanks to
741 +the other members of the Storage Network Industry Association CIFS Technical
742 +Workgroup for their work specifying this highly complex protocol and finally
743 +thanks to the Samba team for their technical advice and encouragement.
744 +
745 +Patch Contributors
746 +------------------
747 +Zwane Mwaikambo
748 +Andi Kleen
749 +Amrut Joshi
750 +Shobhit Dayal
751 +Sergey Vlasov
752 +Richard Hughes
753 +Yury Umanets
754 +
755 +Test case and Bug Report contributors
756 +-------------------------------------
757 +Thanks to those in the community who have submitted detailed bug reports
758 +and debug of problems they have found: Jochen Dolze, David Blaine,
759 +Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
760 +Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
761 +Olaf Kirch, Kieron Briggs, Nick Millington and others.
762 +
763 +And thanks to the IBM LTC and Power test teams and SuSE testers for
764 +finding multiple bugs during excellent stress test runs.
765 diff -urN linux-2.4.29.old/fs/cifs/CHANGES linux-2.4.29/fs/cifs/CHANGES
766 --- linux-2.4.29.old/fs/cifs/CHANGES 1970-01-01 01:00:00.000000000 +0100
767 +++ linux-2.4.29/fs/cifs/CHANGES 2004-07-14 00:25:04.000000000 +0200
768 @@ -0,0 +1,572 @@
769 +Version 1.20
770 +------------
771 +Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
772 +info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir
773 +(in build_wildcard_path_from_dentry). Fix mknod to pass type field
774 +(block/char/fifo) properly. Remove spurious mount warning log entry when
775 +credentials passed as mount argument. Set major/minor device number in
776 +inode for block and char devices when unix extensions enabled.
777 +
778 +Version 1.19
779 +------------
780 +Fix /proc/fs/cifs/Stats and DebugData display to handle larger
781 +amounts of return data. Properly limit requests to MAX_REQ (50
782 +is the usual maximum active multiplex SMB/CIFS requests per server).
783 +Do not kill cifsd (and thus hurt the other SMB session) when more than one
784 +session to the same server (but with different userids) exists and one
785 +of the two user's smb sessions is being removed while leaving the other.
786 +Do not loop reconnecting in cifsd demultiplex thread when admin
787 +kills the thread without going through unmount.
788 +
789 +Version 1.18
790 +------------
791 +Do not rename hardlinked files (since that should be a noop). Flush
792 +cached write behind data when reopening a file after session abend,
793 +except when already in write. Grab per socket sem during reconnect
794 +to avoid oops in sendmsg if overlapping with reconnect. Do not
795 +reset cached inode file size on readdir for files open for write on
796 +client.
797 +
798 +
799 +Version 1.17
800 +------------
801 +Update number of blocks in file so du command is happier (in Linux a fake
802 +blocksize of 512 is required for calculating number of blocks in inode).
803 +Fix prepare write of partial pages to read in data from server if possible.
804 +Fix race on tcpStatus field between unmount and reconnection code, causing
805 +cifsd process sometimes to hang around forever. Improve out of memory
806 +checks in cifs_filldir
807 +
808 +Version 1.16
809 +------------
810 +Fix incorrect file size in file handle based setattr on big endian hardware.
811 +Fix oops in build_path_from_dentry when out of memory. Add checks for invalid
812 +and closing file structs in writepage/partialpagewrite. Add statistics
813 +for each mounted share (new menuconfig option). Fix endianness problem in
814 +volume information displayed in /proc/fs/cifs/DebugData (only affects
815 +affects big endian architectures). Prevent renames while constructing
816 +path names for open, mkdir and rmdir.
817 +
818 +Version 1.15
819 +------------
820 +Change to mempools for alloc smb request buffers and multiplex structs
821 +to better handle low memory problems (and potential deadlocks).
822 +
823 +Version 1.14
824 +------------
825 +Fix incomplete listings of large directories on Samba servers when Unix
826 +extensions enabled. Fix oops when smb_buffer can not be allocated. Fix
827 +rename deadlock when writing out dirty pages at same time.
828 +
829 +Version 1.13
830 +------------
831 +Fix open of files in which O_CREATE can cause the mode to change in
832 +some cases. Fix case in which retry of write overlaps file close.
833 +Fix PPC64 build error. Reduce excessive stack usage in smb password
834 +hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
835 +
836 +Version 1.12
837 +------------
838 +Fixes for large file copy, signal handling, socket retry, buffer
839 +allocation and low memory situations.
840 +
841 +Version 1.11
842 +------------
843 +Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
844 +also now allowing support for specifying client netbiosname. NT4 support added.
845 +
846 +Version 1.10
847 +------------
848 +Fix reconnection (and certain failed mounts) to properly wake up the
849 +blocked users thread so it does not seem hung (in some cases was blocked
850 +until the cifs receive timeout expired). Fix spurious error logging
851 +to kernel log when application with open network files killed.
852 +
853 +Version 1.09
854 +------------
855 +Fix /proc/fs module unload warning message (that could be logged
856 +to the kernel log). Fix intermittent failure in connectathon
857 +test7 (hardlink count not immediately refreshed in case in which
858 +inode metadata can be incorrectly kept cached when time near zero)
859 +
860 +Version 1.08
861 +------------
862 +Allow file_mode and dir_mode (specified at mount time) to be enforced
863 +locally (the server already enforced its own ACLs too) for servers
864 +that do not report the correct mode (do not support the
865 +CIFS Unix Extensions).
866 +
867 +Version 1.07
868 +------------
869 +Fix some small memory leaks in some unmount error paths. Fix major leak
870 +of cache pages in readpages causing multiple read oriented stress
871 +testcases (including fsx, and even large file copy) to fail over time.
872 +
873 +Version 1.06
874 +------------
875 +Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
876 +This allows files that differ only in case and improves performance of file
877 +creation and file open to such servers. Fix semaphore conflict which causes
878 +slow delete of open file to Samba (which unfortunately can cause an oplock
879 +break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
880 +
881 +Version 1.05
882 +------------
883 +fixes to cifs_readpages for fsx test case
884 +
885 +Version 1.04
886 +------------
887 +Fix caching data integrity bug when extending file size especially when no
888 +oplock on file. Fix spurious logging of valid already parsed mount options
889 +that are parsed outside of the cifs vfs such as nosuid.
890 +
891 +
892 +Version 1.03
893 +------------
894 +Connect to server when port number override not specified, and tcp port
895 +unitialized. Reset search to restart at correct file when kernel routine
896 +filldir returns error during large directory searches (readdir).
897 +
898 +Version 1.02
899 +------------
900 +Fix caching problem when files opened by multiple clients in which
901 +page cache could contain stale data, and write through did
902 +not occur often enough while file was still open when read ahead
903 +(read oplock) not allowed. Treat "sep=" when first mount option
904 +as an overrride of comma as the default separator between mount
905 +options.
906 +
907 +Version 1.01
908 +------------
909 +Allow passwords longer than 16 bytes. Allow null password string.
910 +
911 +Version 1.00
912 +------------
913 +Gracefully clean up failed mounts when attempting to mount to servers such as
914 +Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
915 +embedded commas in mount parsing of passwords.
916 +
917 +Version 0.99
918 +------------
919 +Invalidate local inode cached pages on oplock break and when last file
920 +instance is closed so that the client does not continue using stale local
921 +copy rather than later modified server copy of file. Do not reconnect
922 +when server drops the tcp session prematurely before negotiate
923 +protocol response. Fix oops in roepen_file when dentry freed. Allow
924 +the support for CIFS Unix Extensions to be disabled via proc interface.
925 +
926 +Version 0.98
927 +------------
928 +Fix hang in commit_write during reconnection of open files under heavy load.
929 +Fix unload_nls oops in a mount failure path. Serialize writes to same socket
930 +which also fixes any possible races when cifs signatures are enabled in SMBs
931 +being sent out of signature sequence number order.
932 +
933 +Version 0.97
934 +------------
935 +Fix byte range locking bug (endian problem) causing bad offset and
936 +length.
937 +
938 +Version 0.96
939 +------------
940 +Fix oops (in send_sig) caused by CIFS unmount code trying to
941 +wake up the demultiplex thread after it had exited. Do not log
942 +error on harmless oplock release of closed handle.
943 +
944 +Version 0.95
945 +------------
946 +Fix unsafe global variable usage and password hash failure on gcc 3.3.1
947 +Fix problem reconnecting secondary mounts to same server after session
948 +failure. Fix invalid dentry - race in mkdir when directory gets created
949 +by another client between the lookup and mkdir.
950 +
951 +Version 0.94
952 +------------
953 +Fix to list processing in reopen_files. Fix reconnection when server hung
954 +but tcpip session still alive. Set proper timeout on socket read.
955 +
956 +Version 0.93
957 +------------
958 +Add missing mount options including iocharset. SMP fixes in write and open.
959 +Fix errors in reconnecting after TCP session failure. Fix module unloading
960 +of default nls codepage
961 +
962 +Version 0.92
963 +------------
964 +Active smb transactions should never go negative (fix double FreeXid). Fix
965 +list processing in file routines. Check return code on kmalloc in open.
966 +Fix spinlock usage for SMP.
967 +
968 +Version 0.91
969 +------------
970 +Fix oops in reopen_files when invalid dentry. drop dentry on server rename
971 +and on revalidate errors. Fix cases where pid is now tgid. Fix return code
972 +on create hard link when server does not support them.
973 +
974 +Version 0.90
975 +------------
976 +Fix scheduling while atomic error in getting inode info on newly created file.
977 +Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
978 +
979 +Version 0.89
980 +------------
981 +Fix oops on write to dead tcp session. Remove error log write for case when file open
982 +O_CREAT but not O_EXCL
983 +
984 +Version 0.88
985 +------------
986 +Fix non-POSIX behavior on rename of open file and delete of open file by taking
987 +advantage of trans2 SetFileInfo rename facility if available on target server.
988 +Retry on ENOSPC and EAGAIN socket errors.
989 +
990 +Version 0.87
991 +------------
992 +Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
993 +allocation size miscalculation. After oplock token lost do not read through
994 +cache.
995 +
996 +Version 0.86
997 +------------
998 +Fix oops on empty file readahead. Fix for file size handling for locally cached files.
999 +
1000 +Version 0.85
1001 +------------
1002 +Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
1003 +during auto reconnection to server after server recovered from failure.
1004 +
1005 +Version 0.84
1006 +------------
1007 +Finish support for Linux 2.5 open/create changes, which removes the
1008 +redundant NTCreate/QPathInfo/close that was sent during file create.
1009 +Enable oplock by default. Enable packet signing by default (needed to
1010 +access many recent Windows servers)
1011 +
1012 +Version 0.83
1013 +------------
1014 +Fix oops when mounting to long server names caused by inverted parms to kmalloc.
1015 +Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
1016 +we will choose a cifs user session (smb uid) that better matches the local
1017 +uid if a) the mount uid does not match the current uid and b) we have another
1018 +session to the same server (ip address) for a different mount which
1019 +matches the current local uid.
1020 +
1021 +Version 0.82
1022 +------------
1023 +Add support for mknod of block or character devices. Fix oplock
1024 +code (distributed caching) to properly send response to oplock
1025 +break from server.
1026 +
1027 +Version 0.81
1028 +------------
1029 +Finish up CIFS packet digital signing for the default
1030 +NTLM security case. This should help Windows 2003
1031 +network interoperability since it is common for
1032 +packet signing to be required now. Fix statfs (stat -f)
1033 +which recently started returning errors due to
1034 +invalid value (-1 instead of 0) being set in the
1035 +struct kstatfs f_ffiles field.
1036 +
1037 +Version 0.80
1038 +-----------
1039 +Fix oops on stopping oplock thread when removing cifs when
1040 +built as module.
1041 +
1042 +Version 0.79
1043 +------------
1044 +Fix mount options for ro (readonly), uid, gid and file and directory mode.
1045 +
1046 +Version 0.78
1047 +------------
1048 +Fix errors displayed on failed mounts to be more understandable.
1049 +Fixed various incorrect or misleading smb to posix error code mappings.
1050 +
1051 +Version 0.77
1052 +------------
1053 +Fix display of NTFS DFS junctions to display as symlinks.
1054 +They are the network equivalent. Fix oops in
1055 +cifs_partialpagewrite caused by missing spinlock protection
1056 +of openfile linked list. Allow writebehind caching errors to
1057 +be returned to the application at file close.
1058 +
1059 +Version 0.76
1060 +------------
1061 +Clean up options displayed in /proc/mounts by show_options to
1062 +be more consistent with other filesystems.
1063 +
1064 +Version 0.75
1065 +------------
1066 +Fix delete of readonly file to Windows servers. Reflect
1067 +presence or absence of read only dos attribute in mode
1068 +bits for servers that do not support CIFS Unix extensions.
1069 +Fix shortened results on readdir of large directories to
1070 +servers supporting CIFS Unix extensions (caused by
1071 +incorrect resume key).
1072 +
1073 +Version 0.74
1074 +------------
1075 +Fix truncate bug (set file size) that could cause hangs e.g. running fsx
1076 +
1077 +Version 0.73
1078 +------------
1079 +unload nls if mount fails.
1080 +
1081 +Version 0.72
1082 +------------
1083 +Add resume key support to search (readdir) code to workaround
1084 +Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
1085 +allows disabling caching of attribute information for
1086 +lookups.
1087 +
1088 +Version 0.71
1089 +------------
1090 +Add more oplock handling (distributed caching code). Remove
1091 +dead code. Remove excessive stack space utilization from
1092 +symlink routines.
1093 +
1094 +Version 0.70
1095 +------------
1096 +Fix oops in get dfs referral (triggered when null path sent in to
1097 +mount). Add support for overriding rsize at mount time.
1098 +
1099 +Version 0.69
1100 +------------
1101 +Fix buffer overrun in readdir which caused intermittent kernel oopses.
1102 +Fix writepage code to release kmap on write data. Allow "-ip=" new
1103 +mount option to be passed in on parameter distinct from the first part
1104 +(server name portion of) the UNC name. Allow override of the
1105 +tcp port of the target server via new mount option "-port="
1106 +
1107 +Version 0.68
1108 +------------
1109 +Fix search handle leak on rewind. Fix setuid and gid so that they are
1110 +reflected in the local inode immediately. Cleanup of whitespace
1111 +to make 2.4 and 2.5 versions more consistent.
1112 +
1113 +
1114 +Version 0.67
1115 +------------
1116 +Fix signal sending so that captive thread (cifsd) exits on umount
1117 +(which was causing the warning in kmem_cache_free of the request buffers
1118 +at rmmod time). This had broken as a sideeffect of the recent global
1119 +kernel change to daemonize. Fix memory leak in readdir code which
1120 +showed up in "ls -R" (and applications that did search rewinding).
1121 +
1122 +Version 0.66
1123 +------------
1124 +Reconnect tids and fids after session reconnection (still do not
1125 +reconnect byte range locks though). Fix problem caching
1126 +lookup information for directory inodes, improving performance,
1127 +especially in deep directory trees. Fix various build warnings.
1128 +
1129 +Version 0.65
1130 +------------
1131 +Finish fixes to commit write for caching/readahead consistency. fsx
1132 +now works to Samba servers. Fix oops caused when readahead
1133 +was interrupted by a signal.
1134 +
1135 +Version 0.64
1136 +------------
1137 +Fix data corruption (in partial page after truncate) that caused fsx to
1138 +fail to Windows servers. Cleaned up some extraneous error logging in
1139 +common error paths. Add generic sendfile support.
1140 +
1141 +Version 0.63
1142 +------------
1143 +Fix memory leak in AllocMidQEntry.
1144 +Finish reconnection logic, so connection with server can be dropped
1145 +(or server rebooted) and the cifs client will reconnect.
1146 +
1147 +Version 0.62
1148 +------------
1149 +Fix temporary socket leak when bad userid or password specified
1150 +(or other SMBSessSetup failure). Increase maximum buffer size to slightly
1151 +over 16K to allow negotiation of up to Samba and Windows server default read
1152 +sizes. Add support for readpages
1153 +
1154 +Version 0.61
1155 +------------
1156 +Fix oops when username not passed in on mount. Extensive fixes and improvements
1157 +to error logging (strip redundant newlines, change debug macros to ensure newline
1158 +passed in and to be more consistent). Fix writepage wrong file handle problem,
1159 +a readonly file handle could be incorrectly used to attempt to write out
1160 +file updates through the page cache to multiply open files. This could cause
1161 +the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
1162 +shares to the same Windows server when using different usernames
1163 +(doing this to Samba servers worked but Windows was rejecting it) - now it is
1164 +possible to use different userids when connecting to the same server from a
1165 +Linux client. Fix oops when treeDisconnect called during unmount on
1166 +previously freed socket.
1167 +
1168 +Version 0.60
1169 +------------
1170 +Fix oops in readpages caused by not setting address space operations in inode in
1171 +rare code path.
1172 +
1173 +Version 0.59
1174 +------------
1175 +Includes support for deleting of open files and renaming over existing files (per POSIX
1176 +requirement). Add readlink support for Windows junction points (directory symlinks).
1177 +
1178 +Version 0.58
1179 +------------
1180 +Changed read and write to go through pagecache. Added additional address space operations.
1181 +Memory mapped operations now working.
1182 +
1183 +Version 0.57
1184 +------------
1185 +Added writepage code for additional memory mapping support. Fixed leak in xids causing
1186 +the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on
1187 +every stat call. Additional formatting cleanup.
1188 +
1189 +Version 0.56
1190 +------------
1191 +Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup.
1192 +
1193 +Version 0.55
1194 +------------
1195 +Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
1196 +Also included a modified version of his fix to protect global list manipulation of
1197 +the smb session and tree connection and mid related global variables.
1198 +
1199 +Version 0.54
1200 +------------
1201 +Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre
1202 +changes to superblock layout. Remove wasteful allocation of smb buffers (now the send
1203 +buffer is reused for responses). Add more oplock handling. Additional minor cleanup.
1204 +
1205 +Version 0.53
1206 +------------
1207 +More stylistic updates to better match kernel style. Add additional statistics
1208 +for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2
1209 +and CIFS Packet Signing enablement.
1210 +
1211 +Version 0.52
1212 +------------
1213 +Replace call to sleep_on with safer wait_on_event.
1214 +Make stylistic changes to better match kernel style recommendations.
1215 +Remove most typedef usage (except for the PDUs themselves).
1216 +
1217 +Version 0.51
1218 +------------
1219 +Update mount so the -unc mount option is no longer required (the ip address can be specified
1220 +in a UNC style device name. Implementation of readpage/writepage started.
1221 +
1222 +Version 0.50
1223 +------------
1224 +Fix intermittent problem with incorrect smb header checking on badly
1225 +fragmented tcp responses
1226 +
1227 +Version 0.49
1228 +------------
1229 +Fixes to setting of allocation size and file size.
1230 +
1231 +Version 0.48
1232 +------------
1233 +Various 2.5.38 fixes. Now works on 2.5.38
1234 +
1235 +Version 0.47
1236 +------------
1237 +Prepare for 2.5 kernel merge. Remove ifdefs.
1238 +
1239 +Version 0.46
1240 +------------
1241 +Socket buffer management fixes. Fix dual free.
1242 +
1243 +Version 0.45
1244 +------------
1245 +Various big endian fixes for hardlinks and symlinks and also for dfs.
1246 +
1247 +Version 0.44
1248 +------------
1249 +Various big endian fixes for servers with Unix extensions such as Samba
1250 +
1251 +Version 0.43
1252 +------------
1253 +Various FindNext fixes for incorrect filenames on large directory searches on big endian
1254 +clients. basic posix file i/o tests now work on big endian machines, not just le
1255 +
1256 +Version 0.42
1257 +------------
1258 +SessionSetup and NegotiateProtocol now work from Big Endian machines.
1259 +Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older
1260 +versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
1261 +
1262 +Version 0.41
1263 +------------
1264 +Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
1265 +files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
1266 +
1267 +Version 0.40
1268 +------------
1269 +Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
1270 +session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
1271 +Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
1272 +(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
1273 +
1274 +Version 0.38
1275 +------------
1276 +Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
1277 +it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
1278 +
1279 +Version 0.37
1280 +------------
1281 +Rewrote much of connection and mount/unmount logic to handle bugs with
1282 +multiple uses to same share, multiple users to same server etc.
1283 +
1284 +Version 0.36
1285 +------------
1286 +Fixed major problem with dentry corruption (missing call to dput)
1287 +
1288 +Version 0.35
1289 +------------
1290 +Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
1291 +Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs
1292 +although corresponding function not fully implemented in the vfs yet
1293 +
1294 +Version 0.34
1295 +------------
1296 +Fixed dentry caching bug, misc. cleanup
1297 +
1298 +Version 0.33
1299 +------------
1300 +Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build
1301 +on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
1302 +Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added.
1303 +
1304 +Version 0.32
1305 +------------
1306 +Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
1307 +and tested against Samba 2.2.5
1308 +
1309 +
1310 +Version 0.31
1311 +------------
1312 +1) Fixed lockrange to be correct (it was one byte too short)
1313 +
1314 +2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly
1315 +show range as locked when there is a conflict with an existing lock.
1316 +
1317 +3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
1318 +in most cases. Eventually will offer optional ability to query server for the correct perms.
1319 +
1320 +3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded
1321 +but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
1322 +session)
1323 +
1324 +4) Fixed error logging of valid mount options
1325 +
1326 +5) Removed logging of password field.
1327 +
1328 +6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
1329 +and cleaned them up and made them more consistent with other cifs functions.
1330 +
1331 +7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
1332 +(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
1333 +nor is the symlink support using the Unix extensions
1334 +
1335 +8) Started adding the readlink and follow_link code
1336 +
1337 +Version 0.3
1338 +-----------
1339 +Initial drop
1340 +
1341 diff -urN linux-2.4.29.old/fs/cifs/cifs_debug.c linux-2.4.29/fs/cifs/cifs_debug.c
1342 --- linux-2.4.29.old/fs/cifs/cifs_debug.c 1970-01-01 01:00:00.000000000 +0100
1343 +++ linux-2.4.29/fs/cifs/cifs_debug.c 2004-07-14 00:25:04.000000000 +0200
1344 @@ -0,0 +1,797 @@
1345 +/*
1346 + * fs/cifs_debug.c
1347 + *
1348 + * Copyright (C) International Business Machines Corp., 2000,2003
1349 + *
1350 + * Modified by Steve French (sfrench@us.ibm.com)
1351 + *
1352 + * This program is free software; you can redistribute it and/or modify
1353 + * it under the terms of the GNU General Public License as published by
1354 + * the Free Software Foundation; either version 2 of the License, or
1355 + * (at your option) any later version.
1356 + *
1357 + * This program is distributed in the hope that it will be useful,
1358 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1359 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1360 + * the GNU General Public License for more details.
1361 + *
1362 + * You should have received a copy of the GNU General Public License
1363 + * along with this program; if not, write to the Free Software
1364 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1365 + */
1366 +#include <linux/fs.h>
1367 +#include <linux/string.h>
1368 +#include <linux/ctype.h>
1369 +#include <linux/module.h>
1370 +#include <linux/proc_fs.h>
1371 +#include <asm/uaccess.h>
1372 +#include "cifspdu.h"
1373 +#include "cifsglob.h"
1374 +#include "cifsproto.h"
1375 +#include "cifs_debug.h"
1376 +
1377 +void
1378 +cifs_dump_mem(char *label, void *data, int length)
1379 +{
1380 + int i, j;
1381 + int *intptr = data;
1382 + char *charptr = data;
1383 + char buf[10], line[80];
1384 +
1385 + printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
1386 + label, length, data);
1387 + for (i = 0; i < length; i += 16) {
1388 + line[0] = 0;
1389 + for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
1390 + sprintf(buf, " %08x", intptr[i / 4 + j]);
1391 + strcat(line, buf);
1392 + }
1393 + buf[0] = ' ';
1394 + buf[2] = 0;
1395 + for (j = 0; (j < 16) && (i + j < length); j++) {
1396 + buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
1397 + strcat(line, buf);
1398 + }
1399 + printk(KERN_DEBUG "%s\n", line);
1400 + }
1401 +}
1402 +
1403 +#ifdef CONFIG_PROC_FS
1404 +int
1405 +cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
1406 + int count, int *eof, void *data)
1407 +{
1408 + struct list_head *tmp;
1409 + struct list_head *tmp1;
1410 + struct mid_q_entry * mid_entry;
1411 + struct cifsSesInfo *ses;
1412 + struct cifsTconInfo *tcon;
1413 + int i;
1414 + int length = 0;
1415 + char * original_buf = buf;
1416 +
1417 + *beginBuffer = buf + offset;
1418 +
1419 +
1420 + length =
1421 + sprintf(buf,
1422 + "Display Internal CIFS Data Structures for Debugging\n"
1423 + "---------------------------------------------------\n");
1424 + buf += length;
1425 +
1426 + length = sprintf(buf, "Servers:\n");
1427 + buf += length;
1428 +
1429 + i = 0;
1430 + read_lock(&GlobalSMBSeslock);
1431 + list_for_each(tmp, &GlobalSMBSessionList) {
1432 + i++;
1433 + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1434 + length =
1435 + sprintf(buf,
1436 + "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d",
1437 + i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
1438 + ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
1439 + buf += length;
1440 + if(ses->server) {
1441 + buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
1442 + atomic_read(&ses->server->socketUseCount),
1443 + ses->server->secMode,
1444 + atomic_read(&ses->server->inFlight));
1445 +
1446 + length = sprintf(buf, "\nMIDs: \n");
1447 + buf += length;
1448 +
1449 + spin_lock(&GlobalMid_Lock);
1450 + list_for_each(tmp1, &ses->server->pending_mid_q) {
1451 + mid_entry = list_entry(tmp1, struct
1452 + mid_q_entry,
1453 + qhead);
1454 + if(mid_entry) {
1455 + 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);
1456 + buf += length;
1457 + }
1458 + }
1459 + spin_unlock(&GlobalMid_Lock);
1460 + }
1461 +
1462 + }
1463 + read_unlock(&GlobalSMBSeslock);
1464 + sprintf(buf, "\n");
1465 + buf++;
1466 +
1467 + length = sprintf(buf, "\nShares:\n");
1468 + buf += length;
1469 +
1470 + i = 0;
1471 + read_lock(&GlobalSMBSeslock);
1472 + list_for_each(tmp, &GlobalTreeConnectionList) {
1473 + i++;
1474 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1475 + length =
1476 + sprintf(buf,
1477 + "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
1478 + i, tcon->treeName,
1479 + atomic_read(&tcon->useCount),
1480 + tcon->nativeFileSystem,
1481 + tcon->fsDevInfo.DeviceCharacteristics,
1482 + tcon->fsAttrInfo.Attributes,
1483 + tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
1484 + buf += length;
1485 + if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
1486 + length = sprintf(buf, " type: DISK ");
1487 + else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
1488 + length = sprintf(buf, " type: CDROM ");
1489 + else
1490 + length =
1491 + sprintf(buf, " type: %d ",
1492 + tcon->fsDevInfo.DeviceType);
1493 + buf += length;
1494 + if(tcon->tidStatus == CifsNeedReconnect) {
1495 + buf += sprintf(buf, "\tDISCONNECTED ");
1496 + length += 14;
1497 + }
1498 + }
1499 + read_unlock(&GlobalSMBSeslock);
1500 +
1501 + length = sprintf(buf, "\n");
1502 + buf += length;
1503 +
1504 + /* BB add code to dump additional info such as TCP session info now */
1505 + /* Now calculate total size of returned data */
1506 + length = buf - original_buf;
1507 +
1508 + if(offset + count >= length)
1509 + *eof = 1;
1510 + if(length < offset) {
1511 + *eof = 1;
1512 + return 0;
1513 + } else {
1514 + length = length - offset;
1515 + }
1516 + if (length > count)
1517 + length = count;
1518 +
1519 + return length;
1520 +}
1521 +
1522 +#ifdef CONFIG_CIFS_STATS
1523 +int
1524 +cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
1525 + int count, int *eof, void *data)
1526 +{
1527 + int item_length,i,length;
1528 + struct list_head *tmp;
1529 + struct cifsTconInfo *tcon;
1530 +
1531 + *beginBuffer = buf + offset;
1532 +
1533 + length = sprintf(buf,
1534 + "Resources in use\nCIFS Session: %d\n",
1535 + sesInfoAllocCount.counter);
1536 + buf += length;
1537 + item_length =
1538 + sprintf(buf,"Share (unique mount targets): %d\n",
1539 + tconInfoAllocCount.counter);
1540 + length += item_length;
1541 + buf += item_length;
1542 + item_length =
1543 + sprintf(buf,"SMB Request/Response Buffer: %d\n",
1544 + bufAllocCount.counter);
1545 + length += item_length;
1546 + buf += item_length;
1547 + item_length =
1548 + sprintf(buf,"Operations (MIDs): %d\n",
1549 + midCount.counter);
1550 + length += item_length;
1551 + buf += item_length;
1552 + item_length = sprintf(buf,
1553 + "\n%d session %d share reconnects\n",
1554 + tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
1555 + length += item_length;
1556 + buf += item_length;
1557 +
1558 + item_length = sprintf(buf,
1559 + "Total vfs operations: %d maximum at one time: %d\n",
1560 + GlobalCurrentXid,GlobalMaxActiveXid);
1561 + length += item_length;
1562 + buf += item_length;
1563 +
1564 + i = 0;
1565 + read_lock(&GlobalSMBSeslock);
1566 + list_for_each(tmp, &GlobalTreeConnectionList) {
1567 + i++;
1568 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1569 + item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
1570 + buf += item_length;
1571 + length += item_length;
1572 + if(tcon->tidStatus == CifsNeedReconnect) {
1573 + buf += sprintf(buf, "\tDISCONNECTED ");
1574 + length += 14;
1575 + }
1576 + item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
1577 + atomic_read(&tcon->num_smbs_sent),
1578 + atomic_read(&tcon->num_oplock_brks));
1579 + buf += item_length;
1580 + length += item_length;
1581 + item_length = sprintf(buf,"\nReads: %d Bytes %lld",
1582 + atomic_read(&tcon->num_reads),
1583 + (long long)(tcon->bytes_read));
1584 + buf += item_length;
1585 + length += item_length;
1586 + item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
1587 + atomic_read(&tcon->num_writes),
1588 + (long long)(tcon->bytes_written));
1589 + buf += item_length;
1590 + length += item_length;
1591 + item_length = sprintf(buf,
1592 + "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
1593 + atomic_read(&tcon->num_opens),
1594 + atomic_read(&tcon->num_deletes),
1595 + atomic_read(&tcon->num_mkdirs),
1596 + atomic_read(&tcon->num_rmdirs));
1597 + buf += item_length;
1598 + length += item_length;
1599 + item_length = sprintf(buf,
1600 + "\nRenames: %d T2 Renames %d",
1601 + atomic_read(&tcon->num_renames),
1602 + atomic_read(&tcon->num_t2renames));
1603 + buf += item_length;
1604 + length += item_length;
1605 + }
1606 + read_unlock(&GlobalSMBSeslock);
1607 +
1608 + buf += sprintf(buf,"\n");
1609 + length++;
1610 +
1611 + if(offset + count >= length)
1612 + *eof = 1;
1613 + if(length < offset) {
1614 + *eof = 1;
1615 + return 0;
1616 + } else {
1617 + length = length - offset;
1618 + }
1619 + if (length > count)
1620 + length = count;
1621 +
1622 + return length;
1623 +}
1624 +#endif
1625 +
1626 +struct proc_dir_entry *proc_fs_cifs;
1627 +read_proc_t cifs_txanchor_read;
1628 +static read_proc_t cifsFYI_read;
1629 +static write_proc_t cifsFYI_write;
1630 +static read_proc_t oplockEnabled_read;
1631 +static write_proc_t oplockEnabled_write;
1632 +static read_proc_t lookupFlag_read;
1633 +static write_proc_t lookupFlag_write;
1634 +static read_proc_t traceSMB_read;
1635 +static write_proc_t traceSMB_write;
1636 +static read_proc_t multiuser_mount_read;
1637 +static write_proc_t multiuser_mount_write;
1638 +static read_proc_t extended_security_read;
1639 +static write_proc_t extended_security_write;
1640 +static read_proc_t ntlmv2_enabled_read;
1641 +static write_proc_t ntlmv2_enabled_write;
1642 +static read_proc_t packet_signing_enabled_read;
1643 +static write_proc_t packet_signing_enabled_write;
1644 +static read_proc_t quotaEnabled_read;
1645 +static write_proc_t quotaEnabled_write;
1646 +static read_proc_t linuxExtensionsEnabled_read;
1647 +static write_proc_t linuxExtensionsEnabled_write;
1648 +
1649 +void
1650 +cifs_proc_init(void)
1651 +{
1652 + struct proc_dir_entry *pde;
1653 +
1654 + proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
1655 + if (proc_fs_cifs == NULL)
1656 + return;
1657 +
1658 + proc_fs_cifs->owner = THIS_MODULE;
1659 + create_proc_read_entry("DebugData", 0, proc_fs_cifs,
1660 + cifs_debug_data_read, NULL);
1661 +
1662 +#ifdef CONFIG_CIFS_STATS
1663 + create_proc_read_entry("Stats", 0, proc_fs_cifs,
1664 + cifs_stats_read, NULL);
1665 +#endif
1666 + pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
1667 + cifsFYI_read, NULL);
1668 + if (pde)
1669 + pde->write_proc = cifsFYI_write;
1670 +
1671 + pde =
1672 + create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
1673 + traceSMB_read, NULL);
1674 + if (pde)
1675 + pde->write_proc = traceSMB_write;
1676 +
1677 + pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
1678 + oplockEnabled_read, NULL);
1679 + if (pde)
1680 + pde->write_proc = oplockEnabled_write;
1681 +
1682 + pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
1683 + quotaEnabled_read, NULL);
1684 + if (pde)
1685 + pde->write_proc = quotaEnabled_write;
1686 +
1687 + pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
1688 + linuxExtensionsEnabled_read, NULL);
1689 + if (pde)
1690 + pde->write_proc = linuxExtensionsEnabled_write;
1691 +
1692 + pde =
1693 + create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
1694 + multiuser_mount_read, NULL);
1695 + if (pde)
1696 + pde->write_proc = multiuser_mount_write;
1697 +
1698 + pde =
1699 + create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
1700 + extended_security_read, NULL);
1701 + if (pde)
1702 + pde->write_proc = extended_security_write;
1703 +
1704 + pde =
1705 + create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
1706 + lookupFlag_read, NULL);
1707 + if (pde)
1708 + pde->write_proc = lookupFlag_write;
1709 +
1710 + pde =
1711 + create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
1712 + ntlmv2_enabled_read, NULL);
1713 + if (pde)
1714 + pde->write_proc = ntlmv2_enabled_write;
1715 +
1716 + pde =
1717 + create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
1718 + packet_signing_enabled_read, NULL);
1719 + if (pde)
1720 + pde->write_proc = packet_signing_enabled_write;
1721 +}
1722 +
1723 +void
1724 +cifs_proc_clean(void)
1725 +{
1726 + if (proc_fs_cifs == NULL)
1727 + return;
1728 +
1729 + remove_proc_entry("DebugData", proc_fs_cifs);
1730 + remove_proc_entry("cifsFYI", proc_fs_cifs);
1731 + remove_proc_entry("traceSMB", proc_fs_cifs);
1732 +#ifdef CONFIG_CIFS_STATS
1733 + remove_proc_entry("Stats", proc_fs_cifs);
1734 +#endif
1735 + remove_proc_entry("MultiuserMount", proc_fs_cifs);
1736 + remove_proc_entry("OplockEnabled", proc_fs_cifs);
1737 + remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
1738 + remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
1739 + remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
1740 + remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
1741 + remove_proc_entry("QuotaEnabled",proc_fs_cifs);
1742 + remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
1743 + remove_proc_entry("cifs", proc_root_fs);
1744 +}
1745 +
1746 +static int
1747 +cifsFYI_read(char *page, char **start, off_t off, int count,
1748 + int *eof, void *data)
1749 +{
1750 + int len;
1751 +
1752 + len = sprintf(page, "%d\n", cifsFYI);
1753 +
1754 + len -= off;
1755 + *start = page + off;
1756 +
1757 + if (len > count)
1758 + len = count;
1759 + else
1760 + *eof = 1;
1761 +
1762 + if (len < 0)
1763 + len = 0;
1764 +
1765 + return len;
1766 +}
1767 +static int
1768 +cifsFYI_write(struct file *file, const char *buffer,
1769 + unsigned long count, void *data)
1770 +{
1771 + char c;
1772 + int rc;
1773 +
1774 + rc = get_user(c, buffer);
1775 + if (rc)
1776 + return rc;
1777 + if (c == '0' || c == 'n' || c == 'N')
1778 + cifsFYI = 0;
1779 + else if (c == '1' || c == 'y' || c == 'Y')
1780 + cifsFYI = 1;
1781 +
1782 + return count;
1783 +}
1784 +
1785 +static int
1786 +oplockEnabled_read(char *page, char **start, off_t off,
1787 + int count, int *eof, void *data)
1788 +{
1789 + int len;
1790 +
1791 + len = sprintf(page, "%d\n", oplockEnabled);
1792 +
1793 + len -= off;
1794 + *start = page + off;
1795 +
1796 + if (len > count)
1797 + len = count;
1798 + else
1799 + *eof = 1;
1800 +
1801 + if (len < 0)
1802 + len = 0;
1803 +
1804 + return len;
1805 +}
1806 +static int
1807 +oplockEnabled_write(struct file *file, const char *buffer,
1808 + unsigned long count, void *data)
1809 +{
1810 + char c;
1811 + int rc;
1812 +
1813 + rc = get_user(c, buffer);
1814 + if (rc)
1815 + return rc;
1816 + if (c == '0' || c == 'n' || c == 'N')
1817 + oplockEnabled = 0;
1818 + else if (c == '1' || c == 'y' || c == 'Y')
1819 + oplockEnabled = 1;
1820 +
1821 + return count;
1822 +}
1823 +
1824 +static int
1825 +quotaEnabled_read(char *page, char **start, off_t off,
1826 + int count, int *eof, void *data)
1827 +{
1828 + int len;
1829 +
1830 + len = sprintf(page, "%d\n", quotaEnabled);
1831 +/* could also check if quotas are enabled in kernel
1832 + as a whole first */
1833 + len -= off;
1834 + *start = page + off;
1835 +
1836 + if (len > count)
1837 + len = count;
1838 + else
1839 + *eof = 1;
1840 +
1841 + if (len < 0)
1842 + len = 0;
1843 +
1844 + return len;
1845 +}
1846 +static int
1847 +quotaEnabled_write(struct file *file, const char *buffer,
1848 + unsigned long count, void *data)
1849 +{
1850 + char c;
1851 + int rc;
1852 +
1853 + rc = get_user(c, buffer);
1854 + if (rc)
1855 + return rc;
1856 + if (c == '0' || c == 'n' || c == 'N')
1857 + quotaEnabled = 0;
1858 + else if (c == '1' || c == 'y' || c == 'Y')
1859 + quotaEnabled = 1;
1860 +
1861 + return count;
1862 +}
1863 +
1864 +static int
1865 +linuxExtensionsEnabled_read(char *page, char **start, off_t off,
1866 + int count, int *eof, void *data)
1867 +{
1868 + int len;
1869 +
1870 + len = sprintf(page, "%d\n", linuxExtEnabled);
1871 +/* could also check if quotas are enabled in kernel
1872 + as a whole first */
1873 + len -= off;
1874 + *start = page + off;
1875 +
1876 + if (len > count)
1877 + len = count;
1878 + else
1879 + *eof = 1;
1880 +
1881 + if (len < 0)
1882 + len = 0;
1883 +
1884 + return len;
1885 +}
1886 +static int
1887 +linuxExtensionsEnabled_write(struct file *file, const char *buffer,
1888 + unsigned long count, void *data)
1889 +{
1890 + char c;
1891 + int rc;
1892 +
1893 + rc = get_user(c, buffer);
1894 + if (rc)
1895 + return rc;
1896 + if (c == '0' || c == 'n' || c == 'N')
1897 + linuxExtEnabled = 0;
1898 + else if (c == '1' || c == 'y' || c == 'Y')
1899 + linuxExtEnabled = 1;
1900 +
1901 + return count;
1902 +}
1903 +
1904 +
1905 +static int
1906 +lookupFlag_read(char *page, char **start, off_t off,
1907 + int count, int *eof, void *data)
1908 +{
1909 + int len;
1910 +
1911 + len = sprintf(page, "%d\n", lookupCacheEnabled);
1912 +
1913 + len -= off;
1914 + *start = page + off;
1915 +
1916 + if (len > count)
1917 + len = count;
1918 + else
1919 + *eof = 1;
1920 +
1921 + if (len < 0)
1922 + len = 0;
1923 +
1924 + return len;
1925 +}
1926 +static int
1927 +lookupFlag_write(struct file *file, const char *buffer,
1928 + unsigned long count, void *data)
1929 +{
1930 + char c;
1931 + int rc;
1932 +
1933 + rc = get_user(c, buffer);
1934 + if (rc)
1935 + return rc;
1936 + if (c == '0' || c == 'n' || c == 'N')
1937 + lookupCacheEnabled = 0;
1938 + else if (c == '1' || c == 'y' || c == 'Y')
1939 + lookupCacheEnabled = 1;
1940 +
1941 + return count;
1942 +}
1943 +static int
1944 +traceSMB_read(char *page, char **start, off_t off, int count,
1945 + int *eof, void *data)
1946 +{
1947 + int len;
1948 +
1949 + len = sprintf(page, "%d\n", traceSMB);
1950 +
1951 + len -= off;
1952 + *start = page + off;
1953 +
1954 + if (len > count)
1955 + len = count;
1956 + else
1957 + *eof = 1;
1958 +
1959 + if (len < 0)
1960 + len = 0;
1961 +
1962 + return len;
1963 +}
1964 +static int
1965 +traceSMB_write(struct file *file, const char *buffer,
1966 + unsigned long count, void *data)
1967 +{
1968 + char c;
1969 + int rc;
1970 +
1971 + rc = get_user(c, buffer);
1972 + if (rc)
1973 + return rc;
1974 + if (c == '0' || c == 'n' || c == 'N')
1975 + traceSMB = 0;
1976 + else if (c == '1' || c == 'y' || c == 'Y')
1977 + traceSMB = 1;
1978 +
1979 + return count;
1980 +}
1981 +
1982 +static int
1983 +multiuser_mount_read(char *page, char **start, off_t off,
1984 + int count, int *eof, void *data)
1985 +{
1986 + int len;
1987 +
1988 + len = sprintf(page, "%d\n", multiuser_mount);
1989 +
1990 + len -= off;
1991 + *start = page + off;
1992 +
1993 + if (len > count)
1994 + len = count;
1995 + else
1996 + *eof = 1;
1997 +
1998 + if (len < 0)
1999 + len = 0;
2000 +
2001 + return len;
2002 +}
2003 +static int
2004 +multiuser_mount_write(struct file *file, const char *buffer,
2005 + unsigned long count, void *data)
2006 +{
2007 + char c;
2008 + int rc;
2009 +
2010 + rc = get_user(c, buffer);
2011 + if (rc)
2012 + return rc;
2013 + if (c == '0' || c == 'n' || c == 'N')
2014 + multiuser_mount = 0;
2015 + else if (c == '1' || c == 'y' || c == 'Y')
2016 + multiuser_mount = 1;
2017 +
2018 + return count;
2019 +}
2020 +
2021 +static int
2022 +extended_security_read(char *page, char **start, off_t off,
2023 + int count, int *eof, void *data)
2024 +{
2025 + int len;
2026 +
2027 + len = sprintf(page, "%d\n", extended_security);
2028 +
2029 + len -= off;
2030 + *start = page + off;
2031 +
2032 + if (len > count)
2033 + len = count;
2034 + else
2035 + *eof = 1;
2036 +
2037 + if (len < 0)
2038 + len = 0;
2039 +
2040 + return len;
2041 +}
2042 +static int
2043 +extended_security_write(struct file *file, const char *buffer,
2044 + unsigned long count, void *data)
2045 +{
2046 + char c;
2047 + int rc;
2048 +
2049 + rc = get_user(c, buffer);
2050 + if (rc)
2051 + return rc;
2052 + if (c == '0' || c == 'n' || c == 'N')
2053 + extended_security = 0;
2054 + else if (c == '1' || c == 'y' || c == 'Y')
2055 + extended_security = 1;
2056 +
2057 + return count;
2058 +}
2059 +
2060 +static int
2061 +ntlmv2_enabled_read(char *page, char **start, off_t off,
2062 + int count, int *eof, void *data)
2063 +{
2064 + int len;
2065 +
2066 + len = sprintf(page, "%d\n", ntlmv2_support);
2067 +
2068 + len -= off;
2069 + *start = page + off;
2070 +
2071 + if (len > count)
2072 + len = count;
2073 + else
2074 + *eof = 1;
2075 +
2076 + if (len < 0)
2077 + len = 0;
2078 +
2079 + return len;
2080 +}
2081 +static int
2082 +ntlmv2_enabled_write(struct file *file, const char *buffer,
2083 + unsigned long count, void *data)
2084 +{
2085 + char c;
2086 + int rc;
2087 +
2088 + rc = get_user(c, buffer);
2089 + if (rc)
2090 + return rc;
2091 + if (c == '0' || c == 'n' || c == 'N')
2092 + ntlmv2_support = 0;
2093 + else if (c == '1' || c == 'y' || c == 'Y')
2094 + ntlmv2_support = 1;
2095 +
2096 + return count;
2097 +}
2098 +
2099 +static int
2100 +packet_signing_enabled_read(char *page, char **start, off_t off,
2101 + int count, int *eof, void *data)
2102 +{
2103 + int len;
2104 +
2105 + len = sprintf(page, "%d\n", sign_CIFS_PDUs);
2106 +
2107 + len -= off;
2108 + *start = page + off;
2109 +
2110 + if (len > count)
2111 + len = count;
2112 + else
2113 + *eof = 1;
2114 +
2115 + if (len < 0)
2116 + len = 0;
2117 +
2118 + return len;
2119 +}
2120 +static int
2121 +packet_signing_enabled_write(struct file *file, const char *buffer,
2122 + unsigned long count, void *data)
2123 +{
2124 + char c;
2125 + int rc;
2126 +
2127 + rc = get_user(c, buffer);
2128 + if (rc)
2129 + return rc;
2130 + if (c == '0' || c == 'n' || c == 'N')
2131 + sign_CIFS_PDUs = 0;
2132 + else if (c == '1' || c == 'y' || c == 'Y')
2133 + sign_CIFS_PDUs = 1;
2134 + else if (c == '2')
2135 + sign_CIFS_PDUs = 2;
2136 +
2137 + return count;
2138 +}
2139 +
2140 +
2141 +#endif
2142 diff -urN linux-2.4.29.old/fs/cifs/cifs_debug.h linux-2.4.29/fs/cifs/cifs_debug.h
2143 --- linux-2.4.29.old/fs/cifs/cifs_debug.h 1970-01-01 01:00:00.000000000 +0100
2144 +++ linux-2.4.29/fs/cifs/cifs_debug.h 2004-07-14 00:25:04.000000000 +0200
2145 @@ -0,0 +1,66 @@
2146 +/*
2147 + *
2148 + * Copyright (c) International Business Machines Corp., 2000,2002
2149 + * Modified by Steve French (sfrench@us.ibm.com)
2150 + *
2151 + * This program is free software; you can redistribute it and/or modify
2152 + * it under the terms of the GNU General Public License as published by
2153 + * the Free Software Foundation; either version 2 of the License, or
2154 + * (at your option) any later version.
2155 + *
2156 + * This program is distributed in the hope that it will be useful,
2157 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2158 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2159 + * the GNU General Public License for more details.
2160 + *
2161 + * You should have received a copy of the GNU General Public License
2162 + * along with this program; if not, write to the Free Software
2163 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2164 + *
2165 +*/
2166 +#define CIFS_DEBUG /* BB temporary */
2167 +
2168 +#ifndef _H_CIFS_DEBUG
2169 +#define _H_CIFS_DEBUG
2170 +
2171 +void cifs_dump_mem(char *label, void *data, int length);
2172 +extern int traceSMB; /* flag which enables the function below */
2173 +void dump_smb(struct smb_hdr *, int);
2174 +
2175 +/*
2176 + * debug ON
2177 + * --------
2178 + */
2179 +#ifdef CIFS_DEBUG
2180 +
2181 +
2182 +/* information message: e.g., configuration, major event */
2183 +extern int cifsFYI;
2184 +#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
2185 +
2186 +#define cFYI(button,prspec) if (button) cifsfyi prspec
2187 +
2188 +#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
2189 +
2190 +/* debug event message: */
2191 +extern int cifsERROR;
2192 +
2193 +#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
2194 +
2195 +/* error event message: e.g., i/o error */
2196 +#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
2197 +
2198 +#define cERROR(button, prspec) if (button) cifserror prspec
2199 +
2200 +/*
2201 + * debug OFF
2202 + * ---------
2203 + */
2204 +#else /* _CIFS_DEBUG */
2205 +#define cERROR(button,prspec)
2206 +#define cEVENT(format,arg...)
2207 +#define cFYI(button, prspec)
2208 +#define cifserror(format,arg...)
2209 +#endif /* _CIFS_DEBUG */
2210 +
2211 +#endif /* _H_CIFS_DEBUG */
2212 diff -urN linux-2.4.29.old/fs/cifs/cifsencrypt.c linux-2.4.29/fs/cifs/cifsencrypt.c
2213 --- linux-2.4.29.old/fs/cifs/cifsencrypt.c 1970-01-01 01:00:00.000000000 +0100
2214 +++ linux-2.4.29/fs/cifs/cifsencrypt.c 2004-07-14 00:25:04.000000000 +0200
2215 @@ -0,0 +1,204 @@
2216 +/*
2217 + * fs/cifs/cifsencrypt.c
2218 + *
2219 + * Copyright (C) International Business Machines Corp., 2003
2220 + * Author(s): Steve French (sfrench@us.ibm.com)
2221 + *
2222 + * This library is free software; you can redistribute it and/or modify
2223 + * it under the terms of the GNU Lesser General Public License as published
2224 + * by the Free Software Foundation; either version 2.1 of the License, or
2225 + * (at your option) any later version.
2226 + *
2227 + * This library is distributed in the hope that it will be useful,
2228 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2229 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2230 + * the GNU Lesser General Public License for more details.
2231 + *
2232 + * You should have received a copy of the GNU Lesser General Public License
2233 + * along with this library; if not, write to the Free Software
2234 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2235 + */
2236 +
2237 +#include <linux/fs.h>
2238 +#include "cifspdu.h"
2239 +#include "cifsglob.h"
2240 +#include "cifs_debug.h"
2241 +#include "md5.h"
2242 +#include "cifs_unicode.h"
2243 +
2244 +/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
2245 +/* the 16 byte signature must be allocated by the caller */
2246 +/* Note we only use the 1st eight bytes */
2247 +/* Note that the smb header signature field on input contains the
2248 + sequence number before this function is called */
2249 +
2250 +extern void mdfour(unsigned char *out, unsigned char *in, int n);
2251 +extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
2252 +
2253 +static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
2254 +{
2255 + struct MD5Context context;
2256 +
2257 + if((cifs_pdu == NULL) || (signature == NULL))
2258 + return -EINVAL;
2259 +
2260 + MD5Init(&context);
2261 + MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
2262 + MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
2263 + MD5Final(signature,&context);
2264 + return 0;
2265 +}
2266 +
2267 +int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
2268 + __u32 * pexpected_response_sequence_number)
2269 +{
2270 + int rc = 0;
2271 + char smb_signature[20];
2272 +
2273 + /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
2274 + /* BB remember to add code to save expected sequence number in midQ entry BB */
2275 +
2276 + if((cifs_pdu == NULL) || (ses == NULL))
2277 + return -EINVAL;
2278 +
2279 + if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
2280 + return rc;
2281 +
2282 + spin_lock(&GlobalMid_Lock);
2283 + cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
2284 + cifs_pdu->Signature.Sequence.Reserved = 0;
2285 +
2286 + *pexpected_response_sequence_number = ses->sequence_number++;
2287 + ses->sequence_number++;
2288 + spin_unlock(&GlobalMid_Lock);
2289 +
2290 + rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
2291 + if(rc)
2292 + memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
2293 + else
2294 + memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
2295 +
2296 + return rc;
2297 +}
2298 +
2299 +int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
2300 + __u32 expected_sequence_number)
2301 +{
2302 + unsigned int rc;
2303 + char server_response_sig[8];
2304 + char what_we_think_sig_should_be[20];
2305 +
2306 + if((cifs_pdu == NULL) || (mac_key == NULL))
2307 + return -EINVAL;
2308 +
2309 + if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
2310 + return 0;
2311 +
2312 + if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
2313 + struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
2314 + if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
2315 + return 0;
2316 + }
2317 +
2318 + /* BB what if signatures are supposed to be on for session but server does not
2319 + send one? BB */
2320 +
2321 + /* Do not need to verify session setups with signature "BSRSPYL " */
2322 + if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
2323 + cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
2324 +
2325 + expected_sequence_number = cpu_to_le32(expected_sequence_number);
2326 +
2327 + /* save off the origiginal signature so we can modify the smb and check
2328 + its signature against what the server sent */
2329 + memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
2330 +
2331 + cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
2332 + cifs_pdu->Signature.Sequence.Reserved = 0;
2333 +
2334 + rc = cifs_calculate_signature(cifs_pdu, mac_key,
2335 + what_we_think_sig_should_be);
2336 +
2337 + if(rc)
2338 + return rc;
2339 +
2340 +
2341 +/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
2342 +
2343 + if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
2344 + return -EACCES;
2345 + else
2346 + return 0;
2347 +
2348 +}
2349 +
2350 +/* We fill in key by putting in 40 byte array which was allocated by caller */
2351 +int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
2352 +{
2353 + char temp_key[16];
2354 + if ((key == NULL) || (rn == NULL))
2355 + return -EINVAL;
2356 +
2357 + E_md4hash(password, temp_key);
2358 + mdfour(key,temp_key,16);
2359 + memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
2360 + return 0;
2361 +}
2362 +
2363 +int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
2364 +{
2365 + char temp_hash[16];
2366 + struct HMACMD5Context ctx;
2367 + char * ucase_buf;
2368 + wchar_t * unicode_buf;
2369 + unsigned int i,user_name_len,dom_name_len;
2370 +
2371 + if(ses)
2372 + return -EINVAL;
2373 +
2374 + E_md4hash(ses->password, temp_hash);
2375 +
2376 + hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
2377 + user_name_len = strlen(ses->userName);
2378 + if(user_name_len > MAX_USERNAME_SIZE)
2379 + return -EINVAL;
2380 + dom_name_len = strlen(ses->domainName);
2381 + if(dom_name_len > MAX_USERNAME_SIZE)
2382 + return -EINVAL;
2383 +
2384 + ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
2385 + unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
2386 +
2387 + for(i=0;i<user_name_len;i++)
2388 + ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
2389 + ucase_buf[i] = 0;
2390 + user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
2391 + unicode_buf[user_name_len] = 0;
2392 + user_name_len++;
2393 +
2394 + for(i=0;i<dom_name_len;i++)
2395 + ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
2396 + ucase_buf[i] = 0;
2397 + dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
2398 +
2399 + unicode_buf[user_name_len + dom_name_len] = 0;
2400 + hmac_md5_update((const unsigned char *) unicode_buf,
2401 + (user_name_len+dom_name_len)*2,&ctx);
2402 +
2403 + hmac_md5_final(ses->mac_signing_key,&ctx);
2404 + kfree(ucase_buf);
2405 + kfree(unicode_buf);
2406 + return 0;
2407 +}
2408 +void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
2409 +{
2410 + struct HMACMD5Context context;
2411 + memcpy(v2_session_response + 8, ses->server->cryptKey,8);
2412 + /* gen_blob(v2_session_response + 16); */
2413 + hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
2414 +
2415 + hmac_md5_update(ses->server->cryptKey,8,&context);
2416 +/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
2417 +
2418 + hmac_md5_final(v2_session_response,&context);
2419 +}
2420 diff -urN linux-2.4.29.old/fs/cifs/cifserr.c linux-2.4.29/fs/cifs/cifserr.c
2421 --- linux-2.4.29.old/fs/cifs/cifserr.c 1970-01-01 01:00:00.000000000 +0100
2422 +++ linux-2.4.29/fs/cifs/cifserr.c 2004-07-14 00:25:04.000000000 +0200
2423 @@ -0,0 +1,70 @@
2424 +/*
2425 + * fs/cifserr.c
2426 + *
2427 + * Copyright (c) International Business Machines Corp., 2002
2428 + * Author(s): Steve French (sfrench@us.ibm.com)
2429 + *
2430 + * This library is free software; you can redistribute it and/or modify
2431 + * it under the terms of the GNU Lesser General Public License as published
2432 + * by the Free Software Foundation; either version 2.1 of the License, or
2433 + * (at your option) any later version.
2434 + *
2435 + * This library is distributed in the hope that it will be useful,
2436 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2437 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2438 + * the GNU Lesser General Public License for more details.
2439 + *
2440 + * You should have received a copy of the GNU Lesser General Public License
2441 + * along with this library; if not, write to the Free Software
2442 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2443 + */
2444 +
2445 +#include <linux/errno.h>
2446 +#include <linux/fs.h>
2447 +#include <linux/smbno.h>
2448 +#include "cifsfs.h"
2449 +
2450 +int map_cifs_error(int error_class, int error_code,
2451 + int status_codes_negotiated)
2452 +{
2453 +
2454 +
2455 + if (status_codes_negotiated) {
2456 + switch (error_code) {
2457 + default:
2458 + return EIO;
2459 + }
2460 + } else
2461 + switch (error_class) {
2462 + case SUCCESS:
2463 + return 0;
2464 +
2465 + case ERRDOS:
2466 + switch (error_code) {
2467 + case ERRbadfunc:
2468 + return EINVAL;
2469 + default:
2470 + return EIO;
2471 + }
2472 +
2473 + case ERRSRV:
2474 + switch (error_code) {
2475 + default:
2476 + return EIO;
2477 + }
2478 +
2479 + case ERRHRD:
2480 + switch (error_code) {
2481 + default:
2482 + return EIO;
2483 + }
2484 + default:
2485 + return EIO;
2486 + }
2487 + return 0;
2488 +}
2489 +
2490 +int map_smb_error(int error_class, int error_code)
2491 +{
2492 + return map_cifs_error(error_class, error_code, FALSE);
2493 +}
2494 diff -urN linux-2.4.29.old/fs/cifs/cifsfs.c linux-2.4.29/fs/cifs/cifsfs.c
2495 --- linux-2.4.29.old/fs/cifs/cifsfs.c 1970-01-01 01:00:00.000000000 +0100
2496 +++ linux-2.4.29/fs/cifs/cifsfs.c 2004-07-14 00:25:04.000000000 +0200
2497 @@ -0,0 +1,769 @@
2498 +/*
2499 + * fs/cifs/cifsfs.c
2500 + *
2501 + * Copyright (C) International Business Machines Corp., 2002,2004
2502 + * Author(s): Steve French (sfrench@us.ibm.com)
2503 + *
2504 + * Common Internet FileSystem (CIFS) client
2505 + *
2506 + * This library is free software; you can redistribute it and/or modify
2507 + * it under the terms of the GNU Lesser General Public License as published
2508 + * by the Free Software Foundation; either version 2.1 of the License, or
2509 + * (at your option) any later version.
2510 + *
2511 + * This library is distributed in the hope that it will be useful,
2512 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2513 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2514 + * the GNU Lesser General Public License for more details.
2515 + *
2516 + * You should have received a copy of the GNU Lesser General Public License
2517 + * along with this library; if not, write to the Free Software
2518 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2519 + */
2520 +
2521 +/* Note that BB means BUGBUG (ie something to fix eventually) */
2522 +
2523 +#include <linux/module.h>
2524 +#include <linux/fs.h>
2525 +#include <linux/mount.h>
2526 +#include <linux/slab.h>
2527 +#include <linux/init.h>
2528 +#include <linux/version.h>
2529 +#include <linux/list.h>
2530 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2531 +#include <linux/seq_file.h>
2532 +#endif
2533 +#include <linux/vfs.h>
2534 +#include "cifsfs.h"
2535 +#include "cifspdu.h"
2536 +#define DECLARE_GLOBALS_HERE
2537 +#include "cifsglob.h"
2538 +#include "cifsproto.h"
2539 +#include "cifs_debug.h"
2540 +#include "cifs_fs_sb.h"
2541 +#include <linux/mm.h>
2542 +#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
2543 +/* BB when mempool_resize is added back in, we will resize pool on new mount */
2544 +#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
2545 +
2546 +#ifdef CONFIG_CIFS_QUOTA
2547 +static struct quotactl_ops cifs_quotactl_ops;
2548 +#endif
2549 +
2550 +extern struct file_system_type cifs_fs_type;
2551 +
2552 +int cifsFYI = 0;
2553 +int cifsERROR = 1;
2554 +int traceSMB = 0;
2555 +unsigned int oplockEnabled = 1;
2556 +unsigned int quotaEnabled = 0;
2557 +unsigned int linuxExtEnabled = 1;
2558 +unsigned int lookupCacheEnabled = 1;
2559 +unsigned int multiuser_mount = 0;
2560 +unsigned int extended_security = 0;
2561 +unsigned int ntlmv2_support = 0;
2562 +unsigned int sign_CIFS_PDUs = 1;
2563 +unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
2564 +struct task_struct * oplockThread = NULL;
2565 +
2566 +extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
2567 + const char *);
2568 +extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
2569 +void cifs_proc_init(void);
2570 +void cifs_proc_clean(void);
2571 +
2572 +static DECLARE_COMPLETION(cifs_oplock_exited);
2573 +
2574 +
2575 +struct super_block *
2576 +cifs_read_super(struct super_block *sb, void *data, int silent)
2577 +{
2578 + struct inode *inode;
2579 + struct cifs_sb_info *cifs_sb;
2580 + int rc = 0;
2581 +
2582 + sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
2583 + cifs_sb = CIFS_SB(sb);
2584 + if(cifs_sb == NULL)
2585 + return 0;
2586 + else
2587 + memset(cifs_sb,0,sizeof(struct cifs_sb_info));
2588 +
2589 +
2590 + rc = cifs_mount(sb, cifs_sb, data, NULL);
2591 +
2592 + if (rc) {
2593 + if (!silent)
2594 + cERROR(1,
2595 + ("cifs_mount failed w/return code = %d", rc));
2596 + goto out_mount_failed;
2597 + }
2598 +
2599 + sb->s_magic = CIFS_MAGIC_NUMBER;
2600 + sb->s_op = &cifs_super_ops;
2601 +/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
2602 + sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
2603 +#ifdef CONFIG_CIFS_QUOTA
2604 + sb->s_qcop = &cifs_quotactl_ops;
2605 +#endif
2606 + sb->s_blocksize = CIFS_MAX_MSGSIZE;
2607 + sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
2608 + inode = iget(sb, ROOT_I);
2609 +
2610 + if (!inode) {
2611 + goto out_no_root;
2612 + }
2613 +
2614 + sb->s_root = d_alloc_root(inode);
2615 +
2616 + if (!sb->s_root) {
2617 + goto out_no_root;
2618 + }
2619 +
2620 + return sb;
2621 +
2622 +out_no_root:
2623 + cERROR(1, ("cifs_read_super: get root inode failed"));
2624 + if (inode)
2625 + iput(inode);
2626 +
2627 +out_mount_failed:
2628 + if(cifs_sb->local_nls)
2629 + unload_nls(cifs_sb->local_nls);
2630 + sb->s_dev = 0;
2631 + return 0;
2632 +}
2633 +
2634 +static void
2635 +cifs_put_super(struct super_block *sb)
2636 +{
2637 + int rc = 0;
2638 + struct cifs_sb_info *cifs_sb;
2639 +
2640 + cFYI(1, ("In cifs_put_super"));
2641 + cifs_sb = CIFS_SB(sb);
2642 + if(cifs_sb == NULL) {
2643 + cFYI(1,("Empty cifs superblock info passed to unmount"));
2644 + return;
2645 + }
2646 + rc = cifs_umount(sb, cifs_sb);
2647 + if (rc) {
2648 + cERROR(1, ("cifs_umount failed with return code %d", rc));
2649 + }
2650 + unload_nls(cifs_sb->local_nls);
2651 + return;
2652 +}
2653 +
2654 +static int
2655 +cifs_statfs(struct super_block *sb, struct statfs *buf)
2656 +{
2657 + int xid, rc;
2658 + struct cifs_sb_info *cifs_sb;
2659 + struct cifsTconInfo *pTcon;
2660 +
2661 + xid = GetXid();
2662 +
2663 + cifs_sb = CIFS_SB(sb);
2664 + pTcon = cifs_sb->tcon;
2665 +
2666 + buf->f_type = CIFS_MAGIC_NUMBER;
2667 +
2668 + /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
2669 + buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably
2670 + be length of total path, note that some servers may be
2671 + able to support more than this, but best to be safe
2672 + since Win2k and others can not handle very long filenames */
2673 + buf->f_files = 0; /* undefined */
2674 + buf->f_ffree = 0; /* unlimited */
2675 +
2676 + rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
2677 +
2678 + /*
2679 + int f_type;
2680 + __fsid_t f_fsid;
2681 + int f_namelen; */
2682 + /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
2683 + FreeXid(xid);
2684 + return 0; /* always return success? what if volume is no longer available? */
2685 +}
2686 +
2687 +static int cifs_permission(struct inode * inode, int mask)
2688 +{
2689 + /* the server does permission checks, we do not need to do it here */
2690 + return 0;
2691 +}
2692 +
2693 +kmem_cache_t *cifs_req_cachep;
2694 +kmem_cache_t *cifs_mid_cachep;
2695 +kmem_cache_t *cifs_oplock_cachep;
2696 +
2697 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2698 +static struct inode *
2699 +cifs_alloc_inode(struct super_block *sb)
2700 +{
2701 + struct cifsInodeInfo *cifs_inode;
2702 + cifs_inode =
2703 + (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
2704 + SLAB_KERNEL);
2705 + if (!cifs_inode)
2706 + return NULL;
2707 + cifs_inode->cifsAttrs = 0x20; /* default */
2708 + atomic_set(&cifs_inode->inUse, 0);
2709 + cifs_inode->time = 0;
2710 + /* Until the file is open and we have gotten oplock
2711 + info back from the server, can not assume caching of
2712 + file data or metadata */
2713 + cifs_inode->clientCanCacheRead = FALSE;
2714 + cifs_inode->clientCanCacheAll = FALSE;
2715 + INIT_LIST_HEAD(&cifs_inode->openFileList);
2716 + return &cifs_inode->vfs_inode;
2717 +}
2718 +
2719 +static void
2720 +cifs_destroy_inode(struct inode *inode)
2721 +{
2722 + kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
2723 +}
2724 +#endif
2725 +
2726 +/*
2727 + * cifs_show_options() is for displaying mount options in /proc/mounts.
2728 + * Not all settable options are displayed but most of the important
2729 + * ones are.
2730 + */
2731 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2732 +static int
2733 +cifs_show_options(struct seq_file *s, struct vfsmount *m)
2734 +{
2735 + struct cifs_sb_info *cifs_sb;
2736 +
2737 + cifs_sb = CIFS_SB(m->mnt_sb);
2738 +
2739 + if (cifs_sb) {
2740 + if (cifs_sb->tcon) {
2741 + seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
2742 + if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
2743 + seq_printf(s, ",username=%s",
2744 + cifs_sb->tcon->ses->userName);
2745 + if(cifs_sb->tcon->ses->domainName)
2746 + seq_printf(s, ",domain=%s",
2747 + cifs_sb->tcon->ses->domainName);
2748 + }
2749 + seq_printf(s, ",rsize=%d",cifs_sb->rsize);
2750 + seq_printf(s, ",wsize=%d",cifs_sb->wsize);
2751 + }
2752 + return 0;
2753 +}
2754 +#endif
2755 +
2756 +#ifdef CONFIG_CIFS_QUOTA
2757 +int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
2758 + struct fs_disk_quota * pdquota)
2759 +{
2760 + int xid;
2761 + int rc = 0;
2762 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2763 + struct cifsTconInfo *pTcon;
2764 +
2765 + if(cifs_sb)
2766 + pTcon = cifs_sb->tcon;
2767 + else
2768 + return -EIO;
2769 +
2770 +
2771 + xid = GetXid();
2772 + if(pTcon) {
2773 + cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
2774 + } else {
2775 + return -EIO;
2776 + }
2777 +
2778 + FreeXid(xid);
2779 + return rc;
2780 +}
2781 +
2782 +int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
2783 + struct fs_disk_quota * pdquota)
2784 +{
2785 + int xid;
2786 + int rc = 0;
2787 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2788 + struct cifsTconInfo *pTcon;
2789 +
2790 + if(cifs_sb)
2791 + pTcon = cifs_sb->tcon;
2792 + else
2793 + return -EIO;
2794 +
2795 + xid = GetXid();
2796 + if(pTcon) {
2797 + cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
2798 + } else {
2799 + rc = -EIO;
2800 + }
2801 +
2802 + FreeXid(xid);
2803 + return rc;
2804 +}
2805 +
2806 +int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
2807 +{
2808 + int xid;
2809 + int rc = 0;
2810 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2811 + struct cifsTconInfo *pTcon;
2812 +
2813 + if(cifs_sb)
2814 + pTcon = cifs_sb->tcon;
2815 + else
2816 + return -EIO;
2817 +
2818 + xid = GetXid();
2819 + if(pTcon) {
2820 + cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
2821 + } else {
2822 + rc = -EIO;
2823 + }
2824 +
2825 + FreeXid(xid);
2826 + return rc;
2827 +}
2828 +
2829 +int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
2830 +{
2831 + int xid;
2832 + int rc = 0;
2833 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2834 + struct cifsTconInfo *pTcon;
2835 +
2836 + if(cifs_sb) {
2837 + pTcon = cifs_sb->tcon;
2838 + } else {
2839 + return -EIO;
2840 + }
2841 + xid = GetXid();
2842 + if(pTcon) {
2843 + cFYI(1,("pqstats %p",qstats));
2844 + } else {
2845 + rc = -EIO;
2846 + }
2847 +
2848 + FreeXid(xid);
2849 + return rc;
2850 +}
2851 +
2852 +static struct quotactl_ops cifs_quotactl_ops = {
2853 + .set_xquota = cifs_xquota_set,
2854 + .get_xquota = cifs_xquota_set,
2855 + .set_xstate = cifs_xstate_set,
2856 + .get_xstate = cifs_xstate_get,
2857 +};
2858 +#endif
2859 +
2860 +static int cifs_remount(struct super_block *sb, int *flags, char *data)
2861 +{
2862 + *flags |= MS_NODIRATIME;
2863 + return 0;
2864 +}
2865 +
2866 +struct super_operations cifs_super_ops = {
2867 + .read_inode = cifs_read_inode,
2868 + .put_super = cifs_put_super,
2869 + .statfs = cifs_statfs,
2870 +/* .alloc_inode = cifs_alloc_inode,
2871 + .destroy_inode = cifs_destroy_inode, */
2872 +/* .drop_inode = generic_delete_inode,
2873 + .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
2874 + unless later we add lazy close of inodes or unless the kernel forgets to call
2875 + us with the same number of releases (closes) as opens */
2876 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
2877 + .show_options = cifs_show_options,
2878 +#endif
2879 +/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
2880 +};
2881 +
2882 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2883 +static struct super_block *
2884 +cifs_get_sb(struct file_system_type *fs_type,
2885 + int flags, const char *dev_name, void *data)
2886 +{
2887 + int rc;
2888 + struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
2889 +
2890 + cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
2891 +
2892 + if (IS_ERR(sb))
2893 + return sb;
2894 +
2895 + sb->s_flags = flags;
2896 +
2897 + rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
2898 + if (rc) {
2899 + up_write(&sb->s_umount);
2900 + deactivate_super(sb);
2901 + return ERR_PTR(rc);
2902 + }
2903 + sb->s_flags |= MS_ACTIVE;
2904 + return sb;
2905 +}
2906 +#endif
2907 +
2908 +static ssize_t
2909 +cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
2910 + loff_t * poffset)
2911 +{
2912 + if(file == NULL)
2913 + return -EIO;
2914 + else if(file->f_dentry == NULL)
2915 + return -EIO;
2916 + else if(file->f_dentry->d_inode == NULL)
2917 + return -EIO;
2918 +
2919 + if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
2920 + return generic_file_read(file,read_data,read_size,poffset);
2921 + } else {
2922 + /* BB do we need to lock inode from here until after invalidate? */
2923 +/* if(file->f_dentry->d_inode->i_mapping) {
2924 + filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
2925 + filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
2926 + }*/
2927 +/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
2928 +
2929 + /* BB we should make timer configurable - perhaps
2930 + by simply calling cifs_revalidate here */
2931 + /* invalidate_remote_inode(file->f_dentry->d_inode);*/
2932 + return generic_file_read(file,read_data,read_size,poffset);
2933 + }
2934 +}
2935 +
2936 +static ssize_t
2937 +cifs_write_wrapper(struct file * file, const char *write_data,
2938 + size_t write_size, loff_t * poffset)
2939 +{
2940 + ssize_t written;
2941 +
2942 + if(file == NULL)
2943 + return -EIO;
2944 + else if(file->f_dentry == NULL)
2945 + return -EIO;
2946 + else if(file->f_dentry->d_inode == NULL)
2947 + return -EIO;
2948 +
2949 + /* check whether we can cache writes locally */
2950 + written = generic_file_write(file,write_data,write_size,poffset);
2951 + if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
2952 + if(file->f_dentry->d_inode->i_mapping) {
2953 + filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
2954 + }
2955 + }
2956 + return written;
2957 +}
2958 +
2959 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2960 +static struct file_system_type cifs_fs_type = {
2961 + .owner = THIS_MODULE,
2962 + .name = "cifs",
2963 + .get_sb = cifs_get_sb,
2964 + .kill_sb = kill_anon_super,
2965 + /* .fs_flags */
2966 +};
2967 +#endif
2968 +
2969 +static DECLARE_FSTYPE(cifs_fs_type, "cifs", cifs_read_super,0);
2970 +
2971 +
2972 +struct inode_operations cifs_dir_inode_ops = {
2973 + .create = cifs_create,
2974 + .lookup = cifs_lookup,
2975 + .unlink = cifs_unlink,
2976 + .link = cifs_hardlink,
2977 + .mkdir = cifs_mkdir,
2978 + .rmdir = cifs_rmdir,
2979 + .rename = cifs_rename,
2980 + .permission = cifs_permission,
2981 + .revalidate = cifs_revalidate,
2982 + .setattr = cifs_setattr,
2983 + .symlink = cifs_symlink,
2984 + .mknod = cifs_mknod,
2985 +};
2986 +
2987 +struct inode_operations cifs_file_inode_ops = {
2988 + .revalidate = cifs_revalidate,
2989 + .setattr = cifs_setattr,
2990 +/* .getattr = cifs_getattr,*/
2991 + .rename = cifs_rename,
2992 + .permission = cifs_permission,
2993 +#ifdef CONFIG_CIFS_XATTR
2994 + .setxattr = cifs_setxattr,
2995 + .getxattr = cifs_getxattr,
2996 + .listxattr = cifs_listxattr,
2997 + .removexattr = cifs_removexattr,
2998 +#endif
2999 +};
3000 +
3001 +struct inode_operations cifs_symlink_inode_ops = {
3002 + .readlink = cifs_readlink,
3003 + .follow_link = cifs_follow_link,
3004 + .permission = cifs_permission,
3005 + /* BB add the following two eventually */
3006 + /* revalidate: cifs_revalidate,
3007 + setattr: cifs_notify_change, *//* BB do we need notify change */
3008 +#ifdef CONFIG_CIFS_XATTR
3009 + .setxattr = cifs_setxattr,
3010 + .getxattr = cifs_getxattr,
3011 + .listxattr = cifs_listxattr,
3012 + .removexattr = cifs_removexattr,
3013 +#endif
3014 +};
3015 +
3016 +struct file_operations cifs_file_ops = {
3017 + .read = cifs_read_wrapper,
3018 + .write = cifs_write_wrapper,
3019 + .open = cifs_open,
3020 + .release = cifs_close,
3021 + .lock = cifs_lock,
3022 + .fsync = cifs_fsync,
3023 + .flush = cifs_flush,
3024 + .mmap = cifs_file_mmap,
3025 +/* .sendfile = generic_file_sendfile,*/
3026 +#ifdef CONFIG_CIFS_FCNTL
3027 + .fcntl = cifs_fcntl,
3028 +#endif
3029 +};
3030 +
3031 +struct file_operations cifs_dir_ops = {
3032 + .readdir = cifs_readdir,
3033 + .release = cifs_closedir,
3034 + .read = generic_read_dir,
3035 +#ifdef CONFIG_CIFS_FCNTL
3036 + .fcntl = cifs_fcntl,
3037 +#endif
3038 +};
3039 +/*
3040 +static void
3041 +cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
3042 +{
3043 + struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
3044 +
3045 + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
3046 + SLAB_CTOR_CONSTRUCTOR) {
3047 + inode_init_once(&cifsi->vfs_inode);
3048 + INIT_LIST_HEAD(&cifsi->lockList);
3049 + }
3050 +}
3051 +
3052 +static int
3053 +cifs_init_inodecache(void)
3054 +{
3055 + cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
3056 + sizeof (struct cifsInodeInfo),
3057 + 0, SLAB_HWCACHE_ALIGN,
3058 + cifs_init_once, NULL);
3059 + if (cifs_inode_cachep == NULL)
3060 + return -ENOMEM;
3061 +
3062 +
3063 + return 0;
3064 +}
3065 +
3066 +static void
3067 +cifs_destroy_inodecache(void)
3068 +{
3069 + if (kmem_cache_destroy(cifs_inode_cachep))
3070 + printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
3071 +} */
3072 +
3073 +static int
3074 +cifs_init_request_bufs(void)
3075 +{
3076 + cifs_req_cachep = kmem_cache_create("cifs_request",
3077 + CIFS_MAX_MSGSIZE +
3078 + MAX_CIFS_HDR_SIZE, 0,
3079 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3080 + if (cifs_req_cachep == NULL)
3081 + return -ENOMEM;
3082 +
3083 + return 0;
3084 +}
3085 +
3086 +static void
3087 +cifs_destroy_request_bufs(void)
3088 +{
3089 + if (kmem_cache_destroy(cifs_req_cachep))
3090 + printk(KERN_WARNING
3091 + "cifs_destroy_request_cache: error not all structures were freed\n");
3092 +}
3093 +
3094 +static int
3095 +cifs_init_mids(void)
3096 +{
3097 + cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
3098 + sizeof (struct mid_q_entry), 0,
3099 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3100 + if (cifs_mid_cachep == NULL)
3101 + return -ENOMEM;
3102 + cifs_oplock_cachep = kmem_cache_create("cifs_oplock_struct",
3103 + sizeof (struct oplock_q_entry), 0,
3104 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3105 + if (cifs_oplock_cachep == NULL) {
3106 + kmem_cache_destroy(cifs_mid_cachep);
3107 + return -ENOMEM;
3108 + }
3109 +
3110 + return 0;
3111 +}
3112 +
3113 +static void
3114 +cifs_destroy_mids(void)
3115 +{
3116 + if (kmem_cache_destroy(cifs_mid_cachep))
3117 + printk(KERN_WARNING
3118 + "cifs_destroy_mids: error not all structures were freed\n");
3119 + if (kmem_cache_destroy(cifs_oplock_cachep))
3120 + printk(KERN_WARNING
3121 + "error not all oplock structures were freed\n");
3122 +}
3123 +
3124 +static int cifs_oplock_thread(void * dummyarg)
3125 +{
3126 + struct oplock_q_entry * oplock_item;
3127 + struct cifsTconInfo *pTcon;
3128 + struct inode * inode;
3129 + __u16 netfid;
3130 + int rc = 0;
3131 +
3132 + daemonize();
3133 + sprintf(current->comm,"cifsoplockd");
3134 +
3135 + oplockThread = current;
3136 + do {
3137 + set_current_state(TASK_INTERRUPTIBLE);
3138 +
3139 + schedule_timeout(1*HZ);
3140 + spin_lock(&GlobalMid_Lock);
3141 + if(list_empty(&GlobalOplock_Q)) {
3142 + spin_unlock(&GlobalMid_Lock);
3143 + set_current_state(TASK_INTERRUPTIBLE);
3144 + schedule_timeout(39*HZ);
3145 + } else {
3146 + oplock_item = list_entry(GlobalOplock_Q.next,
3147 + struct oplock_q_entry, qhead);
3148 + if(oplock_item) {
3149 + cFYI(1,("found oplock item to write out"));
3150 + pTcon = oplock_item->tcon;
3151 + inode = oplock_item->pinode;
3152 + netfid = oplock_item->netfid;
3153 + spin_unlock(&GlobalMid_Lock);
3154 + DeleteOplockQEntry(oplock_item);
3155 + /* can not grab inode sem here since it would
3156 + deadlock when oplock received on delete
3157 + since vfs_unlink holds the i_sem across
3158 + the call */
3159 + /* down(&inode->i_sem);*/
3160 + if (S_ISREG(inode->i_mode)) {
3161 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
3162 + rc = filemap_fdatasync(inode->i_mapping);
3163 + if(rc)
3164 + CIFS_I(inode)->write_behind_rc = rc;
3165 +#else
3166 + filemap_fdatasync(inode->i_mapping);
3167 +#endif
3168 + if(CIFS_I(inode)->clientCanCacheRead == 0)
3169 + invalidate_inode_pages(inode);
3170 + } else
3171 + rc = 0;
3172 + /* releasing a stale oplock after recent reconnection
3173 + of smb session using a now incorrect file
3174 + handle is not a data integrity issue but do
3175 + not bother sending an oplock release if session
3176 + to server still is disconnected since oplock
3177 + already released by the server in that case */
3178 + if(pTcon->tidStatus != CifsNeedReconnect) {
3179 + rc = CIFSSMBLock(0, pTcon,
3180 + netfid,
3181 + 0 /* len */ , 0 /* offset */, 0,
3182 + 0, LOCKING_ANDX_OPLOCK_RELEASE,
3183 + 0 /* wait flag */);
3184 + cFYI(1,("Oplock release rc = %d ",rc));
3185 + }
3186 + } else
3187 + spin_unlock(&GlobalMid_Lock);
3188 + }
3189 + } while(!signal_pending(current));
3190 + complete_and_exit (&cifs_oplock_exited, 0);
3191 +}
3192 +
3193 +static int __init
3194 +init_cifs(void)
3195 +{
3196 + int rc = 0;
3197 +#if CONFIG_PROC_FS
3198 + cifs_proc_init();
3199 +#endif
3200 + INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
3201 + INIT_LIST_HEAD(&GlobalSMBSessionList);
3202 + INIT_LIST_HEAD(&GlobalTreeConnectionList);
3203 + INIT_LIST_HEAD(&GlobalOplock_Q);
3204 +/*
3205 + * Initialize Global counters
3206 + */
3207 + atomic_set(&sesInfoAllocCount, 0);
3208 + atomic_set(&tconInfoAllocCount, 0);
3209 + atomic_set(&tcpSesReconnectCount, 0);
3210 + atomic_set(&tconInfoReconnectCount, 0);
3211 +
3212 + atomic_set(&bufAllocCount, 0);
3213 + atomic_set(&midCount, 0);
3214 + GlobalCurrentXid = 0;
3215 + GlobalTotalActiveXid = 0;
3216 + GlobalMaxActiveXid = 0;
3217 + GlobalSMBSeslock = RW_LOCK_UNLOCKED;
3218 + GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
3219 +
3220 +/* rc = cifs_init_inodecache();*/
3221 + if (!rc) {
3222 + rc = cifs_init_mids();
3223 + if (!rc) {
3224 + rc = cifs_init_request_bufs();
3225 + if (!rc) {
3226 + rc = register_filesystem(&cifs_fs_type);
3227 + if (!rc) {
3228 + kernel_thread(cifs_oplock_thread, NULL,
3229 + CLONE_FS | CLONE_FILES | CLONE_VM);
3230 + return rc; /* Success */
3231 + } else
3232 + cifs_destroy_request_bufs();
3233 + }
3234 + cifs_destroy_mids();
3235 + }
3236 +/* cifs_destroy_inodecache(); */
3237 + }
3238 +#if CONFIG_PROC_FS
3239 + cifs_proc_clean();
3240 +#endif
3241 + return rc;
3242 +}
3243 +
3244 +static void __exit
3245 +exit_cifs(void)
3246 +{
3247 + cFYI(0, ("In unregister ie exit_cifs"));
3248 +#if CONFIG_PROC_FS
3249 + cifs_proc_clean();
3250 +#endif
3251 + unregister_filesystem(&cifs_fs_type);
3252 +/* cifs_destroy_inodecache();*/
3253 + cifs_destroy_mids();
3254 + cifs_destroy_request_bufs();
3255 + if(oplockThread) {
3256 + send_sig(SIGTERM, oplockThread, 1);
3257 + wait_for_completion(&cifs_oplock_exited);
3258 + }
3259 +}
3260 +
3261 +MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
3262 +MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
3263 +MODULE_DESCRIPTION
3264 + ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
3265 +module_init(init_cifs)
3266 +module_exit(exit_cifs)
3267 diff -urN linux-2.4.29.old/fs/cifs/cifsfs.h linux-2.4.29/fs/cifs/cifsfs.h
3268 --- linux-2.4.29.old/fs/cifs/cifsfs.h 1970-01-01 01:00:00.000000000 +0100
3269 +++ linux-2.4.29/fs/cifs/cifsfs.h 2004-07-14 00:25:04.000000000 +0200
3270 @@ -0,0 +1,97 @@
3271 +/*
3272 + * fs/cifs/cifsfs.h
3273 + *
3274 + * Copyright (c) International Business Machines Corp., 2002
3275 + * Author(s): Steve French (sfrench@us.ibm.com)
3276 + *
3277 + * This library is free software; you can redistribute it and/or modify
3278 + * it under the terms of the GNU Lesser General Public License as published
3279 + * by the Free Software Foundation; either version 2.1 of the License, or
3280 + * (at your option) any later version.
3281 + *
3282 + * This library is distributed in the hope that it will be useful,
3283 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3284 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3285 + * the GNU Lesser General Public License for more details.
3286 + *
3287 + * You should have received a copy of the GNU Lesser General Public License
3288 + * along with this library; if not, write to the Free Software
3289 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3290 + */
3291 +
3292 +#ifndef _CIFSFS_H
3293 +#define _CIFSFS_H
3294 +
3295 +#define ROOT_I 2
3296 +
3297 +#ifndef FALSE
3298 +#define FALSE 0
3299 +#endif
3300 +
3301 +#ifndef TRUE
3302 +#define TRUE 1
3303 +#endif
3304 +
3305 +extern int map_cifs_error(int error_class, int error_code,
3306 + int status_codes_negotiated);
3307 +
3308 +extern struct address_space_operations cifs_addr_ops;
3309 +
3310 +/* Functions related to super block operations */
3311 +extern struct super_operations cifs_super_ops;
3312 +extern void cifs_put_inode(struct inode *);
3313 +extern void cifs_read_inode(struct inode *);
3314 +extern void cifs_delete_inode(struct inode *);
3315 +/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
3316 +
3317 +/* Functions related to inodes */
3318 +extern struct inode_operations cifs_dir_inode_ops;
3319 +extern int cifs_create(struct inode *, struct dentry *, int);
3320 +extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
3321 +extern int cifs_unlink(struct inode *, struct dentry *);
3322 +extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
3323 +extern int cifs_mknod(struct inode *, struct dentry *, int, int);
3324 +extern int cifs_mkdir(struct inode *, struct dentry *, int);
3325 +extern int cifs_rmdir(struct inode *, struct dentry *);
3326 +extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
3327 + struct dentry *);
3328 +extern int cifs_revalidate(struct dentry *);
3329 +extern int cifs_setattr(struct dentry *, struct iattr *);
3330 +
3331 +extern struct inode_operations cifs_file_inode_ops;
3332 +extern void cifs_truncate_file(struct inode *);
3333 +extern struct inode_operations cifs_symlink_inode_ops;
3334 +
3335 +/* Functions related to files and directories */
3336 +extern struct file_operations cifs_file_ops;
3337 +extern int cifs_open(struct inode *inode, struct file *file);
3338 +extern int cifs_close(struct inode *inode, struct file *file);
3339 +extern int cifs_closedir(struct inode *inode, struct file *file);
3340 +extern ssize_t cifs_read(struct file *file, char *read_data,
3341 + size_t read_size, loff_t * poffset);
3342 +extern ssize_t cifs_write(struct file *file, const char *write_data,
3343 + size_t write_size, loff_t * poffset);
3344 +extern int cifs_lock(struct file *, int, struct file_lock *);
3345 +extern int cifs_fsync(struct file *, struct dentry *, int);
3346 +extern int cifs_flush(struct file *);
3347 +extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
3348 +extern struct file_operations cifs_dir_ops;
3349 +extern int cifs_dir_open(struct inode *inode, struct file *file);
3350 +extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
3351 +extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *);
3352 +
3353 +/* Functions related to dir entries */
3354 +extern struct dentry_operations cifs_dentry_ops;
3355 +
3356 +/* Functions related to symlinks */
3357 +extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
3358 +extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
3359 +extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
3360 + const char *symname);
3361 +extern int cifs_removexattr(struct dentry *, const char *);
3362 +extern int cifs_setxattr(struct dentry *, const char *, const void *,
3363 + size_t, int);
3364 +extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
3365 +extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
3366 +#define CIFS_VERSION "1.20"
3367 +#endif /* _CIFSFS_H */
3368 diff -urN linux-2.4.29.old/fs/cifs/cifs_fs_sb.h linux-2.4.29/fs/cifs/cifs_fs_sb.h
3369 --- linux-2.4.29.old/fs/cifs/cifs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
3370 +++ linux-2.4.29/fs/cifs/cifs_fs_sb.h 2004-07-14 00:25:04.000000000 +0200
3371 @@ -0,0 +1,32 @@
3372 +/*
3373 + * fs/cifs/cifs_fs_sb.h
3374 + *
3375 + * Copyright (c) International Business Machines Corp., 2002
3376 + * Author(s): Steve French (sfrench@us.ibm.com)
3377 + *
3378 + * This library is free software; you can redistribute it and/or modify
3379 + * it under the terms of the GNU Lesser General Public License as published
3380 + * by the Free Software Foundation; either version 2.1 of the License, or
3381 + * (at your option) any later version.
3382 + *
3383 + * This library is distributed in the hope that it will be useful,
3384 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3385 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3386 + * the GNU Lesser General Public License for more details.
3387 + *
3388 + */
3389 +#ifndef _CIFS_FS_SB_H
3390 +#define _CIFS_FS_SB_H
3391 +
3392 +struct cifs_sb_info {
3393 + struct cifsTconInfo *tcon; /* primary mount */
3394 + struct list_head nested_tcon_q;
3395 + struct nls_table *local_nls;
3396 + unsigned int rsize;
3397 + unsigned int wsize;
3398 + uid_t mnt_uid;
3399 + gid_t mnt_gid;
3400 + mode_t mnt_file_mode;
3401 + mode_t mnt_dir_mode;
3402 +};
3403 +#endif /* _CIFS_FS_SB_H */
3404 diff -urN linux-2.4.29.old/fs/cifs/cifsglob.h linux-2.4.29/fs/cifs/cifsglob.h
3405 --- linux-2.4.29.old/fs/cifs/cifsglob.h 1970-01-01 01:00:00.000000000 +0100
3406 +++ linux-2.4.29/fs/cifs/cifsglob.h 2004-07-14 00:25:05.000000000 +0200
3407 @@ -0,0 +1,413 @@
3408 +/*
3409 + * fs/cifs/cifsglob.h
3410 + *
3411 + * Copyright (C) International Business Machines Corp., 2002,2003
3412 + * Author(s): Steve French (sfrench@us.ibm.com)
3413 + *
3414 + * This library is free software; you can redistribute it and/or modify
3415 + * it under the terms of the GNU Lesser General Public License as published
3416 + * by the Free Software Foundation; either version 2.1 of the License, or
3417 + * (at your option) any later version.
3418 + *
3419 + * This library is distributed in the hope that it will be useful,
3420 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3421 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3422 + * the GNU Lesser General Public License for more details.
3423 + *
3424 + */
3425 +#include <linux/in.h>
3426 +#include <linux/in6.h>
3427 +#include "cifs_fs_sb.h"
3428 +/*
3429 + * The sizes of various internal tables and strings
3430 + */
3431 +#define MAX_UID_INFO 16
3432 +#define MAX_SES_INFO 2
3433 +#define MAX_TCON_INFO 4
3434 +
3435 +#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
3436 +#define MAX_SERVER_SIZE 15
3437 +#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
3438 +#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
3439 + termination then *2 for unicode versions */
3440 +#define MAX_PASSWORD_SIZE 16
3441 +
3442 +/*
3443 + * MAX_REQ is the maximum number of requests that WE will send
3444 + * on one socket concurently. It also matches the most common
3445 + * value of max multiplex returned by servers. We may
3446 + * eventually want to use the negotiated value (in case
3447 + * future servers can handle more) when we are more confident that
3448 + * we will not have problems oveloading the socket with pending
3449 + * write data.
3450 + */
3451 +#define CIFS_MAX_REQ 50
3452 +
3453 +#define SERVER_NAME_LENGTH 15
3454 +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
3455 +
3456 +/* used to define string lengths for reversing unicode strings */
3457 +/* (256+1)*2 = 514 */
3458 +/* (max path length + 1 for null) * 2 for unicode */
3459 +#define MAX_NAME 514
3460 +
3461 +#include "cifspdu.h"
3462 +
3463 +#ifndef FALSE
3464 +#define FALSE 0
3465 +#endif
3466 +
3467 +#ifndef TRUE
3468 +#define TRUE 1
3469 +#endif
3470 +
3471 +#ifndef XATTR_DOS_ATTRIB
3472 +#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
3473 +#endif
3474 +
3475 +/*
3476 + * This information is kept on every Server we know about.
3477 + *
3478 + * Some things to note:
3479 + *
3480 + */
3481 +#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
3482 +
3483 +/*
3484 + * CIFS vfs client Status information (based on what we know.)
3485 + */
3486 +
3487 + /* associated with each tcp and smb session */
3488 +enum statusEnum {
3489 + CifsNew = 0,
3490 + CifsGood,
3491 + CifsExiting,
3492 + CifsNeedReconnect
3493 +};
3494 +
3495 +enum securityEnum {
3496 + NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
3497 + NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
3498 + RawNTLMSSP, /* NTLMSSP without SPNEGO */
3499 + NTLMSSP, /* NTLMSSP via SPNEGO */
3500 + Kerberos /* Kerberos via SPNEGO */
3501 +};
3502 +
3503 +enum protocolEnum {
3504 + IPV4 = 0,
3505 + IPV6,
3506 + SCTP
3507 + /* Netbios frames protocol not supported at this time */
3508 +};
3509 +
3510 +/*
3511 + *****************************************************************
3512 + * Except the CIFS PDUs themselves all the
3513 + * globally interesting structs should go here
3514 + *****************************************************************
3515 + */
3516 +
3517 +struct TCP_Server_Info {
3518 + char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
3519 + char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
3520 + struct socket *ssocket;
3521 + union {
3522 + struct sockaddr_in sockAddr;
3523 + struct sockaddr_in6 sockAddr6;
3524 + } addr;
3525 + wait_queue_head_t response_q;
3526 + wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
3527 + struct list_head pending_mid_q;
3528 + void *Server_NlsInfo; /* BB - placeholder for future NLS info */
3529 + unsigned short server_codepage; /* codepage for the server */
3530 + unsigned long ip_address; /* IP addr for the server if known */
3531 + enum protocolEnum protocolType;
3532 + char versionMajor;
3533 + char versionMinor;
3534 + int svlocal:1; /* local server or remote */
3535 + atomic_t socketUseCount; /* number of open cifs sessions on socket */
3536 + atomic_t inFlight; /* number of requests on the wire to server */
3537 + enum statusEnum tcpStatus; /* what we think the status is */
3538 + struct semaphore tcpSem;
3539 + struct task_struct *tsk;
3540 + char server_GUID[16];
3541 + char secMode;
3542 + enum securityEnum secType;
3543 + unsigned int maxReq; /* Clients should submit no more */
3544 + /* than maxReq distinct unanswered SMBs to the server when using */
3545 + /* multiplexed reads or writes */
3546 + unsigned int maxBuf; /* maxBuf specifies the maximum */
3547 + /* message size the server can send or receive for non-raw SMBs */
3548 + unsigned int maxRw; /* maxRw specifies the maximum */
3549 + /* message size the server can send or receive for */
3550 + /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
3551 + char sessid[4]; /* unique token id for this session */
3552 + /* (returned on Negotiate */
3553 + int capabilities; /* allow selective disabling of caps by smb sess */
3554 + __u16 timeZone;
3555 + char cryptKey[CIFS_CRYPTO_KEY_SIZE];
3556 + char workstation_RFC1001_name[16]; /* 16th byte is always zero */
3557 +};
3558 +
3559 +/*
3560 + * The following is our shortcut to user information. We surface the uid,
3561 + * and name. We always get the password on the fly in case it
3562 + * has changed. We also hang a list of sessions owned by this user off here.
3563 + */
3564 +struct cifsUidInfo {
3565 + struct list_head userList;
3566 + struct list_head sessionList; /* SMB sessions for this user */
3567 + uid_t linux_uid;
3568 + char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
3569 + /* BB may need ptr or callback for PAM or WinBind info */
3570 +};
3571 +
3572 +/*
3573 + * Session structure. One of these for each uid session with a particular host
3574 + */
3575 +struct cifsSesInfo {
3576 + struct list_head cifsSessionList;
3577 + struct semaphore sesSem;
3578 + struct cifsUidInfo *uidInfo; /* pointer to user info */
3579 + struct TCP_Server_Info *server; /* pointer to server info */
3580 + atomic_t inUse; /* # of mounts (tree connections) on this ses */
3581 + enum statusEnum status;
3582 + __u32 sequence_number; /* needed for CIFS PDU signature */
3583 + __u16 ipc_tid; /* special tid for connection to IPC share */
3584 + char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
3585 + char *serverOS; /* name of operating system underlying the server */
3586 + char *serverNOS; /* name of network operating system that the server is running */
3587 + char *serverDomain; /* security realm of server */
3588 + int Suid; /* remote smb uid */
3589 + uid_t linux_uid; /* local Linux uid */
3590 + int capabilities;
3591 + char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
3592 + char userName[MAX_USERNAME_SIZE + 1];
3593 + char domainName[MAX_USERNAME_SIZE + 1];
3594 + char * password;
3595 +};
3596 +
3597 +/*
3598 + * there is one of these for each connection to a resource on a particular
3599 + * session
3600 + */
3601 +struct cifsTconInfo {
3602 + struct list_head cifsConnectionList;
3603 + struct list_head openFileList;
3604 + struct semaphore tconSem;
3605 + struct cifsSesInfo *ses; /* pointer to session associated with */
3606 + char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
3607 + char *nativeFileSystem;
3608 + __u16 tid; /* The 2 byte tree id */
3609 + __u16 Flags; /* optional support bits */
3610 + enum statusEnum tidStatus;
3611 + atomic_t useCount; /* how many mounts (explicit or implicit) to this share */
3612 +#ifdef CONFIG_CIFS_STATS
3613 + atomic_t num_smbs_sent;
3614 + atomic_t num_writes;
3615 + atomic_t num_reads;
3616 + atomic_t num_oplock_brks;
3617 + atomic_t num_opens;
3618 + atomic_t num_deletes;
3619 + atomic_t num_mkdirs;
3620 + atomic_t num_rmdirs;
3621 + atomic_t num_renames;
3622 + atomic_t num_t2renames;
3623 + __u64 bytes_read;
3624 + __u64 bytes_written;
3625 + spinlock_t stat_lock;
3626 +#endif
3627 + FILE_SYSTEM_DEVICE_INFO fsDevInfo;
3628 + FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
3629 + FILE_SYSTEM_UNIX_INFO fsUnixInfo;
3630 + int retry:1;
3631 + /* BB add field for back pointer to sb struct? */
3632 +};
3633 +
3634 +/*
3635 + * This info hangs off the cifsFileInfo structure. This is used to track
3636 + * byte stream locks on the file
3637 + */
3638 +struct cifsLockInfo {
3639 + struct cifsLockInfo *next;
3640 + int start;
3641 + int length;
3642 + int type;
3643 +};
3644 +
3645 +/*
3646 + * One of these for each open instance of a file
3647 + */
3648 +struct cifsFileInfo {
3649 + struct list_head tlist; /* pointer to next fid owned by tcon */
3650 + struct list_head flist; /* next fid (file instance) for this inode */
3651 + unsigned int uid; /* allows finding which FileInfo structure */
3652 + __u32 pid; /* process id who opened file */
3653 + __u16 netfid; /* file id from remote */
3654 + /* BB add lock scope info here if needed */ ;
3655 + /* lock scope id (0 if none) */
3656 + struct file * pfile; /* needed for writepage */
3657 + struct inode * pInode; /* needed for oplock break */
3658 + int endOfSearch:1; /* we have reached end of search */
3659 + int closePend:1; /* file is marked to close */
3660 + int emptyDir:1;
3661 + int invalidHandle:1; /* file closed via session abend */
3662 + struct semaphore fh_sem; /* prevents reopen race after dead ses*/
3663 + char * search_resume_name;
3664 + unsigned int resume_name_length;
3665 + __u32 resume_key;
3666 +};
3667 +
3668 +/*
3669 + * One of these for each file inode
3670 + */
3671 +
3672 +struct cifsInodeInfo {
3673 + struct list_head lockList;
3674 + /* BB add in lists for dirty pages - i.e. write caching info for oplock */
3675 + struct list_head openFileList;
3676 + int write_behind_rc;
3677 + __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
3678 + atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
3679 + unsigned long time; /* jiffies of last update/check of inode */
3680 + int clientCanCacheRead:1; /* read oplock */
3681 + int clientCanCacheAll:1; /* read and writebehind oplock */
3682 + int oplockPending:1;
3683 + struct inode vfs_inode;
3684 +};
3685 +
3686 +static inline struct cifsInodeInfo * CIFS_I(struct inode *inode)
3687 +{
3688 + return (struct cifsInodeInfo *)&(inode->u);
3689 +}
3690 +
3691 +static inline struct cifs_sb_info * CIFS_SB(struct super_block *sb)
3692 +{
3693 + return (struct cifs_sb_info *) &(sb->u);
3694 +}
3695 +
3696 +
3697 +/* one of these for every pending CIFS request to the server */
3698 +struct mid_q_entry {
3699 + struct list_head qhead; /* mids waiting on reply from this server */
3700 + __u16 mid; /* multiplex id */
3701 + __u16 pid; /* process id */
3702 + __u32 sequence_number; /* for CIFS signing */
3703 + __u16 command; /* smb command code */
3704 + struct timeval when_sent; /* time when smb sent */
3705 + struct cifsSesInfo *ses; /* smb was sent to this server */
3706 + struct task_struct *tsk; /* task waiting for response */
3707 + struct smb_hdr *resp_buf; /* response buffer */
3708 + int midState; /* wish this were enum but can not pass to wait_event */
3709 +};
3710 +
3711 +struct oplock_q_entry {
3712 + struct list_head qhead;
3713 + struct inode * pinode;
3714 + struct cifsTconInfo * tcon;
3715 + __u16 netfid;
3716 +};
3717 +
3718 +#define MID_FREE 0
3719 +#define MID_REQUEST_ALLOCATED 1
3720 +#define MID_REQUEST_SUBMITTED 2
3721 +#define MID_RESPONSE_RECEIVED 4
3722 +#define MID_RETRY_NEEDED 8 /* session closed while this request out */
3723 +
3724 +/*
3725 + *****************************************************************
3726 + * All constants go here
3727 + *****************************************************************
3728 + */
3729 +
3730 +#define UID_HASH (16)
3731 +
3732 +/*
3733 + * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
3734 + * following to be declared.
3735 + */
3736 +
3737 +/****************************************************************************
3738 + * Locking notes. All updates to global variables and lists should be
3739 + * protected by spinlocks or semaphores.
3740 + *
3741 + * Spinlocks
3742 + * ---------
3743 + * GlobalMid_Lock protects:
3744 + * list operations on pending_mid_q and oplockQ
3745 + * updates to XID counters, multiplex id and SMB sequence numbers
3746 + * GlobalSMBSesLock protects:
3747 + * list operations on tcp and SMB session lists and tCon lists
3748 + * f_owner.lock protects certain per file struct operations
3749 + * mapping->page_lock protects certain per page operations
3750 + *
3751 + * Semaphores
3752 + * ----------
3753 + * sesSem operations on smb session
3754 + * tconSem operations on tree connection
3755 + * fh_sem file handle reconnection operations
3756 + *
3757 + ****************************************************************************/
3758 +
3759 +#ifdef DECLARE_GLOBALS_HERE
3760 +#define GLOBAL_EXTERN
3761 +#else
3762 +#define GLOBAL_EXTERN extern
3763 +#endif
3764 +
3765 +/*
3766 + * The list of servers that did not respond with NT LM 0.12.
3767 + * This list helps improve performance and eliminate the messages indicating
3768 + * that we had a communications error talking to the server in this list.
3769 + */
3770 +GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
3771 +
3772 +/*
3773 + * The following is a hash table of all the users we know about.
3774 + */
3775 +GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
3776 +
3777 +GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
3778 +GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
3779 +GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
3780 +GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
3781 +
3782 +GLOBAL_EXTERN struct list_head GlobalOplock_Q;
3783 +
3784 +/*
3785 + * Global transaction id (XID) information
3786 + */
3787 +GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
3788 +GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
3789 +GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
3790 +GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
3791 + /* on midQ entries */
3792 +GLOBAL_EXTERN char Local_System_Name[15];
3793 +
3794 +/*
3795 + * Global counters, updated atomically
3796 + */
3797 +GLOBAL_EXTERN atomic_t sesInfoAllocCount;
3798 +GLOBAL_EXTERN atomic_t tconInfoAllocCount;
3799 +
3800 +GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
3801 +GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
3802 +
3803 +/* Various Debug counters to remove someday (BB) */
3804 +GLOBAL_EXTERN atomic_t bufAllocCount;
3805 +GLOBAL_EXTERN atomic_t midCount;
3806 +
3807 +/* Misc globals */
3808 +GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
3809 + to be established on existing mount if we
3810 + have the uid/password or Kerberos credential
3811 + or equivalent for current user */
3812 +GLOBAL_EXTERN unsigned int oplockEnabled;
3813 +GLOBAL_EXTERN unsigned int quotaEnabled;
3814 +GLOBAL_EXTERN unsigned int lookupCacheEnabled;
3815 +GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
3816 + with more secure ntlmssp2 challenge/resp */
3817 +GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
3818 +GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
3819 +GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */
3820 +
3821 diff -urN linux-2.4.29.old/fs/cifs/cifspdu.h linux-2.4.29/fs/cifs/cifspdu.h
3822 --- linux-2.4.29.old/fs/cifs/cifspdu.h 1970-01-01 01:00:00.000000000 +0100
3823 +++ linux-2.4.29/fs/cifs/cifspdu.h 2004-07-14 00:25:05.000000000 +0200
3824 @@ -0,0 +1,1793 @@
3825 +/*
3826 + * fs/cifs/cifspdu.h
3827 + *
3828 + * Copyright (c) International Business Machines Corp., 2002
3829 + * Author(s): Steve French (sfrench@us.ibm.com)
3830 + *
3831 + * This library is free software; you can redistribute it and/or modify
3832 + * it under the terms of the GNU Lesser General Public License as published
3833 + * by the Free Software Foundation; either version 2.1 of the License, or
3834 + * (at your option) any later version.
3835 + *
3836 + * This library is distributed in the hope that it will be useful,
3837 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3838 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3839 + * the GNU Lesser General Public License for more details.
3840 + *
3841 + * You should have received a copy of the GNU Lesser General Public License
3842 + * along with this library; if not, write to the Free Software
3843 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3844 + */
3845 +
3846 +#ifndef _CIFSPDU_H
3847 +#define _CIFSPDU_H
3848 +
3849 +#include <net/sock.h>
3850 +
3851 +#define CIFS_PROT 0
3852 +#define BAD_PROT CIFS_PROT+1
3853 +
3854 +/* SMB command codes */
3855 +#define SMB_COM_CREATE_DIRECTORY 0x00
3856 +#define SMB_COM_DELETE_DIRECTORY 0x01
3857 +#define SMB_COM_CLOSE 0x04
3858 +#define SMB_COM_DELETE 0x06
3859 +#define SMB_COM_RENAME 0x07
3860 +#define SMB_COM_LOCKING_ANDX 0x24
3861 +#define SMB_COM_COPY 0x29
3862 +#define SMB_COM_READ_ANDX 0x2E
3863 +#define SMB_COM_WRITE_ANDX 0x2F
3864 +#define SMB_COM_TRANSACTION2 0x32
3865 +#define SMB_COM_TRANSACTION2_SECONDARY 0x33
3866 +#define SMB_COM_FIND_CLOSE2 0x34
3867 +#define SMB_COM_TREE_DISCONNECT 0x71
3868 +#define SMB_COM_NEGOTIATE 0x72
3869 +#define SMB_COM_SESSION_SETUP_ANDX 0x73
3870 +#define SMB_COM_LOGOFF_ANDX 0x74
3871 +#define SMB_COM_TREE_CONNECT_ANDX 0x75
3872 +#define SMB_COM_NT_TRANSACT 0xA0
3873 +#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
3874 +#define SMB_COM_NT_CREATE_ANDX 0xA2
3875 +#define SMB_COM_NT_RENAME 0xA5
3876 +
3877 +/* Transact2 subcommand codes */
3878 +#define TRANS2_OPEN 0x00
3879 +#define TRANS2_FIND_FIRST 0x01
3880 +#define TRANS2_FIND_NEXT 0x02
3881 +#define TRANS2_QUERY_FS_INFORMATION 0x03
3882 +#define TRANS2_QUERY_PATH_INFORMATION 0x05
3883 +#define TRANS2_SET_PATH_INFORMATION 0x06
3884 +#define TRANS2_QUERY_FILE_INFORMATION 0x07
3885 +#define TRANS2_SET_FILE_INFORMATION 0x08
3886 +#define TRANS2_GET_DFS_REFERRAL 0x10
3887 +#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
3888 +
3889 +/* NT Transact subcommand codes */
3890 +#define NT_TRANSACT_CREATE 0x01
3891 +#define NT_TRANSACT_IOCTL 0x02
3892 +#define NT_TRANSACT_SET_SECURITY_DESC 0x03
3893 +#define NT_TRANSACT_NOTIFY_CHANGE 0x04
3894 +#define NT_TRANSACT_RENAME 0x05
3895 +#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
3896 +#define NT_TRANSACT_GET_USER_QUOTA 0x07
3897 +#define NT_TRANSACT_SET_USER_QUOTA 0x08
3898 +
3899 +#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
3900 +
3901 +/* internal cifs vfs structures */
3902 +/*****************************************************************
3903 + * All constants go here
3904 + *****************************************************************
3905 + */
3906 +
3907 +/*
3908 + * Starting value for maximum SMB size negotiation
3909 + */
3910 +#define CIFS_MAX_MSGSIZE (4*4096)
3911 +
3912 +/*
3913 + * Size of encrypted user password in bytes
3914 + */
3915 +#define CIFS_ENCPWD_SIZE (16)
3916 +
3917 +/*
3918 + * Size of the crypto key returned on the negotiate SMB in bytes
3919 + */
3920 +#define CIFS_CRYPTO_KEY_SIZE (8)
3921 +
3922 +/*
3923 + * Size of the session key (crypto key encrypted with the password
3924 + */
3925 +#define CIFS_SESSION_KEY_SIZE (24)
3926 +
3927 +/*
3928 + * Maximum user name length
3929 + */
3930 +#define CIFS_UNLEN (20)
3931 +
3932 +/*
3933 + * Flags on SMB open
3934 + */
3935 +#define SMBOPEN_WRITE_THROUGH 0x4000
3936 +#define SMBOPEN_DENY_ALL 0x0010
3937 +#define SMBOPEN_DENY_WRITE 0x0020
3938 +#define SMBOPEN_DENY_READ 0x0030
3939 +#define SMBOPEN_DENY_NONE 0x0040
3940 +#define SMBOPEN_READ 0x0000
3941 +#define SMBOPEN_WRITE 0x0001
3942 +#define SMBOPEN_READWRITE 0x0002
3943 +#define SMBOPEN_EXECUTE 0x0003
3944 +
3945 +#define SMBOPEN_OCREATE 0x0010
3946 +#define SMBOPEN_OTRUNC 0x0002
3947 +#define SMBOPEN_OAPPEND 0x0001
3948 +
3949 +/*
3950 + * SMB flag definitions
3951 + */
3952 +#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
3953 +#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
3954 +#define SMBFLG_RSVD 0x04
3955 +#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
3956 +#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
3957 +#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
3958 +#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
3959 +#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
3960 +
3961 +/*
3962 + * SMB flag2 definitions
3963 + */
3964 +#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */
3965 +#define SMBFLG2_KNOWS_EAS 0x0002
3966 +#define SMBFLG2_SECURITY_SIGNATURE 0x0004
3967 +#define SMBFLG2_IS_LONG_NAME 0x0040
3968 +#define SMBFLG2_EXT_SEC 0x0800
3969 +#define SMBFLG2_DFS 0x1000
3970 +#define SMBFLG2_PAGING_IO 0x2000
3971 +#define SMBFLG2_ERR_STATUS 0x4000
3972 +#define SMBFLG2_UNICODE 0x8000
3973 +
3974 +/*
3975 + * These are the file access permission bits defined in CIFS for the
3976 + * NTCreateAndX as well as the level 0x107
3977 + * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
3978 + * responds with the AccessFlags.
3979 + * The AccessFlags specifies the access permissions a caller has to the
3980 + * file and can have any suitable combination of the following values:
3981 + */
3982 +
3983 +#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
3984 +#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
3985 +#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
3986 +#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
3987 + /* with the file can be read */
3988 +#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
3989 + /* with the file can be written */
3990 +#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
3991 + /* the file using system paging I/O */
3992 +#define FILE_DELETE_CHILD 0x00000040
3993 +#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
3994 + /* file can be read */
3995 +#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
3996 + /* file can be written */
3997 +#define DELETE 0x00010000 /* The file can be deleted */
3998 +#define READ_CONTROL 0x00020000 /* The access control list and */
3999 + /* ownership associated with the */
4000 + /* file can be read */
4001 +#define WRITE_DAC 0x00040000 /* The access control list and */
4002 + /* ownership associated with the */
4003 + /* file can be written. */
4004 +#define WRITE_OWNER 0x00080000 /* Ownership information associated */
4005 + /* with the file can be written */
4006 +#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
4007 + /* synchronize with the completion */
4008 + /* of an input/output request */
4009 +#define GENERIC_ALL 0x10000000
4010 +#define GENERIC_EXECUTE 0x20000000
4011 +#define GENERIC_WRITE 0x40000000
4012 +#define GENERIC_READ 0x80000000
4013 + /* In summary - Relevant file */
4014 + /* access flags from CIFS are */
4015 + /* file_read_data, file_write_data */
4016 + /* file_execute, file_read_attributes */
4017 + /* write_dac, and delete. */
4018 +
4019 +/*
4020 + * Invalid readdir handle
4021 + */
4022 +#define CIFS_NO_HANDLE 0xFFFF
4023 +
4024 +/* IPC$ in ASCII */
4025 +#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
4026 +
4027 +/* IPC$ in Unicode */
4028 +#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
4029 +
4030 +/* Unicode Null terminate 2 bytes of 0 */
4031 +#define UNICODE_NULL "\x00\x00"
4032 +#define ASCII_NULL 0x00
4033 +
4034 +/*
4035 + * Server type values (returned on EnumServer API
4036 + */
4037 +#define CIFS_SV_TYPE_DC 0x00000008
4038 +#define CIFS_SV_TYPE_BACKDC 0x00000010
4039 +
4040 +/*
4041 + * Alias type flags (From EnumAlias API call
4042 + */
4043 +#define CIFS_ALIAS_TYPE_FILE 0x0001
4044 +#define CIFS_SHARE_TYPE_FILE 0x0000
4045 +
4046 +/*
4047 + * File Attribute flags
4048 + */
4049 +#define ATTR_READONLY 0x0001
4050 +#define ATTR_HIDDEN 0x0002
4051 +#define ATTR_SYSTEM 0x0004
4052 +#define ATTR_VOLUME 0x0008
4053 +#define ATTR_DIRECTORY 0x0010
4054 +#define ATTR_ARCHIVE 0x0020
4055 +#define ATTR_DEVICE 0x0040
4056 +#define ATTR_NORMAL 0x0080
4057 +#define ATTR_TEMPORARY 0x0100
4058 +#define ATTR_SPARSE 0x0200
4059 +#define ATTR_REPARSE 0x0400
4060 +#define ATTR_COMPRESSED 0x0800
4061 +#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
4062 +#define ATTR_NOT_CONTENT_INDEXED 0x2000
4063 +#define ATTR_ENCRYPTED 0x4000
4064 +#define ATTR_POSIX_SEMANTICS 0x01000000
4065 +#define ATTR_BACKUP_SEMANTICS 0x02000000
4066 +#define ATTR_DELETE_ON_CLOSE 0x04000000
4067 +#define ATTR_SEQUENTIAL_SCAN 0x08000000
4068 +#define ATTR_RANDOM_ACCESS 0x10000000
4069 +#define ATTR_NO_BUFFERING 0x20000000
4070 +#define ATTR_WRITE_THROUGH 0x80000000
4071 +
4072 +/* ShareAccess flags */
4073 +#define FILE_NO_SHARE 0x00000000
4074 +#define FILE_SHARE_READ 0x00000001
4075 +#define FILE_SHARE_WRITE 0x00000002
4076 +#define FILE_SHARE_DELETE 0x00000004
4077 +#define FILE_SHARE_ALL 0x00000007
4078 +
4079 +/* CreateDisposition flags */
4080 +#define FILE_SUPERSEDE 0x00000000
4081 +#define FILE_OPEN 0x00000001
4082 +#define FILE_CREATE 0x00000002
4083 +#define FILE_OPEN_IF 0x00000003
4084 +#define FILE_OVERWRITE 0x00000004
4085 +#define FILE_OVERWRITE_IF 0x00000005
4086 +
4087 +/* CreateOptions */
4088 +#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
4089 +#define CREATE_WRITE_THROUGH 0x00000002
4090 +#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
4091 +#define CREATE_RANDOM_ACCESS 0x00000800
4092 +#define CREATE_DELETE_ON_CLOSE 0x00001000
4093 +#define OPEN_REPARSE_POINT 0x00200000
4094 +
4095 +/* ImpersonationLevel flags */
4096 +#define SECURITY_ANONYMOUS 0
4097 +#define SECURITY_IDENTIFICATION 1
4098 +#define SECURITY_IMPERSONATION 2
4099 +#define SECURITY_DELEGATION 3
4100 +
4101 +/* SecurityFlags */
4102 +#define SECURITY_CONTEXT_TRACKING 0x01
4103 +#define SECURITY_EFFECTIVE_ONLY 0x02
4104 +
4105 +/*
4106 + * Default PID value, used in all SMBs where the PID is not important
4107 + */
4108 +#define CIFS_DFT_PID 0x1234
4109 +
4110 +/*
4111 + * We use the same routine for Copy and Move SMBs. This flag is used to
4112 + * distinguish
4113 + */
4114 +#define CIFS_COPY_OP 1
4115 +#define CIFS_RENAME_OP 2
4116 +
4117 +#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
4118 +#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
4119 +
4120 +#pragma pack(1)
4121 +
4122 +struct smb_hdr {
4123 + __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 */
4124 + __u8 Protocol[4];
4125 + __u8 Command;
4126 + union {
4127 + struct {
4128 + __u8 ErrorClass;
4129 + __u8 Reserved;
4130 + __u16 Error; /* note: treated as little endian (le) on wire */
4131 + } DosError;
4132 + __u32 CifsError; /* note: le */
4133 + } Status;
4134 + __u8 Flags;
4135 + __u16 Flags2; /* note: le */
4136 + __u16 PidHigh; /* note: le */
4137 + union {
4138 + struct {
4139 + __u32 SequenceNumber; /* le */
4140 + __u32 Reserved; /* zero */
4141 + } Sequence;
4142 + __u8 SecuritySignature[8]; /* le */
4143 + } Signature;
4144 + __u8 pad[2];
4145 + __u16 Tid;
4146 + __u16 Pid; /* note: le */
4147 + __u16 Uid;
4148 + __u16 Mid;
4149 + __u8 WordCount;
4150 +};
4151 +/* given a pointer to an smb_hdr retrieve the value of byte count */
4152 +#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
4153 +
4154 +/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
4155 +#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
4156 +
4157 +/*
4158 + * Computer Name Length
4159 + */
4160 +#define CNLEN 15
4161 +
4162 +/*
4163 + * Share Name Length @S8A
4164 + * Note: This length is limited by the SMB used to get @S8A
4165 + * the Share info. NetShareEnum only returns 13 @S8A
4166 + * chars, including the null termination. @S8A
4167 + */
4168 +#define SNLEN 12 /*@S8A */
4169 +
4170 +/*
4171 + * Comment Length
4172 + */
4173 +#define MAXCOMMENTLEN 40
4174 +
4175 +/*
4176 + * The OS/2 maximum path name
4177 + */
4178 +#define MAX_PATHCONF 256
4179 +
4180 +/*
4181 + * SMB frame definitions (following must be packed structs)
4182 + * See the SNIA CIFS Specification for details.
4183 + *
4184 + * The Naming convention is the lower case version of the
4185 + * smb command code name for the struct and this is typedef to the
4186 + * uppercase version of the same name with the prefix SMB_ removed
4187 + * for brevity. Although typedefs are not commonly used for
4188 + * structure definitions in the Linux kernel, their use in the
4189 + * CIFS standards document, which this code is based on, may
4190 + * make this one of the cases where typedefs for structures make
4191 + * sense to improve readability for readers of the standards doc.
4192 + * Typedefs can always be removed later if they are too distracting
4193 + * and they are only used for the CIFSs PDUs themselves, not
4194 + * internal cifs vfs structures
4195 + *
4196 + */
4197 +
4198 +typedef struct negotiate_req {
4199 + struct smb_hdr hdr; /* wct = 0 */
4200 + __u16 ByteCount;
4201 + unsigned char DialectsArray[1];
4202 +} NEGOTIATE_REQ;
4203 +
4204 +typedef struct negotiate_rsp {
4205 + struct smb_hdr hdr; /* wct = 17 */
4206 + __u16 DialectIndex;
4207 + __u8 SecurityMode;
4208 + __u16 MaxMpxCount;
4209 + __u16 MaxNumberVcs;
4210 + __u32 MaxBufferSize;
4211 + __u32 MaxRawSize;
4212 + __u32 SessionKey;
4213 + __u32 Capabilities; /* see below */
4214 + __u32 SystemTimeLow;
4215 + __u32 SystemTimeHigh;
4216 + __u16 ServerTimeZone;
4217 + __u8 EncryptionKeyLength;
4218 + __u16 ByteCount;
4219 + union {
4220 + unsigned char EncryptionKey[1]; /* if cap extended security is off */
4221 + /* followed by Domain name - if extended security is off */
4222 + /* followed by 16 bytes of server GUID */
4223 + /* followed by security blob if cap_extended_security negotiated */
4224 + struct {
4225 + unsigned char GUID[16];
4226 + unsigned char SecurityBlob[1];
4227 + } extended_response;
4228 + } u;
4229 +} NEGOTIATE_RSP;
4230 +
4231 +/* SecurityMode bits */
4232 +#define SECMODE_USER 0x01 /* off indicates share level security */
4233 +#define SECMODE_PW_ENCRYPT 0x02
4234 +#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
4235 +#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
4236 +
4237 +/* Negotiate response Capabilities */
4238 +#define CAP_RAW_MODE 0x00000001
4239 +#define CAP_MPX_MODE 0x00000002
4240 +#define CAP_UNICODE 0x00000004
4241 +#define CAP_LARGE_FILES 0x00000008
4242 +#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
4243 +#define CAP_RPC_REMOTE_APIS 0x00000020
4244 +#define CAP_STATUS32 0x00000040
4245 +#define CAP_LEVEL_II_OPLOCKS 0x00000080
4246 +#define CAP_LOCK_AND_READ 0x00000100
4247 +#define CAP_NT_FIND 0x00000200
4248 +#define CAP_DFS 0x00001000
4249 +#define CAP_INFOLEVEL_PASSTHRU 0x00002000
4250 +#define CAP_LARGE_READ_X 0x00004000
4251 +#define CAP_LARGE_WRITE_X 0x00008000
4252 +#define CAP_UNIX 0x00800000
4253 +#define CAP_RESERVED 0x02000000
4254 +#define CAP_BULK_TRANSFER 0x20000000
4255 +#define CAP_COMPRESSED_DATA 0x40000000
4256 +#define CAP_EXTENDED_SECURITY 0x80000000
4257 +
4258 +typedef union smb_com_session_setup_andx {
4259 + struct { /* request format */
4260 + struct smb_hdr hdr; /* wct = 12 */
4261 + __u8 AndXCommand;
4262 + __u8 AndXReserved;
4263 + __u16 AndXOffset;
4264 + __u16 MaxBufferSize;
4265 + __u16 MaxMpxCount;
4266 + __u16 VcNumber;
4267 + __u32 SessionKey;
4268 + __u16 SecurityBlobLength;
4269 + __u32 Reserved;
4270 + __u32 Capabilities; /* see below */
4271 + __u16 ByteCount;
4272 + unsigned char SecurityBlob[1]; /* followed by */
4273 + /* STRING NativeOS */
4274 + /* STRING NativeLanMan */
4275 + } req; /* NTLM request format (with extended security */
4276 +
4277 + struct { /* request format */
4278 + struct smb_hdr hdr; /* wct = 13 */
4279 + __u8 AndXCommand;
4280 + __u8 AndXReserved;
4281 + __u16 AndXOffset;
4282 + __u16 MaxBufferSize;
4283 + __u16 MaxMpxCount;
4284 + __u16 VcNumber;
4285 + __u32 SessionKey;
4286 + __u16 CaseInsensitivePasswordLength; /* ASCII password length */
4287 + __u16 CaseSensitivePasswordLength; /* Unicode password length */
4288 + __u32 Reserved; /* see below */
4289 + __u32 Capabilities;
4290 + __u16 ByteCount;
4291 + unsigned char CaseInsensitivePassword[1]; /* followed by: */
4292 + /* unsigned char * CaseSensitivePassword; */
4293 + /* STRING AccountName */
4294 + /* STRING PrimaryDomain */
4295 + /* STRING NativeOS */
4296 + /* STRING NativeLanMan */
4297 + } req_no_secext; /* NTLM request format (without extended security */
4298 +
4299 + struct { /* default (NTLM) response format */
4300 + struct smb_hdr hdr; /* wct = 4 */
4301 + __u8 AndXCommand;
4302 + __u8 AndXReserved;
4303 + __u16 AndXOffset;
4304 + __u16 Action; /* see below */
4305 + __u16 SecurityBlobLength;
4306 + __u16 ByteCount;
4307 + unsigned char SecurityBlob[1]; /* followed by */
4308 +/* unsigned char * NativeOS; */
4309 +/* unsigned char * NativeLanMan; */
4310 +/* unsigned char * PrimaryDomain; */
4311 + } resp; /* NTLM response format (with or without extended security */
4312 +
4313 + struct { /* request format */
4314 + struct smb_hdr hdr; /* wct = 10 */
4315 + __u8 AndXCommand;
4316 + __u8 AndXReserved;
4317 + __u16 AndXOffset;
4318 + __u16 MaxBufferSize;
4319 + __u16 MaxMpxCount;
4320 + __u16 VcNumber;
4321 + __u32 SessionKey;
4322 + __u16 PassswordLength;
4323 + __u32 Reserved;
4324 + __u16 ByteCount;
4325 + unsigned char AccountPassword[1]; /* followed by */
4326 + /* STRING AccountName */
4327 + /* STRING PrimaryDomain */
4328 + /* STRING NativeOS */
4329 + /* STRING NativeLanMan */
4330 + } old_req; /* pre-NTLM (LANMAN2.1) request format */
4331 +
4332 + struct { /* default (NTLM) response format */
4333 + struct smb_hdr hdr; /* wct = 3 */
4334 + __u8 AndXCommand;
4335 + __u8 AndXReserved;
4336 + __u16 AndXOffset;
4337 + __u16 Action; /* see below */
4338 + __u16 ByteCount;
4339 + unsigned char NativeOS[1]; /* followed by */
4340 +/* unsigned char * NativeLanMan; */
4341 +/* unsigned char * PrimaryDomain; */
4342 + } old_resp; /* pre-NTLM (LANMAN2.1) response format */
4343 +} SESSION_SETUP_ANDX;
4344 +
4345 +#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
4346 +
4347 +/* Capabilities bits (for NTLM SessSetup request) */
4348 +#define CAP_UNICODE 0x00000004
4349 +#define CAP_LARGE_FILES 0x00000008
4350 +#define CAP_NT_SMBS 0x00000010
4351 +#define CAP_STATUS32 0x00000040
4352 +#define CAP_LEVEL_II_OPLOCKS 0x00000080
4353 +#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
4354 +#define CAP_BULK_TRANSFER 0x20000000
4355 +#define CAP_EXTENDED_SECURITY 0x80000000
4356 +
4357 +/* Action bits */
4358 +#define GUEST_LOGIN 1
4359 +
4360 +typedef struct smb_com_tconx_req {
4361 + struct smb_hdr hdr; /* wct = 4 */
4362 + __u8 AndXCommand;
4363 + __u8 AndXReserved;
4364 + __u16 AndXOffset;
4365 + __u16 Flags; /* see below */
4366 + __u16 PasswordLength;
4367 + __u16 ByteCount;
4368 + unsigned char Password[1]; /* followed by */
4369 +/* STRING Path *//* \\server\share name */
4370 + /* STRING Service */
4371 +} TCONX_REQ;
4372 +
4373 +typedef struct smb_com_tconx_rsp {
4374 + struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
4375 + __u8 AndXCommand;
4376 + __u8 AndXReserved;
4377 + __u16 AndXOffset;
4378 + __u16 OptionalSupport; /* see below */
4379 + __u16 ByteCount;
4380 + unsigned char Service[1]; /* always ASCII, not Unicode */
4381 + /* STRING NativeFileSystem */
4382 +} TCONX_RSP;
4383 +
4384 +/* tree connect Flags */
4385 +#define DISCONNECT_TID 0x0001
4386 +#define TCON_EXTENDED_SECINFO 0x0008
4387 +/* OptionalSupport bits */
4388 +#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
4389 +#define SMB_SHARE_IS_IN_DFS 0x0002
4390 +
4391 +typedef struct smb_com_logoff_andx_req {
4392 +
4393 + struct smb_hdr hdr; /* wct = 2 */
4394 + __u8 AndXCommand;
4395 + __u8 AndXReserved;
4396 + __u16 AndXOffset;
4397 + __u16 ByteCount;
4398 +} LOGOFF_ANDX_REQ;
4399 +
4400 +typedef struct smb_com_logoff_andx_rsp {
4401 + struct smb_hdr hdr; /* wct = 2 */
4402 + __u8 AndXCommand;
4403 + __u8 AndXReserved;
4404 + __u16 AndXOffset;
4405 + __u16 ByteCount;
4406 +} LOGOFF_ANDX_RSP;
4407 +
4408 +typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
4409 + struct {
4410 + struct smb_hdr hdr; /* wct = 0 */
4411 + __u16 ByteCount; /* bcc = 0 */
4412 + } req;
4413 + struct {
4414 + struct smb_hdr hdr; /* wct = 0 */
4415 + __u16 ByteCount; /* bcc = 0 */
4416 + } resp;
4417 +} TREE_DISCONNECT;
4418 +
4419 +typedef struct smb_com_close_req {
4420 + struct smb_hdr hdr; /* wct = 3 */
4421 + __u16 FileID;
4422 + __u32 LastWriteTime; /* should be zero */
4423 + __u16 ByteCount; /* 0 */
4424 +} CLOSE_REQ;
4425 +
4426 +typedef struct smb_com_close_rsp {
4427 + struct smb_hdr hdr; /* wct = 0 */
4428 + __u16 ByteCount; /* bct = 0 */
4429 +} CLOSE_RSP;
4430 +
4431 +typedef struct smb_com_findclose_req {
4432 + struct smb_hdr hdr; /* wct = 1 */
4433 + __u16 FileID;
4434 + __u16 ByteCount; /* 0 */
4435 +} FINDCLOSE_REQ;
4436 +
4437 +/* OpenFlags */
4438 +#define REQ_OPLOCK 0x00000002
4439 +#define REQ_BATCHOPLOCK 0x00000004
4440 +#define REQ_OPENDIRONLY 0x00000008
4441 +
4442 +typedef struct smb_com_open_req { /* also handles create */
4443 + struct smb_hdr hdr; /* wct = 24 */
4444 + __u8 AndXCommand;
4445 + __u8 AndXReserved;
4446 + __u16 AndXOffset;
4447 + __u8 Reserved; /* Must Be Zero */
4448 + __u16 NameLength;
4449 + __u32 OpenFlags;
4450 + __u32 RootDirectoryFid;
4451 + __u32 DesiredAccess;
4452 + __u64 AllocationSize;
4453 + __u32 FileAttributes;
4454 + __u32 ShareAccess;
4455 + __u32 CreateDisposition;
4456 + __u32 CreateOptions;
4457 + __u32 ImpersonationLevel;
4458 + __u8 SecurityFlags;
4459 + __u16 ByteCount;
4460 + char fileName[1];
4461 +} OPEN_REQ;
4462 +
4463 +/* open response: oplock levels */
4464 +#define OPLOCK_NONE 0
4465 +#define OPLOCK_EXCLUSIVE 1
4466 +#define OPLOCK_BATCH 2
4467 +#define OPLOCK_READ 3 /* level 2 oplock */
4468 +
4469 +/* open response for CreateAction shifted left */
4470 +#define CIFS_CREATE_ACTION 0x20000 /* file created */
4471 +
4472 +typedef struct smb_com_open_rsp {
4473 + struct smb_hdr hdr; /* wct = 34 BB */
4474 + __u8 AndXCommand;
4475 + __u8 AndXReserved;
4476 + __u16 AndXOffset;
4477 + __u8 OplockLevel;
4478 + __u16 Fid;
4479 + __u32 CreateAction;
4480 + __u64 CreationTime;
4481 + __u64 LastAccessTime;
4482 + __u64 LastWriteTime;
4483 + __u64 ChangeTime;
4484 + __u32 FileAttributes;
4485 + __u64 AllocationSize;
4486 + __u64 EndOfFile;
4487 + __u16 FileType;
4488 + __u16 DeviceState;
4489 + __u8 DirectoryFlag;
4490 + __u16 ByteCount; /* bct = 0 */
4491 +} OPEN_RSP;
4492 +
4493 +typedef struct smb_com_write_req {
4494 + struct smb_hdr hdr; /* wct = 14 */
4495 + __u8 AndXCommand;
4496 + __u8 AndXReserved;
4497 + __u16 AndXOffset;
4498 + __u16 Fid;
4499 + __u32 OffsetLow;
4500 + __u32 Reserved;
4501 + __u16 WriteMode;
4502 + __u16 Remaining;
4503 + __u16 DataLengthHigh;
4504 + __u16 DataLengthLow;
4505 + __u16 DataOffset;
4506 + __u32 OffsetHigh;
4507 + __u16 ByteCount;
4508 + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
4509 + char Data[1];
4510 +} WRITE_REQ;
4511 +
4512 +typedef struct smb_com_write_rsp {
4513 + struct smb_hdr hdr; /* wct = 6 */
4514 + __u8 AndXCommand;
4515 + __u8 AndXReserved;
4516 + __u16 AndXOffset;
4517 + __u16 Count;
4518 + __u16 Remaining;
4519 + __u32 Reserved;
4520 + __u16 ByteCount;
4521 +} WRITE_RSP;
4522 +
4523 +typedef struct smb_com_read_req {
4524 + struct smb_hdr hdr; /* wct = 12 */
4525 + __u8 AndXCommand;
4526 + __u8 AndXReserved;
4527 + __u16 AndXOffset;
4528 + __u16 Fid;
4529 + __u32 OffsetLow;
4530 + __u16 MaxCount;
4531 + __u16 MinCount; /* obsolete */
4532 + __u32 MaxCountHigh;
4533 + __u16 Remaining;
4534 + __u32 OffsetHigh;
4535 + __u16 ByteCount;
4536 +} READ_REQ;
4537 +
4538 +typedef struct smb_com_read_rsp {
4539 + struct smb_hdr hdr; /* wct = 12 */
4540 + __u8 AndXCommand;
4541 + __u8 AndXReserved;
4542 + __u16 AndXOffset;
4543 + __u16 Remaining;
4544 + __u16 DataCompactionMode;
4545 + __u16 Reserved;
4546 + __u16 DataLength;
4547 + __u16 DataOffset;
4548 + __u16 DataLengthHigh;
4549 + __u64 Reserved2;
4550 + __u16 ByteCount;
4551 + __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
4552 + char Data[1];
4553 +} READ_RSP;
4554 +
4555 +typedef struct locking_andx_range {
4556 + __u16 Pid;
4557 + __u16 Pad;
4558 + __u32 OffsetHigh;
4559 + __u32 OffsetLow;
4560 + __u32 LengthHigh;
4561 + __u32 LengthLow;
4562 +} LOCKING_ANDX_RANGE;
4563 +
4564 +#define LOCKING_ANDX_SHARED_LOCK 0x01
4565 +#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
4566 +#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
4567 +#define LOCKING_ANDX_CANCEL_LOCK 0x08
4568 +#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
4569 +
4570 +typedef struct smb_com_lock_req {
4571 + struct smb_hdr hdr; /* wct = 8 */
4572 + __u8 AndXCommand;
4573 + __u8 AndXReserved;
4574 + __u16 AndXOffset;
4575 + __u16 Fid;
4576 + __u8 LockType;
4577 + __u8 OplockLevel;
4578 + __u32 Timeout;
4579 + __u16 NumberOfUnlocks;
4580 + __u16 NumberOfLocks;
4581 + __u16 ByteCount;
4582 + LOCKING_ANDX_RANGE Locks[1];
4583 +} LOCK_REQ;
4584 +
4585 +typedef struct smb_com_lock_rsp {
4586 + struct smb_hdr hdr; /* wct = 2 */
4587 + __u8 AndXCommand;
4588 + __u8 AndXReserved;
4589 + __u16 AndXOffset;
4590 + __u16 ByteCount;
4591 +} LOCK_RSP;
4592 +
4593 +typedef struct smb_com_rename_req {
4594 + struct smb_hdr hdr; /* wct = 1 */
4595 + __u16 SearchAttributes; /* target file attributes */
4596 + __u16 ByteCount;
4597 + __u8 BufferFormat; /* 4 = ASCII or Unicode */
4598 + unsigned char OldFileName[1];
4599 + /* followed by __u8 BufferFormat2 */
4600 + /* followed by NewFileName */
4601 +} RENAME_REQ;
4602 +
4603 + /* copy request flags */
4604 +#define COPY_MUST_BE_FILE 0x0001
4605 +#define COPY_MUST_BE_DIR 0x0002
4606 +#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
4607 +#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
4608 +#define COPY_VERIFY_WRITES 0x0010
4609 +#define COPY_TREE 0x0020
4610 +
4611 +typedef struct smb_com_copy_req {
4612 + struct smb_hdr hdr; /* wct = 3 */
4613 + __u16 Tid2;
4614 + __u16 OpenFunction;
4615 + __u16 Flags;
4616 + __u16 ByteCount;
4617 + __u8 BufferFormat; /* 4 = ASCII or Unicode */
4618 + unsigned char OldFileName[1];
4619 + /* followed by __u8 BufferFormat2 */
4620 + /* followed by NewFileName string */
4621 +} COPY_REQ;
4622 +
4623 +typedef struct smb_com_copy_rsp {
4624 + struct smb_hdr hdr; /* wct = 1 */
4625 + __u16 CopyCount; /* number of files copied */
4626 + __u16 ByteCount; /* may be zero */
4627 + __u8 BufferFormat; /* 0x04 - only present if errored file follows */
4628 + unsigned char ErrorFileName[1]; /* only present if error in copy */
4629 +} COPY_RSP;
4630 +
4631 +#define CREATE_HARD_LINK 0x103
4632 +#define MOVEFILE_COPY_ALLOWED 0x0002
4633 +#define MOVEFILE_REPLACE_EXISTING 0x0001
4634 +
4635 +typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
4636 + struct smb_hdr hdr; /* wct = 4 */
4637 + __u16 SearchAttributes; /* target file attributes */
4638 + __u16 Flags; /* spec says Information Level */
4639 + __u32 ClusterCount;
4640 + __u16 ByteCount;
4641 + __u8 BufferFormat; /* 4 = ASCII or Unicode */
4642 + unsigned char OldFileName[1];
4643 + /* followed by __u8 BufferFormat2 */
4644 + /* followed by NewFileName */
4645 +} NT_RENAME_REQ;
4646 +
4647 +typedef struct smb_com_rename_rsp {
4648 + struct smb_hdr hdr; /* wct = 0 */
4649 + __u16 ByteCount; /* bct = 0 */
4650 +} RENAME_RSP;
4651 +
4652 +typedef struct smb_com_delete_file_req {
4653 + struct smb_hdr hdr; /* wct = 1 */
4654 + __u16 SearchAttributes;
4655 + __u16 ByteCount;
4656 + __u8 BufferFormat; /* 4 = ASCII */
4657 + unsigned char fileName[1];
4658 +} DELETE_FILE_REQ;
4659 +
4660 +typedef struct smb_com_delete_file_rsp {
4661 + struct smb_hdr hdr; /* wct = 0 */
4662 + __u16 ByteCount; /* bct = 0 */
4663 +} DELETE_FILE_RSP;
4664 +
4665 +typedef struct smb_com_delete_directory_req {
4666 + struct smb_hdr hdr; /* wct = 0 */
4667 + __u16 ByteCount;
4668 + __u8 BufferFormat; /* 4 = ASCII */
4669 + unsigned char DirName[1];
4670 +} DELETE_DIRECTORY_REQ;
4671 +
4672 +typedef struct smb_com_delete_directory_rsp {
4673 + struct smb_hdr hdr; /* wct = 0 */
4674 + __u16 ByteCount; /* bct = 0 */
4675 +} DELETE_DIRECTORY_RSP;
4676 +
4677 +typedef struct smb_com_create_directory_req {
4678 + struct smb_hdr hdr; /* wct = 0 */
4679 + __u16 ByteCount;
4680 + __u8 BufferFormat; /* 4 = ASCII */
4681 + unsigned char DirName[1];
4682 +} CREATE_DIRECTORY_REQ;
4683 +
4684 +typedef struct smb_com_create_directory_rsp {
4685 + struct smb_hdr hdr; /* wct = 0 */
4686 + __u16 ByteCount; /* bct = 0 */
4687 +} CREATE_DIRECTORY_RSP;
4688 +
4689 +/***************************************************/
4690 +/* NT Transact structure defintions follow */
4691 +/* Currently only ioctl and notify are implemented */
4692 +/***************************************************/
4693 +typedef struct smb_com_transaction_ioctl_req {
4694 + struct smb_hdr hdr; /* wct = 23 */
4695 + __u8 MaxSetupCount;
4696 + __u16 Reserved;
4697 + __u32 TotalParameterCount;
4698 + __u32 TotalDataCount;
4699 + __u32 MaxParameterCount;
4700 + __u32 MaxDataCount;
4701 + __u32 ParameterCount;
4702 + __u32 ParameterOffset;
4703 + __u32 DataCount;
4704 + __u32 DataOffset;
4705 + __u8 SetupCount; /* four setup words follow subcommand */
4706 + /* SNIA spec incorrectly included spurious pad here */
4707 + __u16 SubCommand;/* 2 = IOCTL/FSCTL */
4708 + __u32 FunctionCode;
4709 + __u16 Fid;
4710 + __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
4711 + __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
4712 + __u16 ByteCount;
4713 + __u8 Pad[3];
4714 + __u8 Data[1];
4715 +} TRANSACT_IOCTL_REQ;
4716 +
4717 +typedef struct smb_com_transaction_ioctl_rsp {
4718 + struct smb_hdr hdr; /* wct = 19 */
4719 + __u8 Reserved[3];
4720 + __u32 TotalParameterCount;
4721 + __u32 TotalDataCount;
4722 + __u32 ParameterCount;
4723 + __u32 ParameterOffset;
4724 + __u32 ParameterDisplacement;
4725 + __u32 DataCount;
4726 + __u32 DataOffset;
4727 + __u32 DataDisplacement;
4728 + __u8 SetupCount; /* 1 */
4729 + __u16 ReturnedDataLen;
4730 + __u16 ByteCount;
4731 + __u8 Pad[3];
4732 +} TRANSACT_IOCTL_RSP;
4733 +
4734 +typedef struct smb_com_transaction_change_notify_req {
4735 + struct smb_hdr hdr; /* wct = 23 */
4736 + __u8 MaxSetupCount;
4737 + __u16 Reserved;
4738 + __u32 TotalParameterCount;
4739 + __u32 TotalDataCount;
4740 + __u32 MaxParameterCount;
4741 + __u32 MaxDataCount;
4742 + __u32 ParameterCount;
4743 + __u32 ParameterOffset;
4744 + __u32 DataCount;
4745 + __u32 DataOffset;
4746 + __u8 SetupCount; /* four setup words follow subcommand */
4747 + /* SNIA spec incorrectly included spurious pad here */
4748 + __u16 SubCommand;/* 4 = Change Notify */
4749 + __u32 CompletionFilter; /* operation to monitor */
4750 + __u16 Fid;
4751 + __u8 WatchTree; /* 1 = Monitor subdirectories */
4752 + __u8 Reserved2;
4753 + __u16 ByteCount;
4754 +/* __u8 Pad[3];*/
4755 +/* __u8 Data[1];*/
4756 +} TRANSACT_CHANGE_NOTIFY_REQ;
4757 +
4758 +typedef struct smb_com_transaction_change_notify_rsp {
4759 + struct smb_hdr hdr; /* wct = 18 */
4760 + __u8 Reserved[3];
4761 + __u32 TotalParameterCount;
4762 + __u32 TotalDataCount;
4763 + __u32 ParameterCount;
4764 + __u32 ParameterOffset;
4765 + __u32 ParameterDisplacement;
4766 + __u32 DataCount;
4767 + __u32 DataOffset;
4768 + __u32 DataDisplacement;
4769 + __u8 SetupCount; /* 0 */
4770 + __u16 ByteCount;
4771 + /* __u8 Pad[3]; */
4772 +} TRANSACT_CHANGE_NOTIFY_RSP;
4773 +/* Completion Filter flags for Notify */
4774 +#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
4775 +#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
4776 +#define FILE_NOTIFY_CHANGE_NAME 0x00000003
4777 +#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
4778 +#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
4779 +#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
4780 +#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
4781 +#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
4782 +#define FILE_NOTIFY_CHANGE_EA 0x00000080
4783 +#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
4784 +#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
4785 +#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
4786 +#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
4787 +
4788 +#define FILE_ACTION_ADDED 0x00000001
4789 +#define FILE_ACTION_REMOVED 0x00000002
4790 +#define FILE_ACTION_MODIFIED 0x00000003
4791 +#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
4792 +#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
4793 +#define FILE_ACTION_ADDED_STREAM 0x00000006
4794 +#define FILE_ACTION_REMOVED_STREAM 0x00000007
4795 +#define FILE_ACTION_MODIFIED_STREAM 0x00000008
4796 +
4797 +/* response contains array of the following structures */
4798 +struct file_notify_information {
4799 + __u32 NextEntryOffset;
4800 + __u32 Action;
4801 + __u32 FileNameLength;
4802 + __u8 FileName[1];
4803 +};
4804 +
4805 +struct reparse_data {
4806 + __u32 ReparseTag;
4807 + __u16 ReparseDataLength;
4808 + __u16 Reserved;
4809 + __u16 AltNameOffset;
4810 + __u16 AltNameLen;
4811 + __u16 TargetNameOffset;
4812 + __u16 TargetNameLen;
4813 + char LinkNamesBuf[1];
4814 +};
4815 +
4816 +struct cifs_quota_data {
4817 + __u32 rsrvd1; /* 0 */
4818 + __u32 sid_size;
4819 + __u64 rsrvd2; /* 0 */
4820 + __u64 space_used;
4821 + __u64 soft_limit;
4822 + __u64 hard_limit;
4823 + char sid[1]; /* variable size? */
4824 +};
4825 +
4826 +/* quota sub commands */
4827 +#define QUOTA_LIST_CONTINUE 0
4828 +#define QUOTA_LIST_START 0x100
4829 +#define QUOTA_FOR_SID 0x101
4830 +
4831 +typedef union smb_com_transaction2 {
4832 + struct {
4833 + struct smb_hdr hdr; /* wct = 14+ */
4834 + __u16 TotalParameterCount;
4835 + __u16 TotalDataCount;
4836 + __u16 MaxParameterCount;
4837 + __u16 MaxDataCount;
4838 + __u8 MaxSetupCount;
4839 + __u8 Reserved;
4840 + __u16 Flags;
4841 + __u32 Timeout;
4842 + __u16 Reserved2;
4843 + __u16 ParameterCount;
4844 + __u16 ParameterOffset;
4845 + __u16 DataCount;
4846 + __u16 DataOffset;
4847 + __u8 SetupCount;
4848 + __u8 Reserved3;
4849 + __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */
4850 + __u16 ByteCount; /* careful - setupcount is not always one */
4851 + } req;
4852 + struct {
4853 + struct smb_hdr hdr; /* wct = 0 */
4854 + __u16 TotalParameterCount;
4855 + __u16 TotalDataCount;
4856 + __u16 Reserved;
4857 + __u16 ParameterCount;
4858 + __u16 ParamterOffset;
4859 + __u16 ParameterDisplacement;
4860 + __u16 DataCount;
4861 + __u16 DataOffset;
4862 + __u16 DataDisplacement;
4863 + __u8 SetupCount;
4864 + __u8 Reserved1; /* should be zero setup words following */
4865 + __u16 ByteCount;
4866 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4867 + /* data area follows */
4868 + } resp;
4869 +} TRANSACTION2;
4870 +
4871 +/* PathInfo/FileInfo infolevels */
4872 +#define SMB_INFO_STANDARD 1
4873 +#define SMB_INFO_QUERY_EAS_FROM_LIST 3
4874 +#define SMB_INFO_QUERY_ALL_EAS 4
4875 +#define SMB_INFO_IS_NAME_VALID 6
4876 +#define SMB_QUERY_FILE_BASIC_INFO 0x101
4877 +#define SMB_QUERY_FILE_STANDARD_INFO 0x102
4878 +#define SMB_QUERY_FILE_EA_INFO 0x103
4879 +#define SMB_QUERY_FILE_NAME_INFO 0x104
4880 +#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
4881 +#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
4882 +#define SMB_QUERY_FILE_ALL_INFO 0x107
4883 +#define SMB_QUERY_ALT_NAME_INFO 0x108
4884 +#define SMB_QUERY_FILE_STREAM_INFO 0x109
4885 +#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
4886 +#define SMB_QUERY_FILE_UNIX_BASIC 0x200
4887 +#define SMB_QUERY_FILE_UNIX_LINK 0x201
4888 +
4889 +#define SMB_SET_FILE_BASIC_INFO 0x101
4890 +#define SMB_SET_FILE_DISPOSITION_INFO 0x102
4891 +#define SMB_SET_FILE_ALLOCATION_INFO 0x103
4892 +#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
4893 +#define SMB_SET_FILE_UNIX_BASIC 0x200
4894 +#define SMB_SET_FILE_UNIX_LINK 0x201
4895 +#define SMB_SET_FILE_UNIX_HLINK 0x203
4896 +#define SMB_SET_FILE_BASIC_INFO2 0x3ec
4897 +#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
4898 +#define SMB_FILE_ALL_INFO2 0x3fa
4899 +#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
4900 +#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
4901 +#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
4902 +#define SMB_FILE_QUOTA_INFO 0x408
4903 +#define SMB_FILE_REPARSEPOINT_INFO 0x409
4904 +#define SMB_FILE_MAXIMUM_INFO 0x40d
4905 +
4906 +/* Find File infolevels */
4907 +#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
4908 +#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
4909 +#define SMB_FIND_FILE_NAMES_INFO 0x103
4910 +#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
4911 +#define SMB_FIND_FILE_UNIX 0x202
4912 +
4913 +typedef struct smb_com_transaction2_qpi_req {
4914 + struct smb_hdr hdr; /* wct = 14+ */
4915 + __u16 TotalParameterCount;
4916 + __u16 TotalDataCount;
4917 + __u16 MaxParameterCount;
4918 + __u16 MaxDataCount;
4919 + __u8 MaxSetupCount;
4920 + __u8 Reserved;
4921 + __u16 Flags;
4922 + __u32 Timeout;
4923 + __u16 Reserved2;
4924 + __u16 ParameterCount;
4925 + __u16 ParameterOffset;
4926 + __u16 DataCount;
4927 + __u16 DataOffset;
4928 + __u8 SetupCount;
4929 + __u8 Reserved3;
4930 + __u16 SubCommand; /* one setup word */
4931 + __u16 ByteCount;
4932 + __u8 Pad;
4933 + __u16 InformationLevel;
4934 + __u32 Reserved4;
4935 + char FileName[1];
4936 +} TRANSACTION2_QPI_REQ;
4937 +
4938 +typedef struct smb_com_transaction2_qpi_rsp {
4939 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
4940 + __u16 TotalParameterCount;
4941 + __u16 TotalDataCount;
4942 + __u16 Reserved;
4943 + __u16 ParameterCount;
4944 + __u16 ParameterOffset;
4945 + __u16 ParameterDisplacement;
4946 + __u16 DataCount;
4947 + __u16 DataOffset;
4948 + __u16 DataDisplacement;
4949 + __u8 SetupCount;
4950 + __u8 Reserved1; /* should be zero setup words following */
4951 + __u16 ByteCount;
4952 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4953 +} TRANSACTION2_QPI_RSP;
4954 +
4955 +typedef struct smb_com_transaction2_spi_req {
4956 + struct smb_hdr hdr; /* wct = 15 */
4957 + __u16 TotalParameterCount;
4958 + __u16 TotalDataCount;
4959 + __u16 MaxParameterCount;
4960 + __u16 MaxDataCount;
4961 + __u8 MaxSetupCount;
4962 + __u8 Reserved;
4963 + __u16 Flags;
4964 + __u32 Timeout;
4965 + __u16 Reserved2;
4966 + __u16 ParameterCount;
4967 + __u16 ParameterOffset;
4968 + __u16 DataCount;
4969 + __u16 DataOffset;
4970 + __u8 SetupCount;
4971 + __u8 Reserved3;
4972 + __u16 SubCommand; /* one setup word */
4973 + __u16 ByteCount;
4974 + __u8 Pad;
4975 + __u16 Pad1;
4976 + __u16 InformationLevel;
4977 + __u32 Reserved4;
4978 + char FileName[1];
4979 +} TRANSACTION2_SPI_REQ;
4980 +
4981 +typedef struct smb_com_transaction2_spi_rsp {
4982 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
4983 + __u16 TotalParameterCount;
4984 + __u16 TotalDataCount;
4985 + __u16 Reserved;
4986 + __u16 ParameterCount;
4987 + __u16 ParameterOffset;
4988 + __u16 ParameterDisplacement;
4989 + __u16 DataCount;
4990 + __u16 DataOffset;
4991 + __u16 DataDisplacement;
4992 + __u8 SetupCount;
4993 + __u8 Reserved1; /* should be zero setup words following */
4994 + __u16 ByteCount;
4995 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
4996 +} TRANSACTION2_SPI_RSP;
4997 +
4998 +struct set_file_rename {
4999 + __u32 overwrite; /* 1 = overwrite dest */
5000 + __u32 root_fid; /* zero */
5001 + __u32 target_name_len;
5002 + char target_name[0]; /* Must be unicode */
5003 +};
5004 +
5005 +struct smb_com_transaction2_sfi_req {
5006 + struct smb_hdr hdr; /* wct = 15 */
5007 + __u16 TotalParameterCount;
5008 + __u16 TotalDataCount;
5009 + __u16 MaxParameterCount;
5010 + __u16 MaxDataCount;
5011 + __u8 MaxSetupCount;
5012 + __u8 Reserved;
5013 + __u16 Flags;
5014 + __u32 Timeout;
5015 + __u16 Reserved2;
5016 + __u16 ParameterCount;
5017 + __u16 ParameterOffset;
5018 + __u16 DataCount;
5019 + __u16 DataOffset;
5020 + __u8 SetupCount;
5021 + __u8 Reserved3;
5022 + __u16 SubCommand; /* one setup word */
5023 + __u16 ByteCount;
5024 + __u8 Pad;
5025 + __u16 Pad1;
5026 + __u16 Fid;
5027 + __u16 InformationLevel;
5028 + __u16 Reserved4;
5029 +};
5030 +
5031 +struct smb_com_transaction2_sfi_rsp {
5032 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
5033 + __u16 TotalParameterCount;
5034 + __u16 TotalDataCount;
5035 + __u16 Reserved;
5036 + __u16 ParameterCount;
5037 + __u16 ParameterOffset;
5038 + __u16 ParameterDisplacement;
5039 + __u16 DataCount;
5040 + __u16 DataOffset;
5041 + __u16 DataDisplacement;
5042 + __u8 SetupCount;
5043 + __u8 Reserved1; /* should be zero setup words following */
5044 + __u16 ByteCount;
5045 + __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
5046 +};
5047 +
5048 +
5049 +/*
5050 + * Flags on T2 FINDFIRST and FINDNEXT
5051 + */
5052 +#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
5053 +#define CIFS_SEARCH_CLOSE_AT_END 0x0002
5054 +#define CIFS_SEARCH_RETURN_RESUME 0x0004
5055 +#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
5056 +#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
5057 +
5058 +/*
5059 + * Size of the resume key on FINDFIRST and FINDNEXT calls
5060 + */
5061 +#define CIFS_SMB_RESUME_KEY_SIZE 4
5062 +
5063 +typedef struct smb_com_transaction2_ffirst_req {
5064 + struct smb_hdr hdr; /* wct = 15 */
5065 + __u16 TotalParameterCount;
5066 + __u16 TotalDataCount;
5067 + __u16 MaxParameterCount;
5068 + __u16 MaxDataCount;
5069 + __u8 MaxSetupCount;
5070 + __u8 Reserved;
5071 + __u16 Flags;
5072 + __u32 Timeout;
5073 + __u16 Reserved2;
5074 + __u16 ParameterCount;
5075 + __u16 ParameterOffset;
5076 + __u16 DataCount;
5077 + __u16 DataOffset;
5078 + __u8 SetupCount; /* one */
5079 + __u8 Reserved3;
5080 + __u16 SubCommand; /* TRANS2_FIND_FIRST */
5081 + __u16 ByteCount;
5082 + __u8 Pad;
5083 + __u16 SearchAttributes;
5084 + __u16 SearchCount;
5085 + __u16 SearchFlags;
5086 + __u16 InformationLevel;
5087 + __u32 SearchStorageType;
5088 + char FileName[1];
5089 +} TRANSACTION2_FFIRST_REQ;
5090 +
5091 +typedef struct smb_com_transaction2_ffirst_rsp {
5092 + struct smb_hdr hdr; /* wct = 10 */
5093 + __u16 TotalParameterCount;
5094 + __u16 TotalDataCount;
5095 + __u16 Reserved;
5096 + __u16 ParameterCount;
5097 + __u16 ParameterOffset;
5098 + __u16 ParameterDisplacement;
5099 + __u16 DataCount;
5100 + __u16 DataOffset;
5101 + __u16 DataDisplacement;
5102 + __u8 SetupCount;
5103 + __u8 Reserved1; /* should be zero setup words following */
5104 + __u16 ByteCount;
5105 +} TRANSACTION2_FFIRST_RSP;
5106 +
5107 +typedef struct smb_com_transaction2_ffirst_rsp_parms {
5108 + __u16 SearchHandle;
5109 + __u16 SearchCount;
5110 + __u16 EndofSearch;
5111 + __u16 EAErrorOffset;
5112 + __u16 LastNameOffset;
5113 +} T2_FFIRST_RSP_PARMS;
5114 +
5115 +typedef struct smb_com_transaction2_fnext_req {
5116 + struct smb_hdr hdr; /* wct = 15 */
5117 + __u16 TotalParameterCount;
5118 + __u16 TotalDataCount;
5119 + __u16 MaxParameterCount;
5120 + __u16 MaxDataCount;
5121 + __u8 MaxSetupCount;
5122 + __u8 Reserved;
5123 + __u16 Flags;
5124 + __u32 Timeout;
5125 + __u16 Reserved2;
5126 + __u16 ParameterCount;
5127 + __u16 ParameterOffset;
5128 + __u16 DataCount;
5129 + __u16 DataOffset;
5130 + __u8 SetupCount; /* one */
5131 + __u8 Reserved3;
5132 + __u16 SubCommand; /* TRANS2_FIND_NEXT */
5133 + __u16 ByteCount;
5134 + __u8 Pad;
5135 + __u16 SearchHandle;
5136 + __u16 SearchCount;
5137 + __u16 InformationLevel;
5138 + __u32 ResumeKey;
5139 + __u16 SearchFlags;
5140 + char ResumeFileName[1];
5141 +} TRANSACTION2_FNEXT_REQ;
5142 +
5143 +typedef struct smb_com_transaction2_fnext_rsp {
5144 + struct smb_hdr hdr; /* wct = 10 */
5145 + __u16 TotalParameterCount;
5146 + __u16 TotalDataCount;
5147 + __u16 Reserved;
5148 + __u16 ParameterCount;
5149 + __u16 ParameterOffset;
5150 + __u16 ParameterDisplacement;
5151 + __u16 DataCount;
5152 + __u16 DataOffset;
5153 + __u16 DataDisplacement;
5154 + __u8 SetupCount;
5155 + __u8 Reserved1; /* should be zero setup words following */
5156 + __u16 ByteCount;
5157 +} TRANSACTION2_FNEXT_RSP;
5158 +
5159 +typedef struct smb_com_transaction2_fnext_rsp_parms {
5160 + __u16 SearchCount;
5161 + __u16 EndofSearch;
5162 + __u16 EAErrorOffset;
5163 + __u16 LastNameOffset;
5164 +} T2_FNEXT_RSP_PARMS;
5165 +
5166 +/* QFSInfo Levels */
5167 +#define SMB_INFO_ALLOCATION 1
5168 +#define SMB_INFO_VOLUME 2
5169 +#define SMB_QUERY_FS_VOLUME_INFO 0x102
5170 +#define SMB_QUERY_FS_SIZE_INFO 0x103
5171 +#define SMB_QUERY_FS_DEVICE_INFO 0x104
5172 +#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
5173 +#define SMB_QUERY_CIFS_UNIX_INFO 0x200
5174 +#define SMB_QUERY_LABEL_INFO 0x3ea
5175 +#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
5176 +
5177 +typedef struct smb_com_transaction2_qfsi_req {
5178 + struct smb_hdr hdr; /* wct = 14+ */
5179 + __u16 TotalParameterCount;
5180 + __u16 TotalDataCount;
5181 + __u16 MaxParameterCount;
5182 + __u16 MaxDataCount;
5183 + __u8 MaxSetupCount;
5184 + __u8 Reserved;
5185 + __u16 Flags;
5186 + __u32 Timeout;
5187 + __u16 Reserved2;
5188 + __u16 ParameterCount;
5189 + __u16 ParameterOffset;
5190 + __u16 DataCount;
5191 + __u16 DataOffset;
5192 + __u8 SetupCount;
5193 + __u8 Reserved3;
5194 + __u16 SubCommand; /* one setup word */
5195 + __u16 ByteCount;
5196 + __u8 Pad;
5197 + __u16 InformationLevel;
5198 +} TRANSACTION2_QFSI_REQ;
5199 +
5200 +typedef struct smb_com_transaction_qfsi_rsp {
5201 + struct smb_hdr hdr; /* wct = 10 + SetupCount */
5202 + __u16 TotalParameterCount;
5203 + __u16 TotalDataCount;
5204 + __u16 Reserved;
5205 + __u16 ParameterCount;
5206 + __u16 ParameterOffset;
5207 + __u16 ParameterDisplacement;
5208 + __u16 DataCount;
5209 + __u16 DataOffset;
5210 + __u16 DataDisplacement;
5211 + __u8 SetupCount;
5212 + __u8 Reserved1; /* should be zero setup words following */
5213 + __u16 ByteCount;
5214 + __u8 Pad; /* may be three bytes *//* followed by data area */
5215 +} TRANSACTION2_QFSI_RSP;
5216 +
5217 +typedef struct smb_com_transaction2_get_dfs_refer_req {
5218 + struct smb_hdr hdr; /* wct = 15 */
5219 + __u16 TotalParameterCount;
5220 + __u16 TotalDataCount;
5221 + __u16 MaxParameterCount;
5222 + __u16 MaxDataCount;
5223 + __u8 MaxSetupCount;
5224 + __u8 Reserved;
5225 + __u16 Flags;
5226 + __u32 Timeout;
5227 + __u16 Reserved2;
5228 + __u16 ParameterCount;
5229 + __u16 ParameterOffset;
5230 + __u16 DataCount;
5231 + __u16 DataOffset;
5232 + __u8 SetupCount;
5233 + __u8 Reserved3;
5234 + __u16 SubCommand; /* one setup word */
5235 + __u16 ByteCount;
5236 + __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
5237 + __u16 MaxReferralLevel;
5238 + char RequestFileName[1];
5239 +} TRANSACTION2_GET_DFS_REFER_REQ;
5240 +
5241 +typedef struct dfs_referral_level_3 {
5242 + __u16 VersionNumber;
5243 + __u16 ReferralSize;
5244 + __u16 ServerType; /* 0x0001 = CIFS server */
5245 + __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 */
5246 + __u16 TimeToLive;
5247 + __u16 Proximity;
5248 + __u16 DfsPathOffset;
5249 + __u16 DfsAlternatePathOffset;
5250 + __u16 NetworkAddressOffset;
5251 +} REFERRAL3;
5252 +
5253 +typedef struct smb_com_transaction_get_dfs_refer_rsp {
5254 + struct smb_hdr hdr; /* wct = 10 */
5255 + __u16 TotalParameterCount;
5256 + __u16 TotalDataCount;
5257 + __u16 Reserved;
5258 + __u16 ParameterCount;
5259 + __u16 ParameterOffset;
5260 + __u16 ParameterDisplacement;
5261 + __u16 DataCount;
5262 + __u16 DataOffset;
5263 + __u16 DataDisplacement;
5264 + __u8 SetupCount;
5265 + __u8 Reserved1; /* zero setup words following */
5266 + __u16 ByteCount;
5267 + __u8 Pad;
5268 + __u16 PathConsumed;
5269 + __u16 NumberOfReferrals;
5270 + __u16 DFSFlags;
5271 + __u16 Pad2;
5272 + REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
5273 + /* followed by the strings pointed to by the referral structures */
5274 +} TRANSACTION2_GET_DFS_REFER_RSP;
5275 +
5276 +/* DFS Flags */
5277 +#define DFSREF_REFERRAL_SERVER 0x0001
5278 +#define DFSREF_STORAGE_SERVER 0x0002
5279 +
5280 +/* IOCTL information */
5281 +/* List of ioctl function codes that look to be of interest to remote clients like this. */
5282 +/* Need to do some experimentation to make sure they all work remotely. */
5283 +/* Some of the following such as the encryption/compression ones would be */
5284 +/* invoked from tools via a specialized hook into the VFS rather than via the */
5285 +/* standard vfs entry points */
5286 +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
5287 +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
5288 +#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
5289 +#define FSCTL_LOCK_VOLUME 0x00090018
5290 +#define FSCTL_UNLOCK_VOLUME 0x0009001C
5291 +#define FSCTL_GET_COMPRESSION 0x0009003C
5292 +#define FSCTL_SET_COMPRESSION 0x0009C040
5293 +#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
5294 +#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
5295 +#define FSCTL_SET_REPARSE_POINT 0x000900A4
5296 +#define FSCTL_GET_REPARSE_POINT 0x000900A8
5297 +#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
5298 +#define FSCTL_SET_SPARSE 0x000900C4
5299 +#define FSCTL_SET_ZERO_DATA 0x000900C8
5300 +#define FSCTL_SET_ENCRYPTION 0x000900D7
5301 +#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
5302 +#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
5303 +#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
5304 +#define FSCTL_SIS_COPYFILE 0x00090100
5305 +#define FSCTL_SIS_LINK_FILES 0x0009C104
5306 +
5307 +#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
5308 +#define IO_REPARSE_TAG_HSM 0xC0000004
5309 +#define IO_REPARSE_TAG_SIS 0x80000007
5310 +
5311 +/*
5312 + ************************************************************************
5313 + * All structs for everything above the SMB PDUs themselves
5314 + * (such as the T2 level specific data) go here
5315 + ************************************************************************
5316 + */
5317 +
5318 +/*
5319 + * Information on a server
5320 + */
5321 +
5322 +struct serverInfo {
5323 + char name[16];
5324 + unsigned char versionMajor;
5325 + unsigned char versionMinor;
5326 + unsigned long type;
5327 + unsigned int commentOffset;
5328 +};
5329 +
5330 +/*
5331 + * The following structure is the format of the data returned on a NetShareEnum
5332 + * with level "90" (x5A)
5333 + */
5334 +
5335 +struct shareInfo {
5336 + char shareName[13];
5337 + char pad;
5338 + unsigned short type;
5339 + unsigned int commentOffset;
5340 +};
5341 +
5342 +struct aliasInfo {
5343 + char aliasName[9];
5344 + char pad;
5345 + unsigned int commentOffset;
5346 + unsigned char type[2];
5347 +};
5348 +
5349 +struct aliasInfo92 {
5350 + int aliasNameOffset;
5351 + int serverNameOffset;
5352 + int shareNameOffset;
5353 +};
5354 +
5355 +typedef struct {
5356 + __u64 TotalAllocationUnits;
5357 + __u64 FreeAllocationUnits;
5358 + __u32 SectorsPerAllocationUnit;
5359 + __u32 BytesPerSector;
5360 +} FILE_SYSTEM_INFO; /* size info, level 0x103 */
5361 +
5362 +typedef struct {
5363 + __u16 MajorVersionNumber;
5364 + __u16 MinorVersionNumber;
5365 + __u64 Capability;
5366 +} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
5367 +/* Linux/Unix extensions capability flags */
5368 +#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
5369 +#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
5370 +
5371 +/* DeviceType Flags */
5372 +#define FILE_DEVICE_CD_ROM 0x00000002
5373 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
5374 +#define FILE_DEVICE_DFS 0x00000006
5375 +#define FILE_DEVICE_DISK 0x00000007
5376 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
5377 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009
5378 +#define FILE_DEVICE_NAMED_PIPE 0x00000011
5379 +#define FILE_DEVICE_NETWORK 0x00000012
5380 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
5381 +#define FILE_DEVICE_NULL 0x00000015
5382 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016
5383 +#define FILE_DEVICE_PRINTER 0x00000018
5384 +#define FILE_DEVICE_SERIAL_PORT 0x0000001b
5385 +#define FILE_DEVICE_STREAMS 0x0000001e
5386 +#define FILE_DEVICE_TAPE 0x0000001f
5387 +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
5388 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
5389 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
5390 +
5391 +typedef struct {
5392 + __u32 DeviceType;
5393 + __u32 DeviceCharacteristics;
5394 +} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
5395 +
5396 +typedef struct {
5397 + __u32 Attributes;
5398 + __u32 MaxPathNameComponentLength;
5399 + __u32 FileSystemNameLen;
5400 + char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
5401 +} FILE_SYSTEM_ATTRIBUTE_INFO;
5402 +
5403 +typedef struct { /* data block encoding of response to level 263 QPathInfo */
5404 + __u64 CreationTime;
5405 + __u64 LastAccessTime;
5406 + __u64 LastWriteTime;
5407 + __u64 ChangeTime;
5408 + __u32 Attributes;
5409 + __u32 Pad1;
5410 + __u64 AllocationSize;
5411 + __u64 EndOfFile; /* size ie offset to first free byte in file */
5412 + __u32 NumberOfLinks; /* hard links */
5413 + __u8 DeletePending;
5414 + __u8 Directory;
5415 + __u16 Pad2;
5416 + __u64 IndexNumber;
5417 + __u32 EASize;
5418 + __u32 AccessFlags;
5419 + __u64 IndexNumber1;
5420 + __u64 CurrentByteOffset;
5421 + __u32 Mode;
5422 + __u32 AlignmentRequirement;
5423 + __u32 FileNameLength;
5424 + char FileName[1];
5425 +} FILE_ALL_INFO; /* level 263 QPathInfo */
5426 +
5427 +typedef struct {
5428 + __u64 EndOfFile;
5429 + __u64 NumOfBytes;
5430 + __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
5431 + __u64 LastAccessTime;
5432 + __u64 LastModificationTime;
5433 + __u64 Uid;
5434 + __u64 Gid;
5435 + __u32 Type;
5436 + __u64 DevMajor;
5437 + __u64 DevMinor;
5438 + __u64 UniqueId;
5439 + __u64 Permissions;
5440 + __u64 Nlinks;
5441 +} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */
5442 +
5443 +typedef struct {
5444 + char LinkDest[1];
5445 +} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */
5446 +
5447 +/* defines for enumerating possible values of the Unix type field below */
5448 +#define UNIX_FILE 0
5449 +#define UNIX_DIR 1
5450 +#define UNIX_SYMLINK 2
5451 +#define UNIX_CHARDEV 3
5452 +#define UNIX_BLOCKDEV 4
5453 +#define UNIX_FIFO 5
5454 +#define UNIX_SOCKET 6
5455 +
5456 +typedef struct {
5457 + __u32 NextEntryOffset;
5458 + __u32 ResumeKey;
5459 + __u64 EndOfFile;
5460 + __u64 NumOfBytes;
5461 + __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
5462 + __u64 LastAccessTime;
5463 + __u64 LastModificationTime;
5464 + __u64 Uid;
5465 + __u64 Gid;
5466 + __u32 Type;
5467 + __u64 DevMajor;
5468 + __u64 DevMinor;
5469 + __u64 UniqueId;
5470 + __u64 Permissions;
5471 + __u64 Nlinks;
5472 + char FileName[1];
5473 +} FILE_UNIX_INFO;
5474 +
5475 +typedef struct {
5476 + __u64 CreationTime;
5477 + __u64 LastAccessTime;
5478 + __u64 LastWriteTime;
5479 + __u64 ChangeTime;
5480 + __u32 Attributes;
5481 + __u32 Pad;
5482 +} FILE_BASIC_INFO; /* size info, level 0x101 */
5483 +
5484 +struct file_allocation_info {
5485 + __u64 AllocationSize;
5486 +}; /* size info, level 0x103 */
5487 +
5488 +struct file_end_of_file_info {
5489 + __u64 FileSize; /* offset to end of file */
5490 +}; /* size info, level 0x104 */
5491 +
5492 +typedef struct {
5493 + __u32 NextEntryOffset;
5494 + __u32 FileIndex;
5495 + __u64 CreationTime;
5496 + __u64 LastAccessTime;
5497 + __u64 LastWriteTime;
5498 + __u64 ChangeTime;
5499 + __u64 EndOfFile;
5500 + __u64 AllocationSize;
5501 + __u32 ExtFileAttributes;
5502 + __u32 FileNameLength;
5503 + char FileName[1];
5504 +} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
5505 +
5506 +struct gea {
5507 + unsigned char cbName;
5508 + char szName[1];
5509 +};
5510 +
5511 +struct gealist {
5512 + unsigned long cbList;
5513 + struct gea list[1];
5514 +};
5515 +
5516 +struct fea {
5517 + unsigned char EA_flags;
5518 + __u8 name_len;
5519 + __u16 value_len;
5520 + char szName[1];
5521 + /* optionally followed by value */
5522 +};
5523 +/* flags for _FEA.fEA */
5524 +#define FEA_NEEDEA 0x80 /* need EA bit */
5525 +
5526 +struct fealist {
5527 + __u32 list_len;
5528 + struct fea list[1];
5529 +};
5530 +
5531 +/* used to hold an arbitrary blob of data */
5532 +struct data_blob {
5533 + __u8 *data;
5534 + size_t length;
5535 + void (*free) (struct data_blob * data_blob);
5536 +};
5537 +
5538 +#ifdef CONFIG_CIFS_POSIX
5539 +/*
5540 + For better POSIX semantics from Linux client, (even better
5541 + than the existing CIFS Unix Extensions) we need updated PDUs for:
5542 +
5543 + 1) PosixCreateX - to set and return the mode, inode#, device info and
5544 + perhaps add a CreateDevice - to create Pipes and other special .inodes
5545 + Also note POSIX open flags
5546 + 2) Close - to return the last write time to do cache across close more safely
5547 + 3) PosixQFSInfo - to return statfs info
5548 + 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
5549 + 5) Mkdir - set mode
5550 +
5551 + And under consideration:
5552 + 6) FindClose2 (return nanosecond timestamp ??)
5553 + 7) Use nanosecond timestamps throughout all time fields if
5554 + corresponding attribute flag is set
5555 + 8) sendfile - handle based copy
5556 + 9) Direct i/o
5557 + 10) "POSIX ACL" support
5558 + 11) Misc fcntls?
5559 +
5560 + what about fixing 64 bit alignment
5561 +
5562 + There are also various legacy SMB/CIFS requests used as is
5563 +
5564 + From existing Lanman and NTLM dialects:
5565 + --------------------------------------
5566 + NEGOTIATE
5567 + SESSION_SETUP_ANDX (BB which?)
5568 + TREE_CONNECT_ANDX (BB which wct?)
5569 + TREE_DISCONNECT (BB add volume timestamp on response)
5570 + LOGOFF_ANDX
5571 + DELETE (note delete open file behavior)
5572 + DELETE_DIRECTORY
5573 + READ_AND_X
5574 + WRITE_AND_X
5575 + LOCKING_AND_X (note posix lock semantics)
5576 + RENAME (note rename across dirs and open file rename posix behaviors)
5577 + NT_RENAME (for hardlinks) Is this good enough for all features?
5578 + FIND_CLOSE2
5579 + TRANSACTION2 (18 cases)
5580 + SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
5581 + (BB verify that never need to set allocation size)
5582 + SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
5583 +
5584 + COPY (note support for copy across directories) - FUTURE, OPTIONAL
5585 + setting/getting OS/2 EAs - FUTURE (BB can this handle
5586 + setting Linux xattrs perfectly) - OPTIONAL
5587 + dnotify - FUTURE, OPTIONAL
5588 + quota - FUTURE, OPTIONAL
5589 +
5590 + Note that various requests implemented for NT interop such as
5591 + NT_TRANSACT (IOCTL) QueryReparseInfo
5592 + are unneeded to servers compliant with the CIFS POSIX extensions
5593 +
5594 + From CIFS Unix Extensions:
5595 + -------------------------
5596 + T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
5597 + T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
5598 + T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
5599 + T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
5600 + Actually need QUERY_FILE_UNIX_INFO since has inode num
5601 + BB what about a) blksize/blkbits/blocks
5602 + b) i_version
5603 + c) i_rdev
5604 + d) notify mask?
5605 + e) generation
5606 + f) size_seqcount
5607 + T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
5608 + TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
5609 + T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
5610 +
5611 +
5612 + */
5613 +#endif
5614 +
5615 +#pragma pack() /* resume default structure packing */
5616 +
5617 +#endif /* _CIFSPDU_H */
5618 diff -urN linux-2.4.29.old/fs/cifs/cifsproto.h linux-2.4.29/fs/cifs/cifsproto.h
5619 --- linux-2.4.29.old/fs/cifs/cifsproto.h 1970-01-01 01:00:00.000000000 +0100
5620 +++ linux-2.4.29/fs/cifs/cifsproto.h 2004-07-14 00:25:05.000000000 +0200
5621 @@ -0,0 +1,254 @@
5622 +/*
5623 + * fs/cifs/cifsproto.h
5624 + *
5625 + * Copyright (c) International Business Machines Corp., 2002
5626 + * Author(s): Steve French (sfrench@us.ibm.com)
5627 + *
5628 + * This library is free software; you can redistribute it and/or modify
5629 + * it under the terms of the GNU Lesser General Public License as published
5630 + * by the Free Software Foundation; either version 2.1 of the License, or
5631 + * (at your option) any later version.
5632 + *
5633 + * This library is distributed in the hope that it will be useful,
5634 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5635 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5636 + * the GNU Lesser General Public License for more details.
5637 + *
5638 + * You should have received a copy of the GNU Lesser General Public License
5639 + * along with this library; if not, write to the Free Software
5640 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5641 + */
5642 +#ifndef _CIFSPROTO_H
5643 +#define _CIFSPROTO_H
5644 +#include <linux/nls.h>
5645 +
5646 +struct statfs;
5647 +
5648 +/*
5649 + *****************************************************************
5650 + * All Prototypes
5651 + *****************************************************************
5652 + */
5653 +
5654 +extern struct smb_hdr *cifs_buf_get(void);
5655 +extern void cifs_buf_release(void *);
5656 +extern int smb_send(struct socket *, struct smb_hdr *,
5657 + unsigned int /* length */ , struct sockaddr *);
5658 +extern unsigned int _GetXid(void);
5659 +extern void _FreeXid(unsigned int);
5660 +#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
5661 +#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
5662 +extern char *build_path_from_dentry(struct dentry *);
5663 +extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
5664 +extern void renew_parental_timestamps(struct dentry *direntry);
5665 +extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
5666 + struct smb_hdr * /* input */ ,
5667 + struct smb_hdr * /* out */ ,
5668 + int * /* bytes returned */ , const int long_op);
5669 +extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
5670 +extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
5671 +extern int is_valid_oplock_break(struct smb_hdr *smb);
5672 +extern unsigned int smbCalcSize(struct smb_hdr *ptr);
5673 +extern int decode_negTokenInit(unsigned char *security_blob, int length,
5674 + enum securityEnum *secType);
5675 +extern int map_smb_to_linux_error(struct smb_hdr *smb);
5676 +extern void header_assemble(struct smb_hdr *, char /* command */ ,
5677 + const struct cifsTconInfo *, int
5678 + /* length of fixed section (word count) in two byte units */
5679 + );
5680 +struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
5681 +void DeleteOplockQEntry(struct oplock_q_entry *);
5682 +extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
5683 +extern u64 cifs_UnixTimeToNT(time_t);
5684 +extern int cifs_get_inode_info(struct inode **pinode,
5685 + const unsigned char *search_path,
5686 + FILE_ALL_INFO * pfile_info,
5687 + struct super_block *sb, int xid);
5688 +extern int cifs_get_inode_info_unix(struct inode **pinode,
5689 + const unsigned char *search_path,
5690 + struct super_block *sb,int xid);
5691 +
5692 +extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
5693 + struct nls_table * nls_info);
5694 +extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
5695 +
5696 +extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
5697 + const char *tree, struct cifsTconInfo *tcon,
5698 + const struct nls_table *);
5699 +
5700 +extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
5701 + const char *searchName,
5702 + FILE_DIRECTORY_INFO * findData,
5703 + T2_FFIRST_RSP_PARMS * findParms,
5704 + const struct nls_table *nls_codepage,
5705 + int *pUnicodeFlag,
5706 + int *pUnixFlag /* if Unix extensions used */ );
5707 +extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
5708 + FILE_DIRECTORY_INFO * findData,
5709 + T2_FNEXT_RSP_PARMS * findParms,
5710 + const __u16 searchHandle, char * resume_name,
5711 + int name_length, __u32 resume_key,
5712 + int *UnicodeFlag, int *pUnixFlag);
5713 +
5714 +extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
5715 + const __u16 search_handle);
5716 +
5717 +extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
5718 + const unsigned char *searchName,
5719 + FILE_ALL_INFO * findData,
5720 + const struct nls_table *nls_codepage);
5721 +
5722 +extern int CIFSSMBUnixQPathInfo(const int xid,
5723 + struct cifsTconInfo *tcon,
5724 + const unsigned char *searchName,
5725 + FILE_UNIX_BASIC_INFO * pFindData,
5726 + const struct nls_table *nls_codepage);
5727 +
5728 +extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
5729 + const unsigned char *searchName,
5730 + unsigned char **targetUNCs,
5731 + unsigned int *number_of_UNC_in_array,
5732 + const struct nls_table *nls_codepage);
5733 +
5734 +extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
5735 + const char *old_path,
5736 + const struct nls_table *nls_codepage);
5737 +extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
5738 + const char *old_path, const struct nls_table *nls_codepage,
5739 + unsigned int *pnum_referrals, unsigned char ** preferrals);
5740 +extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
5741 + struct statfs *FSData,
5742 + const struct nls_table *nls_codepage);
5743 +extern int CIFSSMBQFSAttributeInfo(const int xid,
5744 + struct cifsTconInfo *tcon,
5745 + const struct nls_table *nls_codepage);
5746 +extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
5747 + const struct nls_table *nls_codepage);
5748 +extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
5749 + const struct nls_table *nls_codepage);
5750 +
5751 +extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
5752 + char *fileName, FILE_BASIC_INFO * data,
5753 + const struct nls_table *nls_codepage);
5754 +extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
5755 + char *fileName, __u64 size,int setAllocationSizeFlag,
5756 + const struct nls_table *nls_codepage);
5757 +extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
5758 + __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
5759 +extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
5760 + char *full_path, __u64 mode, __u64 uid,
5761 + __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
5762 +
5763 +extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
5764 + const char *newName,
5765 + const struct nls_table *nls_codepage);
5766 +extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
5767 + const char *name, const struct nls_table *nls_codepage);
5768 +
5769 +extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
5770 + const char *name,
5771 + const struct nls_table *nls_codepage);
5772 +extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
5773 + const char *fromName, const char *toName,
5774 + const struct nls_table *nls_codepage);
5775 +extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
5776 + int netfid, char * target_name, const struct nls_table *nls_codepage);
5777 +extern int CIFSCreateHardLink(const int xid,
5778 + struct cifsTconInfo *tcon,
5779 + const char *fromName, const char *toName,
5780 + const struct nls_table *nls_codepage);
5781 +extern int CIFSUnixCreateHardLink(const int xid,
5782 + struct cifsTconInfo *tcon,
5783 + const char *fromName, const char *toName,
5784 + const struct nls_table *nls_codepage);
5785 +extern int CIFSUnixCreateSymLink(const int xid,
5786 + struct cifsTconInfo *tcon,
5787 + const char *fromName, const char *toName,
5788 + const struct nls_table *nls_codepage);
5789 +extern int CIFSSMBUnixQuerySymLink(const int xid,
5790 + struct cifsTconInfo *tcon,
5791 + const unsigned char *searchName,
5792 + char *syminfo, const int buflen,
5793 + const struct nls_table *nls_codepage);
5794 +extern int CIFSSMBQueryReparseLinkInfo(const int xid,
5795 + struct cifsTconInfo *tcon,
5796 + const unsigned char *searchName,
5797 + char *symlinkinfo, const int buflen, __u16 fid,
5798 + const struct nls_table *nls_codepage);
5799 +
5800 +extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
5801 + const char *fileName, const int disposition,
5802 + const int access_flags, const int omode,
5803 + __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
5804 + const struct nls_table *nls_codepage);
5805 +extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
5806 + const int smb_file_id);
5807 +
5808 +extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
5809 + const int netfid, unsigned int count,
5810 + const __u64 lseek, unsigned int *nbytes, char **buf);
5811 +extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
5812 + const int netfid, const unsigned int count,
5813 + const __u64 lseek, unsigned int *nbytes,
5814 + const char *buf, const int long_op);
5815 +extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
5816 + const __u16 netfid, const __u64 len,
5817 + const __u64 offset, const __u32 numUnlock,
5818 + const __u32 numLock, const __u8 lockType,
5819 + const int waitFlag);
5820 +
5821 +extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
5822 +extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
5823 +
5824 +extern struct cifsSesInfo *sesInfoAlloc(void);
5825 +extern void sesInfoFree(struct cifsSesInfo *);
5826 +extern struct cifsTconInfo *tconInfoAlloc(void);
5827 +extern void tconInfoFree(struct cifsTconInfo *);
5828 +
5829 +extern int cifs_reconnect(struct TCP_Server_Info *server);
5830 +
5831 +extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
5832 +extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
5833 + __u32 expected_sequence_number);
5834 +extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
5835 +extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
5836 +extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
5837 +
5838 +extern int CIFSBuildServerList(int xid, char *serverBufferList,
5839 + int recordlength, int *entries,
5840 + int *totalEntries, int *topoChangedFlag);
5841 +extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
5842 + struct shareInfo *shareList, int bufferLen,
5843 + int *entries, int *totalEntries);
5844 +extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
5845 + struct aliasInfo *aliasList, int bufferLen,
5846 + int *entries, int *totalEntries);
5847 +extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
5848 + char *aliasName, char *serverName,
5849 + char *shareName, char *comment);
5850 +extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
5851 + char *share, char *comment);
5852 +extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
5853 + char *userName, char *searchName, int *perms);
5854 +extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
5855 +
5856 +extern int CIFSSMBSeek(int xid,
5857 + struct cifsTconInfo *tcon,
5858 + int netfid,
5859 + int pid,
5860 + int whence, unsigned long offset, long long *newoffset);
5861 +
5862 +extern int CIFSSMBCopy(int xid,
5863 + struct cifsTconInfo *source_tcon,
5864 + const char *fromName,
5865 + const __u16 target_tid,
5866 + const char *toName, const int flags,
5867 + const struct nls_table *nls_codepage);
5868 +extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5869 + const int notify_subdirs,const __u16 netfid,__u32 filter,
5870 + const struct nls_table *nls_codepage);
5871 +extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5872 + const unsigned char *searchName,
5873 + char * EAData, size_t size,
5874 + const struct nls_table *nls_codepage);
5875 +#endif /* _CIFSPROTO_H */
5876 diff -urN linux-2.4.29.old/fs/cifs/cifssmb.c linux-2.4.29/fs/cifs/cifssmb.c
5877 --- linux-2.4.29.old/fs/cifs/cifssmb.c 1970-01-01 01:00:00.000000000 +0100
5878 +++ linux-2.4.29/fs/cifs/cifssmb.c 2004-07-14 00:25:05.000000000 +0200
5879 @@ -0,0 +1,3016 @@
5880 +/*
5881 + * fs/cifs/cifssmb.c
5882 + *
5883 + * Copyright (C) International Business Machines Corp., 2002,2003
5884 + * Author(s): Steve French (sfrench@us.ibm.com)
5885 + *
5886 + * Contains the routines for constructing the SMB PDUs themselves
5887 + *
5888 + * This library is free software; you can redistribute it and/or modify
5889 + * it under the terms of the GNU Lesser General Public License as published
5890 + * by the Free Software Foundation; either version 2.1 of the License, or
5891 + * (at your option) any later version.
5892 + *
5893 + * This library is distributed in the hope that it will be useful,
5894 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5895 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5896 + * the GNU Lesser General Public License for more details.
5897 + *
5898 + * You should have received a copy of the GNU Lesser General Public License
5899 + * along with this library; if not, write to the Free Software
5900 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5901 + */
5902 +
5903 + /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
5904 + /* These are mostly routines that operate on a pathname, or on a tree id */
5905 + /* (mounted volume), but there are eight handle based routines which must be */
5906 + /* treated slightly different for reconnection purposes since we never want */
5907 + /* to reuse a stale file handle and the caller knows the file handle */
5908 +
5909 +#include <linux/fs.h>
5910 +#include <linux/kernel.h>
5911 +#include <linux/vfs.h>
5912 +#include <asm/uaccess.h>
5913 +#include "cifspdu.h"
5914 +#include "cifsglob.h"
5915 +#include "cifsproto.h"
5916 +#include "cifs_unicode.h"
5917 +#include "cifs_debug.h"
5918 +
5919 +#ifdef CONFIG_CIFS_POSIX
5920 +static struct {
5921 + int index;
5922 + char *name;
5923 +} protocols[] = {
5924 + {CIFS_PROT, "\2NT LM 0.12"},
5925 + {CIFS_PROT, "\2POSIX 2"},
5926 + {BAD_PROT, "\2"}
5927 +};
5928 +#else
5929 +static struct {
5930 + int index;
5931 + char *name;
5932 +} protocols[] = {
5933 + {CIFS_PROT, "\2NT LM 0.12"},
5934 + {BAD_PROT, "\2"}
5935 +};
5936 +#endif
5937 +
5938 +
5939 +/* Mark as invalid, all open files on tree connections since they
5940 + were closed when session to server was lost */
5941 +static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
5942 +{
5943 + struct cifsFileInfo *open_file = NULL;
5944 + struct list_head * tmp;
5945 + struct list_head * tmp1;
5946 +
5947 +/* list all files open on tree connection and mark them invalid */
5948 + write_lock(&GlobalSMBSeslock);
5949 + list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
5950 + open_file = list_entry(tmp,struct cifsFileInfo, tlist);
5951 + if(open_file) {
5952 + open_file->invalidHandle = TRUE;
5953 + }
5954 + }
5955 + write_unlock(&GlobalSMBSeslock);
5956 + /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
5957 +}
5958 +
5959 +static int
5960 +smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
5961 + void **request_buf /* returned */ ,
5962 + void **response_buf /* returned */ )
5963 +{
5964 + int rc = 0;
5965 + int timeout = 10 * HZ;
5966 +
5967 + /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
5968 + check for tcp and smb session status done differently
5969 + for those three - in the calling routine */
5970 + if(tcon) {
5971 + if((tcon->ses) && (tcon->ses->server)){
5972 + struct nls_table *nls_codepage;
5973 + /* Give Demultiplex thread up to 10 seconds to
5974 + reconnect, should be greater than cifs socket
5975 + timeout which is 7 seconds */
5976 + while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
5977 + while ((tcon->ses->server->tcpStatus != CifsGood) && (timeout > 0)){
5978 + timeout = interruptible_sleep_on_timeout(&tcon->ses->server->response_q,timeout);
5979 + }
5980 + if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
5981 + /* on "soft" mounts we wait once */
5982 + if((tcon->retry == FALSE) ||
5983 + (tcon->ses->status == CifsExiting)) {
5984 + cFYI(1,("gave up waiting on reconnect in smb_init"));
5985 + return -EHOSTDOWN;
5986 + } /* else "hard" mount - keep retrying until
5987 + process is killed or server comes back up */
5988 + } else /* TCP session is reestablished now */
5989 + break;
5990 +
5991 + }
5992 +
5993 + nls_codepage = load_nls_default();
5994 + /* need to prevent multiple threads trying to
5995 + simultaneously reconnect the same SMB session */
5996 + down(&tcon->ses->sesSem);
5997 + if(tcon->ses->status == CifsNeedReconnect)
5998 + rc = cifs_setup_session(0, tcon->ses, nls_codepage);
5999 + if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
6000 + mark_open_files_invalid(tcon);
6001 + rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
6002 + nls_codepage);
6003 + up(&tcon->ses->sesSem);
6004 + if(rc == 0)
6005 + atomic_inc(&tconInfoReconnectCount);
6006 +
6007 + cFYI(1, ("reconnect tcon rc = %d", rc));
6008 + /* Removed call to reopen open files here -
6009 + it is safer (and faster) to reopen files
6010 + one at a time as needed in read and write */
6011 +
6012 + /* Check if handle based operation so we
6013 + know whether we can continue or not without
6014 + returning to caller to reset file handle */
6015 + switch(smb_command) {
6016 + case SMB_COM_READ_ANDX:
6017 + case SMB_COM_WRITE_ANDX:
6018 + case SMB_COM_CLOSE:
6019 + case SMB_COM_FIND_CLOSE2:
6020 + case SMB_COM_LOCKING_ANDX: {
6021 + unload_nls(nls_codepage);
6022 + return -EAGAIN;
6023 + }
6024 + }
6025 + } else {
6026 + up(&tcon->ses->sesSem);
6027 + }
6028 + unload_nls(nls_codepage);
6029 +
6030 + } else {
6031 + return -EIO;
6032 + }
6033 + }
6034 + if(rc)
6035 + return rc;
6036 +
6037 + *request_buf = cifs_buf_get();
6038 + if (*request_buf == 0) {
6039 + /* BB should we add a retry in here if not a writepage? */
6040 + return -ENOMEM;
6041 + }
6042 + /* Although the original thought was we needed the response buf for */
6043 + /* potential retries of smb operations it turns out we can determine */
6044 + /* from the mid flags when the request buffer can be resent without */
6045 + /* having to use a second distinct buffer for the response */
6046 + *response_buf = *request_buf;
6047 +
6048 + header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
6049 + wct /*wct */ );
6050 +
6051 +#ifdef CONFIG_CIFS_STATS
6052 + if(tcon != NULL) {
6053 + atomic_inc(&tcon->num_smbs_sent);
6054 + }
6055 +#endif
6056 + return rc;
6057 +}
6058 +
6059 +int
6060 +CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
6061 +{
6062 + NEGOTIATE_REQ *pSMB;
6063 + NEGOTIATE_RSP *pSMBr;
6064 + int rc = 0;
6065 + int bytes_returned;
6066 + struct TCP_Server_Info * server;
6067 +
6068 + if(ses->server)
6069 + server = ses->server;
6070 + else {
6071 + rc = -EIO;
6072 + return rc;
6073 + }
6074 + rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
6075 + (void **) &pSMB, (void **) &pSMBr);
6076 + if (rc)
6077 + return rc;
6078 +
6079 + pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
6080 + if (extended_security)
6081 + pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
6082 +
6083 + pSMB->ByteCount = strlen(protocols[0].name) + 1;
6084 + strncpy(pSMB->DialectsArray, protocols[0].name, 30);
6085 + /* null guaranteed to be at end of source and target buffers anyway */
6086 +
6087 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6088 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6089 +
6090 + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
6091 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6092 + if (rc == 0) {
6093 + server->secMode = pSMBr->SecurityMode;
6094 + server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
6095 + /* one byte - no need to convert this or EncryptionKeyLen from le,*/
6096 + server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
6097 + /* probably no need to store and check maxvcs */
6098 + server->maxBuf =
6099 + min(le32_to_cpu(pSMBr->MaxBufferSize),
6100 + (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
6101 + server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
6102 + cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
6103 + GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
6104 + server->capabilities = le32_to_cpu(pSMBr->Capabilities);
6105 + server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
6106 + /* BB with UTC do we ever need to be using srvr timezone? */
6107 + if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
6108 + memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
6109 + CIFS_CRYPTO_KEY_SIZE);
6110 + } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
6111 + && (pSMBr->EncryptionKeyLength == 0)) {
6112 + /* decode security blob */
6113 + } else
6114 + rc = -EIO;
6115 +
6116 + /* BB might be helpful to save off the domain of server here */
6117 +
6118 + if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
6119 + if (pSMBr->ByteCount < 16)
6120 + rc = -EIO;
6121 + else if (pSMBr->ByteCount == 16) {
6122 + server->secType = RawNTLMSSP;
6123 + if (server->socketUseCount.counter > 1) {
6124 + if (memcmp
6125 + (server->server_GUID,
6126 + pSMBr->u.extended_response.
6127 + GUID, 16) != 0) {
6128 + cFYI(1,
6129 + ("UID of server does not match previous connection to same ip address"));
6130 + memcpy(server->
6131 + server_GUID,
6132 + pSMBr->u.
6133 + extended_response.
6134 + GUID, 16);
6135 + }
6136 + } else
6137 + memcpy(server->server_GUID,
6138 + pSMBr->u.extended_response.
6139 + GUID, 16);
6140 + } else {
6141 + rc = decode_negTokenInit(pSMBr->u.
6142 + extended_response.
6143 + SecurityBlob,
6144 + pSMBr->ByteCount -
6145 + 16, &server->secType);
6146 + }
6147 + } else
6148 + server->capabilities &= ~CAP_EXTENDED_SECURITY;
6149 + if(sign_CIFS_PDUs == FALSE) {
6150 + if(server->secMode & SECMODE_SIGN_REQUIRED)
6151 + cERROR(1,
6152 + ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
6153 + server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
6154 + } else if(sign_CIFS_PDUs == 1) {
6155 + if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
6156 + server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
6157 + }
6158 +
6159 + }
6160 + if (pSMB)
6161 + cifs_buf_release(pSMB);
6162 + return rc;
6163 +}
6164 +
6165 +int
6166 +CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
6167 +{
6168 + struct smb_hdr *smb_buffer;
6169 + struct smb_hdr *smb_buffer_response;
6170 + int rc = 0;
6171 + int length;
6172 +
6173 + cFYI(1, ("In tree disconnect"));
6174 + /*
6175 + * If last user of the connection and
6176 + * connection alive - disconnect it
6177 + * If this is the last connection on the server session disconnect it
6178 + * (and inside session disconnect we should check if tcp socket needs
6179 + * to be freed and kernel thread woken up).
6180 + */
6181 + if (tcon)
6182 + down(&tcon->tconSem);
6183 + else
6184 + return -EIO;
6185 +
6186 + atomic_dec(&tcon->useCount);
6187 + if (atomic_read(&tcon->useCount) > 0) {
6188 + up(&tcon->tconSem);
6189 + return -EBUSY;
6190 + }
6191 +
6192 + /* No need to return error on this operation if tid invalidated and
6193 + closed on server already e.g. due to tcp session crashing */
6194 + if(tcon->tidStatus == CifsNeedReconnect) {
6195 + up(&tcon->tconSem);
6196 + return 0;
6197 + }
6198 +
6199 + if((tcon->ses == 0) || (tcon->ses->server == 0)) {
6200 + up(&tcon->tconSem);
6201 + return -EIO;
6202 + }
6203 +
6204 + rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
6205 + (void **) &smb_buffer, (void **) &smb_buffer_response);
6206 + if (rc) {
6207 + up(&tcon->tconSem);
6208 + return rc;
6209 + }
6210 + rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
6211 + &length, 0);
6212 + if (rc)
6213 + cFYI(1, (" Tree disconnect failed %d", rc));
6214 +
6215 + if (smb_buffer)
6216 + cifs_buf_release(smb_buffer);
6217 + up(&tcon->tconSem);
6218 +
6219 + /* No need to return error on this operation if tid invalidated and
6220 + closed on server already e.g. due to tcp session crashing */
6221 + if (rc == -EAGAIN)
6222 + rc = 0;
6223 +
6224 + return rc;
6225 +}
6226 +
6227 +int
6228 +CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
6229 +{
6230 + struct smb_hdr *smb_buffer_response;
6231 + LOGOFF_ANDX_REQ *pSMB;
6232 + int rc = 0;
6233 + int length;
6234 +
6235 + cFYI(1, ("In SMBLogoff for session disconnect"));
6236 + if (ses)
6237 + down(&ses->sesSem);
6238 + else
6239 + return -EIO;
6240 +
6241 + atomic_dec(&ses->inUse);
6242 + if (atomic_read(&ses->inUse) > 0) {
6243 + up(&ses->sesSem);
6244 + return -EBUSY;
6245 + }
6246 +
6247 + rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
6248 + (void **) &pSMB, (void **) &smb_buffer_response);
6249 +
6250 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
6251 + pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
6252 +
6253 + if (rc) {
6254 + up(&ses->sesSem);
6255 + return rc;
6256 + }
6257 +
6258 + pSMB->hdr.Uid = ses->Suid;
6259 +
6260 + pSMB->AndXCommand = 0xFF;
6261 + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
6262 + smb_buffer_response, &length, 0);
6263 + if (ses->server) {
6264 + atomic_dec(&ses->server->socketUseCount);
6265 + if (atomic_read(&ses->server->socketUseCount) == 0) {
6266 + spin_lock(&GlobalMid_Lock);
6267 + ses->server->tcpStatus = CifsExiting;
6268 + spin_unlock(&GlobalMid_Lock);
6269 + rc = -ESHUTDOWN;
6270 + }
6271 + }
6272 + if (pSMB)
6273 + cifs_buf_release(pSMB);
6274 + up(&ses->sesSem);
6275 +
6276 + /* if session dead then we do not need to do ulogoff,
6277 + since server closed smb session, no sense reporting
6278 + error */
6279 + if (rc == -EAGAIN)
6280 + rc = 0;
6281 + return rc;
6282 +}
6283 +
6284 +int
6285 +CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
6286 + const char *fileName, const struct nls_table *nls_codepage)
6287 +{
6288 + DELETE_FILE_REQ *pSMB = NULL;
6289 + DELETE_FILE_RSP *pSMBr = NULL;
6290 + int rc = 0;
6291 + int bytes_returned;
6292 + int name_len;
6293 +
6294 +DelFileRetry:
6295 + rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
6296 + (void **) &pSMBr);
6297 + if (rc)
6298 + return rc;
6299 +
6300 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6301 + name_len =
6302 + cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
6303 + /* find define for this maxpathcomponent */
6304 + , nls_codepage);
6305 + name_len++; /* trailing null */
6306 + name_len *= 2;
6307 + } else { /* BB improve the check for buffer overruns BB */
6308 + name_len = strnlen(fileName, 530);
6309 + name_len++; /* trailing null */
6310 + strncpy(pSMB->fileName, fileName, name_len);
6311 + }
6312 + pSMB->SearchAttributes =
6313 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
6314 + pSMB->ByteCount = name_len + 1;
6315 + pSMB->BufferFormat = 0x04;
6316 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6317 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6318 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6319 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6320 + if (rc) {
6321 + cFYI(1, ("Error in RMFile = %d", rc));
6322 + }
6323 +#ifdef CONFIG_CIFS_STATS
6324 + else {
6325 + atomic_inc(&tcon->num_deletes);
6326 + }
6327 +#endif
6328 +
6329 + if (pSMB)
6330 + cifs_buf_release(pSMB);
6331 + if (rc == -EAGAIN)
6332 + goto DelFileRetry;
6333 +
6334 + return rc;
6335 +}
6336 +
6337 +int
6338 +CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
6339 + const char *dirName, const struct nls_table *nls_codepage)
6340 +{
6341 + DELETE_DIRECTORY_REQ *pSMB = NULL;
6342 + DELETE_DIRECTORY_RSP *pSMBr = NULL;
6343 + int rc = 0;
6344 + int bytes_returned;
6345 + int name_len;
6346 +
6347 + cFYI(1, ("In CIFSSMBRmDir"));
6348 +RmDirRetry:
6349 + rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
6350 + (void **) &pSMBr);
6351 + if (rc)
6352 + return rc;
6353 +
6354 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6355 + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
6356 + /* find define for this maxpathcomponent */
6357 + , nls_codepage);
6358 + name_len++; /* trailing null */
6359 + name_len *= 2;
6360 + } else { /* BB improve the check for buffer overruns BB */
6361 + name_len = strnlen(dirName, 530);
6362 + name_len++; /* trailing null */
6363 + strncpy(pSMB->DirName, dirName, name_len);
6364 + }
6365 +
6366 + pSMB->ByteCount = name_len + 1;
6367 + pSMB->BufferFormat = 0x04;
6368 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6369 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6370 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6371 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6372 + if (rc) {
6373 + cFYI(1, ("Error in RMDir = %d", rc));
6374 + }
6375 +#ifdef CONFIG_CIFS_STATS
6376 + else {
6377 + atomic_inc(&tcon->num_rmdirs);
6378 + }
6379 +#endif
6380 +
6381 + if (pSMB)
6382 + cifs_buf_release(pSMB);
6383 + if (rc == -EAGAIN)
6384 + goto RmDirRetry;
6385 + return rc;
6386 +}
6387 +
6388 +int
6389 +CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
6390 + const char *name, const struct nls_table *nls_codepage)
6391 +{
6392 + int rc = 0;
6393 + CREATE_DIRECTORY_REQ *pSMB = NULL;
6394 + CREATE_DIRECTORY_RSP *pSMBr = NULL;
6395 + int bytes_returned;
6396 + int name_len;
6397 +
6398 + cFYI(1, ("In CIFSSMBMkDir"));
6399 +MkDirRetry:
6400 + rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
6401 + (void **) &pSMBr);
6402 + if (rc)
6403 + return rc;
6404 +
6405 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6406 + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
6407 + /* find define for this maxpathcomponent */
6408 + , nls_codepage);
6409 + name_len++; /* trailing null */
6410 + name_len *= 2;
6411 + } else { /* BB improve the check for buffer overruns BB */
6412 + name_len = strnlen(name, 530);
6413 + name_len++; /* trailing null */
6414 + strncpy(pSMB->DirName, name, name_len);
6415 + }
6416 +
6417 + pSMB->ByteCount = name_len + 1 /* for buf format */ ;
6418 + pSMB->BufferFormat = 0x04;
6419 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6420 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6421 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6422 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6423 + if (rc) {
6424 + cFYI(1, ("Error in Mkdir = %d", rc));
6425 + }
6426 +#ifdef CONFIG_CIFS_STATS
6427 + else {
6428 + atomic_inc(&tcon->num_mkdirs);
6429 + }
6430 +#endif
6431 + if (pSMB)
6432 + cifs_buf_release(pSMB);
6433 + if (rc == -EAGAIN)
6434 + goto MkDirRetry;
6435 + return rc;
6436 +}
6437 +
6438 +int
6439 +CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
6440 + const char *fileName, const int openDisposition,
6441 + const int access_flags, const int create_options, __u16 * netfid,
6442 + int *pOplock, FILE_ALL_INFO * pfile_info,
6443 + const struct nls_table *nls_codepage)
6444 +{
6445 + int rc = -EACCES;
6446 + OPEN_REQ *pSMB = NULL;
6447 + OPEN_RSP *pSMBr = NULL;
6448 + int bytes_returned;
6449 + int name_len;
6450 +
6451 +openRetry:
6452 + rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
6453 + (void **) &pSMBr);
6454 + if (rc)
6455 + return rc;
6456 +
6457 + pSMB->AndXCommand = 0xFF; /* none */
6458 +
6459 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6460 + pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
6461 + name_len =
6462 + cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
6463 + fileName, 530
6464 + /* find define for this maxpathcomponent */
6465 + , nls_codepage);
6466 + name_len++; /* trailing null */
6467 + name_len *= 2;
6468 + pSMB->NameLength = cpu_to_le16(name_len);
6469 + } else { /* BB improve the check for buffer overruns BB */
6470 + pSMB->ByteCount = 0; /* no pad */
6471 + name_len = strnlen(fileName, 530);
6472 + name_len++; /* trailing null */
6473 + pSMB->NameLength = cpu_to_le16(name_len);
6474 + strncpy(pSMB->fileName, fileName, name_len);
6475 + }
6476 + if (*pOplock & REQ_OPLOCK)
6477 + pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
6478 + else if (*pOplock & REQ_BATCHOPLOCK) {
6479 + pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
6480 + }
6481 + pSMB->DesiredAccess = cpu_to_le32(access_flags);
6482 + pSMB->AllocationSize = 0;
6483 + pSMB->FileAttributes = ATTR_NORMAL;
6484 + /* XP does not handle ATTR_POSIX_SEMANTICS */
6485 + /* but it helps speed up case sensitive checks for other
6486 + servers such as Samba */
6487 + if (tcon->ses->capabilities & CAP_UNIX)
6488 + pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
6489 +
6490 + /* if ((omode & S_IWUGO) == 0)
6491 + pSMB->FileAttributes |= ATTR_READONLY;*/
6492 + /* Above line causes problems due to vfs splitting create into two
6493 + pieces - need to set mode after file created not while it is
6494 + being created */
6495 + pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
6496 + pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
6497 + pSMB->CreateDisposition = cpu_to_le32(openDisposition);
6498 + pSMB->CreateOptions = cpu_to_le32(create_options);
6499 + pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
6500 + pSMB->SecurityFlags =
6501 + cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
6502 +
6503 + pSMB->ByteCount += name_len;
6504 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6505 +
6506 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6507 + /* long_op set to 1 to allow for oplock break timeouts */
6508 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6509 + (struct smb_hdr *) pSMBr, &bytes_returned, 1);
6510 + if (rc) {
6511 + cFYI(1, ("Error in Open = %d", rc));
6512 + } else {
6513 + *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
6514 + *netfid = pSMBr->Fid; /* cifs fid stays in le */
6515 + /* Let caller know file was created so we can set the mode. */
6516 + /* Do we care about the CreateAction in any other cases? */
6517 + if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
6518 + *pOplock |= CIFS_CREATE_ACTION;
6519 + if(pfile_info) {
6520 + memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
6521 + 36 /* CreationTime to Attributes */);
6522 + /* the file_info buf is endian converted by caller */
6523 + pfile_info->AllocationSize = pSMBr->AllocationSize;
6524 + pfile_info->EndOfFile = pSMBr->EndOfFile;
6525 + pfile_info->NumberOfLinks = cpu_to_le32(1);
6526 + }
6527 +
6528 +#ifdef CONFIG_CIFS_STATS
6529 + atomic_inc(&tcon->num_opens);
6530 +#endif
6531 + }
6532 + if (pSMB)
6533 + cifs_buf_release(pSMB);
6534 + if (rc == -EAGAIN)
6535 + goto openRetry;
6536 + return rc;
6537 +}
6538 +
6539 +/* If no buffer passed in, then caller wants to do the copy
6540 + as in the case of readpages so the SMB buffer must be
6541 + freed by the caller */
6542 +
6543 +int
6544 +CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
6545 + const int netfid, const unsigned int count,
6546 + const __u64 lseek, unsigned int *nbytes, char **buf)
6547 +{
6548 + int rc = -EACCES;
6549 + READ_REQ *pSMB = NULL;
6550 + READ_RSP *pSMBr = NULL;
6551 + char *pReadData = NULL;
6552 + int bytes_returned;
6553 +
6554 + *nbytes = 0;
6555 + rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
6556 + (void **) &pSMBr);
6557 + if (rc)
6558 + return rc;
6559 +
6560 + /* tcon and ses pointer are checked in smb_init */
6561 + if (tcon->ses->server == NULL)
6562 + return -ECONNABORTED;
6563 +
6564 + pSMB->AndXCommand = 0xFF; /* none */
6565 + pSMB->Fid = netfid;
6566 + pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
6567 + pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
6568 + pSMB->Remaining = 0;
6569 + pSMB->MaxCount = cpu_to_le16(count);
6570 + pSMB->MaxCountHigh = 0;
6571 + pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
6572 +
6573 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6574 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6575 + if (rc) {
6576 + cERROR(1, ("Send error in read = %d", rc));
6577 + } else {
6578 + pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
6579 + *nbytes = pSMBr->DataLength;
6580 + /*check that DataLength would not go beyond end of SMB */
6581 + if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
6582 + || (pSMBr->DataLength > count)) {
6583 + cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
6584 + rc = -EIO;
6585 + *nbytes = 0;
6586 + } else {
6587 + pReadData =
6588 + (char *) (&pSMBr->hdr.Protocol) +
6589 + le16_to_cpu(pSMBr->DataOffset);
6590 +/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
6591 + cERROR(1,("Faulting on read rc = %d",rc));
6592 + rc = -EFAULT;
6593 + }*/ /* can not use copy_to_user when using page cache*/
6594 + if(*buf)
6595 + memcpy(*buf,pReadData,pSMBr->DataLength);
6596 + }
6597 + }
6598 + if (pSMB) {
6599 + if(*buf)
6600 + cifs_buf_release(pSMB);
6601 + else
6602 + *buf = (char *)pSMB;
6603 + }
6604 +
6605 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6606 + since file handle passed in no longer valid */
6607 + return rc;
6608 +}
6609 +
6610 +int
6611 +CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
6612 + const int netfid, const unsigned int count,
6613 + const __u64 offset, unsigned int *nbytes, const char *buf,
6614 + const int long_op)
6615 +{
6616 + int rc = -EACCES;
6617 + WRITE_REQ *pSMB = NULL;
6618 + WRITE_RSP *pSMBr = NULL;
6619 + int bytes_returned;
6620 +
6621 + rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
6622 + (void **) &pSMBr);
6623 + if (rc)
6624 + return rc;
6625 + /* tcon and ses pointer are checked in smb_init */
6626 + if (tcon->ses->server == NULL)
6627 + return -ECONNABORTED;
6628 +
6629 + pSMB->AndXCommand = 0xFF; /* none */
6630 + pSMB->Fid = netfid;
6631 + pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
6632 + pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
6633 + pSMB->Remaining = 0;
6634 + if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
6635 + pSMB->DataLengthLow =
6636 + (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
6637 + else
6638 + pSMB->DataLengthLow = count;
6639 + pSMB->DataLengthHigh = 0;
6640 + pSMB->DataOffset =
6641 + cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
6642 +
6643 + memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
6644 +
6645 + pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
6646 + pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
6647 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6648 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6649 +
6650 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6651 + (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
6652 + if (rc) {
6653 + cFYI(1, ("Send error in write = %d", rc));
6654 + *nbytes = 0;
6655 + } else
6656 + *nbytes = le16_to_cpu(pSMBr->Count);
6657 +
6658 + if (pSMB)
6659 + cifs_buf_release(pSMB);
6660 +
6661 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6662 + since file handle passed in no longer valid */
6663 +
6664 + return rc;
6665 +}
6666 +
6667 +int
6668 +CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
6669 + const __u16 smb_file_id, const __u64 len,
6670 + const __u64 offset, const __u32 numUnlock,
6671 + const __u32 numLock, const __u8 lockType, const int waitFlag)
6672 +{
6673 + int rc = 0;
6674 + LOCK_REQ *pSMB = NULL;
6675 + LOCK_RSP *pSMBr = NULL;
6676 + int bytes_returned;
6677 + int timeout = 0;
6678 + __u64 temp;
6679 +
6680 + cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
6681 + rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
6682 + (void **) &pSMBr);
6683 + if (rc)
6684 + return rc;
6685 +
6686 + if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
6687 + timeout = -1; /* no response expected */
6688 + pSMB->Timeout = 0;
6689 + } else if (waitFlag == TRUE) {
6690 + timeout = 3; /* blocking operation, no timeout */
6691 + pSMB->Timeout = -1; /* blocking - do not time out */
6692 + } else {
6693 + pSMB->Timeout = 0;
6694 + }
6695 +
6696 + pSMB->NumberOfLocks = cpu_to_le32(numLock);
6697 + pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
6698 + pSMB->LockType = lockType;
6699 + pSMB->AndXCommand = 0xFF; /* none */
6700 + pSMB->Fid = smb_file_id; /* netfid stays le */
6701 +
6702 + if(numLock != 0) {
6703 + pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
6704 + /* BB where to store pid high? */
6705 + temp = cpu_to_le64(len);
6706 + pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
6707 + pSMB->Locks[0].LengthHigh = (__u32)(temp>>32);
6708 + temp = cpu_to_le64(offset);
6709 + pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
6710 + pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
6711 + pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
6712 + } else {
6713 + /* oplock break */
6714 + pSMB->ByteCount = 0;
6715 + }
6716 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6717 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6718 +
6719 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6720 + (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
6721 +
6722 + if (rc) {
6723 + cFYI(1, ("Send error in Lock = %d", rc));
6724 + }
6725 + if (pSMB)
6726 + cifs_buf_release(pSMB);
6727 +
6728 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6729 + since file handle passed in no longer valid */
6730 + return rc;
6731 +}
6732 +
6733 +int
6734 +CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
6735 +{
6736 + int rc = 0;
6737 + CLOSE_REQ *pSMB = NULL;
6738 + CLOSE_RSP *pSMBr = NULL;
6739 + int bytes_returned;
6740 + cFYI(1, ("In CIFSSMBClose"));
6741 +
6742 +/* do not retry on dead session on close */
6743 + rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
6744 + (void **) &pSMBr);
6745 + if(rc == -EAGAIN)
6746 + return 0;
6747 + if (rc)
6748 + return rc;
6749 +
6750 + pSMB->FileID = (__u16) smb_file_id;
6751 + pSMB->LastWriteTime = 0;
6752 + pSMB->ByteCount = 0;
6753 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6754 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6755 + if (rc) {
6756 + if(rc!=-EINTR) {
6757 + /* EINTR is expected when user ctl-c to kill app */
6758 + cERROR(1, ("Send error in Close = %d", rc));
6759 + }
6760 + }
6761 + if (pSMB)
6762 + cifs_buf_release(pSMB);
6763 +
6764 + /* Since session is dead, file will be closed on server already */
6765 + if(rc == -EAGAIN)
6766 + rc = 0;
6767 +
6768 + return rc;
6769 +}
6770 +
6771 +int
6772 +CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
6773 + const char *fromName, const char *toName,
6774 + const struct nls_table *nls_codepage)
6775 +{
6776 + int rc = 0;
6777 + RENAME_REQ *pSMB = NULL;
6778 + RENAME_RSP *pSMBr = NULL;
6779 + int bytes_returned;
6780 + int name_len, name_len2;
6781 +
6782 + cFYI(1, ("In CIFSSMBRename"));
6783 +renameRetry:
6784 + rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
6785 + (void **) &pSMBr);
6786 + if (rc)
6787 + return rc;
6788 +
6789 + pSMB->BufferFormat = 0x04;
6790 + pSMB->SearchAttributes =
6791 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
6792 + ATTR_DIRECTORY);
6793 +
6794 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6795 + name_len =
6796 + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
6797 + /* find define for this maxpathcomponent */
6798 + , nls_codepage);
6799 + name_len++; /* trailing null */
6800 + name_len *= 2;
6801 + pSMB->OldFileName[name_len] = 0x04; /* pad */
6802 + /* protocol requires ASCII signature byte on Unicode string */
6803 + pSMB->OldFileName[name_len + 1] = 0x00;
6804 + name_len2 =
6805 + cifs_strtoUCS((wchar_t *) & pSMB->
6806 + OldFileName[name_len + 2], toName, 530,
6807 + nls_codepage);
6808 + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
6809 + name_len2 *= 2; /* convert to bytes */
6810 + } else { /* BB improve the check for buffer overruns BB */
6811 + name_len = strnlen(fromName, 530);
6812 + name_len++; /* trailing null */
6813 + strncpy(pSMB->OldFileName, fromName, name_len);
6814 + name_len2 = strnlen(toName, 530);
6815 + name_len2++; /* trailing null */
6816 + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
6817 + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
6818 + name_len2++; /* trailing null */
6819 + name_len2++; /* signature byte */
6820 + }
6821 +
6822 + pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
6823 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6824 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6825 +
6826 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6827 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6828 + if (rc) {
6829 + cFYI(1, ("Send error in rename = %d", rc));
6830 + }
6831 +
6832 +#ifdef CONFIG_CIFS_STATS
6833 + else {
6834 + atomic_inc(&tcon->num_renames);
6835 + }
6836 +#endif
6837 +
6838 + if (pSMB)
6839 + cifs_buf_release(pSMB);
6840 +
6841 + if (rc == -EAGAIN)
6842 + goto renameRetry;
6843 +
6844 + return rc;
6845 +}
6846 +
6847 +int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
6848 + int netfid, char * target_name, const struct nls_table * nls_codepage)
6849 +{
6850 + struct smb_com_transaction2_sfi_req *pSMB = NULL;
6851 + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
6852 + struct set_file_rename * rename_info;
6853 + char *data_offset;
6854 + char dummy_string[30];
6855 + int rc = 0;
6856 + int bytes_returned = 0;
6857 + int len_of_str;
6858 +
6859 + cFYI(1, ("Rename to File by handle"));
6860 + rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
6861 + (void **) &pSMBr);
6862 + if (rc)
6863 + return rc;
6864 +
6865 + pSMB->ParameterCount = 6;
6866 + pSMB->MaxSetupCount = 0;
6867 + pSMB->Reserved = 0;
6868 + pSMB->Flags = 0;
6869 + pSMB->Timeout = 0;
6870 + pSMB->Reserved2 = 0;
6871 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
6872 + Fid) - 4;
6873 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
6874 +
6875 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
6876 + rename_info = (struct set_file_rename *) data_offset;
6877 + pSMB->MaxParameterCount = cpu_to_le16(2);
6878 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
6879 + pSMB->SetupCount = 1;
6880 + pSMB->Reserved3 = 0;
6881 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6882 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
6883 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
6884 + pSMB->TotalParameterCount = pSMB->ParameterCount;
6885 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
6886 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
6887 + /* construct random name ".cifs_tmp<inodenum><mid>" */
6888 + rename_info->overwrite = cpu_to_le32(1);
6889 + rename_info->root_fid = 0;
6890 + /* unicode only call */
6891 + if(target_name == NULL) {
6892 + sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
6893 + len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
6894 + } else {
6895 + len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
6896 + }
6897 + rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
6898 + pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
6899 + pSMB->ByteCount += pSMB->DataCount;
6900 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
6901 + pSMB->TotalDataCount = pSMB->DataCount;
6902 + pSMB->Fid = netfid;
6903 + pSMB->InformationLevel =
6904 + cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
6905 + pSMB->Reserved4 = 0;
6906 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6907 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6908 + rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
6909 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6910 + if (rc) {
6911 + cFYI(1,("Send error in Rename (by file handle) = %d", rc));
6912 + }
6913 +#ifdef CONFIG_CIFS_STATS
6914 + else {
6915 + atomic_inc(&pTcon->num_t2renames);
6916 + }
6917 +#endif
6918 + if (pSMB)
6919 + cifs_buf_release(pSMB);
6920 +
6921 + /* Note: On -EAGAIN error only caller can retry on handle based calls
6922 + since file handle passed in no longer valid */
6923 +
6924 + return rc;
6925 +}
6926 +
6927 +int
6928 +CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
6929 + const __u16 target_tid, const char *toName, const int flags,
6930 + const struct nls_table *nls_codepage)
6931 +{
6932 + int rc = 0;
6933 + COPY_REQ *pSMB = NULL;
6934 + COPY_RSP *pSMBr = NULL;
6935 + int bytes_returned;
6936 + int name_len, name_len2;
6937 +
6938 + cFYI(1, ("In CIFSSMBCopy"));
6939 +copyRetry:
6940 + rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
6941 + (void **) &pSMBr);
6942 + if (rc)
6943 + return rc;
6944 +
6945 + pSMB->BufferFormat = 0x04;
6946 + pSMB->Tid2 = target_tid;
6947 +
6948 + if(flags & COPY_TREE)
6949 + pSMB->Flags |= COPY_TREE;
6950 + pSMB->Flags = cpu_to_le16(pSMB->Flags);
6951 +
6952 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6953 + name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
6954 + fromName,
6955 + 530 /* find define for this maxpathcomponent */,
6956 + nls_codepage);
6957 + name_len++; /* trailing null */
6958 + name_len *= 2;
6959 + pSMB->OldFileName[name_len] = 0x04; /* pad */
6960 + /* protocol requires ASCII signature byte on Unicode string */
6961 + pSMB->OldFileName[name_len + 1] = 0x00;
6962 + name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
6963 + OldFileName[name_len + 2], toName, 530,
6964 + nls_codepage);
6965 + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
6966 + name_len2 *= 2; /* convert to bytes */
6967 + } else { /* BB improve the check for buffer overruns BB */
6968 + name_len = strnlen(fromName, 530);
6969 + name_len++; /* trailing null */
6970 + strncpy(pSMB->OldFileName, fromName, name_len);
6971 + name_len2 = strnlen(toName, 530);
6972 + name_len2++; /* trailing null */
6973 + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
6974 + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
6975 + name_len2++; /* trailing null */
6976 + name_len2++; /* signature byte */
6977 + }
6978 +
6979 + pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
6980 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
6981 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
6982 +
6983 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6984 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6985 + if (rc) {
6986 + cFYI(1, ("Send error in copy = %d with %d files copied",
6987 + rc, pSMBr->CopyCount));
6988 + }
6989 + if (pSMB)
6990 + cifs_buf_release(pSMB);
6991 +
6992 + if (rc == -EAGAIN)
6993 + goto copyRetry;
6994 +
6995 + return rc;
6996 +}
6997 +
6998 +int
6999 +CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
7000 + const char *fromName, const char *toName,
7001 + const struct nls_table *nls_codepage)
7002 +{
7003 + TRANSACTION2_SPI_REQ *pSMB = NULL;
7004 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
7005 + char *data_offset;
7006 + int name_len;
7007 + int name_len_target;
7008 + int rc = 0;
7009 + int bytes_returned = 0;
7010 +
7011 + cFYI(1, ("In Symlink Unix style"));
7012 +createSymLinkRetry:
7013 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7014 + (void **) &pSMBr);
7015 + if (rc)
7016 + return rc;
7017 +
7018 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7019 + name_len =
7020 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
7021 + /* find define for this maxpathcomponent */
7022 + , nls_codepage);
7023 + name_len++; /* trailing null */
7024 + name_len *= 2;
7025 +
7026 + } else { /* BB improve the check for buffer overruns BB */
7027 + name_len = strnlen(fromName, 530);
7028 + name_len++; /* trailing null */
7029 + strncpy(pSMB->FileName, fromName, name_len);
7030 + }
7031 + pSMB->ParameterCount = 6 + name_len;
7032 + pSMB->MaxSetupCount = 0;
7033 + pSMB->Reserved = 0;
7034 + pSMB->Flags = 0;
7035 + pSMB->Timeout = 0;
7036 + pSMB->Reserved2 = 0;
7037 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
7038 + InformationLevel) - 4;
7039 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
7040 +
7041 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
7042 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7043 + name_len_target =
7044 + cifs_strtoUCS((wchar_t *) data_offset, toName, 530
7045 + /* find define for this maxpathcomponent */
7046 + , nls_codepage);
7047 + name_len_target++; /* trailing null */
7048 + name_len_target *= 2;
7049 + } else { /* BB improve the check for buffer overruns BB */
7050 + name_len_target = strnlen(toName, 530);
7051 + name_len_target++; /* trailing null */
7052 + strncpy(data_offset, toName, name_len_target);
7053 + }
7054 +
7055 + pSMB->DataCount = name_len_target;
7056 + pSMB->MaxParameterCount = cpu_to_le16(2);
7057 + /* BB find exact max on data count below from sess */
7058 + pSMB->MaxDataCount = cpu_to_le16(1000);
7059 + pSMB->SetupCount = 1;
7060 + pSMB->Reserved3 = 0;
7061 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
7062 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
7063 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
7064 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7065 + pSMB->TotalDataCount = pSMB->DataCount;
7066 + pSMB->TotalParameterCount = pSMB->ParameterCount;
7067 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
7068 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
7069 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
7070 + pSMB->Reserved4 = 0;
7071 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7072 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7073 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7074 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7075 + if (rc) {
7076 + cFYI(1,
7077 + ("Send error in SetPathInfo (create symlink) = %d",
7078 + rc));
7079 + }
7080 +
7081 + if (pSMB)
7082 + cifs_buf_release(pSMB);
7083 +
7084 + if (rc == -EAGAIN)
7085 + goto createSymLinkRetry;
7086 +
7087 + return rc;
7088 +}
7089 +
7090 +int
7091 +CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
7092 + const char *fromName, const char *toName,
7093 + const struct nls_table *nls_codepage)
7094 +{
7095 + TRANSACTION2_SPI_REQ *pSMB = NULL;
7096 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
7097 + char *data_offset;
7098 + int name_len;
7099 + int name_len_target;
7100 + int rc = 0;
7101 + int bytes_returned = 0;
7102 +
7103 + cFYI(1, ("In Create Hard link Unix style"));
7104 +createHardLinkRetry:
7105 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7106 + (void **) &pSMBr);
7107 + if (rc)
7108 + return rc;
7109 +
7110 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7111 + name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
7112 + /* find define for this maxpathcomponent */
7113 + , nls_codepage);
7114 + name_len++; /* trailing null */
7115 + name_len *= 2;
7116 +
7117 + } else { /* BB improve the check for buffer overruns BB */
7118 + name_len = strnlen(toName, 530);
7119 + name_len++; /* trailing null */
7120 + strncpy(pSMB->FileName, toName, name_len);
7121 + }
7122 + pSMB->ParameterCount = 6 + name_len;
7123 + pSMB->MaxSetupCount = 0;
7124 + pSMB->Reserved = 0;
7125 + pSMB->Flags = 0;
7126 + pSMB->Timeout = 0;
7127 + pSMB->Reserved2 = 0;
7128 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
7129 + InformationLevel) - 4;
7130 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
7131 +
7132 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
7133 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7134 + name_len_target =
7135 + cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
7136 + /* find define for this maxpathcomponent */
7137 + , nls_codepage);
7138 + name_len_target++; /* trailing null */
7139 + name_len_target *= 2;
7140 + } else { /* BB improve the check for buffer overruns BB */
7141 + name_len_target = strnlen(fromName, 530);
7142 + name_len_target++; /* trailing null */
7143 + strncpy(data_offset, fromName, name_len_target);
7144 + }
7145 +
7146 + pSMB->DataCount = name_len_target;
7147 + pSMB->MaxParameterCount = cpu_to_le16(2);
7148 + /* BB find exact max on data count below from sess*/
7149 + pSMB->MaxDataCount = cpu_to_le16(1000);
7150 + pSMB->SetupCount = 1;
7151 + pSMB->Reserved3 = 0;
7152 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
7153 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
7154 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7155 + pSMB->TotalParameterCount = pSMB->ParameterCount;
7156 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
7157 + pSMB->TotalDataCount = pSMB->DataCount;
7158 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
7159 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
7160 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
7161 + pSMB->Reserved4 = 0;
7162 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7163 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7164 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7165 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7166 + if (rc) {
7167 + cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
7168 + }
7169 +
7170 + if (pSMB)
7171 + cifs_buf_release(pSMB);
7172 + if (rc == -EAGAIN)
7173 + goto createHardLinkRetry;
7174 +
7175 + return rc;
7176 +}
7177 +
7178 +int
7179 +CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
7180 + const char *fromName, const char *toName,
7181 + const struct nls_table *nls_codepage)
7182 +{
7183 + int rc = 0;
7184 + NT_RENAME_REQ *pSMB = NULL;
7185 + RENAME_RSP *pSMBr = NULL;
7186 + int bytes_returned;
7187 + int name_len, name_len2;
7188 +
7189 + cFYI(1, ("In CIFSCreateHardLink"));
7190 +winCreateHardLinkRetry:
7191 +
7192 + rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
7193 + (void **) &pSMBr);
7194 + if (rc)
7195 + return rc;
7196 +
7197 + pSMB->SearchAttributes =
7198 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7199 + ATTR_DIRECTORY);
7200 + pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
7201 + pSMB->ClusterCount = 0;
7202 +
7203 + pSMB->BufferFormat = 0x04;
7204 +
7205 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7206 + name_len =
7207 + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
7208 + /* find define for this maxpathcomponent */
7209 + , nls_codepage);
7210 + name_len++; /* trailing null */
7211 + name_len *= 2;
7212 + pSMB->OldFileName[name_len] = 0; /* pad */
7213 + pSMB->OldFileName[name_len + 1] = 0x04;
7214 + name_len2 =
7215 + cifs_strtoUCS((wchar_t *) & pSMB->
7216 + OldFileName[name_len + 2], toName, 530,
7217 + nls_codepage);
7218 + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
7219 + name_len2 *= 2; /* convert to bytes */
7220 + } else { /* BB improve the check for buffer overruns BB */
7221 + name_len = strnlen(fromName, 530);
7222 + name_len++; /* trailing null */
7223 + strncpy(pSMB->OldFileName, fromName, name_len);
7224 + name_len2 = strnlen(toName, 530);
7225 + name_len2++; /* trailing null */
7226 + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
7227 + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
7228 + name_len2++; /* trailing null */
7229 + name_len2++; /* signature byte */
7230 + }
7231 +
7232 + pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
7233 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7234 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7235 +
7236 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7237 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7238 + if (rc) {
7239 + cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
7240 + }
7241 + if (pSMB)
7242 + cifs_buf_release(pSMB);
7243 + if (rc == -EAGAIN)
7244 + goto winCreateHardLinkRetry;
7245 +
7246 + return rc;
7247 +}
7248 +
7249 +int
7250 +CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
7251 + const unsigned char *searchName,
7252 + char *symlinkinfo, const int buflen,
7253 + const struct nls_table *nls_codepage)
7254 +{
7255 +/* SMB_QUERY_FILE_UNIX_LINK */
7256 + TRANSACTION2_QPI_REQ *pSMB = NULL;
7257 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
7258 + int rc = 0;
7259 + int bytes_returned;
7260 + int name_len;
7261 +
7262 + cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
7263 +
7264 +querySymLinkRetry:
7265 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7266 + (void **) &pSMBr);
7267 + if (rc)
7268 + return rc;
7269 +
7270 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7271 + name_len =
7272 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7273 + /* find define for this maxpathcomponent */
7274 + , nls_codepage);
7275 + name_len++; /* trailing null */
7276 + name_len *= 2;
7277 + } else { /* BB improve the check for buffer overruns BB */
7278 + name_len = strnlen(searchName, 530);
7279 + name_len++; /* trailing null */
7280 + strncpy(pSMB->FileName, searchName, name_len);
7281 + }
7282 +
7283 + pSMB->TotalParameterCount =
7284 + 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
7285 + pSMB->TotalDataCount = 0;
7286 + pSMB->MaxParameterCount = cpu_to_le16(2);
7287 + /* BB find exact max data count below from sess structure BB */
7288 + pSMB->MaxDataCount = cpu_to_le16(4000);
7289 + pSMB->MaxSetupCount = 0;
7290 + pSMB->Reserved = 0;
7291 + pSMB->Flags = 0;
7292 + pSMB->Timeout = 0;
7293 + pSMB->Reserved2 = 0;
7294 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7295 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7296 + pSMB->DataCount = 0;
7297 + pSMB->DataOffset = 0;
7298 + pSMB->SetupCount = 1;
7299 + pSMB->Reserved3 = 0;
7300 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7301 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7302 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7303 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7304 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
7305 + pSMB->Reserved4 = 0;
7306 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7307 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7308 +
7309 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7310 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7311 + if (rc) {
7312 + cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
7313 + } else { /* decode response */
7314 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7315 + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
7316 + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
7317 + /* BB also check enough total bytes returned */
7318 + rc = -EIO; /* bad smb */
7319 + else {
7320 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
7321 + name_len = UniStrnlen((wchar_t *) ((char *)
7322 + &pSMBr->hdr.Protocol +pSMBr->DataOffset),
7323 + min_t(const int, buflen,pSMBr->DataCount) / 2);
7324 + cifs_strfromUCS_le(symlinkinfo,
7325 + (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
7326 + pSMBr->DataOffset),
7327 + name_len, nls_codepage);
7328 + } else {
7329 + strncpy(symlinkinfo,
7330 + (char *) &pSMBr->hdr.Protocol +
7331 + pSMBr->DataOffset,
7332 + min_t(const int, buflen, pSMBr->DataCount));
7333 + }
7334 + symlinkinfo[buflen] = 0;
7335 + /* just in case so calling code does not go off the end of buffer */
7336 + }
7337 + }
7338 + if (pSMB)
7339 + cifs_buf_release(pSMB);
7340 + if (rc == -EAGAIN)
7341 + goto querySymLinkRetry;
7342 + return rc;
7343 +}
7344 +
7345 +
7346 +
7347 +int
7348 +CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
7349 + const unsigned char *searchName,
7350 + char *symlinkinfo, const int buflen,__u16 fid,
7351 + const struct nls_table *nls_codepage)
7352 +{
7353 + int rc = 0;
7354 + int bytes_returned;
7355 + int name_len;
7356 + struct smb_com_transaction_ioctl_req * pSMB;
7357 + struct smb_com_transaction_ioctl_rsp * pSMBr;
7358 +
7359 + cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
7360 + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
7361 + (void **) &pSMBr);
7362 + if (rc)
7363 + return rc;
7364 +
7365 + pSMB->TotalParameterCount = 0 ;
7366 + pSMB->TotalDataCount = 0;
7367 + pSMB->MaxParameterCount = cpu_to_le32(2);
7368 + /* BB find exact data count max from sess structure BB */
7369 + pSMB->MaxDataCount = cpu_to_le32(4000);
7370 + pSMB->MaxSetupCount = 4;
7371 + pSMB->Reserved = 0;
7372 + pSMB->ParameterOffset = 0;
7373 + pSMB->DataCount = 0;
7374 + pSMB->DataOffset = 0;
7375 + pSMB->SetupCount = 4;
7376 + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
7377 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7378 + pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
7379 + pSMB->IsFsctl = 1; /* FSCTL */
7380 + pSMB->IsRootFlag = 0;
7381 + pSMB->Fid = fid; /* file handle always le */
7382 + pSMB->ByteCount = 0;
7383 +
7384 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7385 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7386 + if (rc) {
7387 + cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
7388 + } else { /* decode response */
7389 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7390 + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
7391 + if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
7392 + /* BB also check enough total bytes returned */
7393 + rc = -EIO; /* bad smb */
7394 + else {
7395 + if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
7396 + /* could also validate reparse tag && better check name length */
7397 + struct reparse_data * reparse_buf = (struct reparse_data *)
7398 + ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
7399 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
7400 + name_len = UniStrnlen((wchar_t *)
7401 + (reparse_buf->LinkNamesBuf +
7402 + reparse_buf->TargetNameOffset),
7403 + min(buflen/2, reparse_buf->TargetNameLen / 2));
7404 + cifs_strfromUCS_le(symlinkinfo,
7405 + (wchar_t *) (reparse_buf->LinkNamesBuf +
7406 + reparse_buf->TargetNameOffset),
7407 + name_len, nls_codepage);
7408 + } else { /* ASCII names */
7409 + strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
7410 + reparse_buf->TargetNameOffset,
7411 + min_t(const int, buflen, reparse_buf->TargetNameLen));
7412 + }
7413 + } else {
7414 + rc = -EIO;
7415 + cFYI(1,("Invalid return data count on get reparse info ioctl"));
7416 + }
7417 + symlinkinfo[buflen] = 0; /* just in case so the caller
7418 + does not go off the end of the buffer */
7419 + cFYI(1,("readlink result - %s ",symlinkinfo));
7420 + }
7421 + }
7422 + if (pSMB)
7423 + cifs_buf_release(pSMB);
7424 +
7425 + /* Note: On -EAGAIN error only caller can retry on handle based calls
7426 + since file handle passed in no longer valid */
7427 +
7428 + return rc;
7429 +}
7430 +
7431 +int
7432 +CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
7433 + const unsigned char *searchName,
7434 + FILE_ALL_INFO * pFindData,
7435 + const struct nls_table *nls_codepage)
7436 +{
7437 +/* level 263 SMB_QUERY_FILE_ALL_INFO */
7438 + TRANSACTION2_QPI_REQ *pSMB = NULL;
7439 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
7440 + int rc = 0;
7441 + int bytes_returned;
7442 + int name_len;
7443 +
7444 + cFYI(1, ("In QPathInfo path %s", searchName));
7445 +QPathInfoRetry:
7446 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7447 + (void **) &pSMBr);
7448 + if (rc)
7449 + return rc;
7450 +
7451 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7452 + name_len =
7453 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7454 + /* find define for this maxpathcomponent */
7455 + , nls_codepage);
7456 + name_len++; /* trailing null */
7457 + name_len *= 2;
7458 + } else { /* BB improve the check for buffer overruns BB */
7459 + name_len = strnlen(searchName, 530);
7460 + name_len++; /* trailing null */
7461 + strncpy(pSMB->FileName, searchName, name_len);
7462 + }
7463 +
7464 + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
7465 + name_len /* includes null */ ;
7466 + pSMB->TotalDataCount = 0;
7467 + pSMB->MaxParameterCount = cpu_to_le16(2);
7468 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7469 + pSMB->MaxSetupCount = 0;
7470 + pSMB->Reserved = 0;
7471 + pSMB->Flags = 0;
7472 + pSMB->Timeout = 0;
7473 + pSMB->Reserved2 = 0;
7474 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7475 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7476 + pSMB->DataCount = 0;
7477 + pSMB->DataOffset = 0;
7478 + pSMB->SetupCount = 1;
7479 + pSMB->Reserved3 = 0;
7480 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7481 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7482 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7483 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7484 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
7485 + pSMB->Reserved4 = 0;
7486 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7487 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7488 +
7489 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7490 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7491 + if (rc) {
7492 + cFYI(1, ("Send error in QPathInfo = %d", rc));
7493 + } else { /* decode response */
7494 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7495 + /* BB also check enough total bytes returned */
7496 + /* BB we need to improve the validity checking
7497 + of these trans2 responses */
7498 + if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
7499 + rc = -EIO; /* bad smb */
7500 + else if (pFindData){
7501 + memcpy((char *) pFindData,
7502 + (char *) &pSMBr->hdr.Protocol +
7503 + pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
7504 + } else
7505 + rc = -ENOMEM;
7506 + }
7507 + if (pSMB)
7508 + cifs_buf_release(pSMB);
7509 + if (rc == -EAGAIN)
7510 + goto QPathInfoRetry;
7511 +
7512 + return rc;
7513 +}
7514 +
7515 +int
7516 +CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
7517 + const unsigned char *searchName,
7518 + FILE_UNIX_BASIC_INFO * pFindData,
7519 + const struct nls_table *nls_codepage)
7520 +{
7521 +/* SMB_QUERY_FILE_UNIX_BASIC */
7522 + TRANSACTION2_QPI_REQ *pSMB = NULL;
7523 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
7524 + int rc = 0;
7525 + int bytes_returned = 0;
7526 + int name_len;
7527 +
7528 + cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
7529 +UnixQPathInfoRetry:
7530 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7531 + (void **) &pSMBr);
7532 + if (rc)
7533 + return rc;
7534 +
7535 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7536 + name_len =
7537 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7538 + /* find define for this maxpathcomponent */
7539 + , nls_codepage);
7540 + name_len++; /* trailing null */
7541 + name_len *= 2;
7542 + } else { /* BB improve the check for buffer overruns BB */
7543 + name_len = strnlen(searchName, 530);
7544 + name_len++; /* trailing null */
7545 + strncpy(pSMB->FileName, searchName, name_len);
7546 + }
7547 +
7548 + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
7549 + name_len /* includes null */ ;
7550 + pSMB->TotalDataCount = 0;
7551 + pSMB->MaxParameterCount = cpu_to_le16(2);
7552 + /* BB find exact max SMB PDU from sess structure BB */
7553 + pSMB->MaxDataCount = cpu_to_le16(4000);
7554 + pSMB->MaxSetupCount = 0;
7555 + pSMB->Reserved = 0;
7556 + pSMB->Flags = 0;
7557 + pSMB->Timeout = 0;
7558 + pSMB->Reserved2 = 0;
7559 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7560 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
7561 + pSMB->DataCount = 0;
7562 + pSMB->DataOffset = 0;
7563 + pSMB->SetupCount = 1;
7564 + pSMB->Reserved3 = 0;
7565 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
7566 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7567 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7568 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7569 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
7570 + pSMB->Reserved4 = 0;
7571 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7572 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7573 +
7574 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7575 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7576 + if (rc) {
7577 + cFYI(1, ("Send error in QPathInfo = %d", rc));
7578 + } else { /* decode response */
7579 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
7580 + /* BB also check if enough total bytes returned */
7581 + if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
7582 + (pSMBr->DataOffset > 512) ||
7583 + (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
7584 + cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
7585 + (int)pSMBr->DataOffset,bytes_returned));
7586 + rc = -EIO; /* bad smb */
7587 + } else {
7588 + memcpy((char *) pFindData,
7589 + (char *) &pSMBr->hdr.Protocol +
7590 + pSMBr->DataOffset,
7591 + sizeof (FILE_UNIX_BASIC_INFO));
7592 + }
7593 + }
7594 + if (pSMB)
7595 + cifs_buf_release(pSMB);
7596 + if (rc == -EAGAIN)
7597 + goto UnixQPathInfoRetry;
7598 +
7599 + return rc;
7600 +}
7601 +
7602 +int
7603 +CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
7604 + const char *searchName, FILE_ALL_INFO * findData,
7605 + const struct nls_table *nls_codepage)
7606 +{
7607 +/* level 257 SMB_ */
7608 + TRANSACTION2_FFIRST_REQ *pSMB = NULL;
7609 + TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
7610 + int rc = 0;
7611 + int bytes_returned;
7612 + int name_len;
7613 +
7614 + cFYI(1, ("In FindUnique"));
7615 +findUniqueRetry:
7616 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7617 + (void **) &pSMBr);
7618 + if (rc)
7619 + return rc;
7620 +
7621 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7622 + name_len =
7623 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7624 + /* find define for this maxpathcomponent */
7625 + , nls_codepage);
7626 + name_len++; /* trailing null */
7627 + name_len *= 2;
7628 + } else { /* BB improve the check for buffer overruns BB */
7629 + name_len = strnlen(searchName, 530);
7630 + name_len++; /* trailing null */
7631 + strncpy(pSMB->FileName, searchName, name_len);
7632 + }
7633 +
7634 + pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
7635 + pSMB->TotalDataCount = 0; /* no EAs */
7636 + pSMB->MaxParameterCount = cpu_to_le16(2);
7637 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7638 + pSMB->MaxSetupCount = 0;
7639 + pSMB->Reserved = 0;
7640 + pSMB->Flags = 0;
7641 + pSMB->Timeout = 0;
7642 + pSMB->Reserved2 = 0;
7643 + pSMB->ParameterOffset = cpu_to_le16(
7644 + offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
7645 + pSMB->DataCount = 0;
7646 + pSMB->DataOffset = 0;
7647 + pSMB->SetupCount = 1; /* one byte, no need to le convert */
7648 + pSMB->Reserved3 = 0;
7649 + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
7650 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7651 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
7652 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7653 + pSMB->SearchAttributes =
7654 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7655 + ATTR_DIRECTORY);
7656 + pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
7657 + pSMB->SearchFlags = cpu_to_le16(1);
7658 + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7659 + pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
7660 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7661 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7662 +
7663 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7664 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7665 +
7666 + if (rc) {
7667 + cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
7668 + } else { /* decode response */
7669 +
7670 + /* BB fill in */
7671 + }
7672 + if (pSMB)
7673 + cifs_buf_release(pSMB);
7674 + if (rc == -EAGAIN)
7675 + goto findUniqueRetry;
7676 +
7677 + return rc;
7678 +}
7679 +
7680 +int
7681 +CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
7682 + const char *searchName, FILE_DIRECTORY_INFO * findData,
7683 + T2_FFIRST_RSP_PARMS * findParms,
7684 + const struct nls_table *nls_codepage, int *pUnicodeFlag,
7685 + int *pUnixFlag)
7686 +{
7687 +/* level 257 SMB_ */
7688 + TRANSACTION2_FFIRST_REQ *pSMB = NULL;
7689 + TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
7690 + char *response_data;
7691 + int rc = 0;
7692 + int bytes_returned;
7693 + int name_len;
7694 +
7695 + cFYI(1, ("In FindFirst"));
7696 +findFirstRetry:
7697 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7698 + (void **) &pSMBr);
7699 + if (rc)
7700 + return rc;
7701 +
7702 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
7703 + name_len =
7704 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
7705 + /* find define for this maxpathcomponent */
7706 + , nls_codepage);
7707 + name_len++; /* trailing null */
7708 + name_len *= 2;
7709 + } else { /* BB improve the check for buffer overruns BB */
7710 + name_len = strnlen(searchName, 530);
7711 + name_len++; /* trailing null */
7712 + strncpy(pSMB->FileName, searchName, name_len);
7713 + }
7714 +
7715 + pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
7716 + pSMB->TotalDataCount = 0; /* no EAs */
7717 + pSMB->MaxParameterCount = cpu_to_le16(10);
7718 + pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
7719 + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
7720 + pSMB->MaxSetupCount = 0;
7721 + pSMB->Reserved = 0;
7722 + pSMB->Flags = 0;
7723 + pSMB->Timeout = 0;
7724 + pSMB->Reserved2 = 0;
7725 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7726 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7727 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7728 + pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
7729 + smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
7730 + pSMB->DataCount = 0;
7731 + pSMB->DataOffset = 0;
7732 + pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
7733 + pSMB->Reserved3 = 0;
7734 + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
7735 + pSMB->SearchAttributes =
7736 + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
7737 + ATTR_DIRECTORY);
7738 + pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
7739 + pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
7740 +
7741 + /* test for Unix extensions */
7742 + if (tcon->ses->capabilities & CAP_UNIX) {
7743 + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
7744 + *pUnixFlag = TRUE;
7745 + } else {
7746 + pSMB->InformationLevel =
7747 + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7748 + *pUnixFlag = FALSE;
7749 + }
7750 + pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
7751 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7752 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7753 +
7754 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7755 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7756 +
7757 + if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
7758 + cFYI(1, ("Error in FindFirst = %d", rc));
7759 + } else { /* decode response */
7760 + /* BB add safety checks for these memcpys */
7761 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
7762 + *pUnicodeFlag = TRUE;
7763 + else
7764 + *pUnicodeFlag = FALSE;
7765 + memcpy(findParms,
7766 + (char *) &pSMBr->hdr.Protocol +
7767 + le16_to_cpu(pSMBr->ParameterOffset),
7768 + sizeof (T2_FFIRST_RSP_PARMS));
7769 + /* search handle can stay LE and EAoffset not needed so not converted */
7770 + findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
7771 + findParms->LastNameOffset =
7772 + le16_to_cpu(findParms->LastNameOffset);
7773 + findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
7774 + response_data =
7775 + (char *) &pSMBr->hdr.Protocol +
7776 + le16_to_cpu(pSMBr->DataOffset);
7777 + memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
7778 + }
7779 + if (pSMB)
7780 + cifs_buf_release(pSMB);
7781 +
7782 + if (rc == -EAGAIN)
7783 + goto findFirstRetry;
7784 +
7785 + return rc;
7786 +}
7787 +
7788 +int
7789 +CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
7790 + FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
7791 + const __u16 searchHandle, char * resume_file_name, int name_len,
7792 + __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
7793 +{
7794 +/* level 257 SMB_ */
7795 + TRANSACTION2_FNEXT_REQ *pSMB = NULL;
7796 + TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
7797 + char *response_data;
7798 + int rc = 0;
7799 + int bytes_returned;
7800 +
7801 + cFYI(1, ("In FindNext"));
7802 +
7803 + if(resume_file_name == NULL) {
7804 + return -EIO;
7805 + }
7806 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
7807 + (void **) &pSMBr);
7808 + if (rc)
7809 + return rc;
7810 +
7811 + pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
7812 + pSMB->TotalDataCount = 0; /* no EAs */
7813 + pSMB->MaxParameterCount = cpu_to_le16(8);
7814 + pSMB->MaxDataCount =
7815 + cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
7816 + pSMB->MaxSetupCount = 0;
7817 + pSMB->Reserved = 0;
7818 + pSMB->Flags = 0;
7819 + pSMB->Timeout = 0;
7820 + pSMB->Reserved2 = 0;
7821 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7822 + struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
7823 + pSMB->DataCount = 0;
7824 + pSMB->DataOffset = 0;
7825 + pSMB->SetupCount = 1;
7826 + pSMB->Reserved3 = 0;
7827 + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
7828 + pSMB->SearchHandle = searchHandle; /* always kept as le */
7829 + findParms->SearchCount = 0; /* set to zero in case of error */
7830 + pSMB->SearchCount =
7831 + cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
7832 + /* test for Unix extensions */
7833 + if (tcon->ses->capabilities & CAP_UNIX) {
7834 + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
7835 + *pUnixFlag = TRUE;
7836 + } else {
7837 + pSMB->InformationLevel =
7838 + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
7839 + *pUnixFlag = FALSE;
7840 + }
7841 + pSMB->ResumeKey = resume_key;
7842 + pSMB->SearchFlags =
7843 + cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
7844 + /* BB add check to make sure we do not cross end of smb */
7845 + if(name_len < CIFS_MAX_MSGSIZE) {
7846 + memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
7847 + pSMB->ByteCount += name_len;
7848 + }
7849 + pSMB->TotalParameterCount += name_len;
7850 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
7851 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
7852 + pSMB->ParameterCount = pSMB->TotalParameterCount;
7853 + /* BB improve error handling here */
7854 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
7855 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
7856 +
7857 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7858 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7859 +
7860 + if (rc) {
7861 + if (rc == -EBADF)
7862 + rc = 0; /* search probably was closed at end of search above */
7863 + else
7864 + cFYI(1, ("FindNext returned = %d", rc));
7865 + } else { /* decode response */
7866 + /* BB add safety checks for these memcpys */
7867 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
7868 + *pUnicodeFlag = TRUE;
7869 + else
7870 + *pUnicodeFlag = FALSE;
7871 + memcpy(findParms,
7872 + (char *) &pSMBr->hdr.Protocol +
7873 + le16_to_cpu(pSMBr->ParameterOffset),
7874 + sizeof (T2_FNEXT_RSP_PARMS));
7875 + findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
7876 + findParms->LastNameOffset =
7877 + le16_to_cpu(findParms->LastNameOffset);
7878 + findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
7879 + response_data =
7880 + (char *) &pSMBr->hdr.Protocol +
7881 + le16_to_cpu(pSMBr->DataOffset);
7882 + memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
7883 + }
7884 + if (pSMB)
7885 + cifs_buf_release(pSMB);
7886 +
7887 + /* Note: On -EAGAIN error only caller can retry on handle based calls
7888 + since file handle passed in no longer valid */
7889 +
7890 + return rc;
7891 +}
7892 +
7893 +int
7894 +CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
7895 +{
7896 + int rc = 0;
7897 + FINDCLOSE_REQ *pSMB = NULL;
7898 + CLOSE_RSP *pSMBr = NULL;
7899 + int bytes_returned;
7900 +
7901 + cFYI(1, ("In CIFSSMBFindClose"));
7902 + rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
7903 + (void **) &pSMBr);
7904 + /* no sense returning error if session restarted
7905 + file handle has been closed */
7906 + if(rc == -EAGAIN)
7907 + return 0;
7908 + if (rc)
7909 + return rc;
7910 +
7911 + pSMB->FileID = searchHandle;
7912 + pSMB->ByteCount = 0;
7913 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
7914 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
7915 + if (rc) {
7916 + cERROR(1, ("Send error in FindClose = %d", rc));
7917 + }
7918 + if (pSMB)
7919 + cifs_buf_release(pSMB);
7920 +
7921 + /* Since session is dead, search handle closed on server already */
7922 + if (rc == -EAGAIN)
7923 + rc = 0;
7924 +
7925 + return rc;
7926 +}
7927 +
7928 +int
7929 +CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
7930 + const unsigned char *searchName,
7931 + unsigned char **targetUNCs,
7932 + unsigned int *number_of_UNC_in_array,
7933 + const struct nls_table *nls_codepage)
7934 +{
7935 +/* TRANS2_GET_DFS_REFERRAL */
7936 + TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
7937 + TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
7938 + struct dfs_referral_level_3 * referrals = NULL;
7939 + int rc = 0;
7940 + int bytes_returned;
7941 + int name_len;
7942 + unsigned int i;
7943 + char * temp;
7944 + *number_of_UNC_in_array = 0;
7945 + *targetUNCs = NULL;
7946 +
7947 + cFYI(1, ("In GetDFSRefer the path %s", searchName));
7948 + if (ses == NULL)
7949 + return -ENODEV;
7950 +getDFSRetry:
7951 + rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
7952 + (void **) &pSMBr);
7953 + if (rc)
7954 + return rc;
7955 +
7956 + pSMB->hdr.Tid = ses->ipc_tid;
7957 + pSMB->hdr.Uid = ses->Suid;
7958 + if (ses->capabilities & CAP_STATUS32) {
7959 + pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
7960 + }
7961 + if (ses->capabilities & CAP_DFS) {
7962 + pSMB->hdr.Flags2 |= SMBFLG2_DFS;
7963 + }
7964 +
7965 + if (ses->capabilities & CAP_UNICODE) {
7966 + pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
7967 + name_len =
7968 + cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
7969 + searchName, 530
7970 + /* find define for this maxpathcomponent */
7971 + , nls_codepage);
7972 + name_len++; /* trailing null */
7973 + name_len *= 2;
7974 + } else { /* BB improve the check for buffer overruns BB */
7975 + name_len = strnlen(searchName, 530);
7976 + name_len++; /* trailing null */
7977 + strncpy(pSMB->RequestFileName, searchName, name_len);
7978 + }
7979 +
7980 + pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
7981 + pSMB->TotalDataCount = 0;
7982 + pSMB->DataCount = 0;
7983 + pSMB->DataOffset = 0;
7984 + pSMB->MaxParameterCount = 0;
7985 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
7986 + pSMB->MaxSetupCount = 0;
7987 + pSMB->Reserved = 0;
7988 + pSMB->Flags = 0;
7989 + pSMB->Timeout = 0;
7990 + pSMB->Reserved2 = 0;
7991 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
7992 + struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
7993 + pSMB->SetupCount = 1;
7994 + pSMB->Reserved3 = 0;
7995 + pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
7996 + pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
7997 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
7998 + pSMB->TotalParameterCount = pSMB->ParameterCount;
7999 + pSMB->MaxReferralLevel = cpu_to_le16(3);
8000 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8001 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8002 +
8003 + rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
8004 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8005 + if (rc) {
8006 + cFYI(1, ("Send error in GetDFSRefer = %d", rc));
8007 + } else { /* decode response */
8008 +/* BB Add logic to parse referrals here */
8009 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8010 + pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
8011 + cFYI(1,
8012 + ("Decoding GetDFSRefer response. BCC: %d Offset %d",
8013 + pSMBr->ByteCount, pSMBr->DataOffset));
8014 + if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
8015 + rc = -EIO; /* bad smb */
8016 + else {
8017 + referrals =
8018 + (struct dfs_referral_level_3 *)
8019 + (8 /* sizeof start of data block */ +
8020 + pSMBr->DataOffset +
8021 + (char *) &pSMBr->hdr.Protocol);
8022 + 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));
8023 + /* BB This field is actually two bytes in from start of
8024 + data block so we could do safety check that DataBlock
8025 + begins at address of pSMBr->NumberOfReferrals */
8026 + *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
8027 +
8028 + /* BB Fix below so can return more than one referral */
8029 + if(*number_of_UNC_in_array > 1)
8030 + *number_of_UNC_in_array = 1;
8031 +
8032 + /* get the length of the strings describing refs */
8033 + name_len = 0;
8034 + for(i=0;i<*number_of_UNC_in_array;i++) {
8035 + /* make sure that DfsPathOffset not past end */
8036 + referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
8037 + if(referrals->DfsPathOffset > pSMBr->DataCount) {
8038 + /* if invalid referral, stop here and do
8039 + not try to copy any more */
8040 + *number_of_UNC_in_array = i;
8041 + break;
8042 + }
8043 + temp = ((char *)referrals) + referrals->DfsPathOffset;
8044 +
8045 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
8046 + name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
8047 + } else {
8048 + name_len += strnlen(temp,pSMBr->DataCount);
8049 + }
8050 + referrals++;
8051 + /* BB add check that referral pointer does not fall off end PDU */
8052 +
8053 + }
8054 + /* BB add check for name_len bigger than bcc */
8055 + *targetUNCs =
8056 + kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
8057 + /* copy the ref strings */
8058 + referrals =
8059 + (struct dfs_referral_level_3 *)
8060 + (8 /* sizeof data hdr */ +
8061 + pSMBr->DataOffset +
8062 + (char *) &pSMBr->hdr.Protocol);
8063 +
8064 + for(i=0;i<*number_of_UNC_in_array;i++) {
8065 + temp = ((char *)referrals) + referrals->DfsPathOffset;
8066 + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
8067 + cifs_strfromUCS_le(*targetUNCs,
8068 + (wchar_t *) temp, name_len, nls_codepage);
8069 + } else {
8070 + strncpy(*targetUNCs,temp,name_len);
8071 + }
8072 + /* BB update target_uncs pointers */
8073 + referrals++;
8074 + }
8075 + temp = *targetUNCs;
8076 + temp[name_len] = 0;
8077 + }
8078 +
8079 + }
8080 + if (pSMB)
8081 + cifs_buf_release(pSMB);
8082 +
8083 + if (rc == -EAGAIN)
8084 + goto getDFSRetry;
8085 +
8086 + return rc;
8087 +}
8088 +
8089 +int
8090 +CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
8091 + struct statfs *FSData, const struct nls_table *nls_codepage)
8092 +{
8093 +/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
8094 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8095 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8096 + FILE_SYSTEM_INFO *response_data;
8097 + int rc = 0;
8098 + int bytes_returned = 0;
8099 +
8100 + cFYI(1, ("In QFSInfo"));
8101 +QFSInfoRetry:
8102 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8103 + (void **) &pSMBr);
8104 + if (rc)
8105 + return rc;
8106 +
8107 + pSMB->TotalParameterCount = 2; /* level */
8108 + pSMB->TotalDataCount = 0;
8109 + pSMB->MaxParameterCount = cpu_to_le16(2);
8110 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8111 + pSMB->MaxSetupCount = 0;
8112 + pSMB->Reserved = 0;
8113 + pSMB->Flags = 0;
8114 + pSMB->Timeout = 0;
8115 + pSMB->Reserved2 = 0;
8116 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8117 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8118 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8119 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8120 + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8121 + pSMB->DataCount = 0;
8122 + pSMB->DataOffset = 0;
8123 + pSMB->SetupCount = 1;
8124 + pSMB->Reserved3 = 0;
8125 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8126 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
8127 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8128 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8129 +
8130 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8131 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8132 + if (rc) {
8133 + cERROR(1, ("Send error in QFSInfo = %d", rc));
8134 + } else { /* decode response */
8135 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8136 + cFYI(1,
8137 + ("Decoding qfsinfo response. BCC: %d Offset %d",
8138 + pSMBr->ByteCount, pSMBr->DataOffset));
8139 + if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
8140 + rc = -EIO; /* bad smb */
8141 + else {
8142 + response_data =
8143 + (FILE_SYSTEM_INFO
8144 + *) (((char *) &pSMBr->hdr.Protocol) +
8145 + pSMBr->DataOffset);
8146 + FSData->f_bsize =
8147 + le32_to_cpu(response_data->BytesPerSector) *
8148 + le32_to_cpu(response_data->
8149 + SectorsPerAllocationUnit);
8150 + FSData->f_blocks =
8151 + le64_to_cpu(response_data->TotalAllocationUnits);
8152 + FSData->f_bfree = FSData->f_bavail =
8153 + le64_to_cpu(response_data->FreeAllocationUnits);
8154 + cFYI(1,
8155 + ("Blocks: %lld Free: %lld Block size %ld",
8156 + (unsigned long long)FSData->f_blocks,
8157 + (unsigned long long)FSData->f_bfree,
8158 + FSData->f_bsize));
8159 + }
8160 + }
8161 + if (pSMB)
8162 + cifs_buf_release(pSMB);
8163 +
8164 + if (rc == -EAGAIN)
8165 + goto QFSInfoRetry;
8166 +
8167 + return rc;
8168 +}
8169 +
8170 +int
8171 +CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
8172 + const struct nls_table *nls_codepage)
8173 +{
8174 +/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
8175 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8176 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8177 + FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
8178 + int rc = 0;
8179 + int bytes_returned = 0;
8180 +
8181 + cFYI(1, ("In QFSAttributeInfo"));
8182 +QFSAttributeRetry:
8183 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8184 + (void **) &pSMBr);
8185 + if (rc)
8186 + return rc;
8187 +
8188 + pSMB->TotalParameterCount = 2; /* level */
8189 + pSMB->TotalDataCount = 0;
8190 + pSMB->MaxParameterCount = cpu_to_le16(2);
8191 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8192 + pSMB->MaxSetupCount = 0;
8193 + pSMB->Reserved = 0;
8194 + pSMB->Flags = 0;
8195 + pSMB->Timeout = 0;
8196 + pSMB->Reserved2 = 0;
8197 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8198 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8199 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8200 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8201 + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8202 + pSMB->DataCount = 0;
8203 + pSMB->DataOffset = 0;
8204 + pSMB->SetupCount = 1;
8205 + pSMB->Reserved3 = 0;
8206 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8207 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
8208 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8209 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8210 +
8211 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8212 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8213 + if (rc) {
8214 + cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
8215 + } else { /* decode response */
8216 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8217 + if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
8218 + rc = -EIO; /* bad smb */
8219 + } else {
8220 + response_data =
8221 + (FILE_SYSTEM_ATTRIBUTE_INFO
8222 + *) (((char *) &pSMBr->hdr.Protocol) +
8223 + pSMBr->DataOffset);
8224 + response_data->Attributes = le32_to_cpu(response_data->Attributes);
8225 + response_data->MaxPathNameComponentLength =
8226 + le32_to_cpu(response_data->MaxPathNameComponentLength);
8227 + response_data->FileSystemNameLen =
8228 + le32_to_cpu(response_data->FileSystemNameLen);
8229 + memcpy(&tcon->fsAttrInfo, response_data,
8230 + sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
8231 + }
8232 + }
8233 + if (pSMB)
8234 + cifs_buf_release(pSMB);
8235 +
8236 + if (rc == -EAGAIN)
8237 + goto QFSAttributeRetry;
8238 +
8239 + return rc;
8240 +}
8241 +
8242 +int
8243 +CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
8244 + const struct nls_table *nls_codepage)
8245 +{
8246 +/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
8247 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8248 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8249 + FILE_SYSTEM_DEVICE_INFO *response_data;
8250 + int rc = 0;
8251 + int bytes_returned = 0;
8252 +
8253 + cFYI(1, ("In QFSDeviceInfo"));
8254 +QFSDeviceRetry:
8255 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8256 + (void **) &pSMBr);
8257 + if (rc)
8258 + return rc;
8259 +
8260 + pSMB->TotalParameterCount = 2; /* level */
8261 + pSMB->TotalDataCount = 0;
8262 + pSMB->MaxParameterCount = cpu_to_le16(2);
8263 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8264 + pSMB->MaxSetupCount = 0;
8265 + pSMB->Reserved = 0;
8266 + pSMB->Flags = 0;
8267 + pSMB->Timeout = 0;
8268 + pSMB->Reserved2 = 0;
8269 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8270 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8271 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8272 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8273 + struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8274 +
8275 + pSMB->DataCount = 0;
8276 + pSMB->DataOffset = 0;
8277 + pSMB->SetupCount = 1;
8278 + pSMB->Reserved3 = 0;
8279 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8280 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
8281 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8282 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8283 +
8284 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8285 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8286 + if (rc) {
8287 + cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
8288 + } else { /* decode response */
8289 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8290 + if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
8291 + || (pSMBr->DataOffset > 512))
8292 + rc = -EIO; /* bad smb */
8293 + else {
8294 + response_data =
8295 + (FILE_SYSTEM_DEVICE_INFO
8296 + *) (((char *) &pSMBr->hdr.Protocol) +
8297 + pSMBr->DataOffset);
8298 + response_data->DeviceType =
8299 + le32_to_cpu(response_data->DeviceType);
8300 + response_data->DeviceCharacteristics =
8301 + le32_to_cpu(response_data->DeviceCharacteristics);
8302 + memcpy(&tcon->fsDevInfo, response_data,
8303 + sizeof (FILE_SYSTEM_DEVICE_INFO));
8304 + }
8305 + }
8306 + if (pSMB)
8307 + cifs_buf_release(pSMB);
8308 +
8309 + if (rc == -EAGAIN)
8310 + goto QFSDeviceRetry;
8311 +
8312 + return rc;
8313 +}
8314 +
8315 +int
8316 +CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
8317 + const struct nls_table *nls_codepage)
8318 +{
8319 +/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
8320 + TRANSACTION2_QFSI_REQ *pSMB = NULL;
8321 + TRANSACTION2_QFSI_RSP *pSMBr = NULL;
8322 + FILE_SYSTEM_UNIX_INFO *response_data;
8323 + int rc = 0;
8324 + int bytes_returned = 0;
8325 +
8326 + cFYI(1, ("In QFSUnixInfo"));
8327 +QFSUnixRetry:
8328 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8329 + (void **) &pSMBr);
8330 + if (rc)
8331 + return rc;
8332 +
8333 + pSMB->ParameterCount = 2; /* level */
8334 + pSMB->TotalDataCount = 0;
8335 + pSMB->DataCount = 0;
8336 + pSMB->DataOffset = 0;
8337 + pSMB->MaxParameterCount = cpu_to_le16(2);
8338 + pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
8339 + pSMB->MaxSetupCount = 0;
8340 + pSMB->Reserved = 0;
8341 + pSMB->Flags = 0;
8342 + pSMB->Timeout = 0;
8343 + pSMB->Reserved2 = 0;
8344 + pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
8345 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8346 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8347 + pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
8348 + smb_com_transaction2_qfsi_req, InformationLevel) - 4);
8349 + pSMB->SetupCount = 1;
8350 + pSMB->Reserved3 = 0;
8351 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
8352 + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
8353 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8354 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8355 +
8356 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8357 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8358 + if (rc) {
8359 + cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
8360 + } else { /* decode response */
8361 + pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
8362 + if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
8363 + rc = -EIO; /* bad smb */
8364 + } else {
8365 + response_data =
8366 + (FILE_SYSTEM_UNIX_INFO
8367 + *) (((char *) &pSMBr->hdr.Protocol) +
8368 + pSMBr->DataOffset);
8369 + response_data->MajorVersionNumber =
8370 + le16_to_cpu(response_data->MajorVersionNumber);
8371 + response_data->MinorVersionNumber =
8372 + le16_to_cpu(response_data->MinorVersionNumber);
8373 + response_data->Capability =
8374 + le64_to_cpu(response_data->Capability);
8375 + memcpy(&tcon->fsUnixInfo, response_data,
8376 + sizeof (FILE_SYSTEM_UNIX_INFO));
8377 + }
8378 + }
8379 + if (pSMB)
8380 + cifs_buf_release(pSMB);
8381 +
8382 + if (rc == -EAGAIN)
8383 + goto QFSUnixRetry;
8384 +
8385 +
8386 + return rc;
8387 +}
8388 +
8389 +/* We can not use write of zero bytes trick to
8390 + set file size due to need for large file support. Also note that
8391 + this SetPathInfo is preferred to SetFileInfo based method in next
8392 + routine which is only needed to work around a sharing violation bug
8393 + in Samba which this routine can run into */
8394 +
8395 +int
8396 +CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
8397 + __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
8398 +{
8399 + struct smb_com_transaction2_spi_req *pSMB = NULL;
8400 + struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
8401 + struct file_end_of_file_info *parm_data;
8402 + int name_len;
8403 + int rc = 0;
8404 + int bytes_returned = 0;
8405 +
8406 + cFYI(1, ("In SetEOF"));
8407 +SetEOFRetry:
8408 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8409 + (void **) &pSMBr);
8410 + if (rc)
8411 + return rc;
8412 +
8413 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8414 + name_len =
8415 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8416 + /* find define for this maxpathcomponent */
8417 + , nls_codepage);
8418 + name_len++; /* trailing null */
8419 + name_len *= 2;
8420 + } else { /* BB improve the check for buffer overruns BB */
8421 + name_len = strnlen(fileName, 530);
8422 + name_len++; /* trailing null */
8423 + strncpy(pSMB->FileName, fileName, name_len);
8424 + }
8425 + pSMB->ParameterCount = 6 + name_len;
8426 + pSMB->DataCount = sizeof (struct file_end_of_file_info);
8427 + pSMB->MaxParameterCount = cpu_to_le16(2);
8428 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
8429 + pSMB->MaxSetupCount = 0;
8430 + pSMB->Reserved = 0;
8431 + pSMB->Flags = 0;
8432 + pSMB->Timeout = 0;
8433 + pSMB->Reserved2 = 0;
8434 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8435 + InformationLevel) - 4;
8436 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8437 + if(SetAllocation) {
8438 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8439 + pSMB->InformationLevel =
8440 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
8441 + else
8442 + pSMB->InformationLevel =
8443 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
8444 + } else /* Set File Size */ {
8445 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8446 + pSMB->InformationLevel =
8447 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
8448 + else
8449 + pSMB->InformationLevel =
8450 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
8451 + }
8452 +
8453 + parm_data =
8454 + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
8455 + pSMB->DataOffset);
8456 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8457 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8458 + pSMB->SetupCount = 1;
8459 + pSMB->Reserved3 = 0;
8460 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8461 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8462 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8463 + pSMB->TotalDataCount = pSMB->DataCount;
8464 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8465 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8466 + pSMB->Reserved4 = 0;
8467 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8468 + parm_data->FileSize = cpu_to_le64(size);
8469 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8470 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8471 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8472 + if (rc) {
8473 + cFYI(1, ("SetPathInfo (file size) returned %d", rc));
8474 + }
8475 +
8476 + if (pSMB)
8477 + cifs_buf_release(pSMB);
8478 +
8479 + if (rc == -EAGAIN)
8480 + goto SetEOFRetry;
8481 +
8482 + return rc;
8483 +}
8484 +
8485 +int
8486 +CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
8487 + __u16 fid, __u32 pid_of_opener, int SetAllocation)
8488 +{
8489 + struct smb_com_transaction2_sfi_req *pSMB = NULL;
8490 + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
8491 + char *data_offset;
8492 + struct file_end_of_file_info *parm_data;
8493 + int rc = 0;
8494 + int bytes_returned = 0;
8495 + __u32 tmp;
8496 +
8497 + cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
8498 + (long long)size));
8499 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8500 + (void **) &pSMBr);
8501 + if (rc)
8502 + return rc;
8503 +
8504 + tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
8505 + so network fid will be valid */
8506 + pSMB->hdr.Pid = tmp & 0xFFFF;
8507 + tmp >>= 16;
8508 + pSMB->hdr.PidHigh = tmp & 0xFFFF;
8509 +
8510 + pSMB->ParameterCount = 6;
8511 + pSMB->MaxSetupCount = 0;
8512 + pSMB->Reserved = 0;
8513 + pSMB->Flags = 0;
8514 + pSMB->Timeout = 0;
8515 + pSMB->Reserved2 = 0;
8516 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
8517 + Fid) - 4;
8518 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8519 +
8520 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
8521 +
8522 + pSMB->DataCount = sizeof(struct file_end_of_file_info);
8523 + pSMB->MaxParameterCount = cpu_to_le16(2);
8524 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
8525 + pSMB->SetupCount = 1;
8526 + pSMB->Reserved3 = 0;
8527 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
8528 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8529 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8530 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8531 + pSMB->TotalDataCount = pSMB->DataCount;
8532 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8533 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8534 + parm_data =
8535 + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
8536 + pSMB->DataOffset);
8537 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
8538 + parm_data->FileSize = cpu_to_le64(size);
8539 + pSMB->Fid = fid;
8540 + if(SetAllocation) {
8541 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8542 + pSMB->InformationLevel =
8543 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
8544 + else
8545 + pSMB->InformationLevel =
8546 + cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
8547 + } else /* Set File Size */ {
8548 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8549 + pSMB->InformationLevel =
8550 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
8551 + else
8552 + pSMB->InformationLevel =
8553 + cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
8554 + }
8555 + pSMB->Reserved4 = 0;
8556 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8557 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8558 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8559 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8560 + if (rc) {
8561 + cFYI(1,
8562 + ("Send error in SetFileInfo (SetFileSize) = %d",
8563 + rc));
8564 + }
8565 +
8566 + if (pSMB)
8567 + cifs_buf_release(pSMB);
8568 +
8569 + /* Note: On -EAGAIN error only caller can retry on handle based calls
8570 + since file handle passed in no longer valid */
8571 +
8572 + return rc;
8573 +}
8574 +
8575 +int
8576 +CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
8577 + FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
8578 +{
8579 + TRANSACTION2_SPI_REQ *pSMB = NULL;
8580 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
8581 + int name_len;
8582 + int rc = 0;
8583 + int bytes_returned = 0;
8584 + char *data_offset;
8585 +
8586 + cFYI(1, ("In SetTimes"));
8587 +
8588 +SetTimesRetry:
8589 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8590 + (void **) &pSMBr);
8591 + if (rc)
8592 + return rc;
8593 +
8594 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8595 + name_len =
8596 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8597 + /* find define for this maxpathcomponent */
8598 + , nls_codepage);
8599 + name_len++; /* trailing null */
8600 + name_len *= 2;
8601 + } else { /* BB improve the check for buffer overruns BB */
8602 + name_len = strnlen(fileName, 530);
8603 + name_len++; /* trailing null */
8604 + strncpy(pSMB->FileName, fileName, name_len);
8605 + }
8606 +
8607 + pSMB->ParameterCount = 6 + name_len;
8608 + pSMB->DataCount = sizeof (FILE_BASIC_INFO);
8609 + pSMB->MaxParameterCount = cpu_to_le16(2);
8610 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8611 + pSMB->MaxSetupCount = 0;
8612 + pSMB->Reserved = 0;
8613 + pSMB->Flags = 0;
8614 + pSMB->Timeout = 0;
8615 + pSMB->Reserved2 = 0;
8616 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8617 + InformationLevel) - 4;
8618 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8619 + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
8620 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8621 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8622 + pSMB->SetupCount = 1;
8623 + pSMB->Reserved3 = 0;
8624 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8625 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8626 +
8627 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8628 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8629 + pSMB->TotalDataCount = pSMB->DataCount;
8630 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8631 + if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
8632 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
8633 + else
8634 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
8635 + pSMB->Reserved4 = 0;
8636 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8637 + memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
8638 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8639 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8640 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8641 + if (rc) {
8642 + cFYI(1, ("SetPathInfo (times) returned %d", rc));
8643 + }
8644 +
8645 + if (pSMB)
8646 + cifs_buf_release(pSMB);
8647 +
8648 + if (rc == -EAGAIN)
8649 + goto SetTimesRetry;
8650 +
8651 + return rc;
8652 +}
8653 +
8654 +int
8655 +CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
8656 + char *fileName, __u64 mode, __u64 uid, __u64 gid,
8657 + dev_t device, const struct nls_table *nls_codepage)
8658 +{
8659 + TRANSACTION2_SPI_REQ *pSMB = NULL;
8660 + TRANSACTION2_SPI_RSP *pSMBr = NULL;
8661 + int name_len;
8662 + int rc = 0;
8663 + int bytes_returned = 0;
8664 + FILE_UNIX_BASIC_INFO *data_offset;
8665 +
8666 + cFYI(1, ("In SetUID/GID/Mode"));
8667 +setPermsRetry:
8668 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8669 + (void **) &pSMBr);
8670 + if (rc)
8671 + return rc;
8672 +
8673 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8674 + name_len =
8675 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
8676 + /* find define for this maxpathcomponent */
8677 + , nls_codepage);
8678 + name_len++; /* trailing null */
8679 + name_len *= 2;
8680 + } else { /* BB improve the check for buffer overruns BB */
8681 + name_len = strnlen(fileName, 530);
8682 + name_len++; /* trailing null */
8683 + strncpy(pSMB->FileName, fileName, name_len);
8684 + }
8685 +
8686 + pSMB->ParameterCount = 6 + name_len;
8687 + pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
8688 + pSMB->MaxParameterCount = cpu_to_le16(2);
8689 + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
8690 + pSMB->MaxSetupCount = 0;
8691 + pSMB->Reserved = 0;
8692 + pSMB->Flags = 0;
8693 + pSMB->Timeout = 0;
8694 + pSMB->Reserved2 = 0;
8695 + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
8696 + InformationLevel) - 4;
8697 + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
8698 + data_offset =
8699 + (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
8700 + pSMB->DataOffset);
8701 + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
8702 + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
8703 + pSMB->SetupCount = 1;
8704 + pSMB->Reserved3 = 0;
8705 + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
8706 + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
8707 + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
8708 + pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
8709 + pSMB->TotalParameterCount = pSMB->ParameterCount;
8710 + pSMB->TotalDataCount = pSMB->DataCount;
8711 + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
8712 + pSMB->Reserved4 = 0;
8713 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8714 + data_offset->Uid = cpu_to_le64(uid);
8715 + data_offset->Gid = cpu_to_le64(gid);
8716 + /* better to leave device as zero when it is */
8717 + data_offset->DevMajor = cpu_to_le64(MAJOR(device));
8718 + data_offset->DevMinor = cpu_to_le64(MINOR(device));
8719 + data_offset->Permissions = cpu_to_le64(mode);
8720 +
8721 + if(S_ISREG(mode))
8722 + data_offset->Type = cpu_to_le32(UNIX_FILE);
8723 + else if(S_ISDIR(mode))
8724 + data_offset->Type = cpu_to_le32(UNIX_DIR);
8725 + else if(S_ISLNK(mode))
8726 + data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
8727 + else if(S_ISCHR(mode))
8728 + data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
8729 + else if(S_ISBLK(mode))
8730 + data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
8731 + else if(S_ISFIFO(mode))
8732 + data_offset->Type = cpu_to_le32(UNIX_FIFO);
8733 + else if(S_ISSOCK(mode))
8734 + data_offset->Type = cpu_to_le32(UNIX_SOCKET);
8735 +
8736 +
8737 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8738 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8739 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8740 + if (rc) {
8741 + cFYI(1, ("SetPathInfo (perms) returned %d", rc));
8742 + }
8743 +
8744 + if (pSMB)
8745 + cifs_buf_release(pSMB);
8746 + if (rc == -EAGAIN)
8747 + goto setPermsRetry;
8748 + return rc;
8749 +}
8750 +
8751 +int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
8752 + const int notify_subdirs, const __u16 netfid,
8753 + __u32 filter, const struct nls_table *nls_codepage)
8754 +{
8755 + int rc = 0;
8756 + struct smb_com_transaction_change_notify_req * pSMB = NULL;
8757 + struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
8758 + int bytes_returned;
8759 +
8760 + cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
8761 + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
8762 + (void **) &pSMBr);
8763 + if (rc)
8764 + return rc;
8765 +
8766 + pSMB->TotalParameterCount = 0 ;
8767 + pSMB->TotalDataCount = 0;
8768 + pSMB->MaxParameterCount = cpu_to_le32(2);
8769 + /* BB find exact data count max from sess structure BB */
8770 + pSMB->MaxDataCount = 0; /* same in little endian or be */
8771 + pSMB->MaxSetupCount = 4;
8772 + pSMB->Reserved = 0;
8773 + pSMB->ParameterOffset = 0;
8774 + pSMB->DataCount = 0;
8775 + pSMB->DataOffset = 0;
8776 + pSMB->SetupCount = 4; /* single byte does not need le conversion */
8777 + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
8778 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8779 + if(notify_subdirs)
8780 + pSMB->WatchTree = 1; /* one byte - no le conversion needed */
8781 + pSMB->Reserved2 = 0;
8782 + pSMB->CompletionFilter = cpu_to_le32(filter);
8783 + pSMB->Fid = netfid; /* file handle always le */
8784 + pSMB->ByteCount = 0;
8785 +
8786 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8787 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8788 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8789 + if (rc) {
8790 + cFYI(1, ("Error in Notify = %d", rc));
8791 + }
8792 + if (pSMB)
8793 + cifs_buf_release(pSMB);
8794 +/* if (rc == -EAGAIN)
8795 + goto NotifyRetry; */
8796 + return rc;
8797 +}
8798 +#ifdef CONFIG_CIFS_XATTR
8799 +int
8800 +CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
8801 + const unsigned char *searchName,
8802 + char * EAData, size_t size,
8803 + const struct nls_table *nls_codepage)
8804 +{
8805 + /* BB assumes one setup word */
8806 + TRANSACTION2_QPI_REQ *pSMB = NULL;
8807 + TRANSACTION2_QPI_RSP *pSMBr = NULL;
8808 + int rc = 0;
8809 + int bytes_returned;
8810 + int name_len;
8811 +
8812 + cFYI(1, ("In Query All EAs path %s", searchName));
8813 +QAllEAsRetry:
8814 + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
8815 + (void **) &pSMBr);
8816 + if (rc)
8817 + return rc;
8818 +
8819 + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
8820 + name_len =
8821 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
8822 + /* find define for this maxpathcomponent */
8823 + , nls_codepage);
8824 + name_len++; /* trailing null */
8825 + name_len *= 2;
8826 + } else { /* BB improve the check for buffer overruns BB */
8827 + name_len = strnlen(searchName, 530);
8828 + name_len++; /* trailing null */
8829 + strncpy(pSMB->FileName, searchName, name_len);
8830 + }
8831 +
8832 + pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
8833 + name_len /* includes null */ ;
8834 + pSMB->TotalDataCount = 0;
8835 + pSMB->MaxParameterCount = cpu_to_le16(2);
8836 + pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
8837 + pSMB->MaxSetupCount = 0;
8838 + pSMB->Reserved = 0;
8839 + pSMB->Flags = 0;
8840 + pSMB->Timeout = 0;
8841 + pSMB->Reserved2 = 0;
8842 + pSMB->ParameterOffset = cpu_to_le16(offsetof(
8843 + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
8844 + pSMB->DataCount = 0;
8845 + pSMB->DataOffset = 0;
8846 + pSMB->SetupCount = 1;
8847 + pSMB->Reserved3 = 0;
8848 + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
8849 + pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
8850 + pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
8851 + pSMB->ParameterCount = pSMB->TotalParameterCount;
8852 + pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
8853 + pSMB->Reserved4 = 0;
8854 + pSMB->hdr.smb_buf_length += pSMB->ByteCount;
8855 + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
8856 +
8857 + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
8858 + (struct smb_hdr *) pSMBr, &bytes_returned, 0);
8859 + if (rc) {
8860 + cFYI(1, ("Send error in QueryAllEAs = %d", rc));
8861 + } else { /* decode response */
8862 + pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
8863 + /* BB also check enough total bytes returned */
8864 + /* BB we need to improve the validity checking
8865 + of these trans2 responses */
8866 + if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
8867 + rc = -EIO; /* bad smb */
8868 + /* else if (pFindData){
8869 + memcpy((char *) pFindData,
8870 + (char *) &pSMBr->hdr.Protocol +
8871 + pSMBr->DataOffset, kl);
8872 + }*/ else {
8873 + /* check that length of list is not more than bcc */
8874 + /* check that each entry does not go beyond length
8875 + of list */
8876 + /* check that each element of each entry does not
8877 + go beyond end of list */
8878 + struct fealist * ea_response_data;
8879 + rc = 0;
8880 + /* validate_trans2_offsets() */
8881 + /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
8882 + ea_response_data = (struct fealist *)
8883 + (((char *) &pSMBr->hdr.Protocol) +
8884 + pSMBr->DataOffset);
8885 + cFYI(1,("ea length %d",ea_response_data->list_len));
8886 + }
8887 + }
8888 + if (pSMB)
8889 + cifs_buf_release(pSMB);
8890 + if (rc == -EAGAIN)
8891 + goto QAllEAsRetry;
8892 +
8893 + return rc;
8894 +}
8895 +#endif
8896 diff -urN linux-2.4.29.old/fs/cifs/cifs_unicode.c linux-2.4.29/fs/cifs/cifs_unicode.c
8897 --- linux-2.4.29.old/fs/cifs/cifs_unicode.c 1970-01-01 01:00:00.000000000 +0100
8898 +++ linux-2.4.29/fs/cifs/cifs_unicode.c 2004-07-14 00:25:04.000000000 +0200
8899 @@ -0,0 +1,87 @@
8900 +/*
8901 + * fs/cifs/cifs_unicode.c
8902 + *
8903 + * Copyright (c) International Business Machines Corp., 2000,2002
8904 + * Modified by Steve French (sfrench@us.ibm.com)
8905 + *
8906 + * This program is free software; you can redistribute it and/or modify
8907 + * it under the terms of the GNU General Public License as published by
8908 + * the Free Software Foundation; either version 2 of the License, or
8909 + * (at your option) any later version.
8910 + *
8911 + * This program is distributed in the hope that it will be useful,
8912 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8913 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8914 + * the GNU General Public License for more details.
8915 + *
8916 + * You should have received a copy of the GNU General Public License
8917 + * along with this program; if not, write to the Free Software
8918 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8919 + */
8920 +#include <linux/fs.h>
8921 +#include "cifs_unicode.h"
8922 +#include "cifs_uniupr.h"
8923 +#include "cifspdu.h"
8924 +#include "cifs_debug.h"
8925 +
8926 +/*
8927 + * NAME: cifs_strfromUCS()
8928 + *
8929 + * FUNCTION: Convert little-endian unicode string to character string
8930 + *
8931 + */
8932 +int
8933 +cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
8934 + int len, const struct nls_table *codepage)
8935 +{
8936 + int i;
8937 + int outlen = 0;
8938 +
8939 + for (i = 0; (i < len) && from[i]; i++) {
8940 + int charlen;
8941 + /* 2.4.0 kernel or greater */
8942 + charlen =
8943 + codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
8944 + NLS_MAX_CHARSET_SIZE);
8945 + if (charlen > 0) {
8946 + outlen += charlen;
8947 + } else {
8948 + to[outlen++] = '?';
8949 + }
8950 + }
8951 + to[outlen] = 0;
8952 + return outlen;
8953 +}
8954 +
8955 +/*
8956 + * NAME: cifs_strtoUCS()
8957 + *
8958 + * FUNCTION: Convert character string to unicode string
8959 + *
8960 + */
8961 +int
8962 +cifs_strtoUCS(wchar_t * to, const char *from, int len,
8963 + const struct nls_table *codepage)
8964 +{
8965 + int charlen;
8966 + int i;
8967 +
8968 + for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
8969 +
8970 + /* works for 2.4.0 kernel or later */
8971 + charlen = codepage->char2uni(from, len, &to[i]);
8972 + if (charlen < 1) {
8973 + cERROR(1,
8974 + ("cifs_strtoUCS: char2uni returned %d",
8975 + charlen));
8976 + to[i] = cpu_to_le16(0x003f); /* a question mark */
8977 + charlen = 1;
8978 + }
8979 + to[i] = cpu_to_le16(to[i]);
8980 +
8981 + }
8982 +
8983 + to[i] = 0;
8984 + return i;
8985 +}
8986 +
8987 diff -urN linux-2.4.29.old/fs/cifs/cifs_unicode.h linux-2.4.29/fs/cifs/cifs_unicode.h
8988 --- linux-2.4.29.old/fs/cifs/cifs_unicode.h 1970-01-01 01:00:00.000000000 +0100
8989 +++ linux-2.4.29/fs/cifs/cifs_unicode.h 2004-07-14 00:25:04.000000000 +0200
8990 @@ -0,0 +1,353 @@
8991 +/*
8992 + * cifs_unicode: Unicode kernel case support
8993 + *
8994 + * Function:
8995 + * Convert a unicode character to upper or lower case using
8996 + * compressed tables.
8997 + *
8998 + * Copyright (c) International Business Machines Corp., 2000,2002
8999 + *
9000 + * This program is free software; you can redistribute it and/or modify
9001 + * it under the terms of the GNU General Public License as published by
9002 + * the Free Software Foundation; either version 2 of the License, or
9003 + * (at your option) any later version.
9004 + *
9005 + * This program is distributed in the hope that it will be useful,
9006 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9007 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9008 + * the GNU General Public License for more details.
9009 + *
9010 + * You should have received a copy of the GNU General Public License
9011 + * along with this program; if not, write to the Free Software
9012 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9013 + *
9014 + *
9015 + * Notes:
9016 + * These APIs are based on the C library functions. The semantics
9017 + * should match the C functions but with expanded size operands.
9018 + *
9019 + * The upper/lower functions are based on a table created by mkupr.
9020 + * This is a compressed table of upper and lower case conversion.
9021 + *
9022 + */
9023 +
9024 +#include <asm/byteorder.h>
9025 +#include <linux/types.h>
9026 +#include <linux/nls.h>
9027 +
9028 +#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
9029 +
9030 +/* Just define what we want from uniupr.h. We don't want to define the tables
9031 + * in each source file.
9032 + */
9033 +#ifndef UNICASERANGE_DEFINED
9034 +struct UniCaseRange {
9035 + wchar_t start;
9036 + wchar_t end;
9037 + signed char *table;
9038 +};
9039 +#endif /* UNICASERANGE_DEFINED */
9040 +
9041 +#ifndef UNIUPR_NOUPPER
9042 +extern signed char CifsUniUpperTable[512];
9043 +extern const struct UniCaseRange CifsUniUpperRange[];
9044 +#endif /* UNIUPR_NOUPPER */
9045 +
9046 +#ifndef UNIUPR_NOLOWER
9047 +extern signed char UniLowerTable[512];
9048 +extern struct UniCaseRange UniLowerRange[];
9049 +#endif /* UNIUPR_NOLOWER */
9050 +
9051 +#ifdef __KERNEL__
9052 +int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
9053 +int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
9054 +#endif
9055 +
9056 +/*
9057 + * UniStrcat: Concatenate the second string to the first
9058 + *
9059 + * Returns:
9060 + * Address of the first string
9061 + */
9062 +static inline wchar_t *
9063 +UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
9064 +{
9065 + wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
9066 +
9067 + while (*ucs1++) ; /* To end of first string */
9068 + ucs1--; /* Return to the null */
9069 + while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
9070 + return anchor;
9071 +}
9072 +
9073 +/*
9074 + * UniStrchr: Find a character in a string
9075 + *
9076 + * Returns:
9077 + * Address of first occurrence of character in string
9078 + * or NULL if the character is not in the string
9079 + */
9080 +static inline wchar_t *
9081 +UniStrchr(const wchar_t * ucs, wchar_t uc)
9082 +{
9083 + while ((*ucs != uc) && *ucs)
9084 + ucs++;
9085 +
9086 + if (*ucs == uc)
9087 + return (wchar_t *) ucs;
9088 + return NULL;
9089 +}
9090 +
9091 +/*
9092 + * UniStrcmp: Compare two strings
9093 + *
9094 + * Returns:
9095 + * < 0: First string is less than second
9096 + * = 0: Strings are equal
9097 + * > 0: First string is greater than second
9098 + */
9099 +static inline int
9100 +UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
9101 +{
9102 + while ((*ucs1 == *ucs2) && *ucs1) {
9103 + ucs1++;
9104 + ucs2++;
9105 + }
9106 + return (int) *ucs1 - (int) *ucs2;
9107 +}
9108 +
9109 +/*
9110 + * UniStrcpy: Copy a string
9111 + */
9112 +static inline wchar_t *
9113 +UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
9114 +{
9115 + wchar_t *anchor = ucs1; /* save the start of result string */
9116 +
9117 + while ((*ucs1++ = *ucs2++)) ;
9118 + return anchor;
9119 +}
9120 +
9121 +/*
9122 + * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
9123 + */
9124 +static inline size_t
9125 +UniStrlen(const wchar_t * ucs1)
9126 +{
9127 + int i = 0;
9128 +
9129 + while (*ucs1++)
9130 + i++;
9131 + return i;
9132 +}
9133 +
9134 +/*
9135 + * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
9136 + */
9137 +static inline size_t
9138 +UniStrnlen(const wchar_t * ucs1, int maxlen)
9139 +{
9140 + int i = 0;
9141 +
9142 + while (*ucs1++) {
9143 + i++;
9144 + if (i >= maxlen)
9145 + break;
9146 + }
9147 + return i;
9148 +}
9149 +
9150 +/*
9151 + * UniStrncat: Concatenate length limited string
9152 + */
9153 +static inline wchar_t *
9154 +UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9155 +{
9156 + wchar_t *anchor = ucs1; /* save pointer to string 1 */
9157 +
9158 + while (*ucs1++) ;
9159 + ucs1--; /* point to null terminator of s1 */
9160 + while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
9161 + ucs1++;
9162 + ucs2++;
9163 + }
9164 + *ucs1 = 0; /* Null terminate the result */
9165 + return (anchor);
9166 +}
9167 +
9168 +/*
9169 + * UniStrncmp: Compare length limited string
9170 + */
9171 +static inline int
9172 +UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9173 +{
9174 + if (!n)
9175 + return 0; /* Null strings are equal */
9176 + while ((*ucs1 == *ucs2) && *ucs1 && --n) {
9177 + ucs1++;
9178 + ucs2++;
9179 + }
9180 + return (int) *ucs1 - (int) *ucs2;
9181 +}
9182 +
9183 +/*
9184 + * UniStrncmp_le: Compare length limited string - native to little-endian
9185 + */
9186 +static inline int
9187 +UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9188 +{
9189 + if (!n)
9190 + return 0; /* Null strings are equal */
9191 + while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
9192 + ucs1++;
9193 + ucs2++;
9194 + }
9195 + return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
9196 +}
9197 +
9198 +/*
9199 + * UniStrncpy: Copy length limited string with pad
9200 + */
9201 +static inline wchar_t *
9202 +UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9203 +{
9204 + wchar_t *anchor = ucs1;
9205 +
9206 + while (n-- && *ucs2) /* Copy the strings */
9207 + *ucs1++ = *ucs2++;
9208 +
9209 + n++;
9210 + while (n--) /* Pad with nulls */
9211 + *ucs1++ = 0;
9212 + return anchor;
9213 +}
9214 +
9215 +/*
9216 + * UniStrncpy_le: Copy length limited string with pad to little-endian
9217 + */
9218 +static inline wchar_t *
9219 +UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
9220 +{
9221 + wchar_t *anchor = ucs1;
9222 +
9223 + while (n-- && *ucs2) /* Copy the strings */
9224 + *ucs1++ = __le16_to_cpu(*ucs2++);
9225 +
9226 + n++;
9227 + while (n--) /* Pad with nulls */
9228 + *ucs1++ = 0;
9229 + return anchor;
9230 +}
9231 +
9232 +/*
9233 + * UniStrstr: Find a string in a string
9234 + *
9235 + * Returns:
9236 + * Address of first match found
9237 + * NULL if no matching string is found
9238 + */
9239 +static inline wchar_t *
9240 +UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
9241 +{
9242 + const wchar_t *anchor1 = ucs1;
9243 + const wchar_t *anchor2 = ucs2;
9244 +
9245 + while (*ucs1) {
9246 + if (*ucs1 == *ucs2) { /* Partial match found */
9247 + ucs1++;
9248 + ucs2++;
9249 + } else {
9250 + if (!*ucs2) /* Match found */
9251 + return (wchar_t *) anchor1;
9252 + ucs1 = ++anchor1; /* No match */
9253 + ucs2 = anchor2;
9254 + }
9255 + }
9256 +
9257 + if (!*ucs2) /* Both end together */
9258 + return (wchar_t *) anchor1; /* Match found */
9259 + return NULL; /* No match */
9260 +}
9261 +
9262 +#ifndef UNIUPR_NOUPPER
9263 +/*
9264 + * UniToupper: Convert a unicode character to upper case
9265 + */
9266 +static inline wchar_t
9267 +UniToupper(register wchar_t uc)
9268 +{
9269 + register const struct UniCaseRange *rp;
9270 +
9271 + if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */
9272 + return uc + CifsUniUpperTable[uc]; /* Use base tables */
9273 + } else {
9274 + rp = CifsUniUpperRange; /* Use range tables */
9275 + while (rp->start) {
9276 + if (uc < rp->start) /* Before start of range */
9277 + return uc; /* Uppercase = input */
9278 + if (uc <= rp->end) /* In range */
9279 + return uc + rp->table[uc - rp->start];
9280 + rp++; /* Try next range */
9281 + }
9282 + }
9283 + return uc; /* Past last range */
9284 +}
9285 +
9286 +/*
9287 + * UniStrupr: Upper case a unicode string
9288 + */
9289 +static inline wchar_t *
9290 +UniStrupr(register wchar_t * upin)
9291 +{
9292 + register wchar_t *up;
9293 +
9294 + up = upin;
9295 + while (*up) { /* For all characters */
9296 + *up = UniToupper(*up);
9297 + up++;
9298 + }
9299 + return upin; /* Return input pointer */
9300 +}
9301 +#endif /* UNIUPR_NOUPPER */
9302 +
9303 +#ifndef UNIUPR_NOLOWER
9304 +/*
9305 + * UniTolower: Convert a unicode character to lower case
9306 + */
9307 +static inline wchar_t
9308 +UniTolower(wchar_t uc)
9309 +{
9310 + register struct UniCaseRange *rp;
9311 +
9312 + if (uc < sizeof (UniLowerTable)) { /* Latin characters */
9313 + return uc + UniLowerTable[uc]; /* Use base tables */
9314 + } else {
9315 + rp = UniLowerRange; /* Use range tables */
9316 + while (rp->start) {
9317 + if (uc < rp->start) /* Before start of range */
9318 + return uc; /* Uppercase = input */
9319 + if (uc <= rp->end) /* In range */
9320 + return uc + rp->table[uc - rp->start];
9321 + rp++; /* Try next range */
9322 + }
9323 + }
9324 + return uc; /* Past last range */
9325 +}
9326 +
9327 +/*
9328 + * UniStrlwr: Lower case a unicode string
9329 + */
9330 +static inline wchar_t *
9331 +UniStrlwr(register wchar_t * upin)
9332 +{
9333 + register wchar_t *up;
9334 +
9335 + up = upin;
9336 + while (*up) { /* For all characters */
9337 + *up = UniTolower(*up);
9338 + up++;
9339 + }
9340 + return upin; /* Return input pointer */
9341 +}
9342 +
9343 +#endif
9344 diff -urN linux-2.4.29.old/fs/cifs/cifs_uniupr.h linux-2.4.29/fs/cifs/cifs_uniupr.h
9345 --- linux-2.4.29.old/fs/cifs/cifs_uniupr.h 1970-01-01 01:00:00.000000000 +0100
9346 +++ linux-2.4.29/fs/cifs/cifs_uniupr.h 2004-07-14 00:25:04.000000000 +0200
9347 @@ -0,0 +1,253 @@
9348 +/*
9349 + * Copyright (c) International Business Machines Corp., 2000,2002
9350 + *
9351 + * This program is free software; you can redistribute it and/or modify
9352 + * it under the terms of the GNU General Public License as published by
9353 + * the Free Software Foundation; either version 2 of the License, or
9354 + * (at your option) any later version.
9355 + *
9356 + * This program is distributed in the hope that it will be useful,
9357 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9358 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9359 + * the GNU General Public License for more details.
9360 + *
9361 + * You should have received a copy of the GNU General Public License
9362 + * along with this program; if not, write to the Free Software
9363 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9364 + *
9365 + * uniupr.h - Unicode compressed case ranges
9366 + *
9367 +*/
9368 +
9369 +#ifndef UNIUPR_NOUPPER
9370 +/*
9371 + * Latin upper case
9372 + */
9373 +signed char CifsUniUpperTable[512] = {
9374 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
9375 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
9376 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
9377 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
9378 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
9379 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
9380 + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
9381 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
9382 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
9383 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
9384 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
9385 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
9386 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
9387 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
9388 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
9389 + -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
9390 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
9391 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
9392 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
9393 + 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
9394 + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
9395 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
9396 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
9397 + 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
9398 + 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
9399 + 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
9400 + 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
9401 + -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
9402 + 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
9403 + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
9404 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
9405 + 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
9406 +};
9407 +
9408 +/* Upper case range - Greek */
9409 +static signed char UniCaseRangeU03a0[47] = {
9410 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
9411 + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
9412 + -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
9413 + -63, -63,
9414 +};
9415 +
9416 +/* Upper case range - Cyrillic */
9417 +static signed char UniCaseRangeU0430[48] = {
9418 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
9419 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
9420 + 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
9421 +};
9422 +
9423 +/* Upper case range - Extended cyrillic */
9424 +static signed char UniCaseRangeU0490[61] = {
9425 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
9426 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
9427 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
9428 + 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
9429 +};
9430 +
9431 +/* Upper case range - Extended latin and greek */
9432 +static signed char UniCaseRangeU1e00[509] = {
9433 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
9434 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
9435 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
9436 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
9437 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
9438 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
9439 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
9440 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
9441 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
9442 + 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
9443 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
9444 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
9445 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
9446 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
9447 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
9448 + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
9449 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
9450 + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
9451 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
9452 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
9453 + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
9454 + 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
9455 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
9456 + 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
9457 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
9458 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
9459 + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
9460 + 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
9461 + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
9462 + 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
9463 + 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
9464 + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9465 +};
9466 +
9467 +/* Upper case range - Wide latin */
9468 +static signed char UniCaseRangeUff40[27] = {
9469 + 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
9470 + -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
9471 +};
9472 +
9473 +/*
9474 + * Upper Case Range
9475 + */
9476 +const struct UniCaseRange CifsUniUpperRange[] = {
9477 + {0x03a0, 0x03ce, UniCaseRangeU03a0},
9478 + {0x0430, 0x045f, UniCaseRangeU0430},
9479 + {0x0490, 0x04cc, UniCaseRangeU0490},
9480 + {0x1e00, 0x1ffc, UniCaseRangeU1e00},
9481 + {0xff40, 0xff5a, UniCaseRangeUff40},
9482 + {0, 0, NULL}
9483 +};
9484 +#endif
9485 +
9486 +#ifndef UNIUPR_NOLOWER
9487 +/*
9488 + * Latin lower case
9489 + */
9490 +static signed char CifsUniLowerTable[512] = {
9491 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
9492 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
9493 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
9494 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
9495 + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
9496 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
9497 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
9498 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
9499 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
9500 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
9501 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
9502 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
9503 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
9504 + 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
9505 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
9506 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
9507 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
9508 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
9509 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
9510 + 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
9511 + 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
9512 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
9513 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
9514 + 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
9515 + 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
9516 + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
9517 + 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
9518 + 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
9519 + 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
9520 + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
9521 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
9522 + 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
9523 +};
9524 +
9525 +/* Lower case range - Greek */
9526 +static signed char UniCaseRangeL0380[44] = {
9527 + 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
9528 + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
9529 + 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
9530 +};
9531 +
9532 +/* Lower case range - Cyrillic */
9533 +static signed char UniCaseRangeL0400[48] = {
9534 + 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
9535 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
9536 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
9537 +};
9538 +
9539 +/* Lower case range - Extended cyrillic */
9540 +static signed char UniCaseRangeL0490[60] = {
9541 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
9542 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
9543 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
9544 + 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
9545 +};
9546 +
9547 +/* Lower case range - Extended latin and greek */
9548 +static signed char UniCaseRangeL1e00[504] = {
9549 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
9550 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
9551 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
9552 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
9553 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
9554 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
9555 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
9556 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
9557 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
9558 + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
9559 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
9560 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
9561 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
9562 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
9563 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
9564 + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
9565 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
9566 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
9567 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
9568 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
9569 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
9570 + 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
9571 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
9572 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
9573 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
9574 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
9575 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
9576 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
9577 + 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
9578 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
9579 + 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
9580 + 0, 0, 0, 0, 0, 0, 0, 0,
9581 +};
9582 +
9583 +/* Lower case range - Wide latin */
9584 +static signed char UniCaseRangeLff20[27] = {
9585 + 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
9586 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
9587 +};
9588 +
9589 +/*
9590 + * Lower Case Range
9591 + */
9592 +const static struct UniCaseRange CifsUniLowerRange[] = {
9593 + 0x0380, 0x03ab, UniCaseRangeL0380,
9594 + 0x0400, 0x042f, UniCaseRangeL0400,
9595 + 0x0490, 0x04cb, UniCaseRangeL0490,
9596 + 0x1e00, 0x1ff7, UniCaseRangeL1e00,
9597 + 0xff20, 0xff3a, UniCaseRangeLff20,
9598 + 0, 0, 0
9599 +};
9600 +#endif
9601 diff -urN linux-2.4.29.old/fs/cifs/connect.c linux-2.4.29/fs/cifs/connect.c
9602 --- linux-2.4.29.old/fs/cifs/connect.c 1970-01-01 01:00:00.000000000 +0100
9603 +++ linux-2.4.29/fs/cifs/connect.c 2004-07-14 00:25:05.000000000 +0200
9604 @@ -0,0 +1,2924 @@
9605 +/*
9606 + * fs/cifs/connect.c
9607 + *
9608 + * Copyright (C) International Business Machines Corp., 2002,2004
9609 + * Author(s): Steve French (sfrench@us.ibm.com)
9610 + *
9611 + * This library is free software; you can redistribute it and/or modify
9612 + * it under the terms of the GNU Lesser General Public License as published
9613 + * by the Free Software Foundation; either version 2.1 of the License, or
9614 + * (at your option) any later version.
9615 + *
9616 + * This library is distributed in the hope that it will be useful,
9617 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9618 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9619 + * the GNU Lesser General Public License for more details.
9620 + *
9621 + * You should have received a copy of the GNU Lesser General Public License
9622 + * along with this library; if not, write to the Free Software
9623 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9624 + */
9625 +#include <linux/fs.h>
9626 +#include <linux/net.h>
9627 +#include <linux/string.h>
9628 +#include <linux/list.h>
9629 +#include <linux/wait.h>
9630 +#include <linux/version.h>
9631 +#include <linux/ipv6.h>
9632 +#include <linux/pagemap.h>
9633 +#include <linux/ctype.h>
9634 +#include <linux/utsname.h>
9635 +#include <asm/uaccess.h>
9636 +#include <asm/processor.h>
9637 +#include "cifspdu.h"
9638 +#include "cifsglob.h"
9639 +#include "cifsproto.h"
9640 +#include "cifs_unicode.h"
9641 +#include "cifs_debug.h"
9642 +#include "cifs_fs_sb.h"
9643 +#include "ntlmssp.h"
9644 +#include "nterr.h"
9645 +#include "rfc1002pdu.h"
9646 +
9647 +#define CIFS_PORT 445
9648 +#define RFC1001_PORT 139
9649 +
9650 +extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
9651 + unsigned char *p24);
9652 +extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
9653 + unsigned char *p24);
9654 +extern int cifs_inet_pton(int, const char *, void *dst);
9655 +
9656 +struct smb_vol {
9657 + char *username;
9658 + char *password;
9659 + char *domainname;
9660 + char *UNC;
9661 + char *UNCip;
9662 + char *iocharset; /* local code page for mapping to and from Unicode */
9663 + char source_rfc1001_name[16]; /* netbios name of client */
9664 + uid_t linux_uid;
9665 + gid_t linux_gid;
9666 + mode_t file_mode;
9667 + mode_t dir_mode;
9668 + int rw:1;
9669 + int retry:1;
9670 + int intr:1;
9671 + unsigned int rsize;
9672 + unsigned int wsize;
9673 + unsigned int sockopt;
9674 + unsigned short int port;
9675 +};
9676 +
9677 +static int ipv4_connect(struct sockaddr_in *psin_server,
9678 + struct socket **csocket,
9679 + char * netb_name);
9680 +static int ipv6_connect(struct sockaddr_in6 *psin_server,
9681 + struct socket **csocket);
9682 +
9683 +
9684 + /*
9685 + * cifs tcp session reconnection
9686 + *
9687 + * mark tcp session as reconnecting so temporarily locked
9688 + * mark all smb sessions as reconnecting for tcp session
9689 + * reconnect tcp session
9690 + * wake up waiters on reconnection? - (not needed currently)
9691 + */
9692 +
9693 +int
9694 +cifs_reconnect(struct TCP_Server_Info *server)
9695 +{
9696 + int rc = 0;
9697 + struct list_head *tmp;
9698 + struct cifsSesInfo *ses;
9699 + struct cifsTconInfo *tcon;
9700 + struct mid_q_entry * mid_entry;
9701 +
9702 + spin_lock(&GlobalMid_Lock);
9703 + if(server->tcpStatus == CifsExiting) {
9704 + /* the demux thread will exit normally
9705 + next time through the loop */
9706 + spin_unlock(&GlobalMid_Lock);
9707 + return rc;
9708 + } else
9709 + server->tcpStatus = CifsNeedReconnect;
9710 + spin_unlock(&GlobalMid_Lock);
9711 + server->maxBuf = 0;
9712 +
9713 + cFYI(1, ("Reconnecting tcp session "));
9714 +
9715 + /* before reconnecting the tcp session, mark the smb session (uid)
9716 + and the tid bad so they are not used until reconnected */
9717 + read_lock(&GlobalSMBSeslock);
9718 + list_for_each(tmp, &GlobalSMBSessionList) {
9719 + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
9720 + if (ses->server) {
9721 + if (ses->server == server) {
9722 + ses->status = CifsNeedReconnect;
9723 + ses->ipc_tid = 0;
9724 + }
9725 + }
9726 + /* else tcp and smb sessions need reconnection */
9727 + }
9728 + list_for_each(tmp, &GlobalTreeConnectionList) {
9729 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
9730 + if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
9731 + tcon->tidStatus = CifsNeedReconnect;
9732 + }
9733 + }
9734 + read_unlock(&GlobalSMBSeslock);
9735 + /* do not want to be sending data on a socket we are freeing */
9736 + down(&server->tcpSem);
9737 + if(server->ssocket) {
9738 + cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
9739 + server->ssocket->flags));
9740 + server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
9741 + cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
9742 + server->ssocket->flags));
9743 + sock_release(server->ssocket);
9744 + server->ssocket = NULL;
9745 + }
9746 +
9747 + spin_lock(&GlobalMid_Lock);
9748 + list_for_each(tmp, &server->pending_mid_q) {
9749 + mid_entry = list_entry(tmp, struct
9750 + mid_q_entry,
9751 + qhead);
9752 + if(mid_entry) {
9753 + if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
9754 + /* Mark other intransit requests as needing retry so
9755 + we do not immediately mark the session bad again
9756 + (ie after we reconnect below) as they timeout too */
9757 + mid_entry->midState = MID_RETRY_NEEDED;
9758 + }
9759 + }
9760 + }
9761 + spin_unlock(&GlobalMid_Lock);
9762 + up(&server->tcpSem);
9763 +
9764 + while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
9765 + {
9766 + if(server->protocolType == IPV6) {
9767 + rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
9768 + } else {
9769 + rc = ipv4_connect(&server->addr.sockAddr,
9770 + &server->ssocket,
9771 + server->workstation_RFC1001_name);
9772 + }
9773 + if(rc) {
9774 + set_current_state(TASK_INTERRUPTIBLE);
9775 + schedule_timeout(3 * HZ);
9776 + } else {
9777 + atomic_inc(&tcpSesReconnectCount);
9778 + spin_lock(&GlobalMid_Lock);
9779 + if(server->tcpStatus != CifsExiting)
9780 + server->tcpStatus = CifsGood;
9781 + spin_unlock(&GlobalMid_Lock);
9782 + /* atomic_set(&server->inFlight,0);*/
9783 + wake_up(&server->response_q);
9784 + }
9785 + }
9786 + return rc;
9787 +}
9788 +
9789 +static int
9790 +cifs_demultiplex_thread(struct TCP_Server_Info *server)
9791 +{
9792 + int length;
9793 + unsigned int pdu_length, total_read;
9794 + struct smb_hdr *smb_buffer = NULL;
9795 + struct msghdr smb_msg;
9796 + mm_segment_t temp_fs;
9797 + struct iovec iov;
9798 + struct socket *csocket = server->ssocket;
9799 + struct list_head *tmp;
9800 + struct cifsSesInfo *ses;
9801 + struct task_struct *task_to_wake = NULL;
9802 + struct mid_q_entry *mid_entry;
9803 + char *temp;
9804 +
9805 + daemonize();
9806 + sprintf(current->comm,"cifsd");
9807 + /* allow_signal(SIGKILL);*/
9808 + current->flags |= PF_MEMALLOC;
9809 + server->tsk = current; /* save process info to wake at shutdown */
9810 + cFYI(1, ("Demultiplex PID: %d", current->pid));
9811 +
9812 + temp_fs = get_fs(); /* we must turn off socket api parm checking */
9813 + set_fs(get_ds());
9814 +
9815 + while (server->tcpStatus != CifsExiting) {
9816 + if (smb_buffer == NULL)
9817 + smb_buffer = cifs_buf_get();
9818 + else
9819 + memset(smb_buffer, 0, sizeof (struct smb_hdr));
9820 +
9821 + if (smb_buffer == NULL) {
9822 + cERROR(1,("Can not get memory for SMB response"));
9823 + set_current_state(TASK_INTERRUPTIBLE);
9824 + schedule_timeout(HZ * 3); /* give system time to free memory */
9825 + continue;
9826 + }
9827 + iov.iov_base = smb_buffer;
9828 + iov.iov_len = sizeof (struct smb_hdr) - 1;
9829 + /* 1 byte less above since wct is not always returned in error cases */
9830 + smb_msg.msg_iov = &iov;
9831 + smb_msg.msg_iovlen = 1;
9832 + smb_msg.msg_control = NULL;
9833 + smb_msg.msg_controllen = 0;
9834 +
9835 + length =
9836 + sock_recvmsg(csocket, &smb_msg,
9837 + sizeof (struct smb_hdr) -
9838 + 1 /* RFC1001 header and SMB header */ ,
9839 + MSG_PEEK /* flags see socket.h */ );
9840 +
9841 + if(server->tcpStatus == CifsExiting) {
9842 + break;
9843 + } else if (server->tcpStatus == CifsNeedReconnect) {
9844 + cFYI(1,("Reconnecting after server stopped responding"));
9845 + cifs_reconnect(server);
9846 + cFYI(1,("call to reconnect done"));
9847 + csocket = server->ssocket;
9848 + continue;
9849 + } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
9850 + set_current_state(TASK_INTERRUPTIBLE);
9851 + schedule_timeout(1); /* minimum sleep to prevent looping
9852 + allowing socket to clear and app threads to set
9853 + tcpStatus CifsNeedReconnect if server hung */
9854 + continue;
9855 + } else if (length <= 0) {
9856 + if(server->tcpStatus == CifsNew) {
9857 + cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
9858 + /* some servers kill tcp session rather than returning
9859 + smb negprot error in which case reconnecting here is
9860 + not going to help - return error to mount */
9861 + break;
9862 + }
9863 + if(length == -EINTR) {
9864 + cFYI(1,("cifsd thread killed"));
9865 + break;
9866 + }
9867 + cFYI(1,("Reconnecting after unexpected peek error %d",length));
9868 + cifs_reconnect(server);
9869 + csocket = server->ssocket;
9870 + wake_up(&server->response_q);
9871 + continue;
9872 + }
9873 +
9874 + pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
9875 + /* Ony read pdu_length after below checks for too short (due
9876 + to e.g. int overflow) and too long ie beyond end of buf */
9877 + cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
9878 +
9879 + temp = (char *) smb_buffer;
9880 + if (length > 3) {
9881 + if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
9882 + iov.iov_base = smb_buffer;
9883 + iov.iov_len = 4;
9884 + length = sock_recvmsg(csocket, &smb_msg, 4, 0);
9885 + cFYI(0,("Received 4 byte keep alive packet"));
9886 + } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
9887 + iov.iov_base = smb_buffer;
9888 + iov.iov_len = 4;
9889 + length = sock_recvmsg(csocket, &smb_msg, 4, 0);
9890 + cFYI(1,("Good RFC 1002 session rsp"));
9891 + } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
9892 + && (length == 5)) {
9893 + /* we get this from Windows 98 instead of error on SMB negprot response */
9894 + cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
9895 + if(server->tcpStatus == CifsNew) {
9896 + /* if nack on negprot (rather than
9897 + ret of smb negprot error) reconnecting
9898 + not going to help, ret error to mount */
9899 + break;
9900 + } else {
9901 + /* give server a second to
9902 + clean up before reconnect attempt */
9903 + set_current_state(TASK_INTERRUPTIBLE);
9904 + schedule_timeout(HZ);
9905 + /* always try 445 first on reconnect
9906 + since we get NACK on some if we ever
9907 + connected to port 139 (the NACK is
9908 + since we do not begin with RFC1001
9909 + session initialize frame) */
9910 + server->addr.sockAddr.sin_port = CIFS_PORT;
9911 + cifs_reconnect(server);
9912 + csocket = server->ssocket;
9913 + wake_up(&server->response_q);
9914 + continue;
9915 + }
9916 + } else if (temp[0] != (char) 0) {
9917 + cERROR(1,("Unknown RFC 1002 frame"));
9918 + cifs_dump_mem(" Received Data: ", temp, length);
9919 + cifs_reconnect(server);
9920 + csocket = server->ssocket;
9921 + continue;
9922 + } else {
9923 + if ((length != sizeof (struct smb_hdr) - 1)
9924 + || (pdu_length >
9925 + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
9926 + || (pdu_length <
9927 + sizeof (struct smb_hdr) - 1)
9928 + ||
9929 + (checkSMBhdr
9930 + (smb_buffer, smb_buffer->Mid))) {
9931 + cERROR(1,
9932 + ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
9933 + length, pdu_length));
9934 + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
9935 + /* could we fix this network corruption by finding next
9936 + smb header (instead of killing the session) and
9937 + restart reading from next valid SMB found? */
9938 + cifs_reconnect(server);
9939 + csocket = server->ssocket;
9940 + continue;
9941 + } else { /* length ok */
9942 +
9943 + length = 0;
9944 + iov.iov_base = smb_buffer;
9945 + iov.iov_len = pdu_length;
9946 + for (total_read = 0;
9947 + total_read < pdu_length;
9948 + total_read += length) {
9949 + length = sock_recvmsg(csocket, &smb_msg,
9950 + pdu_length - total_read, 0);
9951 + if (length == 0) {
9952 + cERROR(1,
9953 + ("Zero length receive when expecting %d ",
9954 + pdu_length - total_read));
9955 + cifs_reconnect(server);
9956 + csocket = server->ssocket;
9957 + continue;
9958 + }
9959 + }
9960 + }
9961 +
9962 + dump_smb(smb_buffer, length);
9963 + if (checkSMB
9964 + (smb_buffer, smb_buffer->Mid, total_read)) {
9965 + cERROR(1, ("Bad SMB Received "));
9966 + continue;
9967 + }
9968 +
9969 + task_to_wake = NULL;
9970 + spin_lock(&GlobalMid_Lock);
9971 + list_for_each(tmp, &server->pending_mid_q) {
9972 + mid_entry = list_entry(tmp, struct
9973 + mid_q_entry,
9974 + qhead);
9975 +
9976 + if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
9977 + cFYI(1,
9978 + (" Mid 0x%x matched - waking up ",mid_entry->mid));
9979 + task_to_wake = mid_entry->tsk;
9980 + mid_entry->resp_buf =
9981 + smb_buffer;
9982 + mid_entry->midState =
9983 + MID_RESPONSE_RECEIVED;
9984 + }
9985 + }
9986 + spin_unlock(&GlobalMid_Lock);
9987 + if (task_to_wake) {
9988 + smb_buffer = NULL; /* will be freed by users thread after he is done */
9989 + wake_up_process(task_to_wake);
9990 + } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
9991 + cERROR(1, ("No task to wake, unknown frame rcvd!"));
9992 + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
9993 + }
9994 + }
9995 + } else {
9996 + cFYI(0,
9997 + ("Frame less than four bytes received %d bytes long.",
9998 + length));
9999 + if (length > 0) {
10000 + length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
10001 + cFYI(1,
10002 + (" with junk 0x%x in it ",
10003 + *(__u32 *) smb_buffer));
10004 + }
10005 + }
10006 + }
10007 + spin_lock(&GlobalMid_Lock);
10008 + server->tcpStatus = CifsExiting;
10009 + server->tsk = NULL;
10010 + atomic_set(&server->inFlight, 0);
10011 + spin_unlock(&GlobalMid_Lock);
10012 + /* Although there should not be any requests blocked on
10013 + this queue it can not hurt to be paranoid and try to wake up requests
10014 + that may haven been blocked when more than 50 at time were on the wire
10015 + to the same server - they now will see the session is in exit state
10016 + and get out of SendReceive. */
10017 + wake_up_all(&server->request_q);
10018 + /* give those requests time to exit */
10019 + set_current_state(TASK_INTERRUPTIBLE);
10020 + schedule_timeout(HZ/8);
10021 +
10022 + if(server->ssocket) {
10023 + sock_release(csocket);
10024 + server->ssocket = NULL;
10025 + }
10026 + set_fs(temp_fs);
10027 + if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
10028 + cifs_buf_release(smb_buffer);
10029 +
10030 + read_lock(&GlobalSMBSeslock);
10031 + if (list_empty(&server->pending_mid_q)) {
10032 + /* loop through server session structures attached to this and mark them dead */
10033 + list_for_each(tmp, &GlobalSMBSessionList) {
10034 + ses =
10035 + list_entry(tmp, struct cifsSesInfo,
10036 + cifsSessionList);
10037 + if (ses->server == server) {
10038 + ses->status = CifsExiting;
10039 + ses->server = NULL;
10040 + }
10041 + }
10042 + read_unlock(&GlobalSMBSeslock);
10043 + } else {
10044 + spin_lock(&GlobalMid_Lock);
10045 + list_for_each(tmp, &server->pending_mid_q) {
10046 + mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
10047 + if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
10048 + cFYI(1,
10049 + (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
10050 + task_to_wake = mid_entry->tsk;
10051 + if(task_to_wake) {
10052 + wake_up_process(task_to_wake);
10053 + }
10054 + }
10055 + }
10056 + spin_unlock(&GlobalMid_Lock);
10057 + read_unlock(&GlobalSMBSeslock);
10058 + set_current_state(TASK_INTERRUPTIBLE);
10059 + /* 1/8th of sec is more than enough time for them to exit */
10060 + schedule_timeout(HZ/8);
10061 + }
10062 +
10063 + if (list_empty(&server->pending_mid_q)) {
10064 + /* mpx threads have not exited yet give them
10065 + at least the smb send timeout time for long ops */
10066 + cFYI(1, ("Wait for exit from demultiplex thread"));
10067 + set_current_state(TASK_INTERRUPTIBLE);
10068 + schedule_timeout(46 * HZ);
10069 + /* if threads still have not exited they are probably never
10070 + coming home not much else we can do but free the memory */
10071 + }
10072 + kfree(server);
10073 +
10074 + set_current_state(TASK_INTERRUPTIBLE);
10075 + schedule_timeout(HZ/4);
10076 + return 0;
10077 +}
10078 +
10079 +static void *
10080 +cifs_kcalloc(size_t size, int type)
10081 +{
10082 + void *addr;
10083 + addr = kmalloc(size, type);
10084 + if (addr)
10085 + memset(addr, 0, size);
10086 + return addr;
10087 +}
10088 +
10089 +static int
10090 +cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
10091 +{
10092 + char *value;
10093 + char *data;
10094 + unsigned int temp_len, i, j;
10095 + char separator[2];
10096 +
10097 + separator[0] = ',';
10098 + separator[1] = 0;
10099 +
10100 + memset(vol->source_rfc1001_name,0x20,15);
10101 + for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
10102 + /* does not have to be a perfect mapping since the field is
10103 + informational, only used for servers that do not support
10104 + port 445 and it can be overridden at mount time */
10105 + vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
10106 + }
10107 + vol->source_rfc1001_name[15] = 0;
10108 +
10109 + vol->linux_uid = current->uid; /* current->euid instead? */
10110 + vol->linux_gid = current->gid;
10111 + vol->dir_mode = S_IRWXUGO;
10112 + /* 2767 perms indicate mandatory locking support */
10113 + vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
10114 +
10115 + /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
10116 + vol->rw = TRUE;
10117 +
10118 + if (!options)
10119 + return 1;
10120 +
10121 + if(strncmp(options,"sep=",4) == 0) {
10122 + if(options[4] != 0) {
10123 + separator[0] = options[4];
10124 + options += 5;
10125 + } else {
10126 + cFYI(1,("Null separator not allowed"));
10127 + }
10128 + }
10129 +
10130 + while ((data = strsep(&options, separator)) != NULL) {
10131 + if (!*data)
10132 + continue;
10133 + if ((value = strchr(data, '=')) != NULL)
10134 + *value++ = '\0';
10135 + if (strnicmp(data, "user", 4) == 0) {
10136 + if (!value || !*value) {
10137 + printk(KERN_WARNING
10138 + "CIFS: invalid or missing username\n");
10139 + return 1; /* needs_arg; */
10140 + }
10141 + if (strnlen(value, 200) < 200) {
10142 + vol->username = value;
10143 + } else {
10144 + printk(KERN_WARNING "CIFS: username too long\n");
10145 + return 1;
10146 + }
10147 + } else if (strnicmp(data, "pass", 4) == 0) {
10148 + if (!value || !*value) {
10149 + vol->password = NULL;
10150 + continue;
10151 + }
10152 + temp_len = strlen(value);
10153 + /* removed password length check, NTLM passwords
10154 + can be arbitrarily long */
10155 +
10156 + /* if comma in password, the string will be
10157 + prematurely null terminated. Commas in password are
10158 + specified across the cifs mount interface by a double
10159 + comma ie ,, and a comma used as in other cases ie ','
10160 + as a parameter delimiter/separator is single and due
10161 + to the strsep above is temporarily zeroed. */
10162 +
10163 + /* NB: password legally can have multiple commas and
10164 + the only illegal character in a password is null */
10165 +
10166 + if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
10167 + /* reinsert comma */
10168 + value[temp_len] = separator[0];
10169 + temp_len+=2; /* move after the second comma */
10170 + while(value[temp_len] != 0) {
10171 + if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
10172 + /* single comma indicating start of next parm */
10173 + break;
10174 + }
10175 + temp_len++;
10176 + }
10177 + if(value[temp_len] == 0) {
10178 + options = NULL;
10179 + } else {
10180 + value[temp_len] = 0;
10181 + /* move options to point to start of next parm */
10182 + options = value + temp_len + 1;
10183 + }
10184 + /* go from value to (value + temp_len) condensing double commas to singles */
10185 + vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
10186 + for(i=0,j=0;i<temp_len;i++,j++) {
10187 + vol->password[j] = value[i];
10188 + if(value[i] == separator[0] && value[i+1] == separator[0]) {
10189 + /* skip second comma */
10190 + i++;
10191 + }
10192 + }
10193 + /* value[temp_len] is zeroed above so
10194 + vol->password[temp_len] guaranteed to be null */
10195 + } else {
10196 + vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
10197 + strcpy(vol->password, value);
10198 + }
10199 + } else if (strnicmp(data, "ip", 2) == 0) {
10200 + if (!value || !*value) {
10201 + vol->UNCip = NULL;
10202 + } else if (strnlen(value, 35) < 35) {
10203 + vol->UNCip = value;
10204 + } else {
10205 + printk(KERN_WARNING "CIFS: ip address too long\n");
10206 + return 1;
10207 + }
10208 + } else if ((strnicmp(data, "unc", 3) == 0)
10209 + || (strnicmp(data, "target", 6) == 0)
10210 + || (strnicmp(data, "path", 4) == 0)) {
10211 + if (!value || !*value) {
10212 + printk(KERN_WARNING
10213 + "CIFS: invalid path to network resource\n");
10214 + return 1; /* needs_arg; */
10215 + }
10216 + if ((temp_len = strnlen(value, 300)) < 300) {
10217 + vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
10218 + if(vol->UNC == NULL)
10219 + return 1;
10220 + strcpy(vol->UNC,value);
10221 + if (strncmp(vol->UNC, "//", 2) == 0) {
10222 + vol->UNC[0] = '\\';
10223 + vol->UNC[1] = '\\';
10224 + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
10225 + printk(KERN_WARNING
10226 + "CIFS: UNC Path does not begin with // or \\\\ \n");
10227 + return 1;
10228 + }
10229 + } else {
10230 + printk(KERN_WARNING "CIFS: UNC name too long\n");
10231 + return 1;
10232 + }
10233 + } else if ((strnicmp(data, "domain", 3) == 0)
10234 + || (strnicmp(data, "workgroup", 5) == 0)) {
10235 + if (!value || !*value) {
10236 + printk(KERN_WARNING "CIFS: invalid domain name\n");
10237 + return 1; /* needs_arg; */
10238 + }
10239 + /* BB are there cases in which a comma can be valid in
10240 + a domain name and need special handling? */
10241 + if (strnlen(value, 65) < 65) {
10242 + vol->domainname = value;
10243 + cFYI(1, ("Domain name set"));
10244 + } else {
10245 + printk(KERN_WARNING "CIFS: domain name too long\n");
10246 + return 1;
10247 + }
10248 + } else if (strnicmp(data, "iocharset", 9) == 0) {
10249 + if (!value || !*value) {
10250 + printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
10251 + return 1; /* needs_arg; */
10252 + }
10253 + if (strnlen(value, 65) < 65) {
10254 + if(strnicmp(value,"default",7))
10255 + vol->iocharset = value;
10256 + /* if iocharset not set load_nls_default used by caller */
10257 + cFYI(1, ("iocharset set to %s",value));
10258 + } else {
10259 + printk(KERN_WARNING "CIFS: iocharset name too long.\n");
10260 + return 1;
10261 + }
10262 + } else if (strnicmp(data, "uid", 3) == 0) {
10263 + if (value && *value) {
10264 + vol->linux_uid =
10265 + simple_strtoul(value, &value, 0);
10266 + }
10267 + } else if (strnicmp(data, "gid", 3) == 0) {
10268 + if (value && *value) {
10269 + vol->linux_gid =
10270 + simple_strtoul(value, &value, 0);
10271 + }
10272 + } else if (strnicmp(data, "file_mode", 4) == 0) {
10273 + if (value && *value) {
10274 + vol->file_mode =
10275 + simple_strtoul(value, &value, 0);
10276 + }
10277 + } else if (strnicmp(data, "dir_mode", 3) == 0) {
10278 + if (value && *value) {
10279 + vol->dir_mode =
10280 + simple_strtoul(value, &value, 0);
10281 + }
10282 + } else if (strnicmp(data, "port", 4) == 0) {
10283 + if (value && *value) {
10284 + vol->port =
10285 + simple_strtoul(value, &value, 0);
10286 + }
10287 + } else if (strnicmp(data, "rsize", 5) == 0) {
10288 + if (value && *value) {
10289 + vol->rsize =
10290 + simple_strtoul(value, &value, 0);
10291 + }
10292 + } else if (strnicmp(data, "wsize", 5) == 0) {
10293 + if (value && *value) {
10294 + vol->wsize =
10295 + simple_strtoul(value, &value, 0);
10296 + }
10297 + } else if (strnicmp(data, "sockopt", 5) == 0) {
10298 + if (value && *value) {
10299 + vol->sockopt =
10300 + simple_strtoul(value, &value, 0);
10301 + }
10302 + } else if (strnicmp(data, "netbiosname", 4) == 0) {
10303 + if (!value || !*value || (*value == ' ')) {
10304 + cFYI(1,("invalid (empty) netbiosname specified"));
10305 + } else {
10306 + memset(vol->source_rfc1001_name,0x20,15);
10307 + for(i=0;i<15;i++) {
10308 + /* BB are there cases in which a comma can be
10309 + valid in this workstation netbios name (and need
10310 + special handling)? */
10311 +
10312 + /* We do not uppercase netbiosname for user */
10313 + if (value[i]==0)
10314 + break;
10315 + else
10316 + vol->source_rfc1001_name[i] = value[i];
10317 + }
10318 + /* The string has 16th byte zero still from
10319 + set at top of the function */
10320 + if((i==15) && (value[i] != 0))
10321 + printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
10322 + }
10323 + } else if (strnicmp(data, "credentials", 4) == 0) {
10324 + /* ignore */
10325 + } else if (strnicmp(data, "version", 3) == 0) {
10326 + /* ignore */
10327 + } else if (strnicmp(data, "rw", 2) == 0) {
10328 + vol->rw = TRUE;
10329 + } else if ((strnicmp(data, "suid", 4) == 0) ||
10330 + (strnicmp(data, "nosuid", 6) == 0) ||
10331 + (strnicmp(data, "exec", 4) == 0) ||
10332 + (strnicmp(data, "noexec", 6) == 0) ||
10333 + (strnicmp(data, "nodev", 5) == 0) ||
10334 + (strnicmp(data, "noauto", 6) == 0) ||
10335 + (strnicmp(data, "dev", 3) == 0)) {
10336 + /* The mount tool or mount.cifs helper (if present)
10337 + uses these opts to set flags, and the flags are read
10338 + by the kernel vfs layer before we get here (ie
10339 + before read super) so there is no point trying to
10340 + parse these options again and set anything and it
10341 + is ok to just ignore them */
10342 + continue;
10343 + } else if (strnicmp(data, "ro", 2) == 0) {
10344 + vol->rw = FALSE;
10345 + } else if (strnicmp(data, "hard", 4) == 0) {
10346 + vol->retry = 1;
10347 + } else if (strnicmp(data, "soft", 4) == 0) {
10348 + vol->retry = 0;
10349 + } else if (strnicmp(data, "nohard", 6) == 0) {
10350 + vol->retry = 0;
10351 + } else if (strnicmp(data, "nosoft", 6) == 0) {
10352 + vol->retry = 1;
10353 + } else if (strnicmp(data, "nointr", 6) == 0) {
10354 + vol->intr = 0;
10355 + } else if (strnicmp(data, "intr", 4) == 0) {
10356 + vol->intr = 1;
10357 + } else if (strnicmp(data, "noac", 4) == 0) {
10358 + printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
10359 + } else
10360 + printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
10361 + }
10362 + if (vol->UNC == NULL) {
10363 + if(devname == NULL) {
10364 + printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
10365 + return 1;
10366 + }
10367 + if ((temp_len = strnlen(devname, 300)) < 300) {
10368 + vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
10369 + if(vol->UNC == NULL)
10370 + return 1;
10371 + strcpy(vol->UNC,devname);
10372 + if (strncmp(vol->UNC, "//", 2) == 0) {
10373 + vol->UNC[0] = '\\';
10374 + vol->UNC[1] = '\\';
10375 + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
10376 + printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
10377 + return 1;
10378 + }
10379 + } else {
10380 + printk(KERN_WARNING "CIFS: UNC name too long\n");
10381 + return 1;
10382 + }
10383 + }
10384 + if(vol->UNCip == 0)
10385 + vol->UNCip = &vol->UNC[2];
10386 +
10387 + return 0;
10388 +}
10389 +
10390 +static struct cifsSesInfo *
10391 +cifs_find_tcp_session(__u32 new_target_ip_addr,
10392 + char *userName, struct TCP_Server_Info **psrvTcp)
10393 +{
10394 + struct list_head *tmp;
10395 + struct cifsSesInfo *ses;
10396 +
10397 + *psrvTcp = NULL;
10398 + read_lock(&GlobalSMBSeslock);
10399 + list_for_each(tmp, &GlobalSMBSessionList) {
10400 + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
10401 + if (ses->server) {
10402 + if (ses->server->addr.sockAddr.sin_addr.s_addr ==
10403 + new_target_ip_addr) {
10404 + /* BB lock server and tcp session and increment use count here?? */
10405 + *psrvTcp = ses->server; /* found a match on the TCP session */
10406 + /* BB check if reconnection needed */
10407 + if (strncmp
10408 + (ses->userName, userName,
10409 + MAX_USERNAME_SIZE) == 0){
10410 + read_unlock(&GlobalSMBSeslock);
10411 + return ses; /* found exact match on both tcp and SMB sessions */
10412 + }
10413 + }
10414 + }
10415 + /* else tcp and smb sessions need reconnection */
10416 + }
10417 + read_unlock(&GlobalSMBSeslock);
10418 + return NULL;
10419 +}
10420 +
10421 +static struct cifsTconInfo *
10422 +find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
10423 +{
10424 + struct list_head *tmp;
10425 + struct cifsTconInfo *tcon;
10426 +
10427 + read_lock(&GlobalSMBSeslock);
10428 + list_for_each(tmp, &GlobalTreeConnectionList) {
10429 + cFYI(1, ("Next tcon - "));
10430 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
10431 + if (tcon->ses) {
10432 + if (tcon->ses->server) {
10433 + cFYI(1,
10434 + (" old ip addr: %x == new ip %x ?",
10435 + tcon->ses->server->addr.sockAddr.sin_addr.
10436 + s_addr, new_target_ip_addr));
10437 + if (tcon->ses->server->addr.sockAddr.sin_addr.
10438 + s_addr == new_target_ip_addr) {
10439 + /* BB lock tcon and server and tcp session and increment use count here? */
10440 + /* found a match on the TCP session */
10441 + /* BB check if reconnection needed */
10442 + cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
10443 + tcon->treeName, uncName));
10444 + if (strncmp
10445 + (tcon->treeName, uncName,
10446 + MAX_TREE_SIZE) == 0) {
10447 + cFYI(1,
10448 + ("Matched UNC, old user: %s == new: %s ?",
10449 + tcon->treeName, uncName));
10450 + if (strncmp
10451 + (tcon->ses->userName,
10452 + userName,
10453 + MAX_USERNAME_SIZE) == 0) {
10454 + read_unlock(&GlobalSMBSeslock);
10455 + return tcon;/* also matched user (smb session)*/
10456 + }
10457 + }
10458 + }
10459 + }
10460 + }
10461 + }
10462 + read_unlock(&GlobalSMBSeslock);
10463 + return NULL;
10464 +}
10465 +
10466 +int
10467 +connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
10468 + const char *old_path, const struct nls_table *nls_codepage)
10469 +{
10470 + unsigned char *referrals = NULL;
10471 + unsigned int num_referrals;
10472 + int rc = 0;
10473 +
10474 + rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
10475 + &num_referrals, &referrals);
10476 +
10477 + /* BB Add in code to: if valid refrl, if not ip address contact
10478 + the helper that resolves tcp names, mount to it, try to
10479 + tcon to it unmount it if fail */
10480 +
10481 + if(referrals)
10482 + kfree(referrals);
10483 +
10484 + return rc;
10485 +}
10486 +
10487 +int
10488 +get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
10489 + const char *old_path, const struct nls_table *nls_codepage,
10490 + unsigned int *pnum_referrals, unsigned char ** preferrals)
10491 +{
10492 + char *temp_unc;
10493 + int rc = 0;
10494 +
10495 + *pnum_referrals = 0;
10496 +
10497 + if (pSesInfo->ipc_tid == 0) {
10498 + temp_unc = kmalloc(2 /* for slashes */ +
10499 + strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
10500 + + 1 + 4 /* slash IPC$ */ + 2,
10501 + GFP_KERNEL);
10502 + if (temp_unc == NULL)
10503 + return -ENOMEM;
10504 + temp_unc[0] = '\\';
10505 + temp_unc[1] = '\\';
10506 + strcpy(temp_unc + 2, pSesInfo->serverName);
10507 + strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
10508 + rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
10509 + cFYI(1,
10510 + ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
10511 + kfree(temp_unc);
10512 + }
10513 + if (rc == 0)
10514 + rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
10515 + pnum_referrals, nls_codepage);
10516 +
10517 + return rc;
10518 +}
10519 +
10520 +/* See RFC1001 section 14 on representation of Netbios names */
10521 +static void rfc1002mangle(char * target,char * source, unsigned int length)
10522 +{
10523 + unsigned int i,j;
10524 +
10525 + for(i=0,j=0;i<(length);i++) {
10526 + /* mask a nibble at a time and encode */
10527 + target[j] = 'A' + (0x0F & (source[i] >> 4));
10528 + target[j+1] = 'A' + (0x0F & source[i]);
10529 + j+=2;
10530 + }
10531 +
10532 +}
10533 +
10534 +
10535 +static int
10536 +ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
10537 + char * netbios_name)
10538 +{
10539 + int rc = 0;
10540 + int connected = 0;
10541 + unsigned short int orig_port = 0;
10542 +
10543 + if(*csocket == NULL) {
10544 + rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
10545 + if (rc < 0) {
10546 + cERROR(1, ("Error %d creating socket",rc));
10547 + *csocket = NULL;
10548 + return rc;
10549 + } else {
10550 + /* BB other socket options to set KEEPALIVE, NODELAY? */
10551 + cFYI(1,("Socket created"));
10552 + (*csocket)->sk->allocation = GFP_NOFS;
10553 + }
10554 + }
10555 +
10556 + psin_server->sin_family = AF_INET;
10557 + if(psin_server->sin_port) { /* user overrode default port */
10558 + rc = (*csocket)->ops->connect(*csocket,
10559 + (struct sockaddr *) psin_server,
10560 + sizeof (struct sockaddr_in),0);
10561 + if (rc >= 0)
10562 + connected = 1;
10563 + }
10564 +
10565 + if(!connected) {
10566 + /* save original port so we can retry user specified port
10567 + later if fall back ports fail this time */
10568 + orig_port = psin_server->sin_port;
10569 +
10570 + /* do not retry on the same port we just failed on */
10571 + if(psin_server->sin_port != htons(CIFS_PORT)) {
10572 + psin_server->sin_port = htons(CIFS_PORT);
10573 +
10574 + rc = (*csocket)->ops->connect(*csocket,
10575 + (struct sockaddr *) psin_server,
10576 + sizeof (struct sockaddr_in),0);
10577 + if (rc >= 0)
10578 + connected = 1;
10579 + }
10580 + }
10581 + if (!connected) {
10582 + psin_server->sin_port = htons(RFC1001_PORT);
10583 + rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
10584 + psin_server, sizeof (struct sockaddr_in),0);
10585 + if (rc >= 0)
10586 + connected = 1;
10587 + }
10588 +
10589 + /* give up here - unless we want to retry on different
10590 + protocol families some day */
10591 + if (!connected) {
10592 + if(orig_port)
10593 + psin_server->sin_port = orig_port;
10594 + cFYI(1,("Error %d connecting to server via ipv4",rc));
10595 + sock_release(*csocket);
10596 + *csocket = NULL;
10597 + return rc;
10598 + }
10599 + /* Eventually check for other socket options to change from
10600 + the default. sock_setsockopt not used because it expects
10601 + user space buffer */
10602 + (*csocket)->sk->rcvtimeo = 7 * HZ;
10603 +
10604 + /* send RFC1001 sessinit */
10605 +
10606 + if(psin_server->sin_port == htons(139)) {
10607 + /* some servers require RFC1001 sessinit before sending
10608 + negprot - BB check reconnection in case where second
10609 + sessinit is sent but no second negprot */
10610 + struct rfc1002_session_packet * ses_init_buf;
10611 + struct smb_hdr * smb_buf;
10612 + ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
10613 + if(ses_init_buf) {
10614 + ses_init_buf->trailer.session_req.called_len = 32;
10615 + rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
10616 + DEFAULT_CIFS_CALLED_NAME,16);
10617 + ses_init_buf->trailer.session_req.calling_len = 32;
10618 + /* calling name ends in null (byte 16) from old smb
10619 + convention. */
10620 + if(netbios_name && (netbios_name[0] !=0)) {
10621 + rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
10622 + netbios_name,16);
10623 + } else {
10624 + rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
10625 + "LINUX_CIFS_CLNT",16);
10626 + }
10627 + ses_init_buf->trailer.session_req.scope1 = 0;
10628 + ses_init_buf->trailer.session_req.scope2 = 0;
10629 + smb_buf = (struct smb_hdr *)ses_init_buf;
10630 + /* sizeof RFC1002_SESSION_REQUEST with no scope */
10631 + smb_buf->smb_buf_length = 0x81000044;
10632 + rc = smb_send(*csocket, smb_buf, 0x44,
10633 + (struct sockaddr *)psin_server);
10634 + kfree(ses_init_buf);
10635 + }
10636 + /* else the negprot may still work without this
10637 + even though malloc failed */
10638 +
10639 + }
10640 +
10641 + return rc;
10642 +}
10643 +
10644 +static int
10645 +ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
10646 +{
10647 + int rc = 0;
10648 + int connected = 0;
10649 +
10650 + if(*csocket == NULL) {
10651 + rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
10652 + if (rc < 0) {
10653 + cERROR(1, ("Error %d creating ipv6 socket",rc));
10654 + *csocket = NULL;
10655 + return rc;
10656 + } else {
10657 + /* BB other socket options to set KEEPALIVE, NODELAY? */
10658 + cFYI(1,("ipv6 Socket created"));
10659 + (*csocket)->sk->allocation = GFP_NOFS;
10660 + }
10661 + }
10662 +
10663 + psin_server->sin6_family = AF_INET6;
10664 +
10665 + if(psin_server->sin6_port) { /* user overrode default port */
10666 + rc = (*csocket)->ops->connect(*csocket,
10667 + (struct sockaddr *) psin_server,
10668 + sizeof (struct sockaddr_in6),0);
10669 + if (rc >= 0)
10670 + connected = 1;
10671 + }
10672 +
10673 + if(!connected) {
10674 + /* do not retry on the same port we just failed on */
10675 + if(psin_server->sin6_port != htons(CIFS_PORT)) {
10676 + psin_server->sin6_port = htons(CIFS_PORT);
10677 +
10678 + rc = (*csocket)->ops->connect(*csocket,
10679 + (struct sockaddr *) psin_server,
10680 + sizeof (struct sockaddr_in6),0);
10681 + if (rc >= 0)
10682 + connected = 1;
10683 + }
10684 + }
10685 + if (!connected) {
10686 + psin_server->sin6_port = htons(RFC1001_PORT);
10687 + rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
10688 + psin_server, sizeof (struct sockaddr_in6),0);
10689 + if (rc >= 0)
10690 + connected = 1;
10691 + }
10692 +
10693 + /* give up here - unless we want to retry on different
10694 + protocol families some day */
10695 + if (!connected) {
10696 + cFYI(1,("Error %d connecting to server via ipv6",rc));
10697 + sock_release(*csocket);
10698 + *csocket = NULL;
10699 + return rc;
10700 + }
10701 + /* Eventually check for other socket options to change from
10702 + the default. sock_setsockopt not used because it expects
10703 + user space buffer */
10704 + (*csocket)->sk->rcvtimeo = 7 * HZ;
10705 +
10706 + return rc;
10707 +}
10708 +
10709 +int
10710 +cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
10711 + char *mount_data, const char *devname)
10712 +{
10713 + int rc = 0;
10714 + int xid;
10715 + struct socket *csocket = NULL;
10716 + struct sockaddr_in sin_server;
10717 + struct sockaddr_in6 sin_server6;
10718 + struct smb_vol volume_info;
10719 + struct cifsSesInfo *pSesInfo = NULL;
10720 + struct cifsSesInfo *existingCifsSes = NULL;
10721 + struct cifsTconInfo *tcon = NULL;
10722 + struct TCP_Server_Info *srvTcp = NULL;
10723 +
10724 + xid = GetXid();
10725 +
10726 + cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); /* BB removeme BB fixme */
10727 +
10728 + memset(&volume_info,0,sizeof(struct smb_vol));
10729 + if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
10730 + if(volume_info.UNC)
10731 + kfree(volume_info.UNC);
10732 + if(volume_info.password)
10733 + kfree(volume_info.password);
10734 + FreeXid(xid);
10735 + return -EINVAL;
10736 + }
10737 +
10738 + if (volume_info.username) {
10739 + cFYI(1, ("Username: %s ", volume_info.username));
10740 +
10741 + } else {
10742 + cifserror("No username specified ");
10743 + /* In userspace mount helper we can get user name from alternate
10744 + locations such as env variables and files on disk */
10745 + if(volume_info.UNC)
10746 + kfree(volume_info.UNC);
10747 + if(volume_info.password)
10748 + kfree(volume_info.password);
10749 + FreeXid(xid);
10750 + return -EINVAL;
10751 + }
10752 +
10753 + if (volume_info.UNCip && volume_info.UNC) {
10754 + rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
10755 +
10756 + if(rc == 0) {
10757 + /* not ipv4 address, try ipv6 */
10758 + rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
10759 + }
10760 +
10761 + if(rc != 1) {
10762 + /* we failed translating address */
10763 + if(volume_info.UNC)
10764 + kfree(volume_info.UNC);
10765 + if(volume_info.password)
10766 + kfree(volume_info.password);
10767 + FreeXid(xid);
10768 + return -EINVAL;
10769 + }
10770 +
10771 + cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
10772 + /* success */
10773 + rc = 0;
10774 + } else if (volume_info.UNCip){
10775 + /* BB using ip addr as server name connect to the DFS root below */
10776 + cERROR(1,("Connecting to DFS root not implemented yet"));
10777 + if(volume_info.UNC)
10778 + kfree(volume_info.UNC);
10779 + if(volume_info.password)
10780 + kfree(volume_info.password);
10781 + FreeXid(xid);
10782 + return -EINVAL;
10783 + } else /* which servers DFS root would we conect to */ {
10784 + cERROR(1,
10785 + ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
10786 + if(volume_info.UNC)
10787 + kfree(volume_info.UNC);
10788 + if(volume_info.password)
10789 + kfree(volume_info.password);
10790 + FreeXid(xid);
10791 + return -EINVAL;
10792 + }
10793 +
10794 + /* this is needed for ASCII cp to Unicode converts */
10795 + if(volume_info.iocharset == NULL) {
10796 + cifs_sb->local_nls = load_nls_default();
10797 + /* load_nls_default can not return null */
10798 + } else {
10799 + cifs_sb->local_nls = load_nls(volume_info.iocharset);
10800 + if(cifs_sb->local_nls == NULL) {
10801 + cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
10802 + if(volume_info.UNC)
10803 + kfree(volume_info.UNC);
10804 + if(volume_info.password)
10805 + kfree(volume_info.password);
10806 + FreeXid(xid);
10807 + return -ELIBACC;
10808 + }
10809 + }
10810 +
10811 + existingCifsSes =
10812 + cifs_find_tcp_session(sin_server.sin_addr.s_addr,
10813 + volume_info.username, &srvTcp);
10814 + if (srvTcp) {
10815 + cFYI(1, ("Existing tcp session with server found "));
10816 + } else { /* create socket */
10817 + if(volume_info.port)
10818 + sin_server.sin_port = htons(volume_info.port);
10819 + else
10820 + sin_server.sin_port = 0;
10821 + rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
10822 + if (rc < 0) {
10823 + cERROR(1,
10824 + ("Error connecting to IPv4 socket. Aborting operation"));
10825 + if(csocket != NULL)
10826 + sock_release(csocket);
10827 + if(volume_info.UNC)
10828 + kfree(volume_info.UNC);
10829 + if(volume_info.password)
10830 + kfree(volume_info.password);
10831 + FreeXid(xid);
10832 + return rc;
10833 + }
10834 +
10835 + srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
10836 + if (srvTcp == NULL) {
10837 + rc = -ENOMEM;
10838 + sock_release(csocket);
10839 + if(volume_info.UNC)
10840 + kfree(volume_info.UNC);
10841 + if(volume_info.password)
10842 + kfree(volume_info.password);
10843 + FreeXid(xid);
10844 + return rc;
10845 + } else {
10846 + memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
10847 + memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
10848 + atomic_set(&srvTcp->inFlight,0);
10849 + /* BB Add code for ipv6 case too */
10850 + srvTcp->ssocket = csocket;
10851 + srvTcp->protocolType = IPV4;
10852 + init_waitqueue_head(&srvTcp->response_q);
10853 + init_waitqueue_head(&srvTcp->request_q);
10854 + INIT_LIST_HEAD(&srvTcp->pending_mid_q);
10855 + /* at this point we are the only ones with the pointer
10856 + to the struct since the kernel thread not created yet
10857 + so no need to spinlock this init of tcpStatus */
10858 + srvTcp->tcpStatus = CifsNew;
10859 + init_MUTEX(&srvTcp->tcpSem);
10860 + kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
10861 + CLONE_FS | CLONE_FILES | CLONE_VM);
10862 + memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
10863 + }
10864 + }
10865 +
10866 + if (existingCifsSes) {
10867 + pSesInfo = existingCifsSes;
10868 + cFYI(1, ("Existing smb sess found "));
10869 + if(volume_info.password)
10870 + kfree(volume_info.password);
10871 + /* volume_info.UNC freed at end of function */
10872 + } else if (!rc) {
10873 + cFYI(1, ("Existing smb sess not found "));
10874 + pSesInfo = sesInfoAlloc();
10875 + if (pSesInfo == NULL)
10876 + rc = -ENOMEM;
10877 + else {
10878 + pSesInfo->server = srvTcp;
10879 + sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
10880 + NIPQUAD(sin_server.sin_addr.s_addr));
10881 + }
10882 +
10883 + if (!rc){
10884 + /* volume_info.password freed at unmount */
10885 + if (volume_info.password)
10886 + pSesInfo->password = volume_info.password;
10887 + if (volume_info.username)
10888 + strncpy(pSesInfo->userName,
10889 + volume_info.username,MAX_USERNAME_SIZE);
10890 + if (volume_info.domainname)
10891 + strncpy(pSesInfo->domainName,
10892 + volume_info.domainname,MAX_USERNAME_SIZE);
10893 + pSesInfo->linux_uid = volume_info.linux_uid;
10894 + down(&pSesInfo->sesSem);
10895 + rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
10896 + up(&pSesInfo->sesSem);
10897 + if(!rc)
10898 + atomic_inc(&srvTcp->socketUseCount);
10899 + } else
10900 + if(volume_info.password)
10901 + kfree(volume_info.password);
10902 + }
10903 +
10904 + /* search for existing tcon to this server share */
10905 + if (!rc) {
10906 + if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
10907 + cifs_sb->rsize = volume_info.rsize;
10908 + else
10909 + cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
10910 + if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
10911 + cifs_sb->wsize = volume_info.wsize;
10912 + else
10913 + cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
10914 + if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
10915 + cifs_sb->rsize = PAGE_CACHE_SIZE;
10916 + cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
10917 + }
10918 + cifs_sb->mnt_uid = volume_info.linux_uid;
10919 + cifs_sb->mnt_gid = volume_info.linux_gid;
10920 + cifs_sb->mnt_file_mode = volume_info.file_mode;
10921 + cifs_sb->mnt_dir_mode = volume_info.dir_mode;
10922 + cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
10923 + tcon =
10924 + find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
10925 + volume_info.username);
10926 + if (tcon) {
10927 + cFYI(1, ("Found match on UNC path "));
10928 + /* we can have only one retry value for a connection
10929 + to a share so for resources mounted more than once
10930 + to the same server share the last value passed in
10931 + for the retry flag is used */
10932 + tcon->retry = volume_info.retry;
10933 + } else {
10934 + tcon = tconInfoAlloc();
10935 + if (tcon == NULL)
10936 + rc = -ENOMEM;
10937 + else {
10938 + /* check for null share name ie connect to dfs root */
10939 +
10940 + /* BB check if this works for exactly length three strings */
10941 + if ((strchr(volume_info.UNC + 3, '\\') == NULL)
10942 + && (strchr(volume_info.UNC + 3, '/') ==
10943 + NULL)) {
10944 + rc = connect_to_dfs_path(xid,
10945 + pSesInfo,
10946 + "",
10947 + cifs_sb->
10948 + local_nls);
10949 + if(volume_info.UNC)
10950 + kfree(volume_info.UNC);
10951 + FreeXid(xid);
10952 + return -ENODEV;
10953 + } else {
10954 + rc = CIFSTCon(xid, pSesInfo,
10955 + volume_info.UNC,
10956 + tcon, cifs_sb->local_nls);
10957 + cFYI(1, ("CIFS Tcon rc = %d", rc));
10958 + }
10959 + if (!rc) {
10960 + atomic_inc(&pSesInfo->inUse);
10961 + tcon->retry = volume_info.retry;
10962 + }
10963 + }
10964 + }
10965 + }
10966 + if(pSesInfo) {
10967 + if (pSesInfo->capabilities & CAP_LARGE_FILES) {
10968 + sb->s_maxbytes = (u64) 1 << 63;
10969 + } else
10970 + sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
10971 + }
10972 +
10973 +/* on error free sesinfo and tcon struct if needed */
10974 + if (rc) {
10975 + /* if session setup failed, use count is zero but
10976 + we still need to free cifsd thread */
10977 + if(atomic_read(&srvTcp->socketUseCount) == 0) {
10978 + spin_lock(&GlobalMid_Lock);
10979 + srvTcp->tcpStatus = CifsExiting;
10980 + spin_unlock(&GlobalMid_Lock);
10981 + if(srvTcp->tsk)
10982 + send_sig(SIGKILL,srvTcp->tsk,1);
10983 + }
10984 + /* If find_unc succeeded then rc == 0 so we can not end */
10985 + if (tcon) /* up accidently freeing someone elses tcon struct */
10986 + tconInfoFree(tcon);
10987 + if (existingCifsSes == 0) {
10988 + if (pSesInfo) {
10989 + if ((pSesInfo->server) &&
10990 + (pSesInfo->status == CifsGood)) {
10991 + int temp_rc;
10992 + temp_rc = CIFSSMBLogoff(xid, pSesInfo);
10993 + /* if the socketUseCount is now zero */
10994 + if((temp_rc == -ESHUTDOWN) &&
10995 + (pSesInfo->server->tsk))
10996 + send_sig(SIGKILL,pSesInfo->server->tsk,1);
10997 + } else
10998 + cFYI(1, ("No session or bad tcon"));
10999 + sesInfoFree(pSesInfo);
11000 + /* pSesInfo = NULL; */
11001 + }
11002 + }
11003 + } else {
11004 + atomic_inc(&tcon->useCount);
11005 + cifs_sb->tcon = tcon;
11006 + tcon->ses = pSesInfo;
11007 +
11008 + /* do not care if following two calls succeed - informational only */
11009 + CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
11010 + CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
11011 + if (tcon->ses->capabilities & CAP_UNIX)
11012 + CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
11013 + }
11014 +
11015 + /* volume_info.password is freed above when existing session found
11016 + (in which case it is not needed anymore) but when new sesion is created
11017 + the password ptr is put in the new session structure (in which case the
11018 + password will be freed at unmount time) */
11019 + if(volume_info.UNC)
11020 + kfree(volume_info.UNC);
11021 + FreeXid(xid);
11022 + return rc;
11023 +}
11024 +
11025 +static int
11026 +CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11027 + char session_key[CIFS_SESSION_KEY_SIZE],
11028 + const struct nls_table *nls_codepage)
11029 +{
11030 + struct smb_hdr *smb_buffer;
11031 + struct smb_hdr *smb_buffer_response;
11032 + SESSION_SETUP_ANDX *pSMB;
11033 + SESSION_SETUP_ANDX *pSMBr;
11034 + char *bcc_ptr;
11035 + char *user = ses->userName;
11036 + char *domain = ses->domainName;
11037 + int rc = 0;
11038 + int remaining_words = 0;
11039 + int bytes_returned = 0;
11040 + int len;
11041 +
11042 + cFYI(1, ("In sesssetup "));
11043 +
11044 + smb_buffer = cifs_buf_get();
11045 + if (smb_buffer == 0) {
11046 + return -ENOMEM;
11047 + }
11048 + smb_buffer_response = smb_buffer;
11049 + pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11050 +
11051 + /* send SMBsessionSetup here */
11052 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11053 + NULL /* no tCon exists yet */ , 13 /* wct */ );
11054 +
11055 + pSMB->req_no_secext.AndXCommand = 0xFF;
11056 + pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11057 + pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11058 +
11059 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11060 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11061 +
11062 + pSMB->req_no_secext.Capabilities =
11063 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
11064 + if (ses->capabilities & CAP_UNICODE) {
11065 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11066 + pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
11067 + }
11068 + if (ses->capabilities & CAP_STATUS32) {
11069 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11070 + pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
11071 + }
11072 + if (ses->capabilities & CAP_DFS) {
11073 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11074 + pSMB->req_no_secext.Capabilities |= CAP_DFS;
11075 + }
11076 + pSMB->req_no_secext.Capabilities =
11077 + cpu_to_le32(pSMB->req_no_secext.Capabilities);
11078 + /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
11079 + CIFS_SESSION_KEY_SIZE; */
11080 + pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
11081 + pSMB->req_no_secext.CaseSensitivePasswordLength =
11082 + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11083 + bcc_ptr = pByteArea(smb_buffer);
11084 + /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
11085 + bcc_ptr += CIFS_SESSION_KEY_SIZE; */
11086 + memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
11087 + bcc_ptr += CIFS_SESSION_KEY_SIZE;
11088 +
11089 + if (ses->capabilities & CAP_UNICODE) {
11090 + if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
11091 + *bcc_ptr = 0;
11092 + bcc_ptr++;
11093 + }
11094 + if(user == NULL)
11095 + bytes_returned = 0; /* skill null user */
11096 + else
11097 + bytes_returned =
11098 + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
11099 + nls_codepage);
11100 + bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
11101 + bcc_ptr += 2; /* trailing null */
11102 + if (domain == NULL)
11103 + bytes_returned =
11104 + cifs_strtoUCS((wchar_t *) bcc_ptr,
11105 + "CIFS_LINUX_DOM", 32, nls_codepage);
11106 + else
11107 + bytes_returned =
11108 + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11109 + nls_codepage);
11110 + bcc_ptr += 2 * bytes_returned;
11111 + bcc_ptr += 2;
11112 + bytes_returned =
11113 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11114 + 32, nls_codepage);
11115 + bcc_ptr += 2 * bytes_returned;
11116 + bytes_returned =
11117 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11118 + nls_codepage);
11119 + bcc_ptr += 2 * bytes_returned;
11120 + bcc_ptr += 2;
11121 + bytes_returned =
11122 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11123 + 64, nls_codepage);
11124 + bcc_ptr += 2 * bytes_returned;
11125 + bcc_ptr += 2;
11126 + } else {
11127 + if(user != NULL) {
11128 + strncpy(bcc_ptr, user, 200);
11129 + bcc_ptr += strnlen(user, 200);
11130 + }
11131 + *bcc_ptr = 0;
11132 + bcc_ptr++;
11133 + if (domain == NULL) {
11134 + strcpy(bcc_ptr, "CIFS_LINUX_DOM");
11135 + bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
11136 + } else {
11137 + strncpy(bcc_ptr, domain, 64);
11138 + bcc_ptr += strnlen(domain, 64);
11139 + *bcc_ptr = 0;
11140 + bcc_ptr++;
11141 + }
11142 + strcpy(bcc_ptr, "Linux version ");
11143 + bcc_ptr += strlen("Linux version ");
11144 + strcpy(bcc_ptr, UTS_RELEASE);
11145 + bcc_ptr += strlen(UTS_RELEASE) + 1;
11146 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11147 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11148 + }
11149 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11150 + smb_buffer->smb_buf_length += BCC(smb_buffer);
11151 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11152 +
11153 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11154 + &bytes_returned, 1);
11155 + if (rc) {
11156 +/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
11157 + } else if ((smb_buffer_response->WordCount == 3)
11158 + || (smb_buffer_response->WordCount == 4)) {
11159 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11160 + if (pSMBr->resp.Action & GUEST_LOGIN)
11161 + cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
11162 + if (ses) {
11163 + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
11164 + cFYI(1, ("UID = %d ", ses->Suid));
11165 + /* response can have either 3 or 4 word count - Samba sends 3 */
11166 + bcc_ptr = pByteArea(smb_buffer_response);
11167 + if ((pSMBr->resp.hdr.WordCount == 3)
11168 + || ((pSMBr->resp.hdr.WordCount == 4)
11169 + && (pSMBr->resp.SecurityBlobLength <
11170 + pSMBr->resp.ByteCount))) {
11171 + if (pSMBr->resp.hdr.WordCount == 4)
11172 + bcc_ptr +=
11173 + pSMBr->resp.SecurityBlobLength;
11174 +
11175 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11176 + if ((long) (bcc_ptr) % 2) {
11177 + remaining_words =
11178 + (BCC(smb_buffer_response)
11179 + - 1) / 2;
11180 + bcc_ptr++; /* Unicode strings must be word aligned */
11181 + } else {
11182 + remaining_words =
11183 + BCC
11184 + (smb_buffer_response) / 2;
11185 + }
11186 + len =
11187 + UniStrnlen((wchar_t *) bcc_ptr,
11188 + remaining_words - 1);
11189 +/* We look for obvious messed up bcc or strings in response so we do not go off
11190 + the end since (at least) WIN2K and Windows XP have a major bug in not null
11191 + terminating last Unicode string in response */
11192 + ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11193 + cifs_strfromUCS_le(ses->serverOS,
11194 + (wchar_t *)bcc_ptr, len,nls_codepage);
11195 + bcc_ptr += 2 * (len + 1);
11196 + remaining_words -= len + 1;
11197 + ses->serverOS[2 * len] = 0;
11198 + ses->serverOS[1 + (2 * len)] = 0;
11199 + if (remaining_words > 0) {
11200 + len = UniStrnlen((wchar_t *)bcc_ptr,
11201 + remaining_words
11202 + - 1);
11203 + ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
11204 + cifs_strfromUCS_le(ses->serverNOS,
11205 + (wchar_t *)bcc_ptr,len,nls_codepage);
11206 + bcc_ptr += 2 * (len + 1);
11207 + ses->serverNOS[2 * len] = 0;
11208 + ses->serverNOS[1 + (2 * len)] = 0;
11209 + remaining_words -= len + 1;
11210 + if (remaining_words > 0) {
11211 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11212 + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11213 + ses->serverDomain =
11214 + cifs_kcalloc(2*(len+1),GFP_KERNEL);
11215 + cifs_strfromUCS_le(ses->serverDomain,
11216 + (wchar_t *)bcc_ptr,len,nls_codepage);
11217 + bcc_ptr += 2 * (len + 1);
11218 + ses->serverDomain[2*len] = 0;
11219 + ses->serverDomain[1+(2*len)] = 0;
11220 + } /* else no more room so create dummy domain string */
11221 + else
11222 + ses->serverDomain =
11223 + cifs_kcalloc(2,
11224 + GFP_KERNEL);
11225 + } else { /* no room so create dummy domain and NOS string */
11226 + ses->serverDomain =
11227 + cifs_kcalloc(2, GFP_KERNEL);
11228 + ses->serverNOS =
11229 + cifs_kcalloc(2, GFP_KERNEL);
11230 + }
11231 + } else { /* ASCII */
11232 + len = strnlen(bcc_ptr, 1024);
11233 + if (((long) bcc_ptr + len) - (long)
11234 + pByteArea(smb_buffer_response)
11235 + <= BCC(smb_buffer_response)) {
11236 + ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11237 + strncpy(ses->serverOS,bcc_ptr, len);
11238 +
11239 + bcc_ptr += len;
11240 + bcc_ptr[0] = 0; /* null terminate the string */
11241 + bcc_ptr++;
11242 +
11243 + len = strnlen(bcc_ptr, 1024);
11244 + ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11245 + strncpy(ses->serverNOS, bcc_ptr, len);
11246 + bcc_ptr += len;
11247 + bcc_ptr[0] = 0;
11248 + bcc_ptr++;
11249 +
11250 + len = strnlen(bcc_ptr, 1024);
11251 + ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
11252 + strncpy(ses->serverDomain, bcc_ptr, len);
11253 + bcc_ptr += len;
11254 + bcc_ptr[0] = 0;
11255 + bcc_ptr++;
11256 + } else
11257 + cFYI(1,
11258 + ("Variable field of length %d extends beyond end of smb ",
11259 + len));
11260 + }
11261 + } else {
11262 + cERROR(1,
11263 + (" Security Blob Length extends beyond end of SMB"));
11264 + }
11265 + } else {
11266 + cERROR(1, ("No session structure passed in."));
11267 + }
11268 + } else {
11269 + cERROR(1,
11270 + (" Invalid Word count %d: ",
11271 + smb_buffer_response->WordCount));
11272 + rc = -EIO;
11273 + }
11274 +
11275 + if (smb_buffer)
11276 + cifs_buf_release(smb_buffer);
11277 +
11278 + return rc;
11279 +}
11280 +
11281 +static int
11282 +CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11283 + char *SecurityBlob,int SecurityBlobLength,
11284 + const struct nls_table *nls_codepage)
11285 +{
11286 + struct smb_hdr *smb_buffer;
11287 + struct smb_hdr *smb_buffer_response;
11288 + SESSION_SETUP_ANDX *pSMB;
11289 + SESSION_SETUP_ANDX *pSMBr;
11290 + char *bcc_ptr;
11291 + char *user = ses->userName;
11292 + char *domain = ses->domainName;
11293 + int rc = 0;
11294 + int remaining_words = 0;
11295 + int bytes_returned = 0;
11296 + int len;
11297 +
11298 + cFYI(1, ("In spnego sesssetup "));
11299 +
11300 + smb_buffer = cifs_buf_get();
11301 + if (smb_buffer == 0) {
11302 + return -ENOMEM;
11303 + }
11304 + smb_buffer_response = smb_buffer;
11305 + pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11306 +
11307 + /* send SMBsessionSetup here */
11308 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11309 + NULL /* no tCon exists yet */ , 12 /* wct */ );
11310 + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11311 + pSMB->req.AndXCommand = 0xFF;
11312 + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11313 + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11314 +
11315 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11316 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11317 +
11318 + pSMB->req.Capabilities =
11319 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11320 + CAP_EXTENDED_SECURITY;
11321 + if (ses->capabilities & CAP_UNICODE) {
11322 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11323 + pSMB->req.Capabilities |= CAP_UNICODE;
11324 + }
11325 + if (ses->capabilities & CAP_STATUS32) {
11326 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11327 + pSMB->req.Capabilities |= CAP_STATUS32;
11328 + }
11329 + if (ses->capabilities & CAP_DFS) {
11330 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11331 + pSMB->req.Capabilities |= CAP_DFS;
11332 + }
11333 + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11334 +
11335 + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
11336 + bcc_ptr = pByteArea(smb_buffer);
11337 + memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
11338 + bcc_ptr += SecurityBlobLength;
11339 +
11340 + if (ses->capabilities & CAP_UNICODE) {
11341 + if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
11342 + *bcc_ptr = 0;
11343 + bcc_ptr++;
11344 + }
11345 + bytes_returned =
11346 + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
11347 + bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
11348 + bcc_ptr += 2; /* trailing null */
11349 + if (domain == NULL)
11350 + bytes_returned =
11351 + cifs_strtoUCS((wchar_t *) bcc_ptr,
11352 + "CIFS_LINUX_DOM", 32, nls_codepage);
11353 + else
11354 + bytes_returned =
11355 + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11356 + nls_codepage);
11357 + bcc_ptr += 2 * bytes_returned;
11358 + bcc_ptr += 2;
11359 + bytes_returned =
11360 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11361 + 32, nls_codepage);
11362 + bcc_ptr += 2 * bytes_returned;
11363 + bytes_returned =
11364 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11365 + nls_codepage);
11366 + bcc_ptr += 2 * bytes_returned;
11367 + bcc_ptr += 2;
11368 + bytes_returned =
11369 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11370 + 64, nls_codepage);
11371 + bcc_ptr += 2 * bytes_returned;
11372 + bcc_ptr += 2;
11373 + } else {
11374 + strncpy(bcc_ptr, user, 200);
11375 + bcc_ptr += strnlen(user, 200);
11376 + *bcc_ptr = 0;
11377 + bcc_ptr++;
11378 + if (domain == NULL) {
11379 + strcpy(bcc_ptr, "CIFS_LINUX_DOM");
11380 + bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
11381 + } else {
11382 + strncpy(bcc_ptr, domain, 64);
11383 + bcc_ptr += strnlen(domain, 64);
11384 + *bcc_ptr = 0;
11385 + bcc_ptr++;
11386 + }
11387 + strcpy(bcc_ptr, "Linux version ");
11388 + bcc_ptr += strlen("Linux version ");
11389 + strcpy(bcc_ptr, UTS_RELEASE);
11390 + bcc_ptr += strlen(UTS_RELEASE) + 1;
11391 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11392 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11393 + }
11394 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11395 + smb_buffer->smb_buf_length += BCC(smb_buffer);
11396 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11397 +
11398 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11399 + &bytes_returned, 1);
11400 + if (rc) {
11401 +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
11402 + } else if ((smb_buffer_response->WordCount == 3)
11403 + || (smb_buffer_response->WordCount == 4)) {
11404 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11405 + pSMBr->resp.SecurityBlobLength =
11406 + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
11407 + if (pSMBr->resp.Action & GUEST_LOGIN)
11408 + cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
11409 + if (ses) {
11410 + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
11411 + cFYI(1, ("UID = %d ", ses->Suid));
11412 + bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
11413 +
11414 + /* BB Fix below to make endian neutral !! */
11415 +
11416 + if ((pSMBr->resp.hdr.WordCount == 3)
11417 + || ((pSMBr->resp.hdr.WordCount == 4)
11418 + && (pSMBr->resp.SecurityBlobLength <
11419 + pSMBr->resp.ByteCount))) {
11420 + if (pSMBr->resp.hdr.WordCount == 4) {
11421 + bcc_ptr +=
11422 + pSMBr->resp.SecurityBlobLength;
11423 + cFYI(1,
11424 + ("Security Blob Length %d ",
11425 + pSMBr->resp.SecurityBlobLength));
11426 + }
11427 +
11428 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11429 + if ((long) (bcc_ptr) % 2) {
11430 + remaining_words =
11431 + (BCC(smb_buffer_response)
11432 + - 1) / 2;
11433 + bcc_ptr++; /* Unicode strings must be word aligned */
11434 + } else {
11435 + remaining_words =
11436 + BCC
11437 + (smb_buffer_response) / 2;
11438 + }
11439 + len =
11440 + UniStrnlen((wchar_t *) bcc_ptr,
11441 + remaining_words - 1);
11442 +/* We look for obvious messed up bcc or strings in response so we do not go off
11443 + the end since (at least) WIN2K and Windows XP have a major bug in not null
11444 + terminating last Unicode string in response */
11445 + ses->serverOS =
11446 + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11447 + cifs_strfromUCS_le(ses->serverOS,
11448 + (wchar_t *)
11449 + bcc_ptr, len,
11450 + nls_codepage);
11451 + bcc_ptr += 2 * (len + 1);
11452 + remaining_words -= len + 1;
11453 + ses->serverOS[2 * len] = 0;
11454 + ses->serverOS[1 + (2 * len)] = 0;
11455 + if (remaining_words > 0) {
11456 + len = UniStrnlen((wchar_t *)bcc_ptr,
11457 + remaining_words
11458 + - 1);
11459 + ses->serverNOS =
11460 + cifs_kcalloc(2 * (len + 1),
11461 + GFP_KERNEL);
11462 + cifs_strfromUCS_le(ses->serverNOS,
11463 + (wchar_t *)bcc_ptr,
11464 + len,
11465 + nls_codepage);
11466 + bcc_ptr += 2 * (len + 1);
11467 + ses->serverNOS[2 * len] = 0;
11468 + ses->serverNOS[1 + (2 * len)] = 0;
11469 + remaining_words -= len + 1;
11470 + if (remaining_words > 0) {
11471 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11472 + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11473 + ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
11474 + cifs_strfromUCS_le(ses->serverDomain,
11475 + (wchar_t *)bcc_ptr,
11476 + len,
11477 + nls_codepage);
11478 + bcc_ptr += 2*(len+1);
11479 + ses->serverDomain[2*len] = 0;
11480 + ses->serverDomain[1+(2*len)] = 0;
11481 + } /* else no more room so create dummy domain string */
11482 + else
11483 + ses->serverDomain =
11484 + cifs_kcalloc(2,GFP_KERNEL);
11485 + } else { /* no room so create dummy domain and NOS string */
11486 + ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
11487 + ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
11488 + }
11489 + } else { /* ASCII */
11490 +
11491 + len = strnlen(bcc_ptr, 1024);
11492 + if (((long) bcc_ptr + len) - (long)
11493 + pByteArea(smb_buffer_response)
11494 + <= BCC(smb_buffer_response)) {
11495 + ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
11496 + strncpy(ses->serverOS, bcc_ptr, len);
11497 +
11498 + bcc_ptr += len;
11499 + bcc_ptr[0] = 0; /* null terminate the string */
11500 + bcc_ptr++;
11501 +
11502 + len = strnlen(bcc_ptr, 1024);
11503 + ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
11504 + strncpy(ses->serverNOS, bcc_ptr, len);
11505 + bcc_ptr += len;
11506 + bcc_ptr[0] = 0;
11507 + bcc_ptr++;
11508 +
11509 + len = strnlen(bcc_ptr, 1024);
11510 + ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
11511 + strncpy(ses->serverDomain, bcc_ptr, len);
11512 + bcc_ptr += len;
11513 + bcc_ptr[0] = 0;
11514 + bcc_ptr++;
11515 + } else
11516 + cFYI(1,
11517 + ("Variable field of length %d extends beyond end of smb ",
11518 + len));
11519 + }
11520 + } else {
11521 + cERROR(1,
11522 + (" Security Blob Length extends beyond end of SMB"));
11523 + }
11524 + } else {
11525 + cERROR(1, ("No session structure passed in."));
11526 + }
11527 + } else {
11528 + cERROR(1,
11529 + (" Invalid Word count %d: ",
11530 + smb_buffer_response->WordCount));
11531 + rc = -EIO;
11532 + }
11533 +
11534 + if (smb_buffer)
11535 + cifs_buf_release(smb_buffer);
11536 +
11537 + return rc;
11538 +}
11539 +
11540 +static int
11541 +CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
11542 + struct cifsSesInfo *ses, int * pNTLMv2_flag,
11543 + const struct nls_table *nls_codepage)
11544 +{
11545 + struct smb_hdr *smb_buffer;
11546 + struct smb_hdr *smb_buffer_response;
11547 + SESSION_SETUP_ANDX *pSMB;
11548 + SESSION_SETUP_ANDX *pSMBr;
11549 + char *bcc_ptr;
11550 + char *domain = ses->domainName;
11551 + int rc = 0;
11552 + int remaining_words = 0;
11553 + int bytes_returned = 0;
11554 + int len;
11555 + int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
11556 + PNEGOTIATE_MESSAGE SecurityBlob;
11557 + PCHALLENGE_MESSAGE SecurityBlob2;
11558 +
11559 + cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
11560 + *pNTLMv2_flag = FALSE;
11561 + smb_buffer = cifs_buf_get();
11562 + if (smb_buffer == 0) {
11563 + return -ENOMEM;
11564 + }
11565 + smb_buffer_response = smb_buffer;
11566 + pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11567 + pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
11568 +
11569 + /* send SMBsessionSetup here */
11570 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11571 + NULL /* no tCon exists yet */ , 12 /* wct */ );
11572 + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11573 + pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
11574 +
11575 + pSMB->req.AndXCommand = 0xFF;
11576 + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11577 + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11578 +
11579 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11580 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11581 +
11582 + pSMB->req.Capabilities =
11583 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11584 + CAP_EXTENDED_SECURITY;
11585 + if (ses->capabilities & CAP_UNICODE) {
11586 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11587 + pSMB->req.Capabilities |= CAP_UNICODE;
11588 + }
11589 + if (ses->capabilities & CAP_STATUS32) {
11590 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11591 + pSMB->req.Capabilities |= CAP_STATUS32;
11592 + }
11593 + if (ses->capabilities & CAP_DFS) {
11594 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11595 + pSMB->req.Capabilities |= CAP_DFS;
11596 + }
11597 + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11598 +
11599 + bcc_ptr = (char *) &pSMB->req.SecurityBlob;
11600 + SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
11601 + strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
11602 + SecurityBlob->MessageType = NtLmNegotiate;
11603 + SecurityBlob->NegotiateFlags =
11604 + NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
11605 + NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
11606 + /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
11607 + if(sign_CIFS_PDUs)
11608 + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
11609 + if(ntlmv2_support)
11610 + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
11611 + /* setup pointers to domain name and workstation name */
11612 + bcc_ptr += SecurityBlobLength;
11613 +
11614 + SecurityBlob->WorkstationName.Buffer = 0;
11615 + SecurityBlob->WorkstationName.Length = 0;
11616 + SecurityBlob->WorkstationName.MaximumLength = 0;
11617 +
11618 + if (domain == NULL) {
11619 + SecurityBlob->DomainName.Buffer = 0;
11620 + SecurityBlob->DomainName.Length = 0;
11621 + SecurityBlob->DomainName.MaximumLength = 0;
11622 + } else {
11623 + SecurityBlob->NegotiateFlags |=
11624 + NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
11625 + strncpy(bcc_ptr, domain, 63);
11626 + SecurityBlob->DomainName.Length = strnlen(domain, 64);
11627 + SecurityBlob->DomainName.MaximumLength =
11628 + cpu_to_le16(SecurityBlob->DomainName.Length);
11629 + SecurityBlob->DomainName.Buffer =
11630 + cpu_to_le32((long) &SecurityBlob->
11631 + DomainString -
11632 + (long) &SecurityBlob->Signature);
11633 + bcc_ptr += SecurityBlob->DomainName.Length;
11634 + SecurityBlobLength += SecurityBlob->DomainName.Length;
11635 + SecurityBlob->DomainName.Length =
11636 + cpu_to_le16(SecurityBlob->DomainName.Length);
11637 + }
11638 + if (ses->capabilities & CAP_UNICODE) {
11639 + if ((long) bcc_ptr % 2) {
11640 + *bcc_ptr = 0;
11641 + bcc_ptr++;
11642 + }
11643 +
11644 + bytes_returned =
11645 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
11646 + 32, nls_codepage);
11647 + bcc_ptr += 2 * bytes_returned;
11648 + bytes_returned =
11649 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
11650 + nls_codepage);
11651 + bcc_ptr += 2 * bytes_returned;
11652 + bcc_ptr += 2; /* null terminate Linux version */
11653 + bytes_returned =
11654 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
11655 + 64, nls_codepage);
11656 + bcc_ptr += 2 * bytes_returned;
11657 + *(bcc_ptr + 1) = 0;
11658 + *(bcc_ptr + 2) = 0;
11659 + bcc_ptr += 2; /* null terminate network opsys string */
11660 + *(bcc_ptr + 1) = 0;
11661 + *(bcc_ptr + 2) = 0;
11662 + bcc_ptr += 2; /* null domain */
11663 + } else { /* ASCII */
11664 + strcpy(bcc_ptr, "Linux version ");
11665 + bcc_ptr += strlen("Linux version ");
11666 + strcpy(bcc_ptr, UTS_RELEASE);
11667 + bcc_ptr += strlen(UTS_RELEASE) + 1;
11668 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
11669 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
11670 + bcc_ptr++; /* empty domain field */
11671 + *bcc_ptr = 0;
11672 + }
11673 + SecurityBlob->NegotiateFlags =
11674 + cpu_to_le32(SecurityBlob->NegotiateFlags);
11675 + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
11676 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
11677 + smb_buffer->smb_buf_length += BCC(smb_buffer);
11678 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
11679 +
11680 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
11681 + &bytes_returned, 1);
11682 +
11683 + if (smb_buffer_response->Status.CifsError ==
11684 + (NT_STATUS_MORE_PROCESSING_REQUIRED))
11685 + rc = 0;
11686 +
11687 + if (rc) {
11688 +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
11689 + } else if ((smb_buffer_response->WordCount == 3)
11690 + || (smb_buffer_response->WordCount == 4)) {
11691 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
11692 + pSMBr->resp.SecurityBlobLength =
11693 + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
11694 + if (pSMBr->resp.Action & GUEST_LOGIN)
11695 + cFYI(1, (" Guest login"));
11696 + /* Do we want to set anything in SesInfo struct when guest login? */
11697 +
11698 + bcc_ptr = pByteArea(smb_buffer_response);
11699 + /* response can have either 3 or 4 word count - Samba sends 3 */
11700 +
11701 + SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
11702 + if (SecurityBlob2->MessageType != NtLmChallenge) {
11703 + cFYI(1,
11704 + ("Unexpected NTLMSSP message type received %d",
11705 + SecurityBlob2->MessageType));
11706 + } else if (ses) {
11707 + ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
11708 + cFYI(1, ("UID = %d ", ses->Suid));
11709 + if ((pSMBr->resp.hdr.WordCount == 3)
11710 + || ((pSMBr->resp.hdr.WordCount == 4)
11711 + && (pSMBr->resp.SecurityBlobLength <
11712 + pSMBr->resp.ByteCount))) {
11713 + if (pSMBr->resp.hdr.WordCount == 4) {
11714 + bcc_ptr +=
11715 + pSMBr->resp.SecurityBlobLength;
11716 + cFYI(1,
11717 + ("Security Blob Length %d ",
11718 + pSMBr->resp.SecurityBlobLength));
11719 + }
11720 +
11721 + cFYI(1, ("NTLMSSP Challenge rcvd "));
11722 +
11723 + memcpy(ses->server->cryptKey,
11724 + SecurityBlob2->Challenge,
11725 + CIFS_CRYPTO_KEY_SIZE);
11726 + if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
11727 + *pNTLMv2_flag = TRUE;
11728 +
11729 + if((SecurityBlob2->NegotiateFlags &
11730 + NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
11731 + || (sign_CIFS_PDUs > 1))
11732 + ses->server->secMode |=
11733 + SECMODE_SIGN_REQUIRED;
11734 + if ((SecurityBlob2->NegotiateFlags &
11735 + NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
11736 + ses->server->secMode |=
11737 + SECMODE_SIGN_ENABLED;
11738 +
11739 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
11740 + if ((long) (bcc_ptr) % 2) {
11741 + remaining_words =
11742 + (BCC(smb_buffer_response)
11743 + - 1) / 2;
11744 + bcc_ptr++; /* Unicode strings must be word aligned */
11745 + } else {
11746 + remaining_words =
11747 + BCC
11748 + (smb_buffer_response) / 2;
11749 + }
11750 + len =
11751 + UniStrnlen((wchar_t *) bcc_ptr,
11752 + remaining_words - 1);
11753 +/* We look for obvious messed up bcc or strings in response so we do not go off
11754 + the end since (at least) WIN2K and Windows XP have a major bug in not null
11755 + terminating last Unicode string in response */
11756 + ses->serverOS =
11757 + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
11758 + cifs_strfromUCS_le(ses->serverOS,
11759 + (wchar_t *)
11760 + bcc_ptr, len,
11761 + nls_codepage);
11762 + bcc_ptr += 2 * (len + 1);
11763 + remaining_words -= len + 1;
11764 + ses->serverOS[2 * len] = 0;
11765 + ses->serverOS[1 + (2 * len)] = 0;
11766 + if (remaining_words > 0) {
11767 + len = UniStrnlen((wchar_t *)
11768 + bcc_ptr,
11769 + remaining_words
11770 + - 1);
11771 + ses->serverNOS =
11772 + cifs_kcalloc(2 * (len + 1),
11773 + GFP_KERNEL);
11774 + cifs_strfromUCS_le(ses->
11775 + serverNOS,
11776 + (wchar_t *)
11777 + bcc_ptr,
11778 + len,
11779 + nls_codepage);
11780 + bcc_ptr += 2 * (len + 1);
11781 + ses->serverNOS[2 * len] = 0;
11782 + ses->serverNOS[1 +
11783 + (2 * len)] = 0;
11784 + remaining_words -= len + 1;
11785 + if (remaining_words > 0) {
11786 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
11787 + /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
11788 + ses->serverDomain =
11789 + cifs_kcalloc(2 *
11790 + (len +
11791 + 1),
11792 + GFP_KERNEL);
11793 + cifs_strfromUCS_le
11794 + (ses->
11795 + serverDomain,
11796 + (wchar_t *)
11797 + bcc_ptr, len,
11798 + nls_codepage);
11799 + bcc_ptr +=
11800 + 2 * (len + 1);
11801 + ses->
11802 + serverDomain[2
11803 + * len]
11804 + = 0;
11805 + ses->
11806 + serverDomain[1
11807 + +
11808 + (2
11809 + *
11810 + len)]
11811 + = 0;
11812 + } /* else no more room so create dummy domain string */
11813 + else
11814 + ses->serverDomain =
11815 + cifs_kcalloc(2,
11816 + GFP_KERNEL);
11817 + } else { /* no room so create dummy domain and NOS string */
11818 + ses->serverDomain =
11819 + cifs_kcalloc(2, GFP_KERNEL);
11820 + ses->serverNOS =
11821 + cifs_kcalloc(2, GFP_KERNEL);
11822 + }
11823 + } else { /* ASCII */
11824 + len = strnlen(bcc_ptr, 1024);
11825 + if (((long) bcc_ptr + len) - (long)
11826 + pByteArea(smb_buffer_response)
11827 + <= BCC(smb_buffer_response)) {
11828 + ses->serverOS =
11829 + cifs_kcalloc(len + 1,
11830 + GFP_KERNEL);
11831 + strncpy(ses->serverOS,
11832 + bcc_ptr, len);
11833 +
11834 + bcc_ptr += len;
11835 + bcc_ptr[0] = 0; /* null terminate string */
11836 + bcc_ptr++;
11837 +
11838 + len = strnlen(bcc_ptr, 1024);
11839 + ses->serverNOS =
11840 + cifs_kcalloc(len + 1,
11841 + GFP_KERNEL);
11842 + strncpy(ses->serverNOS, bcc_ptr, len);
11843 + bcc_ptr += len;
11844 + bcc_ptr[0] = 0;
11845 + bcc_ptr++;
11846 +
11847 + len = strnlen(bcc_ptr, 1024);
11848 + ses->serverDomain =
11849 + cifs_kcalloc(len + 1,
11850 + GFP_KERNEL);
11851 + strncpy(ses->serverDomain, bcc_ptr, len);
11852 + bcc_ptr += len;
11853 + bcc_ptr[0] = 0;
11854 + bcc_ptr++;
11855 + } else
11856 + cFYI(1,
11857 + ("Variable field of length %d extends beyond end of smb ",
11858 + len));
11859 + }
11860 + } else {
11861 + cERROR(1,
11862 + (" Security Blob Length extends beyond end of SMB"));
11863 + }
11864 + } else {
11865 + cERROR(1, ("No session structure passed in."));
11866 + }
11867 + } else {
11868 + cERROR(1,
11869 + (" Invalid Word count %d: ",
11870 + smb_buffer_response->WordCount));
11871 + rc = -EIO;
11872 + }
11873 +
11874 + if (smb_buffer)
11875 + cifs_buf_release(smb_buffer);
11876 +
11877 + return rc;
11878 +}
11879 +
11880 +static int
11881 +CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
11882 + char *ntlm_session_key, int ntlmv2_flag,
11883 + const struct nls_table *nls_codepage)
11884 +{
11885 + struct smb_hdr *smb_buffer;
11886 + struct smb_hdr *smb_buffer_response;
11887 + SESSION_SETUP_ANDX *pSMB;
11888 + SESSION_SETUP_ANDX *pSMBr;
11889 + char *bcc_ptr;
11890 + char *user = ses->userName;
11891 + char *domain = ses->domainName;
11892 + int rc = 0;
11893 + int remaining_words = 0;
11894 + int bytes_returned = 0;
11895 + int len;
11896 + int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
11897 + PAUTHENTICATE_MESSAGE SecurityBlob;
11898 +
11899 + cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
11900 +
11901 + smb_buffer = cifs_buf_get();
11902 + if (smb_buffer == 0) {
11903 + return -ENOMEM;
11904 + }
11905 + smb_buffer_response = smb_buffer;
11906 + pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
11907 + pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
11908 +
11909 + /* send SMBsessionSetup here */
11910 + header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
11911 + NULL /* no tCon exists yet */ , 12 /* wct */ );
11912 + pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
11913 + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
11914 + pSMB->req.AndXCommand = 0xFF;
11915 + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
11916 + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
11917 +
11918 + pSMB->req.hdr.Uid = ses->Suid;
11919 +
11920 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
11921 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
11922 +
11923 + pSMB->req.Capabilities =
11924 + CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
11925 + CAP_EXTENDED_SECURITY;
11926 + if (ses->capabilities & CAP_UNICODE) {
11927 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
11928 + pSMB->req.Capabilities |= CAP_UNICODE;
11929 + }
11930 + if (ses->capabilities & CAP_STATUS32) {
11931 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
11932 + pSMB->req.Capabilities |= CAP_STATUS32;
11933 + }
11934 + if (ses->capabilities & CAP_DFS) {
11935 + smb_buffer->Flags2 |= SMBFLG2_DFS;
11936 + pSMB->req.Capabilities |= CAP_DFS;
11937 + }
11938 + pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
11939 +
11940 + bcc_ptr = (char *) &pSMB->req.SecurityBlob;
11941 + SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
11942 + strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
11943 + SecurityBlob->MessageType = NtLmAuthenticate;
11944 + bcc_ptr += SecurityBlobLength;
11945 + SecurityBlob->NegotiateFlags =
11946 + NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
11947 + NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
11948 + 0x80000000 | NTLMSSP_NEGOTIATE_128;
11949 + if(sign_CIFS_PDUs)
11950 + SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
11951 + if(ntlmv2_flag)
11952 + SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
11953 +
11954 +/* setup pointers to domain name and workstation name */
11955 +
11956 + SecurityBlob->WorkstationName.Buffer = 0;
11957 + SecurityBlob->WorkstationName.Length = 0;
11958 + SecurityBlob->WorkstationName.MaximumLength = 0;
11959 + SecurityBlob->SessionKey.Length = 0;
11960 + SecurityBlob->SessionKey.MaximumLength = 0;
11961 + SecurityBlob->SessionKey.Buffer = 0;
11962 +
11963 + SecurityBlob->LmChallengeResponse.Length = 0;
11964 + SecurityBlob->LmChallengeResponse.MaximumLength = 0;
11965 + SecurityBlob->LmChallengeResponse.Buffer = 0;
11966 +
11967 + SecurityBlob->NtChallengeResponse.Length =
11968 + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11969 + SecurityBlob->NtChallengeResponse.MaximumLength =
11970 + cpu_to_le16(CIFS_SESSION_KEY_SIZE);
11971 + memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
11972 + SecurityBlob->NtChallengeResponse.Buffer =
11973 + cpu_to_le32(SecurityBlobLength);
11974 + SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
11975 + bcc_ptr += CIFS_SESSION_KEY_SIZE;
11976 +
11977 + if (ses->capabilities & CAP_UNICODE) {
11978 + if (domain == NULL) {
11979 + SecurityBlob->DomainName.Buffer = 0;
11980 + SecurityBlob->DomainName.Length = 0;
11981 + SecurityBlob->DomainName.MaximumLength = 0;
11982 + } else {
11983 + SecurityBlob->DomainName.Length =
11984 + cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
11985 + nls_codepage);
11986 + SecurityBlob->DomainName.Length *= 2;
11987 + SecurityBlob->DomainName.MaximumLength =
11988 + cpu_to_le16(SecurityBlob->DomainName.Length);
11989 + SecurityBlob->DomainName.Buffer =
11990 + cpu_to_le32(SecurityBlobLength);
11991 + bcc_ptr += SecurityBlob->DomainName.Length;
11992 + SecurityBlobLength += SecurityBlob->DomainName.Length;
11993 + SecurityBlob->DomainName.Length =
11994 + cpu_to_le16(SecurityBlob->DomainName.Length);
11995 + }
11996 + if (user == NULL) {
11997 + SecurityBlob->UserName.Buffer = 0;
11998 + SecurityBlob->UserName.Length = 0;
11999 + SecurityBlob->UserName.MaximumLength = 0;
12000 + } else {
12001 + SecurityBlob->UserName.Length =
12002 + cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
12003 + nls_codepage);
12004 + SecurityBlob->UserName.Length *= 2;
12005 + SecurityBlob->UserName.MaximumLength =
12006 + cpu_to_le16(SecurityBlob->UserName.Length);
12007 + SecurityBlob->UserName.Buffer =
12008 + cpu_to_le32(SecurityBlobLength);
12009 + bcc_ptr += SecurityBlob->UserName.Length;
12010 + SecurityBlobLength += SecurityBlob->UserName.Length;
12011 + SecurityBlob->UserName.Length =
12012 + cpu_to_le16(SecurityBlob->UserName.Length);
12013 + }
12014 +
12015 + /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
12016 + SecurityBlob->WorkstationName.Length *= 2;
12017 + SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
12018 + SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
12019 + bcc_ptr += SecurityBlob->WorkstationName.Length;
12020 + SecurityBlobLength += SecurityBlob->WorkstationName.Length;
12021 + SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
12022 +
12023 + if ((long) bcc_ptr % 2) {
12024 + *bcc_ptr = 0;
12025 + bcc_ptr++;
12026 + }
12027 + bytes_returned =
12028 + cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
12029 + 32, nls_codepage);
12030 + bcc_ptr += 2 * bytes_returned;
12031 + bytes_returned =
12032 + cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
12033 + nls_codepage);
12034 + bcc_ptr += 2 * bytes_returned;
12035 + bcc_ptr += 2; /* null term version string */
12036 + bytes_returned =
12037 + cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
12038 + 64, nls_codepage);
12039 + bcc_ptr += 2 * bytes_returned;
12040 + *(bcc_ptr + 1) = 0;
12041 + *(bcc_ptr + 2) = 0;
12042 + bcc_ptr += 2; /* null terminate network opsys string */
12043 + *(bcc_ptr + 1) = 0;
12044 + *(bcc_ptr + 2) = 0;
12045 + bcc_ptr += 2; /* null domain */
12046 + } else { /* ASCII */
12047 + if (domain == NULL) {
12048 + SecurityBlob->DomainName.Buffer = 0;
12049 + SecurityBlob->DomainName.Length = 0;
12050 + SecurityBlob->DomainName.MaximumLength = 0;
12051 + } else {
12052 + SecurityBlob->NegotiateFlags |=
12053 + NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
12054 + strncpy(bcc_ptr, domain, 63);
12055 + SecurityBlob->DomainName.Length = strnlen(domain, 64);
12056 + SecurityBlob->DomainName.MaximumLength =
12057 + cpu_to_le16(SecurityBlob->DomainName.Length);
12058 + SecurityBlob->DomainName.Buffer =
12059 + cpu_to_le32(SecurityBlobLength);
12060 + bcc_ptr += SecurityBlob->DomainName.Length;
12061 + SecurityBlobLength += SecurityBlob->DomainName.Length;
12062 + SecurityBlob->DomainName.Length =
12063 + cpu_to_le16(SecurityBlob->DomainName.Length);
12064 + }
12065 + if (user == NULL) {
12066 + SecurityBlob->UserName.Buffer = 0;
12067 + SecurityBlob->UserName.Length = 0;
12068 + SecurityBlob->UserName.MaximumLength = 0;
12069 + } else {
12070 + strncpy(bcc_ptr, user, 63);
12071 + SecurityBlob->UserName.Length = strnlen(user, 64);
12072 + SecurityBlob->UserName.MaximumLength =
12073 + cpu_to_le16(SecurityBlob->UserName.Length);
12074 + SecurityBlob->UserName.Buffer =
12075 + cpu_to_le32(SecurityBlobLength);
12076 + bcc_ptr += SecurityBlob->UserName.Length;
12077 + SecurityBlobLength += SecurityBlob->UserName.Length;
12078 + SecurityBlob->UserName.Length =
12079 + cpu_to_le16(SecurityBlob->UserName.Length);
12080 + }
12081 + /* BB fill in our workstation name if known BB */
12082 +
12083 + strcpy(bcc_ptr, "Linux version ");
12084 + bcc_ptr += strlen("Linux version ");
12085 + strcpy(bcc_ptr, UTS_RELEASE);
12086 + bcc_ptr += strlen(UTS_RELEASE) + 1;
12087 + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
12088 + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
12089 + bcc_ptr++; /* null domain */
12090 + *bcc_ptr = 0;
12091 + }
12092 + SecurityBlob->NegotiateFlags =
12093 + cpu_to_le32(SecurityBlob->NegotiateFlags);
12094 + pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
12095 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
12096 + smb_buffer->smb_buf_length += BCC(smb_buffer);
12097 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
12098 +
12099 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
12100 + &bytes_returned, 1);
12101 + if (rc) {
12102 +/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
12103 + } else if ((smb_buffer_response->WordCount == 3)
12104 + || (smb_buffer_response->WordCount == 4)) {
12105 + pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
12106 + pSMBr->resp.SecurityBlobLength =
12107 + le16_to_cpu(pSMBr->resp.SecurityBlobLength);
12108 + if (pSMBr->resp.Action & GUEST_LOGIN)
12109 + cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
12110 +/* if(SecurityBlob2->MessageType != NtLm??){
12111 + cFYI("Unexpected message type on auth response is %d "));
12112 + } */
12113 + if (ses) {
12114 + cFYI(1,
12115 + ("Does UID on challenge %d match auth response UID %d ",
12116 + ses->Suid, smb_buffer_response->Uid));
12117 + ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
12118 + bcc_ptr = pByteArea(smb_buffer_response);
12119 + /* response can have either 3 or 4 word count - Samba sends 3 */
12120 + if ((pSMBr->resp.hdr.WordCount == 3)
12121 + || ((pSMBr->resp.hdr.WordCount == 4)
12122 + && (pSMBr->resp.SecurityBlobLength <
12123 + pSMBr->resp.ByteCount))) {
12124 + if (pSMBr->resp.hdr.WordCount == 4) {
12125 + bcc_ptr +=
12126 + pSMBr->resp.SecurityBlobLength;
12127 + cFYI(1,
12128 + ("Security Blob Length %d ",
12129 + pSMBr->resp.SecurityBlobLength));
12130 + }
12131 +
12132 + cFYI(1,
12133 + ("NTLMSSP response to Authenticate "));
12134 +
12135 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
12136 + if ((long) (bcc_ptr) % 2) {
12137 + remaining_words =
12138 + (BCC(smb_buffer_response)
12139 + - 1) / 2;
12140 + bcc_ptr++; /* Unicode strings must be word aligned */
12141 + } else {
12142 + remaining_words = BCC(smb_buffer_response) / 2;
12143 + }
12144 + len =
12145 + UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
12146 +/* We look for obvious messed up bcc or strings in response so we do not go off
12147 + the end since (at least) WIN2K and Windows XP have a major bug in not null
12148 + terminating last Unicode string in response */
12149 + ses->serverOS =
12150 + cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
12151 + cifs_strfromUCS_le(ses->serverOS,
12152 + (wchar_t *)
12153 + bcc_ptr, len,
12154 + nls_codepage);
12155 + bcc_ptr += 2 * (len + 1);
12156 + remaining_words -= len + 1;
12157 + ses->serverOS[2 * len] = 0;
12158 + ses->serverOS[1 + (2 * len)] = 0;
12159 + if (remaining_words > 0) {
12160 + len = UniStrnlen((wchar_t *)
12161 + bcc_ptr,
12162 + remaining_words
12163 + - 1);
12164 + ses->serverNOS =
12165 + cifs_kcalloc(2 * (len + 1),
12166 + GFP_KERNEL);
12167 + cifs_strfromUCS_le(ses->
12168 + serverNOS,
12169 + (wchar_t *)
12170 + bcc_ptr,
12171 + len,
12172 + nls_codepage);
12173 + bcc_ptr += 2 * (len + 1);
12174 + ses->serverNOS[2 * len] = 0;
12175 + ses->serverNOS[1+(2*len)] = 0;
12176 + remaining_words -= len + 1;
12177 + if (remaining_words > 0) {
12178 + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
12179 + /* last string not always null terminated (e.g. for Windows XP & 2000) */
12180 + ses->serverDomain =
12181 + cifs_kcalloc(2 *
12182 + (len +
12183 + 1),
12184 + GFP_KERNEL);
12185 + cifs_strfromUCS_le
12186 + (ses->
12187 + serverDomain,
12188 + (wchar_t *)
12189 + bcc_ptr, len,
12190 + nls_codepage);
12191 + bcc_ptr +=
12192 + 2 * (len + 1);
12193 + ses->
12194 + serverDomain[2
12195 + * len]
12196 + = 0;
12197 + ses->
12198 + serverDomain[1
12199 + +
12200 + (2
12201 + *
12202 + len)]
12203 + = 0;
12204 + } /* else no more room so create dummy domain string */
12205 + else
12206 + ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
12207 + } else { /* no room so create dummy domain and NOS string */
12208 + ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
12209 + ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
12210 + }
12211 + } else { /* ASCII */
12212 + len = strnlen(bcc_ptr, 1024);
12213 + if (((long) bcc_ptr + len) -
12214 + (long) pByteArea(smb_buffer_response)
12215 + <= BCC(smb_buffer_response)) {
12216 + ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
12217 + strncpy(ses->serverOS,bcc_ptr, len);
12218 +
12219 + bcc_ptr += len;
12220 + bcc_ptr[0] = 0; /* null terminate the string */
12221 + bcc_ptr++;
12222 +
12223 + len = strnlen(bcc_ptr, 1024);
12224 + ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
12225 + strncpy(ses->serverNOS, bcc_ptr, len);
12226 + bcc_ptr += len;
12227 + bcc_ptr[0] = 0;
12228 + bcc_ptr++;
12229 +
12230 + len = strnlen(bcc_ptr, 1024);
12231 + ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
12232 + strncpy(ses->serverDomain, bcc_ptr, len);
12233 + bcc_ptr += len;
12234 + bcc_ptr[0] = 0;
12235 + bcc_ptr++;
12236 + } else
12237 + cFYI(1,
12238 + ("Variable field of length %d extends beyond end of smb ",
12239 + len));
12240 + }
12241 + } else {
12242 + cERROR(1,
12243 + (" Security Blob Length extends beyond end of SMB"));
12244 + }
12245 + } else {
12246 + cERROR(1, ("No session structure passed in."));
12247 + }
12248 + } else {
12249 + cERROR(1,
12250 + (" Invalid Word count %d: ",
12251 + smb_buffer_response->WordCount));
12252 + rc = -EIO;
12253 + }
12254 +
12255 + if (smb_buffer)
12256 + cifs_buf_release(smb_buffer);
12257 +
12258 + return rc;
12259 +}
12260 +
12261 +int
12262 +CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
12263 + const char *tree, struct cifsTconInfo *tcon,
12264 + const struct nls_table *nls_codepage)
12265 +{
12266 + struct smb_hdr *smb_buffer;
12267 + struct smb_hdr *smb_buffer_response;
12268 + TCONX_REQ *pSMB;
12269 + TCONX_RSP *pSMBr;
12270 + char *bcc_ptr;
12271 + int rc = 0;
12272 + int length;
12273 +
12274 + if (ses == NULL)
12275 + return -EIO;
12276 +
12277 + smb_buffer = cifs_buf_get();
12278 + if (smb_buffer == 0) {
12279 + return -ENOMEM;
12280 + }
12281 + smb_buffer_response = smb_buffer;
12282 +
12283 + header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
12284 + NULL /*no tid */ , 4 /*wct */ );
12285 + smb_buffer->Uid = ses->Suid;
12286 + pSMB = (TCONX_REQ *) smb_buffer;
12287 + pSMBr = (TCONX_RSP *) smb_buffer_response;
12288 +
12289 + pSMB->AndXCommand = 0xFF;
12290 + pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
12291 + pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
12292 + bcc_ptr = &(pSMB->Password[0]);
12293 + bcc_ptr++; /* skip password */
12294 +
12295 + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
12296 + smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
12297 +
12298 + if (ses->capabilities & CAP_STATUS32) {
12299 + smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
12300 + }
12301 + if (ses->capabilities & CAP_DFS) {
12302 + smb_buffer->Flags2 |= SMBFLG2_DFS;
12303 + }
12304 + if (ses->capabilities & CAP_UNICODE) {
12305 + smb_buffer->Flags2 |= SMBFLG2_UNICODE;
12306 + length =
12307 + cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
12308 + bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
12309 + bcc_ptr += 2; /* skip trailing null */
12310 + } else { /* ASCII */
12311 +
12312 + strcpy(bcc_ptr, tree);
12313 + bcc_ptr += strlen(tree) + 1;
12314 + }
12315 + strcpy(bcc_ptr, "?????");
12316 + bcc_ptr += strlen("?????");
12317 + bcc_ptr += 1;
12318 + BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
12319 + smb_buffer->smb_buf_length += BCC(smb_buffer);
12320 + BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
12321 +
12322 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
12323 +
12324 + /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
12325 + /* above now done in SendReceive */
12326 + if ((rc == 0) && (tcon != NULL)) {
12327 + tcon->tidStatus = CifsGood;
12328 + tcon->tid = smb_buffer_response->Tid;
12329 + bcc_ptr = pByteArea(smb_buffer_response);
12330 + length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
12331 + /* skip service field (NB: this field is always ASCII) */
12332 + bcc_ptr += length + 1;
12333 + strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
12334 + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
12335 + length = UniStrnlen((wchar_t *) bcc_ptr, 512);
12336 + if (((long) bcc_ptr + (2 * length)) -
12337 + (long) pByteArea(smb_buffer_response) <=
12338 + BCC(smb_buffer_response)) {
12339 + if(tcon->nativeFileSystem)
12340 + kfree(tcon->nativeFileSystem);
12341 + tcon->nativeFileSystem =
12342 + cifs_kcalloc(length + 2, GFP_KERNEL);
12343 + cifs_strfromUCS_le(tcon->nativeFileSystem,
12344 + (wchar_t *) bcc_ptr,
12345 + length, nls_codepage);
12346 + bcc_ptr += 2 * length;
12347 + bcc_ptr[0] = 0; /* null terminate the string */
12348 + bcc_ptr[1] = 0;
12349 + bcc_ptr += 2;
12350 + }
12351 + /* else do not bother copying these informational fields */
12352 + } else {
12353 + length = strnlen(bcc_ptr, 1024);
12354 + if (((long) bcc_ptr + length) -
12355 + (long) pByteArea(smb_buffer_response) <=
12356 + BCC(smb_buffer_response)) {
12357 + if(tcon->nativeFileSystem)
12358 + kfree(tcon->nativeFileSystem);
12359 + tcon->nativeFileSystem =
12360 + cifs_kcalloc(length + 1, GFP_KERNEL);
12361 + strncpy(tcon->nativeFileSystem, bcc_ptr,
12362 + length);
12363 + }
12364 + /* else do not bother copying these informational fields */
12365 + }
12366 + tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
12367 + cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
12368 + } else if ((rc == 0) && tcon == NULL) {
12369 + /* all we need to save for IPC$ connection */
12370 + ses->ipc_tid = smb_buffer_response->Tid;
12371 + }
12372 +
12373 + if (smb_buffer)
12374 + cifs_buf_release(smb_buffer);
12375 + return rc;
12376 +}
12377 +
12378 +int
12379 +cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
12380 +{
12381 + int rc = 0;
12382 + int xid;
12383 + struct cifsSesInfo *ses = NULL;
12384 + struct task_struct *cifsd_task;
12385 +
12386 + xid = GetXid();
12387 +
12388 + if (cifs_sb->tcon) {
12389 + ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
12390 + rc = CIFSSMBTDis(xid, cifs_sb->tcon);
12391 + if (rc == -EBUSY) {
12392 + FreeXid(xid);
12393 + return 0;
12394 + }
12395 + tconInfoFree(cifs_sb->tcon);
12396 + if ((ses) && (ses->server)) {
12397 + /* save off task so we do not refer to ses later */
12398 + cifsd_task = ses->server->tsk;
12399 + cFYI(1, ("About to do SMBLogoff "));
12400 + rc = CIFSSMBLogoff(xid, ses);
12401 + if (rc == -EBUSY) {
12402 + FreeXid(xid);
12403 + return 0;
12404 + } else if (rc == -ESHUTDOWN) {
12405 + cFYI(1,("Waking up socket by sending it signal"));
12406 + send_sig(SIGKILL,cifsd_task,1);
12407 + rc = 0;
12408 + } /* else - we have an smb session
12409 + left on this socket do not kill cifsd */
12410 + } else
12411 + cFYI(1, ("No session or bad tcon"));
12412 + }
12413 +
12414 + cifs_sb->tcon = NULL;
12415 + if (ses) {
12416 + set_current_state(TASK_INTERRUPTIBLE);
12417 + schedule_timeout(HZ / 2);
12418 + }
12419 + if (ses)
12420 + sesInfoFree(ses);
12421 +
12422 + FreeXid(xid);
12423 + return rc; /* BB check if we should always return zero here */
12424 +}
12425 +
12426 +int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
12427 + struct nls_table * nls_info)
12428 +{
12429 + int rc = 0;
12430 + char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
12431 + int ntlmv2_flag = FALSE;
12432 +
12433 + /* what if server changes its buffer size after dropping the session? */
12434 + if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
12435 + rc = CIFSSMBNegotiate(xid, pSesInfo);
12436 + if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
12437 + rc = CIFSSMBNegotiate(xid, pSesInfo);
12438 + if(rc == -EAGAIN)
12439 + rc = -EHOSTDOWN;
12440 + }
12441 + if(rc == 0) {
12442 + spin_lock(&GlobalMid_Lock);
12443 + if(pSesInfo->server->tcpStatus != CifsExiting)
12444 + pSesInfo->server->tcpStatus = CifsGood;
12445 + else
12446 + rc = -EHOSTDOWN;
12447 + spin_unlock(&GlobalMid_Lock);
12448 +
12449 + }
12450 + }
12451 + if (!rc) {
12452 + pSesInfo->capabilities = pSesInfo->server->capabilities;
12453 + if(linuxExtEnabled == 0)
12454 + pSesInfo->capabilities &= (~CAP_UNIX);
12455 + pSesInfo->sequence_number = 0;
12456 + cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
12457 + pSesInfo->server->secMode,
12458 + pSesInfo->server->capabilities,
12459 + pSesInfo->server->timeZone));
12460 + if (extended_security
12461 + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
12462 + && (pSesInfo->server->secType == NTLMSSP)) {
12463 + cFYI(1, ("New style sesssetup "));
12464 + rc = CIFSSpnegoSessSetup(xid, pSesInfo,
12465 + NULL /* security blob */,
12466 + 0 /* blob length */,
12467 + nls_info);
12468 + } else if (extended_security
12469 + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
12470 + && (pSesInfo->server->secType == RawNTLMSSP)) {
12471 + cFYI(1, ("NTLMSSP sesssetup "));
12472 + rc = CIFSNTLMSSPNegotiateSessSetup(xid,
12473 + pSesInfo,
12474 + &ntlmv2_flag,
12475 + nls_info);
12476 + if (!rc) {
12477 + if(ntlmv2_flag) {
12478 + char * v2_response;
12479 + cFYI(1,("Can use more secure NTLM version 2 password hash"));
12480 + CalcNTLMv2_partial_mac_key(pSesInfo,
12481 + nls_info);
12482 + v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
12483 + if(v2_response) {
12484 + CalcNTLMv2_response(pSesInfo,v2_response);
12485 +/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
12486 + kfree(v2_response);
12487 + /* BB Put dummy sig in SessSetup PDU? */
12488 + } else
12489 + rc = -ENOMEM;
12490 +
12491 + } else {
12492 + SMBNTencrypt(pSesInfo->password,
12493 + pSesInfo->server->cryptKey,
12494 + ntlm_session_key);
12495 +
12496 + cifs_calculate_mac_key(pSesInfo->mac_signing_key,
12497 + ntlm_session_key,
12498 + pSesInfo->password);
12499 + }
12500 + /* for better security the weaker lanman hash not sent
12501 + in AuthSessSetup so we no longer calculate it */
12502 +
12503 + rc = CIFSNTLMSSPAuthSessSetup(xid,
12504 + pSesInfo,
12505 + ntlm_session_key,
12506 + ntlmv2_flag,
12507 + nls_info);
12508 + }
12509 + } else { /* old style NTLM 0.12 session setup */
12510 + SMBNTencrypt(pSesInfo->password,
12511 + pSesInfo->server->cryptKey,
12512 + ntlm_session_key);
12513 +
12514 + cifs_calculate_mac_key(pSesInfo->mac_signing_key,
12515 + ntlm_session_key, pSesInfo->password);
12516 + rc = CIFSSessSetup(xid, pSesInfo,
12517 + ntlm_session_key, nls_info);
12518 + }
12519 + if (rc) {
12520 + cERROR(1,("Send error in SessSetup = %d",rc));
12521 + } else {
12522 + cFYI(1,("CIFS Session Established successfully"));
12523 + pSesInfo->status = CifsGood;
12524 + }
12525 + }
12526 + return rc;
12527 +}
12528 +
12529 diff -urN linux-2.4.29.old/fs/cifs/dir.c linux-2.4.29/fs/cifs/dir.c
12530 --- linux-2.4.29.old/fs/cifs/dir.c 1970-01-01 01:00:00.000000000 +0100
12531 +++ linux-2.4.29/fs/cifs/dir.c 2004-07-14 00:25:05.000000000 +0200
12532 @@ -0,0 +1,425 @@
12533 +/*
12534 + * fs/cifs/dir.c
12535 + *
12536 + * vfs operations that deal with dentries
12537 + *
12538 + * Copyright (C) International Business Machines Corp., 2002,2003
12539 + * Author(s): Steve French (sfrench@us.ibm.com)
12540 + *
12541 + * This library is free software; you can redistribute it and/or modify
12542 + * it under the terms of the GNU Lesser General Public License as published
12543 + * by the Free Software Foundation; either version 2.1 of the License, or
12544 + * (at your option) any later version.
12545 + *
12546 + * This library is distributed in the hope that it will be useful,
12547 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12548 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12549 + * the GNU Lesser General Public License for more details.
12550 + *
12551 + * You should have received a copy of the GNU Lesser General Public License
12552 + * along with this library; if not, write to the Free Software
12553 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12554 + */
12555 +#include <linux/fs.h>
12556 +#include <linux/stat.h>
12557 +#include <linux/slab.h>
12558 +#include "cifsfs.h"
12559 +#include "cifspdu.h"
12560 +#include "cifsglob.h"
12561 +#include "cifsproto.h"
12562 +#include "cifs_debug.h"
12563 +#include "cifs_fs_sb.h"
12564 +
12565 +void
12566 +renew_parental_timestamps(struct dentry *direntry)
12567 +{
12568 + /* BB check if there is a way to get the kernel to do this or if we really need this */
12569 + do {
12570 + direntry->d_time = jiffies;
12571 + direntry = direntry->d_parent;
12572 + } while (!IS_ROOT(direntry));
12573 +}
12574 +
12575 +/* Note: caller must free return buffer */
12576 +char *
12577 +build_path_from_dentry(struct dentry *direntry)
12578 +{
12579 + struct dentry *temp;
12580 + int namelen = 0;
12581 + char *full_path;
12582 +
12583 + if(direntry == NULL)
12584 + return NULL; /* not much we can do if dentry is freed and
12585 + we need to reopen the file after it was closed implicitly
12586 + when the server crashed */
12587 +
12588 +cifs_bp_rename_retry:
12589 + for (temp = direntry; !IS_ROOT(temp);) {
12590 + namelen += (1 + temp->d_name.len);
12591 + temp = temp->d_parent;
12592 + if(temp == NULL) {
12593 + cERROR(1,("corrupt dentry"));
12594 + return NULL;
12595 + }
12596 + }
12597 +
12598 + full_path = kmalloc(namelen+1, GFP_KERNEL);
12599 + if(full_path == NULL)
12600 + return full_path;
12601 + full_path[namelen] = 0; /* trailing null */
12602 +
12603 + for (temp = direntry; !IS_ROOT(temp);) {
12604 + namelen -= 1 + temp->d_name.len;
12605 + if (namelen < 0) {
12606 + break;
12607 + } else {
12608 + full_path[namelen] = '\\';
12609 + strncpy(full_path + namelen + 1, temp->d_name.name,
12610 + temp->d_name.len);
12611 + cFYI(0, (" name: %s ", full_path + namelen));
12612 + }
12613 + temp = temp->d_parent;
12614 + if(temp == NULL) {
12615 + cERROR(1,("corrupt dentry"));
12616 + kfree(full_path);
12617 + return NULL;
12618 + }
12619 + }
12620 + if (namelen != 0) {
12621 + cERROR(1,
12622 + ("We did not end path lookup where we expected namelen is %d",
12623 + namelen));
12624 + /* presumably this is only possible if we were racing with a rename
12625 + of one of the parent directories (we can not lock the dentries
12626 + above us to prevent this, but retrying should be harmless) */
12627 + kfree(full_path);
12628 + namelen = 0;
12629 + goto cifs_bp_rename_retry;
12630 + }
12631 +
12632 + return full_path;
12633 +}
12634 +
12635 +/* Note: caller must free return buffer */
12636 +char *
12637 +build_wildcard_path_from_dentry(struct dentry *direntry)
12638 +{
12639 + struct dentry *temp;
12640 + int namelen = 0;
12641 + char *full_path;
12642 +
12643 + if(direntry == NULL)
12644 + return NULL; /* not much we can do if dentry is freed and
12645 + we need to reopen the file after it was closed implicitly
12646 + when the server crashed */
12647 +
12648 +cifs_bwp_rename_retry:
12649 + for (temp = direntry; !IS_ROOT(temp);) {
12650 + namelen += (1 + temp->d_name.len);
12651 + temp = temp->d_parent;
12652 + if(temp == NULL) {
12653 + cERROR(1,("corrupt dentry"));
12654 + return NULL;
12655 + }
12656 + }
12657 +
12658 + full_path = kmalloc(namelen+3, GFP_KERNEL);
12659 + if(full_path == NULL)
12660 + return full_path;
12661 +
12662 + full_path[namelen] = '\\';
12663 + full_path[namelen+1] = '*';
12664 + full_path[namelen+2] = 0; /* trailing null */
12665 +
12666 + for (temp = direntry; !IS_ROOT(temp);) {
12667 + namelen -= 1 + temp->d_name.len;
12668 + if (namelen < 0) {
12669 + break;
12670 + } else {
12671 + full_path[namelen] = '\\';
12672 + strncpy(full_path + namelen + 1, temp->d_name.name,
12673 + temp->d_name.len);
12674 + cFYI(0, (" name: %s ", full_path + namelen));
12675 + }
12676 + temp = temp->d_parent;
12677 + if(temp == NULL) {
12678 + cERROR(1,("corrupt dentry"));
12679 + kfree(full_path);
12680 + return NULL;
12681 + }
12682 + }
12683 + if (namelen != 0) {
12684 + cERROR(1,
12685 + ("We did not end path lookup where we expected namelen is %d",
12686 + namelen));
12687 + /* presumably this is only possible if we were racing with a rename
12688 + of one of the parent directories (we can not lock the dentries
12689 + above us to prevent this, but retrying should be harmless) */
12690 + kfree(full_path);
12691 + namelen = 0;
12692 + goto cifs_bwp_rename_retry;
12693 + }
12694 +
12695 + return full_path;
12696 +}
12697 +
12698 +/* Inode operations in similar order to how they appear in the Linux file fs.h */
12699 +
12700 +int
12701 +cifs_create(struct inode *inode, struct dentry *direntry, int mode)
12702 +{
12703 + int rc = -ENOENT;
12704 + int xid;
12705 + int oplock = 0; /* no sense requested oplock if we are just going to
12706 + immediately close the file */
12707 + __u16 fileHandle;
12708 + struct cifs_sb_info *cifs_sb;
12709 + struct cifsTconInfo *pTcon;
12710 + char *full_path = NULL;
12711 + FILE_ALL_INFO * buf = NULL;
12712 + struct inode *newinode = NULL;
12713 +
12714 + xid = GetXid();
12715 +
12716 + cifs_sb = CIFS_SB(inode->i_sb);
12717 + pTcon = cifs_sb->tcon;
12718 +
12719 + down(&direntry->d_sb->s_vfs_rename_sem);
12720 + full_path = build_path_from_dentry(direntry);
12721 + up(&direntry->d_sb->s_vfs_rename_sem);
12722 + if(full_path == NULL) {
12723 + FreeXid(xid);
12724 + return -ENOMEM;
12725 + }
12726 +
12727 + /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
12728 +
12729 + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
12730 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
12731 + GENERIC_WRITE, CREATE_NOT_DIR,
12732 + &fileHandle, &oplock, buf, cifs_sb->local_nls);
12733 + if (rc) {
12734 + cFYI(1, ("cifs_create returned 0x%x ", rc));
12735 + } else {
12736 + /* BB for case of overwriting existing file can we use the inode that was
12737 + passed in rather than creating new one?? */
12738 + if (pTcon->ses->capabilities & CAP_UNIX)
12739 + rc = cifs_get_inode_info_unix(&newinode, full_path,
12740 + inode->i_sb,xid);
12741 + else
12742 + rc = cifs_get_inode_info(&newinode, full_path,
12743 + buf, inode->i_sb,xid);
12744 +
12745 + if (rc != 0) {
12746 + cFYI(1,("Create worked but get_inode_info failed with rc = %d",
12747 + rc));
12748 + } else {
12749 + direntry->d_op = &cifs_dentry_ops;
12750 + d_instantiate(direntry, newinode);
12751 + }
12752 + CIFSSMBClose(xid, pTcon, fileHandle);
12753 +
12754 + if(newinode) {
12755 + newinode->i_mode = mode;
12756 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
12757 + CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
12758 + (__u64)-1,
12759 + (__u64)-1,
12760 + 0 /* dev */,
12761 + cifs_sb->local_nls);
12762 + else { /* BB implement via Windows security descriptors */
12763 + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
12764 + /* in the meantime could set r/o dos attribute when perms are eg:
12765 + mode & 0222 == 0 */
12766 + }
12767 + }
12768 + }
12769 +
12770 + if (buf)
12771 + kfree(buf);
12772 + if (full_path)
12773 + kfree(full_path);
12774 + FreeXid(xid);
12775 +
12776 + return rc;
12777 +}
12778 +
12779 +int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number)
12780 +{
12781 + int rc = -EPERM;
12782 + int xid;
12783 + struct cifs_sb_info *cifs_sb;
12784 + struct cifsTconInfo *pTcon;
12785 + char *full_path = NULL;
12786 + struct inode * newinode = NULL;
12787 +
12788 + xid = GetXid();
12789 +
12790 + cifs_sb = CIFS_SB(inode->i_sb);
12791 + pTcon = cifs_sb->tcon;
12792 +
12793 + down(&direntry->d_sb->s_vfs_rename_sem);
12794 + full_path = build_path_from_dentry(direntry);
12795 + up(&direntry->d_sb->s_vfs_rename_sem);
12796 + if(full_path == NULL)
12797 + rc = -ENOMEM;
12798 +
12799 + if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
12800 + rc = CIFSSMBUnixSetPerms(xid, pTcon,
12801 + full_path, mode, current->euid, current->egid,
12802 + device_number, cifs_sb->local_nls);
12803 + if(!rc) {
12804 + rc = cifs_get_inode_info_unix(&newinode, full_path,
12805 + inode->i_sb,xid);
12806 + direntry->d_op = &cifs_dentry_ops;
12807 + if(rc == 0)
12808 + d_instantiate(direntry, newinode);
12809 + }
12810 + }
12811 +
12812 + if (full_path)
12813 + kfree(full_path);
12814 + FreeXid(xid);
12815 +
12816 + return rc;
12817 +}
12818 +
12819 +
12820 +struct dentry *
12821 +cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
12822 +{
12823 + int xid;
12824 + int rc = 0; /* to get around spurious gcc warning, set to zero here */
12825 + struct cifs_sb_info *cifs_sb;
12826 + struct cifsTconInfo *pTcon;
12827 + struct inode *newInode = NULL;
12828 + char *full_path = NULL;
12829 +
12830 + xid = GetXid();
12831 +
12832 + cFYI(1,
12833 + (" parent inode = 0x%p name is: %s and dentry = 0x%p",
12834 + parent_dir_inode, direntry->d_name.name, direntry));
12835 +
12836 + /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
12837 +
12838 + /* check whether path exists */
12839 +
12840 + cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
12841 + pTcon = cifs_sb->tcon;
12842 +
12843 + /* can not grab the rename sem here since it would
12844 + deadlock in the cases (beginning of sys_rename itself)
12845 + in which we already have the sb rename sem */
12846 + full_path = build_path_from_dentry(direntry);
12847 + if(full_path == NULL) {
12848 + FreeXid(xid);
12849 + return ERR_PTR(-ENOMEM);
12850 + }
12851 +
12852 + if (direntry->d_inode != NULL) {
12853 + cFYI(1, (" non-NULL inode in lookup"));
12854 + } else {
12855 + cFYI(1, (" NULL inode in lookup"));
12856 + }
12857 + cFYI(1,
12858 + (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
12859 +
12860 + if (pTcon->ses->capabilities & CAP_UNIX)
12861 + rc = cifs_get_inode_info_unix(&newInode, full_path,
12862 + parent_dir_inode->i_sb,xid);
12863 + else
12864 + rc = cifs_get_inode_info(&newInode, full_path, NULL,
12865 + parent_dir_inode->i_sb,xid);
12866 +
12867 + if ((rc == 0) && (newInode != NULL)) {
12868 + direntry->d_op = &cifs_dentry_ops;
12869 + d_add(direntry, newInode);
12870 +
12871 + /* since paths are not looked up by component - the parent directories are presumed to be good here */
12872 + renew_parental_timestamps(direntry);
12873 +
12874 + } else if (rc == -ENOENT) {
12875 + rc = 0;
12876 + d_add(direntry, NULL);
12877 + } else {
12878 + cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
12879 + /* BB special case check for Access Denied - watch security
12880 + exposure of returning dir info implicitly via different rc
12881 + if file exists or not but no access BB */
12882 + }
12883 +
12884 + if (full_path)
12885 + kfree(full_path);
12886 + FreeXid(xid);
12887 + return ERR_PTR(rc);
12888 +}
12889 +
12890 +int
12891 +cifs_dir_open(struct inode *inode, struct file *file)
12892 +{ /* NB: currently unused since searches are opened in readdir */
12893 + int rc = 0;
12894 + int xid;
12895 + struct cifs_sb_info *cifs_sb;
12896 + struct cifsTconInfo *pTcon;
12897 + char *full_path = NULL;
12898 +
12899 + xid = GetXid();
12900 +
12901 + cifs_sb = CIFS_SB(inode->i_sb);
12902 + pTcon = cifs_sb->tcon;
12903 +
12904 + if(file->f_dentry) {
12905 + down(&file->f_dentry->d_sb->s_vfs_rename_sem);
12906 + full_path = build_wildcard_path_from_dentry(file->f_dentry);
12907 + up(&file->f_dentry->d_sb->s_vfs_rename_sem);
12908 + } else {
12909 + FreeXid(xid);
12910 + return -EIO;
12911 + }
12912 +
12913 + cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
12914 +
12915 + if (full_path)
12916 + kfree(full_path);
12917 + FreeXid(xid);
12918 + return rc;
12919 +}
12920 +
12921 +static int
12922 +cifs_d_revalidate(struct dentry *direntry, int flags)
12923 +{
12924 + int isValid = 1;
12925 +
12926 +/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
12927 +
12928 + if (direntry->d_inode) {
12929 + if (cifs_revalidate(direntry)) {
12930 + /* unlock_kernel(); */
12931 + return 0;
12932 + }
12933 + } else {
12934 + cFYI(1,
12935 + ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
12936 + direntry->d_name.name, direntry));
12937 + }
12938 +
12939 +/* unlock_kernel(); */
12940 +
12941 + return isValid;
12942 +}
12943 +
12944 +/* static int cifs_d_delete(struct dentry *direntry)
12945 +{
12946 + int rc = 0;
12947 +
12948 + cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
12949 +
12950 + return rc;
12951 +} */
12952 +
12953 +struct dentry_operations cifs_dentry_ops = {
12954 + .d_revalidate = cifs_d_revalidate,
12955 +/* d_delete: cifs_d_delete, *//* not needed except for debugging */
12956 + /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
12957 +};
12958 diff -urN linux-2.4.29.old/fs/cifs/file.c linux-2.4.29/fs/cifs/file.c
12959 --- linux-2.4.29.old/fs/cifs/file.c 1970-01-01 01:00:00.000000000 +0100
12960 +++ linux-2.4.29/fs/cifs/file.c 2004-07-14 00:25:05.000000000 +0200
12961 @@ -0,0 +1,2185 @@
12962 +/*
12963 + * fs/cifs/file.c
12964 + *
12965 + * vfs operations that deal with files
12966 + *
12967 + * Copyright (C) International Business Machines Corp., 2002,2003
12968 + * Author(s): Steve French (sfrench@us.ibm.com)
12969 + *
12970 + * This library is free software; you can redistribute it and/or modify
12971 + * it under the terms of the GNU Lesser General Public License as published
12972 + * by the Free Software Foundation; either version 2.1 of the License, or
12973 + * (at your option) any later version.
12974 + *
12975 + * This library is distributed in the hope that it will be useful,
12976 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12977 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12978 + * the GNU Lesser General Public License for more details.
12979 + *
12980 + * You should have received a copy of the GNU Lesser General Public License
12981 + * along with this library; if not, write to the Free Software
12982 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12983 + */
12984 +#include <linux/fs.h>
12985 +#include <linux/stat.h>
12986 +#include <linux/fcntl.h>
12987 +#include <linux/version.h>
12988 +#include <linux/pagemap.h>
12989 +#include <linux/smp_lock.h>
12990 +#include <linux/list.h>
12991 +#include <asm/div64.h>
12992 +#include <linux/mm.h>
12993 +#include <linux/types.h>
12994 +#include "cifsfs.h"
12995 +#include "cifspdu.h"
12996 +#include "cifsglob.h"
12997 +#include "cifsproto.h"
12998 +#include "cifs_unicode.h"
12999 +#include "cifs_debug.h"
13000 +#include "cifs_fs_sb.h"
13001 +
13002 +int
13003 +cifs_open(struct inode *inode, struct file *file)
13004 +{
13005 + int rc = -EACCES;
13006 + int xid, oplock;
13007 + struct cifs_sb_info *cifs_sb;
13008 + struct cifsTconInfo *pTcon;
13009 + struct cifsFileInfo *pCifsFile;
13010 + struct cifsInodeInfo *pCifsInode;
13011 + char *full_path = NULL;
13012 + int desiredAccess = 0x20197;
13013 + int disposition;
13014 + __u16 netfid;
13015 + FILE_ALL_INFO * buf = NULL;
13016 + time_t temp;
13017 +
13018 + xid = GetXid();
13019 +
13020 + cifs_sb = CIFS_SB(inode->i_sb);
13021 + pTcon = cifs_sb->tcon;
13022 +
13023 + down(&inode->i_sb->s_vfs_rename_sem);
13024 + full_path = build_path_from_dentry(file->f_dentry);
13025 + up(&inode->i_sb->s_vfs_rename_sem);
13026 + if(full_path == NULL) {
13027 + FreeXid(xid);
13028 + return -ENOMEM;
13029 + }
13030 +
13031 + cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
13032 + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
13033 + desiredAccess = GENERIC_READ;
13034 + else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
13035 + desiredAccess = GENERIC_WRITE;
13036 + else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
13037 + /* GENERIC_ALL is too much permission to request */
13038 + /* can cause unnecessary access denied on create */
13039 + /* desiredAccess = GENERIC_ALL; */
13040 + desiredAccess = GENERIC_READ | GENERIC_WRITE;
13041 + }
13042 +
13043 +/*********************************************************************
13044 + * open flag mapping table:
13045 + *
13046 + * POSIX Flag CIFS Disposition
13047 + * ---------- ----------------
13048 + * O_CREAT FILE_OPEN_IF
13049 + * O_CREAT | O_EXCL FILE_CREATE
13050 + * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
13051 + * O_TRUNC FILE_OVERWRITE
13052 + * none of the above FILE_OPEN
13053 + *
13054 + * Note that there is not a direct match between disposition
13055 + * FILE_SUPERSEDE (ie create whether or not file exists although
13056 + * O_CREAT | O_TRUNC is similar but truncates the existing
13057 + * file rather than creating a new file as FILE_SUPERSEDE does
13058 + * (which uses the attributes / metadata passed in on open call)
13059 + *?
13060 + *? O_SYNC is a reasonable match to CIFS writethrough flag
13061 + *? and the read write flags match reasonably. O_LARGEFILE
13062 + *? is irrelevant because largefile support is always used
13063 + *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
13064 + * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
13065 + *********************************************************************/
13066 +
13067 + /* For 2.4 case, file was already checked for existence
13068 + before create by vfs lookup and created in create
13069 + entry point, we are now just opening the newly
13070 + created file with the right desiredAccess flags */
13071 +
13072 + if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
13073 + disposition = FILE_OPEN_IF;
13074 + else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
13075 + disposition = FILE_OVERWRITE_IF;
13076 + else if((file->f_flags & O_CREAT) == O_CREAT)
13077 + disposition = FILE_OPEN_IF;
13078 + else
13079 + disposition = FILE_OPEN;
13080 +
13081 + if (oplockEnabled)
13082 + oplock = REQ_OPLOCK;
13083 + else
13084 + oplock = FALSE;
13085 +
13086 + /* BB pass O_SYNC flag through on file attributes .. BB */
13087 +
13088 + /* Also refresh inode by passing in file_info buf returned by SMBOpen
13089 + and calling get_inode_info with returned buf (at least
13090 + helps non-Unix server case */
13091 +
13092 + /* BB we can not do this if this is the second open of a file
13093 + and the first handle has writebehind data, we might be
13094 + able to simply do a filemap_fdatawrite/filemap_fdatawait first */
13095 + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
13096 + if(buf==0) {
13097 + if (full_path)
13098 + kfree(full_path);
13099 + FreeXid(xid);
13100 + return -ENOMEM;
13101 + }
13102 + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
13103 + CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
13104 + if (rc) {
13105 + cFYI(1, ("cifs_open returned 0x%x ", rc));
13106 + cFYI(1, ("oplock: %d ", oplock));
13107 + } else {
13108 + file->private_data =
13109 + kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
13110 + if (file->private_data) {
13111 + memset(file->private_data, 0, sizeof(struct cifsFileInfo));
13112 + pCifsFile = (struct cifsFileInfo *) file->private_data;
13113 + pCifsFile->netfid = netfid;
13114 + pCifsFile->pid = current->pid;
13115 + init_MUTEX(&pCifsFile->fh_sem);
13116 + pCifsFile->pfile = file; /* needed for writepage */
13117 + pCifsFile->pInode = inode;
13118 + pCifsFile->invalidHandle = FALSE;
13119 + pCifsFile->closePend = FALSE;
13120 + write_lock(&GlobalSMBSeslock);
13121 + spin_lock(&files_lock);
13122 + list_add(&pCifsFile->tlist,&pTcon->openFileList);
13123 + pCifsInode = CIFS_I(file->f_dentry->d_inode);
13124 + if(pCifsInode) {
13125 + /* want handles we can use to read with first */
13126 + /* in the list so we do not have to walk the */
13127 + /* list to search for one in prepare_write */
13128 + if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
13129 + list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
13130 + } else {
13131 + list_add(&pCifsFile->flist,&pCifsInode->openFileList);
13132 + }
13133 + spin_unlock(&files_lock);
13134 + write_unlock(&GlobalSMBSeslock);
13135 + if(pCifsInode->clientCanCacheRead) {
13136 + /* we have the inode open somewhere else
13137 + no need to discard cache data */
13138 + } else {
13139 + if(buf) {
13140 + /* BB need same check in cifs_create too? */
13141 +
13142 + /* if not oplocked, invalidate inode pages if mtime
13143 + or file size changed */
13144 + temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
13145 + if((file->f_dentry->d_inode->i_mtime == temp) &&
13146 + (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
13147 + cFYI(1,("inode unchanged on server"));
13148 + } else {
13149 + if(file->f_dentry->d_inode->i_mapping) {
13150 + /* BB no need to lock inode until after invalidate*/
13151 + /* since namei code should already have it locked?*/
13152 + filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
13153 + }
13154 + cFYI(1,("invalidating remote inode since open detected it changed"));
13155 + invalidate_inode_pages(file->f_dentry->d_inode);
13156 + }
13157 + }
13158 + }
13159 + if (pTcon->ses->capabilities & CAP_UNIX)
13160 + rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
13161 + full_path, inode->i_sb,xid);
13162 + else
13163 + rc = cifs_get_inode_info(&file->f_dentry->d_inode,
13164 + full_path, buf, inode->i_sb,xid);
13165 +
13166 + if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
13167 + pCifsInode->clientCanCacheAll = TRUE;
13168 + pCifsInode->clientCanCacheRead = TRUE;
13169 + cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
13170 + } else if((oplock & 0xF) == OPLOCK_READ)
13171 + pCifsInode->clientCanCacheRead = TRUE;
13172 + } else {
13173 + spin_unlock(&files_lock);
13174 + write_unlock(&GlobalSMBSeslock);
13175 + }
13176 + if(oplock & CIFS_CREATE_ACTION) {
13177 + /* time to set mode which we can not set earlier due
13178 + to problems creating new read-only files */
13179 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
13180 + CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
13181 + (__u64)-1,
13182 + (__u64)-1,
13183 + 0 /* dev */,
13184 + cifs_sb->local_nls);
13185 + else {/* BB implement via Windows security descriptors */
13186 + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
13187 + /* in the meantime could set r/o dos attribute when perms are eg:
13188 + mode & 0222 == 0 */
13189 + }
13190 + }
13191 + }
13192 + }
13193 +
13194 + if (buf)
13195 + kfree(buf);
13196 + if (full_path)
13197 + kfree(full_path);
13198 + FreeXid(xid);
13199 + return rc;
13200 +}
13201 +
13202 +/* Try to reaquire byte range locks that were released when session */
13203 +/* to server was lost */
13204 +static int cifs_relock_file(struct cifsFileInfo * cifsFile)
13205 +{
13206 + int rc = 0;
13207 +
13208 +/* BB list all locks open on this file and relock */
13209 +
13210 + return rc;
13211 +}
13212 +
13213 +static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
13214 +{
13215 + int rc = -EACCES;
13216 + int xid, oplock;
13217 + struct cifs_sb_info *cifs_sb;
13218 + struct cifsTconInfo *pTcon;
13219 + struct cifsFileInfo *pCifsFile;
13220 + struct cifsInodeInfo *pCifsInode;
13221 + char *full_path = NULL;
13222 + int desiredAccess = 0x20197;
13223 + int disposition = FILE_OPEN;
13224 + __u16 netfid;
13225 +
13226 + if(inode == NULL)
13227 + return -EBADF;
13228 + if (file->private_data) {
13229 + pCifsFile = (struct cifsFileInfo *) file->private_data;
13230 + } else
13231 + return -EBADF;
13232 +
13233 + xid = GetXid();
13234 + down(&pCifsFile->fh_sem);
13235 + if(pCifsFile->invalidHandle == FALSE) {
13236 + up(&pCifsFile->fh_sem);
13237 + FreeXid(xid);
13238 + return 0;
13239 + }
13240 +
13241 + if(file->f_dentry == NULL) {
13242 + up(&pCifsFile->fh_sem);
13243 + cFYI(1,("failed file reopen, no valid name if dentry freed"));
13244 + FreeXid(xid);
13245 + return -EBADF;
13246 + }
13247 + cifs_sb = CIFS_SB(inode->i_sb);
13248 + pTcon = cifs_sb->tcon;
13249 +/* can not grab rename sem here because various ops, including
13250 +those that already have the rename sem can end up causing writepage
13251 +to get called and if the server was down that means we end up here,
13252 +and we can never tell if the caller already has the rename_sem */
13253 + full_path = build_path_from_dentry(file->f_dentry);
13254 + if(full_path == NULL) {
13255 + up(&pCifsFile->fh_sem);
13256 + FreeXid(xid);
13257 + return -ENOMEM;
13258 + }
13259 +
13260 + cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
13261 + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
13262 + desiredAccess = GENERIC_READ;
13263 + else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
13264 + desiredAccess = GENERIC_WRITE;
13265 + else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
13266 + /* GENERIC_ALL is too much permission to request */
13267 + /* can cause unnecessary access denied on create */
13268 + /* desiredAccess = GENERIC_ALL; */
13269 + desiredAccess = GENERIC_READ | GENERIC_WRITE;
13270 + }
13271 +
13272 + if (oplockEnabled)
13273 + oplock = REQ_OPLOCK;
13274 + else
13275 + oplock = FALSE;
13276 +
13277 +
13278 + /* Can not refresh inode by passing in file_info buf to be returned
13279 + by SMBOpen and then calling get_inode_info with returned buf
13280 + since file might have write behind data that needs to be flushed
13281 + and server version of file size can be stale. If we
13282 + knew for sure that inode was not dirty locally we could do this */
13283 +
13284 +/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
13285 + if(buf==0) {
13286 + up(&pCifsFile->fh_sem);
13287 + if (full_path)
13288 + kfree(full_path);
13289 + FreeXid(xid);
13290 + return -ENOMEM;
13291 + }*/
13292 + rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
13293 + CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
13294 + if (rc) {
13295 + up(&pCifsFile->fh_sem);
13296 + cFYI(1, ("cifs_open returned 0x%x ", rc));
13297 + cFYI(1, ("oplock: %d ", oplock));
13298 + } else {
13299 + pCifsFile->netfid = netfid;
13300 + pCifsFile->invalidHandle = FALSE;
13301 + up(&pCifsFile->fh_sem);
13302 + pCifsInode = CIFS_I(inode);
13303 + if(pCifsInode) {
13304 + if(can_flush) {
13305 + filemap_fdatasync(inode->i_mapping);
13306 + filemap_fdatawait(inode->i_mapping);
13307 + /* temporarily disable caching while we
13308 + go to server to get inode info */
13309 + pCifsInode->clientCanCacheAll = FALSE;
13310 + pCifsInode->clientCanCacheRead = FALSE;
13311 + if (pTcon->ses->capabilities & CAP_UNIX)
13312 + rc = cifs_get_inode_info_unix(&inode,
13313 + full_path, inode->i_sb,xid);
13314 + else
13315 + rc = cifs_get_inode_info(&inode,
13316 + full_path, NULL, inode->i_sb,xid);
13317 + } /* else we are writing out data to server already
13318 + and could deadlock if we tried to flush data, and
13319 + since we do not know if we have data that would
13320 + invalidate the current end of file on the server
13321 + we can not go to the server to get the new
13322 + inod info */
13323 + if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
13324 + pCifsInode->clientCanCacheAll = TRUE;
13325 + pCifsInode->clientCanCacheRead = TRUE;
13326 + cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
13327 + } else if((oplock & 0xF) == OPLOCK_READ) {
13328 + pCifsInode->clientCanCacheRead = TRUE;
13329 + pCifsInode->clientCanCacheAll = FALSE;
13330 + } else {
13331 + pCifsInode->clientCanCacheRead = FALSE;
13332 + pCifsInode->clientCanCacheAll = FALSE;
13333 + }
13334 + cifs_relock_file(pCifsFile);
13335 + }
13336 + }
13337 +
13338 + if (full_path)
13339 + kfree(full_path);
13340 + FreeXid(xid);
13341 + return rc;
13342 +}
13343 +
13344 +int
13345 +cifs_close(struct inode *inode, struct file *file)
13346 +{
13347 + int rc = 0;
13348 + int xid;
13349 + struct cifs_sb_info *cifs_sb;
13350 + struct cifsTconInfo *pTcon;
13351 + struct cifsFileInfo *pSMBFile =
13352 + (struct cifsFileInfo *) file->private_data;
13353 +
13354 + xid = GetXid();
13355 +
13356 + cifs_sb = CIFS_SB(inode->i_sb);
13357 + pTcon = cifs_sb->tcon;
13358 + if (pSMBFile) {
13359 + pSMBFile->closePend = TRUE;
13360 + spin_lock(&files_lock);
13361 + if(pTcon) {
13362 + /* no sense reconnecting to close a file that is
13363 + already closed */
13364 + if (pTcon->tidStatus != CifsNeedReconnect) {
13365 + spin_unlock(&files_lock);
13366 + rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
13367 + spin_lock(&files_lock);
13368 + }
13369 + }
13370 + list_del(&pSMBFile->flist);
13371 + list_del(&pSMBFile->tlist);
13372 + spin_unlock(&files_lock);
13373 + if(pSMBFile->search_resume_name)
13374 + kfree(pSMBFile->search_resume_name);
13375 + kfree(file->private_data);
13376 + file->private_data = NULL;
13377 + } else
13378 + rc = -EBADF;
13379 +
13380 + if(list_empty(&(CIFS_I(inode)->openFileList))) {
13381 + cFYI(1,("closing last open instance for inode %p",inode));
13382 + /* if the file is not open we do not know if we can cache
13383 + info on this inode, much less write behind and read ahead */
13384 + CIFS_I(inode)->clientCanCacheRead = FALSE;
13385 + CIFS_I(inode)->clientCanCacheAll = FALSE;
13386 + }
13387 + if((rc ==0) && CIFS_I(inode)->write_behind_rc)
13388 + rc = CIFS_I(inode)->write_behind_rc;
13389 + FreeXid(xid);
13390 + return rc;
13391 +}
13392 +
13393 +int
13394 +cifs_closedir(struct inode *inode, struct file *file)
13395 +{
13396 + int rc = 0;
13397 + int xid;
13398 + struct cifsFileInfo *pSMBFileStruct =
13399 + (struct cifsFileInfo *) file->private_data;
13400 +
13401 + cFYI(1, ("Closedir inode = 0x%p with ", inode));
13402 +
13403 + xid = GetXid();
13404 +
13405 + if (pSMBFileStruct) {
13406 + cFYI(1, ("Freeing private data in close dir"));
13407 + kfree(file->private_data);
13408 + file->private_data = NULL;
13409 + }
13410 + FreeXid(xid);
13411 + return rc;
13412 +}
13413 +
13414 +int
13415 +cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
13416 +{
13417 + int rc, xid;
13418 + __u32 lockType = LOCKING_ANDX_LARGE_FILES;
13419 + __u32 numLock = 0;
13420 + __u32 numUnlock = 0;
13421 + __u64 length;
13422 + int wait_flag = FALSE;
13423 + struct cifs_sb_info *cifs_sb;
13424 + struct cifsTconInfo *pTcon;
13425 + length = 1 + pfLock->fl_end - pfLock->fl_start;
13426 +
13427 + rc = -EACCES;
13428 +
13429 + xid = GetXid();
13430 +
13431 + cFYI(1,
13432 + ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
13433 + cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
13434 + pfLock->fl_end));
13435 +
13436 + if (pfLock->fl_flags & FL_POSIX)
13437 + cFYI(1, ("Posix "));
13438 + if (pfLock->fl_flags & FL_FLOCK)
13439 + cFYI(1, ("Flock "));
13440 +/* if (pfLock->fl_flags & FL_SLEEP) {
13441 + cFYI(1, ("Blocking lock "));
13442 + wait_flag = TRUE;
13443 + } */
13444 + if (pfLock->fl_flags & FL_ACCESS)
13445 + cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
13446 + if (pfLock->fl_flags & FL_LEASE)
13447 + cFYI(1, ("Lease on file - not implemented yet"));
13448 + if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_ACCESS | FL_LEASE)))
13449 + cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
13450 +
13451 + if (pfLock->fl_type == F_WRLCK) {
13452 + cFYI(1, ("F_WRLCK "));
13453 + numLock = 1;
13454 + } else if (pfLock->fl_type == F_UNLCK) {
13455 + cFYI(1, ("F_UNLCK "));
13456 + numUnlock = 1;
13457 + } else if (pfLock->fl_type == F_RDLCK) {
13458 + cFYI(1, ("F_RDLCK "));
13459 + lockType |= LOCKING_ANDX_SHARED_LOCK;
13460 + numLock = 1;
13461 + } else if (pfLock->fl_type == F_EXLCK) {
13462 + cFYI(1, ("F_EXLCK "));
13463 + numLock = 1;
13464 + } else if (pfLock->fl_type == F_SHLCK) {
13465 + cFYI(1, ("F_SHLCK "));
13466 + lockType |= LOCKING_ANDX_SHARED_LOCK;
13467 + numLock = 1;
13468 + } else
13469 + cFYI(1, ("Unknown type of lock "));
13470 +
13471 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13472 + pTcon = cifs_sb->tcon;
13473 +
13474 + if (file->private_data == NULL) {
13475 + FreeXid(xid);
13476 + return -EBADF;
13477 + }
13478 +
13479 + if (IS_GETLK(cmd)) {
13480 + rc = CIFSSMBLock(xid, pTcon,
13481 + ((struct cifsFileInfo *) file->
13482 + private_data)->netfid,
13483 + length,
13484 + pfLock->fl_start, 0, 1, lockType,
13485 + 0 /* wait flag */ );
13486 + if (rc == 0) {
13487 + rc = CIFSSMBLock(xid, pTcon,
13488 + ((struct cifsFileInfo *) file->
13489 + private_data)->netfid,
13490 + length,
13491 + pfLock->fl_start, 1 /* numUnlock */ ,
13492 + 0 /* numLock */ , lockType,
13493 + 0 /* wait flag */ );
13494 + pfLock->fl_type = F_UNLCK;
13495 + if (rc != 0)
13496 + cERROR(1,
13497 + ("Error unlocking previously locked range %d during test of lock ",
13498 + rc));
13499 + rc = 0;
13500 +
13501 + } else {
13502 + /* if rc == ERR_SHARING_VIOLATION ? */
13503 + rc = 0; /* do not change lock type to unlock since range in use */
13504 + }
13505 +
13506 + FreeXid(xid);
13507 + return rc;
13508 + }
13509 +
13510 + rc = CIFSSMBLock(xid, pTcon,
13511 + ((struct cifsFileInfo *) file->private_data)->
13512 + netfid, length,
13513 + pfLock->fl_start, numUnlock, numLock, lockType,
13514 + wait_flag);
13515 + FreeXid(xid);
13516 + return rc;
13517 +}
13518 +
13519 +ssize_t
13520 +cifs_write(struct file * file, const char *write_data,
13521 + size_t write_size, loff_t * poffset)
13522 +{
13523 + int rc = 0;
13524 + unsigned int bytes_written = 0;
13525 + unsigned int total_written;
13526 + struct cifs_sb_info *cifs_sb;
13527 + struct cifsTconInfo *pTcon;
13528 + int xid, long_op;
13529 + struct cifsFileInfo * open_file;
13530 +
13531 + if(file->f_dentry == NULL)
13532 + return -EBADF;
13533 +
13534 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13535 + if(cifs_sb == NULL) {
13536 + return -EBADF;
13537 + }
13538 + pTcon = cifs_sb->tcon;
13539 +
13540 + /*cFYI(1,
13541 + (" write %d bytes to offset %lld of %s", write_size,
13542 + *poffset, file->f_dentry->d_name.name)); */
13543 +
13544 + if (file->private_data == NULL) {
13545 + return -EBADF;
13546 + } else {
13547 + open_file = (struct cifsFileInfo *) file->private_data;
13548 + }
13549 +
13550 + xid = GetXid();
13551 + if(file->f_dentry->d_inode == NULL) {
13552 + FreeXid(xid);
13553 + return -EBADF;
13554 + }
13555 +
13556 + if (*poffset > file->f_dentry->d_inode->i_size)
13557 + long_op = 2; /* writes past end of file can take a long time */
13558 + else
13559 + long_op = 1;
13560 +
13561 + for (total_written = 0; write_size > total_written;
13562 + total_written += bytes_written) {
13563 + rc = -EAGAIN;
13564 + while(rc == -EAGAIN) {
13565 + if(file->private_data == NULL) {
13566 + /* file has been closed on us */
13567 + FreeXid(xid);
13568 + /* if we have gotten here we have written some data
13569 + and blocked, and the file has been freed on us
13570 + while we blocked so return what we managed to write */
13571 + return total_written;
13572 + }
13573 + if(open_file->closePend) {
13574 + FreeXid(xid);
13575 + if(total_written)
13576 + return total_written;
13577 + else
13578 + return -EBADF;
13579 + }
13580 + if (open_file->invalidHandle) {
13581 + if((file->f_dentry == NULL) ||
13582 + (file->f_dentry->d_inode == NULL)) {
13583 + FreeXid(xid);
13584 + return total_written;
13585 + }
13586 + /* we could deadlock if we called
13587 + filemap_fdatawait from here so tell
13588 + reopen_file not to flush data to server now */
13589 + rc = cifs_reopen_file(file->f_dentry->d_inode,
13590 + file,FALSE);
13591 + if(rc != 0)
13592 + break;
13593 + }
13594 +
13595 + rc = CIFSSMBWrite(xid, pTcon,
13596 + open_file->netfid,
13597 + write_size - total_written, *poffset,
13598 + &bytes_written,
13599 + write_data + total_written, long_op);
13600 + }
13601 + if (rc || (bytes_written == 0)) {
13602 + if (total_written)
13603 + break;
13604 + else {
13605 + FreeXid(xid);
13606 + return rc;
13607 + }
13608 + } else
13609 + *poffset += bytes_written;
13610 + long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
13611 + }
13612 +
13613 +#ifdef CONFIG_CIFS_STATS
13614 + if(total_written > 0) {
13615 + atomic_inc(&pTcon->num_writes);
13616 + spin_lock(&pTcon->stat_lock);
13617 + pTcon->bytes_written += total_written;
13618 + spin_unlock(&pTcon->stat_lock);
13619 + }
13620 +#endif
13621 +
13622 + /* since the write may have blocked check these pointers again */
13623 + if(file->f_dentry) {
13624 + if(file->f_dentry->d_inode) {
13625 + file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
13626 + CURRENT_TIME;
13627 + if (total_written > 0) {
13628 + if (*poffset > file->f_dentry->d_inode->i_size)
13629 + file->f_dentry->d_inode->i_size = *poffset;
13630 + }
13631 + mark_inode_dirty_sync(file->f_dentry->d_inode);
13632 + }
13633 + }
13634 + FreeXid(xid);
13635 + return total_written;
13636 +}
13637 +
13638 +static int
13639 +cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
13640 +{
13641 + struct address_space *mapping = page->mapping;
13642 + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
13643 + char * write_data;
13644 + int rc = -EFAULT;
13645 + int bytes_written = 0;
13646 + struct cifs_sb_info *cifs_sb;
13647 + struct cifsTconInfo *pTcon;
13648 + struct inode *inode;
13649 + struct cifsInodeInfo *cifsInode;
13650 + struct cifsFileInfo *open_file = NULL;
13651 + struct list_head *tmp;
13652 + struct list_head *tmp1;
13653 +
13654 + if (!mapping) {
13655 + return -EFAULT;
13656 + } else if(!mapping->host) {
13657 + return -EFAULT;
13658 + }
13659 +
13660 + inode = page->mapping->host;
13661 + cifs_sb = CIFS_SB(inode->i_sb);
13662 + pTcon = cifs_sb->tcon;
13663 +
13664 + offset += (loff_t)from;
13665 + write_data = kmap(page);
13666 + write_data += from;
13667 +
13668 + if((to > PAGE_CACHE_SIZE) || (from > to)) {
13669 + kunmap(page);
13670 + return -EIO;
13671 + }
13672 +
13673 + /* racing with truncate? */
13674 + if(offset > mapping->host->i_size) {
13675 + kunmap(page);
13676 + return 0; /* don't care */
13677 + }
13678 +
13679 + /* check to make sure that we are not extending the file */
13680 + if(mapping->host->i_size - offset < (loff_t)to)
13681 + to = (unsigned)(mapping->host->i_size - offset);
13682 +
13683 +
13684 + cifsInode = CIFS_I(mapping->host);
13685 + read_lock(&GlobalSMBSeslock);
13686 + /* BB we should start at the end */
13687 + list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
13688 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
13689 + if(open_file->closePend)
13690 + continue;
13691 + /* We check if file is open for writing first */
13692 + if((open_file->pfile) &&
13693 + ((open_file->pfile->f_flags & O_RDWR) ||
13694 + (open_file->pfile->f_flags & O_WRONLY))) {
13695 + read_unlock(&GlobalSMBSeslock);
13696 + bytes_written = cifs_write(open_file->pfile, write_data,
13697 + to-from, &offset);
13698 + read_lock(&GlobalSMBSeslock);
13699 + /* Does mm or vfs already set times? */
13700 + inode->i_atime = inode->i_mtime = CURRENT_TIME;
13701 + if ((bytes_written > 0) && (offset)) {
13702 + rc = 0;
13703 + } else if(bytes_written < 0) {
13704 + if(rc == -EBADF) {
13705 + /* have seen a case in which
13706 + kernel seemed to have closed/freed a file
13707 + even with writes active so we might as well
13708 + see if there are other file structs to try
13709 + for the same inode before giving up */
13710 + continue;
13711 + } else
13712 + rc = bytes_written;
13713 + }
13714 + break; /* now that we found a valid file handle
13715 + and tried to write to it we are done, no
13716 + sense continuing to loop looking for another */
13717 + }
13718 + if(tmp->next == NULL) {
13719 + cFYI(1,("File instance %p removed",tmp));
13720 + break;
13721 + }
13722 + }
13723 + read_unlock(&GlobalSMBSeslock);
13724 + if(open_file == NULL) {
13725 + cFYI(1,("No writeable filehandles for inode"));
13726 + rc = -EIO;
13727 + }
13728 +
13729 + kunmap(page);
13730 + return rc;
13731 +}
13732 +
13733 +#if 0
13734 +static int
13735 +cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
13736 +{
13737 + int rc = -EFAULT;
13738 + int xid;
13739 +
13740 + xid = GetXid();
13741 +/* call 16K write then Setpageuptodate */
13742 + FreeXid(xid);
13743 + return rc;
13744 +}
13745 +#endif
13746 +
13747 +static int
13748 +cifs_writepage(struct page* page)
13749 +{
13750 + int rc = -EFAULT;
13751 + int xid;
13752 +
13753 + xid = GetXid();
13754 +/* BB add check for wbc flags */
13755 + page_cache_get(page);
13756 + if (!Page_Uptodate(page)) {
13757 + cFYI(1,("ppw - page not up to date"));
13758 + }
13759 +
13760 + rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
13761 + SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
13762 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
13763 + unlock_page(page);
13764 +#else
13765 + UnlockPage(page);
13766 +#endif
13767 + page_cache_release(page);
13768 + FreeXid(xid);
13769 + return rc;
13770 +}
13771 +
13772 +static int
13773 +cifs_commit_write(struct file *file, struct page *page, unsigned offset,
13774 + unsigned to)
13775 +{
13776 + int xid;
13777 + int rc = 0;
13778 + struct inode *inode = page->mapping->host;
13779 + loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
13780 + char * page_data;
13781 +
13782 + xid = GetXid();
13783 + cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
13784 + if (position > inode->i_size){
13785 + inode->i_size = position;
13786 + /*if (file->private_data == NULL) {
13787 + rc = -EBADF;
13788 + } else {
13789 + open_file = (struct cifsFileInfo *)file->private_data;
13790 + cifs_sb = CIFS_SB(inode->i_sb);
13791 + rc = -EAGAIN;
13792 + while(rc == -EAGAIN) {
13793 + if((open_file->invalidHandle) &&
13794 + (!open_file->closePend)) {
13795 + rc = cifs_reopen_file(file->f_dentry->d_inode,file);
13796 + if(rc != 0)
13797 + break;
13798 + }
13799 + if(!open_file->closePend) {
13800 + rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
13801 + position, open_file->netfid,
13802 + open_file->pid,FALSE);
13803 + } else {
13804 + rc = -EBADF;
13805 + break;
13806 + }
13807 + }
13808 + cFYI(1,(" SetEOF (commit write) rc = %d",rc));
13809 + }*/
13810 + }
13811 + if (!Page_Uptodate(page)) {
13812 + position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
13813 + /* can not rely on (or let) writepage write this data */
13814 + if(to < offset) {
13815 + cFYI(1,("Illegal offsets, can not copy from %d to %d",
13816 + offset,to));
13817 + FreeXid(xid);
13818 + return rc;
13819 + }
13820 + /* this is probably better than directly calling
13821 + partialpage_write since in this function
13822 + the file handle is known which we might as well
13823 + leverage */
13824 + /* BB check if anything else missing out of ppw */
13825 + /* such as updating last write time */
13826 + page_data = kmap(page);
13827 + rc = cifs_write(file, page_data+offset,to-offset,
13828 + &position);
13829 + if(rc > 0)
13830 + rc = 0;
13831 + /* else if rc < 0 should we set writebehind rc? */
13832 + kunmap(page);
13833 + } else {
13834 + set_page_dirty(page);
13835 + }
13836 +
13837 + FreeXid(xid);
13838 + return rc;
13839 +}
13840 +
13841 +int
13842 +cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
13843 +{
13844 + int xid;
13845 + int rc = 0;
13846 + struct inode * inode = file->f_dentry->d_inode;
13847 +
13848 + xid = GetXid();
13849 +
13850 + cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
13851 + dentry->d_name.name, datasync));
13852 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
13853 + rc = filemap_fdatasync(inode->i_mapping);
13854 +#else
13855 + filemap_fdatasync(inode->i_mapping);
13856 +#endif
13857 + if(rc == 0)
13858 + CIFS_I(inode)->write_behind_rc = 0;
13859 + FreeXid(xid);
13860 + return rc;
13861 +}
13862 +
13863 +static int
13864 +cifs_sync_page(struct page *page)
13865 +{
13866 + struct address_space *mapping;
13867 + struct inode *inode;
13868 + unsigned long index = page->index;
13869 + unsigned int rpages = 0;
13870 + int rc = 0;
13871 +
13872 + cFYI(1,("sync page %p",page));
13873 + mapping = page->mapping;
13874 + if (!mapping)
13875 + return 0;
13876 + inode = mapping->host;
13877 + if (!inode)
13878 + return 0;
13879 +
13880 +/* fill in rpages then
13881 + result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
13882 +
13883 + cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
13884 +
13885 + if (rc < 0)
13886 + return rc;
13887 + return 0;
13888 +}
13889 +
13890 +/*
13891 + * As file closes, flush all cached write data for this inode checking
13892 + * for write behind errors.
13893 + *
13894 + */
13895 +int cifs_flush(struct file *file)
13896 +{
13897 + struct inode * inode = file->f_dentry->d_inode;
13898 + int rc = 0;
13899 +
13900 + /* Rather than do the steps manually: */
13901 + /* lock the inode for writing */
13902 + /* loop through pages looking for write behind data (dirty pages) */
13903 + /* coalesce into contiguous 16K (or smaller) chunks to write to server */
13904 + /* send to server (prefer in parallel) */
13905 + /* deal with writebehind errors */
13906 + /* unlock inode for writing */
13907 + /* filemapfdatawrite appears easier for the time being */
13908 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
13909 + rc = filemap_fdatasync(inode->i_mapping);
13910 +#else
13911 + filemap_fdatasync(inode->i_mapping);
13912 +#endif
13913 + if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
13914 + CIFS_I(inode)->write_behind_rc = 0;
13915 +
13916 + cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
13917 +
13918 + return rc;
13919 +}
13920 +
13921 +
13922 +ssize_t
13923 +cifs_read(struct file * file, char *read_data, size_t read_size,
13924 + loff_t * poffset)
13925 +{
13926 + int rc = -EACCES;
13927 + unsigned int bytes_read = 0;
13928 + unsigned int total_read;
13929 + unsigned int current_read_size;
13930 + struct cifs_sb_info *cifs_sb;
13931 + struct cifsTconInfo *pTcon;
13932 + int xid;
13933 + char * current_offset;
13934 + struct cifsFileInfo * open_file;
13935 +
13936 + xid = GetXid();
13937 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
13938 + pTcon = cifs_sb->tcon;
13939 +
13940 + if (file->private_data == NULL) {
13941 + FreeXid(xid);
13942 + return -EBADF;
13943 + }
13944 + open_file = (struct cifsFileInfo *)file->private_data;
13945 +
13946 + if((file->f_flags & O_ACCMODE) == O_WRONLY) {
13947 + cFYI(1,("attempting read on write only file instance"));
13948 + }
13949 +
13950 + for (total_read = 0,current_offset=read_data; read_size > total_read;
13951 + total_read += bytes_read,current_offset+=bytes_read) {
13952 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
13953 + current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
13954 +#else
13955 + current_read_size = min(read_size - total_read,cifs_sb->rsize);
13956 +#endif
13957 + rc = -EAGAIN;
13958 + while(rc == -EAGAIN) {
13959 + if ((open_file->invalidHandle) && (!open_file->closePend)) {
13960 + rc = cifs_reopen_file(file->f_dentry->d_inode,
13961 + file,TRUE);
13962 + if(rc != 0)
13963 + break;
13964 + }
13965 +
13966 + rc = CIFSSMBRead(xid, pTcon,
13967 + open_file->netfid,
13968 + current_read_size, *poffset,
13969 + &bytes_read, &current_offset);
13970 + }
13971 + if (rc || (bytes_read == 0)) {
13972 + if (total_read) {
13973 + break;
13974 + } else {
13975 + FreeXid(xid);
13976 + return rc;
13977 + }
13978 + } else {
13979 +#ifdef CONFIG_CIFS_STATS
13980 + atomic_inc(&pTcon->num_reads);
13981 + spin_lock(&pTcon->stat_lock);
13982 + pTcon->bytes_read += total_read;
13983 + spin_unlock(&pTcon->stat_lock);
13984 +#endif
13985 + *poffset += bytes_read;
13986 + }
13987 + }
13988 + FreeXid(xid);
13989 + return total_read;
13990 +}
13991 +
13992 +int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
13993 +{
13994 + struct dentry * dentry = file->f_dentry;
13995 + int rc, xid;
13996 +
13997 + xid = GetXid();
13998 + rc = cifs_revalidate(dentry);
13999 + if (rc) {
14000 + cFYI(1,("Validation prior to mmap failed, error=%d", rc));
14001 + FreeXid(xid);
14002 + return rc;
14003 + }
14004 + rc = generic_file_mmap(file, vma);
14005 + FreeXid(xid);
14006 + return rc;
14007 +}
14008 +
14009 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
14010 +static void cifs_copy_cache_pages(struct address_space *mapping,
14011 + struct list_head *pages, int bytes_read,
14012 + char *data,struct pagevec * plru_pvec)
14013 +{
14014 + struct page *page;
14015 + char * target;
14016 +
14017 + while (bytes_read > 0) {
14018 + if(list_empty(pages))
14019 + break;
14020 +
14021 + page = list_entry(pages->prev, struct page, lru);
14022 + list_del(&page->lru);
14023 +
14024 + if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
14025 + page_cache_release(page);
14026 + cFYI(1,("Add page cache failed"));
14027 + continue;
14028 + }
14029 +
14030 + target = kmap_atomic(page,KM_USER0);
14031 +
14032 + if(PAGE_CACHE_SIZE > bytes_read) {
14033 + memcpy(target,data,bytes_read);
14034 + /* zero the tail end of this partial page */
14035 + memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
14036 + bytes_read = 0;
14037 + } else {
14038 + memcpy(target,data,PAGE_CACHE_SIZE);
14039 + bytes_read -= PAGE_CACHE_SIZE;
14040 + }
14041 + kunmap_atomic(target,KM_USER0);
14042 +
14043 + flush_dcache_page(page);
14044 + SetPageUptodate(page);
14045 + unlock_page(page);
14046 + if (!pagevec_add(plru_pvec, page))
14047 + __pagevec_lru_add(plru_pvec);
14048 + data += PAGE_CACHE_SIZE;
14049 + }
14050 + return;
14051 +}
14052 +
14053 +
14054 +static int
14055 +cifs_readpages(struct file *file, struct address_space *mapping,
14056 + struct list_head *page_list, unsigned num_pages)
14057 +{
14058 + int rc = -EACCES;
14059 + int xid;
14060 + loff_t offset;
14061 + struct page * page;
14062 + struct cifs_sb_info *cifs_sb;
14063 + struct cifsTconInfo *pTcon;
14064 + int bytes_read = 0;
14065 + unsigned int read_size,i;
14066 + char * smb_read_data = NULL;
14067 + struct smb_com_read_rsp * pSMBr;
14068 + struct pagevec lru_pvec;
14069 + struct cifsFileInfo * open_file;
14070 +
14071 + xid = GetXid();
14072 + if (file->private_data == NULL) {
14073 + FreeXid(xid);
14074 + return -EBADF;
14075 + }
14076 + open_file = (struct cifsFileInfo *)file->private_data;
14077 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14078 + pTcon = cifs_sb->tcon;
14079 +
14080 + pagevec_init(&lru_pvec, 0);
14081 +
14082 + for(i = 0;i<num_pages;) {
14083 + unsigned contig_pages;
14084 + struct page * tmp_page;
14085 + unsigned long expected_index;
14086 +
14087 + if(list_empty(page_list)) {
14088 + break;
14089 + }
14090 + page = list_entry(page_list->prev, struct page, lru);
14091 + offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
14092 +
14093 + /* count adjacent pages that we will read into */
14094 + contig_pages = 0;
14095 + expected_index = list_entry(page_list->prev,struct page,lru)->index;
14096 + list_for_each_entry_reverse(tmp_page,page_list,lru) {
14097 + if(tmp_page->index == expected_index) {
14098 + contig_pages++;
14099 + expected_index++;
14100 + } else {
14101 + break;
14102 + }
14103 + }
14104 + if(contig_pages + i > num_pages) {
14105 + contig_pages = num_pages - i;
14106 + }
14107 +
14108 + /* for reads over a certain size could initiate async read ahead */
14109 +
14110 + read_size = contig_pages * PAGE_CACHE_SIZE;
14111 + /* Read size needs to be in multiples of one page */
14112 + read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
14113 +
14114 + rc = -EAGAIN;
14115 + while(rc == -EAGAIN) {
14116 + if ((open_file->invalidHandle) && (!open_file->closePend)) {
14117 + rc = cifs_reopen_file(file->f_dentry->d_inode,
14118 + file, TRUE);
14119 + if(rc != 0)
14120 + break;
14121 + }
14122 +
14123 + rc = CIFSSMBRead(xid, pTcon,
14124 + open_file->netfid,
14125 + read_size, offset,
14126 + &bytes_read, &smb_read_data);
14127 + /* BB need to check return code here */
14128 + if(rc== -EAGAIN) {
14129 + if(smb_read_data) {
14130 + cifs_buf_release(smb_read_data);
14131 + smb_read_data = NULL;
14132 + }
14133 + }
14134 + }
14135 + if ((rc < 0) || (smb_read_data == NULL)) {
14136 + cFYI(1,("Read error in readpages: %d",rc));
14137 + /* clean up remaing pages off list */
14138 + while (!list_empty(page_list) && (i < num_pages)) {
14139 + page = list_entry(page_list->prev, struct page, lru);
14140 + list_del(&page->lru);
14141 + page_cache_release(page);
14142 + }
14143 + break;
14144 + } else if (bytes_read > 0) {
14145 + pSMBr = (struct smb_com_read_rsp *)smb_read_data;
14146 + cifs_copy_cache_pages(mapping, page_list, bytes_read,
14147 + smb_read_data + 4 /* RFC1001 hdr */ +
14148 + le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
14149 +
14150 + i += bytes_read >> PAGE_CACHE_SHIFT;
14151 +#ifdef CONFIG_CIFS_STATS
14152 + atomic_inc(&pTcon->num_reads);
14153 + spin_lock(&pTcon->stat_lock);
14154 + pTcon->bytes_read += bytes_read;
14155 + spin_unlock(&pTcon->stat_lock);
14156 +#endif
14157 + if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
14158 + cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
14159 +
14160 + i++; /* account for partial page */
14161 +
14162 + /* server copy of file can have smaller size than client */
14163 + /* BB do we need to verify this common case ? this case is ok -
14164 + if we are at server EOF we will hit it on next read */
14165 +
14166 + /* while(!list_empty(page_list) && (i < num_pages)) {
14167 + page = list_entry(page_list->prev,struct page, list);
14168 + list_del(&page->list);
14169 + page_cache_release(page);
14170 + }
14171 + break; */
14172 + }
14173 + } else {
14174 + cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
14175 + /* BB turn off caching and do new lookup on file size at server? */
14176 + while (!list_empty(page_list) && (i < num_pages)) {
14177 + page = list_entry(page_list->prev, struct page, lru);
14178 + list_del(&page->lru);
14179 + page_cache_release(page); /* BB removeme - replace with zero of page? */
14180 + }
14181 + break;
14182 + }
14183 + if(smb_read_data) {
14184 + cifs_buf_release(smb_read_data);
14185 + smb_read_data = NULL;
14186 + }
14187 + bytes_read = 0;
14188 + }
14189 +
14190 + pagevec_lru_add(&lru_pvec);
14191 +
14192 +/* need to free smb_read_data buf before exit */
14193 + if(smb_read_data) {
14194 + cifs_buf_release(smb_read_data);
14195 + smb_read_data = NULL;
14196 + }
14197 +
14198 + FreeXid(xid);
14199 + return rc;
14200 +}
14201 +#endif
14202 +
14203 +static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
14204 +{
14205 + char * read_data;
14206 + int rc;
14207 +
14208 + page_cache_get(page);
14209 + read_data = kmap(page);
14210 + /* for reads over a certain size could initiate async read ahead */
14211 +
14212 + rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
14213 +
14214 + if (rc < 0)
14215 + goto io_error;
14216 + else {
14217 + cFYI(1,("Bytes read %d ",rc));
14218 + }
14219 +
14220 + file->f_dentry->d_inode->i_atime = CURRENT_TIME;
14221 +
14222 + if(PAGE_CACHE_SIZE > rc) {
14223 + memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
14224 + }
14225 + flush_dcache_page(page);
14226 + SetPageUptodate(page);
14227 + rc = 0;
14228 +
14229 +io_error:
14230 + kunmap(page);
14231 + page_cache_release(page);
14232 + return rc;
14233 +}
14234 +
14235 +static int
14236 +cifs_readpage(struct file *file, struct page *page)
14237 +{
14238 + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
14239 + int rc = -EACCES;
14240 + int xid;
14241 +
14242 + xid = GetXid();
14243 +
14244 + if (file->private_data == NULL) {
14245 + FreeXid(xid);
14246 + return -EBADF;
14247 + }
14248 +
14249 + cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
14250 +
14251 + rc = cifs_readpage_worker(file,page,&offset);
14252 +
14253 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
14254 + unlock_page(page);
14255 +#else
14256 + UnlockPage(page);
14257 +#endif
14258 +
14259 + FreeXid(xid);
14260 + return rc;
14261 +}
14262 +
14263 +/* We do not want to update the file size from server for inodes
14264 + open for write - to avoid races with writepage extending
14265 + the file - in the future we could consider allowing
14266 + refreshing the inode only on increases in the file size
14267 + but this is tricky to do without racing with writebehind
14268 + page caching in the current Linux kernel design */
14269 +
14270 +int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
14271 +{
14272 + struct list_head *tmp;
14273 + struct list_head *tmp1;
14274 + struct cifsFileInfo *open_file = NULL;
14275 + int rc = TRUE;
14276 +
14277 + if(cifsInode == NULL)
14278 + return rc;
14279 +
14280 + read_lock(&GlobalSMBSeslock);
14281 + list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
14282 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
14283 + if(open_file == NULL)
14284 + break;
14285 + if(open_file->closePend)
14286 + continue;
14287 + /* We check if file is open for writing,
14288 + BB we could supplement this with a check to see if file size
14289 + changes have been flushed to server - ie inode metadata dirty */
14290 + if((open_file->pfile) &&
14291 + ((open_file->pfile->f_flags & O_RDWR) ||
14292 + (open_file->pfile->f_flags & O_WRONLY))) {
14293 + rc = FALSE;
14294 + break;
14295 + }
14296 + if(tmp->next == NULL) {
14297 + cFYI(1,("File instance %p removed",tmp));
14298 + break;
14299 + }
14300 + }
14301 + read_unlock(&GlobalSMBSeslock);
14302 + return rc;
14303 +}
14304 +
14305 +
14306 +void
14307 +fill_in_inode(struct inode *tmp_inode,
14308 + FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
14309 +{
14310 + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
14311 + struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
14312 +
14313 + pfindData->ExtFileAttributes =
14314 + le32_to_cpu(pfindData->ExtFileAttributes);
14315 + pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
14316 + pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
14317 + cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
14318 + cifsInfo->time = jiffies;
14319 +
14320 + /* Linux can not store file creation time unfortunately so ignore it */
14321 + tmp_inode->i_atime =
14322 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
14323 + tmp_inode->i_mtime =
14324 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
14325 + tmp_inode->i_ctime =
14326 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
14327 + /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
14328 + /* 2767 perms - indicate mandatory locking */
14329 + /* BB fill in uid and gid here? with help from winbind?
14330 + or retrieve from NTFS stream extended attribute */
14331 + if(atomic_read(&cifsInfo->inUse) == 0) {
14332 + tmp_inode->i_uid = cifs_sb->mnt_uid;
14333 + tmp_inode->i_gid = cifs_sb->mnt_gid;
14334 + /* set default mode. will override for dirs below */
14335 + tmp_inode->i_mode = cifs_sb->mnt_file_mode;
14336 + }
14337 +
14338 + cFYI(0,
14339 + ("CIFS FFIRST: Attributes came in as 0x%x",
14340 + pfindData->ExtFileAttributes));
14341 + if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
14342 + *pobject_type = DT_LNK;
14343 + /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
14344 + tmp_inode->i_mode |= S_IFLNK;
14345 + } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
14346 + *pobject_type = DT_DIR;
14347 + /* override default perms since we do not lock dirs */
14348 + if(atomic_read(&cifsInfo->inUse) == 0) {
14349 + tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
14350 + }
14351 + tmp_inode->i_mode |= S_IFDIR;
14352 + } else {
14353 + *pobject_type = DT_REG;
14354 + tmp_inode->i_mode |= S_IFREG;
14355 + if(pfindData->ExtFileAttributes & ATTR_READONLY)
14356 + tmp_inode->i_mode &= ~(S_IWUGO);
14357 +
14358 + }/* could add code here - to validate if device or weird share type? */
14359 +
14360 + /* can not fill in nlink here as in qpathinfo version and Unx search */
14361 + if(atomic_read(&cifsInfo->inUse) == 0) {
14362 + atomic_set(&cifsInfo->inUse,1);
14363 + }
14364 + if(is_size_safe_to_change(cifsInfo)) {
14365 + /* can not safely change the file size here if the
14366 + client is writing to it due to potential races */
14367 + tmp_inode->i_size = pfindData->EndOfFile;
14368 +
14369 + /* 512 bytes (2**9) is the fake blocksize that must be used */
14370 + /* for this calculation, even though the reported blocksize is larger */
14371 + tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
14372 + }
14373 +
14374 + if (pfindData->AllocationSize < pfindData->EndOfFile)
14375 + cFYI(1, ("Possible sparse file: allocation size less than end of file "));
14376 + cFYI(1,
14377 + ("File Size %ld and blocks %ld and blocksize %ld",
14378 + (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
14379 + tmp_inode->i_blksize));
14380 + if (S_ISREG(tmp_inode->i_mode)) {
14381 + cFYI(1, (" File inode "));
14382 + tmp_inode->i_op = &cifs_file_inode_ops;
14383 + tmp_inode->i_fop = &cifs_file_ops;
14384 + tmp_inode->i_data.a_ops = &cifs_addr_ops;
14385 + } else if (S_ISDIR(tmp_inode->i_mode)) {
14386 + cFYI(1, (" Directory inode"));
14387 + tmp_inode->i_op = &cifs_dir_inode_ops;
14388 + tmp_inode->i_fop = &cifs_dir_ops;
14389 + } else if (S_ISLNK(tmp_inode->i_mode)) {
14390 + cFYI(1, (" Symbolic Link inode "));
14391 + tmp_inode->i_op = &cifs_symlink_inode_ops;
14392 + } else {
14393 + cFYI(1, (" Init special inode "));
14394 + init_special_inode(tmp_inode, tmp_inode->i_mode,
14395 + kdev_t_to_nr(tmp_inode->i_rdev));
14396 + }
14397 +}
14398 +
14399 +void
14400 +unix_fill_in_inode(struct inode *tmp_inode,
14401 + FILE_UNIX_INFO * pfindData, int *pobject_type)
14402 +{
14403 + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
14404 + cifsInfo->time = jiffies;
14405 + atomic_inc(&cifsInfo->inUse);
14406 +
14407 + tmp_inode->i_atime =
14408 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
14409 + tmp_inode->i_mtime =
14410 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
14411 + tmp_inode->i_ctime =
14412 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
14413 +
14414 + tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
14415 + pfindData->Type = le32_to_cpu(pfindData->Type);
14416 + if (pfindData->Type == UNIX_FILE) {
14417 + *pobject_type = DT_REG;
14418 + tmp_inode->i_mode |= S_IFREG;
14419 + } else if (pfindData->Type == UNIX_SYMLINK) {
14420 + *pobject_type = DT_LNK;
14421 + tmp_inode->i_mode |= S_IFLNK;
14422 + } else if (pfindData->Type == UNIX_DIR) {
14423 + *pobject_type = DT_DIR;
14424 + tmp_inode->i_mode |= S_IFDIR;
14425 + } else if (pfindData->Type == UNIX_CHARDEV) {
14426 + *pobject_type = DT_CHR;
14427 + tmp_inode->i_mode |= S_IFCHR;
14428 + tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
14429 + le64_to_cpu(pfindData->DevMinor) & MINORMASK);
14430 + } else if (pfindData->Type == UNIX_BLOCKDEV) {
14431 + *pobject_type = DT_BLK;
14432 + tmp_inode->i_mode |= S_IFBLK;
14433 + tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
14434 + le64_to_cpu(pfindData->DevMinor) & MINORMASK);
14435 + } else if (pfindData->Type == UNIX_FIFO) {
14436 + *pobject_type = DT_FIFO;
14437 + tmp_inode->i_mode |= S_IFIFO;
14438 + } else if (pfindData->Type == UNIX_SOCKET) {
14439 + *pobject_type = DT_SOCK;
14440 + tmp_inode->i_mode |= S_IFSOCK;
14441 + }
14442 +
14443 + tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
14444 + tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
14445 + tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
14446 +
14447 + pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
14448 + if(is_size_safe_to_change(cifsInfo)) {
14449 + /* can not safely change the file size here if the
14450 + client is writing to it due to potential races */
14451 + pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
14452 + tmp_inode->i_size = pfindData->EndOfFile;
14453 +
14454 + /* 512 bytes (2**9) is the fake blocksize that must be used */
14455 + /* for this calculation, not the real blocksize */
14456 + tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
14457 + }
14458 +
14459 + if (S_ISREG(tmp_inode->i_mode)) {
14460 + cFYI(1, ("File inode"));
14461 + tmp_inode->i_op = &cifs_file_inode_ops;
14462 + tmp_inode->i_fop = &cifs_file_ops;
14463 + tmp_inode->i_data.a_ops = &cifs_addr_ops;
14464 + } else if (S_ISDIR(tmp_inode->i_mode)) {
14465 + cFYI(1, ("Directory inode"));
14466 + tmp_inode->i_op = &cifs_dir_inode_ops;
14467 + tmp_inode->i_fop = &cifs_dir_ops;
14468 + } else if (S_ISLNK(tmp_inode->i_mode)) {
14469 + cFYI(1, ("Symbolic Link inode"));
14470 + tmp_inode->i_op = &cifs_symlink_inode_ops;
14471 +/* tmp_inode->i_fop = *//* do not need to set to anything */
14472 + } else {
14473 + cFYI(1, ("Special inode"));
14474 + init_special_inode(tmp_inode, tmp_inode->i_mode,
14475 + kdev_t_to_nr(tmp_inode->i_rdev));
14476 + }
14477 +}
14478 +
14479 +static void
14480 +construct_dentry(struct qstr *qstring, struct file *file,
14481 + struct inode **ptmp_inode, struct dentry **pnew_dentry)
14482 +{
14483 + struct dentry *tmp_dentry;
14484 + struct cifs_sb_info *cifs_sb;
14485 + struct cifsTconInfo *pTcon;
14486 + struct cifsInodeInfo *pCifsI;
14487 +
14488 + cFYI(1, ("For %s ", qstring->name));
14489 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14490 + pTcon = cifs_sb->tcon;
14491 +
14492 + qstring->hash = full_name_hash(qstring->name, qstring->len);
14493 + tmp_dentry = d_lookup(file->f_dentry, qstring);
14494 + if (tmp_dentry) {
14495 + cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
14496 + *ptmp_inode = tmp_dentry->d_inode;
14497 + /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
14498 + if(*ptmp_inode == NULL) {
14499 + *ptmp_inode = new_inode(file->f_dentry->d_sb);
14500 + if(*ptmp_inode == NULL)
14501 + return;
14502 + d_instantiate(tmp_dentry, *ptmp_inode);
14503 + insert_inode_hash(*ptmp_inode);
14504 + pCifsI = CIFS_I(*ptmp_inode);
14505 + INIT_LIST_HEAD(&pCifsI->openFileList);
14506 + /* can not enable caching for this inode
14507 + until a file instance is open and we
14508 + can check the oplock flag on the open
14509 + response */
14510 + (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
14511 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
14512 + (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
14513 +#endif
14514 + pCifsI->clientCanCacheRead = FALSE;
14515 + pCifsI->clientCanCacheAll = FALSE;
14516 + pCifsI->time = 0;
14517 + /* do not need to set cifs Attrs since
14518 + they are about to be overwritten
14519 + in fill_in_inode */
14520 + atomic_set(&pCifsI->inUse, 0);
14521 + }
14522 + } else {
14523 + tmp_dentry = d_alloc(file->f_dentry, qstring);
14524 + if(tmp_dentry == NULL) {
14525 + cERROR(1,("Failed allocating dentry"));
14526 + return;
14527 + }
14528 +
14529 + if(ptmp_inode) {
14530 + *ptmp_inode = new_inode(file->f_dentry->d_sb);
14531 + if(*ptmp_inode == NULL)
14532 + return;
14533 + pCifsI = CIFS_I(*ptmp_inode);
14534 + insert_inode_hash(*ptmp_inode);
14535 + INIT_LIST_HEAD(&pCifsI->openFileList);
14536 + /* can not enable caching for this inode
14537 + until a file instance is open and we
14538 + can check the oplock flag on the open
14539 + response */
14540 + (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
14541 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
14542 + (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
14543 +#endif
14544 + pCifsI->clientCanCacheRead = FALSE;
14545 + pCifsI->clientCanCacheAll = FALSE;
14546 + pCifsI->time = 0;
14547 + /* do not need to set cifs Attrs since
14548 + they are about to be overwritten
14549 + in fill_in_inode */
14550 + atomic_set(&pCifsI->inUse, 0);
14551 + }
14552 + tmp_dentry->d_op = &cifs_dentry_ops;
14553 + d_instantiate(tmp_dentry, *ptmp_inode);
14554 + d_rehash(tmp_dentry);
14555 + }
14556 +
14557 + tmp_dentry->d_time = jiffies;
14558 + *pnew_dentry = tmp_dentry;
14559 +}
14560 +
14561 +static void reset_resume_key(struct file * dir_file,
14562 + unsigned char * filename,
14563 + unsigned int len,int Unicode,struct nls_table * nls_tab) {
14564 + struct cifsFileInfo *cifsFile;
14565 +
14566 + cifsFile = (struct cifsFileInfo *)dir_file->private_data;
14567 + if(cifsFile == NULL)
14568 + return;
14569 + if(cifsFile->search_resume_name) {
14570 + kfree(cifsFile->search_resume_name);
14571 + }
14572 +
14573 + if(Unicode)
14574 + len *= 2;
14575 + cifsFile->resume_name_length = len;
14576 +
14577 + cifsFile->search_resume_name =
14578 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14579 +
14580 + if(cifsFile->search_resume_name == NULL) {
14581 + cERROR(1,("failed new resume key allocate, length %d",
14582 + cifsFile->resume_name_length));
14583 + return;
14584 + }
14585 + if(Unicode)
14586 + cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
14587 + filename, len, nls_tab);
14588 + else
14589 + memcpy(cifsFile->search_resume_name, filename,
14590 + cifsFile->resume_name_length);
14591 + cFYI(1,("Reset resume key to: %s with len %d",filename,len));
14592 + return;
14593 +}
14594 +
14595 +
14596 +
14597 +static int
14598 +cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
14599 + struct file *file, filldir_t filldir, void *direntry)
14600 +{
14601 + struct inode *tmp_inode;
14602 + struct dentry *tmp_dentry;
14603 + int object_type,rc;
14604 +
14605 + pqstring->name = pfindData->FileName;
14606 + pqstring->len = pfindData->FileNameLength;
14607 +
14608 + construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
14609 + if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
14610 + return -ENOMEM;
14611 + }
14612 + fill_in_inode(tmp_inode, pfindData, &object_type);
14613 + rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
14614 + tmp_inode->i_ino, object_type);
14615 + if(rc) {
14616 + /* due to readdir error we need to recalculate resume
14617 + key so next readdir will restart on right entry */
14618 + cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
14619 + }
14620 + dput(tmp_dentry);
14621 + return rc;
14622 +}
14623 +
14624 +static int
14625 +cifs_filldir_unix(struct qstr *pqstring,
14626 + FILE_UNIX_INFO * pUnixFindData, struct file *file,
14627 + filldir_t filldir, void *direntry)
14628 +{
14629 + struct inode *tmp_inode;
14630 + struct dentry *tmp_dentry;
14631 + int object_type, rc;
14632 +
14633 + pqstring->name = pUnixFindData->FileName;
14634 + pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
14635 +
14636 + construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
14637 + if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
14638 + return -ENOMEM;
14639 + }
14640 +
14641 + unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
14642 + rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
14643 + file->f_pos, tmp_inode->i_ino, object_type);
14644 + if(rc) {
14645 + /* due to readdir error we need to recalculate resume
14646 + key so next readdir will restart on right entry */
14647 + cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
14648 + }
14649 + dput(tmp_dentry);
14650 + return rc;
14651 +}
14652 +
14653 +int
14654 +cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
14655 +{
14656 + int rc = 0;
14657 + int xid;
14658 + int Unicode = FALSE;
14659 + int UnixSearch = FALSE;
14660 + unsigned int bufsize, i;
14661 + __u16 searchHandle;
14662 + struct cifs_sb_info *cifs_sb;
14663 + struct cifsTconInfo *pTcon;
14664 + struct cifsFileInfo *cifsFile = NULL;
14665 + char *full_path = NULL;
14666 + char *data;
14667 + struct qstr qstring;
14668 + T2_FFIRST_RSP_PARMS findParms;
14669 + T2_FNEXT_RSP_PARMS findNextParms;
14670 + FILE_DIRECTORY_INFO *pfindData;
14671 + FILE_DIRECTORY_INFO *lastFindData;
14672 + FILE_UNIX_INFO *pfindDataUnix;
14673 +
14674 + xid = GetXid();
14675 +
14676 + cifs_sb = CIFS_SB(file->f_dentry->d_sb);
14677 + pTcon = cifs_sb->tcon;
14678 + bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
14679 + if(bufsize > CIFS_MAX_MSGSIZE) {
14680 + FreeXid(xid);
14681 + return -EIO;
14682 + }
14683 + data = kmalloc(bufsize, GFP_KERNEL);
14684 + pfindData = (FILE_DIRECTORY_INFO *) data;
14685 +
14686 + if(file->f_dentry == NULL) {
14687 + FreeXid(xid);
14688 + return -EIO;
14689 + }
14690 + down(&file->f_dentry->d_sb->s_vfs_rename_sem);
14691 + full_path = build_wildcard_path_from_dentry(file->f_dentry);
14692 + up(&file->f_dentry->d_sb->s_vfs_rename_sem);
14693 +
14694 +
14695 + cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
14696 +
14697 + switch ((int) file->f_pos) {
14698 + case 0:
14699 + if (filldir(direntry, ".", 1, file->f_pos,
14700 + file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
14701 + cERROR(1, ("Filldir for current dir failed "));
14702 + break;
14703 + }
14704 + file->f_pos++;
14705 + /* fallthrough */
14706 + case 1:
14707 + if (filldir(direntry, "..", 2, file->f_pos,
14708 + file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
14709 + cERROR(1, ("Filldir for parent dir failed "));
14710 + break;
14711 + }
14712 + file->f_pos++;
14713 + /* fallthrough */
14714 + case 2:
14715 + if (file->private_data != NULL) {
14716 + cifsFile =
14717 + (struct cifsFileInfo *) file->private_data;
14718 + if (cifsFile->endOfSearch) {
14719 + if(cifsFile->emptyDir) {
14720 + cFYI(1, ("End of search, empty dir"));
14721 + rc = 0;
14722 + break;
14723 + }
14724 + } else {
14725 + cifsFile->invalidHandle = TRUE;
14726 + CIFSFindClose(xid, pTcon, cifsFile->netfid);
14727 + }
14728 + if(cifsFile->search_resume_name) {
14729 + kfree(cifsFile->search_resume_name);
14730 + cifsFile->search_resume_name = NULL;
14731 + }
14732 + }
14733 + rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
14734 + &findParms, cifs_sb->local_nls,
14735 + &Unicode, &UnixSearch);
14736 + cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
14737 + findParms.EndofSearch));
14738 +
14739 + if (rc == 0) {
14740 + searchHandle = findParms.SearchHandle;
14741 + if(file->private_data == NULL)
14742 + file->private_data =
14743 + kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
14744 + if (file->private_data) {
14745 + memset(file->private_data, 0,
14746 + sizeof (struct cifsFileInfo));
14747 + cifsFile =
14748 + (struct cifsFileInfo *) file->private_data;
14749 + cifsFile->netfid = searchHandle;
14750 + cifsFile->invalidHandle = FALSE;
14751 + init_MUTEX(&cifsFile->fh_sem);
14752 + } else {
14753 + rc = -ENOMEM;
14754 + break;
14755 + }
14756 +
14757 + renew_parental_timestamps(file->f_dentry);
14758 + lastFindData =
14759 + (FILE_DIRECTORY_INFO *) ((char *) pfindData +
14760 + findParms.LastNameOffset);
14761 + if((char *)lastFindData > (char *)pfindData + bufsize) {
14762 + cFYI(1,("last search entry past end of packet"));
14763 + rc = -EIO;
14764 + break;
14765 + }
14766 + /* Offset of resume key same for levels 257 and 514 */
14767 + cifsFile->resume_key = lastFindData->FileIndex;
14768 + if(UnixSearch == FALSE) {
14769 + cifsFile->resume_name_length =
14770 + le32_to_cpu(lastFindData->FileNameLength);
14771 + if(cifsFile->resume_name_length > bufsize - 64) {
14772 + cFYI(1,("Illegal resume file name length %d",
14773 + cifsFile->resume_name_length));
14774 + rc = -ENOMEM;
14775 + break;
14776 + }
14777 + cifsFile->search_resume_name =
14778 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14779 + cFYI(1,("Last file: %s with name %d bytes long",
14780 + lastFindData->FileName,
14781 + cifsFile->resume_name_length));
14782 + memcpy(cifsFile->search_resume_name,
14783 + lastFindData->FileName,
14784 + cifsFile->resume_name_length);
14785 + } else {
14786 + pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
14787 + if (Unicode == TRUE) {
14788 + for(i=0;(pfindDataUnix->FileName[i]
14789 + | pfindDataUnix->FileName[i+1]);
14790 + i+=2) {
14791 + if(i > bufsize-64)
14792 + break;
14793 + }
14794 + cifsFile->resume_name_length = i + 2;
14795 + } else {
14796 + cifsFile->resume_name_length =
14797 + strnlen(pfindDataUnix->FileName,
14798 + bufsize-63);
14799 + }
14800 + if(cifsFile->resume_name_length > bufsize - 64) {
14801 + cFYI(1,("Illegal resume file name length %d",
14802 + cifsFile->resume_name_length));
14803 + rc = -ENOMEM;
14804 + break;
14805 + }
14806 + cifsFile->search_resume_name =
14807 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14808 + cFYI(1,("Last file: %s with name %d bytes long",
14809 + pfindDataUnix->FileName,
14810 + cifsFile->resume_name_length));
14811 + memcpy(cifsFile->search_resume_name,
14812 + pfindDataUnix->FileName,
14813 + cifsFile->resume_name_length);
14814 + }
14815 + for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
14816 + if (UnixSearch == FALSE) {
14817 + pfindData->FileNameLength =
14818 + le32_to_cpu(pfindData->FileNameLength);
14819 + if (Unicode == TRUE)
14820 + pfindData->FileNameLength =
14821 + cifs_strfromUCS_le
14822 + (pfindData->FileName,
14823 + (wchar_t *)
14824 + pfindData->FileName,
14825 + (pfindData->
14826 + FileNameLength) / 2,
14827 + cifs_sb->local_nls);
14828 + qstring.len = pfindData->FileNameLength;
14829 + if (((qstring.len != 1)
14830 + || (pfindData->FileName[0] != '.'))
14831 + && ((qstring.len != 2)
14832 + || (pfindData->
14833 + FileName[0] != '.')
14834 + || (pfindData->
14835 + FileName[1] != '.'))) {
14836 + if(cifs_filldir(&qstring,
14837 + pfindData,
14838 + file, filldir,
14839 + direntry)) {
14840 + /* do not end search if
14841 + kernel not ready to take
14842 + remaining entries yet */
14843 + reset_resume_key(file, pfindData->FileName,qstring.len,
14844 + Unicode, cifs_sb->local_nls);
14845 + findParms.EndofSearch = 0;
14846 + break;
14847 + }
14848 + file->f_pos++;
14849 + }
14850 + } else { /* UnixSearch */
14851 + pfindDataUnix =
14852 + (FILE_UNIX_INFO *) pfindData;
14853 + if (Unicode == TRUE)
14854 + qstring.len =
14855 + cifs_strfromUCS_le
14856 + (pfindDataUnix->FileName,
14857 + (wchar_t *)
14858 + pfindDataUnix->FileName,
14859 + MAX_PATHCONF,
14860 + cifs_sb->local_nls);
14861 + else
14862 + qstring.len =
14863 + strnlen(pfindDataUnix->
14864 + FileName,
14865 + MAX_PATHCONF);
14866 + if (((qstring.len != 1)
14867 + || (pfindDataUnix->
14868 + FileName[0] != '.'))
14869 + && ((qstring.len != 2)
14870 + || (pfindDataUnix->
14871 + FileName[0] != '.')
14872 + || (pfindDataUnix->
14873 + FileName[1] != '.'))) {
14874 + if(cifs_filldir_unix(&qstring,
14875 + pfindDataUnix,
14876 + file,
14877 + filldir,
14878 + direntry)) {
14879 + /* do not end search if
14880 + kernel not ready to take
14881 + remaining entries yet */
14882 + findParms.EndofSearch = 0;
14883 + reset_resume_key(file, pfindDataUnix->FileName,
14884 + qstring.len,Unicode,cifs_sb->local_nls);
14885 + break;
14886 + }
14887 + file->f_pos++;
14888 + }
14889 + }
14890 + /* works also for Unix ff struct since first field of both */
14891 + pfindData =
14892 + (FILE_DIRECTORY_INFO *) ((char *) pfindData
14893 + + le32_to_cpu(pfindData->NextEntryOffset));
14894 + /* BB also should check to make sure that pointer is not beyond the end of the SMB */
14895 + /* if(pfindData > lastFindData) rc = -EIO; break; */
14896 + } /* end for loop */
14897 + if ((findParms.EndofSearch != 0) && cifsFile) {
14898 + cifsFile->endOfSearch = TRUE;
14899 + if(findParms.SearchCount == 2)
14900 + cifsFile->emptyDir = TRUE;
14901 + }
14902 + } else {
14903 + if (cifsFile)
14904 + cifsFile->endOfSearch = TRUE;
14905 + /* unless parent directory gone do not return error */
14906 + rc = 0;
14907 + }
14908 + break;
14909 + default:
14910 + if (file->private_data == NULL) {
14911 + rc = -EBADF;
14912 + cFYI(1,
14913 + ("Readdir on closed srch, pos = %lld",
14914 + file->f_pos));
14915 + } else {
14916 + cifsFile = (struct cifsFileInfo *) file->private_data;
14917 + if (cifsFile->endOfSearch) {
14918 + rc = 0;
14919 + cFYI(1, ("End of search "));
14920 + break;
14921 + }
14922 + searchHandle = cifsFile->netfid;
14923 + rc = CIFSFindNext(xid, pTcon, pfindData,
14924 + &findNextParms, searchHandle,
14925 + cifsFile->search_resume_name,
14926 + cifsFile->resume_name_length,
14927 + cifsFile->resume_key,
14928 + &Unicode, &UnixSearch);
14929 + cFYI(1,("Count: %d End: %d ",
14930 + findNextParms.SearchCount,
14931 + findNextParms.EndofSearch));
14932 + if ((rc == 0) && (findNextParms.SearchCount != 0)) {
14933 + /* BB save off resume key, key name and name length */
14934 + lastFindData =
14935 + (FILE_DIRECTORY_INFO *) ((char *) pfindData
14936 + + findNextParms.LastNameOffset);
14937 + if((char *)lastFindData > (char *)pfindData + bufsize) {
14938 + cFYI(1,("last search entry past end of packet"));
14939 + rc = -EIO;
14940 + break;
14941 + }
14942 + /* Offset of resume key same for levels 257 and 514 */
14943 + cifsFile->resume_key = lastFindData->FileIndex;
14944 +
14945 + if(UnixSearch == FALSE) {
14946 + cifsFile->resume_name_length =
14947 + le32_to_cpu(lastFindData->FileNameLength);
14948 + if(cifsFile->resume_name_length > bufsize - 64) {
14949 + cFYI(1,("Illegal resume file name length %d",
14950 + cifsFile->resume_name_length));
14951 + rc = -ENOMEM;
14952 + break;
14953 + }
14954 + /* Free the memory allocated by previous findfirst
14955 + or findnext call - we can not reuse the memory since
14956 + the resume name may not be same string length */
14957 + if(cifsFile->search_resume_name)
14958 + kfree(cifsFile->search_resume_name);
14959 + cifsFile->search_resume_name =
14960 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14961 + cFYI(1,("Last file: %s with name %d bytes long",
14962 + lastFindData->FileName,
14963 + cifsFile->resume_name_length));
14964 + memcpy(cifsFile->search_resume_name,
14965 + lastFindData->FileName,
14966 + cifsFile->resume_name_length);
14967 + } else {
14968 + pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
14969 + if (Unicode == TRUE) {
14970 + for(i=0;(pfindDataUnix->FileName[i]
14971 + | pfindDataUnix->FileName[i+1]);
14972 + i+=2) {
14973 + if(i > bufsize-64)
14974 + break;
14975 + }
14976 + cifsFile->resume_name_length = i + 2;
14977 + } else {
14978 + cifsFile->resume_name_length =
14979 + strnlen(pfindDataUnix->
14980 + FileName,
14981 + MAX_PATHCONF);
14982 + }
14983 + if(cifsFile->resume_name_length > bufsize - 64) {
14984 + cFYI(1,("Illegal resume file name length %d",
14985 + cifsFile->resume_name_length));
14986 + rc = -ENOMEM;
14987 + break;
14988 + }
14989 + /* Free the memory allocated by previous findfirst
14990 + or findnext call - we can not reuse the memory since
14991 + the resume name may not be same string length */
14992 + if(cifsFile->search_resume_name)
14993 + kfree(cifsFile->search_resume_name);
14994 + cifsFile->search_resume_name =
14995 + kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
14996 + cFYI(1,("fnext last file: %s with name %d bytes long",
14997 + pfindDataUnix->FileName,
14998 + cifsFile->resume_name_length));
14999 + memcpy(cifsFile->search_resume_name,
15000 + pfindDataUnix->FileName,
15001 + cifsFile->resume_name_length);
15002 + }
15003 +
15004 + for (i = 0; i < findNextParms.SearchCount; i++) {
15005 + pfindData->FileNameLength =
15006 + le32_to_cpu(pfindData->
15007 + FileNameLength);
15008 + if (UnixSearch == FALSE) {
15009 + if (Unicode == TRUE)
15010 + pfindData->FileNameLength =
15011 + cifs_strfromUCS_le
15012 + (pfindData->FileName,
15013 + (wchar_t *)
15014 + pfindData->FileName,
15015 + (pfindData->FileNameLength)/ 2,
15016 + cifs_sb->local_nls);
15017 + qstring.len =
15018 + pfindData->FileNameLength;
15019 + if (((qstring.len != 1)
15020 + || (pfindData->FileName[0] != '.'))
15021 + && ((qstring.len != 2)
15022 + || (pfindData->FileName[0] != '.')
15023 + || (pfindData->FileName[1] !=
15024 + '.'))) {
15025 + if(cifs_filldir
15026 + (&qstring,
15027 + pfindData,
15028 + file, filldir,
15029 + direntry)) {
15030 + /* do not end search if
15031 + kernel not ready to take
15032 + remaining entries yet */
15033 + findNextParms.EndofSearch = 0;
15034 + reset_resume_key(file, pfindData->FileName,qstring.len,
15035 + Unicode,cifs_sb->local_nls);
15036 + break;
15037 + }
15038 + file->f_pos++;
15039 + }
15040 + } else { /* UnixSearch */
15041 + pfindDataUnix =
15042 + (FILE_UNIX_INFO *)
15043 + pfindData;
15044 + if (Unicode == TRUE)
15045 + qstring.len =
15046 + cifs_strfromUCS_le
15047 + (pfindDataUnix->FileName,
15048 + (wchar_t *)
15049 + pfindDataUnix->FileName,
15050 + MAX_PATHCONF,
15051 + cifs_sb->local_nls);
15052 + else
15053 + qstring.len =
15054 + strnlen
15055 + (pfindDataUnix->
15056 + FileName,
15057 + MAX_PATHCONF);
15058 + if (((qstring.len != 1)
15059 + || (pfindDataUnix->
15060 + FileName[0] != '.'))
15061 + && ((qstring.len != 2)
15062 + || (pfindDataUnix->
15063 + FileName[0] != '.')
15064 + || (pfindDataUnix->
15065 + FileName[1] !=
15066 + '.'))) {
15067 + if(cifs_filldir_unix
15068 + (&qstring,
15069 + pfindDataUnix,
15070 + file, filldir,
15071 + direntry)) {
15072 + /* do not end search if
15073 + kernel not ready to take
15074 + remaining entries yet */
15075 + findNextParms.EndofSearch = 0;
15076 + reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
15077 + Unicode,cifs_sb->local_nls);
15078 + break;
15079 + }
15080 + file->f_pos++;
15081 + }
15082 + }
15083 + 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 */
15084 + /* BB also should check to make sure that pointer is not beyond the end of the SMB */
15085 + } /* end for loop */
15086 + if (findNextParms.EndofSearch != 0) {
15087 + cifsFile->endOfSearch = TRUE;
15088 + }
15089 + } else {
15090 + cifsFile->endOfSearch = TRUE;
15091 + rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */
15092 + }
15093 + }
15094 + } /* end switch */
15095 + if (data)
15096 + kfree(data);
15097 + if (full_path)
15098 + kfree(full_path);
15099 + FreeXid(xid);
15100 +
15101 + return rc;
15102 +}
15103 +int cifs_prepare_write(struct file *file, struct page *page,
15104 + unsigned from, unsigned to)
15105 +{
15106 + int rc = 0;
15107 + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
15108 + cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
15109 + if (!Page_Uptodate(page)) {
15110 + /* if (to - from != PAGE_CACHE_SIZE) {
15111 + void *kaddr = kmap_atomic(page, KM_USER0);
15112 + memset(kaddr, 0, from);
15113 + memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
15114 + flush_dcache_page(page);
15115 + kunmap_atomic(kaddr, KM_USER0);
15116 + } */
15117 + /* If we are writing a full page it will be up to date,
15118 + no need to read from the server */
15119 + if((to==PAGE_CACHE_SIZE) && (from == 0))
15120 + SetPageUptodate(page);
15121 +
15122 + /* might as well read a page, it is fast enough */
15123 + if((file->f_flags & O_ACCMODE) != O_WRONLY) {
15124 + rc = cifs_readpage_worker(file,page,&offset);
15125 + } else {
15126 + /* should we try using another
15127 + file handle if there is one - how would we lock it
15128 + to prevent close of that handle racing with this read? */
15129 + /* In any case this will be written out by commit_write */
15130 + }
15131 + }
15132 +
15133 + /* BB should we pass any errors back? e.g. if we do not have read access to the file */
15134 + return 0;
15135 +}
15136 +
15137 +
15138 +struct address_space_operations cifs_addr_ops = {
15139 + .readpage = cifs_readpage,
15140 +/* .readpages = cifs_readpages, */
15141 + .writepage = cifs_writepage,
15142 + .prepare_write = cifs_prepare_write,
15143 + .commit_write = cifs_commit_write,
15144 + .sync_page = cifs_sync_page,
15145 + /*.direct_IO = */
15146 +};
15147 diff -urN linux-2.4.29.old/fs/cifs/inode.c linux-2.4.29/fs/cifs/inode.c
15148 --- linux-2.4.29.old/fs/cifs/inode.c 1970-01-01 01:00:00.000000000 +0100
15149 +++ linux-2.4.29/fs/cifs/inode.c 2004-07-14 00:25:05.000000000 +0200
15150 @@ -0,0 +1,1079 @@
15151 +/*
15152 + * fs/cifs/inode.c
15153 + *
15154 + * Copyright (C) International Business Machines Corp., 2002,2003
15155 + * Author(s): Steve French (sfrench@us.ibm.com)
15156 + *
15157 + * This library is free software; you can redistribute it and/or modify
15158 + * it under the terms of the GNU Lesser General Public License as published
15159 + * by the Free Software Foundation; either version 2.1 of the License, or
15160 + * (at your option) any later version.
15161 + *
15162 + * This library is distributed in the hope that it will be useful,
15163 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15164 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15165 + * the GNU Lesser General Public License for more details.
15166 + *
15167 + * You should have received a copy of the GNU Lesser General Public License
15168 + * along with this library; if not, write to the Free Software
15169 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15170 + */
15171 +#include <linux/fs.h>
15172 +#include <linux/stat.h>
15173 +#include <linux/pagemap.h>
15174 +#include <linux/version.h>
15175 +#include <asm/div64.h>
15176 +#include "cifsfs.h"
15177 +#include "cifspdu.h"
15178 +#include "cifsglob.h"
15179 +#include "cifsproto.h"
15180 +#include "cifs_debug.h"
15181 +#include "cifs_fs_sb.h"
15182 +
15183 +extern int is_size_safe_to_change(struct cifsInodeInfo *);
15184 +
15185 +struct inode * get_cifs_inode(struct super_block * sb)
15186 +{
15187 + struct inode * newinode;
15188 + newinode = new_inode(sb);
15189 + cFYI(1,("got new inode %p",newinode));
15190 + if(newinode) {
15191 + struct cifsInodeInfo * cifsInfo = CIFS_I(newinode);
15192 + cifsInfo->clientCanCacheRead = FALSE;
15193 + cifsInfo->clientCanCacheAll = FALSE;
15194 + INIT_LIST_HEAD(&cifsInfo->openFileList);
15195 + cifsInfo->cifsAttrs = 0x20; /* default */
15196 + newinode->i_blksize = CIFS_MAX_MSGSIZE;
15197 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
15198 + newinode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
15199 +#endif
15200 + atomic_set(&cifsInfo->inUse, 0);
15201 + cifsInfo->time = 0;
15202 + insert_inode_hash(newinode);
15203 + }
15204 + return newinode;
15205 +
15206 +}
15207 +
15208 +int
15209 +cifs_get_inode_info_unix(struct inode **pinode,
15210 + const unsigned char *search_path,
15211 + struct super_block *sb,int xid)
15212 +{
15213 + int rc = 0;
15214 + FILE_UNIX_BASIC_INFO findData;
15215 + struct cifsTconInfo *pTcon;
15216 + struct inode *inode;
15217 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
15218 + char *tmp_path;
15219 +
15220 + pTcon = cifs_sb->tcon;
15221 + cFYI(1, (" Getting info on %s ", search_path));
15222 + /* we could have done a find first instead but this returns more info */
15223 + rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
15224 + cifs_sb->local_nls);
15225 + /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
15226 + if (rc) {
15227 + if (rc == -EREMOTE) {
15228 + tmp_path =
15229 + kmalloc(strnlen
15230 + (pTcon->treeName,
15231 + MAX_TREE_SIZE + 1) +
15232 + strnlen(search_path, MAX_PATHCONF) + 1,
15233 + GFP_KERNEL);
15234 + if (tmp_path == NULL) {
15235 + return -ENOMEM;
15236 + }
15237 + /* have to skip first of the double backslash of UNC name */
15238 + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
15239 + strncat(tmp_path, search_path, MAX_PATHCONF);
15240 + rc = connect_to_dfs_path(xid, pTcon->ses,
15241 + /* treename + */ tmp_path,
15242 + cifs_sb->local_nls);
15243 + kfree(tmp_path);
15244 +
15245 + /* BB fix up inode etc. */
15246 + } else if (rc) {
15247 + return rc;
15248 + }
15249 +
15250 + } else {
15251 + struct cifsInodeInfo *cifsInfo;
15252 +
15253 + /* get new inode */
15254 + if (*pinode == NULL) {
15255 + *pinode = get_cifs_inode(sb);
15256 + }
15257 + if(*pinode == NULL) {
15258 + return -ENOMEM;
15259 + }
15260 +
15261 + inode = *pinode;
15262 + cifsInfo = CIFS_I(inode);
15263 +
15264 + cFYI(1, (" Old time %ld ", cifsInfo->time));
15265 + cifsInfo->time = jiffies;
15266 + cFYI(1, (" New time %ld ", cifsInfo->time));
15267 + atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
15268 +
15269 + inode->i_atime =
15270 + cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
15271 + inode->i_mtime =
15272 + cifs_NTtimeToUnix(le64_to_cpu
15273 + (findData.LastModificationTime));
15274 + inode->i_ctime =
15275 + cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
15276 + inode->i_mode = le64_to_cpu(findData.Permissions);
15277 + findData.Type = le32_to_cpu(findData.Type);
15278 + if (findData.Type == UNIX_FILE) {
15279 + inode->i_mode |= S_IFREG;
15280 + } else if (findData.Type == UNIX_SYMLINK) {
15281 + inode->i_mode |= S_IFLNK;
15282 + } else if (findData.Type == UNIX_DIR) {
15283 + inode->i_mode |= S_IFDIR;
15284 + } else if (findData.Type == UNIX_CHARDEV) {
15285 + inode->i_mode |= S_IFCHR;
15286 + inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
15287 + le64_to_cpu(findData.DevMinor) & MINORMASK);
15288 + } else if (findData.Type == UNIX_BLOCKDEV) {
15289 + inode->i_mode |= S_IFBLK;
15290 + inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
15291 + le64_to_cpu(findData.DevMinor) & MINORMASK);
15292 + } else if (findData.Type == UNIX_FIFO) {
15293 + inode->i_mode |= S_IFIFO;
15294 + } else if (findData.Type == UNIX_SOCKET) {
15295 + inode->i_mode |= S_IFSOCK;
15296 + }
15297 + inode->i_uid = le64_to_cpu(findData.Uid);
15298 + inode->i_gid = le64_to_cpu(findData.Gid);
15299 + inode->i_nlink = le64_to_cpu(findData.Nlinks);
15300 + findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
15301 + findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
15302 +
15303 + if(is_size_safe_to_change(cifsInfo)) {
15304 + /* can not safely change the file size here if the
15305 + client is writing to it due to potential races */
15306 + inode->i_size = findData.EndOfFile;
15307 +/* blksize needs to be multiple of two. So safer to default to blksize
15308 + and blkbits set in superblock so 2**blkbits and blksize will match */
15309 +/* inode->i_blksize =
15310 + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
15311 +
15312 + /* This seems incredibly stupid but it turns out that
15313 + i_blocks is not related to (i_size / i_blksize), instead a
15314 + size of 512 is required to be used for calculating num blocks */
15315 +
15316 +
15317 +/* inode->i_blocks =
15318 + (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
15319 +
15320 + /* 512 bytes (2**9) is the fake blocksize that must be used */
15321 + /* for this calculation */
15322 + inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
15323 + }
15324 +
15325 + if (findData.NumOfBytes < findData.EndOfFile)
15326 + cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
15327 + cFYI(1,
15328 + ("Size %ld and blocks %ld ",
15329 + (unsigned long) inode->i_size, inode->i_blocks));
15330 + if (S_ISREG(inode->i_mode)) {
15331 + cFYI(1, (" File inode "));
15332 + inode->i_op = &cifs_file_inode_ops;
15333 + inode->i_fop = &cifs_file_ops;
15334 + inode->i_data.a_ops = &cifs_addr_ops;
15335 + } else if (S_ISDIR(inode->i_mode)) {
15336 + cFYI(1, (" Directory inode"));
15337 + inode->i_op = &cifs_dir_inode_ops;
15338 + inode->i_fop = &cifs_dir_ops;
15339 + } else if (S_ISLNK(inode->i_mode)) {
15340 + cFYI(1, (" Symbolic Link inode "));
15341 + inode->i_op = &cifs_symlink_inode_ops;
15342 +/* tmp_inode->i_fop = *//* do not need to set to anything */
15343 + } else {
15344 + cFYI(1, (" Init special inode "));
15345 + init_special_inode(inode, inode->i_mode,
15346 + kdev_t_to_nr(inode->i_rdev));
15347 + }
15348 + }
15349 + return rc;
15350 +}
15351 +
15352 +int
15353 +cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
15354 + FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
15355 +{
15356 + int rc = 0;
15357 + struct cifsTconInfo *pTcon;
15358 + struct inode *inode;
15359 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
15360 + char *tmp_path;
15361 + char *buf = NULL;
15362 +
15363 + pTcon = cifs_sb->tcon;
15364 + cFYI(1,("Getting info on %s ", search_path));
15365 +
15366 + if((pfindData == NULL) && (*pinode != NULL)) {
15367 + if(CIFS_I(*pinode)->clientCanCacheRead) {
15368 + cFYI(1,("No need to revalidate inode sizes on cached file "));
15369 + return rc;
15370 + }
15371 + }
15372 +
15373 + /* if file info not passed in then get it from server */
15374 + if(pfindData == NULL) {
15375 + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
15376 + pfindData = (FILE_ALL_INFO *)buf;
15377 + /* could do find first instead but this returns more info */
15378 + rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
15379 + cifs_sb->local_nls);
15380 + }
15381 + /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
15382 + if (rc) {
15383 + if (rc == -EREMOTE) {
15384 + tmp_path =
15385 + kmalloc(strnlen
15386 + (pTcon->treeName,
15387 + MAX_TREE_SIZE + 1) +
15388 + strnlen(search_path, MAX_PATHCONF) + 1,
15389 + GFP_KERNEL);
15390 + if (tmp_path == NULL) {
15391 + if(buf)
15392 + kfree(buf);
15393 + return -ENOMEM;
15394 + }
15395 +
15396 + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
15397 + strncat(tmp_path, search_path, MAX_PATHCONF);
15398 + rc = connect_to_dfs_path(xid, pTcon->ses,
15399 + /* treename + */ tmp_path,
15400 + cifs_sb->local_nls);
15401 + kfree(tmp_path);
15402 + /* BB fix up inode etc. */
15403 + } else if (rc) {
15404 + if(buf)
15405 + kfree(buf);
15406 + return rc;
15407 + }
15408 + } else {
15409 + struct cifsInodeInfo *cifsInfo;
15410 +
15411 + /* get new inode */
15412 + if (*pinode == NULL) {
15413 + *pinode = get_cifs_inode(sb);
15414 + }
15415 + if(*pinode == NULL)
15416 + return -ENOMEM;
15417 + inode = *pinode;
15418 + cifsInfo = CIFS_I(inode);
15419 + pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
15420 + cifsInfo->cifsAttrs = pfindData->Attributes;
15421 + cFYI(1, (" Old time %ld ", cifsInfo->time));
15422 + cifsInfo->time = jiffies;
15423 + cFYI(1, (" New time %ld ", cifsInfo->time));
15424 +
15425 +/* blksize needs to be multiple of two. So safer to default to blksize
15426 + and blkbits set in superblock so 2**blkbits and blksize will match */
15427 +/* inode->i_blksize =
15428 + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
15429 +
15430 + /* Linux can not store file creation time unfortunately so we ignore it */
15431 + inode->i_atime =
15432 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
15433 + inode->i_mtime =
15434 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
15435 + inode->i_ctime =
15436 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
15437 + cFYI(0,
15438 + (" Attributes came in as 0x%x ", pfindData->Attributes));
15439 +
15440 + /* set default mode. will override for dirs below */
15441 + if(atomic_read(&cifsInfo->inUse) == 0)
15442 + /* new inode, can safely set these fields */
15443 + inode->i_mode = cifs_sb->mnt_file_mode;
15444 +
15445 + if (pfindData->Attributes & ATTR_REPARSE) {
15446 + /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
15447 + inode->i_mode |= S_IFLNK;
15448 + } else if (pfindData->Attributes & ATTR_DIRECTORY) {
15449 + /* override default perms since we do not do byte range locking on dirs */
15450 + inode->i_mode = cifs_sb->mnt_dir_mode;
15451 + inode->i_mode |= S_IFDIR;
15452 + } else {
15453 + inode->i_mode |= S_IFREG;
15454 + /* treat the dos attribute of read-only as read-only mode e.g. 555 */
15455 + if(cifsInfo->cifsAttrs & ATTR_READONLY)
15456 + inode->i_mode &= ~(S_IWUGO);
15457 + /* BB add code here - validate if device or weird share or device type? */
15458 + }
15459 + if(is_size_safe_to_change(cifsInfo)) {
15460 + /* can not safely change the file size here if the
15461 + client is writing to it due to potential races */
15462 + inode->i_size = le64_to_cpu(pfindData->EndOfFile);
15463 +
15464 + /* 512 bytes (2**9) is the fake blocksize that must be used */
15465 + /* for this calculation */
15466 + inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
15467 + >> 9;
15468 + }
15469 + pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
15470 +
15471 + cFYI(1,
15472 + (" Size %ld and blocks %ld ",
15473 + (unsigned long) inode->i_size, inode->i_blocks));
15474 + inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
15475 +
15476 + /* BB fill in uid and gid here? with help from winbind?
15477 + or retrieve from NTFS stream extended attribute */
15478 + if(atomic_read(&cifsInfo->inUse) == 0) {
15479 + inode->i_uid = cifs_sb->mnt_uid;
15480 + inode->i_gid = cifs_sb->mnt_gid;
15481 + /* set so we do not keep refreshing these fields with
15482 + bad data after user has changed them in memory */
15483 + atomic_set(&cifsInfo->inUse,1);
15484 + }
15485 +
15486 + if (S_ISREG(inode->i_mode)) {
15487 + cFYI(1, (" File inode "));
15488 + inode->i_op = &cifs_file_inode_ops;
15489 + inode->i_fop = &cifs_file_ops;
15490 + inode->i_data.a_ops = &cifs_addr_ops;
15491 + } else if (S_ISDIR(inode->i_mode)) {
15492 + cFYI(1, (" Directory inode "));
15493 + inode->i_op = &cifs_dir_inode_ops;
15494 + inode->i_fop = &cifs_dir_ops;
15495 + } else if (S_ISLNK(inode->i_mode)) {
15496 + cFYI(1, (" Symbolic Link inode "));
15497 + inode->i_op = &cifs_symlink_inode_ops;
15498 + } else {
15499 + init_special_inode(inode, inode->i_mode,
15500 + kdev_t_to_nr(inode->i_rdev));
15501 + }
15502 + }
15503 + if(buf)
15504 + kfree(buf);
15505 + return rc;
15506 +}
15507 +
15508 +void
15509 +cifs_read_inode(struct inode *inode)
15510 +{ /* gets root inode */
15511 + int xid;
15512 + struct cifs_sb_info *cifs_sb;
15513 + struct cifsInodeInfo *cifs_inode;
15514 +
15515 + cifs_sb = CIFS_SB(inode->i_sb);
15516 + xid = GetXid();
15517 +
15518 + cifs_inode = CIFS_I(inode);
15519 + cifs_inode->cifsAttrs = ATTR_DIRECTORY;
15520 + atomic_set(&cifs_inode->inUse, 0);
15521 + cifs_inode->time = 0;
15522 + inode->i_blksize = CIFS_MAX_MSGSIZE;
15523 + inode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
15524 +
15525 + INIT_LIST_HEAD(&cifs_inode->openFileList);
15526 +
15527 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
15528 + cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
15529 + else
15530 + cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
15531 + /* can not call macro FreeXid here since in a void func */
15532 + _FreeXid(xid);
15533 +}
15534 +
15535 +int
15536 +cifs_unlink(struct inode *inode, struct dentry *direntry)
15537 +{
15538 + int rc = 0;
15539 + int xid;
15540 + struct cifs_sb_info *cifs_sb;
15541 + struct cifsTconInfo *pTcon;
15542 + char *full_path = NULL;
15543 + struct cifsInodeInfo *cifsInode;
15544 + FILE_BASIC_INFO * pinfo_buf;
15545 +
15546 + cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
15547 +
15548 + xid = GetXid();
15549 +
15550 + cifs_sb = CIFS_SB(inode->i_sb);
15551 + pTcon = cifs_sb->tcon;
15552 +
15553 +/* Unlink can be called from rename so we can not grab
15554 + the sem here since we deadlock otherwise */
15555 +/* down(&direntry->d_sb->s_vfs_rename_sem);*/
15556 + full_path = build_path_from_dentry(direntry);
15557 +/* up(&direntry->d_sb->s_vfs_rename_sem);*/
15558 + if(full_path == NULL) {
15559 + FreeXid(xid);
15560 + return -ENOMEM;
15561 + }
15562 + rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
15563 +
15564 + if (!rc) {
15565 + direntry->d_inode->i_nlink--;
15566 + } else if (rc == -ENOENT) {
15567 + d_drop(direntry);
15568 + } else if (rc == -ETXTBSY) {
15569 + int oplock = FALSE;
15570 + __u16 netfid;
15571 +
15572 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
15573 + CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
15574 + &netfid, &oplock, NULL, cifs_sb->local_nls);
15575 + if(rc==0) {
15576 + CIFSSMBRenameOpenFile(xid,pTcon,netfid,
15577 + NULL, cifs_sb->local_nls);
15578 + CIFSSMBClose(xid, pTcon, netfid);
15579 + direntry->d_inode->i_nlink--;
15580 + }
15581 + } else if (rc == -EACCES) {
15582 + /* try only if r/o attribute set in local lookup data? */
15583 + pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
15584 + if(pinfo_buf) {
15585 + memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
15586 + /* ATTRS set to normal clears r/o bit */
15587 + pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
15588 + rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
15589 + cifs_sb->local_nls);
15590 + kfree(pinfo_buf);
15591 + }
15592 + if(rc==0) {
15593 + rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
15594 + if (!rc) {
15595 + direntry->d_inode->i_nlink--;
15596 + } else if (rc == -ETXTBSY) {
15597 + int oplock = FALSE;
15598 + __u16 netfid;
15599 +
15600 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
15601 + CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
15602 + &netfid, &oplock, NULL, cifs_sb->local_nls);
15603 + if(rc==0) {
15604 + CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
15605 + CIFSSMBClose(xid, pTcon, netfid);
15606 + direntry->d_inode->i_nlink--;
15607 + }
15608 + /* BB if rc = -ETXTBUSY goto the rename logic BB */
15609 + }
15610 + }
15611 + }
15612 + cifsInode = CIFS_I(direntry->d_inode);
15613 + cifsInode->time = 0; /* will force revalidate to get info when needed */
15614 + direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
15615 + CURRENT_TIME;
15616 + cifsInode = CIFS_I(inode);
15617 + cifsInode->time = 0; /* force revalidate of dir as well */
15618 +
15619 + if (full_path)
15620 + kfree(full_path);
15621 + FreeXid(xid);
15622 + return rc;
15623 +}
15624 +
15625 +int
15626 +cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
15627 +{
15628 + int rc = 0;
15629 + int xid;
15630 + struct cifs_sb_info *cifs_sb;
15631 + struct cifsTconInfo *pTcon;
15632 + char *full_path = NULL;
15633 + struct inode *newinode = NULL;
15634 +
15635 + cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
15636 +
15637 + xid = GetXid();
15638 +
15639 + cifs_sb = CIFS_SB(inode->i_sb);
15640 + pTcon = cifs_sb->tcon;
15641 +
15642 + down(&inode->i_sb->s_vfs_rename_sem);
15643 + full_path = build_path_from_dentry(direntry);
15644 + up(&inode->i_sb->s_vfs_rename_sem);
15645 + if(full_path == NULL) {
15646 + FreeXid(xid);
15647 + return -ENOMEM;
15648 + }
15649 + /* BB add setting the equivalent of mode via CreateX w/ACLs */
15650 + rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
15651 + if (rc) {
15652 + cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
15653 + d_drop(direntry);
15654 + } else {
15655 + inode->i_nlink++;
15656 + if (pTcon->ses->capabilities & CAP_UNIX)
15657 + rc = cifs_get_inode_info_unix(&newinode, full_path,
15658 + inode->i_sb,xid);
15659 + else
15660 + rc = cifs_get_inode_info(&newinode, full_path,NULL,
15661 + inode->i_sb,xid);
15662 +
15663 + direntry->d_op = &cifs_dentry_ops;
15664 + d_instantiate(direntry, newinode);
15665 + if(direntry->d_inode)
15666 + direntry->d_inode->i_nlink = 2;
15667 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
15668 + CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
15669 + (__u64)-1,
15670 + (__u64)-1,
15671 + 0 /* dev_t */,
15672 + cifs_sb->local_nls);
15673 + else { /* BB to be implemented via Windows secrty descriptors*/
15674 + /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
15675 + }
15676 + }
15677 + if (full_path)
15678 + kfree(full_path);
15679 + FreeXid(xid);
15680 +
15681 + return rc;
15682 +}
15683 +
15684 +int
15685 +cifs_rmdir(struct inode *inode, struct dentry *direntry)
15686 +{
15687 + int rc = 0;
15688 + int xid;
15689 + struct cifs_sb_info *cifs_sb;
15690 + struct cifsTconInfo *pTcon;
15691 + char *full_path = NULL;
15692 + struct cifsInodeInfo *cifsInode;
15693 +
15694 + cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
15695 +
15696 + xid = GetXid();
15697 +
15698 + cifs_sb = CIFS_SB(inode->i_sb);
15699 + pTcon = cifs_sb->tcon;
15700 +
15701 + down(&inode->i_sb->s_vfs_rename_sem);
15702 + full_path = build_path_from_dentry(direntry);
15703 + up(&inode->i_sb->s_vfs_rename_sem);
15704 + if(full_path == NULL) {
15705 + FreeXid(xid);
15706 + return -ENOMEM;
15707 + }
15708 +
15709 + rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
15710 +
15711 + if (!rc) {
15712 + inode->i_nlink--;
15713 + direntry->d_inode->i_size = 0;
15714 + direntry->d_inode->i_nlink = 0;
15715 + }
15716 +
15717 + cifsInode = CIFS_I(direntry->d_inode);
15718 + cifsInode->time = 0; /* force revalidate to go get info when needed */
15719 + direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
15720 + CURRENT_TIME;
15721 +
15722 + if (full_path)
15723 + kfree(full_path);
15724 + FreeXid(xid);
15725 + return rc;
15726 +}
15727 +
15728 +int
15729 +cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
15730 + struct inode *target_inode, struct dentry *target_direntry)
15731 +{
15732 + char *fromName;
15733 + char *toName;
15734 + struct cifs_sb_info *cifs_sb_source;
15735 + struct cifs_sb_info *cifs_sb_target;
15736 + struct cifsTconInfo *pTcon;
15737 + int xid;
15738 + int rc = 0;
15739 +
15740 + xid = GetXid();
15741 +
15742 + cifs_sb_target = CIFS_SB(target_inode->i_sb);
15743 + cifs_sb_source = CIFS_SB(source_inode->i_sb);
15744 + pTcon = cifs_sb_source->tcon;
15745 +
15746 + if (pTcon != cifs_sb_target->tcon) {
15747 + FreeXid(xid);
15748 + return -EXDEV; /* BB actually could be allowed if same server, but
15749 + different share. Might eventually add support for this */
15750 + }
15751 +
15752 + /* we already have the rename sem so we do not need
15753 + to grab it again here to protect the path integrity */
15754 + fromName = build_path_from_dentry(source_direntry);
15755 + toName = build_path_from_dentry(target_direntry);
15756 + if((fromName == NULL) || (toName == NULL)) {
15757 + rc = -ENOMEM;
15758 + goto cifs_rename_exit;
15759 + }
15760 +
15761 + rc = CIFSSMBRename(xid, pTcon, fromName, toName,
15762 + cifs_sb_source->local_nls);
15763 + if(rc == -EEXIST) {
15764 + /* check if they are the same file
15765 + because rename of hardlinked files is a noop */
15766 + FILE_UNIX_BASIC_INFO * info_buf_source;
15767 + FILE_UNIX_BASIC_INFO * info_buf_target;
15768 +
15769 + info_buf_source =
15770 + kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
15771 + if(info_buf_source != NULL) {
15772 + info_buf_target = info_buf_source+1;
15773 + rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
15774 + info_buf_source, cifs_sb_source->local_nls);
15775 + if(rc == 0) {
15776 + rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
15777 + info_buf_target,
15778 + cifs_sb_target->local_nls);
15779 + }
15780 + if((rc == 0) &&
15781 + (info_buf_source->UniqueId ==
15782 + info_buf_target->UniqueId)) {
15783 + /* do not rename since the files are hardlinked
15784 + which is a noop */
15785 + } else {
15786 + /* we either can not tell the files are hardlinked
15787 + (as with Windows servers) or files are not hardlinked
15788 + so delete the target manually before renaming to
15789 + follow POSIX rather than Windows semantics */
15790 + cifs_unlink(target_inode, target_direntry);
15791 + rc = CIFSSMBRename(xid, pTcon, fromName, toName,
15792 + cifs_sb_source->local_nls);
15793 + }
15794 + kfree(info_buf_source);
15795 + } /* if we can not get memory just leave rc as EEXIST */
15796 + }
15797 +
15798 + if((rc == -EIO)||(rc == -EEXIST)) {
15799 + int oplock = FALSE;
15800 + __u16 netfid;
15801 +
15802 + rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
15803 + CREATE_NOT_DIR,
15804 + &netfid, &oplock, NULL, cifs_sb_source->local_nls);
15805 + if(rc==0) {
15806 + CIFSSMBRenameOpenFile(xid,pTcon,netfid,
15807 + toName, cifs_sb_source->local_nls);
15808 + CIFSSMBClose(xid, pTcon, netfid);
15809 + }
15810 + }
15811 +
15812 +cifs_rename_exit:
15813 + if (fromName)
15814 + kfree(fromName);
15815 + if (toName)
15816 + kfree(toName);
15817 +
15818 + FreeXid(xid);
15819 + return rc;
15820 +}
15821 +
15822 +int
15823 +cifs_revalidate(struct dentry *direntry)
15824 +{
15825 + int xid;
15826 + int rc = 0;
15827 + char *full_path;
15828 + struct cifs_sb_info *cifs_sb;
15829 + struct cifsInodeInfo *cifsInode;
15830 + loff_t local_size;
15831 + time_t local_mtime;
15832 + int invalidate_inode = FALSE;
15833 +
15834 + if(direntry->d_inode == NULL)
15835 + return -ENOENT;
15836 +
15837 + cifsInode = CIFS_I(direntry->d_inode);
15838 +
15839 + if(cifsInode == NULL)
15840 + return -ENOENT;
15841 +
15842 + /* no sense revalidating inode info on file that no one can write */
15843 + if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
15844 + return rc;
15845 +
15846 + xid = GetXid();
15847 +
15848 + cifs_sb = CIFS_SB(direntry->d_sb);
15849 +
15850 + /* can not safely grab the rename sem here if
15851 + rename calls revalidate since that would deadlock */
15852 + full_path = build_path_from_dentry(direntry);
15853 + if(full_path == NULL) {
15854 + FreeXid(xid);
15855 + return -ENOMEM;
15856 + }
15857 + cFYI(1,
15858 + ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
15859 + full_path, direntry->d_inode,
15860 + direntry->d_inode->i_count.counter, direntry,
15861 + direntry->d_time, jiffies));
15862 +
15863 + if (cifsInode->time == 0){
15864 + /* was set to zero previously to force revalidate */
15865 + } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
15866 + if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
15867 + (direntry->d_inode->i_nlink == 1)) {
15868 + if (full_path)
15869 + kfree(full_path);
15870 + FreeXid(xid);
15871 + return rc;
15872 + } else {
15873 + cFYI(1,("Have to revalidate file due to hardlinks"));
15874 + }
15875 + }
15876 +
15877 + /* save mtime and size */
15878 + local_mtime = direntry->d_inode->i_mtime;
15879 + local_size = direntry->d_inode->i_size;
15880 +
15881 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
15882 + rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
15883 + direntry->d_sb,xid);
15884 + if(rc) {
15885 + cFYI(1,("error on getting revalidate info %d",rc));
15886 +/* if(rc != -ENOENT)
15887 + rc = 0; */ /* BB should we cache info on certain errors? */
15888 + }
15889 + } else {
15890 + rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
15891 + direntry->d_sb,xid);
15892 + if(rc) {
15893 + cFYI(1,("error on getting revalidate info %d",rc));
15894 +/* if(rc != -ENOENT)
15895 + rc = 0; */ /* BB should we cache info on certain errors? */
15896 + }
15897 + }
15898 + /* should we remap certain errors, access denied?, to zero */
15899 +
15900 + /* if not oplocked, we invalidate inode pages if mtime
15901 + or file size had changed on server */
15902 +
15903 + if((local_mtime == direntry->d_inode->i_mtime) &&
15904 + (local_size == direntry->d_inode->i_size)) {
15905 + cFYI(1,("cifs_revalidate - inode unchanged"));
15906 + } else {
15907 + /* file may have changed on server */
15908 + if(cifsInode->clientCanCacheRead) {
15909 + /* no need to invalidate inode pages since we were
15910 + the only ones who could have modified the file and
15911 + the server copy is staler than ours */
15912 + } else {
15913 + invalidate_inode = TRUE;
15914 + }
15915 + }
15916 +
15917 + /* can not grab this sem since kernel filesys locking
15918 + documentation indicates i_sem may be taken by the kernel
15919 + on lookup and rename which could deadlock if we grab
15920 + the i_sem here as well */
15921 +/* down(&direntry->d_inode->i_sem);*/
15922 + /* need to write out dirty pages here */
15923 + if(direntry->d_inode->i_mapping) {
15924 + /* do we need to lock inode until after invalidate completes below? */
15925 + filemap_fdatasync(direntry->d_inode->i_mapping);
15926 + }
15927 + if(invalidate_inode) {
15928 + filemap_fdatawait(direntry->d_inode->i_mapping);
15929 + /* may eventually have to do this for open files too */
15930 + if(list_empty(&(cifsInode->openFileList))) {
15931 + /* Has changed on server - flush read ahead pages */
15932 + cFYI(1,("Invalidating read ahead data on closed file"));
15933 + invalidate_inode_pages(direntry->d_inode);
15934 + }
15935 + }
15936 +/* up(&direntry->d_inode->i_sem);*/
15937 +
15938 + if (full_path)
15939 + kfree(full_path);
15940 + FreeXid(xid);
15941 +
15942 + return rc;
15943 +}
15944 +
15945 +/* int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
15946 +{
15947 + int err = cifs_revalidate(dentry);
15948 + if (!err)
15949 + generic_fillattr(dentry->d_inode, stat);
15950 + return err;
15951 +} */
15952 +
15953 +void
15954 +cifs_truncate_file(struct inode *inode)
15955 +{ /* BB remove - may not need this function after all BB */
15956 + int xid;
15957 + int rc = -EIO;
15958 + int found = FALSE;
15959 + struct cifsFileInfo *open_file = NULL;
15960 + struct cifs_sb_info *cifs_sb;
15961 + struct cifsTconInfo *pTcon;
15962 + struct cifsInodeInfo *cifsInode;
15963 + struct dentry *dirent;
15964 + struct list_head * tmp;
15965 + char *full_path = NULL;
15966 +
15967 + xid = GetXid();
15968 +
15969 + cifs_sb = CIFS_SB(inode->i_sb);
15970 + pTcon = cifs_sb->tcon;
15971 +
15972 + /* To avoid spurious oplock breaks from server, in the case
15973 + of inodes that we already have open, avoid doing path
15974 + based setting of file size if we can do it by handle.
15975 + This keeps our caching token (oplock) and avoids
15976 + timeouts when the local oplock break takes longer to flush
15977 + writebehind data than the SMB timeout for the SetPathInfo
15978 + request would allow */
15979 + read_lock(&GlobalSMBSeslock);
15980 + cifsInode = CIFS_I(inode);
15981 + list_for_each(tmp, &cifsInode->openFileList) {
15982 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
15983 + /* We check if file is open for writing first */
15984 + if((open_file->pfile) && (!open_file->invalidHandle) &&
15985 + ((open_file->pfile->f_flags & O_RDWR) ||
15986 + (open_file->pfile->f_flags & O_WRONLY))) {
15987 + read_unlock(&GlobalSMBSeslock);
15988 + found = TRUE;
15989 + rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
15990 + open_file->netfid,open_file->pid,FALSE);
15991 + if(rc == 0) {
15992 + FreeXid(xid);
15993 + return;
15994 + }
15995 + /* Do not need reopen and retry on EAGAIN since we will
15996 + retry by pathname below */
15997 + if(rc == -EAGAIN)
15998 + rc = -EHOSTDOWN;
15999 +
16000 + break; /* now that we found one valid file handle no
16001 + sense continuing to loop trying others */
16002 + }
16003 + }
16004 + if(found == FALSE)
16005 + read_unlock(&GlobalSMBSeslock);
16006 +
16007 + if (list_empty(&inode->i_dentry)) {
16008 + cERROR(1,
16009 + ("Can not get pathname from empty dentry in inode 0x%p ",
16010 + inode));
16011 + FreeXid(xid);
16012 + return;
16013 + }
16014 +
16015 + dirent = list_entry(inode->i_dentry.next, struct dentry, d_alias);
16016 + if (dirent) {
16017 + full_path = build_path_from_dentry(dirent);
16018 + rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
16019 + cifs_sb->local_nls);
16020 + cFYI(1,(" SetEOF (truncate) rc = %d",rc));
16021 + if (!rc)
16022 + CIFSSMBSetEOF(xid,pTcon,full_path,inode->i_size,TRUE,cifs_sb->local_nls);
16023 + /* allocation size setting seems optional so ignore return code */
16024 + }
16025 + if (full_path)
16026 + kfree(full_path);
16027 + FreeXid(xid);
16028 + return;
16029 +}
16030 +
16031 +static int cifs_truncate_page(struct address_space *mapping, loff_t from)
16032 +{
16033 + unsigned long index = from >> PAGE_CACHE_SHIFT;
16034 + unsigned offset = from & (PAGE_CACHE_SIZE-1);
16035 + struct page *page;
16036 + char *kaddr;
16037 + int rc = 0;
16038 +
16039 + page = grab_cache_page(mapping, index);
16040 + if (!page)
16041 + return -ENOMEM;
16042 +
16043 + kaddr = kmap_atomic(page, KM_USER0);
16044 + memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
16045 + flush_dcache_page(page);
16046 + kunmap_atomic(kaddr, KM_USER0);
16047 + unlock_page(page);
16048 + page_cache_release(page);
16049 + return rc;
16050 +}
16051 +
16052 +int
16053 +cifs_setattr(struct dentry *direntry, struct iattr *attrs)
16054 +{
16055 + int xid;
16056 + struct cifs_sb_info *cifs_sb;
16057 + struct cifsTconInfo *pTcon;
16058 + char *full_path = NULL;
16059 + int rc = -EACCES;
16060 + int found = FALSE;
16061 + struct cifsFileInfo *open_file = NULL;
16062 + FILE_BASIC_INFO time_buf;
16063 + int set_time = FALSE;
16064 + __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
16065 + __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
16066 + __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
16067 + struct cifsInodeInfo *cifsInode;
16068 + struct list_head * tmp;
16069 +
16070 + xid = GetXid();
16071 +
16072 + cFYI(1,
16073 + (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
16074 + direntry->d_name.name, attrs->ia_valid));
16075 + cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
16076 + pTcon = cifs_sb->tcon;
16077 +
16078 + down(&direntry->d_sb->s_vfs_rename_sem);
16079 + full_path = build_path_from_dentry(direntry);
16080 + up(&direntry->d_sb->s_vfs_rename_sem);
16081 + if(full_path == NULL) {
16082 + FreeXid(xid);
16083 + return -ENOMEM;
16084 + }
16085 + cifsInode = CIFS_I(direntry->d_inode);
16086 +
16087 + /* BB check if we need to refresh inode from server now ? BB */
16088 +
16089 + /* need to flush data before changing file size on server */
16090 + filemap_fdatasync(direntry->d_inode->i_mapping);
16091 +
16092 + if (attrs->ia_valid & ATTR_SIZE) {
16093 + read_lock(&GlobalSMBSeslock);
16094 + /* To avoid spurious oplock breaks from server, in the case
16095 + of inodes that we already have open, avoid doing path
16096 + based setting of file size if we can do it by handle.
16097 + This keeps our caching token (oplock) and avoids
16098 + timeouts when the local oplock break takes longer to flush
16099 + writebehind data than the SMB timeout for the SetPathInfo
16100 + request would allow */
16101 + list_for_each(tmp, &cifsInode->openFileList) {
16102 + open_file = list_entry(tmp,struct cifsFileInfo, flist);
16103 + /* We check if file is open for writing first */
16104 + if((open_file->pfile) &&
16105 + ((open_file->pfile->f_flags & O_RDWR) ||
16106 + (open_file->pfile->f_flags & O_WRONLY))) {
16107 + if(open_file->invalidHandle == FALSE) {
16108 + /* we found a valid, writeable network file
16109 + handle to use to try to set the file size */
16110 + __u16 nfid = open_file->netfid;
16111 + __u32 npid = open_file->pid;
16112 + read_unlock(&GlobalSMBSeslock);
16113 + found = TRUE;
16114 + rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
16115 + nfid,npid,FALSE);
16116 + cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
16117 + /* Do not need reopen and retry on EAGAIN since we will
16118 + retry by pathname below */
16119 +
16120 + break; /* now that we found one valid file handle no
16121 + sense continuing to loop trying others */
16122 + }
16123 + }
16124 + }
16125 + if(found == FALSE) {
16126 + read_unlock(&GlobalSMBSeslock);
16127 + }
16128 +
16129 +
16130 + if(rc != 0) {
16131 + /* Set file size by pathname rather than by handle either
16132 + because no valid, writeable file handle for it was found or
16133 + because there was an error setting it by handle */
16134 + rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
16135 + cifs_sb->local_nls);
16136 + cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
16137 + }
16138 +
16139 + /* Server is ok setting allocation size implicitly - no need to call: */
16140 + /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
16141 +
16142 + if (rc == 0) {
16143 + rc = vmtruncate(direntry->d_inode, attrs->ia_size);
16144 + cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
16145 + }
16146 + }
16147 + if (attrs->ia_valid & ATTR_UID) {
16148 + cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
16149 + uid = attrs->ia_uid;
16150 + /* entry->uid = cpu_to_le16(attr->ia_uid); */
16151 + }
16152 + if (attrs->ia_valid & ATTR_GID) {
16153 + cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
16154 + gid = attrs->ia_gid;
16155 + /* entry->gid = cpu_to_le16(attr->ia_gid); */
16156 + }
16157 +
16158 + time_buf.Attributes = 0;
16159 + if (attrs->ia_valid & ATTR_MODE) {
16160 + cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
16161 + mode = attrs->ia_mode;
16162 + /* entry->mode = cpu_to_le16(attr->ia_mode); */
16163 + }
16164 +
16165 + if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16166 + && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
16167 + rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
16168 + 0 /* dev_t */, cifs_sb->local_nls);
16169 + else if (attrs->ia_valid & ATTR_MODE) {
16170 + if((mode & S_IWUGO) == 0) /* not writeable */ {
16171 + if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
16172 + time_buf.Attributes =
16173 + cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
16174 + } else if((mode & S_IWUGO) == S_IWUGO) {
16175 + if(cifsInode->cifsAttrs & ATTR_READONLY)
16176 + time_buf.Attributes =
16177 + cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
16178 + }
16179 + /* BB to be implemented - via Windows security descriptors or streams */
16180 + /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
16181 + }
16182 +
16183 + if (attrs->ia_valid & ATTR_ATIME) {
16184 + set_time = TRUE;
16185 + time_buf.LastAccessTime =
16186 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
16187 + } else
16188 + time_buf.LastAccessTime = 0;
16189 +
16190 + if (attrs->ia_valid & ATTR_MTIME) {
16191 + set_time = TRUE;
16192 + time_buf.LastWriteTime =
16193 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
16194 + } else
16195 + time_buf.LastWriteTime = 0;
16196 +
16197 + if (attrs->ia_valid & ATTR_CTIME) {
16198 + set_time = TRUE;
16199 + time_buf.ChangeTime =
16200 + cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
16201 + } else
16202 + time_buf.ChangeTime = 0;
16203 +
16204 + if (set_time | time_buf.Attributes) {
16205 + /* BB what if setting one attribute fails
16206 + (such as size) but time setting works */
16207 + time_buf.CreationTime = 0; /* do not change */
16208 + /* In the future we should experiment - try setting timestamps
16209 + via Handle (SetFileInfo) instead of by path */
16210 + rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
16211 + cifs_sb->local_nls);
16212 + }
16213 +
16214 + /* do not need local check to inode_check_ok since the server does that */
16215 + if (!rc)
16216 + rc = inode_setattr(direntry->d_inode, attrs);
16217 + if (full_path)
16218 + kfree(full_path);
16219 + FreeXid(xid);
16220 + return rc;
16221 +}
16222 +
16223 +void
16224 +cifs_delete_inode(struct inode *inode)
16225 +{
16226 + cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
16227 + /* may have to add back in if and when safe distributed caching of
16228 + directories added e.g. via FindNotify */
16229 +}
16230 diff -urN linux-2.4.29.old/fs/cifs/link.c linux-2.4.29/fs/cifs/link.c
16231 --- linux-2.4.29.old/fs/cifs/link.c 1970-01-01 01:00:00.000000000 +0100
16232 +++ linux-2.4.29/fs/cifs/link.c 2004-07-14 00:25:05.000000000 +0200
16233 @@ -0,0 +1,328 @@
16234 +/*
16235 + * fs/cifs/link.c
16236 + *
16237 + * Copyright (C) International Business Machines Corp., 2002,2003
16238 + * Author(s): Steve French (sfrench@us.ibm.com)
16239 + *
16240 + * This library is free software; you can redistribute it and/or modify
16241 + * it under the terms of the GNU Lesser General Public License as published
16242 + * by the Free Software Foundation; either version 2.1 of the License, or
16243 + * (at your option) any later version.
16244 + *
16245 + * This library is distributed in the hope that it will be useful,
16246 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16247 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16248 + * the GNU Lesser General Public License for more details.
16249 + *
16250 + * You should have received a copy of the GNU Lesser General Public License
16251 + * along with this library; if not, write to the Free Software
16252 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16253 + */
16254 +#include <linux/fs.h>
16255 +#include <linux/stat.h>
16256 +#include "cifsfs.h"
16257 +#include "cifspdu.h"
16258 +#include "cifsglob.h"
16259 +#include "cifsproto.h"
16260 +#include "cifs_debug.h"
16261 +#include "cifs_fs_sb.h"
16262 +
16263 +int
16264 +cifs_hardlink(struct dentry *old_file, struct inode *inode,
16265 + struct dentry *direntry)
16266 +{
16267 + int rc = -EACCES;
16268 + int xid;
16269 + char *fromName = NULL;
16270 + char *toName = NULL;
16271 + struct cifs_sb_info *cifs_sb_target;
16272 + struct cifsTconInfo *pTcon;
16273 + struct cifsInodeInfo *cifsInode;
16274 +
16275 + xid = GetXid();
16276 +
16277 + cifs_sb_target = CIFS_SB(inode->i_sb);
16278 + pTcon = cifs_sb_target->tcon;
16279 +
16280 +/* No need to check for cross device links since server will do that
16281 + BB note DFS case in future though (when we may have to check) */
16282 +
16283 + down(&inode->i_sb->s_vfs_rename_sem);
16284 + fromName = build_path_from_dentry(old_file);
16285 + toName = build_path_from_dentry(direntry);
16286 + up(&inode->i_sb->s_vfs_rename_sem);
16287 + if((fromName == NULL) || (toName == NULL)) {
16288 + rc = -ENOMEM;
16289 + goto cifs_hl_exit;
16290 + }
16291 +
16292 + if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
16293 + rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
16294 + cifs_sb_target->local_nls);
16295 + else {
16296 + rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
16297 + cifs_sb_target->local_nls);
16298 + if(rc == -EIO)
16299 + rc = -EOPNOTSUPP;
16300 + }
16301 +
16302 +/* if (!rc) */
16303 + {
16304 + /* renew_parental_timestamps(old_file);
16305 + inode->i_nlink++;
16306 + mark_inode_dirty(inode);
16307 + d_instantiate(direntry, inode); */
16308 + /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
16309 + }
16310 + d_drop(direntry); /* force new lookup from server */
16311 + cifsInode = CIFS_I(old_file->d_inode);
16312 + cifsInode->time = 0; /* will force revalidate to go get info when needed */
16313 +
16314 +cifs_hl_exit:
16315 + if (fromName)
16316 + kfree(fromName);
16317 + if (toName)
16318 + kfree(toName);
16319 + FreeXid(xid);
16320 + return rc;
16321 +}
16322 +
16323 +int
16324 +cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
16325 +{
16326 + struct inode *inode = direntry->d_inode;
16327 + int rc = -EACCES;
16328 + int xid;
16329 + char *full_path = NULL;
16330 + char * target_path;
16331 + struct cifs_sb_info *cifs_sb;
16332 + struct cifsTconInfo *pTcon;
16333 +
16334 + xid = GetXid();
16335 +
16336 + down(&direntry->d_sb->s_vfs_rename_sem);
16337 + full_path = build_path_from_dentry(direntry);
16338 + up(&direntry->d_sb->s_vfs_rename_sem);
16339 +
16340 + if(full_path == NULL) {
16341 + FreeXid(xid);
16342 + return -ENOMEM;
16343 + }
16344 + cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
16345 + cifs_sb = CIFS_SB(inode->i_sb);
16346 + pTcon = cifs_sb->tcon;
16347 + target_path = kmalloc(PATH_MAX, GFP_KERNEL);
16348 + if(target_path == NULL) {
16349 + if (full_path)
16350 + kfree(full_path);
16351 + FreeXid(xid);
16352 + return -ENOMEM;
16353 + }
16354 + /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
16355 + /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
16356 +
16357 +/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
16358 + if (pTcon->ses->capabilities & CAP_UNIX)
16359 + rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
16360 + target_path,
16361 + PATH_MAX-1,
16362 + cifs_sb->local_nls);
16363 + else {
16364 + /* rc = CIFSSMBQueryReparseLinkInfo */
16365 + /* BB Add code to Query ReparsePoint info */
16366 + }
16367 + /* BB Anything else to do to handle recursive links? */
16368 + /* BB Should we be using page symlink ops here? */
16369 +
16370 + if (rc == 0) {
16371 +
16372 +/* BB Add special case check for Samba DFS symlinks */
16373 +
16374 + target_path[PATH_MAX-1] = 0;
16375 + rc = vfs_follow_link(nd, target_path);
16376 + }
16377 + /* else EACCESS */
16378 +
16379 + if (target_path)
16380 + kfree(target_path);
16381 + if (full_path)
16382 + kfree(full_path);
16383 + FreeXid(xid);
16384 + return rc;
16385 +}
16386 +
16387 +int
16388 +cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
16389 +{
16390 + int rc = -EOPNOTSUPP;
16391 + int xid;
16392 + struct cifs_sb_info *cifs_sb;
16393 + struct cifsTconInfo *pTcon;
16394 + char *full_path = NULL;
16395 + struct inode *newinode = NULL;
16396 +
16397 + xid = GetXid();
16398 +
16399 + cifs_sb = CIFS_SB(inode->i_sb);
16400 + pTcon = cifs_sb->tcon;
16401 +
16402 + down(&inode->i_sb->s_vfs_rename_sem);
16403 + full_path = build_path_from_dentry(direntry);
16404 + up(&inode->i_sb->s_vfs_rename_sem);
16405 +
16406 + if(full_path == NULL) {
16407 + FreeXid(xid);
16408 + return -ENOMEM;
16409 + }
16410 +
16411 + cFYI(1, ("Full path: %s ", full_path));
16412 + cFYI(1, ("symname is %s", symname));
16413 +
16414 + /* BB what if DFS and this volume is on different share? BB */
16415 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16416 + rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
16417 + cifs_sb->local_nls);
16418 + /* else
16419 + rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
16420 +
16421 + if (rc == 0) {
16422 + if (pTcon->ses->capabilities & CAP_UNIX)
16423 + rc = cifs_get_inode_info_unix(&newinode, full_path,
16424 + inode->i_sb,xid);
16425 + else
16426 + rc = cifs_get_inode_info(&newinode, full_path, NULL,
16427 + inode->i_sb,xid);
16428 +
16429 + if (rc != 0) {
16430 + cFYI(1,
16431 + ("Create symlink worked but get_inode_info failed with rc = %d ",
16432 + rc));
16433 + } else {
16434 + direntry->d_op = &cifs_dentry_ops;
16435 + d_instantiate(direntry, newinode);
16436 + }
16437 + }
16438 +
16439 + if (full_path)
16440 + kfree(full_path);
16441 + FreeXid(xid);
16442 + return rc;
16443 +}
16444 +
16445 +int
16446 +cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
16447 +{
16448 + struct inode *inode = direntry->d_inode;
16449 + int rc = -EACCES;
16450 + int xid;
16451 + int oplock = FALSE;
16452 + struct cifs_sb_info *cifs_sb;
16453 + struct cifsTconInfo *pTcon;
16454 + char *full_path = NULL;
16455 + char *tmp_path = NULL;
16456 + char * tmpbuffer;
16457 + unsigned char * referrals = NULL;
16458 + int num_referrals = 0;
16459 + int len;
16460 + __u16 fid;
16461 +
16462 + xid = GetXid();
16463 + cifs_sb = CIFS_SB(inode->i_sb);
16464 + pTcon = cifs_sb->tcon;
16465 +
16466 +/* BB would it be safe against deadlock to grab this sem
16467 + even though rename itself grabs the sem and calls lookup? */
16468 +/* down(&inode->i_sb->s_vfs_rename_sem);*/
16469 + full_path = build_path_from_dentry(direntry);
16470 +/* up(&inode->i_sb->s_vfs_rename_sem);*/
16471 +
16472 + if(full_path == NULL) {
16473 + FreeXid(xid);
16474 + return -ENOMEM;
16475 + }
16476 +
16477 + cFYI(1,
16478 + ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
16479 + full_path, inode, pBuffer, buflen));
16480 + if(buflen > PATH_MAX)
16481 + len = PATH_MAX;
16482 + else
16483 + len = buflen;
16484 + tmpbuffer = kmalloc(len,GFP_KERNEL);
16485 + if(tmpbuffer == NULL) {
16486 + if (full_path)
16487 + kfree(full_path);
16488 + FreeXid(xid);
16489 + return -ENOMEM;
16490 + }
16491 +
16492 +/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
16493 + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
16494 + rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
16495 + tmpbuffer,
16496 + len - 1,
16497 + cifs_sb->local_nls);
16498 + else {
16499 + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
16500 + OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
16501 + if(!rc) {
16502 + rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
16503 + tmpbuffer,
16504 + len - 1,
16505 + fid,
16506 + cifs_sb->local_nls);
16507 + if(CIFSSMBClose(xid, pTcon, fid)) {
16508 + cFYI(1,("Error closing junction point (open for ioctl)"));
16509 + }
16510 + if(rc == -EIO) {
16511 + /* Query if DFS Junction */
16512 + tmp_path =
16513 + kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
16514 + GFP_KERNEL);
16515 + if (tmp_path) {
16516 + strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
16517 + strncat(tmp_path, full_path, MAX_PATHCONF);
16518 + rc = get_dfs_path(xid, pTcon->ses, tmp_path,
16519 + cifs_sb->local_nls, &num_referrals, &referrals);
16520 + cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
16521 + if((num_referrals == 0) && (rc == 0))
16522 + rc = -EACCES;
16523 + else {
16524 + cFYI(1,("num referral: %d",num_referrals));
16525 + if(referrals) {
16526 + cFYI(1,("referral string: %s ",referrals));
16527 + strncpy(tmpbuffer, referrals, len-1);
16528 + }
16529 + }
16530 + if(referrals)
16531 + kfree(referrals);
16532 + kfree(tmp_path);
16533 + if(referrals) {
16534 + kfree(referrals);
16535 + }
16536 + }
16537 + /* BB add code like else decode referrals then memcpy to
16538 + tmpbuffer and free referrals string array BB */
16539 + }
16540 + }
16541 + }
16542 + /* BB Anything else to do to handle recursive links? */
16543 + /* BB Should we be using page ops here? */
16544 +
16545 + /* BB null terminate returned string in pBuffer? BB */
16546 + if (rc == 0) {
16547 + rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
16548 + cFYI(1,
16549 + ("vfs_readlink called from cifs_readlink returned %d",
16550 + rc));
16551 + }
16552 +
16553 + if (tmpbuffer) {
16554 + kfree(tmpbuffer);
16555 + }
16556 + if (full_path) {
16557 + kfree(full_path);
16558 + }
16559 + FreeXid(xid);
16560 + return rc;
16561 +}
16562 diff -urN linux-2.4.29.old/fs/cifs/Makefile linux-2.4.29/fs/cifs/Makefile
16563 --- linux-2.4.29.old/fs/cifs/Makefile 1970-01-01 01:00:00.000000000 +0100
16564 +++ linux-2.4.29/fs/cifs/Makefile 2004-07-14 00:25:04.000000000 +0200
16565 @@ -0,0 +1,10 @@
16566 +#
16567 +# Makefile for Linux CIFS VFS client
16568 +#
16569 +O_TARGET := cifs.o
16570 +
16571 +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
16572 +
16573 +obj-m := $(O_TARGET)
16574 +
16575 +include $(TOPDIR)/Rules.make
16576 diff -urN linux-2.4.29.old/fs/cifs/md4.c linux-2.4.29/fs/cifs/md4.c
16577 --- linux-2.4.29.old/fs/cifs/md4.c 1970-01-01 01:00:00.000000000 +0100
16578 +++ linux-2.4.29/fs/cifs/md4.c 2004-07-14 00:25:05.000000000 +0200
16579 @@ -0,0 +1,203 @@
16580 +/*
16581 + Unix SMB/Netbios implementation.
16582 + Version 1.9.
16583 + a implementation of MD4 designed for use in the SMB authentication protocol
16584 + Copyright (C) Andrew Tridgell 1997-1998.
16585 + Modified by Steve French (sfrench@us.ibm.com) 2002-2003
16586 +
16587 + This program is free software; you can redistribute it and/or modify
16588 + it under the terms of the GNU General Public License as published by
16589 + the Free Software Foundation; either version 2 of the License, or
16590 + (at your option) any later version.
16591 +
16592 + This program is distributed in the hope that it will be useful,
16593 + but WITHOUT ANY WARRANTY; without even the implied warranty of
16594 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16595 + GNU General Public License for more details.
16596 +
16597 + You should have received a copy of the GNU General Public License
16598 + along with this program; if not, write to the Free Software
16599 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16600 +*/
16601 +#include <linux/module.h>
16602 +#include <linux/fs.h>
16603 +/* NOTE: This code makes no attempt to be fast! */
16604 +
16605 +static __u32
16606 +F(__u32 X, __u32 Y, __u32 Z)
16607 +{
16608 + return (X & Y) | ((~X) & Z);
16609 +}
16610 +
16611 +static __u32
16612 +G(__u32 X, __u32 Y, __u32 Z)
16613 +{
16614 + return (X & Y) | (X & Z) | (Y & Z);
16615 +}
16616 +
16617 +static __u32
16618 +H(__u32 X, __u32 Y, __u32 Z)
16619 +{
16620 + return X ^ Y ^ Z;
16621 +}
16622 +
16623 +static __u32
16624 +lshift(__u32 x, int s)
16625 +{
16626 + x &= 0xFFFFFFFF;
16627 + return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
16628 +}
16629 +
16630 +#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
16631 +#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
16632 +#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
16633 +
16634 +/* this applies md4 to 64 byte chunks */
16635 +static void
16636 +mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
16637 +{
16638 + int j;
16639 + __u32 AA, BB, CC, DD;
16640 + __u32 X[16];
16641 +
16642 +
16643 + for (j = 0; j < 16; j++)
16644 + X[j] = M[j];
16645 +
16646 + AA = *A;
16647 + BB = *B;
16648 + CC = *C;
16649 + DD = *D;
16650 +
16651 + ROUND1(A, B, C, D, 0, 3);
16652 + ROUND1(D, A, B, C, 1, 7);
16653 + ROUND1(C, D, A, B, 2, 11);
16654 + ROUND1(B, C, D, A, 3, 19);
16655 + ROUND1(A, B, C, D, 4, 3);
16656 + ROUND1(D, A, B, C, 5, 7);
16657 + ROUND1(C, D, A, B, 6, 11);
16658 + ROUND1(B, C, D, A, 7, 19);
16659 + ROUND1(A, B, C, D, 8, 3);
16660 + ROUND1(D, A, B, C, 9, 7);
16661 + ROUND1(C, D, A, B, 10, 11);
16662 + ROUND1(B, C, D, A, 11, 19);
16663 + ROUND1(A, B, C, D, 12, 3);
16664 + ROUND1(D, A, B, C, 13, 7);
16665 + ROUND1(C, D, A, B, 14, 11);
16666 + ROUND1(B, C, D, A, 15, 19);
16667 +
16668 + ROUND2(A, B, C, D, 0, 3);
16669 + ROUND2(D, A, B, C, 4, 5);
16670 + ROUND2(C, D, A, B, 8, 9);
16671 + ROUND2(B, C, D, A, 12, 13);
16672 + ROUND2(A, B, C, D, 1, 3);
16673 + ROUND2(D, A, B, C, 5, 5);
16674 + ROUND2(C, D, A, B, 9, 9);
16675 + ROUND2(B, C, D, A, 13, 13);
16676 + ROUND2(A, B, C, D, 2, 3);
16677 + ROUND2(D, A, B, C, 6, 5);
16678 + ROUND2(C, D, A, B, 10, 9);
16679 + ROUND2(B, C, D, A, 14, 13);
16680 + ROUND2(A, B, C, D, 3, 3);
16681 + ROUND2(D, A, B, C, 7, 5);
16682 + ROUND2(C, D, A, B, 11, 9);
16683 + ROUND2(B, C, D, A, 15, 13);
16684 +
16685 + ROUND3(A, B, C, D, 0, 3);
16686 + ROUND3(D, A, B, C, 8, 9);
16687 + ROUND3(C, D, A, B, 4, 11);
16688 + ROUND3(B, C, D, A, 12, 15);
16689 + ROUND3(A, B, C, D, 2, 3);
16690 + ROUND3(D, A, B, C, 10, 9);
16691 + ROUND3(C, D, A, B, 6, 11);
16692 + ROUND3(B, C, D, A, 14, 15);
16693 + ROUND3(A, B, C, D, 1, 3);
16694 + ROUND3(D, A, B, C, 9, 9);
16695 + ROUND3(C, D, A, B, 5, 11);
16696 + ROUND3(B, C, D, A, 13, 15);
16697 + ROUND3(A, B, C, D, 3, 3);
16698 + ROUND3(D, A, B, C, 11, 9);
16699 + ROUND3(C, D, A, B, 7, 11);
16700 + ROUND3(B, C, D, A, 15, 15);
16701 +
16702 + *A += AA;
16703 + *B += BB;
16704 + *C += CC;
16705 + *D += DD;
16706 +
16707 + *A &= 0xFFFFFFFF;
16708 + *B &= 0xFFFFFFFF;
16709 + *C &= 0xFFFFFFFF;
16710 + *D &= 0xFFFFFFFF;
16711 +
16712 + for (j = 0; j < 16; j++)
16713 + X[j] = 0;
16714 +}
16715 +
16716 +static void
16717 +copy64(__u32 * M, unsigned char *in)
16718 +{
16719 + int i;
16720 +
16721 + for (i = 0; i < 16; i++)
16722 + M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
16723 + (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
16724 +}
16725 +
16726 +static void
16727 +copy4(unsigned char *out, __u32 x)
16728 +{
16729 + out[0] = x & 0xFF;
16730 + out[1] = (x >> 8) & 0xFF;
16731 + out[2] = (x >> 16) & 0xFF;
16732 + out[3] = (x >> 24) & 0xFF;
16733 +}
16734 +
16735 +/* produce a md4 message digest from data of length n bytes */
16736 +void
16737 +mdfour(unsigned char *out, unsigned char *in, int n)
16738 +{
16739 + unsigned char buf[128];
16740 + __u32 M[16];
16741 + __u32 b = n * 8;
16742 + int i;
16743 + __u32 A = 0x67452301;
16744 + __u32 B = 0xefcdab89;
16745 + __u32 C = 0x98badcfe;
16746 + __u32 D = 0x10325476;
16747 +
16748 + while (n > 64) {
16749 + copy64(M, in);
16750 + mdfour64(M,&A,&B, &C, &D);
16751 + in += 64;
16752 + n -= 64;
16753 + }
16754 +
16755 + for (i = 0; i < 128; i++)
16756 + buf[i] = 0;
16757 + memcpy(buf, in, n);
16758 + buf[n] = 0x80;
16759 +
16760 + if (n <= 55) {
16761 + copy4(buf + 56, b);
16762 + copy64(M, buf);
16763 + mdfour64(M, &A, &B, &C, &D);
16764 + } else {
16765 + copy4(buf + 120, b);
16766 + copy64(M, buf);
16767 + mdfour64(M, &A, &B, &C, &D);
16768 + copy64(M, buf + 64);
16769 + mdfour64(M, &A, &B, &C, &D);
16770 + }
16771 +
16772 + for (i = 0; i < 128; i++)
16773 + buf[i] = 0;
16774 + copy64(M, buf);
16775 +
16776 + copy4(out, A);
16777 + copy4(out + 4, B);
16778 + copy4(out + 8, C);
16779 + copy4(out + 12, D);
16780 +
16781 + A = B = C = D = 0;
16782 +}
16783 diff -urN linux-2.4.29.old/fs/cifs/md5.c linux-2.4.29/fs/cifs/md5.c
16784 --- linux-2.4.29.old/fs/cifs/md5.c 1970-01-01 01:00:00.000000000 +0100
16785 +++ linux-2.4.29/fs/cifs/md5.c 2004-07-14 00:25:05.000000000 +0200
16786 @@ -0,0 +1,363 @@
16787 +/*
16788 + * This code implements the MD5 message-digest algorithm.
16789 + * The algorithm is due to Ron Rivest. This code was
16790 + * written by Colin Plumb in 1993, no copyright is claimed.
16791 + * This code is in the public domain; do with it what you wish.
16792 + *
16793 + * Equivalent code is available from RSA Data Security, Inc.
16794 + * This code has been tested against that, and is equivalent,
16795 + * except that you don't need to include two pages of legalese
16796 + * with every copy.
16797 + *
16798 + * To compute the message digest of a chunk of bytes, declare an
16799 + * MD5Context structure, pass it to MD5Init, call MD5Update as
16800 + * needed on buffers full of bytes, and then call MD5Final, which
16801 + * will fill a supplied 16-byte array with the digest.
16802 + */
16803 +
16804 +/* This code slightly modified to fit into Samba by
16805 + abartlet@samba.org Jun 2001
16806 + and to fit the cifs vfs by
16807 + Steve French sfrench@us.ibm.com */
16808 +
16809 +#include <linux/string.h>
16810 +#include "md5.h"
16811 +
16812 +static void MD5Transform(__u32 buf[4], __u32 const in[16]);
16813 +
16814 +/*
16815 + * Note: this code is harmless on little-endian machines.
16816 + */
16817 +static void
16818 +byteReverse(unsigned char *buf, unsigned longs)
16819 +{
16820 + __u32 t;
16821 + do {
16822 + t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
16823 + ((unsigned) buf[1] << 8 | buf[0]);
16824 + *(__u32 *) buf = t;
16825 + buf += 4;
16826 + } while (--longs);
16827 +}
16828 +
16829 +/*
16830 + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
16831 + * initialization constants.
16832 + */
16833 +void
16834 +MD5Init(struct MD5Context *ctx)
16835 +{
16836 + ctx->buf[0] = 0x67452301;
16837 + ctx->buf[1] = 0xefcdab89;
16838 + ctx->buf[2] = 0x98badcfe;
16839 + ctx->buf[3] = 0x10325476;
16840 +
16841 + ctx->bits[0] = 0;
16842 + ctx->bits[1] = 0;
16843 +}
16844 +
16845 +/*
16846 + * Update context to reflect the concatenation of another buffer full
16847 + * of bytes.
16848 + */
16849 +void
16850 +MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
16851 +{
16852 + register __u32 t;
16853 +
16854 + /* Update bitcount */
16855 +
16856 + t = ctx->bits[0];
16857 + if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
16858 + ctx->bits[1]++; /* Carry from low to high */
16859 + ctx->bits[1] += len >> 29;
16860 +
16861 + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
16862 +
16863 + /* Handle any leading odd-sized chunks */
16864 +
16865 + if (t) {
16866 + unsigned char *p = (unsigned char *) ctx->in + t;
16867 +
16868 + t = 64 - t;
16869 + if (len < t) {
16870 + memmove(p, buf, len);
16871 + return;
16872 + }
16873 + memmove(p, buf, t);
16874 + byteReverse(ctx->in, 16);
16875 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16876 + buf += t;
16877 + len -= t;
16878 + }
16879 + /* Process data in 64-byte chunks */
16880 +
16881 + while (len >= 64) {
16882 + memmove(ctx->in, buf, 64);
16883 + byteReverse(ctx->in, 16);
16884 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16885 + buf += 64;
16886 + len -= 64;
16887 + }
16888 +
16889 + /* Handle any remaining bytes of data. */
16890 +
16891 + memmove(ctx->in, buf, len);
16892 +}
16893 +
16894 +/*
16895 + * Final wrapup - pad to 64-byte boundary with the bit pattern
16896 + * 1 0* (64-bit count of bits processed, MSB-first)
16897 + */
16898 +void
16899 +MD5Final(unsigned char digest[16], struct MD5Context *ctx)
16900 +{
16901 + unsigned int count;
16902 + unsigned char *p;
16903 +
16904 + /* Compute number of bytes mod 64 */
16905 + count = (ctx->bits[0] >> 3) & 0x3F;
16906 +
16907 + /* Set the first char of padding to 0x80. This is safe since there is
16908 + always at least one byte free */
16909 + p = ctx->in + count;
16910 + *p++ = 0x80;
16911 +
16912 + /* Bytes of padding needed to make 64 bytes */
16913 + count = 64 - 1 - count;
16914 +
16915 + /* Pad out to 56 mod 64 */
16916 + if (count < 8) {
16917 + /* Two lots of padding: Pad the first block to 64 bytes */
16918 + memset(p, 0, count);
16919 + byteReverse(ctx->in, 16);
16920 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16921 +
16922 + /* Now fill the next block with 56 bytes */
16923 + memset(ctx->in, 0, 56);
16924 + } else {
16925 + /* Pad block to 56 bytes */
16926 + memset(p, 0, count - 8);
16927 + }
16928 + byteReverse(ctx->in, 14);
16929 +
16930 + /* Append length in bits and transform */
16931 + ((__u32 *) ctx->in)[14] = ctx->bits[0];
16932 + ((__u32 *) ctx->in)[15] = ctx->bits[1];
16933 +
16934 + MD5Transform(ctx->buf, (__u32 *) ctx->in);
16935 + byteReverse((unsigned char *) ctx->buf, 4);
16936 + memmove(digest, ctx->buf, 16);
16937 + memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
16938 +}
16939 +
16940 +/* The four core functions - F1 is optimized somewhat */
16941 +
16942 +/* #define F1(x, y, z) (x & y | ~x & z) */
16943 +#define F1(x, y, z) (z ^ (x & (y ^ z)))
16944 +#define F2(x, y, z) F1(z, x, y)
16945 +#define F3(x, y, z) (x ^ y ^ z)
16946 +#define F4(x, y, z) (y ^ (x | ~z))
16947 +
16948 +/* This is the central step in the MD5 algorithm. */
16949 +#define MD5STEP(f, w, x, y, z, data, s) \
16950 + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
16951 +
16952 +/*
16953 + * The core of the MD5 algorithm, this alters an existing MD5 hash to
16954 + * reflect the addition of 16 longwords of new data. MD5Update blocks
16955 + * the data and converts bytes into longwords for this routine.
16956 + */
16957 +static void
16958 +MD5Transform(__u32 buf[4], __u32 const in[16])
16959 +{
16960 + register __u32 a, b, c, d;
16961 +
16962 + a = buf[0];
16963 + b = buf[1];
16964 + c = buf[2];
16965 + d = buf[3];
16966 +
16967 + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
16968 + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
16969 + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
16970 + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
16971 + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
16972 + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
16973 + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
16974 + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
16975 + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
16976 + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
16977 + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
16978 + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
16979 + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
16980 + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
16981 + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
16982 + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
16983 +
16984 + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
16985 + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
16986 + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
16987 + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
16988 + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
16989 + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
16990 + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
16991 + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
16992 + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
16993 + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
16994 + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
16995 + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
16996 + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
16997 + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
16998 + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
16999 + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
17000 +
17001 + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
17002 + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
17003 + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
17004 + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
17005 + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
17006 + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
17007 + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
17008 + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
17009 + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
17010 + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
17011 + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
17012 + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
17013 + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
17014 + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
17015 + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
17016 + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
17017 +
17018 + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
17019 + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
17020 + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
17021 + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
17022 + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
17023 + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
17024 + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
17025 + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
17026 + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
17027 + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
17028 + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
17029 + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
17030 + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
17031 + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
17032 + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
17033 + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
17034 +
17035 + buf[0] += a;
17036 + buf[1] += b;
17037 + buf[2] += c;
17038 + buf[3] += d;
17039 +}
17040 +
17041 +/***********************************************************************
17042 + the rfc 2104 version of hmac_md5 initialisation.
17043 +***********************************************************************/
17044 +void
17045 +hmac_md5_init_rfc2104(unsigned char *key, int key_len,
17046 + struct HMACMD5Context *ctx)
17047 +{
17048 + int i;
17049 +
17050 + /* if key is longer than 64 bytes reset it to key=MD5(key) */
17051 + if (key_len > 64) {
17052 + unsigned char tk[16];
17053 + struct MD5Context tctx;
17054 +
17055 + MD5Init(&tctx);
17056 + MD5Update(&tctx, key, key_len);
17057 + MD5Final(tk, &tctx);
17058 +
17059 + key = tk;
17060 + key_len = 16;
17061 + }
17062 +
17063 + /* start out by storing key in pads */
17064 + memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
17065 + memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
17066 + memcpy(ctx->k_ipad, key, key_len);
17067 + memcpy(ctx->k_opad, key, key_len);
17068 +
17069 + /* XOR key with ipad and opad values */
17070 + for (i = 0; i < 64; i++) {
17071 + ctx->k_ipad[i] ^= 0x36;
17072 + ctx->k_opad[i] ^= 0x5c;
17073 + }
17074 +
17075 + MD5Init(&ctx->ctx);
17076 + MD5Update(&ctx->ctx, ctx->k_ipad, 64);
17077 +}
17078 +
17079 +/***********************************************************************
17080 + the microsoft version of hmac_md5 initialisation.
17081 +***********************************************************************/
17082 +void
17083 +hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
17084 + struct HMACMD5Context *ctx)
17085 +{
17086 + int i;
17087 +
17088 + /* if key is longer than 64 bytes truncate it */
17089 + if (key_len > 64) {
17090 + key_len = 64;
17091 + }
17092 +
17093 + /* start out by storing key in pads */
17094 + memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
17095 + memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
17096 + memcpy(ctx->k_ipad, key, key_len);
17097 + memcpy(ctx->k_opad, key, key_len);
17098 +
17099 + /* XOR key with ipad and opad values */
17100 + for (i = 0; i < 64; i++) {
17101 + ctx->k_ipad[i] ^= 0x36;
17102 + ctx->k_opad[i] ^= 0x5c;
17103 + }
17104 +
17105 + MD5Init(&ctx->ctx);
17106 + MD5Update(&ctx->ctx, ctx->k_ipad, 64);
17107 +}
17108 +
17109 +/***********************************************************************
17110 + update hmac_md5 "inner" buffer
17111 +***********************************************************************/
17112 +void
17113 +hmac_md5_update(const unsigned char *text, int text_len,
17114 + struct HMACMD5Context *ctx)
17115 +{
17116 + MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
17117 +}
17118 +
17119 +/***********************************************************************
17120 + finish off hmac_md5 "inner" buffer and generate outer one.
17121 +***********************************************************************/
17122 +void
17123 +hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
17124 +{
17125 + struct MD5Context ctx_o;
17126 +
17127 + MD5Final(digest, &ctx->ctx);
17128 +
17129 + MD5Init(&ctx_o);
17130 + MD5Update(&ctx_o, ctx->k_opad, 64);
17131 + MD5Update(&ctx_o, digest, 16);
17132 + MD5Final(digest, &ctx_o);
17133 +}
17134 +
17135 +/***********************************************************
17136 + single function to calculate an HMAC MD5 digest from data.
17137 + use the microsoft hmacmd5 init method because the key is 16 bytes.
17138 +************************************************************/
17139 +void
17140 +hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
17141 + unsigned char *digest)
17142 +{
17143 + struct HMACMD5Context ctx;
17144 + hmac_md5_init_limK_to_64(key, 16, &ctx);
17145 + if (data_len != 0) {
17146 + hmac_md5_update(data, data_len, &ctx);
17147 + }
17148 + hmac_md5_final(digest, &ctx);
17149 +}
17150 diff -urN linux-2.4.29.old/fs/cifs/md5.h linux-2.4.29/fs/cifs/md5.h
17151 --- linux-2.4.29.old/fs/cifs/md5.h 1970-01-01 01:00:00.000000000 +0100
17152 +++ linux-2.4.29/fs/cifs/md5.h 2004-07-14 00:25:05.000000000 +0200
17153 @@ -0,0 +1,38 @@
17154 +#ifndef MD5_H
17155 +#define MD5_H
17156 +#ifndef HEADER_MD5_H
17157 +/* Try to avoid clashes with OpenSSL */
17158 +#define HEADER_MD5_H
17159 +#endif
17160 +
17161 +struct MD5Context {
17162 + __u32 buf[4];
17163 + __u32 bits[2];
17164 + unsigned char in[64];
17165 +};
17166 +#endif /* !MD5_H */
17167 +
17168 +#ifndef _HMAC_MD5_H
17169 +struct HMACMD5Context {
17170 + struct MD5Context ctx;
17171 + unsigned char k_ipad[65];
17172 + unsigned char k_opad[65];
17173 +};
17174 +#endif /* _HMAC_MD5_H */
17175 +
17176 +void MD5Init(struct MD5Context *context);
17177 +void MD5Update(struct MD5Context *context, unsigned char const *buf,
17178 + unsigned len);
17179 +void MD5Final(unsigned char digest[16], struct MD5Context *context);
17180 +
17181 +/* The following definitions come from lib/hmacmd5.c */
17182 +
17183 +void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
17184 + struct HMACMD5Context *ctx);
17185 +void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
17186 + struct HMACMD5Context *ctx);
17187 +void hmac_md5_update(const unsigned char *text, int text_len,
17188 + struct HMACMD5Context *ctx);
17189 +void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
17190 +void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
17191 + unsigned char *digest);
17192 diff -urN linux-2.4.29.old/fs/cifs/misc.c linux-2.4.29/fs/cifs/misc.c
17193 --- linux-2.4.29.old/fs/cifs/misc.c 1970-01-01 01:00:00.000000000 +0100
17194 +++ linux-2.4.29/fs/cifs/misc.c 2004-07-14 00:25:05.000000000 +0200
17195 @@ -0,0 +1,463 @@
17196 +/*
17197 + * fs/cifs/misc.c
17198 + *
17199 + * Copyright (C) International Business Machines Corp., 2002,2003
17200 + * Author(s): Steve French (sfrench@us.ibm.com)
17201 + *
17202 + * This library is free software; you can redistribute it and/or modify
17203 + * it under the terms of the GNU Lesser General Public License as published
17204 + * by the Free Software Foundation; either version 2.1 of the License, or
17205 + * (at your option) any later version.
17206 + *
17207 + * This library is distributed in the hope that it will be useful,
17208 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17209 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17210 + * the GNU Lesser General Public License for more details.
17211 + *
17212 + * You should have received a copy of the GNU Lesser General Public License
17213 + * along with this library; if not, write to the Free Software
17214 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17215 + */
17216 +
17217 +#include <linux/slab.h>
17218 +#include <linux/ctype.h>
17219 +#include "cifspdu.h"
17220 +#include "cifsglob.h"
17221 +#include "cifsproto.h"
17222 +#include "cifs_debug.h"
17223 +#include "smberr.h"
17224 +#include "nterr.h"
17225 +
17226 +extern kmem_cache_t *cifs_req_cachep;
17227 +extern struct task_struct * oplockThread;
17228 +
17229 +__u16 GlobalMid; /* multiplex id - rotating counter */
17230 +
17231 +/* The xid serves as a useful identifier for each incoming vfs request,
17232 + in a similar way to the mid which is useful to track each sent smb,
17233 + and CurrentXid can also provide a running counter (although it
17234 + will eventually wrap past zero) of the total vfs operations handled
17235 + since the cifs fs was mounted */
17236 +
17237 +unsigned int
17238 +_GetXid(void)
17239 +{
17240 + unsigned int xid;
17241 +
17242 + spin_lock(&GlobalMid_Lock);
17243 + GlobalTotalActiveXid++;
17244 + if (GlobalTotalActiveXid > GlobalMaxActiveXid)
17245 + GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
17246 + xid = GlobalCurrentXid++;
17247 + spin_unlock(&GlobalMid_Lock);
17248 + return xid;
17249 +}
17250 +
17251 +void
17252 +_FreeXid(unsigned int xid)
17253 +{
17254 + spin_lock(&GlobalMid_Lock);
17255 + /* if(GlobalTotalActiveXid == 0)
17256 + BUG(); */
17257 + GlobalTotalActiveXid--;
17258 + spin_unlock(&GlobalMid_Lock);
17259 +}
17260 +
17261 +struct cifsSesInfo *
17262 +sesInfoAlloc(void)
17263 +{
17264 + struct cifsSesInfo *ret_buf;
17265 +
17266 + ret_buf =
17267 + (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
17268 + GFP_KERNEL);
17269 + if (ret_buf) {
17270 + memset(ret_buf, 0, sizeof (struct cifsSesInfo));
17271 + write_lock(&GlobalSMBSeslock);
17272 + atomic_inc(&sesInfoAllocCount);
17273 + ret_buf->status = CifsNew;
17274 + list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
17275 + init_MUTEX(&ret_buf->sesSem);
17276 + write_unlock(&GlobalSMBSeslock);
17277 + }
17278 + return ret_buf;
17279 +}
17280 +
17281 +void
17282 +sesInfoFree(struct cifsSesInfo *buf_to_free)
17283 +{
17284 + if (buf_to_free == NULL) {
17285 + cFYI(1, ("Null buffer passed to sesInfoFree"));
17286 + return;
17287 + }
17288 +
17289 + write_lock(&GlobalSMBSeslock);
17290 + atomic_dec(&sesInfoAllocCount);
17291 + list_del(&buf_to_free->cifsSessionList);
17292 + write_unlock(&GlobalSMBSeslock);
17293 + if (buf_to_free->serverOS)
17294 + kfree(buf_to_free->serverOS);
17295 + if (buf_to_free->serverDomain)
17296 + kfree(buf_to_free->serverDomain);
17297 + if (buf_to_free->serverNOS)
17298 + kfree(buf_to_free->serverNOS);
17299 + if (buf_to_free->password)
17300 + kfree(buf_to_free->password);
17301 + kfree(buf_to_free);
17302 +}
17303 +
17304 +struct cifsTconInfo *
17305 +tconInfoAlloc(void)
17306 +{
17307 + struct cifsTconInfo *ret_buf;
17308 + ret_buf =
17309 + (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
17310 + GFP_KERNEL);
17311 + if (ret_buf) {
17312 + memset(ret_buf, 0, sizeof (struct cifsTconInfo));
17313 + write_lock(&GlobalSMBSeslock);
17314 + atomic_inc(&tconInfoAllocCount);
17315 + list_add(&ret_buf->cifsConnectionList,
17316 + &GlobalTreeConnectionList);
17317 + ret_buf->tidStatus = CifsNew;
17318 + INIT_LIST_HEAD(&ret_buf->openFileList);
17319 + init_MUTEX(&ret_buf->tconSem);
17320 +#ifdef CONFIG_CIFS_STATS
17321 + ret_buf->stat_lock = SPIN_LOCK_UNLOCKED;
17322 +#endif
17323 + write_unlock(&GlobalSMBSeslock);
17324 + }
17325 + return ret_buf;
17326 +}
17327 +
17328 +void
17329 +tconInfoFree(struct cifsTconInfo *buf_to_free)
17330 +{
17331 + if (buf_to_free == NULL) {
17332 + cFYI(1, ("Null buffer passed to tconInfoFree"));
17333 + return;
17334 + }
17335 + write_lock(&GlobalSMBSeslock);
17336 + atomic_dec(&tconInfoAllocCount);
17337 + list_del(&buf_to_free->cifsConnectionList);
17338 + write_unlock(&GlobalSMBSeslock);
17339 + if (buf_to_free->nativeFileSystem)
17340 + kfree(buf_to_free->nativeFileSystem);
17341 + kfree(buf_to_free);
17342 +}
17343 +
17344 +struct smb_hdr *
17345 +cifs_buf_get(void)
17346 +{
17347 + struct smb_hdr *ret_buf = NULL;
17348 +
17349 +/* We could use negotiated size instead of max_msgsize -
17350 + but it may be more efficient to always alloc same size
17351 + albeit slightly larger than necessary and maxbuffersize
17352 + defaults to this and can not be bigger */
17353 + ret_buf =
17354 + (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
17355 +
17356 + /* clear the first few header bytes */
17357 + if (ret_buf) {
17358 + memset(ret_buf, 0, sizeof (struct smb_hdr));
17359 + atomic_inc(&bufAllocCount);
17360 + }
17361 +
17362 + return ret_buf;
17363 +}
17364 +
17365 +void
17366 +cifs_buf_release(void *buf_to_free)
17367 +{
17368 +
17369 + if (buf_to_free == NULL) {
17370 + cFYI(1, ("Null buffer passed to cifs_buf_release"));
17371 + return;
17372 + }
17373 + kmem_cache_free(cifs_req_cachep, buf_to_free);
17374 +
17375 + atomic_dec(&bufAllocCount);
17376 + return;
17377 +}
17378 +
17379 +void
17380 +header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
17381 + const struct cifsTconInfo *treeCon, int word_count
17382 + /* length of fixed section (word count) in two byte units */
17383 + )
17384 +{
17385 + int i;
17386 + __u32 tmp;
17387 + struct list_head* temp_item;
17388 + struct cifsSesInfo * ses;
17389 + char *temp = (char *) buffer;
17390 +
17391 + for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) {
17392 + temp[i] = 0; /* BB is this needed ?? */
17393 + }
17394 +
17395 + buffer->smb_buf_length =
17396 + (2 * word_count) + sizeof (struct smb_hdr) -
17397 + 4 /* RFC 1001 length field does not count */ +
17398 + 2 /* for bcc field itself */ ;
17399 + /* 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 */
17400 +
17401 + buffer->Protocol[0] = 0xFF;
17402 + buffer->Protocol[1] = 'S';
17403 + buffer->Protocol[2] = 'M';
17404 + buffer->Protocol[3] = 'B';
17405 + buffer->Command = smb_command;
17406 + buffer->Flags = 0x00; /* case sensitive */
17407 + buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
17408 + tmp = cpu_to_le32(current->pid);
17409 + buffer->Pid = tmp & 0xFFFF;
17410 + tmp >>= 16;
17411 + buffer->PidHigh = tmp & 0xFFFF;
17412 + spin_lock(&GlobalMid_Lock);
17413 + GlobalMid++;
17414 + buffer->Mid = GlobalMid;
17415 + spin_unlock(&GlobalMid_Lock);
17416 + if (treeCon) {
17417 + buffer->Tid = treeCon->tid;
17418 + if (treeCon->ses) {
17419 + if (treeCon->ses->capabilities & CAP_UNICODE)
17420 + buffer->Flags2 |= SMBFLG2_UNICODE;
17421 + if (treeCon->ses->capabilities & CAP_STATUS32) {
17422 + buffer->Flags2 |= SMBFLG2_ERR_STATUS;
17423 + }
17424 +
17425 + buffer->Uid = treeCon->ses->Suid; /* always in LE format */
17426 + if(multiuser_mount != 0) {
17427 + /* For the multiuser case, there are few obvious technically */
17428 + /* possible mechanisms to match the local linux user (uid) */
17429 + /* to a valid remote smb user (smb_uid): */
17430 + /* 1) Query Winbind (or other local pam/nss daemon */
17431 + /* for userid/password/logon_domain or credential */
17432 + /* 2) Query Winbind for uid to sid to username mapping */
17433 + /* and see if we have a matching password for existing*/
17434 + /* session for that user perhas getting password by */
17435 + /* adding a new pam_cifs module that stores passwords */
17436 + /* so that the cifs vfs can get at that for all logged*/
17437 + /* on users */
17438 + /* 3) (Which is the mechanism we have chosen) */
17439 + /* Search through sessions to the same server for a */
17440 + /* a match on the uid that was passed in on mount */
17441 + /* with the current processes uid (or euid?) and use */
17442 + /* that smb uid. If no existing smb session for */
17443 + /* that uid found, use the default smb session ie */
17444 + /* the smb session for the volume mounted which is */
17445 + /* the same as would be used if the multiuser mount */
17446 + /* flag were disabled. */
17447 +
17448 + /* BB Add support for establishing new tCon and SMB Session */
17449 + /* with userid/password pairs found on the smb session */
17450 + /* for other target tcp/ip addresses BB */
17451 + if(current->uid != treeCon->ses->linux_uid) {
17452 + cFYI(1,("Multiuser mode and UID did not match tcon uid "));
17453 + read_lock(&GlobalSMBSeslock);
17454 + list_for_each(temp_item, &GlobalSMBSessionList) {
17455 + ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
17456 + if(ses->linux_uid == current->uid) {
17457 + if(ses->server == treeCon->ses->server) {
17458 + cFYI(1,("found matching uid substitute right smb_uid"));
17459 + buffer->Uid = ses->Suid;
17460 + break;
17461 + } else {
17462 + /* BB eventually call cifs_setup_session here */
17463 + cFYI(1,("local UID found but smb sess with this server does not exist"));
17464 + }
17465 + }
17466 + }
17467 + read_unlock(&GlobalSMBSeslock);
17468 + }
17469 + }
17470 + }
17471 + if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
17472 + buffer->Flags2 |= SMBFLG2_DFS;
17473 + if(treeCon->ses->server)
17474 + if(treeCon->ses->server->secMode &
17475 + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
17476 + buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
17477 + }
17478 +
17479 +/* endian conversion of flags is now done just before sending */
17480 + buffer->WordCount = (char) word_count;
17481 + return;
17482 +}
17483 +
17484 +int
17485 +checkSMBhdr(struct smb_hdr *smb, __u16 mid)
17486 +{
17487 + /* Make sure that this really is an SMB, that it is a response,
17488 + and that the message ids match */
17489 + if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
17490 + (mid == smb->Mid)) {
17491 + if(smb->Flags & SMBFLG_RESPONSE)
17492 + return 0;
17493 + else {
17494 + /* only one valid case where server sends us request */
17495 + if(smb->Command == SMB_COM_LOCKING_ANDX)
17496 + return 0;
17497 + else
17498 + cERROR(1, ("Rcvd Request not response "));
17499 + }
17500 + } else { /* bad signature or mid */
17501 + if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
17502 + cERROR(1,
17503 + ("Bad protocol string signature header %x ",
17504 + *(unsigned int *) smb->Protocol));
17505 + if (mid != smb->Mid)
17506 + cERROR(1, ("Mids do not match"));
17507 + }
17508 + cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
17509 + return 1;
17510 +}
17511 +
17512 +int
17513 +checkSMB(struct smb_hdr *smb, __u16 mid, int length)
17514 +{
17515 + cFYI(0,
17516 + ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
17517 + length, ntohl(smb->smb_buf_length)));
17518 + if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
17519 + || (ntohl(smb->smb_buf_length) >
17520 + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
17521 + if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
17522 + cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
17523 + if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
17524 + && (smb->Status.CifsError != 0))
17525 + return 0; /* some error cases do not return wct and bcc */
17526 +
17527 + }
17528 + if (ntohl(smb->smb_buf_length) >
17529 + CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
17530 + cERROR(1,
17531 + ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
17532 + cERROR(1,
17533 + ("bad smb detected. Illegal length. The mid=%d",
17534 + smb->Mid));
17535 + return 1;
17536 + }
17537 +
17538 + if (checkSMBhdr(smb, mid))
17539 + return 1;
17540 +
17541 + if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
17542 + || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
17543 + return 0;
17544 + } else {
17545 + cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
17546 + cERROR(1,
17547 + ("bad smb size detected. The Mid=%d", smb->Mid));
17548 + return 1;
17549 + }
17550 +}
17551 +int
17552 +is_valid_oplock_break(struct smb_hdr *buf)
17553 +{
17554 + struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
17555 + struct list_head *tmp;
17556 + struct list_head *tmp1;
17557 + struct cifsTconInfo *tcon;
17558 + struct cifsFileInfo *netfile;
17559 +
17560 + /* could add check for smb response flag 0x80 */
17561 + cFYI(1,("Checking for oplock break"));
17562 + if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
17563 + return FALSE;
17564 + if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
17565 + /* no sense logging error on invalid handle on oplock
17566 + break - harmless race between close request and oplock
17567 + break response is expected from time to time writing out
17568 + large dirty files cached on the client */
17569 + if ((NT_STATUS_INVALID_HANDLE) ==
17570 + le32_to_cpu(pSMB->hdr.Status.CifsError)) {
17571 + cFYI(1,("invalid handle on oplock break"));
17572 + return TRUE;
17573 + } else if (ERRbadfid ==
17574 + le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
17575 + return TRUE;
17576 + } else {
17577 + return FALSE; /* on valid oplock brk we get "request" */
17578 + }
17579 + }
17580 + if(pSMB->hdr.WordCount != 8)
17581 + return FALSE;
17582 +
17583 + cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
17584 + if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
17585 + return FALSE;
17586 +
17587 + /* look up tcon based on tid & uid */
17588 + read_lock(&GlobalSMBSeslock);
17589 + list_for_each(tmp, &GlobalTreeConnectionList) {
17590 + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
17591 + if (tcon->tid == buf->Tid) {
17592 +#ifdef CONFIG_CIFS_STATS
17593 + atomic_inc(&tcon->num_oplock_brks);
17594 +#endif
17595 + list_for_each(tmp1,&tcon->openFileList){
17596 + netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
17597 + if(pSMB->Fid == netfile->netfid) {
17598 + struct cifsInodeInfo *pCifsInode;
17599 + read_unlock(&GlobalSMBSeslock);
17600 + cFYI(1,("Matching file id, processing oplock break"));
17601 + pCifsInode =
17602 + CIFS_I(netfile->pInode);
17603 + pCifsInode->clientCanCacheAll = FALSE;
17604 + if(pSMB->OplockLevel == 0)
17605 + pCifsInode->clientCanCacheRead = FALSE;
17606 + pCifsInode->oplockPending = TRUE;
17607 + AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
17608 + cFYI(1,("about to wake up oplock thd"));
17609 + wake_up_process(oplockThread);
17610 + return TRUE;
17611 + }
17612 + }
17613 + read_unlock(&GlobalSMBSeslock);
17614 + cFYI(1,("No matching file for oplock break on connection"));
17615 + return TRUE;
17616 + }
17617 + }
17618 + read_unlock(&GlobalSMBSeslock);
17619 + cFYI(1,("Can not process oplock break for non-existent connection"));
17620 + return TRUE;
17621 +}
17622 +
17623 +void
17624 +dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
17625 +{
17626 + int i, j;
17627 + char debug_line[17];
17628 + unsigned char *buffer;
17629 +
17630 + if (traceSMB == 0)
17631 + return;
17632 +
17633 + buffer = (unsigned char *) smb_buf;
17634 + for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
17635 + if (i % 8 == 0) { /* we have reached the beginning of line */
17636 + printk(KERN_DEBUG "| ");
17637 + j = 0;
17638 + }
17639 + printk("%0#4x ", buffer[i]);
17640 + debug_line[2 * j] = ' ';
17641 + if (isprint(buffer[i]))
17642 + debug_line[1 + (2 * j)] = buffer[i];
17643 + else
17644 + debug_line[1 + (2 * j)] = '_';
17645 +
17646 + if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
17647 + debug_line[16] = 0;
17648 + printk(" | %s\n", debug_line);
17649 + }
17650 + }
17651 + for (; j < 8; j++) {
17652 + printk(" ");
17653 + debug_line[2 * j] = ' ';
17654 + debug_line[1 + (2 * j)] = ' ';
17655 + }
17656 + printk( " | %s\n", debug_line);
17657 + return;
17658 +}
17659 diff -urN linux-2.4.29.old/fs/cifs/netmisc.c linux-2.4.29/fs/cifs/netmisc.c
17660 --- linux-2.4.29.old/fs/cifs/netmisc.c 1970-01-01 01:00:00.000000000 +0100
17661 +++ linux-2.4.29/fs/cifs/netmisc.c 2004-07-14 00:25:05.000000000 +0200
17662 @@ -0,0 +1,905 @@
17663 +/*
17664 + * fs/cifs/netmisc.c
17665 + *
17666 + * Copyright (c) International Business Machines Corp., 2002
17667 + * Author(s): Steve French (sfrench@us.ibm.com)
17668 + *
17669 + * Error mapping routines from Samba libsmb/errormap.c
17670 + * Copyright (C) Andrew Tridgell 2001
17671 + *
17672 + *
17673 + * This program is free software; you can redistribute it and/or modify
17674 + * it under the terms of the GNU General Public License as published by
17675 + * the Free Software Foundation; either version 2 of the License, or
17676 + * (at your option) any later version.
17677 + *
17678 + * This program is distributed in the hope that it will be useful,
17679 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17680 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17681 + * the GNU General Public License for more details.
17682 + *
17683 + * You should have received a copy of the GNU General Public License
17684 + * along with this program; if not, write to the Free Software
17685 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17686 + */
17687 +
17688 +#include <linux/net.h>
17689 +#include <linux/string.h>
17690 +#include <linux/in.h>
17691 +#include <linux/ctype.h>
17692 +#include <linux/fs.h>
17693 +#include <asm/div64.h>
17694 +#include <asm/byteorder.h>
17695 +#include "cifsfs.h"
17696 +#include "cifspdu.h"
17697 +#include "cifsglob.h"
17698 +#include "cifsproto.h"
17699 +#include "smberr.h"
17700 +#include "cifs_debug.h"
17701 +#include "nterr.h"
17702 +
17703 +struct smb_to_posix_error {
17704 + __u16 smb_err;
17705 + int posix_code;
17706 +};
17707 +
17708 +const struct smb_to_posix_error mapping_table_ERRDOS[] = {
17709 + {ERRbadfunc, -EINVAL},
17710 + {ERRbadfile, -ENOENT},
17711 + {ERRbadpath, -ENOTDIR},
17712 + {ERRnofids, -EMFILE},
17713 + {ERRnoaccess, -EACCES},
17714 + {ERRbadfid, -EBADF},
17715 + {ERRbadmcb, -EIO},
17716 + {ERRnomem, -ENOMEM},
17717 + {ERRbadmem, -EFAULT},
17718 + {ERRbadenv, -EFAULT},
17719 + {ERRbadformat, -EINVAL},
17720 + {ERRbadaccess, -EACCES},
17721 + {ERRbaddata, -EIO},
17722 + {ERRbaddrive, -ENXIO},
17723 + {ERRremcd, -EACCES},
17724 + {ERRdiffdevice, -EXDEV},
17725 + {ERRnofiles, -ENOENT},
17726 + {ERRbadshare, -ETXTBSY},
17727 + {ERRlock, -EACCES},
17728 + {ERRunsup, -EINVAL},
17729 + {ERRnosuchshare,-ENXIO},
17730 + {ERRfilexists, -EEXIST},
17731 + {ERRinvparm, -EINVAL},
17732 + {ERRdiskfull, -ENOSPC},
17733 + {ERRinvname, -ENOENT},
17734 + {ERRdirnotempty, -ENOTEMPTY},
17735 + {ERRnotlocked, -ENOLCK},
17736 + {ERRalreadyexists, -EEXIST},
17737 + {ERRmoredata, -EOVERFLOW},
17738 + {ErrQuota, -EDQUOT},
17739 + {ErrNotALink, -ENOLINK},
17740 + {ERRnetlogonNotStarted,-ENOPROTOOPT},
17741 + {0, 0}
17742 +};
17743 +
17744 +const struct smb_to_posix_error mapping_table_ERRSRV[] = {
17745 + {ERRerror, -EIO},
17746 + {ERRbadpw, -EPERM},
17747 + {ERRbadtype, -EREMOTE},
17748 + {ERRaccess, -EACCES},
17749 + {ERRinvtid, -ENXIO},
17750 + {ERRinvnetname, -ENODEV},
17751 + {ERRinvdevice, -ENXIO},
17752 + {ERRqfull, -ENOSPC},
17753 + {ERRqtoobig, -ENOSPC},
17754 + {ERRqeof, -EIO},
17755 + {ERRinvpfid, -EBADF},
17756 + {ERRsmbcmd, -EBADRQC},
17757 + {ERRsrverror, -EIO},
17758 + {ERRbadBID, -EIO},
17759 + {ERRfilespecs, -EINVAL},
17760 + {ERRbadLink, -EIO},
17761 + {ERRbadpermits, -EINVAL},
17762 + {ERRbadPID, -ESRCH},
17763 + {ERRsetattrmode, -EINVAL},
17764 + {ERRpaused, -EHOSTDOWN},
17765 + {ERRmsgoff, -EHOSTDOWN},
17766 + {ERRnoroom, -ENOSPC},
17767 + {ERRrmuns, -EUSERS},
17768 + {ERRtimeout, -ETIME},
17769 + {ERRnoresource, -ENOBUFS},
17770 + {ERRtoomanyuids, -EUSERS},
17771 + {ERRbaduid, -EACCES},
17772 + {ERRusempx, -EIO},
17773 + {ERRusestd, -EIO},
17774 + {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
17775 + {ERRaccountexpired, -EACCES},
17776 + {ERRbadclient, -EACCES},
17777 + {ERRbadLogonTime, -EACCES},
17778 + {ERRpasswordExpired, -EACCES},
17779 + {ERRnosupport, -EINVAL},
17780 + {0, 0}
17781 +};
17782 +
17783 +const struct smb_to_posix_error mapping_table_ERRHRD[] = {
17784 + {0, 0}
17785 +};
17786 +
17787 +/* Convert string containing dotted ip address to binary form */
17788 +/* returns 0 if invalid address */
17789 +
17790 +/* BB add address family, change rc to status flag and return union or for ipv6 */
17791 +/* will need parent to call something like inet_pton to convert ipv6 address BB */
17792 +int
17793 +cifs_inet_pton(int address_family, char *cp,void *dst)
17794 +{
17795 + struct in_addr address;
17796 + int value;
17797 + int digit;
17798 + int i;
17799 + char temp;
17800 + char bytes[4];
17801 + char *end = bytes;
17802 + static const int addr_class_max[4] =
17803 + { 0xffffffff, 0xffffff, 0xffff, 0xff };
17804 +
17805 + if(address_family != AF_INET)
17806 + return -EAFNOSUPPORT;
17807 +
17808 + for (i = 0; i < 4; i++) {
17809 + bytes[i] = 0;
17810 + }
17811 +
17812 + temp = *cp;
17813 +
17814 + while (TRUE) {
17815 + if (!isdigit(temp))
17816 + return 0;
17817 +
17818 + value = 0;
17819 + digit = 0;
17820 + for (;;) {
17821 + if (isascii(temp) && isdigit(temp)) {
17822 + value = (value * 10) + temp - '0';
17823 + temp = *++cp;
17824 + digit = 1;
17825 + } else
17826 + break;
17827 + }
17828 +
17829 + if (temp == '.') {
17830 + if ((end > bytes + 2) || (value > 255))
17831 + return 0;
17832 + *end++ = value;
17833 + temp = *++cp;
17834 + } else if (temp == ':') {
17835 + cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
17836 + return -1;
17837 + } else
17838 + break;
17839 + }
17840 +
17841 + /* check for last characters */
17842 + if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
17843 + if (temp != '\\') {
17844 + if (temp != '/')
17845 + return 0;
17846 + else
17847 + (*cp = '\\'); /* switch the slash the expected way */
17848 + }
17849 + if (value > addr_class_max[end - bytes])
17850 + return 0;
17851 +
17852 + address.s_addr = *((int *) bytes) | htonl(value);
17853 + *((int *)dst) = address.s_addr;
17854 + return 1; /* success */
17855 +}
17856 +
17857 +/*****************************************************************************
17858 +convert a NT status code to a dos class/code
17859 + *****************************************************************************/
17860 +/* NT status -> dos error map */
17861 +static const struct {
17862 + __u8 dos_class;
17863 + __u16 dos_code;
17864 + __u32 ntstatus;
17865 +} ntstatus_to_dos_map[] = {
17866 + {
17867 + ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
17868 + ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
17869 + ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
17870 + ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
17871 + ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
17872 + ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
17873 + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
17874 + ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
17875 + ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
17876 + ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
17877 + ERRDOS, 87, NT_STATUS_INVALID_CID}, {
17878 + ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
17879 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
17880 + ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
17881 + ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
17882 + ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
17883 + ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
17884 + ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
17885 + ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
17886 + ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
17887 + ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
17888 +/* { This NT error code was 'sqashed'
17889 + from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
17890 + during the session setup } */
17891 + {
17892 + ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
17893 + ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
17894 + ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
17895 + ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
17896 + ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
17897 + ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
17898 + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
17899 + ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
17900 + ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
17901 + ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
17902 + ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
17903 +/* { This NT error code was 'sqashed'
17904 + from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
17905 + during the session setup } */
17906 + {
17907 + ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
17908 + ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
17909 + ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
17910 + ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
17911 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
17912 + ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
17913 + ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
17914 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
17915 + ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
17916 + ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
17917 + ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
17918 + ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
17919 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
17920 + ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
17921 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
17922 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
17923 + ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
17924 + ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */
17925 + ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
17926 + ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
17927 + ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
17928 + ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
17929 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
17930 + ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
17931 + ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
17932 + ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
17933 + ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
17934 + ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
17935 + ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
17936 + ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
17937 + ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
17938 + ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
17939 + ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
17940 + ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
17941 + ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
17942 + ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
17943 + ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
17944 + ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
17945 + ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
17946 + ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
17947 + ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
17948 + ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
17949 + ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
17950 + ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
17951 + ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
17952 + ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, {
17953 + ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
17954 + ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
17955 + ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
17956 + ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
17957 + ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
17958 + ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
17959 + ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
17960 + ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
17961 + ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
17962 + ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
17963 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
17964 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
17965 + ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
17966 + ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
17967 + ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
17968 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
17969 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
17970 + ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
17971 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
17972 + ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
17973 +/* { This NT error code was 'sqashed'
17974 + from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
17975 + during the session setup } */
17976 + {
17977 + ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
17978 + ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
17979 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
17980 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
17981 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
17982 + ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
17983 +/* { This NT error code was 'sqashed'
17984 + from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
17985 + during the session setup } */
17986 + {
17987 + ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
17988 + ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
17989 + ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
17990 + ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
17991 + ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
17992 + ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
17993 + ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
17994 + ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
17995 + ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
17996 + ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
17997 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
17998 + ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
17999 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
18000 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
18001 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
18002 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
18003 + ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
18004 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
18005 + ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
18006 + ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
18007 + ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
18008 + ERRDOS, 112, NT_STATUS_DISK_FULL}, {
18009 + ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
18010 + ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
18011 + ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
18012 + ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
18013 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
18014 + ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
18015 + ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
18016 + ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
18017 + ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
18018 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
18019 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
18020 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
18021 + ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
18022 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
18023 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
18024 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
18025 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
18026 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
18027 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
18028 + ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
18029 + ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
18030 + ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
18031 + ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
18032 + ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
18033 + ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
18034 + ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
18035 +/* { This NT error code was 'sqashed'
18036 + from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
18037 + during the session setup } */
18038 + {
18039 + ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
18040 + ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
18041 + ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
18042 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
18043 + ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
18044 + ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
18045 + ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
18046 + ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
18047 + ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
18048 + ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
18049 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
18050 + ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
18051 + ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
18052 + ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
18053 + ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
18054 + ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
18055 + ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
18056 + ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
18057 + ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
18058 + ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
18059 + ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
18060 + ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
18061 + ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
18062 + ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
18063 + ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
18064 + ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
18065 + ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
18066 + ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
18067 + ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
18068 + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
18069 + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
18070 + ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
18071 + ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
18072 + ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
18073 + ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
18074 + ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
18075 + ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
18076 + ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
18077 + ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
18078 + ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
18079 + ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
18080 + ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
18081 + ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
18082 + ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
18083 + ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
18084 + ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
18085 + ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
18086 + ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
18087 + ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
18088 + ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
18089 + ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
18090 + ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
18091 + ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
18092 + ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
18093 + ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
18094 + ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
18095 + ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
18096 + ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
18097 + ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
18098 + ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
18099 + ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
18100 + ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
18101 + ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
18102 + ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
18103 + ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
18104 + ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
18105 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
18106 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
18107 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
18108 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
18109 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
18110 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
18111 + ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
18112 + ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
18113 + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
18114 + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
18115 + ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
18116 + ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
18117 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
18118 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
18119 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
18120 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
18121 + ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
18122 + ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
18123 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
18124 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
18125 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
18126 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
18127 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
18128 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
18129 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
18130 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
18131 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
18132 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
18133 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
18134 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
18135 + ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
18136 + ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
18137 + ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
18138 + ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
18139 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
18140 + ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
18141 + ERRDOS, 203, 0xc0000100}, {
18142 + ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
18143 + ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
18144 + ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
18145 + ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
18146 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
18147 + ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
18148 + ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
18149 + ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
18150 + ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
18151 + ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
18152 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
18153 + ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
18154 + ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
18155 + ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
18156 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
18157 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
18158 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
18159 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
18160 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
18161 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
18162 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
18163 + ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
18164 + ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
18165 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
18166 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
18167 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
18168 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
18169 + ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
18170 + ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
18171 + ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
18172 + ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
18173 + ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
18174 + ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
18175 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
18176 + ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
18177 + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
18178 + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
18179 + ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
18180 + ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
18181 + ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
18182 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
18183 + ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
18184 + ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
18185 + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
18186 + ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
18187 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
18188 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
18189 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
18190 + ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
18191 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
18192 + ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
18193 + ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
18194 + ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
18195 + ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
18196 + ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
18197 + ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
18198 + ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
18199 + ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
18200 + ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
18201 + ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
18202 + ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
18203 + ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
18204 + ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
18205 + ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
18206 + ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
18207 + ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
18208 + ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
18209 + ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
18210 + ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
18211 + ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
18212 + ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
18213 + ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
18214 + ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
18215 + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
18216 + ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
18217 + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
18218 + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
18219 + ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
18220 + ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
18221 + ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
18222 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
18223 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
18224 + ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
18225 + ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
18226 + ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
18227 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
18228 + ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
18229 + ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
18230 + ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
18231 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
18232 + ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
18233 + ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
18234 + ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
18235 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
18236 + ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
18237 + ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
18238 + ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
18239 + ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
18240 + ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
18241 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
18242 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
18243 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
18244 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
18245 + ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
18246 + ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
18247 + ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
18248 + ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
18249 + ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
18250 + ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
18251 + ERRHRD, ERRgeneral, 0xc000016e}, {
18252 + ERRHRD, ERRgeneral, 0xc000016f}, {
18253 + ERRHRD, ERRgeneral, 0xc0000170}, {
18254 + ERRHRD, ERRgeneral, 0xc0000171}, {
18255 + ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
18256 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
18257 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
18258 + ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
18259 + ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
18260 + ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
18261 + ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
18262 + ERRHRD, ERRgeneral, 0xc0000179}, {
18263 + ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
18264 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
18265 + ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
18266 + ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
18267 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
18268 + ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
18269 + ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
18270 + ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
18271 + ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
18272 + ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
18273 + ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
18274 + ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
18275 + ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
18276 + ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
18277 + ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
18278 + ERRDOS, 19, NT_STATUS_TOO_LATE}, {
18279 + ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
18280 +/* { This NT error code was 'sqashed'
18281 + from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
18282 + during the session setup } */
18283 + {
18284 + ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
18285 + ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
18286 + ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
18287 + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
18288 + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
18289 + ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
18290 + ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
18291 + ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
18292 + ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
18293 + ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
18294 + ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
18295 + ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
18296 + ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
18297 + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
18298 + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
18299 + ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
18300 +/* { This NT error code was 'sqashed'
18301 + from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
18302 + during the session setup } */
18303 + {
18304 + ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
18305 + ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
18306 + ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
18307 + ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
18308 + ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
18309 + ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
18310 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
18311 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
18312 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
18313 + ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
18314 + ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
18315 + ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
18316 + ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
18317 + ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
18318 + ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
18319 + ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
18320 + ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
18321 + ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
18322 + ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
18323 + ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
18324 + ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
18325 + ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
18326 + ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
18327 + ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
18328 + ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
18329 + ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
18330 + ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
18331 + ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
18332 + ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
18333 + ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
18334 + ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
18335 + ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
18336 + ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
18337 + ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
18338 + ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
18339 + ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
18340 + ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
18341 + ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
18342 + ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
18343 + ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
18344 + ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
18345 + ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
18346 + ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
18347 + ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
18348 + ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
18349 + ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
18350 + ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
18351 + ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
18352 + ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
18353 + ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
18354 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
18355 + ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
18356 + ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
18357 + ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
18358 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
18359 + ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
18360 + ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
18361 + ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
18362 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
18363 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
18364 + ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
18365 + ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
18366 + ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
18367 + ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
18368 + ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
18369 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
18370 + ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
18371 + ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
18372 + ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
18373 + ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
18374 + ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
18375 + ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
18376 + ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
18377 + ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
18378 + ERRHRD, ERRgeneral, 0xc000024a}, {
18379 + ERRHRD, ERRgeneral, 0xc000024b}, {
18380 + ERRHRD, ERRgeneral, 0xc000024c}, {
18381 + ERRHRD, ERRgeneral, 0xc000024d}, {
18382 + ERRHRD, ERRgeneral, 0xc000024e}, {
18383 + ERRHRD, ERRgeneral, 0xc000024f}, {
18384 + ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
18385 + ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
18386 + ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
18387 + ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
18388 + ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
18389 + ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
18390 + ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
18391 + ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
18392 + ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
18393 + ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
18394 + ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
18395 + ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
18396 + ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
18397 + ERRHRD, ERRgeneral, 0xc000025d}, {
18398 + ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
18399 + ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
18400 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
18401 + ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
18402 + ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
18403 + ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
18404 + ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
18405 + ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
18406 + ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
18407 + ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
18408 + ERRDOS, 21, 0xc000026e}, {
18409 + ERRDOS, 161, 0xc0000281}, {
18410 + ERRDOS, ERRnoaccess, 0xc000028a}, {
18411 + ERRDOS, ERRnoaccess, 0xc000028b}, {
18412 + ERRHRD, ERRgeneral, 0xc000028c}, {
18413 + ERRDOS, ERRnoaccess, 0xc000028d}, {
18414 + ERRDOS, ERRnoaccess, 0xc000028e}, {
18415 + ERRDOS, ERRnoaccess, 0xc000028f}, {
18416 + ERRDOS, ERRnoaccess, 0xc0000290}, {
18417 +ERRDOS, ERRbadfunc, 0xc000029c},};
18418 +
18419 +/*****************************************************************************
18420 + Print an error message from the status code
18421 + *****************************************************************************/
18422 +static void
18423 +cifs_print_status(__u32 status_code)
18424 +{
18425 + int idx = 0;
18426 +
18427 + while (nt_errs[idx].nt_errstr != NULL) {
18428 + if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
18429 + (status_code & 0xFFFFFF)) {
18430 + printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
18431 + status_code,nt_errs[idx].nt_errstr);
18432 + }
18433 + idx++;
18434 + }
18435 + return;
18436 +}
18437 +
18438 +
18439 +static void
18440 +ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
18441 +{
18442 + int i;
18443 + if (ntstatus == 0) {
18444 + *eclass = 0;
18445 + *ecode = 0;
18446 + return;
18447 + }
18448 + for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
18449 + if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
18450 + *eclass = ntstatus_to_dos_map[i].dos_class;
18451 + *ecode = ntstatus_to_dos_map[i].dos_code;
18452 + return;
18453 + }
18454 + }
18455 + *eclass = ERRHRD;
18456 + *ecode = ERRgeneral;
18457 +}
18458 +
18459 +int
18460 +map_smb_to_linux_error(struct smb_hdr *smb)
18461 +{
18462 + unsigned int i;
18463 + int rc = -EIO; /* if transport error smb error may not be set */
18464 + __u8 smberrclass;
18465 + __u16 smberrcode;
18466 +
18467 + /* BB if NT Status codes - map NT BB */
18468 +
18469 + /* old style smb error codes */
18470 + if (smb->Status.CifsError == 0)
18471 + return 0;
18472 +
18473 + if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
18474 + /* translate the newer STATUS codes to old style errors and then to POSIX errors */
18475 + smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
18476 + if(cifsFYI)
18477 + cifs_print_status(smb->Status.CifsError);
18478 + ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
18479 + &smberrcode);
18480 + } else {
18481 + smberrclass = smb->Status.DosError.ErrorClass;
18482 + smb->Status.DosError.Error =
18483 + le16_to_cpu(smb->Status.DosError.Error);
18484 + smberrcode = smb->Status.DosError.Error;
18485 + }
18486 +
18487 + /* old style errors */
18488 +
18489 + /* DOS class smb error codes - map DOS */
18490 + if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
18491 + for (i = 0;
18492 + i <
18493 + sizeof (mapping_table_ERRDOS) /
18494 + sizeof (struct smb_to_posix_error); i++) {
18495 + if (mapping_table_ERRDOS[i].smb_err == 0)
18496 + break;
18497 + else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
18498 + rc = mapping_table_ERRDOS[i].posix_code;
18499 + break;
18500 + }
18501 + /* else try the next error mapping one to see if it will match */
18502 + }
18503 + } else if (smberrclass == ERRSRV) { /* server class of error codes */
18504 + for (i = 0;
18505 + i <
18506 + sizeof (mapping_table_ERRSRV) /
18507 + sizeof (struct smb_to_posix_error); i++) {
18508 + if (mapping_table_ERRSRV[i].smb_err == 0)
18509 + break;
18510 + else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
18511 + rc = mapping_table_ERRSRV[i].posix_code;
18512 + break;
18513 + }
18514 + /* else try the next error mapping one to see if it will match */
18515 + }
18516 + }
18517 + /* else ERRHRD class errors or junk - return EIO */
18518 +
18519 + cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
18520 +
18521 + /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
18522 +
18523 + return rc;
18524 +}
18525 +
18526 +/*
18527 + * calculate the size of the SMB message based on the fixed header
18528 + * portion, the number of word parameters and the data portion of the message
18529 + */
18530 +unsigned int
18531 +smbCalcSize(struct smb_hdr *ptr)
18532 +{
18533 + return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
18534 + BCC(ptr));
18535 +}
18536 +
18537 +/* The following are taken from fs/ntfs/util.c */
18538 +
18539 +#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
18540 +
18541 + /*
18542 + * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
18543 + * into Unix UTC (based 1970-01-01, in seconds).
18544 + */
18545 +time_t
18546 +cifs_NTtimeToUnix(__u64 ntutc)
18547 +{
18548 + /* BB what about the timezone? BB */
18549 +
18550 + /* Subtract the NTFS time offset, then convert to 1s intervals. */
18551 + u64 t;
18552 +
18553 + t = ntutc - NTFS_TIME_OFFSET;
18554 + do_div(t, 10000000);
18555 + return (time_t)t;
18556 +}
18557 +
18558 +/* Convert the Unix UTC into NT UTC. */
18559 +__u64
18560 +cifs_UnixTimeToNT(time_t t)
18561 +{
18562 + __u64 dce_time;
18563 + /* Convert to 100ns intervals and then add the NTFS time offset. */
18564 + dce_time = (__u64) t * 10000000;
18565 + dce_time += NTFS_TIME_OFFSET;
18566 + return dce_time;
18567 +}
18568 diff -urN linux-2.4.29.old/fs/cifs/nterr.c linux-2.4.29/fs/cifs/nterr.c
18569 --- linux-2.4.29.old/fs/cifs/nterr.c 1970-01-01 01:00:00.000000000 +0100
18570 +++ linux-2.4.29/fs/cifs/nterr.c 2004-07-14 00:25:05.000000000 +0200
18571 @@ -0,0 +1,687 @@
18572 +/*
18573 + * Unix SMB/Netbios implementation.
18574 + * Version 1.9.
18575 + * RPC Pipe client / server routines
18576 + * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
18577 + *
18578 + * This program is free software; you can redistribute it and/or modify
18579 + * it under the terms of the GNU General Public License as published by
18580 + * the Free Software Foundation; either version 2 of the License, or
18581 + * (at your option) any later version.
18582 + *
18583 + * This program is distributed in the hope that it will be useful,
18584 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18585 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18586 + * GNU General Public License for more details.
18587 + *
18588 + * You should have received a copy of the GNU General Public License
18589 + * along with this program; if not, write to the Free Software
18590 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18591 + */
18592 +
18593 +/* NT error codes - see nterr.h */
18594 +#include <linux/types.h>
18595 +#include <linux/fs.h>
18596 +#include "nterr.h"
18597 +
18598 +const struct nt_err_code_struct nt_errs[] = {
18599 + {"NT_STATUS_OK", NT_STATUS_OK},
18600 + {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
18601 + {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
18602 + {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
18603 + {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
18604 + {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
18605 + {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
18606 + {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
18607 + {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
18608 + {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
18609 + {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
18610 + {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
18611 + {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
18612 + {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
18613 + {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
18614 + {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
18615 + {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
18616 + {"NT_STATUS_INVALID_DEVICE_REQUEST",
18617 + NT_STATUS_INVALID_DEVICE_REQUEST},
18618 + {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
18619 + {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
18620 + {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
18621 + {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
18622 + {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
18623 + {"NT_STATUS_MORE_PROCESSING_REQUIRED",
18624 + NT_STATUS_MORE_PROCESSING_REQUIRED},
18625 + {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
18626 + {"NT_STATUS_CONFLICTING_ADDRESSES",
18627 + NT_STATUS_CONFLICTING_ADDRESSES},
18628 + {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
18629 + {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
18630 + {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
18631 + NT_STATUS_UNABLE_TO_DELETE_SECTION},
18632 + {"NT_STATUS_INVALID_SYSTEM_SERVICE",
18633 + NT_STATUS_INVALID_SYSTEM_SERVICE},
18634 + {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
18635 + {"NT_STATUS_INVALID_LOCK_SEQUENCE",
18636 + NT_STATUS_INVALID_LOCK_SEQUENCE},
18637 + {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
18638 + {"NT_STATUS_INVALID_FILE_FOR_SECTION",
18639 + NT_STATUS_INVALID_FILE_FOR_SECTION},
18640 + {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
18641 + {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
18642 + {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
18643 + {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
18644 + {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
18645 + NT_STATUS_NONCONTINUABLE_EXCEPTION},
18646 + {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
18647 + {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
18648 + {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
18649 + {"NT_STATUS_INVALID_UNWIND_TARGET",
18650 + NT_STATUS_INVALID_UNWIND_TARGET},
18651 + {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
18652 + {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
18653 + {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
18654 + NT_STATUS_UNABLE_TO_DECOMMIT_VM},
18655 + {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
18656 + {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
18657 + NT_STATUS_INVALID_PORT_ATTRIBUTES},
18658 + {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
18659 + NT_STATUS_PORT_MESSAGE_TOO_LONG},
18660 + {"NT_STATUS_INVALID_PARAMETER_MIX",
18661 + NT_STATUS_INVALID_PARAMETER_MIX},
18662 + {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
18663 + {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
18664 + {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
18665 + {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
18666 + NT_STATUS_OBJECT_NAME_NOT_FOUND},
18667 + {"NT_STATUS_OBJECT_NAME_COLLISION",
18668 + NT_STATUS_OBJECT_NAME_COLLISION},
18669 + {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
18670 + {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
18671 + {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
18672 + NT_STATUS_DEVICE_ALREADY_ATTACHED},
18673 + {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
18674 + {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
18675 + NT_STATUS_OBJECT_PATH_NOT_FOUND},
18676 + {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
18677 + NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
18678 + {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
18679 + {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
18680 + {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
18681 + {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
18682 + {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
18683 + {"NT_STATUS_PORT_CONNECTION_REFUSED",
18684 + NT_STATUS_PORT_CONNECTION_REFUSED},
18685 + {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
18686 + {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
18687 + {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
18688 + {"NT_STATUS_INVALID_PAGE_PROTECTION",
18689 + NT_STATUS_INVALID_PAGE_PROTECTION},
18690 + {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
18691 + {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
18692 + NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
18693 + {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
18694 + {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
18695 + {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
18696 + NT_STATUS_SUSPEND_COUNT_EXCEEDED},
18697 + {"NT_STATUS_THREAD_IS_TERMINATING",
18698 + NT_STATUS_THREAD_IS_TERMINATING},
18699 + {"NT_STATUS_BAD_WORKING_SET_LIMIT",
18700 + NT_STATUS_BAD_WORKING_SET_LIMIT},
18701 + {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
18702 + NT_STATUS_INCOMPATIBLE_FILE_MAP},
18703 + {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
18704 + {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
18705 + {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
18706 + {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
18707 + {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
18708 + {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
18709 + {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
18710 + {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
18711 + {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
18712 + {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
18713 + NT_STATUS_CTL_FILE_NOT_SUPPORTED},
18714 + {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
18715 + {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
18716 + {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
18717 + {"NT_STATUS_INVALID_PRIMARY_GROUP",
18718 + NT_STATUS_INVALID_PRIMARY_GROUP},
18719 + {"NT_STATUS_NO_IMPERSONATION_TOKEN",
18720 + NT_STATUS_NO_IMPERSONATION_TOKEN},
18721 + {"NT_STATUS_CANT_DISABLE_MANDATORY",
18722 + NT_STATUS_CANT_DISABLE_MANDATORY},
18723 + {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
18724 + {"NT_STATUS_NO_SUCH_LOGON_SESSION",
18725 + NT_STATUS_NO_SUCH_LOGON_SESSION},
18726 + {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
18727 + {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
18728 + {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
18729 + {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
18730 + {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
18731 + {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
18732 + {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
18733 + {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
18734 + {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
18735 + {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
18736 + {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
18737 + {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
18738 + {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
18739 + {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
18740 + {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
18741 + {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
18742 + {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
18743 + {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
18744 + {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
18745 + {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
18746 + {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
18747 + NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
18748 + {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
18749 + {"NT_STATUS_INVALID_SUB_AUTHORITY",
18750 + NT_STATUS_INVALID_SUB_AUTHORITY},
18751 + {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
18752 + {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
18753 + {"NT_STATUS_INVALID_SECURITY_DESCR",
18754 + NT_STATUS_INVALID_SECURITY_DESCR},
18755 + {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
18756 + {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
18757 + {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
18758 + {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
18759 + {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
18760 + {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
18761 + {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
18762 + {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
18763 + {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
18764 + NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
18765 + {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
18766 + {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
18767 + {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
18768 + {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
18769 + {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
18770 + {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
18771 + {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
18772 + NT_STATUS_RESOURCE_DATA_NOT_FOUND},
18773 + {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
18774 + NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
18775 + {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
18776 + NT_STATUS_RESOURCE_NAME_NOT_FOUND},
18777 + {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
18778 + NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
18779 + {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
18780 + NT_STATUS_FLOAT_DENORMAL_OPERAND},
18781 + {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
18782 + {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
18783 + {"NT_STATUS_FLOAT_INVALID_OPERATION",
18784 + NT_STATUS_FLOAT_INVALID_OPERATION},
18785 + {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
18786 + {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
18787 + {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
18788 + {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
18789 + NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
18790 + {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
18791 + {"NT_STATUS_PRIVILEGED_INSTRUCTION",
18792 + NT_STATUS_PRIVILEGED_INSTRUCTION},
18793 + {"NT_STATUS_TOO_MANY_PAGING_FILES",
18794 + NT_STATUS_TOO_MANY_PAGING_FILES},
18795 + {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
18796 + {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
18797 + NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
18798 + {"NT_STATUS_INSUFFICIENT_RESOURCES",
18799 + NT_STATUS_INSUFFICIENT_RESOURCES},
18800 + {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
18801 + {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
18802 + {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
18803 + {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
18804 + {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
18805 + {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
18806 + {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
18807 + {"NT_STATUS_MEDIA_WRITE_PROTECTED",
18808 + NT_STATUS_MEDIA_WRITE_PROTECTED},
18809 + {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
18810 + {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
18811 + NT_STATUS_INVALID_GROUP_ATTRIBUTES},
18812 + {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
18813 + NT_STATUS_BAD_IMPERSONATION_LEVEL},
18814 + {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
18815 + {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
18816 + {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
18817 + {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
18818 + NT_STATUS_BAD_MASTER_BOOT_RECORD},
18819 + {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
18820 + NT_STATUS_INSTRUCTION_MISALIGNMENT},
18821 + {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
18822 + NT_STATUS_INSTANCE_NOT_AVAILABLE},
18823 + {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
18824 + {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
18825 + {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
18826 + {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
18827 + {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
18828 + {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
18829 + {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
18830 + {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
18831 + {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
18832 + {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
18833 + {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
18834 + {"NT_STATUS_PROFILING_NOT_STARTED",
18835 + NT_STATUS_PROFILING_NOT_STARTED},
18836 + {"NT_STATUS_PROFILING_NOT_STOPPED",
18837 + NT_STATUS_PROFILING_NOT_STOPPED},
18838 + {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
18839 + {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
18840 + {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
18841 + {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
18842 + {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
18843 + {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
18844 + {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
18845 + {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
18846 + NT_STATUS_DEVICE_DOES_NOT_EXIST},
18847 + {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
18848 + {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
18849 + NT_STATUS_ADAPTER_HARDWARE_ERROR},
18850 + {"NT_STATUS_INVALID_NETWORK_RESPONSE",
18851 + NT_STATUS_INVALID_NETWORK_RESPONSE},
18852 + {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
18853 + NT_STATUS_UNEXPECTED_NETWORK_ERROR},
18854 + {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
18855 + {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
18856 + {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
18857 + {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
18858 + {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
18859 + {"NT_STATUS_NETWORK_ACCESS_DENIED",
18860 + NT_STATUS_NETWORK_ACCESS_DENIED},
18861 + {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
18862 + {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
18863 + {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
18864 + {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
18865 + {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
18866 + {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
18867 + {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
18868 + {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
18869 + {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
18870 + {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
18871 + {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
18872 + {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
18873 + NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
18874 + {"NT_STATUS_NO_SECURITY_ON_OBJECT",
18875 + NT_STATUS_NO_SECURITY_ON_OBJECT},
18876 + {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
18877 + {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
18878 + {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
18879 + NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
18880 + {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
18881 + {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
18882 + {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
18883 + {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
18884 + {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
18885 + {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
18886 + {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
18887 + NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
18888 + {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
18889 + {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
18890 + NT_STATUS_INVALID_OPLOCK_PROTOCOL},
18891 + {"NT_STATUS_INTERNAL_DB_CORRUPTION",
18892 + NT_STATUS_INTERNAL_DB_CORRUPTION},
18893 + {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
18894 + {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
18895 + {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
18896 + NT_STATUS_BAD_DESCRIPTOR_FORMAT},
18897 + {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
18898 + {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
18899 + {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
18900 + NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
18901 + {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
18902 + NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
18903 + {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
18904 + NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
18905 + {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
18906 + {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
18907 + {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
18908 + {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
18909 + {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
18910 + {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
18911 + {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
18912 + {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
18913 + {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
18914 + {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
18915 + {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
18916 + {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
18917 + {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
18918 + {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
18919 + {"NT_STATUS_REDIRECTOR_NOT_STARTED",
18920 + NT_STATUS_REDIRECTOR_NOT_STARTED},
18921 + {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
18922 + {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
18923 + {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
18924 + {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
18925 + {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
18926 + {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
18927 + {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
18928 + {"NT_STATUS_BAD_LOGON_SESSION_STATE",
18929 + NT_STATUS_BAD_LOGON_SESSION_STATE},
18930 + {"NT_STATUS_LOGON_SESSION_COLLISION",
18931 + NT_STATUS_LOGON_SESSION_COLLISION},
18932 + {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
18933 + {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
18934 + {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
18935 + {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
18936 + {"NT_STATUS_PROCESS_IS_TERMINATING",
18937 + NT_STATUS_PROCESS_IS_TERMINATING},
18938 + {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
18939 + {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
18940 + {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
18941 + {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
18942 + {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
18943 + {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
18944 + {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
18945 + NT_STATUS_ABIOS_LID_ALREADY_OWNED},
18946 + {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
18947 + {"NT_STATUS_ABIOS_INVALID_COMMAND",
18948 + NT_STATUS_ABIOS_INVALID_COMMAND},
18949 + {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
18950 + {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
18951 + NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
18952 + {"NT_STATUS_ABIOS_INVALID_SELECTOR",
18953 + NT_STATUS_ABIOS_INVALID_SELECTOR},
18954 + {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
18955 + {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
18956 + {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
18957 + {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
18958 + NT_STATUS_INVALID_LDT_DESCRIPTOR},
18959 + {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
18960 + NT_STATUS_INVALID_IMAGE_NE_FORMAT},
18961 + {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
18962 + {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
18963 + {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
18964 + NT_STATUS_MAPPED_FILE_SIZE_ZERO},
18965 + {"NT_STATUS_TOO_MANY_OPENED_FILES",
18966 + NT_STATUS_TOO_MANY_OPENED_FILES},
18967 + {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
18968 + {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
18969 + {"NT_STATUS_INVALID_COMPUTER_NAME",
18970 + NT_STATUS_INVALID_COMPUTER_NAME},
18971 + {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
18972 + {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
18973 + {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
18974 + {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
18975 + {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
18976 + NT_STATUS_MEMBERS_PRIMARY_GROUP},
18977 + {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
18978 + {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
18979 + {"NT_STATUS_THREAD_NOT_IN_PROCESS",
18980 + NT_STATUS_THREAD_NOT_IN_PROCESS},
18981 + {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
18982 + {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
18983 + NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
18984 + {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
18985 + {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
18986 + NT_STATUS_INVALID_IMAGE_LE_FORMAT},
18987 + {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
18988 + {"NT_STATUS_INVALID_IMAGE_PROTECT",
18989 + NT_STATUS_INVALID_IMAGE_PROTECT},
18990 + {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
18991 + {"NT_STATUS_LOGON_SERVER_CONFLICT",
18992 + NT_STATUS_LOGON_SERVER_CONFLICT},
18993 + {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
18994 + NT_STATUS_TIME_DIFFERENCE_AT_DC},
18995 + {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
18996 + NT_STATUS_SYNCHRONIZATION_REQUIRED},
18997 + {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
18998 + {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
18999 + {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
19000 + {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
19001 + {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
19002 + {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
19003 + {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
19004 + {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
19005 + {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
19006 + {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
19007 + {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
19008 + {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
19009 + {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
19010 + {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
19011 + {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
19012 + {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
19013 + {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
19014 + {"NT_STATUS_PAGEFILE_CREATE_FAILED",
19015 + NT_STATUS_PAGEFILE_CREATE_FAILED},
19016 + {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
19017 + {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
19018 + {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
19019 + {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
19020 + NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
19021 + {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
19022 + {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
19023 + {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
19024 + {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
19025 + {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
19026 + {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
19027 + NT_STATUS_SERIAL_NO_DEVICE_INITED},
19028 + {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
19029 + {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
19030 + {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
19031 + {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
19032 + {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
19033 + {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
19034 + {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
19035 + {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
19036 + {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
19037 + {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
19038 + {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
19039 + NT_STATUS_LOGON_TYPE_NOT_GRANTED},
19040 + {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
19041 + {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
19042 + NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
19043 + {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
19044 + NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
19045 + {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
19046 + {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
19047 + NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
19048 + {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
19049 + {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
19050 + {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
19051 + {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
19052 + {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
19053 + NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
19054 + {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
19055 + NT_STATUS_FLOPPY_WRONG_CYLINDER},
19056 + {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
19057 + {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
19058 + {"NT_STATUS_DISK_RECALIBRATE_FAILED",
19059 + NT_STATUS_DISK_RECALIBRATE_FAILED},
19060 + {"NT_STATUS_DISK_OPERATION_FAILED",
19061 + NT_STATUS_DISK_OPERATION_FAILED},
19062 + {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
19063 + {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
19064 + {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
19065 + {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
19066 + {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
19067 + {"NT_STATUS_DEVICE_NOT_PARTITIONED",
19068 + NT_STATUS_DEVICE_NOT_PARTITIONED},
19069 + {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
19070 + {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
19071 + NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
19072 + {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
19073 + {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
19074 + {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
19075 + {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
19076 + {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
19077 + {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
19078 + {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
19079 + {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
19080 + NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
19081 + {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
19082 + {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
19083 + NT_STATUS_CHILD_MUST_BE_VOLATILE},
19084 + {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
19085 + NT_STATUS_DEVICE_CONFIGURATION_ERROR},
19086 + {"NT_STATUS_DRIVER_INTERNAL_ERROR",
19087 + NT_STATUS_DRIVER_INTERNAL_ERROR},
19088 + {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
19089 + {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
19090 + {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
19091 + NT_STATUS_DEVICE_PROTOCOL_ERROR},
19092 + {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
19093 + {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
19094 + {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
19095 + {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
19096 + {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
19097 + {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
19098 + NT_STATUS_TRUSTED_DOMAIN_FAILURE},
19099 + {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
19100 + NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
19101 + {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
19102 + NT_STATUS_EVENTLOG_FILE_CORRUPT},
19103 + {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
19104 + {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
19105 + {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
19106 + NT_STATUS_MUTANT_LIMIT_EXCEEDED},
19107 + {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
19108 + {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
19109 + {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
19110 + {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
19111 + NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
19112 + {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
19113 + {"NT_STATUS_EVENTLOG_FILE_CHANGED",
19114 + NT_STATUS_EVENTLOG_FILE_CHANGED},
19115 + {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
19116 + NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
19117 + {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
19118 + NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
19119 + {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
19120 + NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
19121 + {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
19122 + NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
19123 + {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
19124 + {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
19125 + {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
19126 + {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
19127 + NT_STATUS_RESOURCE_LANG_NOT_FOUND},
19128 + {"NT_STATUS_INSUFF_SERVER_RESOURCES",
19129 + NT_STATUS_INSUFF_SERVER_RESOURCES},
19130 + {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
19131 + {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
19132 + NT_STATUS_INVALID_ADDRESS_COMPONENT},
19133 + {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
19134 + NT_STATUS_INVALID_ADDRESS_WILDCARD},
19135 + {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
19136 + {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
19137 + NT_STATUS_ADDRESS_ALREADY_EXISTS},
19138 + {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
19139 + {"NT_STATUS_CONNECTION_DISCONNECTED",
19140 + NT_STATUS_CONNECTION_DISCONNECTED},
19141 + {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
19142 + {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
19143 + {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
19144 + {"NT_STATUS_TRANSACTION_TIMED_OUT",
19145 + NT_STATUS_TRANSACTION_TIMED_OUT},
19146 + {"NT_STATUS_TRANSACTION_NO_RELEASE",
19147 + NT_STATUS_TRANSACTION_NO_RELEASE},
19148 + {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
19149 + {"NT_STATUS_TRANSACTION_RESPONDED",
19150 + NT_STATUS_TRANSACTION_RESPONDED},
19151 + {"NT_STATUS_TRANSACTION_INVALID_ID",
19152 + NT_STATUS_TRANSACTION_INVALID_ID},
19153 + {"NT_STATUS_TRANSACTION_INVALID_TYPE",
19154 + NT_STATUS_TRANSACTION_INVALID_TYPE},
19155 + {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
19156 + {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
19157 + {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
19158 + NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
19159 + {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
19160 + {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
19161 + NT_STATUS_SYSTEM_PROCESS_TERMINATED},
19162 + {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
19163 + {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
19164 + NT_STATUS_NO_BROWSER_SERVERS_FOUND},
19165 + {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
19166 + {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
19167 + NT_STATUS_DRIVER_CANCEL_TIMEOUT},
19168 + {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
19169 + NT_STATUS_REPLY_MESSAGE_MISMATCH},
19170 + {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
19171 + {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
19172 + NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
19173 + {"NT_STATUS_LOST_WRITEBEHIND_DATA",
19174 + NT_STATUS_LOST_WRITEBEHIND_DATA},
19175 + {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
19176 + NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
19177 + {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
19178 + {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
19179 + {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
19180 + {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
19181 + {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
19182 + {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
19183 + {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
19184 + {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
19185 + {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
19186 + {"NT_STATUS_RETRY", NT_STATUS_RETRY},
19187 + {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
19188 + {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
19189 + {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
19190 + {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
19191 + {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
19192 + {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
19193 + NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
19194 + {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
19195 + {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
19196 + {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
19197 + {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
19198 + {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
19199 + NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
19200 + {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
19201 + NT_STATUS_ADDRESS_NOT_ASSOCIATED},
19202 + {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
19203 + {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
19204 + {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
19205 + {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
19206 + {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
19207 + {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
19208 + {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
19209 + {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
19210 + {"NT_STATUS_BAD_COMPRESSION_BUFFER",
19211 + NT_STATUS_BAD_COMPRESSION_BUFFER},
19212 + {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
19213 + {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
19214 + {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
19215 + NT_STATUS_TIMER_RESOLUTION_NOT_SET},
19216 + {"NT_STATUS_CONNECTION_COUNT_LIMIT",
19217 + NT_STATUS_CONNECTION_COUNT_LIMIT},
19218 + {"NT_STATUS_LOGIN_TIME_RESTRICTION",
19219 + NT_STATUS_LOGIN_TIME_RESTRICTION},
19220 + {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
19221 + NT_STATUS_LOGIN_WKSTA_RESTRICTION},
19222 + {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
19223 + {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
19224 + NT_STATUS_INSUFFICIENT_LOGON_INFO},
19225 + {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
19226 + {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
19227 + NT_STATUS_BAD_SERVICE_ENTRYPOINT},
19228 + {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
19229 + {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
19230 + {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
19231 + {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
19232 + {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
19233 + {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
19234 + {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
19235 + NT_STATUS_LICENSE_QUOTA_EXCEEDED},
19236 + {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
19237 + {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
19238 + {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
19239 + {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
19240 + {"NT_STATUS_UNSUPPORTED_COMPRESSION",
19241 + NT_STATUS_UNSUPPORTED_COMPRESSION},
19242 + {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
19243 + {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
19244 + NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
19245 + {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
19246 + NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
19247 + {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
19248 + NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
19249 + {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
19250 + {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
19251 + {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
19252 + NT_STATUS_QUOTA_LIST_INCONSISTENT},
19253 + {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
19254 + {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
19255 + {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
19256 + {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
19257 + {NULL, 0}
19258 +};
19259 diff -urN linux-2.4.29.old/fs/cifs/nterr.h linux-2.4.29/fs/cifs/nterr.h
19260 --- linux-2.4.29.old/fs/cifs/nterr.h 1970-01-01 01:00:00.000000000 +0100
19261 +++ linux-2.4.29/fs/cifs/nterr.h 2004-07-14 00:25:05.000000000 +0200
19262 @@ -0,0 +1,556 @@
19263 +/*
19264 + Unix SMB/Netbios implementation.
19265 + Version 1.9.
19266 + NT error code constants
19267 + Copyright (C) Andrew Tridgell 1992-2000
19268 + Copyright (C) John H Terpstra 1996-2000
19269 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000
19270 + Copyright (C) Paul Ashton 1998-2000
19271 +
19272 + This program is free software; you can redistribute it and/or modify
19273 + it under the terms of the GNU General Public License as published by
19274 + the Free Software Foundation; either version 2 of the License, or
19275 + (at your option) any later version.
19276 +
19277 + This program is distributed in the hope that it will be useful,
19278 + but WITHOUT ANY WARRANTY; without even the implied warranty of
19279 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19280 + GNU General Public License for more details.
19281 +
19282 + You should have received a copy of the GNU General Public License
19283 + along with this program; if not, write to the Free Software
19284 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19285 +*/
19286 +
19287 +
19288 +
19289 +#ifndef _NTERR_H
19290 +#define _NTERR_H
19291 +
19292 +struct nt_err_code_struct {
19293 + char *nt_errstr;
19294 + __u32 nt_errcode;
19295 +};
19296 +
19297 +extern const struct nt_err_code_struct nt_errs[];
19298 +
19299 +/* Win32 Status codes. */
19300 +
19301 +#define STATUS_BUFFER_OVERFLOW 0x80000005
19302 +#define STATUS_MORE_ENTRIES 0x0105
19303 +#define ERROR_INVALID_PARAMETER 0x0057
19304 +#define ERROR_INSUFFICIENT_BUFFER 0x007a
19305 +#define STATUS_1804 0x070c
19306 +#define STATUS_NOTIFY_ENUM_DIR 0x010c
19307 +
19308 +/* Win32 Error codes extracted using a loop in smbclient then printing a
19309 + netmon sniff to a file. */
19310 +
19311 +#define NT_STATUS_OK 0x0000
19312 +#define STATUS_SOME_UNMAPPED 0x0107
19313 +#define STATUS_BUFFER_OVERFLOW 0x80000005
19314 +#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
19315 +#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
19316 +#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
19317 +#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
19318 +#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
19319 +#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
19320 +#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
19321 +#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
19322 +#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
19323 +#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
19324 +#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
19325 +#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
19326 +#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
19327 +#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
19328 +#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
19329 +#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
19330 +#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
19331 +#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
19332 +#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
19333 +#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
19334 +#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
19335 +#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
19336 +#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
19337 +#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
19338 +#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
19339 +#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
19340 +#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
19341 +#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
19342 +#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
19343 +#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
19344 +#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
19345 +#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
19346 +#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
19347 +#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
19348 +#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
19349 +#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
19350 +#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
19351 +#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
19352 +#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
19353 +#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
19354 +#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
19355 +#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
19356 +#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
19357 +#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
19358 +#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
19359 +#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
19360 +#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
19361 +#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
19362 +#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
19363 +#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
19364 +#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
19365 +#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
19366 +#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
19367 +#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
19368 +#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
19369 +#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
19370 +#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
19371 +#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
19372 +#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
19373 +#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
19374 +#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
19375 +#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
19376 +#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
19377 +#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
19378 +#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
19379 +#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
19380 +#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
19381 +#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
19382 +#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
19383 +#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
19384 +#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
19385 +#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
19386 +#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
19387 +#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
19388 +#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
19389 +#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
19390 +#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
19391 +#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
19392 +#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
19393 +#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
19394 +#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
19395 +#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
19396 +#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
19397 +#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
19398 +#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
19399 +#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
19400 +#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
19401 +#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
19402 +#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
19403 +#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
19404 +#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
19405 +#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
19406 +#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
19407 +#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
19408 +#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
19409 +#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
19410 +#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
19411 +#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
19412 +#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
19413 +#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
19414 +#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
19415 +#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
19416 +#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
19417 +#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
19418 +#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
19419 +#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
19420 +#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
19421 +#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
19422 +#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
19423 +#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
19424 +#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
19425 +#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
19426 +#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
19427 +#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
19428 +#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
19429 +#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
19430 +#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
19431 +#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
19432 +#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
19433 +#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
19434 +#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
19435 +#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
19436 +#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
19437 +#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
19438 +#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
19439 +#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
19440 +#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
19441 +#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
19442 +#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
19443 +#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
19444 +#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
19445 +#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
19446 +#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
19447 +#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
19448 +#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
19449 +#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
19450 +#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
19451 +#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
19452 +#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
19453 +#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
19454 +#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
19455 +#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
19456 +#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
19457 +#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
19458 +#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
19459 +#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
19460 +#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
19461 +#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
19462 +#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
19463 +#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
19464 +#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
19465 +#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
19466 +#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
19467 +#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
19468 +#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
19469 +#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
19470 +#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
19471 +#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
19472 +#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
19473 +#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
19474 +#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
19475 +#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
19476 +#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
19477 +#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
19478 +#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
19479 +#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
19480 +#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
19481 +#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
19482 +#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
19483 +#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
19484 +#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
19485 +#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
19486 +#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
19487 +#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
19488 +#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
19489 +#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
19490 +#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
19491 +#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
19492 +#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
19493 +#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
19494 +#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
19495 +#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
19496 +#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
19497 +#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
19498 +#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
19499 +#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
19500 +#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
19501 +#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
19502 +#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
19503 +#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
19504 +#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
19505 +#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
19506 +#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
19507 +#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
19508 +#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
19509 +#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
19510 +#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
19511 +#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
19512 +#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
19513 +#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
19514 +#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
19515 +#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
19516 +#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
19517 +#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
19518 +#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
19519 +#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
19520 +#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
19521 +#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
19522 +#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
19523 +#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
19524 +#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
19525 +#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
19526 +#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
19527 +#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
19528 +#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
19529 +#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
19530 +#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
19531 +#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
19532 +#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
19533 +#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
19534 +#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
19535 +#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
19536 +#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
19537 +#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
19538 +#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
19539 +#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
19540 +#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
19541 +#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
19542 +#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
19543 +#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
19544 +#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
19545 +#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
19546 +#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
19547 +#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
19548 +#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
19549 +#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
19550 +#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
19551 +#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
19552 +#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
19553 +#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
19554 +#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
19555 +#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
19556 +#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
19557 +#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
19558 +#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
19559 +#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
19560 +#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
19561 +#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
19562 +#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
19563 +#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
19564 +#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
19565 +#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
19566 +#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
19567 +#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
19568 +#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
19569 +#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
19570 +#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
19571 +#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
19572 +#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
19573 +#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
19574 +#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
19575 +#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
19576 +#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
19577 +#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
19578 +#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
19579 +#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
19580 +#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
19581 +#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
19582 +#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
19583 +#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
19584 +#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
19585 +#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
19586 +#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
19587 +#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
19588 +#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
19589 +#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
19590 +#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
19591 +#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
19592 +#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
19593 +#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
19594 +#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
19595 +#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
19596 +#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
19597 +#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
19598 +#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
19599 +#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
19600 +#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
19601 +#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
19602 +#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
19603 +#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
19604 +#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
19605 +#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
19606 +#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
19607 +#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
19608 +#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
19609 +#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
19610 +#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
19611 +#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
19612 +#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
19613 +#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
19614 +#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
19615 +#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
19616 +#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
19617 +#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
19618 +#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
19619 +#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
19620 +#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
19621 +#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
19622 +#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
19623 +#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
19624 +#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
19625 +#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
19626 +#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
19627 +#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
19628 +#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
19629 +#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
19630 +#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
19631 +#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
19632 +#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
19633 +#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
19634 +#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
19635 +#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
19636 +#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
19637 +#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
19638 +#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
19639 +#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
19640 +#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
19641 +#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
19642 +#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
19643 +#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
19644 +#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
19645 +#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
19646 +#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
19647 +#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
19648 +#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
19649 +#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
19650 +#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
19651 +#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
19652 +#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
19653 +#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
19654 +#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
19655 +#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
19656 +#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
19657 +#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
19658 +#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
19659 +#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
19660 +#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
19661 +#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
19662 +#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
19663 +#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
19664 +#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
19665 +#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
19666 +#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
19667 +#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
19668 +#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
19669 +#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
19670 +#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
19671 +#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
19672 +#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
19673 +#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
19674 +#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
19675 +#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
19676 +#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
19677 +#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
19678 +#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
19679 +#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
19680 +#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
19681 +#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
19682 +#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
19683 +#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
19684 +#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
19685 +#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
19686 +#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
19687 +#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
19688 +#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
19689 +#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
19690 +#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
19691 +#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
19692 +#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
19693 +#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
19694 +#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
19695 +#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
19696 +#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
19697 +#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
19698 +#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
19699 +#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
19700 +#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
19701 +#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
19702 +#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
19703 +#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
19704 +#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
19705 +#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
19706 +#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
19707 +#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
19708 +#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
19709 +#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
19710 +#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
19711 +#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
19712 +#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
19713 +#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
19714 +#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
19715 +#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
19716 +#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
19717 +#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
19718 +#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
19719 +#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
19720 +#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
19721 +#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
19722 +#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
19723 +#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
19724 +#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
19725 +#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
19726 +#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
19727 +#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
19728 +#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
19729 +#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
19730 +#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
19731 +#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
19732 +#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
19733 +#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
19734 +#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
19735 +#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
19736 +#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
19737 +#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
19738 +#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
19739 +#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
19740 +#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
19741 +#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
19742 +#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
19743 +#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
19744 +#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
19745 +#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
19746 +#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
19747 +#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
19748 +#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
19749 +#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
19750 +#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
19751 +#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
19752 +#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
19753 +#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
19754 +#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
19755 +#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
19756 +#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
19757 +#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
19758 +#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
19759 +#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
19760 +#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
19761 +#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
19762 +#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
19763 +#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
19764 +#define NT_STATUS_RETRY 0xC0000000 | 0x022d
19765 +#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
19766 +#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
19767 +#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
19768 +#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
19769 +#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
19770 +#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
19771 +#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
19772 +#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
19773 +#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
19774 +#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
19775 +#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
19776 +#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
19777 +#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
19778 +#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
19779 +#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
19780 +#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
19781 +#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
19782 +#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
19783 +#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
19784 +#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
19785 +#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
19786 +#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
19787 +#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
19788 +#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
19789 +#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
19790 +#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
19791 +#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
19792 +#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
19793 +#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
19794 +#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
19795 +#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
19796 +#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
19797 +#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
19798 +#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
19799 +#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
19800 +#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
19801 +#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
19802 +#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
19803 +#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
19804 +#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
19805 +#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
19806 +#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
19807 +#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
19808 +#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
19809 +#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
19810 +#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
19811 +#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
19812 +#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
19813 +#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
19814 +#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
19815 +#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
19816 +#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
19817 +
19818 +#endif /* _NTERR_H */
19819 diff -urN linux-2.4.29.old/fs/cifs/ntlmssp.h linux-2.4.29/fs/cifs/ntlmssp.h
19820 --- linux-2.4.29.old/fs/cifs/ntlmssp.h 1970-01-01 01:00:00.000000000 +0100
19821 +++ linux-2.4.29/fs/cifs/ntlmssp.h 2004-07-14 00:25:05.000000000 +0200
19822 @@ -0,0 +1,101 @@
19823 +/*
19824 + * fs/cifs/ntlmssp.h
19825 + *
19826 + * Copyright (c) International Business Machines Corp., 2002
19827 + * Author(s): Steve French (sfrench@us.ibm.com)
19828 + *
19829 + * This library is free software; you can redistribute it and/or modify
19830 + * it under the terms of the GNU Lesser General Public License as published
19831 + * by the Free Software Foundation; either version 2.1 of the License, or
19832 + * (at your option) any later version.
19833 + *
19834 + * This library is distributed in the hope that it will be useful,
19835 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19836 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19837 + * the GNU Lesser General Public License for more details.
19838 + *
19839 + * You should have received a copy of the GNU Lesser General Public License
19840 + * along with this library; if not, write to the Free Software
19841 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19842 + */
19843 +
19844 +#pragma pack(1)
19845 +
19846 +#define NTLMSSP_SIGNATURE "NTLMSSP"
19847 +/* Message Types */
19848 +#define NtLmNegotiate 1
19849 +#define NtLmChallenge 2
19850 +#define NtLmAuthenticate 3
19851 +#define UnknownMessage 8
19852 +
19853 +/* Negotiate Flags */
19854 +#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
19855 +#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
19856 +#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
19857 +#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
19858 +#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
19859 +#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
19860 +#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
19861 +#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
19862 +#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
19863 +#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
19864 +#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
19865 +#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
19866 +#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
19867 +#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
19868 +#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
19869 +#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
19870 +#define NTLMSSP_REQUEST_INIT_RESP 0x100000
19871 +#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
19872 +#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
19873 +#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
19874 +#define NTLMSSP_NEGOTIATE_128 0x20000000
19875 +#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
19876 +#define NTLMSSP_NEGOTIATE_56 0x80000000
19877 +
19878 +/* Although typedefs are not commonly used for structure definitions */
19879 +/* in the Linux kernel, in this particular case they are useful */
19880 +/* to more closely match the standards document for NTLMSSP from */
19881 +/* OpenGroup and to make the code more closely match the standard in */
19882 +/* appearance */
19883 +
19884 +typedef struct _SECURITY_BUFFER {
19885 + __u16 Length;
19886 + __u16 MaximumLength;
19887 + __u32 Buffer; /* offset to buffer */
19888 +} SECURITY_BUFFER;
19889 +
19890 +typedef struct _NEGOTIATE_MESSAGE {
19891 + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19892 + __u32 MessageType; /* 1 */
19893 + __u32 NegotiateFlags;
19894 + SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
19895 + SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
19896 + char DomainString[0];
19897 + /* followed by WorkstationString */
19898 +} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
19899 +
19900 +typedef struct _CHALLENGE_MESSAGE {
19901 + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19902 + __u32 MessageType; /* 2 */
19903 + SECURITY_BUFFER TargetName;
19904 + __u32 NegotiateFlags;
19905 + __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
19906 + __u8 Reserved[8];
19907 + SECURITY_BUFFER TargetInfoArray;
19908 +} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
19909 +
19910 +typedef struct _AUTHENTICATE_MESSAGE {
19911 + __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
19912 + __u32 MessageType; /* 3 */
19913 + SECURITY_BUFFER LmChallengeResponse;
19914 + SECURITY_BUFFER NtChallengeResponse;
19915 + SECURITY_BUFFER DomainName;
19916 + SECURITY_BUFFER UserName;
19917 + SECURITY_BUFFER WorkstationName;
19918 + SECURITY_BUFFER SessionKey;
19919 + __u32 NegotiateFlags;
19920 + char UserString[0];
19921 +} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
19922 +
19923 +#pragma pack() /* resume default structure packing */
19924 diff -urN linux-2.4.29.old/fs/cifs/README linux-2.4.29/fs/cifs/README
19925 --- linux-2.4.29.old/fs/cifs/README 1970-01-01 01:00:00.000000000 +0100
19926 +++ linux-2.4.29/fs/cifs/README 2004-07-14 00:25:04.000000000 +0200
19927 @@ -0,0 +1,356 @@
19928 +The CIFS VFS support for Linux supports many advanced network filesystem
19929 +features such as heirarchical dfs like namespace, hardlinks, locking and more.
19930 +It was designed to comply with the SNIA CIFS Technical Reference (which
19931 +supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
19932 +practical interoperability with Windows 2000, Windows XP, Samba and equivalent
19933 +servers.
19934 +
19935 +For questions or bug reports please contact:
19936 + sfrench@samba.org (sfrench@us.ibm.com)
19937 +
19938 +Build instructions:
19939 +==================
19940 +For Linux 2.4:
19941 +1) Get the kernel source (e.g.from http://www.kernel.org)
19942 +and download the cifs vfs source (see the project page
19943 +at http://us1.samba.org/samba/Linux_CIFS_client.html)
19944 +and change directory into the top of the kernel directory
19945 +then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
19946 +to add the cifs vfs to your kernel configure options if
19947 +it has not already been added (e.g. current SuSE and UL
19948 +users do not need to apply the cifs_24.patch since the cifs vfs is
19949 +already in the kernel configure menu) and then
19950 +mkdir linux/fs/cifs and then copy the current cifs vfs files from
19951 +the cifs download to your kernel build directory e.g.
19952 +
19953 + cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
19954 +
19955 +2) make menuconfig (or make xconfig)
19956 +3) select cifs from within the network filesystem choices
19957 +4) save and exit
19958 +5) make dep
19959 +6) make modules (or "make" if CIFS VFS not to be built as a module)
19960 +
19961 +For Linux 2.5:
19962 +1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
19963 +at bk://linux.bkbits.net/linux-2.5) and change directory into the top
19964 +of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
19965 +2) make menuconfig (or make xconfig)
19966 +3) select cifs from within the network filesystem choices
19967 +4) save and exit
19968 +5) make
19969 +
19970 +
19971 +Installation instructions:
19972 +=========================
19973 +If you have built the CIFS vfs as module (successfully) simply
19974 +type "make modules_install" (or if you prefer, manually copy the file to
19975 +the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
19976 +
19977 +If you have built the CIFS vfs into the kernel itself, follow the instructions
19978 +for your distribution on how to install a new kernel (usually you
19979 +would simply type "make install").
19980 +
19981 +If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
19982 +the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
19983 +similar files reside (usually /sbin). Although the helper software is not
19984 +required, mount.cifs is recommended. Eventually the Samba 3.0 utility program
19985 +"net" may also be helpful since it may someday provide easier mount syntax for
19986 +users who are used to Windows e.g. net use <mount point> <UNC name or cifs URL>
19987 +Note that running the Winbind pam/nss module (logon service) on all of your
19988 +Linux clients is useful in mapping Uids and Gids consistently across the
19989 +domain to the proper network user. The mount.cifs mount helper can be
19990 +trivially built from Samba 3.0 or later source e.g. by executing:
19991 +
19992 + gcc samba/source/client/mount.cifs.c -o mount.cifs
19993 +
19994 +Note that when the mount.cifs utility is run suid (allowing user mounts),
19995 +in order to reduce risks, the "nosuid" mount flag is passed in on mount to
19996 +disallow execution of an suid program mounted on the remote target.
19997 +When mount is executed as root, nosuid is not passed in by default,
19998 +and execution of suid programs on the remote target would be enabled
19999 +by default. This can be changed, as with nfs and other filesystems,
20000 +by simply specifying "nosuid" among the mount options. For user mounts
20001 +though to be able to pass the suid flag to mount requires rebuilding
20002 +mount.cifs with the following flag:
20003 +
20004 + gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
20005 +
20006 +There is a corresponding manual page for cifs mounting in the Samba 3.0 and
20007 +later source tree in docs/manpages/mount.cifs.8
20008 +
20009 +Samba Considerations
20010 +====================
20011 +To get the maximum benefit from the CIFS VFS, we recommend using a server that
20012 +supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
20013 +Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
20014 +Note that uid, gid and file permissions will display default values if you do
20015 +not have a server that supports the Unix extensions for CIFS (such as Samba
20016 +2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
20017 +the line:
20018 +
20019 + unix extensions = yes
20020 +
20021 +to your smb.conf file on the server. Note that the following smb.conf settings
20022 +are also useful (on the Samba server) when the majority of clients are Unix or
20023 +Linux:
20024 +
20025 + case sensitive = yes
20026 + delete readonly = yes
20027 + ea support = yes
20028 +
20029 +Note that ea support is required for supporting Linux xattrs.
20030 +Some administrators also change the "map archive" and the "create mask"
20031 +parameters from their default values. Creating special devices (mknod)
20032 +remotely may require specifying a mkdev function to Samba if you are not using
20033 +Samba 3.0.5 or later. For more information on these see the manual pages
20034 +("man smb.conf") on the Samba server system. Note that the cifs vfs,
20035 +unlike the smbfs vfs, does not read the smb.conf on the client system
20036 +(the few optional settings are passed in on mount via -o parameters instead).
20037 +Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
20038 +open files (required for strict POSIX compliance). Windows Servers already
20039 +supported this feature. Samba server does not allow symlinks that refer to files
20040 +outside of the share, so in Samba versions prior to 3.0.5, most symlinks to
20041 +files with absolute paths (ie beginning with slash) such as:
20042 + ln -s /mnt/foo bar
20043 +would be forbidden. Samba 3.0.5 server or later includes the ability to create
20044 +such symlinks safely by converting unsafe symlinks (ie symlinks to server
20045 +files that are outside of the share) to a samba specific format on the server
20046 +that is ignored by local server applications and non-cifs clients and that will
20047 +not be traversed by the Samba server). This is opaque to the Linux client
20048 +application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
20049 +later, but only for remote clients using the CIFS Unix extensions, and will
20050 +be invisbile to Windows clients and typically will not affect local
20051 +applications running on the same server as Samba.
20052 +
20053 +Use instructions:
20054 +================
20055 +Once the CIFS VFS support is built into the kernel or installed as a module
20056 +(cifs.o), you can use mount syntax like the following to access Samba or Windows
20057 +servers:
20058 +
20059 + mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
20060 +
20061 +Before -o the option -v may be specified to make the mount.cifs
20062 +mount helper display the mount steps more verbosely.
20063 +After -o the following commonly used cifs vfs specific options
20064 +are supported:
20065 +
20066 + user=<username>
20067 + pass=<password>
20068 + domain=<domain name>
20069 +
20070 +Other cifs mount options are described below. Use of TCP names (in addition to
20071 +ip addresses) is available if the mount helper (mount.cifs) is installed. If
20072 +you do not trust the server to which are mounted, or if you do not have
20073 +cifs signing enabled (and the physical network is insecure), consider use
20074 +of the standard mount options "noexec" and "nosuid" to reduce the risk of
20075 +running an altered binary on your local system (downloaded from a hostile server
20076 +or altered by a hostile router).
20077 +
20078 +When using the mount helper mount.cifs, passwords may be specified via alternate
20079 +mechanisms, instead of specifying it after -o using the normal "pass=" syntax
20080 +on the command line:
20081 +1) By including it in a credential file. Specify credentials=filename as one
20082 +of the mount options. Credential files contain two lines
20083 + username=someuser
20084 + password=your_password
20085 +2) By specifying the password in the PASSWD environment variable (similarly
20086 +the user name can be taken from the USER environment variable).
20087 +3) By specifying the password in a file by name via PASSWD_FILE
20088 +4) By specifying the password in a file by file descriptor via PASSWD_FD
20089 +
20090 +If no password is provided, mount.cifs will prompt for password entry
20091 +
20092 +Restrictions
20093 +============
20094 +Servers must support the NTLM SMB dialect (which is the most recent, supported
20095 +by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
20096 +Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
20097 +1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
20098 +problem as most servers support this. IPv6 support is planned for the future.
20099 +
20100 +CIFS VFS Mount Options
20101 +======================
20102 +A partial list of the supported mount options follows:
20103 + user The user name to use when trying to establish
20104 + the CIFS session.
20105 + password The user password. If the mount helper is
20106 + installed, the user will be prompted for password
20107 + if it is not supplied.
20108 + ip The ip address of the target server
20109 + unc The target server Universal Network Name (export) to
20110 + mount.
20111 + domain Set the SMB/CIFS workgroup name prepended to the
20112 + username during CIFS session establishment
20113 + uid If CIFS Unix extensions are not supported by the server
20114 + this overrides the default uid for inodes. For mounts to
20115 + servers which do support the CIFS Unix extensions, such
20116 + as a properly configured Samba server, the server provides
20117 + the uid, gid and mode. For servers which do not support
20118 + the Unix extensions, the default uid (and gid) returned on
20119 + lookup of existing files is the uid (gid) of the person
20120 + who executed the mount (root, except when mount.cifs
20121 + is configured setuid for user mounts) unless the "uid="
20122 + (gid) mount option is specified. For the uid (gid) of newly
20123 + created files and directories, ie files created since
20124 + the last mount of the server share, the expected uid
20125 + (gid) is cached as as long as the inode remains in
20126 + memory on the client. Also note that permission
20127 + checks (authorization checks) on accesses to a file occur
20128 + at the server, but there are cases in which an administrator
20129 + may want to restrict at the client as well. For those
20130 + servers which do not report a uid/gid owner
20131 + (such as Windows), permissions can also be checked at the
20132 + client, and a crude form of client side permission checking
20133 + can be enabled by specifying file_mode and dir_mode on
20134 + the client
20135 + gid If CIFS Unix extensions are not supported by the server
20136 + this overrides the default gid for inodes.
20137 + file_mode If CIFS Unix extensions are not supported by the server
20138 + this overrides the default mode for file inodes.
20139 + dir_mode If CIFS Unix extensions are not supported by the server
20140 + this overrides the default mode for directory inodes.
20141 + port attempt to contact the server on this tcp port, before
20142 + trying the usual ports (port 445, then 139).
20143 + iocharset Codepage used to convert local path names to and from
20144 + Unicode. Unicode is used by default for network path
20145 + names if the server supports it. If iocharset is
20146 + not specified then the nls_default specified
20147 + during the local client kernel build will be used.
20148 + If server does not support Unicode, this parameter is
20149 + unused.
20150 + rsize default read size
20151 + wsize default write size
20152 + rw mount the network share read-write (note that the
20153 + server may still consider the share read-only)
20154 + ro mount network share read-only
20155 + version used to distinguish different versions of the
20156 + mount helper utility (not typically needed)
20157 + sep if first mount option (after the -o), overrides
20158 + the comma as the separator between the mount
20159 + parms. e.g.
20160 + -o user=myname,password=mypassword,domain=mydom
20161 + could be passed instead with period as the separator by
20162 + -o sep=.user=myname.password=mypassword.domain=mydom
20163 + this might be useful when comma is contained within username
20164 + or password or domain. This option is less important
20165 + when the cifs mount helper cifs.mount (version 1.1 or later)
20166 + is used.
20167 + nosuid Do not allow remote executables with the suid bit
20168 + program to be executed. This is only meaningful for mounts
20169 + to servers such as Samba which support the CIFS Unix Extensions.
20170 + If you do not trust the servers in your network (your mount
20171 + targets) it is recommended that you specify this option for
20172 + greater security.
20173 + suid Allow remote files on this mountpoint with suid enabled to
20174 + be executed (default for mounts when executed as root,
20175 + nosuid is default for user mounts).
20176 + credentials Although ignored by the cifs kernel component, it is used by
20177 + the mount helper, mount.cifs. When mount.cifs is installed it
20178 + opens and reads the credential file specified in order
20179 + to obtain the userid and password arguments which are passed to
20180 + the cifs vfs.
20181 + guest Although ignored by the kernel component, the mount.cifs
20182 + mount helper will not prompt the user for a password
20183 + if guest is specified on the mount options. If no
20184 + password is specified a null password will be used.
20185 +
20186 +The mount.cifs mount helper also accepts a few mount options before -o
20187 +including:
20188 +
20189 + -S take password from stdin (equivalent to setting the environment
20190 + variable "PASSWD_FD=0"
20191 + -V print mount.cifs version
20192 + -? display simple usage information
20193 +
20194 +With recent 2.6 kernel versions of modutils, the version of the cifs kernel
20195 +module can be displayed via modinfo.
20196 +
20197 +Misc /proc/fs/cifs Flags and Debug Info
20198 +=======================================
20199 +Informational pseudo-files:
20200 +DebugData Displays information about active CIFS sessions
20201 + and shares.
20202 +Stats Lists summary resource usage information as well as per
20203 + share statistics, if CONFIG_CIFS_STATS in enabled
20204 + in the kernel configuration.
20205 +
20206 +Configuration pseudo-files:
20207 +MultiuserMount If set to one, more than one CIFS session to
20208 + the same server ip address can be established
20209 + if more than one uid accesses the same mount
20210 + point and if the uids user/password mapping
20211 + information is available. (default is 0)
20212 +PacketSigningEnabled If set to one, cifs packet signing is enabled
20213 + and will be used if the server requires
20214 + it. If set to two, cifs packet signing is
20215 + required even if the server considers packet
20216 + signing optional. (default 1)
20217 +cifsFYI If set to one, additional debug information is
20218 + logged to the system error log. (default 0)
20219 +ExtendedSecurity If set to one, SPNEGO session establishment
20220 + is allowed which enables more advanced
20221 + secure CIFS session establishment (default 0)
20222 +NTLMV2Enabled If set to one, more secure password hashes
20223 + are used when the server supports them and
20224 + when kerberos is not negotiated (default 0)
20225 +traceSMB If set to one, debug information is logged to the
20226 + system error log with the start of smb requests
20227 + and responses (default 0)
20228 +LookupCacheEnable If set to one, inode information is kept cached
20229 + for one second improving performance of lookups
20230 + (default 1)
20231 +OplockEnabled If set to one, safe distributed caching enabled.
20232 + (default 1)
20233 +LinuxExtensionsEnabled If set to one then the client will attempt to
20234 + use the CIFS "UNIX" extensions which are optional
20235 + protocol enhancements that allow CIFS servers
20236 + to return accurate UID/GID information as well
20237 + as support symbolic links. If you use servers
20238 + such as Samba that support the CIFS Unix
20239 + extensions but do not want to use symbolic link
20240 + support and want to map the uid and gid fields
20241 + to values supplied at mount (rather than the
20242 + actual values, then set this to zero. (default 1)
20243 +
20244 +These experimental features and tracing can be enabled by changing flags in
20245 +/proc/fs/cifs (after the cifs module has been installed or built into the
20246 +kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
20247 +tracing to the kernel message log type:
20248 +
20249 + echo 1 > /proc/fs/cifs/cifsFYI
20250 +
20251 +and for more extensive tracing including the start of smb requests and responses
20252 +
20253 + echo 1 > /proc/fs/cifs/traceSMB
20254 +
20255 +Three other experimental features are under development and to test
20256 +require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
20257 +
20258 + CONFIG_CIFS_QUOTA
20259 +
20260 + CONFIG_CIFS_XATTR
20261 +
20262 + CONFIG_CIFS_FCNTL (fcntl needed for support of directory change
20263 + notification and perhaps later for file leases)
20264 +
20265 +Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData
20266 +if the kernel was configured with cifs statistics enabled. The statistics
20267 +represent the number of successful (ie non-zero return code from the server)
20268 +SMB responses to some of the more common commands (open, delete, mkdir etc.).
20269 +Also recorded is the total bytes read and bytes written to the server for
20270 +that share. Note that due to client caching effects this can be less than the
20271 +number of bytes read and written by the application running on the client.
20272 +The statistics for the number of total SMBs and oplock breaks are different in
20273 +that they represent all for that share, not just those for which the server
20274 +returned success.
20275 +
20276 +Also note that "cat /proc/fs/cifs/DebugData" will display information about
20277 +the active sessions and the shares that are mounted. Note: NTLMv2 enablement
20278 +will not work since they its implementation is not quite complete yet.
20279 +Do not alter these configuration values unless you are doing specific testing.
20280 +Enabling extended security works to Windows 2000 Workstations and XP but not to
20281 +Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
20282 +(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
20283 +complete in the CIFS VFS yet).
20284 diff -urN linux-2.4.29.old/fs/cifs/rfc1002pdu.h linux-2.4.29/fs/cifs/rfc1002pdu.h
20285 --- linux-2.4.29.old/fs/cifs/rfc1002pdu.h 1970-01-01 01:00:00.000000000 +0100
20286 +++ linux-2.4.29/fs/cifs/rfc1002pdu.h 2004-07-14 00:25:05.000000000 +0200
20287 @@ -0,0 +1,79 @@
20288 +/*
20289 + * fs/cifs/rfc1002pdu.h
20290 + *
20291 + * Protocol Data Unit definitions for RFC 1001/1002 support
20292 + *
20293 + * Copyright (c) International Business Machines Corp., 2004
20294 + * Author(s): Steve French (sfrench@us.ibm.com)
20295 + *
20296 + * This library is free software; you can redistribute it and/or modify
20297 + * it under the terms of the GNU Lesser General Public License as published
20298 + * by the Free Software Foundation; either version 2.1 of the License, or
20299 + * (at your option) any later version.
20300 + *
20301 + * This library is distributed in the hope that it will be useful,
20302 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20303 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20304 + * the GNU Lesser General Public License for more details.
20305 + *
20306 + * You should have received a copy of the GNU Lesser General Public License
20307 + * along with this library; if not, write to the Free Software
20308 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20309 + */
20310 +
20311 +#pragma pack(1)
20312 +
20313 +/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
20314 +
20315 + /* RFC 1002 session packet types */
20316 +#define RFC1002_SESSION_MESASAGE 0x00
20317 +#define RFC1002_SESSION_REQUEST 0x81
20318 +#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
20319 +#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
20320 +#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
20321 +#define RFC1002_SESSION_KEEP_ALIVE 0x85
20322 +
20323 + /* RFC 1002 flags (only one defined */
20324 +#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
20325 +
20326 +struct rfc1002_session_packet {
20327 + __u8 type;
20328 + __u8 flags;
20329 + __u16 length;
20330 + union {
20331 + struct {
20332 + __u8 called_len;
20333 + __u8 called_name[32];
20334 + __u8 scope1; /* null */
20335 + __u8 calling_len;
20336 + __u8 calling_name[32];
20337 + __u8 scope2; /* null */
20338 + } session_req;
20339 + struct {
20340 + __u32 retarget_ip_addr;
20341 + __u16 port;
20342 + } retarget_resp;
20343 + __u8 neg_ses_resp_error_code;
20344 + /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
20345 + SESSION_KEEP_ALIVE packet also does not include a trailer.
20346 + Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
20347 + } trailer;
20348 +};
20349 +
20350 +/* Negative Session Response error codes */
20351 +#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
20352 +#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
20353 +#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
20354 +#define RFC1002_INSUFFICIENT_RESOURCE 0x83
20355 +#define RFC1002_UNSPECIFIED_ERROR 0x8F
20356 +
20357 +/* RFC 1002 Datagram service packets are not defined here as they
20358 +are not needed for the network filesystem client unless we plan on
20359 +implementing broadcast resolution of the server ip address (from
20360 +server netbios name). Currently server names are resolved only via DNS
20361 +(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
20362 +
20363 +#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
20364 +
20365 +#pragma pack() /* resume default structure packing */
20366 +
20367 diff -urN linux-2.4.29.old/fs/cifs/smbdes.c linux-2.4.29/fs/cifs/smbdes.c
20368 --- linux-2.4.29.old/fs/cifs/smbdes.c 1970-01-01 01:00:00.000000000 +0100
20369 +++ linux-2.4.29/fs/cifs/smbdes.c 2004-07-14 00:25:05.000000000 +0200
20370 @@ -0,0 +1,408 @@
20371 +/*
20372 + Unix SMB/Netbios implementation.
20373 + Version 1.9.
20374 +
20375 + a partial implementation of DES designed for use in the
20376 + SMB authentication protocol
20377 +
20378 + Copyright (C) Andrew Tridgell 1998
20379 + Modified by Steve French (sfrench@us.ibm.com) 2002,2004
20380 +
20381 + This program is free software; you can redistribute it and/or modify
20382 + it under the terms of the GNU General Public License as published by
20383 + the Free Software Foundation; either version 2 of the License, or
20384 + (at your option) any later version.
20385 +
20386 + This program is distributed in the hope that it will be useful,
20387 + but WITHOUT ANY WARRANTY; without even the implied warranty of
20388 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20389 + GNU General Public License for more details.
20390 +
20391 + You should have received a copy of the GNU General Public License
20392 + along with this program; if not, write to the Free Software
20393 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20394 +*/
20395 +
20396 +/* NOTES:
20397 +
20398 + This code makes no attempt to be fast! In fact, it is a very
20399 + slow implementation
20400 +
20401 + This code is NOT a complete DES implementation. It implements only
20402 + the minimum necessary for SMB authentication, as used by all SMB
20403 + products (including every copy of Microsoft Windows95 ever sold)
20404 +
20405 + In particular, it can only do a unchained forward DES pass. This
20406 + means it is not possible to use this code for encryption/decryption
20407 + of data, instead it is only useful as a "hash" algorithm.
20408 +
20409 + There is no entry point into this code that allows normal DES operation.
20410 +
20411 + I believe this means that this code does not come under ITAR
20412 + regulations but this is NOT a legal opinion. If you are concerned
20413 + about the applicability of ITAR regulations to this code then you
20414 + should confirm it for yourself (and maybe let me know if you come
20415 + up with a different answer to the one above)
20416 +*/
20417 +#include <linux/slab.h>
20418 +#define uchar unsigned char
20419 +
20420 +static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
20421 + 1, 58, 50, 42, 34, 26, 18,
20422 + 10, 2, 59, 51, 43, 35, 27,
20423 + 19, 11, 3, 60, 52, 44, 36,
20424 + 63, 55, 47, 39, 31, 23, 15,
20425 + 7, 62, 54, 46, 38, 30, 22,
20426 + 14, 6, 61, 53, 45, 37, 29,
20427 + 21, 13, 5, 28, 20, 12, 4
20428 +};
20429 +
20430 +static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
20431 + 3, 28, 15, 6, 21, 10,
20432 + 23, 19, 12, 4, 26, 8,
20433 + 16, 7, 27, 20, 13, 2,
20434 + 41, 52, 31, 37, 47, 55,
20435 + 30, 40, 51, 45, 33, 48,
20436 + 44, 49, 39, 56, 34, 53,
20437 + 46, 42, 50, 36, 29, 32
20438 +};
20439 +
20440 +static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
20441 + 60, 52, 44, 36, 28, 20, 12, 4,
20442 + 62, 54, 46, 38, 30, 22, 14, 6,
20443 + 64, 56, 48, 40, 32, 24, 16, 8,
20444 + 57, 49, 41, 33, 25, 17, 9, 1,
20445 + 59, 51, 43, 35, 27, 19, 11, 3,
20446 + 61, 53, 45, 37, 29, 21, 13, 5,
20447 + 63, 55, 47, 39, 31, 23, 15, 7
20448 +};
20449 +
20450 +static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
20451 + 4, 5, 6, 7, 8, 9,
20452 + 8, 9, 10, 11, 12, 13,
20453 + 12, 13, 14, 15, 16, 17,
20454 + 16, 17, 18, 19, 20, 21,
20455 + 20, 21, 22, 23, 24, 25,
20456 + 24, 25, 26, 27, 28, 29,
20457 + 28, 29, 30, 31, 32, 1
20458 +};
20459 +
20460 +static uchar perm5[32] = { 16, 7, 20, 21,
20461 + 29, 12, 28, 17,
20462 + 1, 15, 23, 26,
20463 + 5, 18, 31, 10,
20464 + 2, 8, 24, 14,
20465 + 32, 27, 3, 9,
20466 + 19, 13, 30, 6,
20467 + 22, 11, 4, 25
20468 +};
20469 +
20470 +static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
20471 + 39, 7, 47, 15, 55, 23, 63, 31,
20472 + 38, 6, 46, 14, 54, 22, 62, 30,
20473 + 37, 5, 45, 13, 53, 21, 61, 29,
20474 + 36, 4, 44, 12, 52, 20, 60, 28,
20475 + 35, 3, 43, 11, 51, 19, 59, 27,
20476 + 34, 2, 42, 10, 50, 18, 58, 26,
20477 + 33, 1, 41, 9, 49, 17, 57, 25
20478 +};
20479 +
20480 +static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
20481 +
20482 +static uchar sbox[8][4][16] = {
20483 + {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
20484 + {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
20485 + {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
20486 + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
20487 +
20488 + {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
20489 + {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
20490 + {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
20491 + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
20492 +
20493 + {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
20494 + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
20495 + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
20496 + {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
20497 +
20498 + {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
20499 + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
20500 + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
20501 + {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
20502 +
20503 + {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
20504 + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
20505 + {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
20506 + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
20507 +
20508 + {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
20509 + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
20510 + {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
20511 + {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
20512 +
20513 + {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
20514 + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
20515 + {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
20516 + {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
20517 +
20518 + {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
20519 + {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
20520 + {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
20521 + {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
20522 +};
20523 +
20524 +static void
20525 +permute(char *out, char *in, uchar * p, int n)
20526 +{
20527 + int i;
20528 + for (i = 0; i < n; i++)
20529 + out[i] = in[p[i] - 1];
20530 +}
20531 +
20532 +static void
20533 +lshift(char *d, int count, int n)
20534 +{
20535 + char out[64];
20536 + int i;
20537 + for (i = 0; i < n; i++)
20538 + out[i] = d[(i + count) % n];
20539 + for (i = 0; i < n; i++)
20540 + d[i] = out[i];
20541 +}
20542 +
20543 +static void
20544 +concat(char *out, char *in1, char *in2, int l1, int l2)
20545 +{
20546 + while (l1--)
20547 + *out++ = *in1++;
20548 + while (l2--)
20549 + *out++ = *in2++;
20550 +}
20551 +
20552 +static void
20553 +xor(char *out, char *in1, char *in2, int n)
20554 +{
20555 + int i;
20556 + for (i = 0; i < n; i++)
20557 + out[i] = in1[i] ^ in2[i];
20558 +}
20559 +
20560 +static void
20561 +dohash(char *out, char *in, char *key, int forw)
20562 +{
20563 + int i, j, k;
20564 + char *pk1;
20565 + char c[28];
20566 + char d[28];
20567 + char *cd;
20568 + char ki[16][48];
20569 + char *pd1;
20570 + char l[32], r[32];
20571 + char *rl;
20572 +
20573 + /* Have to reduce stack usage */
20574 + pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
20575 + if(pk1 == NULL)
20576 + return;
20577 +
20578 + cd = pk1 + 56;
20579 + pd1= cd + 56;
20580 + rl = pd1 + 64;
20581 +
20582 + permute(pk1, key, perm1, 56);
20583 +
20584 + for (i = 0; i < 28; i++)
20585 + c[i] = pk1[i];
20586 + for (i = 0; i < 28; i++)
20587 + d[i] = pk1[i + 28];
20588 +
20589 + for (i = 0; i < 16; i++) {
20590 + lshift(c, sc[i], 28);
20591 + lshift(d, sc[i], 28);
20592 +
20593 + concat(cd, c, d, 28, 28);
20594 + permute(ki[i], cd, perm2, 48);
20595 + }
20596 +
20597 + permute(pd1, in, perm3, 64);
20598 +
20599 + for (j = 0; j < 32; j++) {
20600 + l[j] = pd1[j];
20601 + r[j] = pd1[j + 32];
20602 + }
20603 +
20604 + for (i = 0; i < 16; i++) {
20605 + char *er; /* er[48] */
20606 + char *erk; /* erk[48] */
20607 + char b[8][6];
20608 + char *cb; /* cb[32] */
20609 + char *pcb; /* pcb[32] */
20610 + char *r2; /* r2[32] */
20611 +
20612 + er = kmalloc(48+48+32+32+32, GFP_KERNEL);
20613 + if(er == NULL) {
20614 + kfree(pk1);
20615 + return;
20616 + }
20617 + erk = er+48;
20618 + cb = erk+48;
20619 + pcb = cb+32;
20620 + r2 = pcb+32;
20621 +
20622 + permute(er, r, perm4, 48);
20623 +
20624 + xor(erk, er, ki[forw ? i : 15 - i], 48);
20625 +
20626 + for (j = 0; j < 8; j++)
20627 + for (k = 0; k < 6; k++)
20628 + b[j][k] = erk[j * 6 + k];
20629 +
20630 + for (j = 0; j < 8; j++) {
20631 + int m, n;
20632 + m = (b[j][0] << 1) | b[j][5];
20633 +
20634 + n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
20635 + 1) | b[j][4];
20636 +
20637 + for (k = 0; k < 4; k++)
20638 + b[j][k] =
20639 + (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
20640 + }
20641 +
20642 + for (j = 0; j < 8; j++)
20643 + for (k = 0; k < 4; k++)
20644 + cb[j * 4 + k] = b[j][k];
20645 + permute(pcb, cb, perm5, 32);
20646 +
20647 + xor(r2, l, pcb, 32);
20648 +
20649 + for (j = 0; j < 32; j++)
20650 + l[j] = r[j];
20651 +
20652 + for (j = 0; j < 32; j++)
20653 + r[j] = r2[j];
20654 +
20655 + kfree(er);
20656 + }
20657 +
20658 + concat(rl, r, l, 32, 32);
20659 +
20660 + permute(out, rl, perm6, 64);
20661 + kfree(pk1);
20662 +}
20663 +
20664 +static void
20665 +str_to_key(unsigned char *str, unsigned char *key)
20666 +{
20667 + int i;
20668 +
20669 + key[0] = str[0] >> 1;
20670 + key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
20671 + key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
20672 + key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
20673 + key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
20674 + key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
20675 + key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
20676 + key[7] = str[6] & 0x7F;
20677 + for (i = 0; i < 8; i++) {
20678 + key[i] = (key[i] << 1);
20679 + }
20680 +}
20681 +
20682 +static void
20683 +smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
20684 +{
20685 + int i;
20686 + char *outb; /* outb[64] */
20687 + char *inb; /* inb[64] */
20688 + char *keyb; /* keyb[64] */
20689 + unsigned char key2[8];
20690 +
20691 + outb = kmalloc(64 * 3,GFP_KERNEL);
20692 + if(outb == NULL)
20693 + return;
20694 +
20695 + inb = outb + 64;
20696 + keyb = inb + 64;
20697 +
20698 + str_to_key(key, key2);
20699 +
20700 + for (i = 0; i < 64; i++) {
20701 + inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
20702 + keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
20703 + outb[i] = 0;
20704 + }
20705 +
20706 + dohash(outb, inb, keyb, forw);
20707 +
20708 + for (i = 0; i < 8; i++) {
20709 + out[i] = 0;
20710 + }
20711 +
20712 + for (i = 0; i < 64; i++) {
20713 + if (outb[i])
20714 + out[i / 8] |= (1 << (7 - (i % 8)));
20715 + }
20716 + kfree(outb);
20717 +}
20718 +
20719 +void
20720 +E_P16(unsigned char *p14, unsigned char *p16)
20721 +{
20722 + unsigned char sp8[8] =
20723 + { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
20724 + smbhash(p16, sp8, p14, 1);
20725 + smbhash(p16 + 8, sp8, p14 + 7, 1);
20726 +}
20727 +
20728 +void
20729 +E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
20730 +{
20731 + smbhash(p24, c8, p21, 1);
20732 + smbhash(p24 + 8, c8, p21 + 7, 1);
20733 + smbhash(p24 + 16, c8, p21 + 14, 1);
20734 +}
20735 +
20736 +void
20737 +D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
20738 +{
20739 + smbhash(out, in, p14, 0);
20740 + smbhash(out + 8, in + 8, p14 + 7, 0);
20741 +}
20742 +
20743 +void
20744 +E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
20745 +{
20746 + smbhash(out, in, p14, 1);
20747 + smbhash(out + 8, in + 8, p14 + 7, 1);
20748 +}
20749 +
20750 +void
20751 +cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
20752 +{
20753 + unsigned char buf[8];
20754 +
20755 + smbhash(buf, in, key, 1);
20756 + smbhash(out, buf, key + 9, 1);
20757 +}
20758 +
20759 +void
20760 +cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
20761 +{
20762 + unsigned char buf[8];
20763 + static unsigned char key2[8];
20764 +
20765 + smbhash(buf, in, key, 1);
20766 + key2[0] = key[7];
20767 + smbhash(out, buf, key2, 1);
20768 +}
20769 +
20770 +void
20771 +cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
20772 +{
20773 + static unsigned char key2[8];
20774 +
20775 + smbhash(out, in, key, forw);
20776 + key2[0] = key[7];
20777 + smbhash(out + 8, in + 8, key2, forw);
20778 +}
20779 diff -urN linux-2.4.29.old/fs/cifs/smbencrypt.c linux-2.4.29/fs/cifs/smbencrypt.c
20780 --- linux-2.4.29.old/fs/cifs/smbencrypt.c 1970-01-01 01:00:00.000000000 +0100
20781 +++ linux-2.4.29/fs/cifs/smbencrypt.c 2004-07-14 00:25:05.000000000 +0200
20782 @@ -0,0 +1,295 @@
20783 +/*
20784 + Unix SMB/Netbios implementation.
20785 + Version 1.9.
20786 + SMB parameters and setup
20787 + Copyright (C) Andrew Tridgell 1992-2000
20788 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000
20789 + Modified by Jeremy Allison 1995.
20790 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
20791 + Modified by Steve French (sfrench@us.ibm.com) 2002-2003
20792 +
20793 + This program is free software; you can redistribute it and/or modify
20794 + it under the terms of the GNU General Public License as published by
20795 + the Free Software Foundation; either version 2 of the License, or
20796 + (at your option) any later version.
20797 +
20798 + This program is distributed in the hope that it will be useful,
20799 + but WITHOUT ANY WARRANTY; without even the implied warranty of
20800 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20801 + GNU General Public License for more details.
20802 +
20803 + You should have received a copy of the GNU General Public License
20804 + along with this program; if not, write to the Free Software
20805 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20806 +*/
20807 +
20808 +#include <linux/module.h>
20809 +#include <linux/fs.h>
20810 +#include <linux/string.h>
20811 +#include <linux/kernel.h>
20812 +#include <linux/random.h>
20813 +#include "cifs_unicode.h"
20814 +#include "cifspdu.h"
20815 +#include "md5.h"
20816 +#include "cifs_debug.h"
20817 +
20818 +#ifndef FALSE
20819 +#define FALSE 0
20820 +#endif
20821 +#ifndef TRUE
20822 +#define TRUE 1
20823 +#endif
20824 +
20825 +/* following came from the other byteorder.h to avoid include conflicts */
20826 +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
20827 +#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
20828 +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
20829 +
20830 +/*The following definitions come from lib/md4.c */
20831 +
20832 +void mdfour(unsigned char *out, unsigned char *in, int n);
20833 +
20834 +/*The following definitions come from libsmb/smbdes.c */
20835 +
20836 +void E_P16(unsigned char *p14, unsigned char *p16);
20837 +void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
20838 +void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
20839 +void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
20840 +void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
20841 +void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
20842 +void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
20843 + int forw);
20844 +
20845 +/*The following definitions come from libsmb/smbencrypt.c */
20846 +
20847 +void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
20848 +void E_md4hash(const unsigned char *passwd, unsigned char *p16);
20849 +void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
20850 +void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
20851 + unsigned char p24[24]);
20852 +void NTLMSSPOWFencrypt(unsigned char passwd[8],
20853 + unsigned char *ntlmchalresp, unsigned char p24[24]);
20854 +void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
20855 +int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
20856 + int new_pwrd_size, __u32 * new_pw_len);
20857 +
20858 +/*
20859 + This implements the X/Open SMB password encryption
20860 + It takes a password, a 8 byte "crypt key" and puts 24 bytes of
20861 + encrypted password into p24 */
20862 +/* Note that password must be uppercased and null terminated */
20863 +void
20864 +SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
20865 +{
20866 + unsigned char p14[15], p21[21];
20867 +
20868 + memset(p21, '\0', 21);
20869 + memset(p14, '\0', 14);
20870 + strncpy((char *) p14, (char *) passwd, 14);
20871 +
20872 +/* strupper((char *)p14); *//* BB at least uppercase the easy range */
20873 + E_P16(p14, p21);
20874 +
20875 + SMBOWFencrypt(p21, c8, p24);
20876 +
20877 + memset(p14,0,15);
20878 + memset(p21,0,21);
20879 +}
20880 +
20881 +/* Routines for Windows NT MD4 Hash functions. */
20882 +static int
20883 +_my_wcslen(__u16 * str)
20884 +{
20885 + int len = 0;
20886 + while (*str++ != 0)
20887 + len++;
20888 + return len;
20889 +}
20890 +
20891 +/*
20892 + * Convert a string into an NT UNICODE string.
20893 + * Note that regardless of processor type
20894 + * this must be in intel (little-endian)
20895 + * format.
20896 + */
20897 +
20898 +static int
20899 +_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
20900 +{ /* not a very good conversion routine - change/fix */
20901 + int i;
20902 + __u16 val;
20903 +
20904 + for (i = 0; i < len; i++) {
20905 + val = *src;
20906 + SSVAL(dst, 0, val);
20907 + dst++;
20908 + src++;
20909 + if (val == 0)
20910 + break;
20911 + }
20912 + return i;
20913 +}
20914 +
20915 +/*
20916 + * Creates the MD4 Hash of the users password in NT UNICODE.
20917 + */
20918 +
20919 +void
20920 +E_md4hash(const unsigned char *passwd, unsigned char *p16)
20921 +{
20922 + int len;
20923 + __u16 wpwd[129];
20924 +
20925 + /* Password cannot be longer than 128 characters */
20926 + if(passwd) {
20927 + len = strlen((char *) passwd);
20928 + if (len > 128) {
20929 + len = 128;
20930 + }
20931 + /* Password must be converted to NT unicode */
20932 + _my_mbstowcs(wpwd, passwd, len);
20933 + } else
20934 + len = 0;
20935 +
20936 + wpwd[len] = 0; /* Ensure string is null terminated */
20937 + /* Calculate length in bytes */
20938 + len = _my_wcslen(wpwd) * sizeof (__u16);
20939 +
20940 + mdfour(p16, (unsigned char *) wpwd, len);
20941 + memset(wpwd,0,129 * 2);
20942 +}
20943 +
20944 +/* Does both the NT and LM owfs of a user's password */
20945 +void
20946 +nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
20947 +{
20948 + char passwd[514];
20949 +
20950 + memset(passwd, '\0', 514);
20951 + if (strlen(pwd) < 513)
20952 + strcpy(passwd, pwd);
20953 + else
20954 + memcpy(passwd, pwd, 512);
20955 + /* Calculate the MD4 hash (NT compatible) of the password */
20956 + memset(nt_p16, '\0', 16);
20957 + E_md4hash(passwd, nt_p16);
20958 +
20959 + /* Mangle the passwords into Lanman format */
20960 + passwd[14] = '\0';
20961 +/* strupper(passwd); */
20962 +
20963 + /* Calculate the SMB (lanman) hash functions of the password */
20964 +
20965 + memset(p16, '\0', 16);
20966 + E_P16((unsigned char *) passwd, (unsigned char *) p16);
20967 +
20968 + /* clear out local copy of user's password (just being paranoid). */
20969 + memset(passwd, '\0', sizeof (passwd));
20970 +}
20971 +
20972 +/* Does the NTLMv2 owfs of a user's password */
20973 +void
20974 +ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
20975 + const char *domain_n, unsigned char kr_buf[16],
20976 + const struct nls_table *nls_codepage)
20977 +{
20978 + wchar_t * user_u;
20979 + wchar_t * dom_u;
20980 + int user_l, domain_l;
20981 + struct HMACMD5Context ctx;
20982 +
20983 + /* might as well do one alloc to hold both (user_u and dom_u) */
20984 + user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
20985 + if(user_u == NULL)
20986 + return;
20987 + dom_u = user_u + 1024;
20988 +
20989 + /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
20990 + push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
20991 +
20992 + /* BB user and domain may need to be uppercased */
20993 + user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
20994 + domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
20995 +
20996 + user_l++; /* trailing null */
20997 + domain_l++;
20998 +
20999 + hmac_md5_init_limK_to_64(owf, 16, &ctx);
21000 + hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
21001 + hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
21002 + hmac_md5_final(kr_buf, &ctx);
21003 +
21004 + kfree(user_u);
21005 +}
21006 +
21007 +/* Does the des encryption from the NT or LM MD4 hash. */
21008 +void
21009 +SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
21010 + unsigned char p24[24])
21011 +{
21012 + unsigned char p21[21];
21013 +
21014 + memset(p21, '\0', 21);
21015 +
21016 + memcpy(p21, passwd, 16);
21017 + E_P24(p21, c8, p24);
21018 +}
21019 +
21020 +/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
21021 +void
21022 +NTLMSSPOWFencrypt(unsigned char passwd[8],
21023 + unsigned char *ntlmchalresp, unsigned char p24[24])
21024 +{
21025 + unsigned char p21[21];
21026 +
21027 + memset(p21, '\0', 21);
21028 + memcpy(p21, passwd, 8);
21029 + memset(p21 + 8, 0xbd, 8);
21030 +
21031 + E_P24(p21, ntlmchalresp, p24);
21032 +}
21033 +
21034 +/* Does the NT MD4 hash then des encryption. */
21035 +
21036 +void
21037 +SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
21038 +{
21039 + unsigned char p21[21];
21040 +
21041 + memset(p21, '\0', 21);
21042 +
21043 + E_md4hash(passwd, p21);
21044 + SMBOWFencrypt(p21, c8, p24);
21045 +}
21046 +
21047 +/* Does the md5 encryption from the NT hash for NTLMv2. */
21048 +void
21049 +SMBOWFencrypt_ntv2(const unsigned char kr[16],
21050 + const struct data_blob * srv_chal,
21051 + const struct data_blob * cli_chal, unsigned char resp_buf[16])
21052 +{
21053 + struct HMACMD5Context ctx;
21054 +
21055 + hmac_md5_init_limK_to_64(kr, 16, &ctx);
21056 + hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
21057 + hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
21058 + hmac_md5_final(resp_buf, &ctx);
21059 +}
21060 +
21061 +void
21062 +SMBsesskeygen_ntv2(const unsigned char kr[16],
21063 + const unsigned char *nt_resp, __u8 sess_key[16])
21064 +{
21065 + struct HMACMD5Context ctx;
21066 +
21067 + hmac_md5_init_limK_to_64(kr, 16, &ctx);
21068 + hmac_md5_update(nt_resp, 16, &ctx);
21069 + hmac_md5_final((unsigned char *) sess_key, &ctx);
21070 +}
21071 +
21072 +void
21073 +SMBsesskeygen_ntv1(const unsigned char kr[16],
21074 + const unsigned char *nt_resp, __u8 sess_key[16])
21075 +{
21076 + mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
21077 +}
21078 diff -urN linux-2.4.29.old/fs/cifs/smberr.c linux-2.4.29/fs/cifs/smberr.c
21079 --- linux-2.4.29.old/fs/cifs/smberr.c 1970-01-01 01:00:00.000000000 +0100
21080 +++ linux-2.4.29/fs/cifs/smberr.c 2004-07-14 00:25:05.000000000 +0200
21081 @@ -0,0 +1,240 @@
21082 +/*
21083 + Unix SMB/Netbios implementation.
21084 + Version 1.9.
21085 + Copyright (C) Andrew Tridgell 1998
21086 + Copyright (C) Steve French (sfrench@us.ibm.com) 2002
21087 + This program is free software; you can redistribute it and/or modify
21088 + it under the terms of the GNU General Public License as published by
21089 + the Free Software Foundation; either version 2 of the License, or
21090 + (at your option) any later version.
21091 +
21092 + This program is distributed in the hope that it will be useful,
21093 + but WITHOUT ANY WARRANTY; without even the implied warranty of
21094 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21095 + GNU General Public License for more details.
21096 +
21097 + You should have received a copy of the GNU General Public License
21098 + along with this program; if not, write to the Free Software
21099 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21100 +*/
21101 +include "smberr.h"
21102 +#define NO_SYSLOG
21103 +/* error code stuff - put together by Merik Karman
21104 + merik@blackadder.dsh.oz.au */
21105 + typedef const struct {
21106 + char *name;
21107 + int code;
21108 + char *message;
21109 + int posix_code;
21110 +} err_code_struct;
21111 +
21112 +/* Dos Error Messages */
21113 +err_code_struct dos_msgs[] = {
21114 + {"ERRbadfunc", ERRbadfunc, "Invalid function.", -EINVAL},
21115 + {"ERRbadfile", ERRbadfile, "File not found.", -ENOENT},
21116 + {"ERRbadpath", ERRbadpath, "Directory invalid.", -ENOENT},
21117 + {"ERRnofids", ERRnofids, "No file descriptors available", -EMFILE},
21118 + {"ERRnoaccess", ERRnoaccess, "Access denied.", -EACCES},
21119 + {"ERRbadfid", ERRbadfid, "Invalid file handle.", -EBADF},
21120 + {"ERRbadmcb", 7, "Memory control blocks destroyed.", -EIO},
21121 + {"ERRnomem", ERRnomem,
21122 + "Insufficient server memory to perform the requested function.",
21123 + -ENOMEM},
21124 + {"ERRbadmem", ERRbadmem, "Invalid memory block address.", -EFAULT},
21125 + {"ERRbadenv", ERRbadenv, "Invalid environment.", -EFAULT},
21126 + {"ERRbadformat", 11, "Invalid format.", -EINVAL},
21127 + {"ERRbadaccess", ERRbadaccess, "Invalid open mode." - EACCES},
21128 + {"ERRbaddata", ERRbaddata, "Invalid data.", -EIO},
21129 + {"ERR", ERRres, "reserved.", -EIO},
21130 + {"ERRbaddrive", ERRbaddrive, "Invalid drive specified.", -ENXIO},
21131 + {"ERRremcd", ERRremcd,
21132 + "A Delete Directory request attempted to remove the server's current directory.",
21133 + -EIO},
21134 + {"ERRdiffdevice", ERRdiffdevice, "Not same device.", -EXDEV},
21135 + {"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 */
21136 + {"ERRbadshare", ERRbadshare,
21137 + "The sharing mode specified for an Open conflicts with existing FIDs on the file.",
21138 + -EXTBSY},
21139 + {"ERRlock", ERRlock,
21140 + "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.",
21141 + -EACCES},
21142 + {"ERRunsup", ERRunsup, "The operation is unsupported", -EINVAL},
21143 + {"ERRnosuchshare", ERRnosuchshare,
21144 + "You specified an invalid share name", -ENXIO},
21145 + {"ERRfilexists", ERRfilexists,
21146 + "The file named in a Create Directory, Make New File or Link request already exists.",
21147 + -EEXIST},
21148 + {"ERRinvalidname", ERRinvalidname, "Invalid name", -ENOENT},
21149 + {"ERRdiskfull", ERRdiskfull, "Disk full", -ENOSPC}
21150 +
21151 + {"ERRmoredata", ERRmoredata,
21152 + "There is more data to be returned.",},
21153 + {"ERRinvgroup", 2455, "Invalid workgroup (try the -W option)"},
21154 + {NULL, -1, NULL, -EIO}
21155 +};
21156 +
21157 +/* Server Error Messages */
21158 +err_code_struct server_msgs[] = {
21159 + {"ERRerror", 1, "Non-specific error code."},
21160 + {"ERRbadpw", 2,
21161 + "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
21162 + {"ERRbadtype", 3, "reserved."},
21163 + {"ERRaccess", 4,
21164 + "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."},
21165 + {"ERRinvnid", 5,
21166 + "The tree ID (TID) specified in a command was invalid."},
21167 + {"ERRinvnetname", 6, "Invalid network name in tree connect."},
21168 + {"ERRinvdevice", 7,
21169 + "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
21170 + {"ERRqfull", 49,
21171 + "Print queue full (files) -- returned by open print file."},
21172 + {"ERRqtoobig", 50, "Print queue full -- no space."},
21173 + {"ERRqeof", 51, "EOF on print queue dump."},
21174 + {"ERRinvpfid", 52, "Invalid print file FID."},
21175 + {"ERRsmbcmd", 64,
21176 + "The server did not recognize the command received."},
21177 + {"ERRsrverror", 65,
21178 + "The server encountered an internal error, e.g., system file unavailable."},
21179 + {"ERRfilespecs", 67,
21180 + "The file handle (FID) and pathname parameters contained an invalid combination of values."},
21181 + {"ERRreserved", 68, "reserved."},
21182 + {"ERRbadpermits", 69,
21183 + "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
21184 + {"ERRreserved", 70, "reserved."},
21185 + {"ERRsetattrmode", 71,
21186 + "The attribute mode in the Set File Attribute request is invalid."},
21187 + {"ERRpaused", 81, "Server is paused."},
21188 + {"ERRmsgoff", 82, "Not receiving messages."},
21189 + {"ERRnoroom", 83, "No room to buffer message."},
21190 + {"ERRrmuns", 87, "Too many remote user names."},
21191 + {"ERRtimeout", 88, "Operation timed out."},
21192 + {"ERRnoresource", 89,
21193 + "No resources currently available for request."},
21194 + {"ERRtoomanyuids", 90, "Too many UIDs active on this session."},
21195 + {"ERRbaduid", 91,
21196 + "The UID is not known as a valid ID on this session."},
21197 + {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode."},
21198 + {"ERRusestd", 251,
21199 + "Temp unable to support Raw, use standard read/write."},
21200 + {"ERRcontmpx", 252, "Continue in MPX mode."},
21201 + {"ERRreserved", 253, "reserved."},
21202 + {"ERRreserved", 254, "reserved."},
21203 + {"ERRnosupport", 0xFFFF, "Function not supported."},
21204 + {NULL, -1, NULL}
21205 +};
21206 +
21207 +/* Hard Error Messages */
21208 +err_code_struct hard_msgs[] = {
21209 + {"ERRnowrite", 19,
21210 + "Attempt to write on write-protected diskette."},
21211 + {"ERRbadunit", 20, "Unknown unit."},
21212 + {"ERRnotready", 21, "Drive not ready."},
21213 + {"ERRbadcmd", 22, "Unknown command."},
21214 + {"ERRdata", 23, "Data error (CRC)."},
21215 + {"ERRbadreq", 24, "Bad request structure length."},
21216 + {"ERRseek", 25, "Seek error."},
21217 + {"ERRbadmedia", 26, "Unknown media type."},
21218 + {"ERRbadsector", 27, "Sector not found."},
21219 + {"ERRnopaper", 28, "Printer out of paper."},
21220 + {"ERRwrite", 29, "Write fault."},
21221 + {"ERRread", 30, "Read fault."},
21222 + {"ERRgeneral", 31, "General failure."},
21223 + {"ERRbadshare", 32, "An open conflicts with an existing open."},
21224 + {"ERRlock", 33,
21225 + "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."},
21226 + {"ERRwrongdisk", 34, "The wrong disk was found in a drive."},
21227 + {"ERRFCBUnavail", 35, "No FCBs are available to process request."},
21228 + {"ERRsharebufexc", 36, "A sharing buffer has been exceeded."},
21229 + {NULL, -1, NULL}
21230 +};
21231 +
21232 +
21233 +const struct {
21234 + int code;
21235 + char *class;
21236 + err_code_struct *err_msgs;
21237 +} err_classes[] = {
21238 + {
21239 + 0, "SUCCESS", NULL}, {
21240 + 0x01, "ERRDOS", dos_msgs}, {
21241 + 0x02, "ERRSRV", server_msgs}, {
21242 + 0x03, "ERRHRD", hard_msgs}, {
21243 + 0x04, "ERRXOS", NULL}, {
21244 + 0xE1, "ERRRMX1", NULL}, {
21245 + 0xE2, "ERRRMX2", NULL}, {
21246 + 0xE3, "ERRRMX3", NULL}, {
21247 + 0xFF, "ERRCMD", NULL}, {
21248 +-1, NULL, NULL}};
21249 +
21250 +
21251 +/****************************************************************************
21252 +return a SMB error string from a SMB buffer
21253 +****************************************************************************/
21254 +char *smb_dos_errstr(char *inbuf)
21255 +{
21256 + static pstring ret;
21257 + int class = CVAL(inbuf, smb_rcls);
21258 + int num = SVAL(inbuf, smb_err);
21259 + int i, j;
21260 +
21261 + for (i = 0; err_classes[i].class; i++)
21262 + if (err_classes[i].code == class) {
21263 + if (err_classes[i].err_msgs) {
21264 + err_code_struct *err =
21265 + err_classes[i].err_msgs;
21266 + for (j = 0; err[j].name; j++)
21267 + if (num == err[j].code) {
21268 + if (DEBUGLEVEL > 0)
21269 + slprintf(ret,
21270 + sizeof
21271 + (ret) - 1,
21272 + "%s - %s (%s)",
21273 + err_classes
21274 + [i].class,
21275 + err[j].
21276 + name,
21277 + err[j].
21278 + message);
21279 + else
21280 + slprintf(ret,
21281 + sizeof
21282 + (ret) - 1,
21283 + "%s - %s",
21284 + err_classes
21285 + [i].class,
21286 + err[j].
21287 + name);
21288 + return ret;
21289 + }
21290 + }
21291 +
21292 + slprintf(ret, sizeof(ret) - 1, "%s - %d",
21293 + err_classes[i].class, num);
21294 + return ret;
21295 + }
21296 +
21297 + slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",
21298 + class, num);
21299 + return (ret);
21300 +}
21301 +
21302 +
21303 +/*****************************************************************************
21304 + returns an WERROR error message.
21305 + *****************************************************************************/
21306 +char *werror_str(WERROR status)
21307 +{
21308 + static fstring msg;
21309 + slprintf(msg, sizeof(msg), "WIN32 code 0x%08x", W_ERROR_V(status));
21310 + return msg;
21311 +}
21312 +
21313 +
21314 +/*****************************************************************************
21315 +map a unix errno to a win32 error
21316 + *****************************************************************************/
21317 +WERROR map_werror_from_unix(int error)
21318 +{
21319 + NTSTATUS status = map_nt_error_from_unix(error);
21320 + return ntstatus_to_werror(status);
21321 +}
21322 diff -urN linux-2.4.29.old/fs/cifs/smberr.h linux-2.4.29/fs/cifs/smberr.h
21323 --- linux-2.4.29.old/fs/cifs/smberr.h 1970-01-01 01:00:00.000000000 +0100
21324 +++ linux-2.4.29/fs/cifs/smberr.h 2004-07-14 00:25:05.000000000 +0200
21325 @@ -0,0 +1,113 @@
21326 +/*
21327 + * fs/cifs/smberr.h
21328 + *
21329 + * Copyright (c) International Business Machines Corp., 2002
21330 + * Author(s): Steve French (sfrench@us.ibm.com)
21331 + *
21332 + * See Error Codes section of the SNIA CIFS Specification
21333 + * for more information
21334 + *
21335 + * This library is free software; you can redistribute it and/or modify
21336 + * it under the terms of the GNU Lesser General Public License as published
21337 + * by the Free Software Foundation; either version 2.1 of the License, or
21338 + * (at your option) any later version.
21339 + *
21340 + * This library is distributed in the hope that it will be useful,
21341 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21342 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21343 + * the GNU Lesser General Public License for more details.
21344 + *
21345 + * You should have received a copy of the GNU Lesser General Public License
21346 + * along with this library; if not, write to the Free Software
21347 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21348 + */
21349 +
21350 +#define SUCCESS 0 /* The request was successful. */
21351 +#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
21352 +#define ERRSRV 0x02 /* Error is generated by the file server daemon */
21353 +#define ERRHRD 0x03 /* Error is a hardware error. */
21354 +#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
21355 +
21356 +/* The following error codes may be generated with the SUCCESS error class.*/
21357 +
21358 +#define SUCCESS 0 /* The request was successful. */
21359 +
21360 +/* The following error codes may be generated with the ERRDOS error class.*/
21361 +
21362 +#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. */
21363 +#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */
21364 +#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */
21365 +#define ERRnofids 4 /* Too many open files. The server has no file handles available. */
21366 +#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 */
21367 +#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */
21368 +#define ERRbadmcb 7 /* Memory control blocks destroyed. */
21369 +#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */
21370 +#define ERRbadmem 9 /* Invalid memory block address. */
21371 +#define ERRbadenv 10 /* Invalid environment. */
21372 +#define ERRbadformat 11 /* Invalid format. */
21373 +#define ERRbadaccess 12 /* Invalid open mode. */
21374 +#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */
21375 +#define ERRbaddrive 15 /* Invalid drive specified. */
21376 +#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */
21377 +#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */
21378 +#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */
21379 +#define ERRgeneral 31
21380 +#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
21381 +#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. */
21382 +#define ERRunsup 50
21383 +#define ERRnosuchshare 67
21384 +#define ERRfilexists 80 /* The file named in the request already exists. */
21385 +#define ERRinvparm 87
21386 +#define ERRdiskfull 112
21387 +#define ERRinvname 123
21388 +#define ERRdirnotempty 145
21389 +#define ERRnotlocked 158
21390 +#define ERRalreadyexists 183
21391 +#define ERRbadpipe 230
21392 +#define ERRpipebusy 231
21393 +#define ERRpipeclosing 232
21394 +#define ERRnotconnected 233
21395 +#define ERRmoredata 234
21396 +#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
21397 +#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
21398 + was not a link. */
21399 +
21400 +/* Following error codes may be generated with the ERRSRV error
21401 +class.*/
21402 +
21403 +#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. */
21404 +#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
21405 +#define ERRbadtype 3 /* used for indicating DFS referral needed */
21406 +#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */
21407 +#define ERRinvtid 5 /* The Tid specified in a command was invalid. */
21408 +#define ERRinvnetname 6 /* Invalid network name in tree connect. */
21409 +#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
21410 +#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */
21411 +#define ERRqtoobig 50 /* Print queue full -- no space. */
21412 +#define ERRqeof 51 /* EOF on print queue dump */
21413 +#define ERRinvpfid 52 /* Invalid print file FID. */
21414 +#define ERRsmbcmd 64 /* The server did not recognize the command received. */
21415 +#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */
21416 +#define ERRbadBID 66 /* (obsolete) */
21417 +#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */
21418 +#define ERRbadLink 68 /* (obsolete) */
21419 +#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */
21420 +#define ERRbadPID 70
21421 +#define ERRsetattrmode 71 /* attribute (mode) is invalid */
21422 +#define ERRpaused 81 /* Server is paused */
21423 +#define ERRmsgoff 82 /* reserved - messaging off */
21424 +#define ERRnoroom 83 /* reserved - no room for message */
21425 +#define ERRrmuns 87 /* reserved - too many remote names */
21426 +#define ERRtimeout 88 /* operation timed out */
21427 +#define ERRnoresource 89 /* No resources available for request */
21428 +#define ERRtoomanyuids 90 /* Too many UIDs active on this session */
21429 +#define ERRbaduid 91 /* The UID is not known as a valid user */
21430 +#define ERRusempx 250 /* temporarily unable to use raw */
21431 +#define ERRusestd 251 /* temporarily unable to use either raw or mpx */
21432 +#define ERR_NOTIFY_ENUM_DIR 1024
21433 +#define ERRaccountexpired 2239
21434 +#define ERRbadclient 2240
21435 +#define ERRbadLogonTime 2241
21436 +#define ERRpasswordExpired 2242
21437 +#define ERRnetlogonNotStarted 2455
21438 +#define ERRnosupport 0xFFFF
21439 diff -urN linux-2.4.29.old/fs/cifs/TODO linux-2.4.29/fs/cifs/TODO
21440 --- linux-2.4.29.old/fs/cifs/TODO 1970-01-01 01:00:00.000000000 +0100
21441 +++ linux-2.4.29/fs/cifs/TODO 2004-07-14 00:25:04.000000000 +0200
21442 @@ -0,0 +1,106 @@
21443 +version 1.16 May 27, 2004
21444 +
21445 +A Partial List of Missing Features
21446 +==================================
21447 +
21448 +Contributions are welcome. There are plenty of opportunities
21449 +for visible, important contributions to this module. Here
21450 +is a partial list of the known problems and missing features:
21451 +
21452 +a) Support for SecurityDescriptors for chmod/chgrp/chown so
21453 +these can be supported for Windows servers
21454 +
21455 +b) Better pam/winbind integration
21456 +
21457 +c) multi-user mounts - multiplexed sessionsetups over single vc
21458 +(ie tcp session) - prettying up needed
21459 +
21460 +d) Kerberos/SPNEGO session setup support - (started)
21461 +
21462 +e) NTLMv2 authentication (mostly implemented)
21463 +
21464 +f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
21465 +used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
21466 +and raw NTLMSSP already. This is important when enabling
21467 +extended security and mounting to Windows 2003 Servers
21468 +
21469 +f) Directory entry caching relies on a 1 second timer, rather than
21470 +using FindNotify or equivalent. - (started)
21471 +
21472 +g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
21473 +style byte range lock differences
21474 +
21475 +h) quota support
21476 +
21477 +i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
21478 +which will allow us to expose dos attributes as well as real
21479 +ACLs. This support has been started in the current code, but is
21480 +ifdeffed out.
21481 +
21482 +k) finish writepages support (multi-page write behind for improved
21483 +performance) and syncpage
21484 +
21485 +l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
21486 +extra copy in/out of the socket buffers in some cases.
21487 +
21488 +m) finish support for IPv6. This is mostly complete but
21489 +needs a simple inet_pton like function to convert ipv6
21490 +addresses in string representation.
21491 +
21492 +o) Better optimize open (and pathbased setfilesize) to reduce the
21493 +oplock breaks coming from windows srv. Piggyback identical file
21494 +opens on top of each other by incrementing reference count rather
21495 +than resending (helps reduce server resource utilization and avoid
21496 +spurious oplock breaks).
21497 +
21498 +p) Improve performance of readpages by sending more than one read
21499 +at a time when 8 pages or more are requested. Evaluate whether
21500 +reads larger than 16K would be helpful.
21501 +
21502 +q) For support of Windows9x/98 we need to retry failed mounts
21503 +to *SMBSERVER (default server name) with the uppercase hostname
21504 +in the RFC1001 session_init request.
21505 +
21506 +r) Add Extended Attributed support (for storing UID/GID info
21507 +to Windows servers)
21508 +
21509 +s) Finish fcntl D_NOTIFY support so kde and gnome file list windows
21510 +will autorefresh
21511 +
21512 +t) Add GUI tool to configure /proc/fs/cifs settings and for display of
21513 +the CIFS statistics
21514 +
21515 +KNOWN BUGS (updated May 27, 2004)
21516 +====================================
21517 +1) existing symbolic links (Windows reparse points) are recognized but
21518 +can not be created remotely. They are implemented for Samba and those that
21519 +support the CIFS Unix extensions but Samba has a bug currently handling
21520 +symlink text beginning with slash
21521 +2) follow_link and readdir code does not follow dfs junctions
21522 +but recognizes them
21523 +3) create of new files to FAT partitions on Windows servers can
21524 +succeed but still return access denied (appears to be Windows
21525 +server not cifs client problem) and has not been reproduced recently.
21526 +NTFS partitions do not have this problem.
21527 +4) debug connectathon lock test case 10 which fails against
21528 +Samba (may be unmappable due to POSIX to Windows lock model
21529 +differences but worth investigating). Also debug Samba to
21530 +see why lock test case 7 takes longer to complete to Samba
21531 +than to Windows.
21532 +
21533 +Misc testing to do
21534 +==================
21535 +1) check out max path names and max path name components against various server
21536 +types. Try nested symlinks. Return max path name in stat -f information
21537 +
21538 +2) Modify file portion of ltp so it can run against a mounted network
21539 +share and run it against cifs vfs.
21540 +
21541 +3) Additional performance testing and optimization using iozone and similar -
21542 +there are some easy changes that can be done to parallelize sequential writes,
21543 +and when signing is disabled to request larger read sizes (larger than
21544 +negotiated size) and send larger write sizes to modern servers.
21545 +
21546 +4) More exhaustively test the recently added NT4 support against various
21547 +NT4 service pack levels.
21548 +
21549 diff -urN linux-2.4.29.old/fs/cifs/transport.c linux-2.4.29/fs/cifs/transport.c
21550 --- linux-2.4.29.old/fs/cifs/transport.c 1970-01-01 01:00:00.000000000 +0100
21551 +++ linux-2.4.29/fs/cifs/transport.c 2004-07-14 00:25:05.000000000 +0200
21552 @@ -0,0 +1,434 @@
21553 +/*
21554 + * fs/cifs/transport.c
21555 + *
21556 + * Copyright (C) International Business Machines Corp., 2002,2004
21557 + * Author(s): Steve French (sfrench@us.ibm.com)
21558 + *
21559 + * This library is free software; you can redistribute it and/or modify
21560 + * it under the terms of the GNU Lesser General Public License as published
21561 + * by the Free Software Foundation; either version 2.1 of the License, or
21562 + * (at your option) any later version.
21563 + *
21564 + * This library is distributed in the hope that it will be useful,
21565 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21566 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21567 + * the GNU Lesser General Public License for more details.
21568 + *
21569 + * You should have received a copy of the GNU Lesser General Public License
21570 + * along with this library; if not, write to the Free Software
21571 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21572 + */
21573 +
21574 +#include <linux/fs.h>
21575 +#include <linux/list.h>
21576 +#include <linux/wait.h>
21577 +#include <linux/net.h>
21578 +#include <linux/version.h>
21579 +#include <asm/uaccess.h>
21580 +#include <asm/processor.h>
21581 +#include "cifspdu.h"
21582 +#include "cifsglob.h"
21583 +#include "cifsproto.h"
21584 +#include "cifs_debug.h"
21585 +
21586 +extern kmem_cache_t *cifs_mid_cachep;
21587 +extern kmem_cache_t *cifs_oplock_cachep;
21588 +
21589 +struct mid_q_entry *
21590 +AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
21591 +{
21592 + struct mid_q_entry *temp;
21593 +
21594 + if (ses == NULL) {
21595 + cERROR(1, ("Null session passed in to AllocMidQEntry "));
21596 + return NULL;
21597 + }
21598 + if (ses->server == NULL) {
21599 + cERROR(1, ("Null TCP session in AllocMidQEntry"));
21600 + return NULL;
21601 + }
21602 +
21603 + temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
21604 + SLAB_KERNEL);
21605 + if (temp == NULL)
21606 + return temp;
21607 + else {
21608 + memset(temp, 0, sizeof (struct mid_q_entry));
21609 + temp->mid = smb_buffer->Mid; /* always LE */
21610 + temp->pid = current->pid;
21611 + temp->command = smb_buffer->Command;
21612 + cFYI(1, ("For smb_command %d", temp->command));
21613 + do_gettimeofday(&temp->when_sent);
21614 + temp->ses = ses;
21615 + temp->tsk = current;
21616 + }
21617 +
21618 + spin_lock(&GlobalMid_Lock);
21619 + list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
21620 + atomic_inc(&midCount);
21621 + temp->midState = MID_REQUEST_ALLOCATED;
21622 + spin_unlock(&GlobalMid_Lock);
21623 + return temp;
21624 +}
21625 +
21626 +void
21627 +DeleteMidQEntry(struct mid_q_entry *midEntry)
21628 +{
21629 + spin_lock(&GlobalMid_Lock);
21630 + midEntry->midState = MID_FREE;
21631 + list_del(&midEntry->qhead);
21632 + atomic_dec(&midCount);
21633 + spin_unlock(&GlobalMid_Lock);
21634 + cifs_buf_release(midEntry->resp_buf);
21635 + kmem_cache_free(cifs_mid_cachep, midEntry);
21636 +}
21637 +
21638 +struct oplock_q_entry *
21639 +AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
21640 +{
21641 + struct oplock_q_entry *temp;
21642 + if ((pinode== NULL) || (tcon == NULL)) {
21643 + cERROR(1, ("Null parms passed to AllocOplockQEntry"));
21644 + return NULL;
21645 + }
21646 + temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
21647 + SLAB_KERNEL);
21648 + if (temp == NULL)
21649 + return temp;
21650 + else {
21651 + temp->pinode = pinode;
21652 + temp->tcon = tcon;
21653 + temp->netfid = fid;
21654 + spin_lock(&GlobalMid_Lock);
21655 + list_add_tail(&temp->qhead, &GlobalOplock_Q);
21656 + spin_unlock(&GlobalMid_Lock);
21657 + }
21658 + return temp;
21659 +
21660 +}
21661 +
21662 +void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
21663 +{
21664 + spin_lock(&GlobalMid_Lock);
21665 + /* should we check if list empty first? */
21666 + list_del(&oplockEntry->qhead);
21667 + spin_unlock(&GlobalMid_Lock);
21668 + kmem_cache_free(cifs_oplock_cachep, oplockEntry);
21669 +}
21670 +
21671 +int
21672 +smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
21673 + unsigned int smb_buf_length, struct sockaddr *sin)
21674 +{
21675 + int rc = 0;
21676 + int i = 0;
21677 + struct msghdr smb_msg;
21678 + struct iovec iov;
21679 + mm_segment_t temp_fs;
21680 +
21681 + if(ssocket == NULL)
21682 + return -ENOTSOCK; /* BB eventually add reconnect code here */
21683 + iov.iov_base = smb_buffer;
21684 + iov.iov_len = smb_buf_length + 4;
21685 +
21686 + smb_msg.msg_name = sin;
21687 + smb_msg.msg_namelen = sizeof (struct sockaddr);
21688 + smb_msg.msg_iov = &iov;
21689 + smb_msg.msg_iovlen = 1;
21690 + smb_msg.msg_control = NULL;
21691 + smb_msg.msg_controllen = 0;
21692 + smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
21693 +
21694 + /* smb header is converted in header_assemble. bcc and rest of SMB word
21695 + area, and byte area if necessary, is converted to littleendian in
21696 + cifssmb.c and RFC1001 len is converted to bigendian in smb_send
21697 + Flags2 is converted in SendReceive */
21698 +
21699 + smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
21700 + cFYI(1, ("Sending smb of length %d ", smb_buf_length));
21701 + dump_smb(smb_buffer, smb_buf_length + 4);
21702 +
21703 + temp_fs = get_fs(); /* we must turn off socket api parm checking */
21704 + set_fs(get_ds());
21705 + while(iov.iov_len > 0) {
21706 + rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
21707 + if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
21708 + i++;
21709 + if(i > 60) {
21710 + cERROR(1,
21711 + ("sends on sock %p stuck for 30 seconds",
21712 + ssocket));
21713 + rc = -EAGAIN;
21714 + break;
21715 + }
21716 + set_current_state(TASK_INTERRUPTIBLE);
21717 + schedule_timeout(HZ/2);
21718 + continue;
21719 + }
21720 + if (rc < 0)
21721 + break;
21722 + iov.iov_base += rc;
21723 + iov.iov_len -= rc;
21724 + }
21725 + set_fs(temp_fs);
21726 +
21727 + if (rc < 0) {
21728 + cERROR(1,("Error %d sending data on socket to server.", rc));
21729 + } else {
21730 + rc = 0;
21731 + }
21732 +
21733 + return rc;
21734 +}
21735 +
21736 +int
21737 +SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
21738 + struct smb_hdr *in_buf, struct smb_hdr *out_buf,
21739 + int *pbytes_returned, const int long_op)
21740 +{
21741 + int rc = 0;
21742 + unsigned int receive_len;
21743 + long timeout;
21744 + struct mid_q_entry *midQ;
21745 +
21746 + if (ses == NULL) {
21747 + cERROR(1,("Null smb session"));
21748 + return -EIO;
21749 + }
21750 + if(ses->server == NULL) {
21751 + cERROR(1,("Null tcp session"));
21752 + return -EIO;
21753 + }
21754 +
21755 + /* Ensure that we do not send more than 50 overlapping requests
21756 + to the same server. We may make this configurable later or
21757 + use ses->maxReq */
21758 + if(long_op == -1) {
21759 + /* oplock breaks must not be held up */
21760 + atomic_inc(&ses->server->inFlight);
21761 + } else {
21762 + spin_lock(&GlobalMid_Lock);
21763 + while(1) {
21764 + if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){
21765 + spin_unlock(&GlobalMid_Lock);
21766 + wait_event(ses->server->request_q,
21767 + atomic_read(&ses->server->inFlight)
21768 + < CIFS_MAX_REQ);
21769 + spin_lock(&GlobalMid_Lock);
21770 + } else {
21771 + if(ses->server->tcpStatus == CifsExiting) {
21772 + spin_unlock(&GlobalMid_Lock);
21773 + return -ENOENT;
21774 + }
21775 +
21776 + /* can not count locking commands against total since
21777 + they are allowed to block on server */
21778 +
21779 + if(long_op < 3) {
21780 + /* update # of requests on the wire to server */
21781 + atomic_inc(&ses->server->inFlight);
21782 + }
21783 + spin_unlock(&GlobalMid_Lock);
21784 + break;
21785 + }
21786 + }
21787 + }
21788 + /* make sure that we sign in the same order that we send on this socket
21789 + and avoid races inside tcp sendmsg code that could cause corruption
21790 + of smb data */
21791 +
21792 + down(&ses->server->tcpSem);
21793 +
21794 + if (ses->server->tcpStatus == CifsExiting) {
21795 + rc = -ENOENT;
21796 + goto out_unlock;
21797 + } else if (ses->server->tcpStatus == CifsNeedReconnect) {
21798 + cFYI(1,("tcp session dead - return to caller to retry"));
21799 + rc = -EAGAIN;
21800 + goto out_unlock;
21801 + } else if (ses->status != CifsGood) {
21802 + /* check if SMB session is bad because we are setting it up */
21803 + if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
21804 + (in_buf->Command != SMB_COM_NEGOTIATE)) {
21805 + rc = -EAGAIN;
21806 + goto out_unlock;
21807 + } /* else ok - we are setting up session */
21808 + }
21809 + midQ = AllocMidQEntry(in_buf, ses);
21810 + if (midQ == NULL) {
21811 + up(&ses->server->tcpSem);
21812 + /* If not lock req, update # of requests on wire to server */
21813 + if(long_op < 3) {
21814 + atomic_dec(&ses->server->inFlight);
21815 + wake_up(&ses->server->request_q);
21816 + }
21817 + return -ENOMEM;
21818 + }
21819 +
21820 + if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
21821 + up(&ses->server->tcpSem);
21822 + cERROR(1,
21823 + ("Illegal length, greater than maximum frame, %d ",
21824 + in_buf->smb_buf_length));
21825 + DeleteMidQEntry(midQ);
21826 + /* If not lock req, update # of requests on wire to server */
21827 + if(long_op < 3) {
21828 + atomic_dec(&ses->server->inFlight);
21829 + wake_up(&ses->server->request_q);
21830 + }
21831 + return -EIO;
21832 + }
21833 +
21834 + if (in_buf->smb_buf_length > 12)
21835 + in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
21836 +
21837 + rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
21838 +
21839 + midQ->midState = MID_REQUEST_SUBMITTED;
21840 + rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
21841 + (struct sockaddr *) &(ses->server->addr.sockAddr));
21842 + if(rc < 0) {
21843 + DeleteMidQEntry(midQ);
21844 + up(&ses->server->tcpSem);
21845 + /* If not lock req, update # of requests on wire to server */
21846 + if(long_op < 3) {
21847 + atomic_dec(&ses->server->inFlight);
21848 + wake_up(&ses->server->request_q);
21849 + }
21850 + return rc;
21851 + } else
21852 + up(&ses->server->tcpSem);
21853 + if (long_op == -1)
21854 + goto cifs_no_response_exit;
21855 + else if (long_op == 2) /* writes past end of file can take looooong time */
21856 + timeout = 300 * HZ;
21857 + else if (long_op == 1)
21858 + timeout = 45 * HZ; /* should be greater than
21859 + servers oplock break timeout (about 43 seconds) */
21860 + else if (long_op > 2) {
21861 + timeout = MAX_SCHEDULE_TIMEOUT;
21862 + } else
21863 + timeout = 15 * HZ;
21864 + /* wait for 15 seconds or until woken up due to response arriving or
21865 + due to last connection to this server being unmounted */
21866 + if (signal_pending(current)) {
21867 + /* if signal pending do not hold up user for full smb timeout
21868 + but we still give response a change to complete */
21869 + if(midQ->midState & MID_REQUEST_SUBMITTED) {
21870 + set_current_state(TASK_UNINTERRUPTIBLE);
21871 + timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
21872 + }
21873 + } else { /* using normal timeout */
21874 + /* timeout = wait_event_interruptible_timeout(ses->server->response_q,
21875 + (midQ->midState & MID_RESPONSE_RECEIVED) ||
21876 + ((ses->server->tcpStatus != CifsGood) &&
21877 + (ses->server->tcpStatus != CifsNew)),
21878 + timeout); */
21879 + /* Can not allow user interrupts- wreaks havoc with performance */
21880 + if(midQ->midState & MID_REQUEST_SUBMITTED) {
21881 + set_current_state(TASK_UNINTERRUPTIBLE);
21882 + timeout = sleep_on_timeout(&ses->server->response_q,timeout);
21883 + }
21884 + }
21885 +
21886 + spin_lock(&GlobalMid_Lock);
21887 + if (midQ->resp_buf) {
21888 + spin_unlock(&GlobalMid_Lock);
21889 + receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
21890 + } else {
21891 + cERROR(1,("No response buffer"));
21892 + if(midQ->midState == MID_REQUEST_SUBMITTED) {
21893 + if(ses->server->tcpStatus == CifsExiting)
21894 + rc = -EHOSTDOWN;
21895 + else {
21896 + ses->server->tcpStatus = CifsNeedReconnect;
21897 + midQ->midState = MID_RETRY_NEEDED;
21898 + }
21899 + }
21900 +
21901 + if (rc != -EHOSTDOWN) {
21902 + if(midQ->midState == MID_RETRY_NEEDED) {
21903 + rc = -EAGAIN;
21904 + cFYI(1,("marking request for retry"));
21905 + } else {
21906 + rc = -EIO;
21907 + }
21908 + }
21909 + spin_unlock(&GlobalMid_Lock);
21910 + DeleteMidQEntry(midQ);
21911 + /* If not lock req, update # of requests on wire to server */
21912 + if(long_op < 3) {
21913 + atomic_dec(&ses->server->inFlight);
21914 + wake_up(&ses->server->request_q);
21915 + }
21916 + return rc;
21917 + }
21918 +
21919 + if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
21920 + cERROR(1,
21921 + ("Frame too large received. Length: %d Xid: %d",
21922 + receive_len, xid));
21923 + rc = -EIO;
21924 + } else { /* rcvd frame is ok */
21925 +
21926 + if (midQ->resp_buf && out_buf
21927 + && (midQ->midState == MID_RESPONSE_RECEIVED)) {
21928 + memcpy(out_buf, midQ->resp_buf,
21929 + receive_len +
21930 + 4 /* include 4 byte RFC1001 header */ );
21931 +
21932 + dump_smb(out_buf, 92);
21933 + /* convert the length into a more usable form */
21934 + out_buf->smb_buf_length =
21935 + be32_to_cpu(out_buf->smb_buf_length);
21936 + if((out_buf->smb_buf_length > 24) &&
21937 + (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
21938 + rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
21939 + if(rc)
21940 + cFYI(1,("Unexpected signature received from server"));
21941 + }
21942 +
21943 + if (out_buf->smb_buf_length > 12)
21944 + out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
21945 + if (out_buf->smb_buf_length > 28)
21946 + out_buf->Pid = le16_to_cpu(out_buf->Pid);
21947 + if (out_buf->smb_buf_length > 28)
21948 + out_buf->PidHigh =
21949 + le16_to_cpu(out_buf->PidHigh);
21950 +
21951 + *pbytes_returned = out_buf->smb_buf_length;
21952 +
21953 + /* BB special case reconnect tid and reconnect uid here? */
21954 + rc = map_smb_to_linux_error(out_buf);
21955 +
21956 + /* convert ByteCount if necessary */
21957 + if (receive_len >=
21958 + sizeof (struct smb_hdr) -
21959 + 4 /* do not count RFC1001 header */ +
21960 + (2 * out_buf->WordCount) + 2 /* bcc */ )
21961 + BCC(out_buf) = le16_to_cpu(BCC(out_buf));
21962 + } else {
21963 + rc = -EIO;
21964 + cFYI(1,("Bad MID state? "));
21965 + }
21966 + }
21967 +cifs_no_response_exit:
21968 + DeleteMidQEntry(midQ);
21969 +
21970 + if(long_op < 3) {
21971 + atomic_dec(&ses->server->inFlight);
21972 + wake_up(&ses->server->request_q);
21973 + }
21974 +
21975 + return rc;
21976 +
21977 +out_unlock:
21978 + up(&ses->server->tcpSem);
21979 + /* If not lock req, update # of requests on wire to server */
21980 + if(long_op < 3) {
21981 + atomic_dec(&ses->server->inFlight);
21982 + wake_up(&ses->server->request_q);
21983 + }
21984 +
21985 + return rc;
21986 +}
21987 diff -urN linux-2.4.29.old/fs/Config.in linux-2.4.29/fs/Config.in
21988 --- linux-2.4.29.old/fs/Config.in 2005-03-21 19:30:22.000000000 +0100
21989 +++ linux-2.4.29/fs/Config.in 2005-03-21 19:36:51.000000000 +0100
21990 @@ -146,6 +146,10 @@
21991 define_bool CONFIG_LOCKD_V4 y
21992 fi
21993
21994 + dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)' CONFIG_CIFS $CONFIG_INET
21995 + dep_mbool ' CIFS statistics' CONFIG_CIFS_STATS $CONFIG_CIFS
21996 + dep_mbool ' CIFS POSIX Protocol Extensions' CONFIG_CIFS_POSIX $CONFIG_CIFS
21997 +
21998 dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
21999 if [ "$CONFIG_SMB_FS" != "n" ]; then
22000 bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT
22001 diff -urN linux-2.4.29.old/fs/Makefile linux-2.4.29/fs/Makefile
22002 --- linux-2.4.29.old/fs/Makefile 2005-03-21 19:30:22.000000000 +0100
22003 +++ linux-2.4.29/fs/Makefile 2005-03-21 19:36:51.000000000 +0100
22004 @@ -37,6 +37,7 @@
22005 subdir-$(CONFIG_VFAT_FS) += vfat
22006 subdir-$(CONFIG_BFS_FS) += bfs
22007 subdir-$(CONFIG_ISO9660_FS) += isofs
22008 +subdir-$(CONFIG_CIFS) += cifs
22009 subdir-$(CONFIG_DEVFS_FS) += devfs
22010 subdir-$(CONFIG_HFSPLUS_FS) += hfsplus # Before hfs to find wrapped HFS+
22011 subdir-$(CONFIG_HFS_FS) += hfs
22012 diff -urN linux-2.4.29.old/fs/nls/Config.in linux-2.4.29/fs/nls/Config.in
22013 --- linux-2.4.29.old/fs/nls/Config.in 2003-08-25 13:44:43.000000000 +0200
22014 +++ linux-2.4.29/fs/nls/Config.in 2005-03-21 19:36:51.000000000 +0100
22015 @@ -11,6 +11,7 @@
22016
22017 # msdos and Joliet want NLS
22018 if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
22019 + -o "$CONFIG_CIFS" != "n" \
22020 -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
22021 -o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \
22022 -o "$CONFIG_BEFS_FS" != "n" -o "$CONFIG_HFSPLUS_FS" != "n" ]; then