CIFS: Add capability to send SMB2 negotiate message
[linux-3.10.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2010
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
25  /* These are mostly routines that operate on a pathname, or on a tree id     */
26  /* (mounted volume), but there are eight handle based routines which must be */
27  /* treated slightly differently for reconnection purposes since we never     */
28  /* want to reuse a stale file handle and only the caller knows the file info */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <asm/uaccess.h>
39 #include "cifspdu.h"
40 #include "cifsglob.h"
41 #include "cifsacl.h"
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
45 #include "fscache.h"
46
47 #ifdef CONFIG_CIFS_POSIX
48 static struct {
49         int index;
50         char *name;
51 } protocols[] = {
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53         {LANMAN_PROT, "\2LM1.2X002"},
54         {LANMAN2_PROT, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56         {CIFS_PROT, "\2NT LM 0.12"},
57         {POSIX_PROT, "\2POSIX 2"},
58         {BAD_PROT, "\2"}
59 };
60 #else
61 static struct {
62         int index;
63         char *name;
64 } protocols[] = {
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66         {LANMAN_PROT, "\2LM1.2X002"},
67         {LANMAN2_PROT, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69         {CIFS_PROT, "\2NT LM 0.12"},
70         {BAD_PROT, "\2"}
71 };
72 #endif
73
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
78 #else
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
81 #else /* not posix */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
84 #else
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
88
89 #ifdef CONFIG_HIGHMEM
90 /*
91  * On arches that have high memory, kmap address space is limited. By
92  * serializing the kmap operations on those arches, we ensure that we don't
93  * end up with a bunch of threads in writeback with partially mapped page
94  * arrays, stuck waiting for kmap to come back. That situation prevents
95  * progress and can deadlock.
96  */
97 static DEFINE_MUTEX(cifs_kmap_mutex);
98
99 static inline void
100 cifs_kmap_lock(void)
101 {
102         mutex_lock(&cifs_kmap_mutex);
103 }
104
105 static inline void
106 cifs_kmap_unlock(void)
107 {
108         mutex_unlock(&cifs_kmap_mutex);
109 }
110 #else /* !CONFIG_HIGHMEM */
111 #define cifs_kmap_lock() do { ; } while(0)
112 #define cifs_kmap_unlock() do { ; } while(0)
113 #endif /* CONFIG_HIGHMEM */
114
115 /* Mark as invalid, all open files on tree connections since they
116    were closed when session to server was lost */
117 static void mark_open_files_invalid(struct cifs_tcon *pTcon)
118 {
119         struct cifsFileInfo *open_file = NULL;
120         struct list_head *tmp;
121         struct list_head *tmp1;
122
123 /* list all files open on tree connection and mark them invalid */
124         spin_lock(&cifs_file_list_lock);
125         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
126                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
127                 open_file->invalidHandle = true;
128                 open_file->oplock_break_cancelled = true;
129         }
130         spin_unlock(&cifs_file_list_lock);
131         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
132            to this tcon */
133 }
134
135 /* reconnect the socket, tcon, and smb session if needed */
136 static int
137 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
138 {
139         int rc;
140         struct cifs_ses *ses;
141         struct TCP_Server_Info *server;
142         struct nls_table *nls_codepage;
143
144         /*
145          * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
146          * tcp and smb session status done differently for those three - in the
147          * calling routine
148          */
149         if (!tcon)
150                 return 0;
151
152         ses = tcon->ses;
153         server = ses->server;
154
155         /*
156          * only tree disconnect, open, and write, (and ulogoff which does not
157          * have tcon) are allowed as we start force umount
158          */
159         if (tcon->tidStatus == CifsExiting) {
160                 if (smb_command != SMB_COM_WRITE_ANDX &&
161                     smb_command != SMB_COM_OPEN_ANDX &&
162                     smb_command != SMB_COM_TREE_DISCONNECT) {
163                         cFYI(1, "can not send cmd %d while umounting",
164                                 smb_command);
165                         return -ENODEV;
166                 }
167         }
168
169         /*
170          * Give demultiplex thread up to 10 seconds to reconnect, should be
171          * greater than cifs socket timeout which is 7 seconds
172          */
173         while (server->tcpStatus == CifsNeedReconnect) {
174                 wait_event_interruptible_timeout(server->response_q,
175                         (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
176
177                 /* are we still trying to reconnect? */
178                 if (server->tcpStatus != CifsNeedReconnect)
179                         break;
180
181                 /*
182                  * on "soft" mounts we wait once. Hard mounts keep
183                  * retrying until process is killed or server comes
184                  * back on-line
185                  */
186                 if (!tcon->retry) {
187                         cFYI(1, "gave up waiting on reconnect in smb_init");
188                         return -EHOSTDOWN;
189                 }
190         }
191
192         if (!ses->need_reconnect && !tcon->need_reconnect)
193                 return 0;
194
195         nls_codepage = load_nls_default();
196
197         /*
198          * need to prevent multiple threads trying to simultaneously
199          * reconnect the same SMB session
200          */
201         mutex_lock(&ses->session_mutex);
202         rc = cifs_negotiate_protocol(0, ses);
203         if (rc == 0 && ses->need_reconnect)
204                 rc = cifs_setup_session(0, ses, nls_codepage);
205
206         /* do we need to reconnect tcon? */
207         if (rc || !tcon->need_reconnect) {
208                 mutex_unlock(&ses->session_mutex);
209                 goto out;
210         }
211
212         mark_open_files_invalid(tcon);
213         rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
214         mutex_unlock(&ses->session_mutex);
215         cFYI(1, "reconnect tcon rc = %d", rc);
216
217         if (rc)
218                 goto out;
219
220         /*
221          * FIXME: check if wsize needs updated due to negotiated smb buffer
222          *        size shrinking
223          */
224         atomic_inc(&tconInfoReconnectCount);
225
226         /* tell server Unix caps we support */
227         if (ses->capabilities & CAP_UNIX)
228                 reset_cifs_unix_caps(0, tcon, NULL, NULL);
229
230         /*
231          * Removed call to reopen open files here. It is safer (and faster) to
232          * reopen files one at a time as needed in read and write.
233          *
234          * FIXME: what about file locks? don't we need to reclaim them ASAP?
235          */
236
237 out:
238         /*
239          * Check if handle based operation so we know whether we can continue
240          * or not without returning to caller to reset file handle
241          */
242         switch (smb_command) {
243         case SMB_COM_READ_ANDX:
244         case SMB_COM_WRITE_ANDX:
245         case SMB_COM_CLOSE:
246         case SMB_COM_FIND_CLOSE2:
247         case SMB_COM_LOCKING_ANDX:
248                 rc = -EAGAIN;
249         }
250
251         unload_nls(nls_codepage);
252         return rc;
253 }
254
255 /* Allocate and return pointer to an SMB request buffer, and set basic
256    SMB information in the SMB header.  If the return code is zero, this
257    function must have filled in request_buf pointer */
258 static int
259 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
260                 void **request_buf)
261 {
262         int rc;
263
264         rc = cifs_reconnect_tcon(tcon, smb_command);
265         if (rc)
266                 return rc;
267
268         *request_buf = cifs_small_buf_get();
269         if (*request_buf == NULL) {
270                 /* BB should we add a retry in here if not a writepage? */
271                 return -ENOMEM;
272         }
273
274         header_assemble((struct smb_hdr *) *request_buf, smb_command,
275                         tcon, wct);
276
277         if (tcon != NULL)
278                 cifs_stats_inc(&tcon->num_smbs_sent);
279
280         return 0;
281 }
282
283 int
284 small_smb_init_no_tc(const int smb_command, const int wct,
285                      struct cifs_ses *ses, void **request_buf)
286 {
287         int rc;
288         struct smb_hdr *buffer;
289
290         rc = small_smb_init(smb_command, wct, NULL, request_buf);
291         if (rc)
292                 return rc;
293
294         buffer = (struct smb_hdr *)*request_buf;
295         buffer->Mid = get_next_mid(ses->server);
296         if (ses->capabilities & CAP_UNICODE)
297                 buffer->Flags2 |= SMBFLG2_UNICODE;
298         if (ses->capabilities & CAP_STATUS32)
299                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
300
301         /* uid, tid can stay at zero as set in header assemble */
302
303         /* BB add support for turning on the signing when
304         this function is used after 1st of session setup requests */
305
306         return rc;
307 }
308
309 /* If the return code is zero, this function must fill in request_buf pointer */
310 static int
311 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
312                         void **request_buf, void **response_buf)
313 {
314         *request_buf = cifs_buf_get();
315         if (*request_buf == NULL) {
316                 /* BB should we add a retry in here if not a writepage? */
317                 return -ENOMEM;
318         }
319     /* Although the original thought was we needed the response buf for  */
320     /* potential retries of smb operations it turns out we can determine */
321     /* from the mid flags when the request buffer can be resent without  */
322     /* having to use a second distinct buffer for the response */
323         if (response_buf)
324                 *response_buf = *request_buf;
325
326         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
327                         wct);
328
329         if (tcon != NULL)
330                 cifs_stats_inc(&tcon->num_smbs_sent);
331
332         return 0;
333 }
334
335 /* If the return code is zero, this function must fill in request_buf pointer */
336 static int
337 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
338          void **request_buf, void **response_buf)
339 {
340         int rc;
341
342         rc = cifs_reconnect_tcon(tcon, smb_command);
343         if (rc)
344                 return rc;
345
346         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
347 }
348
349 static int
350 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
351                         void **request_buf, void **response_buf)
352 {
353         if (tcon->ses->need_reconnect || tcon->need_reconnect)
354                 return -EHOSTDOWN;
355
356         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
357 }
358
359 static int validate_t2(struct smb_t2_rsp *pSMB)
360 {
361         unsigned int total_size;
362
363         /* check for plausible wct */
364         if (pSMB->hdr.WordCount < 10)
365                 goto vt2_err;
366
367         /* check for parm and data offset going beyond end of smb */
368         if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
369             get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
370                 goto vt2_err;
371
372         total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
373         if (total_size >= 512)
374                 goto vt2_err;
375
376         /* check that bcc is at least as big as parms + data, and that it is
377          * less than negotiated smb buffer
378          */
379         total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
380         if (total_size > get_bcc(&pSMB->hdr) ||
381             total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
382                 goto vt2_err;
383
384         return 0;
385 vt2_err:
386         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
387                 sizeof(struct smb_t2_rsp) + 16);
388         return -EINVAL;
389 }
390
391 int
392 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
393 {
394         NEGOTIATE_REQ *pSMB;
395         NEGOTIATE_RSP *pSMBr;
396         int rc = 0;
397         int bytes_returned;
398         int i;
399         struct TCP_Server_Info *server;
400         u16 count;
401         unsigned int secFlags;
402
403         if (ses->server)
404                 server = ses->server;
405         else {
406                 rc = -EIO;
407                 return rc;
408         }
409         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
410                       (void **) &pSMB, (void **) &pSMBr);
411         if (rc)
412                 return rc;
413
414         /* if any of auth flags (ie not sign or seal) are overriden use them */
415         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
416                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
417         else /* if override flags set only sign/seal OR them with global auth */
418                 secFlags = global_secflags | ses->overrideSecFlg;
419
420         cFYI(1, "secFlags 0x%x", secFlags);
421
422         pSMB->hdr.Mid = get_next_mid(server);
423         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
424
425         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
426                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
427         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
428                 cFYI(1, "Kerberos only mechanism, enable extended security");
429                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
430         } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
431                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
432         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
433                 cFYI(1, "NTLMSSP only mechanism, enable extended security");
434                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
435         }
436
437         count = 0;
438         for (i = 0; i < CIFS_NUM_PROT; i++) {
439                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
440                 count += strlen(protocols[i].name) + 1;
441                 /* null at end of source and target buffers anyway */
442         }
443         inc_rfc1001_len(pSMB, count);
444         pSMB->ByteCount = cpu_to_le16(count);
445
446         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
447                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
448         if (rc != 0)
449                 goto neg_err_exit;
450
451         server->dialect = le16_to_cpu(pSMBr->DialectIndex);
452         cFYI(1, "Dialect: %d", server->dialect);
453         /* Check wct = 1 error case */
454         if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
455                 /* core returns wct = 1, but we do not ask for core - otherwise
456                 small wct just comes when dialect index is -1 indicating we
457                 could not negotiate a common dialect */
458                 rc = -EOPNOTSUPP;
459                 goto neg_err_exit;
460 #ifdef CONFIG_CIFS_WEAK_PW_HASH
461         } else if ((pSMBr->hdr.WordCount == 13)
462                         && ((server->dialect == LANMAN_PROT)
463                                 || (server->dialect == LANMAN2_PROT))) {
464                 __s16 tmp;
465                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
466
467                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
468                         (secFlags & CIFSSEC_MAY_PLNTXT))
469                         server->secType = LANMAN;
470                 else {
471                         cERROR(1, "mount failed weak security disabled"
472                                    " in /proc/fs/cifs/SecurityFlags");
473                         rc = -EOPNOTSUPP;
474                         goto neg_err_exit;
475                 }
476                 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
477                 server->maxReq = min_t(unsigned int,
478                                        le16_to_cpu(rsp->MaxMpxCount),
479                                        cifs_max_pending);
480                 set_credits(server, server->maxReq);
481                 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
482                 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
483                 /* even though we do not use raw we might as well set this
484                 accurately, in case we ever find a need for it */
485                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
486                         server->max_rw = 0xFF00;
487                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
488                 } else {
489                         server->max_rw = 0;/* do not need to use raw anyway */
490                         server->capabilities = CAP_MPX_MODE;
491                 }
492                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
493                 if (tmp == -1) {
494                         /* OS/2 often does not set timezone therefore
495                          * we must use server time to calc time zone.
496                          * Could deviate slightly from the right zone.
497                          * Smallest defined timezone difference is 15 minutes
498                          * (i.e. Nepal).  Rounding up/down is done to match
499                          * this requirement.
500                          */
501                         int val, seconds, remain, result;
502                         struct timespec ts, utc;
503                         utc = CURRENT_TIME;
504                         ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
505                                             rsp->SrvTime.Time, 0);
506                         cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
507                                 (int)ts.tv_sec, (int)utc.tv_sec,
508                                 (int)(utc.tv_sec - ts.tv_sec));
509                         val = (int)(utc.tv_sec - ts.tv_sec);
510                         seconds = abs(val);
511                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
512                         remain = seconds % MIN_TZ_ADJ;
513                         if (remain >= (MIN_TZ_ADJ / 2))
514                                 result += MIN_TZ_ADJ;
515                         if (val < 0)
516                                 result = -result;
517                         server->timeAdj = result;
518                 } else {
519                         server->timeAdj = (int)tmp;
520                         server->timeAdj *= 60; /* also in seconds */
521                 }
522                 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
523
524
525                 /* BB get server time for time conversions and add
526                 code to use it and timezone since this is not UTC */
527
528                 if (rsp->EncryptionKeyLength ==
529                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
530                         memcpy(ses->server->cryptkey, rsp->EncryptionKey,
531                                 CIFS_CRYPTO_KEY_SIZE);
532                 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
533                         rc = -EIO; /* need cryptkey unless plain text */
534                         goto neg_err_exit;
535                 }
536
537                 cFYI(1, "LANMAN negotiated");
538                 /* we will not end up setting signing flags - as no signing
539                 was in LANMAN and server did not return the flags on */
540                 goto signing_check;
541 #else /* weak security disabled */
542         } else if (pSMBr->hdr.WordCount == 13) {
543                 cERROR(1, "mount failed, cifs module not built "
544                           "with CIFS_WEAK_PW_HASH support");
545                 rc = -EOPNOTSUPP;
546 #endif /* WEAK_PW_HASH */
547                 goto neg_err_exit;
548         } else if (pSMBr->hdr.WordCount != 17) {
549                 /* unknown wct */
550                 rc = -EOPNOTSUPP;
551                 goto neg_err_exit;
552         }
553         /* else wct == 17 NTLM */
554         server->sec_mode = pSMBr->SecurityMode;
555         if ((server->sec_mode & SECMODE_USER) == 0)
556                 cFYI(1, "share mode security");
557
558         if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
559 #ifdef CONFIG_CIFS_WEAK_PW_HASH
560                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
561 #endif /* CIFS_WEAK_PW_HASH */
562                         cERROR(1, "Server requests plain text password"
563                                   " but client support disabled");
564
565         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
566                 server->secType = NTLMv2;
567         else if (secFlags & CIFSSEC_MAY_NTLM)
568                 server->secType = NTLM;
569         else if (secFlags & CIFSSEC_MAY_NTLMV2)
570                 server->secType = NTLMv2;
571         else if (secFlags & CIFSSEC_MAY_KRB5)
572                 server->secType = Kerberos;
573         else if (secFlags & CIFSSEC_MAY_NTLMSSP)
574                 server->secType = RawNTLMSSP;
575         else if (secFlags & CIFSSEC_MAY_LANMAN)
576                 server->secType = LANMAN;
577         else {
578                 rc = -EOPNOTSUPP;
579                 cERROR(1, "Invalid security type");
580                 goto neg_err_exit;
581         }
582         /* else ... any others ...? */
583
584         /* one byte, so no need to convert this or EncryptionKeyLen from
585            little endian */
586         server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
587                                cifs_max_pending);
588         set_credits(server, server->maxReq);
589         /* probably no need to store and check maxvcs */
590         server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
591         server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
592         cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
593         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
594         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
595         server->timeAdj *= 60;
596         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
597                 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
598                        CIFS_CRYPTO_KEY_SIZE);
599         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
600                         server->capabilities & CAP_EXTENDED_SECURITY) &&
601                                 (pSMBr->EncryptionKeyLength == 0)) {
602                 /* decode security blob */
603                 count = get_bcc(&pSMBr->hdr);
604                 if (count < 16) {
605                         rc = -EIO;
606                         goto neg_err_exit;
607                 }
608                 spin_lock(&cifs_tcp_ses_lock);
609                 if (server->srv_count > 1) {
610                         spin_unlock(&cifs_tcp_ses_lock);
611                         if (memcmp(server->server_GUID,
612                                    pSMBr->u.extended_response.
613                                    GUID, 16) != 0) {
614                                 cFYI(1, "server UID changed");
615                                 memcpy(server->server_GUID,
616                                         pSMBr->u.extended_response.GUID,
617                                         16);
618                         }
619                 } else {
620                         spin_unlock(&cifs_tcp_ses_lock);
621                         memcpy(server->server_GUID,
622                                pSMBr->u.extended_response.GUID, 16);
623                 }
624
625                 if (count == 16) {
626                         server->secType = RawNTLMSSP;
627                 } else {
628                         rc = decode_negTokenInit(pSMBr->u.extended_response.
629                                                  SecurityBlob, count - 16,
630                                                  server);
631                         if (rc == 1)
632                                 rc = 0;
633                         else
634                                 rc = -EINVAL;
635                         if (server->secType == Kerberos) {
636                                 if (!server->sec_kerberos &&
637                                                 !server->sec_mskerberos)
638                                         rc = -EOPNOTSUPP;
639                         } else if (server->secType == RawNTLMSSP) {
640                                 if (!server->sec_ntlmssp)
641                                         rc = -EOPNOTSUPP;
642                         } else
643                                         rc = -EOPNOTSUPP;
644                 }
645         } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
646                 rc = -EIO; /* no crypt key only if plain text pwd */
647                 goto neg_err_exit;
648         } else
649                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
650
651 #ifdef CONFIG_CIFS_WEAK_PW_HASH
652 signing_check:
653 #endif
654         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
655                 /* MUST_SIGN already includes the MAY_SIGN FLAG
656                    so if this is zero it means that signing is disabled */
657                 cFYI(1, "Signing disabled");
658                 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
659                         cERROR(1, "Server requires "
660                                    "packet signing to be enabled in "
661                                    "/proc/fs/cifs/SecurityFlags.");
662                         rc = -EOPNOTSUPP;
663                 }
664                 server->sec_mode &=
665                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
666         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
667                 /* signing required */
668                 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
669                 if ((server->sec_mode &
670                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
671                         cERROR(1, "signing required but server lacks support");
672                         rc = -EOPNOTSUPP;
673                 } else
674                         server->sec_mode |= SECMODE_SIGN_REQUIRED;
675         } else {
676                 /* signing optional ie CIFSSEC_MAY_SIGN */
677                 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
678                         server->sec_mode &=
679                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
680         }
681
682 neg_err_exit:
683         cifs_buf_release(pSMB);
684
685         cFYI(1, "negprot rc %d", rc);
686         return rc;
687 }
688
689 int
690 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
691 {
692         struct smb_hdr *smb_buffer;
693         int rc = 0;
694
695         cFYI(1, "In tree disconnect");
696
697         /* BB: do we need to check this? These should never be NULL. */
698         if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
699                 return -EIO;
700
701         /*
702          * No need to return error on this operation if tid invalidated and
703          * closed on server already e.g. due to tcp session crashing. Also,
704          * the tcon is no longer on the list, so no need to take lock before
705          * checking this.
706          */
707         if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
708                 return 0;
709
710         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
711                             (void **)&smb_buffer);
712         if (rc)
713                 return rc;
714
715         rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
716         if (rc)
717                 cFYI(1, "Tree disconnect failed %d", rc);
718
719         /* No need to return error on this operation if tid invalidated and
720            closed on server already e.g. due to tcp session crashing */
721         if (rc == -EAGAIN)
722                 rc = 0;
723
724         return rc;
725 }
726
727 /*
728  * This is a no-op for now. We're not really interested in the reply, but
729  * rather in the fact that the server sent one and that server->lstrp
730  * gets updated.
731  *
732  * FIXME: maybe we should consider checking that the reply matches request?
733  */
734 static void
735 cifs_echo_callback(struct mid_q_entry *mid)
736 {
737         struct TCP_Server_Info *server = mid->callback_data;
738
739         DeleteMidQEntry(mid);
740         add_credits(server, 1, CIFS_ECHO_OP);
741 }
742
743 int
744 CIFSSMBEcho(struct TCP_Server_Info *server)
745 {
746         ECHO_REQ *smb;
747         int rc = 0;
748         struct kvec iov;
749
750         cFYI(1, "In echo request");
751
752         rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
753         if (rc)
754                 return rc;
755
756         /* set up echo request */
757         smb->hdr.Tid = 0xffff;
758         smb->hdr.WordCount = 1;
759         put_unaligned_le16(1, &smb->EchoCount);
760         put_bcc(1, &smb->hdr);
761         smb->Data[0] = 'a';
762         inc_rfc1001_len(smb, 3);
763         iov.iov_base = smb;
764         iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
765
766         rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
767                              server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
768         if (rc)
769                 cFYI(1, "Echo request failed: %d", rc);
770
771         cifs_small_buf_release(smb);
772
773         return rc;
774 }
775
776 int
777 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
778 {
779         LOGOFF_ANDX_REQ *pSMB;
780         int rc = 0;
781
782         cFYI(1, "In SMBLogoff for session disconnect");
783
784         /*
785          * BB: do we need to check validity of ses and server? They should
786          * always be valid since we have an active reference. If not, that
787          * should probably be a BUG()
788          */
789         if (!ses || !ses->server)
790                 return -EIO;
791
792         mutex_lock(&ses->session_mutex);
793         if (ses->need_reconnect)
794                 goto session_already_dead; /* no need to send SMBlogoff if uid
795                                               already closed due to reconnect */
796         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
797         if (rc) {
798                 mutex_unlock(&ses->session_mutex);
799                 return rc;
800         }
801
802         pSMB->hdr.Mid = get_next_mid(ses->server);
803
804         if (ses->server->sec_mode &
805                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
806                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
807
808         pSMB->hdr.Uid = ses->Suid;
809
810         pSMB->AndXCommand = 0xFF;
811         rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
812 session_already_dead:
813         mutex_unlock(&ses->session_mutex);
814
815         /* if session dead then we do not need to do ulogoff,
816                 since server closed smb session, no sense reporting
817                 error */
818         if (rc == -EAGAIN)
819                 rc = 0;
820         return rc;
821 }
822
823 int
824 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
825                  const char *fileName, __u16 type,
826                  const struct nls_table *nls_codepage, int remap)
827 {
828         TRANSACTION2_SPI_REQ *pSMB = NULL;
829         TRANSACTION2_SPI_RSP *pSMBr = NULL;
830         struct unlink_psx_rq *pRqD;
831         int name_len;
832         int rc = 0;
833         int bytes_returned = 0;
834         __u16 params, param_offset, offset, byte_count;
835
836         cFYI(1, "In POSIX delete");
837 PsxDelete:
838         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
839                       (void **) &pSMBr);
840         if (rc)
841                 return rc;
842
843         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
844                 name_len =
845                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
846                                        PATH_MAX, nls_codepage, remap);
847                 name_len++;     /* trailing null */
848                 name_len *= 2;
849         } else { /* BB add path length overrun check */
850                 name_len = strnlen(fileName, PATH_MAX);
851                 name_len++;     /* trailing null */
852                 strncpy(pSMB->FileName, fileName, name_len);
853         }
854
855         params = 6 + name_len;
856         pSMB->MaxParameterCount = cpu_to_le16(2);
857         pSMB->MaxDataCount = 0; /* BB double check this with jra */
858         pSMB->MaxSetupCount = 0;
859         pSMB->Reserved = 0;
860         pSMB->Flags = 0;
861         pSMB->Timeout = 0;
862         pSMB->Reserved2 = 0;
863         param_offset = offsetof(struct smb_com_transaction2_spi_req,
864                                 InformationLevel) - 4;
865         offset = param_offset + params;
866
867         /* Setup pointer to Request Data (inode type) */
868         pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
869         pRqD->type = cpu_to_le16(type);
870         pSMB->ParameterOffset = cpu_to_le16(param_offset);
871         pSMB->DataOffset = cpu_to_le16(offset);
872         pSMB->SetupCount = 1;
873         pSMB->Reserved3 = 0;
874         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
875         byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
876
877         pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878         pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
879         pSMB->ParameterCount = cpu_to_le16(params);
880         pSMB->TotalParameterCount = pSMB->ParameterCount;
881         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
882         pSMB->Reserved4 = 0;
883         inc_rfc1001_len(pSMB, byte_count);
884         pSMB->ByteCount = cpu_to_le16(byte_count);
885         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
886                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
887         if (rc)
888                 cFYI(1, "Posix delete returned %d", rc);
889         cifs_buf_release(pSMB);
890
891         cifs_stats_inc(&tcon->num_deletes);
892
893         if (rc == -EAGAIN)
894                 goto PsxDelete;
895
896         return rc;
897 }
898
899 int
900 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
901                const char *fileName, const struct nls_table *nls_codepage,
902                int remap)
903 {
904         DELETE_FILE_REQ *pSMB = NULL;
905         DELETE_FILE_RSP *pSMBr = NULL;
906         int rc = 0;
907         int bytes_returned;
908         int name_len;
909
910 DelFileRetry:
911         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
912                       (void **) &pSMBr);
913         if (rc)
914                 return rc;
915
916         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
917                 name_len =
918                     cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
919                                        PATH_MAX, nls_codepage, remap);
920                 name_len++;     /* trailing null */
921                 name_len *= 2;
922         } else {                /* BB improve check for buffer overruns BB */
923                 name_len = strnlen(fileName, PATH_MAX);
924                 name_len++;     /* trailing null */
925                 strncpy(pSMB->fileName, fileName, name_len);
926         }
927         pSMB->SearchAttributes =
928             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
929         pSMB->BufferFormat = 0x04;
930         inc_rfc1001_len(pSMB, name_len + 1);
931         pSMB->ByteCount = cpu_to_le16(name_len + 1);
932         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
933                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
934         cifs_stats_inc(&tcon->num_deletes);
935         if (rc)
936                 cFYI(1, "Error in RMFile = %d", rc);
937
938         cifs_buf_release(pSMB);
939         if (rc == -EAGAIN)
940                 goto DelFileRetry;
941
942         return rc;
943 }
944
945 int
946 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
947              const char *dirName, const struct nls_table *nls_codepage,
948              int remap)
949 {
950         DELETE_DIRECTORY_REQ *pSMB = NULL;
951         DELETE_DIRECTORY_RSP *pSMBr = NULL;
952         int rc = 0;
953         int bytes_returned;
954         int name_len;
955
956         cFYI(1, "In CIFSSMBRmDir");
957 RmDirRetry:
958         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
959                       (void **) &pSMBr);
960         if (rc)
961                 return rc;
962
963         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
964                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
965                                               PATH_MAX, nls_codepage, remap);
966                 name_len++;     /* trailing null */
967                 name_len *= 2;
968         } else {                /* BB improve check for buffer overruns BB */
969                 name_len = strnlen(dirName, PATH_MAX);
970                 name_len++;     /* trailing null */
971                 strncpy(pSMB->DirName, dirName, name_len);
972         }
973
974         pSMB->BufferFormat = 0x04;
975         inc_rfc1001_len(pSMB, name_len + 1);
976         pSMB->ByteCount = cpu_to_le16(name_len + 1);
977         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
978                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
979         cifs_stats_inc(&tcon->num_rmdirs);
980         if (rc)
981                 cFYI(1, "Error in RMDir = %d", rc);
982
983         cifs_buf_release(pSMB);
984         if (rc == -EAGAIN)
985                 goto RmDirRetry;
986         return rc;
987 }
988
989 int
990 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
991              const char *name, const struct nls_table *nls_codepage, int remap)
992 {
993         int rc = 0;
994         CREATE_DIRECTORY_REQ *pSMB = NULL;
995         CREATE_DIRECTORY_RSP *pSMBr = NULL;
996         int bytes_returned;
997         int name_len;
998
999         cFYI(1, "In CIFSSMBMkDir");
1000 MkDirRetry:
1001         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1002                       (void **) &pSMBr);
1003         if (rc)
1004                 return rc;
1005
1006         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1007                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1008                                               PATH_MAX, nls_codepage, remap);
1009                 name_len++;     /* trailing null */
1010                 name_len *= 2;
1011         } else {                /* BB improve check for buffer overruns BB */
1012                 name_len = strnlen(name, PATH_MAX);
1013                 name_len++;     /* trailing null */
1014                 strncpy(pSMB->DirName, name, name_len);
1015         }
1016
1017         pSMB->BufferFormat = 0x04;
1018         inc_rfc1001_len(pSMB, name_len + 1);
1019         pSMB->ByteCount = cpu_to_le16(name_len + 1);
1020         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1021                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1022         cifs_stats_inc(&tcon->num_mkdirs);
1023         if (rc)
1024                 cFYI(1, "Error in Mkdir = %d", rc);
1025
1026         cifs_buf_release(pSMB);
1027         if (rc == -EAGAIN)
1028                 goto MkDirRetry;
1029         return rc;
1030 }
1031
1032 int
1033 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1034                 __u32 posix_flags, __u64 mode, __u16 *netfid,
1035                 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1036                 const char *name, const struct nls_table *nls_codepage,
1037                 int remap)
1038 {
1039         TRANSACTION2_SPI_REQ *pSMB = NULL;
1040         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1041         int name_len;
1042         int rc = 0;
1043         int bytes_returned = 0;
1044         __u16 params, param_offset, offset, byte_count, count;
1045         OPEN_PSX_REQ *pdata;
1046         OPEN_PSX_RSP *psx_rsp;
1047
1048         cFYI(1, "In POSIX Create");
1049 PsxCreat:
1050         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1051                       (void **) &pSMBr);
1052         if (rc)
1053                 return rc;
1054
1055         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1056                 name_len =
1057                     cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1058                                        PATH_MAX, nls_codepage, remap);
1059                 name_len++;     /* trailing null */
1060                 name_len *= 2;
1061         } else {        /* BB improve the check for buffer overruns BB */
1062                 name_len = strnlen(name, PATH_MAX);
1063                 name_len++;     /* trailing null */
1064                 strncpy(pSMB->FileName, name, name_len);
1065         }
1066
1067         params = 6 + name_len;
1068         count = sizeof(OPEN_PSX_REQ);
1069         pSMB->MaxParameterCount = cpu_to_le16(2);
1070         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1071         pSMB->MaxSetupCount = 0;
1072         pSMB->Reserved = 0;
1073         pSMB->Flags = 0;
1074         pSMB->Timeout = 0;
1075         pSMB->Reserved2 = 0;
1076         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1077                                 InformationLevel) - 4;
1078         offset = param_offset + params;
1079         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1080         pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1081         pdata->Permissions = cpu_to_le64(mode);
1082         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1083         pdata->OpenFlags =  cpu_to_le32(*pOplock);
1084         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1085         pSMB->DataOffset = cpu_to_le16(offset);
1086         pSMB->SetupCount = 1;
1087         pSMB->Reserved3 = 0;
1088         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1089         byte_count = 3 /* pad */  + params + count;
1090
1091         pSMB->DataCount = cpu_to_le16(count);
1092         pSMB->ParameterCount = cpu_to_le16(params);
1093         pSMB->TotalDataCount = pSMB->DataCount;
1094         pSMB->TotalParameterCount = pSMB->ParameterCount;
1095         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1096         pSMB->Reserved4 = 0;
1097         inc_rfc1001_len(pSMB, byte_count);
1098         pSMB->ByteCount = cpu_to_le16(byte_count);
1099         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1100                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1101         if (rc) {
1102                 cFYI(1, "Posix create returned %d", rc);
1103                 goto psx_create_err;
1104         }
1105
1106         cFYI(1, "copying inode info");
1107         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1108
1109         if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1110                 rc = -EIO;      /* bad smb */
1111                 goto psx_create_err;
1112         }
1113
1114         /* copy return information to pRetData */
1115         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1116                         + le16_to_cpu(pSMBr->t2.DataOffset));
1117
1118         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1119         if (netfid)
1120                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1121         /* Let caller know file was created so we can set the mode. */
1122         /* Do we care about the CreateAction in any other cases? */
1123         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1124                 *pOplock |= CIFS_CREATE_ACTION;
1125         /* check to make sure response data is there */
1126         if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1127                 pRetData->Type = cpu_to_le32(-1); /* unknown */
1128                 cFYI(DBG2, "unknown type");
1129         } else {
1130                 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1131                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1132                         cERROR(1, "Open response data too small");
1133                         pRetData->Type = cpu_to_le32(-1);
1134                         goto psx_create_err;
1135                 }
1136                 memcpy((char *) pRetData,
1137                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1138                         sizeof(FILE_UNIX_BASIC_INFO));
1139         }
1140
1141 psx_create_err:
1142         cifs_buf_release(pSMB);
1143
1144         if (posix_flags & SMB_O_DIRECTORY)
1145                 cifs_stats_inc(&tcon->num_posixmkdirs);
1146         else
1147                 cifs_stats_inc(&tcon->num_posixopens);
1148
1149         if (rc == -EAGAIN)
1150                 goto PsxCreat;
1151
1152         return rc;
1153 }
1154
1155 static __u16 convert_disposition(int disposition)
1156 {
1157         __u16 ofun = 0;
1158
1159         switch (disposition) {
1160                 case FILE_SUPERSEDE:
1161                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1162                         break;
1163                 case FILE_OPEN:
1164                         ofun = SMBOPEN_OAPPEND;
1165                         break;
1166                 case FILE_CREATE:
1167                         ofun = SMBOPEN_OCREATE;
1168                         break;
1169                 case FILE_OPEN_IF:
1170                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1171                         break;
1172                 case FILE_OVERWRITE:
1173                         ofun = SMBOPEN_OTRUNC;
1174                         break;
1175                 case FILE_OVERWRITE_IF:
1176                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1177                         break;
1178                 default:
1179                         cFYI(1, "unknown disposition %d", disposition);
1180                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1181         }
1182         return ofun;
1183 }
1184
1185 static int
1186 access_flags_to_smbopen_mode(const int access_flags)
1187 {
1188         int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1189
1190         if (masked_flags == GENERIC_READ)
1191                 return SMBOPEN_READ;
1192         else if (masked_flags == GENERIC_WRITE)
1193                 return SMBOPEN_WRITE;
1194
1195         /* just go for read/write */
1196         return SMBOPEN_READWRITE;
1197 }
1198
1199 int
1200 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1201             const char *fileName, const int openDisposition,
1202             const int access_flags, const int create_options, __u16 *netfid,
1203             int *pOplock, FILE_ALL_INFO *pfile_info,
1204             const struct nls_table *nls_codepage, int remap)
1205 {
1206         int rc = -EACCES;
1207         OPENX_REQ *pSMB = NULL;
1208         OPENX_RSP *pSMBr = NULL;
1209         int bytes_returned;
1210         int name_len;
1211         __u16 count;
1212
1213 OldOpenRetry:
1214         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1215                       (void **) &pSMBr);
1216         if (rc)
1217                 return rc;
1218
1219         pSMB->AndXCommand = 0xFF;       /* none */
1220
1221         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1222                 count = 1;      /* account for one byte pad to word boundary */
1223                 name_len =
1224                    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1225                                       fileName, PATH_MAX, nls_codepage, remap);
1226                 name_len++;     /* trailing null */
1227                 name_len *= 2;
1228         } else {                /* BB improve check for buffer overruns BB */
1229                 count = 0;      /* no pad */
1230                 name_len = strnlen(fileName, PATH_MAX);
1231                 name_len++;     /* trailing null */
1232                 strncpy(pSMB->fileName, fileName, name_len);
1233         }
1234         if (*pOplock & REQ_OPLOCK)
1235                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1236         else if (*pOplock & REQ_BATCHOPLOCK)
1237                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1238
1239         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1240         pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1241         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1242         /* set file as system file if special file such
1243            as fifo and server expecting SFU style and
1244            no Unix extensions */
1245
1246         if (create_options & CREATE_OPTION_SPECIAL)
1247                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1248         else /* BB FIXME BB */
1249                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1250
1251         if (create_options & CREATE_OPTION_READONLY)
1252                 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1253
1254         /* BB FIXME BB */
1255 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1256                                                  CREATE_OPTIONS_MASK); */
1257         /* BB FIXME END BB */
1258
1259         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1260         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1261         count += name_len;
1262         inc_rfc1001_len(pSMB, count);
1263
1264         pSMB->ByteCount = cpu_to_le16(count);
1265         /* long_op set to 1 to allow for oplock break timeouts */
1266         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1267                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1268         cifs_stats_inc(&tcon->num_opens);
1269         if (rc) {
1270                 cFYI(1, "Error in Open = %d", rc);
1271         } else {
1272         /* BB verify if wct == 15 */
1273
1274 /*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1275
1276                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1277                 /* Let caller know file was created so we can set the mode. */
1278                 /* Do we care about the CreateAction in any other cases? */
1279         /* BB FIXME BB */
1280 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1281                         *pOplock |= CIFS_CREATE_ACTION; */
1282         /* BB FIXME END */
1283
1284                 if (pfile_info) {
1285                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1286                         pfile_info->LastAccessTime = 0; /* BB fixme */
1287                         pfile_info->LastWriteTime = 0; /* BB fixme */
1288                         pfile_info->ChangeTime = 0;  /* BB fixme */
1289                         pfile_info->Attributes =
1290                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1291                         /* the file_info buf is endian converted by caller */
1292                         pfile_info->AllocationSize =
1293                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1294                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1295                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1296                         pfile_info->DeletePending = 0;
1297                 }
1298         }
1299
1300         cifs_buf_release(pSMB);
1301         if (rc == -EAGAIN)
1302                 goto OldOpenRetry;
1303         return rc;
1304 }
1305
1306 int
1307 CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1308             const char *fileName, const int openDisposition,
1309             const int access_flags, const int create_options, __u16 *netfid,
1310             int *pOplock, FILE_ALL_INFO *pfile_info,
1311             const struct nls_table *nls_codepage, int remap)
1312 {
1313         int rc = -EACCES;
1314         OPEN_REQ *pSMB = NULL;
1315         OPEN_RSP *pSMBr = NULL;
1316         int bytes_returned;
1317         int name_len;
1318         __u16 count;
1319
1320 openRetry:
1321         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1322                       (void **) &pSMBr);
1323         if (rc)
1324                 return rc;
1325
1326         pSMB->AndXCommand = 0xFF;       /* none */
1327
1328         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1329                 count = 1;      /* account for one byte pad to word boundary */
1330                 name_len =
1331                     cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1332                                        fileName, PATH_MAX, nls_codepage, remap);
1333                 name_len++;     /* trailing null */
1334                 name_len *= 2;
1335                 pSMB->NameLength = cpu_to_le16(name_len);
1336         } else {                /* BB improve check for buffer overruns BB */
1337                 count = 0;      /* no pad */
1338                 name_len = strnlen(fileName, PATH_MAX);
1339                 name_len++;     /* trailing null */
1340                 pSMB->NameLength = cpu_to_le16(name_len);
1341                 strncpy(pSMB->fileName, fileName, name_len);
1342         }
1343         if (*pOplock & REQ_OPLOCK)
1344                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1345         else if (*pOplock & REQ_BATCHOPLOCK)
1346                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1347         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1348         pSMB->AllocationSize = 0;
1349         /* set file as system file if special file such
1350            as fifo and server expecting SFU style and
1351            no Unix extensions */
1352         if (create_options & CREATE_OPTION_SPECIAL)
1353                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1354         else
1355                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1356
1357         /* XP does not handle ATTR_POSIX_SEMANTICS */
1358         /* but it helps speed up case sensitive checks for other
1359         servers such as Samba */
1360         if (tcon->ses->capabilities & CAP_UNIX)
1361                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1362
1363         if (create_options & CREATE_OPTION_READONLY)
1364                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1365
1366         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1367         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1368         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1369         /* BB Expirement with various impersonation levels and verify */
1370         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1371         pSMB->SecurityFlags =
1372             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1373
1374         count += name_len;
1375         inc_rfc1001_len(pSMB, count);
1376
1377         pSMB->ByteCount = cpu_to_le16(count);
1378         /* long_op set to 1 to allow for oplock break timeouts */
1379         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1380                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1381         cifs_stats_inc(&tcon->num_opens);
1382         if (rc) {
1383                 cFYI(1, "Error in Open = %d", rc);
1384         } else {
1385                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1386                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1387                 /* Let caller know file was created so we can set the mode. */
1388                 /* Do we care about the CreateAction in any other cases? */
1389                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1390                         *pOplock |= CIFS_CREATE_ACTION;
1391                 if (pfile_info) {
1392                         memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1393                                 36 /* CreationTime to Attributes */);
1394                         /* the file_info buf is endian converted by caller */
1395                         pfile_info->AllocationSize = pSMBr->AllocationSize;
1396                         pfile_info->EndOfFile = pSMBr->EndOfFile;
1397                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1398                         pfile_info->DeletePending = 0;
1399                 }
1400         }
1401
1402         cifs_buf_release(pSMB);
1403         if (rc == -EAGAIN)
1404                 goto openRetry;
1405         return rc;
1406 }
1407
1408 /*
1409  * Discard any remaining data in the current SMB. To do this, we borrow the
1410  * current bigbuf.
1411  */
1412 static int
1413 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1414 {
1415         unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1416         int remaining = rfclen + 4 - server->total_read;
1417         struct cifs_readdata *rdata = mid->callback_data;
1418
1419         while (remaining > 0) {
1420                 int length;
1421
1422                 length = cifs_read_from_socket(server, server->bigbuf,
1423                                 min_t(unsigned int, remaining,
1424                                     CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1425                 if (length < 0)
1426                         return length;
1427                 server->total_read += length;
1428                 remaining -= length;
1429         }
1430
1431         dequeue_mid(mid, rdata->result);
1432         return 0;
1433 }
1434
1435 static int
1436 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1437 {
1438         int length, len;
1439         unsigned int data_offset, data_len;
1440         struct cifs_readdata *rdata = mid->callback_data;
1441         char *buf = server->smallbuf;
1442         unsigned int buflen = get_rfc1002_length(buf) + 4;
1443
1444         cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1445                 mid->mid, rdata->offset, rdata->bytes);
1446
1447         /*
1448          * read the rest of READ_RSP header (sans Data array), or whatever we
1449          * can if there's not enough data. At this point, we've read down to
1450          * the Mid.
1451          */
1452         len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1453                                                         HEADER_SIZE(server) + 1;
1454
1455         rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1456         rdata->iov[0].iov_len = len;
1457
1458         length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1459         if (length < 0)
1460                 return length;
1461         server->total_read += length;
1462
1463         /* Was the SMB read successful? */
1464         rdata->result = server->ops->map_error(buf, false);
1465         if (rdata->result != 0) {
1466                 cFYI(1, "%s: server returned error %d", __func__,
1467                         rdata->result);
1468                 return cifs_readv_discard(server, mid);
1469         }
1470
1471         /* Is there enough to get to the rest of the READ_RSP header? */
1472         if (server->total_read < server->vals->read_rsp_size) {
1473                 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1474                         __func__, server->total_read,
1475                         server->vals->read_rsp_size);
1476                 rdata->result = -EIO;
1477                 return cifs_readv_discard(server, mid);
1478         }
1479
1480         data_offset = server->ops->read_data_offset(buf) + 4;
1481         if (data_offset < server->total_read) {
1482                 /*
1483                  * win2k8 sometimes sends an offset of 0 when the read
1484                  * is beyond the EOF. Treat it as if the data starts just after
1485                  * the header.
1486                  */
1487                 cFYI(1, "%s: data offset (%u) inside read response header",
1488                         __func__, data_offset);
1489                 data_offset = server->total_read;
1490         } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1491                 /* data_offset is beyond the end of smallbuf */
1492                 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1493                         __func__, data_offset);
1494                 rdata->result = -EIO;
1495                 return cifs_readv_discard(server, mid);
1496         }
1497
1498         cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1499                 server->total_read, data_offset);
1500
1501         len = data_offset - server->total_read;
1502         if (len > 0) {
1503                 /* read any junk before data into the rest of smallbuf */
1504                 rdata->iov[0].iov_base = buf + server->total_read;
1505                 rdata->iov[0].iov_len = len;
1506                 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1507                 if (length < 0)
1508                         return length;
1509                 server->total_read += length;
1510         }
1511
1512         /* set up first iov for signature check */
1513         rdata->iov[0].iov_base = buf;
1514         rdata->iov[0].iov_len = server->total_read;
1515         cFYI(1, "0: iov_base=%p iov_len=%zu",
1516                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1517
1518         /* how much data is in the response? */
1519         data_len = server->ops->read_data_length(buf);
1520         if (data_offset + data_len > buflen) {
1521                 /* data_len is corrupt -- discard frame */
1522                 rdata->result = -EIO;
1523                 return cifs_readv_discard(server, mid);
1524         }
1525
1526         /* marshal up the page array */
1527         cifs_kmap_lock();
1528         len = rdata->marshal_iov(rdata, data_len);
1529         cifs_kmap_unlock();
1530         data_len -= len;
1531
1532         /* issue the read if we have any iovecs left to fill */
1533         if (rdata->nr_iov > 1) {
1534                 length = cifs_readv_from_socket(server, &rdata->iov[1],
1535                                                 rdata->nr_iov - 1, len);
1536                 if (length < 0)
1537                         return length;
1538                 server->total_read += length;
1539         } else {
1540                 length = 0;
1541         }
1542
1543         rdata->bytes = length;
1544
1545         cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1546                 buflen, data_len);
1547
1548         /* discard anything left over */
1549         if (server->total_read < buflen)
1550                 return cifs_readv_discard(server, mid);
1551
1552         dequeue_mid(mid, false);
1553         return length;
1554 }
1555
1556 static void
1557 cifs_readv_callback(struct mid_q_entry *mid)
1558 {
1559         struct cifs_readdata *rdata = mid->callback_data;
1560         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1561         struct TCP_Server_Info *server = tcon->ses->server;
1562
1563         cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1564                 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1565
1566         switch (mid->mid_state) {
1567         case MID_RESPONSE_RECEIVED:
1568                 /* result already set, check signature */
1569                 if (server->sec_mode &
1570                     (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1571                         if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1572                                           server, mid->sequence_number + 1))
1573                                 cERROR(1, "Unexpected SMB signature");
1574                 }
1575                 /* FIXME: should this be counted toward the initiating task? */
1576                 task_io_account_read(rdata->bytes);
1577                 cifs_stats_bytes_read(tcon, rdata->bytes);
1578                 break;
1579         case MID_REQUEST_SUBMITTED:
1580         case MID_RETRY_NEEDED:
1581                 rdata->result = -EAGAIN;
1582                 break;
1583         default:
1584                 rdata->result = -EIO;
1585         }
1586
1587         queue_work(cifsiod_wq, &rdata->work);
1588         DeleteMidQEntry(mid);
1589         add_credits(server, 1, 0);
1590 }
1591
1592 /* cifs_async_readv - send an async write, and set up mid to handle result */
1593 int
1594 cifs_async_readv(struct cifs_readdata *rdata)
1595 {
1596         int rc;
1597         READ_REQ *smb = NULL;
1598         int wct;
1599         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1600
1601         cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1602                 rdata->offset, rdata->bytes);
1603
1604         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1605                 wct = 12;
1606         else {
1607                 wct = 10; /* old style read */
1608                 if ((rdata->offset >> 32) > 0)  {
1609                         /* can not handle this big offset for old */
1610                         return -EIO;
1611                 }
1612         }
1613
1614         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1615         if (rc)
1616                 return rc;
1617
1618         smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1619         smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1620
1621         smb->AndXCommand = 0xFF;        /* none */
1622         smb->Fid = rdata->cfile->netfid;
1623         smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1624         if (wct == 12)
1625                 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1626         smb->Remaining = 0;
1627         smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1628         smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1629         if (wct == 12)
1630                 smb->ByteCount = 0;
1631         else {
1632                 /* old style read */
1633                 struct smb_com_readx_req *smbr =
1634                         (struct smb_com_readx_req *)smb;
1635                 smbr->ByteCount = 0;
1636         }
1637
1638         /* 4 for RFC1001 length + 1 for BCC */
1639         rdata->iov[0].iov_base = smb;
1640         rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1641
1642         kref_get(&rdata->refcount);
1643         rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1644                              cifs_readv_receive, cifs_readv_callback,
1645                              rdata, 0);
1646
1647         if (rc == 0)
1648                 cifs_stats_inc(&tcon->num_reads);
1649         else
1650                 kref_put(&rdata->refcount, cifs_readdata_release);
1651
1652         cifs_small_buf_release(smb);
1653         return rc;
1654 }
1655
1656 int
1657 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1658             unsigned int *nbytes, char **buf, int *pbuf_type)
1659 {
1660         int rc = -EACCES;
1661         READ_REQ *pSMB = NULL;
1662         READ_RSP *pSMBr = NULL;
1663         char *pReadData = NULL;
1664         int wct;
1665         int resp_buf_type = 0;
1666         struct kvec iov[1];
1667         __u32 pid = io_parms->pid;
1668         __u16 netfid = io_parms->netfid;
1669         __u64 offset = io_parms->offset;
1670         struct cifs_tcon *tcon = io_parms->tcon;
1671         unsigned int count = io_parms->length;
1672
1673         cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1674         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1675                 wct = 12;
1676         else {
1677                 wct = 10; /* old style read */
1678                 if ((offset >> 32) > 0)  {
1679                         /* can not handle this big offset for old */
1680                         return -EIO;
1681                 }
1682         }
1683
1684         *nbytes = 0;
1685         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1686         if (rc)
1687                 return rc;
1688
1689         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1690         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1691
1692         /* tcon and ses pointer are checked in smb_init */
1693         if (tcon->ses->server == NULL)
1694                 return -ECONNABORTED;
1695
1696         pSMB->AndXCommand = 0xFF;       /* none */
1697         pSMB->Fid = netfid;
1698         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1699         if (wct == 12)
1700                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1701
1702         pSMB->Remaining = 0;
1703         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1704         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1705         if (wct == 12)
1706                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1707         else {
1708                 /* old style read */
1709                 struct smb_com_readx_req *pSMBW =
1710                         (struct smb_com_readx_req *)pSMB;
1711                 pSMBW->ByteCount = 0;
1712         }
1713
1714         iov[0].iov_base = (char *)pSMB;
1715         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1716         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1717                          &resp_buf_type, CIFS_LOG_ERROR);
1718         cifs_stats_inc(&tcon->num_reads);
1719         pSMBr = (READ_RSP *)iov[0].iov_base;
1720         if (rc) {
1721                 cERROR(1, "Send error in read = %d", rc);
1722         } else {
1723                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1724                 data_length = data_length << 16;
1725                 data_length += le16_to_cpu(pSMBr->DataLength);
1726                 *nbytes = data_length;
1727
1728                 /*check that DataLength would not go beyond end of SMB */
1729                 if ((data_length > CIFSMaxBufSize)
1730                                 || (data_length > count)) {
1731                         cFYI(1, "bad length %d for count %d",
1732                                  data_length, count);
1733                         rc = -EIO;
1734                         *nbytes = 0;
1735                 } else {
1736                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1737                                         le16_to_cpu(pSMBr->DataOffset);
1738 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1739                                 cERROR(1, "Faulting on read rc = %d",rc);
1740                                 rc = -EFAULT;
1741                         }*/ /* can not use copy_to_user when using page cache*/
1742                         if (*buf)
1743                                 memcpy(*buf, pReadData, data_length);
1744                 }
1745         }
1746
1747 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1748         if (*buf) {
1749                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1750                         cifs_small_buf_release(iov[0].iov_base);
1751                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1752                         cifs_buf_release(iov[0].iov_base);
1753         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1754                 /* return buffer to caller to free */
1755                 *buf = iov[0].iov_base;
1756                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1757                         *pbuf_type = CIFS_SMALL_BUFFER;
1758                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1759                         *pbuf_type = CIFS_LARGE_BUFFER;
1760         } /* else no valid buffer on return - leave as null */
1761
1762         /* Note: On -EAGAIN error only caller can retry on handle based calls
1763                 since file handle passed in no longer valid */
1764         return rc;
1765 }
1766
1767
1768 int
1769 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1770              unsigned int *nbytes, const char *buf,
1771              const char __user *ubuf, const int long_op)
1772 {
1773         int rc = -EACCES;
1774         WRITE_REQ *pSMB = NULL;
1775         WRITE_RSP *pSMBr = NULL;
1776         int bytes_returned, wct;
1777         __u32 bytes_sent;
1778         __u16 byte_count;
1779         __u32 pid = io_parms->pid;
1780         __u16 netfid = io_parms->netfid;
1781         __u64 offset = io_parms->offset;
1782         struct cifs_tcon *tcon = io_parms->tcon;
1783         unsigned int count = io_parms->length;
1784
1785         *nbytes = 0;
1786
1787         /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1788         if (tcon->ses == NULL)
1789                 return -ECONNABORTED;
1790
1791         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1792                 wct = 14;
1793         else {
1794                 wct = 12;
1795                 if ((offset >> 32) > 0) {
1796                         /* can not handle big offset for old srv */
1797                         return -EIO;
1798                 }
1799         }
1800
1801         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1802                       (void **) &pSMBr);
1803         if (rc)
1804                 return rc;
1805
1806         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1807         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1808
1809         /* tcon and ses pointer are checked in smb_init */
1810         if (tcon->ses->server == NULL)
1811                 return -ECONNABORTED;
1812
1813         pSMB->AndXCommand = 0xFF;       /* none */
1814         pSMB->Fid = netfid;
1815         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1816         if (wct == 14)
1817                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1818
1819         pSMB->Reserved = 0xFFFFFFFF;
1820         pSMB->WriteMode = 0;
1821         pSMB->Remaining = 0;
1822
1823         /* Can increase buffer size if buffer is big enough in some cases ie we
1824         can send more if LARGE_WRITE_X capability returned by the server and if
1825         our buffer is big enough or if we convert to iovecs on socket writes
1826         and eliminate the copy to the CIFS buffer */
1827         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1828                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1829         } else {
1830                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1831                          & ~0xFF;
1832         }
1833
1834         if (bytes_sent > count)
1835                 bytes_sent = count;
1836         pSMB->DataOffset =
1837                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1838         if (buf)
1839                 memcpy(pSMB->Data, buf, bytes_sent);
1840         else if (ubuf) {
1841                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1842                         cifs_buf_release(pSMB);
1843                         return -EFAULT;
1844                 }
1845         } else if (count != 0) {
1846                 /* No buffer */
1847                 cifs_buf_release(pSMB);
1848                 return -EINVAL;
1849         } /* else setting file size with write of zero bytes */
1850         if (wct == 14)
1851                 byte_count = bytes_sent + 1; /* pad */
1852         else /* wct == 12 */
1853                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1854
1855         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1856         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1857         inc_rfc1001_len(pSMB, byte_count);
1858
1859         if (wct == 14)
1860                 pSMB->ByteCount = cpu_to_le16(byte_count);
1861         else { /* old style write has byte count 4 bytes earlier
1862                   so 4 bytes pad  */
1863                 struct smb_com_writex_req *pSMBW =
1864                         (struct smb_com_writex_req *)pSMB;
1865                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1866         }
1867
1868         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1869                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1870         cifs_stats_inc(&tcon->num_writes);
1871         if (rc) {
1872                 cFYI(1, "Send error in write = %d", rc);
1873         } else {
1874                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1875                 *nbytes = (*nbytes) << 16;
1876                 *nbytes += le16_to_cpu(pSMBr->Count);
1877
1878                 /*
1879                  * Mask off high 16 bits when bytes written as returned by the
1880                  * server is greater than bytes requested by the client. Some
1881                  * OS/2 servers are known to set incorrect CountHigh values.
1882                  */
1883                 if (*nbytes > count)
1884                         *nbytes &= 0xFFFF;
1885         }
1886
1887         cifs_buf_release(pSMB);
1888
1889         /* Note: On -EAGAIN error only caller can retry on handle based calls
1890                 since file handle passed in no longer valid */
1891
1892         return rc;
1893 }
1894
1895 void
1896 cifs_writedata_release(struct kref *refcount)
1897 {
1898         struct cifs_writedata *wdata = container_of(refcount,
1899                                         struct cifs_writedata, refcount);
1900
1901         if (wdata->cfile)
1902                 cifsFileInfo_put(wdata->cfile);
1903
1904         kfree(wdata);
1905 }
1906
1907 /*
1908  * Write failed with a retryable error. Resend the write request. It's also
1909  * possible that the page was redirtied so re-clean the page.
1910  */
1911 static void
1912 cifs_writev_requeue(struct cifs_writedata *wdata)
1913 {
1914         int i, rc;
1915         struct inode *inode = wdata->cfile->dentry->d_inode;
1916
1917         for (i = 0; i < wdata->nr_pages; i++) {
1918                 lock_page(wdata->pages[i]);
1919                 clear_page_dirty_for_io(wdata->pages[i]);
1920         }
1921
1922         do {
1923                 rc = cifs_async_writev(wdata);
1924         } while (rc == -EAGAIN);
1925
1926         for (i = 0; i < wdata->nr_pages; i++) {
1927                 if (rc != 0)
1928                         SetPageError(wdata->pages[i]);
1929                 unlock_page(wdata->pages[i]);
1930         }
1931
1932         mapping_set_error(inode->i_mapping, rc);
1933         kref_put(&wdata->refcount, cifs_writedata_release);
1934 }
1935
1936 void
1937 cifs_writev_complete(struct work_struct *work)
1938 {
1939         struct cifs_writedata *wdata = container_of(work,
1940                                                 struct cifs_writedata, work);
1941         struct inode *inode = wdata->cfile->dentry->d_inode;
1942         int i = 0;
1943
1944         if (wdata->result == 0) {
1945                 spin_lock(&inode->i_lock);
1946                 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1947                 spin_unlock(&inode->i_lock);
1948                 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1949                                          wdata->bytes);
1950         } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1951                 return cifs_writev_requeue(wdata);
1952
1953         for (i = 0; i < wdata->nr_pages; i++) {
1954                 struct page *page = wdata->pages[i];
1955                 if (wdata->result == -EAGAIN)
1956                         __set_page_dirty_nobuffers(page);
1957                 else if (wdata->result < 0)
1958                         SetPageError(page);
1959                 end_page_writeback(page);
1960                 page_cache_release(page);
1961         }
1962         if (wdata->result != -EAGAIN)
1963                 mapping_set_error(inode->i_mapping, wdata->result);
1964         kref_put(&wdata->refcount, cifs_writedata_release);
1965 }
1966
1967 struct cifs_writedata *
1968 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1969 {
1970         struct cifs_writedata *wdata;
1971
1972         /* this would overflow */
1973         if (nr_pages == 0) {
1974                 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1975                 return NULL;
1976         }
1977
1978         /* writedata + number of page pointers */
1979         wdata = kzalloc(sizeof(*wdata) +
1980                         sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1981         if (wdata != NULL) {
1982                 kref_init(&wdata->refcount);
1983                 INIT_LIST_HEAD(&wdata->list);
1984                 init_completion(&wdata->done);
1985                 INIT_WORK(&wdata->work, complete);
1986         }
1987         return wdata;
1988 }
1989
1990 /*
1991  * Check the mid_state and signature on received buffer (if any), and queue the
1992  * workqueue completion task.
1993  */
1994 static void
1995 cifs_writev_callback(struct mid_q_entry *mid)
1996 {
1997         struct cifs_writedata *wdata = mid->callback_data;
1998         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1999         unsigned int written;
2000         WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2001
2002         switch (mid->mid_state) {
2003         case MID_RESPONSE_RECEIVED:
2004                 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2005                 if (wdata->result != 0)
2006                         break;
2007
2008                 written = le16_to_cpu(smb->CountHigh);
2009                 written <<= 16;
2010                 written += le16_to_cpu(smb->Count);
2011                 /*
2012                  * Mask off high 16 bits when bytes written as returned
2013                  * by the server is greater than bytes requested by the
2014                  * client. OS/2 servers are known to set incorrect
2015                  * CountHigh values.
2016                  */
2017                 if (written > wdata->bytes)
2018                         written &= 0xFFFF;
2019
2020                 if (written < wdata->bytes)
2021                         wdata->result = -ENOSPC;
2022                 else
2023                         wdata->bytes = written;
2024                 break;
2025         case MID_REQUEST_SUBMITTED:
2026         case MID_RETRY_NEEDED:
2027                 wdata->result = -EAGAIN;
2028                 break;
2029         default:
2030                 wdata->result = -EIO;
2031                 break;
2032         }
2033
2034         queue_work(cifsiod_wq, &wdata->work);
2035         DeleteMidQEntry(mid);
2036         add_credits(tcon->ses->server, 1, 0);
2037 }
2038
2039 /* cifs_async_writev - send an async write, and set up mid to handle result */
2040 int
2041 cifs_async_writev(struct cifs_writedata *wdata)
2042 {
2043         int i, rc = -EACCES;
2044         WRITE_REQ *smb = NULL;
2045         int wct;
2046         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2047         struct kvec *iov = NULL;
2048
2049         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2050                 wct = 14;
2051         } else {
2052                 wct = 12;
2053                 if (wdata->offset >> 32 > 0) {
2054                         /* can not handle big offset for old srv */
2055                         return -EIO;
2056                 }
2057         }
2058
2059         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2060         if (rc)
2061                 goto async_writev_out;
2062
2063         /* 1 iov per page + 1 for header */
2064         iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2065         if (iov == NULL) {
2066                 rc = -ENOMEM;
2067                 goto async_writev_out;
2068         }
2069
2070         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2071         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2072
2073         smb->AndXCommand = 0xFF;        /* none */
2074         smb->Fid = wdata->cfile->netfid;
2075         smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2076         if (wct == 14)
2077                 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2078         smb->Reserved = 0xFFFFFFFF;
2079         smb->WriteMode = 0;
2080         smb->Remaining = 0;
2081
2082         smb->DataOffset =
2083             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2084
2085         /* 4 for RFC1001 length + 1 for BCC */
2086         iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2087         iov[0].iov_base = smb;
2088
2089         /*
2090          * This function should marshal up the page array into the kvec
2091          * array, reserving [0] for the header. It should kmap the pages
2092          * and set the iov_len properly for each one. It may also set
2093          * wdata->bytes too.
2094          */
2095         cifs_kmap_lock();
2096         wdata->marshal_iov(iov, wdata);
2097         cifs_kmap_unlock();
2098
2099         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2100
2101         smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2102         smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2103
2104         if (wct == 14) {
2105                 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2106                 put_bcc(wdata->bytes + 1, &smb->hdr);
2107         } else {
2108                 /* wct == 12 */
2109                 struct smb_com_writex_req *smbw =
2110                                 (struct smb_com_writex_req *)smb;
2111                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2112                 put_bcc(wdata->bytes + 5, &smbw->hdr);
2113                 iov[0].iov_len += 4; /* pad bigger by four bytes */
2114         }
2115
2116         kref_get(&wdata->refcount);
2117         rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2118                              NULL, cifs_writev_callback, wdata, 0);
2119
2120         if (rc == 0)
2121                 cifs_stats_inc(&tcon->num_writes);
2122         else
2123                 kref_put(&wdata->refcount, cifs_writedata_release);
2124
2125         /* send is done, unmap pages */
2126         for (i = 0; i < wdata->nr_pages; i++)
2127                 kunmap(wdata->pages[i]);
2128
2129 async_writev_out:
2130         cifs_small_buf_release(smb);
2131         kfree(iov);
2132         return rc;
2133 }
2134
2135 int
2136 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2137               unsigned int *nbytes, struct kvec *iov, int n_vec,
2138               const int long_op)
2139 {
2140         int rc = -EACCES;
2141         WRITE_REQ *pSMB = NULL;
2142         int wct;
2143         int smb_hdr_len;
2144         int resp_buf_type = 0;
2145         __u32 pid = io_parms->pid;
2146         __u16 netfid = io_parms->netfid;
2147         __u64 offset = io_parms->offset;
2148         struct cifs_tcon *tcon = io_parms->tcon;
2149         unsigned int count = io_parms->length;
2150
2151         *nbytes = 0;
2152
2153         cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2154
2155         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2156                 wct = 14;
2157         } else {
2158                 wct = 12;
2159                 if ((offset >> 32) > 0) {
2160                         /* can not handle big offset for old srv */
2161                         return -EIO;
2162                 }
2163         }
2164         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2165         if (rc)
2166                 return rc;
2167
2168         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2169         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2170
2171         /* tcon and ses pointer are checked in smb_init */
2172         if (tcon->ses->server == NULL)
2173                 return -ECONNABORTED;
2174
2175         pSMB->AndXCommand = 0xFF;       /* none */
2176         pSMB->Fid = netfid;
2177         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2178         if (wct == 14)
2179                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2180         pSMB->Reserved = 0xFFFFFFFF;
2181         pSMB->WriteMode = 0;
2182         pSMB->Remaining = 0;
2183
2184         pSMB->DataOffset =
2185             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2186
2187         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2188         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2189         /* header + 1 byte pad */
2190         smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2191         if (wct == 14)
2192                 inc_rfc1001_len(pSMB, count + 1);
2193         else /* wct == 12 */
2194                 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2195         if (wct == 14)
2196                 pSMB->ByteCount = cpu_to_le16(count + 1);
2197         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2198                 struct smb_com_writex_req *pSMBW =
2199                                 (struct smb_com_writex_req *)pSMB;
2200                 pSMBW->ByteCount = cpu_to_le16(count + 5);
2201         }
2202         iov[0].iov_base = pSMB;
2203         if (wct == 14)
2204                 iov[0].iov_len = smb_hdr_len + 4;
2205         else /* wct == 12 pad bigger by four bytes */
2206                 iov[0].iov_len = smb_hdr_len + 8;
2207
2208
2209         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2210                           long_op);
2211         cifs_stats_inc(&tcon->num_writes);
2212         if (rc) {
2213                 cFYI(1, "Send error Write2 = %d", rc);
2214         } else if (resp_buf_type == 0) {
2215                 /* presumably this can not happen, but best to be safe */
2216                 rc = -EIO;
2217         } else {
2218                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2219                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2220                 *nbytes = (*nbytes) << 16;
2221                 *nbytes += le16_to_cpu(pSMBr->Count);
2222
2223                 /*
2224                  * Mask off high 16 bits when bytes written as returned by the
2225                  * server is greater than bytes requested by the client. OS/2
2226                  * servers are known to set incorrect CountHigh values.
2227                  */
2228                 if (*nbytes > count)
2229                         *nbytes &= 0xFFFF;
2230         }
2231
2232 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2233         if (resp_buf_type == CIFS_SMALL_BUFFER)
2234                 cifs_small_buf_release(iov[0].iov_base);
2235         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2236                 cifs_buf_release(iov[0].iov_base);
2237
2238         /* Note: On -EAGAIN error only caller can retry on handle based calls
2239                 since file handle passed in no longer valid */
2240
2241         return rc;
2242 }
2243
2244 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2245                const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2246                const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2247 {
2248         int rc = 0;
2249         LOCK_REQ *pSMB = NULL;
2250         struct kvec iov[2];
2251         int resp_buf_type;
2252         __u16 count;
2253
2254         cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2255
2256         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2257         if (rc)
2258                 return rc;
2259
2260         pSMB->Timeout = 0;
2261         pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2262         pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2263         pSMB->LockType = lock_type;
2264         pSMB->AndXCommand = 0xFF; /* none */
2265         pSMB->Fid = netfid; /* netfid stays le */
2266
2267         count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2268         inc_rfc1001_len(pSMB, count);
2269         pSMB->ByteCount = cpu_to_le16(count);
2270
2271         iov[0].iov_base = (char *)pSMB;
2272         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2273                          (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2274         iov[1].iov_base = (char *)buf;
2275         iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2276
2277         cifs_stats_inc(&tcon->num_locks);
2278         rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2279         if (rc)
2280                 cFYI(1, "Send error in cifs_lockv = %d", rc);
2281
2282         return rc;
2283 }
2284
2285 int
2286 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2287             const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2288             const __u64 offset, const __u32 numUnlock,
2289             const __u32 numLock, const __u8 lockType,
2290             const bool waitFlag, const __u8 oplock_level)
2291 {
2292         int rc = 0;
2293         LOCK_REQ *pSMB = NULL;
2294 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2295         int bytes_returned;
2296         int flags = 0;
2297         __u16 count;
2298
2299         cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2300         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2301
2302         if (rc)
2303                 return rc;
2304
2305         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2306                 /* no response expected */
2307                 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2308                 pSMB->Timeout = 0;
2309         } else if (waitFlag) {
2310                 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2311                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2312         } else {
2313                 pSMB->Timeout = 0;
2314         }
2315
2316         pSMB->NumberOfLocks = cpu_to_le16(numLock);
2317         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2318         pSMB->LockType = lockType;
2319         pSMB->OplockLevel = oplock_level;
2320         pSMB->AndXCommand = 0xFF;       /* none */
2321         pSMB->Fid = smb_file_id; /* netfid stays le */
2322
2323         if ((numLock != 0) || (numUnlock != 0)) {
2324                 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2325                 /* BB where to store pid high? */
2326                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2327                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2328                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2329                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2330                 count = sizeof(LOCKING_ANDX_RANGE);
2331         } else {
2332                 /* oplock break */
2333                 count = 0;
2334         }
2335         inc_rfc1001_len(pSMB, count);
2336         pSMB->ByteCount = cpu_to_le16(count);
2337
2338         if (waitFlag) {
2339                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2340                         (struct smb_hdr *) pSMB, &bytes_returned);
2341                 cifs_small_buf_release(pSMB);
2342         } else {
2343                 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2344                 /* SMB buffer freed by function above */
2345         }
2346         cifs_stats_inc(&tcon->num_locks);
2347         if (rc)
2348                 cFYI(1, "Send error in Lock = %d", rc);
2349
2350         /* Note: On -EAGAIN error only caller can retry on handle based calls
2351         since file handle passed in no longer valid */
2352         return rc;
2353 }
2354
2355 int
2356 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2357                 const __u16 smb_file_id, const __u32 netpid,
2358                 const loff_t start_offset, const __u64 len,
2359                 struct file_lock *pLockData, const __u16 lock_type,
2360                 const bool waitFlag)
2361 {
2362         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2363         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2364         struct cifs_posix_lock *parm_data;
2365         int rc = 0;
2366         int timeout = 0;
2367         int bytes_returned = 0;
2368         int resp_buf_type = 0;
2369         __u16 params, param_offset, offset, byte_count, count;
2370         struct kvec iov[1];
2371
2372         cFYI(1, "Posix Lock");
2373
2374         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2375
2376         if (rc)
2377                 return rc;
2378
2379         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2380
2381         params = 6;
2382         pSMB->MaxSetupCount = 0;
2383         pSMB->Reserved = 0;
2384         pSMB->Flags = 0;
2385         pSMB->Reserved2 = 0;
2386         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2387         offset = param_offset + params;
2388
2389         count = sizeof(struct cifs_posix_lock);
2390         pSMB->MaxParameterCount = cpu_to_le16(2);
2391         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2392         pSMB->SetupCount = 1;
2393         pSMB->Reserved3 = 0;
2394         if (pLockData)
2395                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2396         else
2397                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2398         byte_count = 3 /* pad */  + params + count;
2399         pSMB->DataCount = cpu_to_le16(count);
2400         pSMB->ParameterCount = cpu_to_le16(params);
2401         pSMB->TotalDataCount = pSMB->DataCount;
2402         pSMB->TotalParameterCount = pSMB->ParameterCount;
2403         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2404         parm_data = (struct cifs_posix_lock *)
2405                         (((char *) &pSMB->hdr.Protocol) + offset);
2406
2407         parm_data->lock_type = cpu_to_le16(lock_type);
2408         if (waitFlag) {
2409                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2410                 parm_data->lock_flags = cpu_to_le16(1);
2411                 pSMB->Timeout = cpu_to_le32(-1);
2412         } else
2413                 pSMB->Timeout = 0;
2414
2415         parm_data->pid = cpu_to_le32(netpid);
2416         parm_data->start = cpu_to_le64(start_offset);
2417         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2418
2419         pSMB->DataOffset = cpu_to_le16(offset);
2420         pSMB->Fid = smb_file_id;
2421         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2422         pSMB->Reserved4 = 0;
2423         inc_rfc1001_len(pSMB, byte_count);
2424         pSMB->ByteCount = cpu_to_le16(byte_count);
2425         if (waitFlag) {
2426                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2427                         (struct smb_hdr *) pSMBr, &bytes_returned);
2428         } else {
2429                 iov[0].iov_base = (char *)pSMB;
2430                 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2431                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2432                                 &resp_buf_type, timeout);
2433                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2434                                 not try to free it twice below on exit */
2435                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2436         }
2437
2438         if (rc) {
2439                 cFYI(1, "Send error in Posix Lock = %d", rc);
2440         } else if (pLockData) {
2441                 /* lock structure can be returned on get */
2442                 __u16 data_offset;
2443                 __u16 data_count;
2444                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2445
2446                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2447                         rc = -EIO;      /* bad smb */
2448                         goto plk_err_exit;
2449                 }
2450                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2451                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2452                 if (data_count < sizeof(struct cifs_posix_lock)) {
2453                         rc = -EIO;
2454                         goto plk_err_exit;
2455                 }
2456                 parm_data = (struct cifs_posix_lock *)
2457                         ((char *)&pSMBr->hdr.Protocol + data_offset);
2458                 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2459                         pLockData->fl_type = F_UNLCK;
2460                 else {
2461                         if (parm_data->lock_type ==
2462                                         __constant_cpu_to_le16(CIFS_RDLCK))
2463                                 pLockData->fl_type = F_RDLCK;
2464                         else if (parm_data->lock_type ==
2465                                         __constant_cpu_to_le16(CIFS_WRLCK))
2466                                 pLockData->fl_type = F_WRLCK;
2467
2468                         pLockData->fl_start = le64_to_cpu(parm_data->start);
2469                         pLockData->fl_end = pLockData->fl_start +
2470                                         le64_to_cpu(parm_data->length) - 1;
2471                         pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2472                 }
2473         }
2474
2475 plk_err_exit:
2476         if (pSMB)
2477                 cifs_small_buf_release(pSMB);
2478
2479         if (resp_buf_type == CIFS_SMALL_BUFFER)
2480                 cifs_small_buf_release(iov[0].iov_base);
2481         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2482                 cifs_buf_release(iov[0].iov_base);
2483
2484         /* Note: On -EAGAIN error only caller can retry on handle based calls
2485            since file handle passed in no longer valid */
2486
2487         return rc;
2488 }
2489
2490
2491 int
2492 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2493 {
2494         int rc = 0;
2495         CLOSE_REQ *pSMB = NULL;
2496         cFYI(1, "In CIFSSMBClose");
2497
2498 /* do not retry on dead session on close */
2499         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2500         if (rc == -EAGAIN)
2501                 return 0;
2502         if (rc)
2503                 return rc;
2504
2505         pSMB->FileID = (__u16) smb_file_id;
2506         pSMB->LastWriteTime = 0xFFFFFFFF;
2507         pSMB->ByteCount = 0;
2508         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2509         cifs_stats_inc(&tcon->num_closes);
2510         if (rc) {
2511                 if (rc != -EINTR) {
2512                         /* EINTR is expected when user ctl-c to kill app */
2513                         cERROR(1, "Send error in Close = %d", rc);
2514                 }
2515         }
2516
2517         /* Since session is dead, file will be closed on server already */
2518         if (rc == -EAGAIN)
2519                 rc = 0;
2520
2521         return rc;
2522 }
2523
2524 int
2525 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2526 {
2527         int rc = 0;
2528         FLUSH_REQ *pSMB = NULL;
2529         cFYI(1, "In CIFSSMBFlush");
2530
2531         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2532         if (rc)
2533                 return rc;
2534
2535         pSMB->FileID = (__u16) smb_file_id;
2536         pSMB->ByteCount = 0;
2537         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2538         cifs_stats_inc(&tcon->num_flushes);
2539         if (rc)
2540                 cERROR(1, "Send error in Flush = %d", rc);
2541
2542         return rc;
2543 }
2544
2545 int
2546 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2547               const char *fromName, const char *toName,
2548               const struct nls_table *nls_codepage, int remap)
2549 {
2550         int rc = 0;
2551         RENAME_REQ *pSMB = NULL;
2552         RENAME_RSP *pSMBr = NULL;
2553         int bytes_returned;
2554         int name_len, name_len2;
2555         __u16 count;
2556
2557         cFYI(1, "In CIFSSMBRename");
2558 renameRetry:
2559         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2560                       (void **) &pSMBr);
2561         if (rc)
2562                 return rc;
2563
2564         pSMB->BufferFormat = 0x04;
2565         pSMB->SearchAttributes =
2566             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2567                         ATTR_DIRECTORY);
2568
2569         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2570                 name_len =
2571                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2572                                        PATH_MAX, nls_codepage, remap);
2573                 name_len++;     /* trailing null */
2574                 name_len *= 2;
2575                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2576         /* protocol requires ASCII signature byte on Unicode string */
2577                 pSMB->OldFileName[name_len + 1] = 0x00;
2578                 name_len2 =
2579                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2580                                        toName, PATH_MAX, nls_codepage, remap);
2581                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2582                 name_len2 *= 2; /* convert to bytes */
2583         } else {        /* BB improve the check for buffer overruns BB */
2584                 name_len = strnlen(fromName, PATH_MAX);
2585                 name_len++;     /* trailing null */
2586                 strncpy(pSMB->OldFileName, fromName, name_len);
2587                 name_len2 = strnlen(toName, PATH_MAX);
2588                 name_len2++;    /* trailing null */
2589                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2590                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2591                 name_len2++;    /* trailing null */
2592                 name_len2++;    /* signature byte */
2593         }
2594
2595         count = 1 /* 1st signature byte */  + name_len + name_len2;
2596         inc_rfc1001_len(pSMB, count);
2597         pSMB->ByteCount = cpu_to_le16(count);
2598
2599         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2600                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2601         cifs_stats_inc(&tcon->num_renames);
2602         if (rc)
2603                 cFYI(1, "Send error in rename = %d", rc);
2604
2605         cifs_buf_release(pSMB);
2606
2607         if (rc == -EAGAIN)
2608                 goto renameRetry;
2609
2610         return rc;
2611 }
2612
2613 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2614                 int netfid, const char *target_name,
2615                 const struct nls_table *nls_codepage, int remap)
2616 {
2617         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2618         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2619         struct set_file_rename *rename_info;
2620         char *data_offset;
2621         char dummy_string[30];
2622         int rc = 0;
2623         int bytes_returned = 0;
2624         int len_of_str;
2625         __u16 params, param_offset, offset, count, byte_count;
2626
2627         cFYI(1, "Rename to File by handle");
2628         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2629                         (void **) &pSMBr);
2630         if (rc)
2631                 return rc;
2632
2633         params = 6;
2634         pSMB->MaxSetupCount = 0;
2635         pSMB->Reserved = 0;
2636         pSMB->Flags = 0;
2637         pSMB->Timeout = 0;
2638         pSMB->Reserved2 = 0;
2639         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2640         offset = param_offset + params;
2641
2642         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2643         rename_info = (struct set_file_rename *) data_offset;
2644         pSMB->MaxParameterCount = cpu_to_le16(2);
2645         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2646         pSMB->SetupCount = 1;
2647         pSMB->Reserved3 = 0;
2648         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2649         byte_count = 3 /* pad */  + params;
2650         pSMB->ParameterCount = cpu_to_le16(params);
2651         pSMB->TotalParameterCount = pSMB->ParameterCount;
2652         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2653         pSMB->DataOffset = cpu_to_le16(offset);
2654         /* construct random name ".cifs_tmp<inodenum><mid>" */
2655         rename_info->overwrite = cpu_to_le32(1);
2656         rename_info->root_fid  = 0;
2657         /* unicode only call */
2658         if (target_name == NULL) {
2659                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2660                 len_of_str =
2661                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2662                                         dummy_string, 24, nls_codepage, remap);
2663         } else {
2664                 len_of_str =
2665                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2666                                         target_name, PATH_MAX, nls_codepage,
2667                                         remap);
2668         }
2669         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2670         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2671         byte_count += count;
2672         pSMB->DataCount = cpu_to_le16(count);
2673         pSMB->TotalDataCount = pSMB->DataCount;
2674         pSMB->Fid = netfid;
2675         pSMB->InformationLevel =
2676                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2677         pSMB->Reserved4 = 0;
2678         inc_rfc1001_len(pSMB, byte_count);
2679         pSMB->ByteCount = cpu_to_le16(byte_count);
2680         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2681                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2682         cifs_stats_inc(&pTcon->num_t2renames);
2683         if (rc)
2684                 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2685
2686         cifs_buf_release(pSMB);
2687
2688         /* Note: On -EAGAIN error only caller can retry on handle based calls
2689                 since file handle passed in no longer valid */
2690
2691         return rc;
2692 }
2693
2694 int
2695 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2696             const char *fromName, const __u16 target_tid, const char *toName,
2697             const int flags, const struct nls_table *nls_codepage, int remap)
2698 {
2699         int rc = 0;
2700         COPY_REQ *pSMB = NULL;
2701         COPY_RSP *pSMBr = NULL;
2702         int bytes_returned;
2703         int name_len, name_len2;
2704         __u16 count;
2705
2706         cFYI(1, "In CIFSSMBCopy");
2707 copyRetry:
2708         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2709                         (void **) &pSMBr);
2710         if (rc)
2711                 return rc;
2712
2713         pSMB->BufferFormat = 0x04;
2714         pSMB->Tid2 = target_tid;
2715
2716         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2717
2718         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2719                 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2720                                               fromName, PATH_MAX, nls_codepage,
2721                                               remap);
2722                 name_len++;     /* trailing null */
2723                 name_len *= 2;
2724                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2725                 /* protocol requires ASCII signature byte on Unicode string */
2726                 pSMB->OldFileName[name_len + 1] = 0x00;
2727                 name_len2 =
2728                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2729                                        toName, PATH_MAX, nls_codepage, remap);
2730                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2731                 name_len2 *= 2; /* convert to bytes */
2732         } else {        /* BB improve the check for buffer overruns BB */
2733                 name_len = strnlen(fromName, PATH_MAX);
2734                 name_len++;     /* trailing null */
2735                 strncpy(pSMB->OldFileName, fromName, name_len);
2736                 name_len2 = strnlen(toName, PATH_MAX);
2737                 name_len2++;    /* trailing null */
2738                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2739                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2740                 name_len2++;    /* trailing null */
2741                 name_len2++;    /* signature byte */
2742         }
2743
2744         count = 1 /* 1st signature byte */  + name_len + name_len2;
2745         inc_rfc1001_len(pSMB, count);
2746         pSMB->ByteCount = cpu_to_le16(count);
2747
2748         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2749                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2750         if (rc) {
2751                 cFYI(1, "Send error in copy = %d with %d files copied",
2752                         rc, le16_to_cpu(pSMBr->CopyCount));
2753         }
2754         cifs_buf_release(pSMB);
2755
2756         if (rc == -EAGAIN)
2757                 goto copyRetry;
2758
2759         return rc;
2760 }
2761
2762 int
2763 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2764                       const char *fromName, const char *toName,
2765                       const struct nls_table *nls_codepage)
2766 {
2767         TRANSACTION2_SPI_REQ *pSMB = NULL;
2768         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2769         char *data_offset;
2770         int name_len;
2771         int name_len_target;
2772         int rc = 0;
2773         int bytes_returned = 0;
2774         __u16 params, param_offset, offset, byte_count;
2775
2776         cFYI(1, "In Symlink Unix style");
2777 createSymLinkRetry:
2778         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2779                       (void **) &pSMBr);
2780         if (rc)
2781                 return rc;
2782
2783         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2784                 name_len =
2785                     cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2786                                     /* find define for this maxpathcomponent */
2787                                     PATH_MAX, nls_codepage);
2788                 name_len++;     /* trailing null */
2789                 name_len *= 2;
2790
2791         } else {        /* BB improve the check for buffer overruns BB */
2792                 name_len = strnlen(fromName, PATH_MAX);
2793                 name_len++;     /* trailing null */
2794                 strncpy(pSMB->FileName, fromName, name_len);
2795         }
2796         params = 6 + name_len;
2797         pSMB->MaxSetupCount = 0;
2798         pSMB->Reserved = 0;
2799         pSMB->Flags = 0;
2800         pSMB->Timeout = 0;
2801         pSMB->Reserved2 = 0;
2802         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2803                                 InformationLevel) - 4;
2804         offset = param_offset + params;
2805
2806         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2807         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2808                 name_len_target =
2809                     cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2810                                     /* find define for this maxpathcomponent */
2811                                     , nls_codepage);
2812                 name_len_target++;      /* trailing null */
2813                 name_len_target *= 2;
2814         } else {        /* BB improve the check for buffer overruns BB */
2815                 name_len_target = strnlen(toName, PATH_MAX);
2816                 name_len_target++;      /* trailing null */
2817                 strncpy(data_offset, toName, name_len_target);
2818         }
2819
2820         pSMB->MaxParameterCount = cpu_to_le16(2);
2821         /* BB find exact max on data count below from sess */
2822         pSMB->MaxDataCount = cpu_to_le16(1000);
2823         pSMB->SetupCount = 1;
2824         pSMB->Reserved3 = 0;
2825         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2826         byte_count = 3 /* pad */  + params + name_len_target;
2827         pSMB->DataCount = cpu_to_le16(name_len_target);
2828         pSMB->ParameterCount = cpu_to_le16(params);
2829         pSMB->TotalDataCount = pSMB->DataCount;
2830         pSMB->TotalParameterCount = pSMB->ParameterCount;
2831         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2832         pSMB->DataOffset = cpu_to_le16(offset);
2833         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2834         pSMB->Reserved4 = 0;
2835         inc_rfc1001_len(pSMB, byte_count);
2836         pSMB->ByteCount = cpu_to_le16(byte_count);
2837         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2838                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2839         cifs_stats_inc(&tcon->num_symlinks);
2840         if (rc)
2841                 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2842
2843         cifs_buf_release(pSMB);
2844
2845         if (rc == -EAGAIN)
2846                 goto createSymLinkRetry;
2847
2848         return rc;
2849 }
2850
2851 int
2852 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2853                        const char *fromName, const char *toName,
2854                        const struct nls_table *nls_codepage, int remap)
2855 {
2856         TRANSACTION2_SPI_REQ *pSMB = NULL;
2857         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2858         char *data_offset;
2859         int name_len;
2860         int name_len_target;
2861         int rc = 0;
2862         int bytes_returned = 0;
2863         __u16 params, param_offset, offset, byte_count;
2864
2865         cFYI(1, "In Create Hard link Unix style");
2866 createHardLinkRetry:
2867         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2868                       (void **) &pSMBr);
2869         if (rc)
2870                 return rc;
2871
2872         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2873                 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2874                                               PATH_MAX, nls_codepage, remap);
2875                 name_len++;     /* trailing null */
2876                 name_len *= 2;
2877
2878         } else {        /* BB improve the check for buffer overruns BB */
2879                 name_len = strnlen(toName, PATH_MAX);
2880                 name_len++;     /* trailing null */
2881                 strncpy(pSMB->FileName, toName, name_len);
2882         }
2883         params = 6 + name_len;
2884         pSMB->MaxSetupCount = 0;
2885         pSMB->Reserved = 0;
2886         pSMB->Flags = 0;
2887         pSMB->Timeout = 0;
2888         pSMB->Reserved2 = 0;
2889         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2890                                 InformationLevel) - 4;
2891         offset = param_offset + params;
2892
2893         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2894         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2895                 name_len_target =
2896                     cifsConvertToUTF16((__le16 *) data_offset, fromName,
2897                                        PATH_MAX, nls_codepage, remap);
2898                 name_len_target++;      /* trailing null */
2899                 name_len_target *= 2;
2900         } else {        /* BB improve the check for buffer overruns BB */
2901                 name_len_target = strnlen(fromName, PATH_MAX);
2902                 name_len_target++;      /* trailing null */
2903                 strncpy(data_offset, fromName, name_len_target);
2904         }
2905
2906         pSMB->MaxParameterCount = cpu_to_le16(2);
2907         /* BB find exact max on data count below from sess*/
2908         pSMB->MaxDataCount = cpu_to_le16(1000);
2909         pSMB->SetupCount = 1;
2910         pSMB->Reserved3 = 0;
2911         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2912         byte_count = 3 /* pad */  + params + name_len_target;
2913         pSMB->ParameterCount = cpu_to_le16(params);
2914         pSMB->TotalParameterCount = pSMB->ParameterCount;
2915         pSMB->DataCount = cpu_to_le16(name_len_target);
2916         pSMB->TotalDataCount = pSMB->DataCount;
2917         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2918         pSMB->DataOffset = cpu_to_le16(offset);
2919         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2920         pSMB->Reserved4 = 0;
2921         inc_rfc1001_len(pSMB, byte_count);
2922         pSMB->ByteCount = cpu_to_le16(byte_count);
2923         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2924                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2925         cifs_stats_inc(&tcon->num_hardlinks);
2926         if (rc)
2927                 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2928
2929         cifs_buf_release(pSMB);
2930         if (rc == -EAGAIN)
2931                 goto createHardLinkRetry;
2932
2933         return rc;
2934 }
2935
2936 int
2937 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2938                    const char *fromName, const char *toName,
2939                    const struct nls_table *nls_codepage, int remap)
2940 {
2941         int rc = 0;
2942         NT_RENAME_REQ *pSMB = NULL;
2943         RENAME_RSP *pSMBr = NULL;
2944         int bytes_returned;
2945         int name_len, name_len2;
2946         __u16 count;
2947
2948         cFYI(1, "In CIFSCreateHardLink");
2949 winCreateHardLinkRetry:
2950
2951         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2952                       (void **) &pSMBr);
2953         if (rc)
2954                 return rc;
2955
2956         pSMB->SearchAttributes =
2957             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2958                         ATTR_DIRECTORY);
2959         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2960         pSMB->ClusterCount = 0;
2961
2962         pSMB->BufferFormat = 0x04;
2963
2964         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2965                 name_len =
2966                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2967                                        PATH_MAX, nls_codepage, remap);
2968                 name_len++;     /* trailing null */
2969                 name_len *= 2;
2970
2971                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2972                 pSMB->OldFileName[name_len] = 0x04;
2973                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2974                 name_len2 =
2975                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2976                                        toName, PATH_MAX, nls_codepage, remap);
2977                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2978                 name_len2 *= 2; /* convert to bytes */
2979         } else {        /* BB improve the check for buffer overruns BB */
2980                 name_len = strnlen(fromName, PATH_MAX);
2981                 name_len++;     /* trailing null */
2982                 strncpy(pSMB->OldFileName, fromName, name_len);
2983                 name_len2 = strnlen(toName, PATH_MAX);
2984                 name_len2++;    /* trailing null */
2985                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2986                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2987                 name_len2++;    /* trailing null */
2988                 name_len2++;    /* signature byte */
2989         }
2990
2991         count = 1 /* string type byte */  + name_len + name_len2;
2992         inc_rfc1001_len(pSMB, count);
2993         pSMB->ByteCount = cpu_to_le16(count);
2994
2995         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2996                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2997         cifs_stats_inc(&tcon->num_hardlinks);
2998         if (rc)
2999                 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3000
3001         cifs_buf_release(pSMB);
3002         if (rc == -EAGAIN)
3003                 goto winCreateHardLinkRetry;
3004
3005         return rc;
3006 }
3007
3008 int
3009 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3010                         const unsigned char *searchName, char **symlinkinfo,
3011                         const struct nls_table *nls_codepage)
3012 {
3013 /* SMB_QUERY_FILE_UNIX_LINK */
3014         TRANSACTION2_QPI_REQ *pSMB = NULL;
3015         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3016         int rc = 0;
3017         int bytes_returned;
3018         int name_len;
3019         __u16 params, byte_count;
3020         char *data_start;
3021
3022         cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3023
3024 querySymLinkRetry:
3025         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3026                       (void **) &pSMBr);
3027         if (rc)
3028                 return rc;
3029
3030         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3031                 name_len =
3032                         cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3033                                         PATH_MAX, nls_codepage);
3034                 name_len++;     /* trailing null */
3035                 name_len *= 2;
3036         } else {        /* BB improve the check for buffer overruns BB */
3037                 name_len = strnlen(searchName, PATH_MAX);
3038                 name_len++;     /* trailing null */
3039                 strncpy(pSMB->FileName, searchName, name_len);
3040         }
3041
3042         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3043         pSMB->TotalDataCount = 0;
3044         pSMB->MaxParameterCount = cpu_to_le16(2);
3045         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3046         pSMB->MaxSetupCount = 0;
3047         pSMB->Reserved = 0;
3048         pSMB->Flags = 0;
3049         pSMB->Timeout = 0;
3050         pSMB->Reserved2 = 0;
3051         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3052         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3053         pSMB->DataCount = 0;
3054         pSMB->DataOffset = 0;
3055         pSMB->SetupCount = 1;
3056         pSMB->Reserved3 = 0;
3057         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3058         byte_count = params + 1 /* pad */ ;
3059         pSMB->TotalParameterCount = cpu_to_le16(params);
3060         pSMB->ParameterCount = pSMB->TotalParameterCount;
3061         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3062         pSMB->Reserved4 = 0;
3063         inc_rfc1001_len(pSMB, byte_count);
3064         pSMB->ByteCount = cpu_to_le16(byte_count);
3065
3066         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3067                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3068         if (rc) {
3069                 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3070         } else {
3071                 /* decode response */
3072
3073                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3074                 /* BB also check enough total bytes returned */
3075                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3076                         rc = -EIO;
3077                 else {
3078                         bool is_unicode;
3079                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3080
3081                         data_start = ((char *) &pSMBr->hdr.Protocol) +
3082                                            le16_to_cpu(pSMBr->t2.DataOffset);
3083
3084                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3085                                 is_unicode = true;
3086                         else
3087                                 is_unicode = false;
3088
3089                         /* BB FIXME investigate remapping reserved chars here */
3090                         *symlinkinfo = cifs_strndup_from_utf16(data_start,
3091                                         count, is_unicode, nls_codepage);
3092                         if (!*symlinkinfo)
3093                                 rc = -ENOMEM;
3094                 }
3095         }
3096         cifs_buf_release(pSMB);
3097         if (rc == -EAGAIN)
3098                 goto querySymLinkRetry;
3099         return rc;
3100 }
3101
3102 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3103 /*
3104  *      Recent Windows versions now create symlinks more frequently
3105  *      and they use the "reparse point" mechanism below.  We can of course
3106  *      do symlinks nicely to Samba and other servers which support the
3107  *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3108  *      "MF" symlinks optionally, but for recent Windows we really need to
3109  *      reenable the code below and fix the cifs_symlink callers to handle this.
3110  *      In the interim this code has been moved to its own config option so
3111  *      it is not compiled in by default until callers fixed up and more tested.
3112  */
3113 int
3114 CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3115                         const unsigned char *searchName,
3116                         char *symlinkinfo, const int buflen, __u16 fid,
3117                         const struct nls_table *nls_codepage)
3118 {
3119         int rc = 0;
3120         int bytes_returned;
3121         struct smb_com_transaction_ioctl_req *pSMB;
3122         struct smb_com_transaction_ioctl_rsp *pSMBr;
3123
3124         cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3125         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3126                       (void **) &pSMBr);
3127         if (rc)
3128                 return rc;
3129
3130         pSMB->TotalParameterCount = 0 ;
3131         pSMB->TotalDataCount = 0;
3132         pSMB->MaxParameterCount = cpu_to_le32(2);
3133         /* BB find exact data count max from sess structure BB */
3134         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3135         pSMB->MaxSetupCount = 4;
3136         pSMB->Reserved = 0;
3137         pSMB->ParameterOffset = 0;
3138         pSMB->DataCount = 0;
3139         pSMB->DataOffset = 0;
3140         pSMB->SetupCount = 4;
3141         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3142         pSMB->ParameterCount = pSMB->TotalParameterCount;
3143         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3144         pSMB->IsFsctl = 1; /* FSCTL */
3145         pSMB->IsRootFlag = 0;
3146         pSMB->Fid = fid; /* file handle always le */
3147         pSMB->ByteCount = 0;
3148
3149         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3150                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3151         if (rc) {
3152                 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3153         } else {                /* decode response */
3154                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3155                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3156                 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3157                         /* BB also check enough total bytes returned */
3158                         rc = -EIO;      /* bad smb */
3159                         goto qreparse_out;
3160                 }
3161                 if (data_count && (data_count < 2048)) {
3162                         char *end_of_smb = 2 /* sizeof byte count */ +
3163                                get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3164
3165                         struct reparse_data *reparse_buf =
3166                                                 (struct reparse_data *)
3167                                                 ((char *)&pSMBr->hdr.Protocol
3168                                                                  + data_offset);
3169                         if ((char *)reparse_buf >= end_of_smb) {
3170                                 rc = -EIO;
3171                                 goto qreparse_out;
3172                         }
3173                         if ((reparse_buf->LinkNamesBuf +
3174                                 reparse_buf->TargetNameOffset +
3175                                 reparse_buf->TargetNameLen) > end_of_smb) {
3176                                 cFYI(1, "reparse buf beyond SMB");
3177                                 rc = -EIO;
3178                                 goto qreparse_out;
3179                         }
3180
3181                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3182                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
3183                                                 (reparse_buf->LinkNamesBuf +
3184                                                 reparse_buf->TargetNameOffset),
3185                                                 buflen,
3186                                                 reparse_buf->TargetNameLen,
3187                                                 nls_codepage, 0);
3188                         } else { /* ASCII names */
3189                                 strncpy(symlinkinfo,
3190                                         reparse_buf->LinkNamesBuf +
3191                                         reparse_buf->TargetNameOffset,
3192                                         min_t(const int, buflen,
3193                                            reparse_buf->TargetNameLen));
3194                         }
3195                 } else {
3196                         rc = -EIO;
3197                         cFYI(1, "Invalid return data count on "
3198                                  "get reparse info ioctl");
3199                 }
3200                 symlinkinfo[buflen] = 0; /* just in case so the caller
3201                                         does not go off the end of the buffer */
3202                 cFYI(1, "readlink result - %s", symlinkinfo);
3203         }
3204
3205 qreparse_out:
3206         cifs_buf_release(pSMB);
3207
3208         /* Note: On -EAGAIN error only caller can retry on handle based calls
3209                 since file handle passed in no longer valid */
3210
3211         return rc;
3212 }
3213 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3214
3215 #ifdef CONFIG_CIFS_POSIX
3216
3217 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3218 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3219                              struct cifs_posix_ace *cifs_ace)
3220 {
3221         /* u8 cifs fields do not need le conversion */
3222         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3223         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3224         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3225         /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3226
3227         return;
3228 }
3229
3230 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3231 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3232                                const int acl_type, const int size_of_data_area)
3233 {
3234         int size =  0;
3235         int i;
3236         __u16 count;
3237         struct cifs_posix_ace *pACE;
3238         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3239         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3240
3241         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3242                 return -EOPNOTSUPP;
3243
3244         if (acl_type & ACL_TYPE_ACCESS) {
3245                 count = le16_to_cpu(cifs_acl->access_entry_count);
3246                 pACE = &cifs_acl->ace_array[0];
3247                 size = sizeof(struct cifs_posix_acl);
3248                 size += sizeof(struct cifs_posix_ace) * count;
3249                 /* check if we would go beyond end of SMB */
3250                 if (size_of_data_area < size) {
3251                         cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3252                                 size_of_data_area, size);
3253                         return -EINVAL;
3254                 }
3255         } else if (acl_type & ACL_TYPE_DEFAULT) {
3256                 count = le16_to_cpu(cifs_acl->access_entry_count);
3257                 size = sizeof(struct cifs_posix_acl);
3258                 size += sizeof(struct cifs_posix_ace) * count;
3259 /* skip past access ACEs to get to default ACEs */
3260                 pACE = &cifs_acl->ace_array[count];
3261                 count = le16_to_cpu(cifs_acl->default_entry_count);
3262                 size += sizeof(struct cifs_posix_ace) * count;
3263                 /* check if we would go beyond end of SMB */
3264                 if (size_of_data_area < size)
3265                         return -EINVAL;
3266         } else {
3267                 /* illegal type */
3268                 return -EINVAL;
3269         }
3270
3271         size = posix_acl_xattr_size(count);
3272         if ((buflen == 0) || (local_acl == NULL)) {
3273                 /* used to query ACL EA size */
3274         } else if (size > buflen) {
3275                 return -ERANGE;
3276         } else /* buffer big enough */ {
3277                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3278                 for (i = 0; i < count ; i++) {
3279                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
3280                         pACE++;
3281                 }
3282         }
3283         return size;
3284 }
3285
3286 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3287                                      const posix_acl_xattr_entry *local_ace)
3288 {
3289         __u16 rc = 0; /* 0 = ACL converted ok */
3290
3291         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3292         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3293         /* BB is there a better way to handle the large uid? */
3294         if (local_ace->e_id == cpu_to_le32(-1)) {
3295         /* Probably no need to le convert -1 on any arch but can not hurt */
3296                 cifs_ace->cifs_uid = cpu_to_le64(-1);
3297         } else
3298                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3299         /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3300         return rc;
3301 }
3302
3303 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3304 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3305                                const int buflen, const int acl_type)
3306 {
3307         __u16 rc = 0;
3308         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3309         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3310         int count;
3311         int i;
3312
3313         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3314                 return 0;
3315
3316         count = posix_acl_xattr_count((size_t)buflen);
3317         cFYI(1, "setting acl with %d entries from buf of length %d and "
3318                 "version of %d",
3319                 count, buflen, le32_to_cpu(local_acl->a_version));
3320         if (le32_to_cpu(local_acl->a_version) != 2) {
3321                 cFYI(1, "unknown POSIX ACL version %d",
3322                      le32_to_cpu(local_acl->a_version));
3323                 return 0;
3324         }
3325         cifs_acl->version = cpu_to_le16(1);
3326         if (acl_type == ACL_TYPE_ACCESS)
3327                 cifs_acl->access_entry_count = cpu_to_le16(count);
3328         else if (acl_type == ACL_TYPE_DEFAULT)
3329                 cifs_acl->default_entry_count = cpu_to_le16(count);
3330         else {
3331                 cFYI(1, "unknown ACL type %d", acl_type);
3332                 return 0;
3333         }
3334         for (i = 0; i < count; i++) {
3335                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3336                                         &local_acl->a_entries[i]);
3337                 if (rc != 0) {
3338                         /* ACE not converted */
3339                         break;
3340                 }
3341         }
3342         if (rc == 0) {
3343                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3344                 rc += sizeof(struct cifs_posix_acl);
3345                 /* BB add check to make sure ACL does not overflow SMB */
3346         }
3347         return rc;
3348 }
3349
3350 int
3351 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3352                    const unsigned char *searchName,
3353                    char *acl_inf, const int buflen, const int acl_type,
3354                    const struct nls_table *nls_codepage, int remap)
3355 {
3356 /* SMB_QUERY_POSIX_ACL */
3357         TRANSACTION2_QPI_REQ *pSMB = NULL;
3358         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3359         int rc = 0;
3360         int bytes_returned;
3361         int name_len;
3362         __u16 params, byte_count;
3363
3364         cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3365
3366 queryAclRetry:
3367         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3368                 (void **) &pSMBr);
3369         if (rc)
3370                 return rc;
3371
3372         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3373                 name_len =
3374                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3375                                            searchName, PATH_MAX, nls_codepage,
3376                                            remap);
3377                 name_len++;     /* trailing null */
3378                 name_len *= 2;
3379                 pSMB->FileName[name_len] = 0;
3380                 pSMB->FileName[name_len+1] = 0;
3381         } else {        /* BB improve the check for buffer overruns BB */
3382                 name_len = strnlen(searchName, PATH_MAX);
3383                 name_len++;     /* trailing null */
3384                 strncpy(pSMB->FileName, searchName, name_len);
3385         }
3386
3387         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3388         pSMB->TotalDataCount = 0;
3389         pSMB->MaxParameterCount = cpu_to_le16(2);
3390         /* BB find exact max data count below from sess structure BB */
3391         pSMB->MaxDataCount = cpu_to_le16(4000);
3392         pSMB->MaxSetupCount = 0;
3393         pSMB->Reserved = 0;
3394         pSMB->Flags = 0;
3395         pSMB->Timeout = 0;
3396         pSMB->Reserved2 = 0;
3397         pSMB->ParameterOffset = cpu_to_le16(
3398                 offsetof(struct smb_com_transaction2_qpi_req,
3399                          InformationLevel) - 4);
3400         pSMB->DataCount = 0;
3401         pSMB->DataOffset = 0;
3402         pSMB->SetupCount = 1;
3403         pSMB->Reserved3 = 0;
3404         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3405         byte_count = params + 1 /* pad */ ;
3406         pSMB->TotalParameterCount = cpu_to_le16(params);
3407         pSMB->ParameterCount = pSMB->TotalParameterCount;
3408         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3409         pSMB->Reserved4 = 0;
3410         inc_rfc1001_len(pSMB, byte_count);
3411         pSMB->ByteCount = cpu_to_le16(byte_count);
3412
3413         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3414                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3415         cifs_stats_inc(&tcon->num_acl_get);
3416         if (rc) {
3417                 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3418         } else {
3419                 /* decode response */
3420
3421                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3422                 /* BB also check enough total bytes returned */
3423                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3424                         rc = -EIO;      /* bad smb */
3425                 else {
3426                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3427                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3428                         rc = cifs_copy_posix_acl(acl_inf,
3429                                 (char *)&pSMBr->hdr.Protocol+data_offset,
3430                                 buflen, acl_type, count);
3431                 }
3432         }
3433         cifs_buf_release(pSMB);
3434         if (rc == -EAGAIN)
3435                 goto queryAclRetry;
3436         return rc;
3437 }
3438
3439 int
3440 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3441                    const unsigned char *fileName,
3442                    const char *local_acl, const int buflen,
3443                    const int acl_type,
3444                    const struct nls_table *nls_codepage, int remap)
3445 {
3446         struct smb_com_transaction2_spi_req *pSMB = NULL;
3447         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3448         char *parm_data;
3449         int name_len;
3450         int rc = 0;
3451         int bytes_returned = 0;
3452         __u16 params, byte_count, data_count, param_offset, offset;
3453
3454         cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3455 setAclRetry:
3456         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3457                       (void **) &pSMBr);
3458         if (rc)
3459                 return rc;
3460         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3461                 name_len =
3462                         cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3463                                            PATH_MAX, nls_codepage, remap);
3464                 name_len++;     /* trailing null */
3465                 name_len *= 2;
3466         } else {        /* BB improve the check for buffer overruns BB */
3467                 name_len = strnlen(fileName, PATH_MAX);
3468                 name_len++;     /* trailing null */
3469                 strncpy(pSMB->FileName, fileName, name_len);
3470         }
3471         params = 6 + name_len;
3472         pSMB->MaxParameterCount = cpu_to_le16(2);
3473         /* BB find max SMB size from sess */
3474         pSMB->MaxDataCount = cpu_to_le16(1000);
3475         pSMB->MaxSetupCount = 0;
3476         pSMB->Reserved = 0;
3477         pSMB->Flags = 0;
3478         pSMB->Timeout = 0;
3479         pSMB->Reserved2 = 0;
3480         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3481                                 InformationLevel) - 4;
3482         offset = param_offset + params;
3483         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3484         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3485
3486         /* convert to on the wire format for POSIX ACL */
3487         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3488
3489         if (data_count == 0) {
3490                 rc = -EOPNOTSUPP;
3491                 goto setACLerrorExit;
3492         }
3493         pSMB->DataOffset = cpu_to_le16(offset);
3494         pSMB->SetupCount = 1;
3495         pSMB->Reserved3 = 0;
3496         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3497         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3498         byte_count = 3 /* pad */  + params + data_count;
3499         pSMB->DataCount = cpu_to_le16(data_count);
3500         pSMB->TotalDataCount = pSMB->DataCount;
3501         pSMB->ParameterCount = cpu_to_le16(params);
3502         pSMB->TotalParameterCount = pSMB->ParameterCount;
3503         pSMB->Reserved4 = 0;
3504         inc_rfc1001_len(pSMB, byte_count);
3505         pSMB->ByteCount = cpu_to_le16(byte_count);
3506         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3507                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3508         if (rc)
3509                 cFYI(1, "Set POSIX ACL returned %d", rc);
3510
3511 setACLerrorExit:
3512         cifs_buf_release(pSMB);
3513         if (rc == -EAGAIN)
3514                 goto setAclRetry;
3515         return rc;
3516 }
3517
3518 /* BB fix tabs in this function FIXME BB */
3519 int
3520 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3521                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3522 {
3523         int rc = 0;
3524         struct smb_t2_qfi_req *pSMB = NULL;
3525         struct smb_t2_qfi_rsp *pSMBr = NULL;
3526         int bytes_returned;
3527         __u16 params, byte_count;
3528
3529         cFYI(1, "In GetExtAttr");
3530         if (tcon == NULL)
3531                 return -ENODEV;
3532
3533 GetExtAttrRetry:
3534         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3535                         (void **) &pSMBr);
3536         if (rc)
3537                 return rc;
3538
3539         params = 2 /* level */ + 2 /* fid */;
3540         pSMB->t2.TotalDataCount = 0;
3541         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3542         /* BB find exact max data count below from sess structure BB */
3543         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3544         pSMB->t2.MaxSetupCount = 0;
3545         pSMB->t2.Reserved = 0;
3546         pSMB->t2.Flags = 0;
3547         pSMB->t2.Timeout = 0;
3548         pSMB->t2.Reserved2 = 0;
3549         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3550                                                Fid) - 4);
3551         pSMB->t2.DataCount = 0;
3552         pSMB->t2.DataOffset = 0;
3553         pSMB->t2.SetupCount = 1;
3554         pSMB->t2.Reserved3 = 0;
3555         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3556         byte_count = params + 1 /* pad */ ;
3557         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3558         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3559         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3560         pSMB->Pad = 0;
3561         pSMB->Fid = netfid;
3562         inc_rfc1001_len(pSMB, byte_count);
3563         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3564
3565         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3566                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3567         if (rc) {
3568                 cFYI(1, "error %d in GetExtAttr", rc);
3569         } else {
3570                 /* decode response */
3571                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3572                 /* BB also check enough total bytes returned */
3573                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3574                         /* If rc should we check for EOPNOSUPP and
3575                            disable the srvino flag? or in caller? */
3576                         rc = -EIO;      /* bad smb */
3577                 else {
3578                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3579                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3580                         struct file_chattr_info *pfinfo;
3581                         /* BB Do we need a cast or hash here ? */
3582                         if (count != 16) {
3583                                 cFYI(1, "Illegal size ret in GetExtAttr");
3584                                 rc = -EIO;
3585                                 goto GetExtAttrOut;
3586                         }
3587                         pfinfo = (struct file_chattr_info *)
3588                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3589                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3590                         *pMask = le64_to_cpu(pfinfo->mask);
3591                 }
3592         }
3593 GetExtAttrOut:
3594         cifs_buf_release(pSMB);
3595         if (rc == -EAGAIN)
3596                 goto GetExtAttrRetry;
3597         return rc;
3598 }
3599
3600 #endif /* CONFIG_POSIX */
3601
3602 #ifdef CONFIG_CIFS_ACL
3603 /*
3604  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3605  * all NT TRANSACTS that we init here have total parm and data under about 400
3606  * bytes (to fit in small cifs buffer size), which is the case so far, it
3607  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3608  * returned setup area) and MaxParameterCount (returned parms size) must be set
3609  * by caller
3610  */
3611 static int
3612 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3613                    const int parm_len, struct cifs_tcon *tcon,
3614                    void **ret_buf)
3615 {
3616         int rc;
3617         __u32 temp_offset;
3618         struct smb_com_ntransact_req *pSMB;
3619
3620         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3621                                 (void **)&pSMB);
3622         if (rc)
3623                 return rc;
3624         *ret_buf = (void *)pSMB;
3625         pSMB->Reserved = 0;
3626         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3627         pSMB->TotalDataCount  = 0;
3628         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3629         pSMB->ParameterCount = pSMB->TotalParameterCount;
3630         pSMB->DataCount  = pSMB->TotalDataCount;
3631         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3632                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
3633         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3634         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3635         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3636         pSMB->SubCommand = cpu_to_le16(sub_command);
3637         return 0;
3638 }
3639
3640 static int
3641 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3642                    __u32 *pparmlen, __u32 *pdatalen)
3643 {
3644         char *end_of_smb;
3645         __u32 data_count, data_offset, parm_count, parm_offset;
3646         struct smb_com_ntransact_rsp *pSMBr;
3647         u16 bcc;
3648
3649         *pdatalen = 0;
3650         *pparmlen = 0;
3651
3652         if (buf == NULL)
3653                 return -EINVAL;
3654
3655         pSMBr = (struct smb_com_ntransact_rsp *)buf;
3656
3657         bcc = get_bcc(&pSMBr->hdr);
3658         end_of_smb = 2 /* sizeof byte count */ + bcc +
3659                         (char *)&pSMBr->ByteCount;
3660
3661         data_offset = le32_to_cpu(pSMBr->DataOffset);
3662         data_count = le32_to_cpu(pSMBr->DataCount);
3663         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3664         parm_count = le32_to_cpu(pSMBr->ParameterCount);
3665
3666         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3667         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3668
3669         /* should we also check that parm and data areas do not overlap? */
3670         if (*ppparm > end_of_smb) {
3671                 cFYI(1, "parms start after end of smb");
3672                 return -EINVAL;
3673         } else if (parm_count + *ppparm > end_of_smb) {
3674                 cFYI(1, "parm end after end of smb");
3675                 return -EINVAL;
3676         } else if (*ppdata > end_of_smb) {
3677                 cFYI(1, "data starts after end of smb");
3678                 return -EINVAL;
3679         } else if (data_count + *ppdata > end_of_smb) {
3680                 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3681                         *ppdata, data_count, (data_count + *ppdata),
3682                         end_of_smb, pSMBr);
3683                 return -EINVAL;
3684         } else if (parm_count + data_count > bcc) {
3685                 cFYI(1, "parm count and data count larger than SMB");
3686                 return -EINVAL;
3687         }
3688         *pdatalen = data_count;
3689         *pparmlen = parm_count;
3690         return 0;
3691 }
3692
3693 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3694 int
3695 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3696                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3697 {
3698         int rc = 0;
3699         int buf_type = 0;
3700         QUERY_SEC_DESC_REQ *pSMB;
3701         struct kvec iov[1];
3702
3703         cFYI(1, "GetCifsACL");
3704
3705         *pbuflen = 0;
3706         *acl_inf = NULL;
3707
3708         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3709                         8 /* parm len */, tcon, (void **) &pSMB);
3710         if (rc)
3711                 return rc;
3712
3713         pSMB->MaxParameterCount = cpu_to_le32(4);
3714         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3715         pSMB->MaxSetupCount = 0;
3716         pSMB->Fid = fid; /* file handle always le */
3717         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3718                                      CIFS_ACL_DACL);
3719         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3720         inc_rfc1001_len(pSMB, 11);
3721         iov[0].iov_base = (char *)pSMB;
3722         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3723
3724         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3725                          0);
3726         cifs_stats_inc(&tcon->num_acl_get);
3727         if (rc) {
3728                 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3729         } else {                /* decode response */
3730                 __le32 *parm;
3731                 __u32 parm_len;
3732                 __u32 acl_len;
3733                 struct smb_com_ntransact_rsp *pSMBr;
3734                 char *pdata;
3735
3736 /* validate_nttransact */
3737                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3738                                         &pdata, &parm_len, pbuflen);
3739                 if (rc)
3740                         goto qsec_out;
3741                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3742
3743                 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3744
3745                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3746                         rc = -EIO;      /* bad smb */
3747                         *pbuflen = 0;
3748                         goto qsec_out;
3749                 }
3750
3751 /* BB check that data area is minimum length and as big as acl_len */
3752
3753                 acl_len = le32_to_cpu(*parm);
3754                 if (acl_len != *pbuflen) {
3755                         cERROR(1, "acl length %d does not match %d",
3756                                    acl_len, *pbuflen);
3757                         if (*pbuflen > acl_len)
3758                                 *pbuflen = acl_len;
3759                 }
3760
3761                 /* check if buffer is big enough for the acl
3762                    header followed by the smallest SID */
3763                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3764                     (*pbuflen >= 64 * 1024)) {
3765                         cERROR(1, "bad acl length %d", *pbuflen);
3766                         rc = -EINVAL;
3767                         *pbuflen = 0;
3768                 } else {
3769                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3770                         if (*acl_inf == NULL) {
3771                                 *pbuflen = 0;
3772                                 rc = -ENOMEM;
3773                         }
3774                         memcpy(*acl_inf, pdata, *pbuflen);
3775                 }
3776         }
3777 qsec_out:
3778         if (buf_type == CIFS_SMALL_BUFFER)
3779                 cifs_small_buf_release(iov[0].iov_base);
3780         else if (buf_type == CIFS_LARGE_BUFFER)
3781                 cifs_buf_release(iov[0].iov_base);
3782 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3783         return rc;
3784 }
3785
3786 int
3787 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3788                         struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3789 {
3790         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3791         int rc = 0;
3792         int bytes_returned = 0;
3793         SET_SEC_DESC_REQ *pSMB = NULL;
3794         void *pSMBr;
3795
3796 setCifsAclRetry:
3797         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3798         if (rc)
3799                 return rc;
3800
3801         pSMB->MaxSetupCount = 0;
3802         pSMB->Reserved = 0;
3803
3804         param_count = 8;
3805         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3806         data_count = acllen;
3807         data_offset = param_offset + param_count;
3808         byte_count = 3 /* pad */  + param_count;
3809
3810         pSMB->DataCount = cpu_to_le32(data_count);
3811         pSMB->TotalDataCount = pSMB->DataCount;
3812         pSMB->MaxParameterCount = cpu_to_le32(4);
3813         pSMB->MaxDataCount = cpu_to_le32(16384);
3814         pSMB->ParameterCount = cpu_to_le32(param_count);
3815         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3816         pSMB->TotalParameterCount = pSMB->ParameterCount;
3817         pSMB->DataOffset = cpu_to_le32(data_offset);
3818         pSMB->SetupCount = 0;
3819         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3820         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3821
3822         pSMB->Fid = fid; /* file handle always le */
3823         pSMB->Reserved2 = 0;
3824         pSMB->AclFlags = cpu_to_le32(aclflag);
3825
3826         if (pntsd && acllen) {
3827                 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3828                                 data_offset, pntsd, acllen);
3829                 inc_rfc1001_len(pSMB, byte_count + data_count);
3830         } else
3831                 inc_rfc1001_len(pSMB, byte_count);
3832
3833         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3834                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3835
3836         cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3837         if (rc)
3838                 cFYI(1, "Set CIFS ACL returned %d", rc);
3839         cifs_buf_release(pSMB);
3840
3841         if (rc == -EAGAIN)
3842                 goto setCifsAclRetry;
3843
3844         return (rc);
3845 }
3846
3847 #endif /* CONFIG_CIFS_ACL */
3848
3849 /* Legacy Query Path Information call for lookup to old servers such
3850    as Win9x/WinME */
3851 int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3852                         const unsigned char *searchName,
3853                         FILE_ALL_INFO *pFinfo,
3854                         const struct nls_table *nls_codepage, int remap)
3855 {
3856         QUERY_INFORMATION_REQ *pSMB;
3857         QUERY_INFORMATION_RSP *pSMBr;
3858         int rc = 0;
3859         int bytes_returned;
3860         int name_len;
3861
3862         cFYI(1, "In SMBQPath path %s", searchName);
3863 QInfRetry:
3864         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3865                       (void **) &pSMBr);
3866         if (rc)
3867                 return rc;
3868
3869         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3870                 name_len =
3871                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3872                                            searchName, PATH_MAX, nls_codepage,
3873                                            remap);
3874                 name_len++;     /* trailing null */
3875                 name_len *= 2;
3876         } else {
3877                 name_len = strnlen(searchName, PATH_MAX);
3878                 name_len++;     /* trailing null */
3879                 strncpy(pSMB->FileName, searchName, name_len);
3880         }
3881         pSMB->BufferFormat = 0x04;
3882         name_len++; /* account for buffer type byte */
3883         inc_rfc1001_len(pSMB, (__u16)name_len);
3884         pSMB->ByteCount = cpu_to_le16(name_len);
3885
3886         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3887                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3888         if (rc) {
3889                 cFYI(1, "Send error in QueryInfo = %d", rc);
3890         } else if (pFinfo) {
3891                 struct timespec ts;
3892                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3893
3894                 /* decode response */
3895                 /* BB FIXME - add time zone adjustment BB */
3896                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3897                 ts.tv_nsec = 0;
3898                 ts.tv_sec = time;
3899                 /* decode time fields */
3900                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3901                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3902                 pFinfo->LastAccessTime = 0;
3903                 pFinfo->AllocationSize =
3904                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3905                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3906                 pFinfo->Attributes =
3907                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3908         } else
3909                 rc = -EIO; /* bad buffer passed in */
3910
3911         cifs_buf_release(pSMB);
3912
3913         if (rc == -EAGAIN)
3914                 goto QInfRetry;
3915
3916         return rc;
3917 }
3918
3919 int
3920 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3921                  u16 netfid, FILE_ALL_INFO *pFindData)
3922 {
3923         struct smb_t2_qfi_req *pSMB = NULL;
3924         struct smb_t2_qfi_rsp *pSMBr = NULL;
3925         int rc = 0;
3926         int bytes_returned;
3927         __u16 params, byte_count;
3928
3929 QFileInfoRetry:
3930         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3931                       (void **) &pSMBr);
3932         if (rc)
3933                 return rc;
3934
3935         params = 2 /* level */ + 2 /* fid */;
3936         pSMB->t2.TotalDataCount = 0;
3937         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3938         /* BB find exact max data count below from sess structure BB */
3939         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3940         pSMB->t2.MaxSetupCount = 0;
3941         pSMB->t2.Reserved = 0;
3942         pSMB->t2.Flags = 0;
3943         pSMB->t2.Timeout = 0;
3944         pSMB->t2.Reserved2 = 0;
3945         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3946                                                Fid) - 4);
3947         pSMB->t2.DataCount = 0;
3948         pSMB->t2.DataOffset = 0;
3949         pSMB->t2.SetupCount = 1;
3950         pSMB->t2.Reserved3 = 0;
3951         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3952         byte_count = params + 1 /* pad */ ;
3953         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3954         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3955         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3956         pSMB->Pad = 0;
3957         pSMB->Fid = netfid;
3958         inc_rfc1001_len(pSMB, byte_count);
3959
3960         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3961                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3962         if (rc) {
3963                 cFYI(1, "Send error in QPathInfo = %d", rc);
3964         } else {                /* decode response */
3965                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3966
3967                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3968                         rc = -EIO;
3969                 else if (get_bcc(&pSMBr->hdr) < 40)
3970                         rc = -EIO;      /* bad smb */
3971                 else if (pFindData) {
3972                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3973                         memcpy((char *) pFindData,
3974                                (char *) &pSMBr->hdr.Protocol +
3975                                data_offset, sizeof(FILE_ALL_INFO));
3976                 } else
3977                     rc = -ENOMEM;
3978         }
3979         cifs_buf_release(pSMB);
3980         if (rc == -EAGAIN)
3981                 goto QFileInfoRetry;
3982
3983         return rc;
3984 }
3985
3986 int
3987 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3988                  const unsigned char *searchName,
3989                  FILE_ALL_INFO *pFindData,
3990                  int legacy /* old style infolevel */,
3991                  const struct nls_table *nls_codepage, int remap)
3992 {
3993 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3994         TRANSACTION2_QPI_REQ *pSMB = NULL;
3995         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3996         int rc = 0;
3997         int bytes_returned;
3998         int name_len;
3999         __u16 params, byte_count;
4000
4001 /* cFYI(1, "In QPathInfo path %s", searchName); */
4002 QPathInfoRetry:
4003         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4004                       (void **) &pSMBr);
4005         if (rc)
4006                 return rc;
4007
4008         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4009                 name_len =
4010                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4011                                        PATH_MAX, nls_codepage, remap);
4012                 name_len++;     /* trailing null */
4013                 name_len *= 2;
4014         } else {        /* BB improve the check for buffer overruns BB */
4015                 name_len = strnlen(searchName, PATH_MAX);
4016                 name_len++;     /* trailing null */
4017                 strncpy(pSMB->FileName, searchName, name_len);
4018         }
4019
4020         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4021         pSMB->TotalDataCount = 0;
4022         pSMB->MaxParameterCount = cpu_to_le16(2);
4023         /* BB find exact max SMB PDU from sess structure BB */
4024         pSMB->MaxDataCount = cpu_to_le16(4000);
4025         pSMB->MaxSetupCount = 0;
4026         pSMB->Reserved = 0;
4027         pSMB->Flags = 0;
4028         pSMB->Timeout = 0;
4029         pSMB->Reserved2 = 0;
4030         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4031         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4032         pSMB->DataCount = 0;
4033         pSMB->DataOffset = 0;
4034         pSMB->SetupCount = 1;
4035         pSMB->Reserved3 = 0;
4036         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4037         byte_count = params + 1 /* pad */ ;
4038         pSMB->TotalParameterCount = cpu_to_le16(params);
4039         pSMB->ParameterCount = pSMB->TotalParameterCount;
4040         if (legacy)
4041                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4042         else
4043                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4044         pSMB->Reserved4 = 0;
4045         inc_rfc1001_len(pSMB, byte_count);
4046         pSMB->ByteCount = cpu_to_le16(byte_count);
4047
4048         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4049                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4050         if (rc) {
4051                 cFYI(1, "Send error in QPathInfo = %d", rc);
4052         } else {                /* decode response */
4053                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4054
4055                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4056                         rc = -EIO;
4057                 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4058                         rc = -EIO;      /* bad smb */
4059                 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4060                         rc = -EIO;  /* 24 or 26 expected but we do not read
4061                                         last field */
4062                 else if (pFindData) {
4063                         int size;
4064                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4065
4066                         /* On legacy responses we do not read the last field,
4067                         EAsize, fortunately since it varies by subdialect and
4068                         also note it differs on Set vs. Get, ie two bytes or 4
4069                         bytes depending but we don't care here */
4070                         if (legacy)
4071                                 size = sizeof(FILE_INFO_STANDARD);
4072                         else
4073                                 size = sizeof(FILE_ALL_INFO);
4074                         memcpy((char *) pFindData,
4075                                (char *) &pSMBr->hdr.Protocol +
4076                                data_offset, size);
4077                 } else
4078                     rc = -ENOMEM;
4079         }
4080         cifs_buf_release(pSMB);
4081         if (rc == -EAGAIN)
4082                 goto QPathInfoRetry;
4083
4084         return rc;
4085 }
4086
4087 int
4088 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4089                  u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4090 {
4091         struct smb_t2_qfi_req *pSMB = NULL;
4092         struct smb_t2_qfi_rsp *pSMBr = NULL;
4093         int rc = 0;
4094         int bytes_returned;
4095         __u16 params, byte_count;
4096
4097 UnixQFileInfoRetry:
4098         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4099                       (void **) &pSMBr);
4100         if (rc)
4101                 return rc;
4102
4103         params = 2 /* level */ + 2 /* fid */;
4104         pSMB->t2.TotalDataCount = 0;
4105         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4106         /* BB find exact max data count below from sess structure BB */
4107         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4108         pSMB->t2.MaxSetupCount = 0;
4109         pSMB->t2.Reserved = 0;
4110         pSMB->t2.Flags = 0;
4111         pSMB->t2.Timeout = 0;
4112         pSMB->t2.Reserved2 = 0;
4113         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4114                                                Fid) - 4);
4115         pSMB->t2.DataCount = 0;
4116         pSMB->t2.DataOffset = 0;
4117         pSMB->t2.SetupCount = 1;
4118         pSMB->t2.Reserved3 = 0;
4119         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4120         byte_count = params + 1 /* pad */ ;
4121         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4122         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4123         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4124         pSMB->Pad = 0;
4125         pSMB->Fid = netfid;
4126         inc_rfc1001_len(pSMB, byte_count);
4127
4128         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4129                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4130         if (rc) {
4131                 cFYI(1, "Send error in QPathInfo = %d", rc);
4132         } else {                /* decode response */
4133                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4134
4135                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4136                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4137                                    "Unix Extensions can be disabled on mount "
4138                                    "by specifying the nosfu mount option.");
4139                         rc = -EIO;      /* bad smb */
4140                 } else {
4141                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4142                         memcpy((char *) pFindData,
4143                                (char *) &pSMBr->hdr.Protocol +
4144                                data_offset,
4145                                sizeof(FILE_UNIX_BASIC_INFO));
4146                 }
4147         }
4148
4149         cifs_buf_release(pSMB);
4150         if (rc == -EAGAIN)
4151                 goto UnixQFileInfoRetry;
4152
4153         return rc;
4154 }
4155
4156 int
4157 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4158                      const unsigned char *searchName,
4159                      FILE_UNIX_BASIC_INFO *pFindData,
4160                      const struct nls_table *nls_codepage, int remap)
4161 {
4162 /* SMB_QUERY_FILE_UNIX_BASIC */
4163         TRANSACTION2_QPI_REQ *pSMB = NULL;
4164         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4165         int rc = 0;
4166         int bytes_returned = 0;
4167         int name_len;
4168         __u16 params, byte_count;
4169
4170         cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4171 UnixQPathInfoRetry:
4172         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4173                       (void **) &pSMBr);
4174         if (rc)
4175                 return rc;
4176
4177         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4178                 name_len =
4179                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4180                                        PATH_MAX, nls_codepage, remap);
4181                 name_len++;     /* trailing null */
4182                 name_len *= 2;
4183         } else {        /* BB improve the check for buffer overruns BB */
4184                 name_len = strnlen(searchName, PATH_MAX);
4185                 name_len++;     /* trailing null */
4186                 strncpy(pSMB->FileName, searchName, name_len);
4187         }
4188
4189         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4190         pSMB->TotalDataCount = 0;
4191         pSMB->MaxParameterCount = cpu_to_le16(2);
4192         /* BB find exact max SMB PDU from sess structure BB */
4193         pSMB->MaxDataCount = cpu_to_le16(4000);
4194         pSMB->MaxSetupCount = 0;
4195         pSMB->Reserved = 0;
4196         pSMB->Flags = 0;
4197         pSMB->Timeout = 0;
4198         pSMB->Reserved2 = 0;
4199         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4200         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4201         pSMB->DataCount = 0;
4202         pSMB->DataOffset = 0;
4203         pSMB->SetupCount = 1;
4204         pSMB->Reserved3 = 0;
4205         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4206         byte_count = params + 1 /* pad */ ;
4207         pSMB->TotalParameterCount = cpu_to_le16(params);
4208         pSMB->ParameterCount = pSMB->TotalParameterCount;
4209         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4210         pSMB->Reserved4 = 0;
4211         inc_rfc1001_len(pSMB, byte_count);
4212         pSMB->ByteCount = cpu_to_le16(byte_count);
4213
4214         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4215                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4216         if (rc) {
4217                 cFYI(1, "Send error in QPathInfo = %d", rc);
4218         } else {                /* decode response */
4219                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4220
4221                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4222                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4223                                    "Unix Extensions can be disabled on mount "
4224                                    "by specifying the nosfu mount option.");
4225                         rc = -EIO;      /* bad smb */
4226                 } else {
4227                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4228                         memcpy((char *) pFindData,
4229                                (char *) &pSMBr->hdr.Protocol +
4230                                data_offset,
4231                                sizeof(FILE_UNIX_BASIC_INFO));
4232                 }
4233         }
4234         cifs_buf_release(pSMB);
4235         if (rc == -EAGAIN)
4236                 goto UnixQPathInfoRetry;
4237
4238         return rc;
4239 }
4240
4241 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4242 int
4243 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4244               const char *searchName,
4245               const struct nls_table *nls_codepage,
4246               __u16 *pnetfid, __u16 search_flags,
4247               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4248 {
4249 /* level 257 SMB_ */
4250         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4251         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4252         T2_FFIRST_RSP_PARMS *parms;
4253         int rc = 0;
4254         int bytes_returned = 0;
4255         int name_len;
4256         __u16 params, byte_count;
4257
4258         cFYI(1, "In FindFirst for %s", searchName);
4259
4260 findFirstRetry:
4261         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4262                       (void **) &pSMBr);
4263         if (rc)
4264                 return rc;
4265
4266         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4267                 name_len =
4268                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4269                                        PATH_MAX, nls_codepage, remap);
4270                 /* We can not add the asterik earlier in case
4271                 it got remapped to 0xF03A as if it were part of the
4272                 directory name instead of a wildcard */
4273                 name_len *= 2;
4274                 pSMB->FileName[name_len] = dirsep;
4275                 pSMB->FileName[name_len+1] = 0;
4276                 pSMB->FileName[name_len+2] = '*';
4277                 pSMB->FileName[name_len+3] = 0;
4278                 name_len += 4; /* now the trailing null */
4279                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4280                 pSMB->FileName[name_len+1] = 0;
4281                 name_len += 2;
4282         } else {        /* BB add check for overrun of SMB buf BB */
4283                 name_len = strnlen(searchName, PATH_MAX);
4284 /* BB fix here and in unicode clause above ie
4285                 if (name_len > buffersize-header)
4286                         free buffer exit; BB */
4287                 strncpy(pSMB->FileName, searchName, name_len);
4288                 pSMB->FileName[name_len] = dirsep;
4289                 pSMB->FileName[name_len+1] = '*';
4290                 pSMB->FileName[name_len+2] = 0;
4291                 name_len += 3;
4292         }
4293
4294         params = 12 + name_len /* includes null */ ;
4295         pSMB->TotalDataCount = 0;       /* no EAs */
4296         pSMB->MaxParameterCount = cpu_to_le16(10);
4297         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4298         pSMB->MaxSetupCount = 0;
4299         pSMB->Reserved = 0;
4300         pSMB->Flags = 0;
4301         pSMB->Timeout = 0;
4302         pSMB->Reserved2 = 0;
4303         byte_count = params + 1 /* pad */ ;
4304         pSMB->TotalParameterCount = cpu_to_le16(params);
4305         pSMB->ParameterCount = pSMB->TotalParameterCount;
4306         pSMB->ParameterOffset = cpu_to_le16(
4307               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4308                 - 4);
4309         pSMB->DataCount = 0;
4310         pSMB->DataOffset = 0;
4311         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4312         pSMB->Reserved3 = 0;
4313         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4314         pSMB->SearchAttributes =
4315             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4316                         ATTR_DIRECTORY);
4317         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4318         pSMB->SearchFlags = cpu_to_le16(search_flags);
4319         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4320
4321         /* BB what should we set StorageType to? Does it matter? BB */
4322         pSMB->SearchStorageType = 0;
4323         inc_rfc1001_len(pSMB, byte_count);
4324         pSMB->ByteCount = cpu_to_le16(byte_count);
4325
4326         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4327                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4328         cifs_stats_inc(&tcon->num_ffirst);
4329
4330         if (rc) {/* BB add logic to retry regular search if Unix search
4331                         rejected unexpectedly by server */
4332                 /* BB Add code to handle unsupported level rc */
4333                 cFYI(1, "Error in FindFirst = %d", rc);
4334
4335                 cifs_buf_release(pSMB);
4336
4337                 /* BB eventually could optimize out free and realloc of buf */
4338                 /*    for this case */
4339                 if (rc == -EAGAIN)
4340                         goto findFirstRetry;
4341         } else { /* decode response */
4342                 /* BB remember to free buffer if error BB */
4343                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4344                 if (rc == 0) {
4345                         unsigned int lnoff;
4346
4347                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4348                                 psrch_inf->unicode = true;
4349                         else
4350                                 psrch_inf->unicode = false;
4351
4352                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4353                         psrch_inf->smallBuf = 0;
4354                         psrch_inf->srch_entries_start =
4355                                 (char *) &pSMBr->hdr.Protocol +
4356                                         le16_to_cpu(pSMBr->t2.DataOffset);
4357                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4358                                le16_to_cpu(pSMBr->t2.ParameterOffset));
4359
4360                         if (parms->EndofSearch)
4361                                 psrch_inf->endOfSearch = true;
4362                         else
4363                                 psrch_inf->endOfSearch = false;
4364
4365                         psrch_inf->entries_in_buffer =
4366                                         le16_to_cpu(parms->SearchCount);
4367                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4368                                 psrch_inf->entries_in_buffer;
4369                         lnoff = le16_to_cpu(parms->LastNameOffset);
4370                         if (CIFSMaxBufSize < lnoff) {
4371                                 cERROR(1, "ignoring corrupt resume name");
4372                                 psrch_inf->last_entry = NULL;
4373                                 return rc;
4374                         }
4375
4376                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
4377                                                         lnoff;
4378
4379                         *pnetfid = parms->SearchHandle;
4380                 } else {
4381                         cifs_buf_release(pSMB);
4382                 }
4383         }
4384
4385         return rc;
4386 }
4387
4388 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4389                  __u16 searchHandle, __u16 search_flags,
4390                  struct cifs_search_info *psrch_inf)
4391 {
4392         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4393         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4394         T2_FNEXT_RSP_PARMS *parms;
4395         char *response_data;
4396         int rc = 0;
4397         int bytes_returned;
4398         unsigned int name_len;
4399         __u16 params, byte_count;
4400
4401         cFYI(1, "In FindNext");
4402
4403         if (psrch_inf->endOfSearch)
4404                 return -ENOENT;
4405
4406         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4407                 (void **) &pSMBr);
4408         if (rc)
4409                 return rc;
4410
4411         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4412         byte_count = 0;
4413         pSMB->TotalDataCount = 0;       /* no EAs */
4414         pSMB->MaxParameterCount = cpu_to_le16(8);
4415         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4416         pSMB->MaxSetupCount = 0;
4417         pSMB->Reserved = 0;
4418         pSMB->Flags = 0;
4419         pSMB->Timeout = 0;
4420         pSMB->Reserved2 = 0;
4421         pSMB->ParameterOffset =  cpu_to_le16(
4422               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4423         pSMB->DataCount = 0;
4424         pSMB->DataOffset = 0;
4425         pSMB->SetupCount = 1;
4426         pSMB->Reserved3 = 0;
4427         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4428         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4429         pSMB->SearchCount =
4430                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4431         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4432         pSMB->ResumeKey = psrch_inf->resume_key;
4433         pSMB->SearchFlags = cpu_to_le16(search_flags);
4434
4435         name_len = psrch_inf->resume_name_len;
4436         params += name_len;
4437         if (name_len < PATH_MAX) {
4438                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4439                 byte_count += name_len;
4440                 /* 14 byte parm len above enough for 2 byte null terminator */
4441                 pSMB->ResumeFileName[name_len] = 0;
4442                 pSMB->ResumeFileName[name_len+1] = 0;
4443         } else {
4444                 rc = -EINVAL;
4445                 goto FNext2_err_exit;
4446         }
4447         byte_count = params + 1 /* pad */ ;
4448         pSMB->TotalParameterCount = cpu_to_le16(params);
4449         pSMB->ParameterCount = pSMB->TotalParameterCount;
4450         inc_rfc1001_len(pSMB, byte_count);
4451         pSMB->ByteCount = cpu_to_le16(byte_count);
4452
4453         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4454                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4455         cifs_stats_inc(&tcon->num_fnext);
4456         if (rc) {
4457                 if (rc == -EBADF) {
4458                         psrch_inf->endOfSearch = true;
4459                         cifs_buf_release(pSMB);
4460                         rc = 0; /* search probably was closed at end of search*/
4461                 } else
4462                         cFYI(1, "FindNext returned = %d", rc);
4463         } else {                /* decode response */
4464                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4465
4466                 if (rc == 0) {
4467                         unsigned int lnoff;
4468
4469                         /* BB fixme add lock for file (srch_info) struct here */
4470                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4471                                 psrch_inf->unicode = true;
4472                         else
4473                                 psrch_inf->unicode = false;
4474                         response_data = (char *) &pSMBr->hdr.Protocol +
4475                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4476                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4477                         response_data = (char *)&pSMBr->hdr.Protocol +
4478                                 le16_to_cpu(pSMBr->t2.DataOffset);
4479                         if (psrch_inf->smallBuf)
4480                                 cifs_small_buf_release(
4481                                         psrch_inf->ntwrk_buf_start);
4482                         else
4483                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4484                         psrch_inf->srch_entries_start = response_data;
4485                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4486                         psrch_inf->smallBuf = 0;
4487                         if (parms->EndofSearch)
4488                                 psrch_inf->endOfSearch = true;
4489                         else
4490                                 psrch_inf->endOfSearch = false;
4491                         psrch_inf->entries_in_buffer =
4492                                                 le16_to_cpu(parms->SearchCount);
4493                         psrch_inf->index_of_last_entry +=
4494                                 psrch_inf->entries_in_buffer;
4495                         lnoff = le16_to_cpu(parms->LastNameOffset);
4496                         if (CIFSMaxBufSize < lnoff) {
4497                                 cERROR(1, "ignoring corrupt resume name");
4498                                 psrch_inf->last_entry = NULL;
4499                                 return rc;
4500                         } else
4501                                 psrch_inf->last_entry =
4502                                         psrch_inf->srch_entries_start + lnoff;
4503
4504 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4505             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4506
4507                         /* BB fixme add unlock here */
4508                 }
4509
4510         }
4511
4512         /* BB On error, should we leave previous search buf (and count and
4513         last entry fields) intact or free the previous one? */
4514
4515         /* Note: On -EAGAIN error only caller can retry on handle based calls
4516         since file handle passed in no longer valid */
4517 FNext2_err_exit:
4518         if (rc != 0)
4519                 cifs_buf_release(pSMB);
4520         return rc;
4521 }
4522
4523 int
4524 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4525               const __u16 searchHandle)
4526 {
4527         int rc = 0;
4528         FINDCLOSE_REQ *pSMB = NULL;
4529
4530         cFYI(1, "In CIFSSMBFindClose");
4531         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4532
4533         /* no sense returning error if session restarted
4534                 as file handle has been closed */
4535         if (rc == -EAGAIN)
4536                 return 0;
4537         if (rc)
4538                 return rc;
4539
4540         pSMB->FileID = searchHandle;
4541         pSMB->ByteCount = 0;
4542         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4543         if (rc)
4544                 cERROR(1, "Send error in FindClose = %d", rc);
4545
4546         cifs_stats_inc(&tcon->num_fclose);
4547
4548         /* Since session is dead, search handle closed on server already */
4549         if (rc == -EAGAIN)
4550                 rc = 0;
4551
4552         return rc;
4553 }
4554
4555 int
4556 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4557                       const unsigned char *searchName,
4558                       __u64 *inode_number,
4559                       const struct nls_table *nls_codepage, int remap)
4560 {
4561         int rc = 0;
4562         TRANSACTION2_QPI_REQ *pSMB = NULL;
4563         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4564         int name_len, bytes_returned;
4565         __u16 params, byte_count;
4566
4567         cFYI(1, "In GetSrvInodeNum for %s", searchName);
4568         if (tcon == NULL)
4569                 return -ENODEV;
4570
4571 GetInodeNumberRetry:
4572         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4573                       (void **) &pSMBr);
4574         if (rc)
4575                 return rc;
4576
4577         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4578                 name_len =
4579                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
4580                                            searchName, PATH_MAX, nls_codepage,
4581                                            remap);
4582                 name_len++;     /* trailing null */
4583                 name_len *= 2;
4584         } else {        /* BB improve the check for buffer overruns BB */
4585                 name_len = strnlen(searchName, PATH_MAX);
4586                 name_len++;     /* trailing null */
4587                 strncpy(pSMB->FileName, searchName, name_len);
4588         }
4589
4590         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4591         pSMB->TotalDataCount = 0;
4592         pSMB->MaxParameterCount = cpu_to_le16(2);
4593         /* BB find exact max data count below from sess structure BB */
4594         pSMB->MaxDataCount = cpu_to_le16(4000);
4595         pSMB->MaxSetupCount = 0;
4596         pSMB->Reserved = 0;
4597         pSMB->Flags = 0;
4598         pSMB->Timeout = 0;
4599         pSMB->Reserved2 = 0;
4600         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4601                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4602         pSMB->DataCount = 0;
4603         pSMB->DataOffset = 0;
4604         pSMB->SetupCount = 1;
4605         pSMB->Reserved3 = 0;
4606         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4607         byte_count = params + 1 /* pad */ ;
4608         pSMB->TotalParameterCount = cpu_to_le16(params);
4609         pSMB->ParameterCount = pSMB->TotalParameterCount;
4610         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4611         pSMB->Reserved4 = 0;
4612         inc_rfc1001_len(pSMB, byte_count);
4613         pSMB->ByteCount = cpu_to_le16(byte_count);
4614
4615         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4616                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4617         if (rc) {
4618                 cFYI(1, "error %d in QueryInternalInfo", rc);
4619         } else {
4620                 /* decode response */
4621                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4622                 /* BB also check enough total bytes returned */
4623                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4624                         /* If rc should we check for EOPNOSUPP and
4625                         disable the srvino flag? or in caller? */
4626                         rc = -EIO;      /* bad smb */
4627                 else {
4628                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4629                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4630                         struct file_internal_info *pfinfo;
4631                         /* BB Do we need a cast or hash here ? */
4632                         if (count < 8) {
4633                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4634                                 rc = -EIO;
4635                                 goto GetInodeNumOut;
4636                         }
4637                         pfinfo = (struct file_internal_info *)
4638                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4639                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4640                 }
4641         }
4642 GetInodeNumOut:
4643         cifs_buf_release(pSMB);
4644         if (rc == -EAGAIN)
4645                 goto GetInodeNumberRetry;
4646         return rc;
4647 }
4648
4649 /* parses DFS refferal V3 structure
4650  * caller is responsible for freeing target_nodes
4651  * returns:
4652  *      on success - 0
4653  *      on failure - errno
4654  */
4655 static int
4656 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4657                 unsigned int *num_of_nodes,
4658                 struct dfs_info3_param **target_nodes,
4659                 const struct nls_table *nls_codepage, int remap,
4660                 const char *searchName)
4661 {
4662         int i, rc = 0;
4663         char *data_end;
4664         bool is_unicode;
4665         struct dfs_referral_level_3 *ref;
4666
4667         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4668                 is_unicode = true;
4669         else
4670                 is_unicode = false;
4671         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4672
4673         if (*num_of_nodes < 1) {
4674                 cERROR(1, "num_referrals: must be at least > 0,"
4675                         "but we get num_referrals = %d", *num_of_nodes);
4676                 rc = -EINVAL;
4677                 goto parse_DFS_referrals_exit;
4678         }
4679
4680         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4681         if (ref->VersionNumber != cpu_to_le16(3)) {
4682                 cERROR(1, "Referrals of V%d version are not supported,"
4683                         "should be V3", le16_to_cpu(ref->VersionNumber));
4684                 rc = -EINVAL;
4685                 goto parse_DFS_referrals_exit;
4686         }
4687
4688         /* get the upper boundary of the resp buffer */
4689         data_end = (char *)(&(pSMBr->PathConsumed)) +
4690                                 le16_to_cpu(pSMBr->t2.DataCount);
4691
4692         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4693                         *num_of_nodes,
4694                         le32_to_cpu(pSMBr->DFSFlags));
4695
4696         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4697                         *num_of_nodes, GFP_KERNEL);
4698         if (*target_nodes == NULL) {
4699                 cERROR(1, "Failed to allocate buffer for target_nodes");
4700                 rc = -ENOMEM;
4701                 goto parse_DFS_referrals_exit;
4702         }
4703
4704         /* collect necessary data from referrals */
4705         for (i = 0; i < *num_of_nodes; i++) {
4706                 char *temp;
4707                 int max_len;
4708                 struct dfs_info3_param *node = (*target_nodes)+i;
4709
4710                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4711                 if (is_unicode) {
4712                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4713                                                 GFP_KERNEL);
4714                         if (tmp == NULL) {
4715                                 rc = -ENOMEM;
4716                                 goto parse_DFS_referrals_exit;
4717                         }
4718                         cifsConvertToUTF16((__le16 *) tmp, searchName,
4719                                            PATH_MAX, nls_codepage, remap);
4720                         node->path_consumed = cifs_utf16_bytes(tmp,
4721                                         le16_to_cpu(pSMBr->PathConsumed),
4722                                         nls_codepage);
4723                         kfree(tmp);
4724                 } else
4725                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4726
4727                 node->server_type = le16_to_cpu(ref->ServerType);
4728                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4729
4730                 /* copy DfsPath */
4731                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4732                 max_len = data_end - temp;
4733                 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4734                                                 is_unicode, nls_codepage);
4735                 if (!node->path_name) {
4736                         rc = -ENOMEM;
4737                         goto parse_DFS_referrals_exit;
4738                 }
4739
4740                 /* copy link target UNC */
4741                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4742                 max_len = data_end - temp;
4743                 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4744                                                 is_unicode, nls_codepage);
4745                 if (!node->node_name) {
4746                         rc = -ENOMEM;
4747                         goto parse_DFS_referrals_exit;
4748                 }
4749
4750                 ref++;
4751         }
4752
4753 parse_DFS_referrals_exit:
4754         if (rc) {
4755                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4756                 *target_nodes = NULL;
4757                 *num_of_nodes = 0;
4758         }
4759         return rc;
4760 }
4761
4762 int
4763 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4764                 const unsigned char *searchName,
4765                 struct dfs_info3_param **target_nodes,
4766                 unsigned int *num_of_nodes,
4767                 const struct nls_table *nls_codepage, int remap)
4768 {
4769 /* TRANS2_GET_DFS_REFERRAL */
4770         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4771         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4772         int rc = 0;
4773         int bytes_returned;
4774         int name_len;
4775         __u16 params, byte_count;
4776         *num_of_nodes = 0;
4777         *target_nodes = NULL;
4778
4779         cFYI(1, "In GetDFSRefer the path %s", searchName);
4780         if (ses == NULL)
4781                 return -ENODEV;
4782 getDFSRetry:
4783         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4784                       (void **) &pSMBr);
4785         if (rc)
4786                 return rc;
4787
4788         /* server pointer checked in called function,
4789         but should never be null here anyway */
4790         pSMB->hdr.Mid = get_next_mid(ses->server);
4791         pSMB->hdr.Tid = ses->ipc_tid;
4792         pSMB->hdr.Uid = ses->Suid;
4793         if (ses->capabilities & CAP_STATUS32)
4794                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4795         if (ses->capabilities & CAP_DFS)
4796                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4797
4798         if (ses->capabilities & CAP_UNICODE) {
4799                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4800                 name_len =
4801                     cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4802                                        searchName, PATH_MAX, nls_codepage,
4803                                        remap);
4804                 name_len++;     /* trailing null */
4805                 name_len *= 2;
4806         } else {        /* BB improve the check for buffer overruns BB */
4807                 name_len = strnlen(searchName, PATH_MAX);
4808                 name_len++;     /* trailing null */
4809                 strncpy(pSMB->RequestFileName, searchName, name_len);
4810         }
4811
4812         if (ses->server) {
4813                 if (ses->server->sec_mode &
4814                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4815                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4816         }
4817
4818         pSMB->hdr.Uid = ses->Suid;
4819
4820         params = 2 /* level */  + name_len /*includes null */ ;
4821         pSMB->TotalDataCount = 0;
4822         pSMB->DataCount = 0;
4823         pSMB->DataOffset = 0;
4824         pSMB->MaxParameterCount = 0;
4825         /* BB find exact max SMB PDU from sess structure BB */
4826         pSMB->MaxDataCount = cpu_to_le16(4000);
4827         pSMB->MaxSetupCount = 0;
4828         pSMB->Reserved = 0;
4829         pSMB->Flags = 0;
4830         pSMB->Timeout = 0;
4831         pSMB->Reserved2 = 0;
4832         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4833           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4834         pSMB->SetupCount = 1;
4835         pSMB->Reserved3 = 0;
4836         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4837         byte_count = params + 3 /* pad */ ;
4838         pSMB->ParameterCount = cpu_to_le16(params);
4839         pSMB->TotalParameterCount = pSMB->ParameterCount;
4840         pSMB->MaxReferralLevel = cpu_to_le16(3);
4841         inc_rfc1001_len(pSMB, byte_count);
4842         pSMB->ByteCount = cpu_to_le16(byte_count);
4843
4844         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4845                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4846         if (rc) {
4847                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4848                 goto GetDFSRefExit;
4849         }
4850         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4851
4852         /* BB Also check if enough total bytes returned? */
4853         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4854                 rc = -EIO;      /* bad smb */
4855                 goto GetDFSRefExit;
4856         }
4857
4858         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4859                                 get_bcc(&pSMBr->hdr),
4860                                 le16_to_cpu(pSMBr->t2.DataOffset));
4861
4862         /* parse returned result into more usable form */
4863         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4864                                  target_nodes, nls_codepage, remap,
4865                                  searchName);
4866
4867 GetDFSRefExit:
4868         cifs_buf_release(pSMB);
4869
4870         if (rc == -EAGAIN)
4871                 goto getDFSRetry;
4872
4873         return rc;
4874 }
4875
4876 /* Query File System Info such as free space to old servers such as Win 9x */
4877 int
4878 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4879               struct kstatfs *FSData)
4880 {
4881 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4882         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4883         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4884         FILE_SYSTEM_ALLOC_INFO *response_data;
4885         int rc = 0;
4886         int bytes_returned = 0;
4887         __u16 params, byte_count;
4888
4889         cFYI(1, "OldQFSInfo");
4890 oldQFSInfoRetry:
4891         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4892                 (void **) &pSMBr);
4893         if (rc)
4894                 return rc;
4895
4896         params = 2;     /* level */
4897         pSMB->TotalDataCount = 0;
4898         pSMB->MaxParameterCount = cpu_to_le16(2);
4899         pSMB->MaxDataCount = cpu_to_le16(1000);
4900         pSMB->MaxSetupCount = 0;
4901         pSMB->Reserved = 0;
4902         pSMB->Flags = 0;
4903         pSMB->Timeout = 0;
4904         pSMB->Reserved2 = 0;
4905         byte_count = params + 1 /* pad */ ;
4906         pSMB->TotalParameterCount = cpu_to_le16(params);
4907         pSMB->ParameterCount = pSMB->TotalParameterCount;
4908         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4909         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4910         pSMB->DataCount = 0;
4911         pSMB->DataOffset = 0;
4912         pSMB->SetupCount = 1;
4913         pSMB->Reserved3 = 0;
4914         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4915         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4916         inc_rfc1001_len(pSMB, byte_count);
4917         pSMB->ByteCount = cpu_to_le16(byte_count);
4918
4919         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4920                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4921         if (rc) {
4922                 cFYI(1, "Send error in QFSInfo = %d", rc);
4923         } else {                /* decode response */
4924                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4925
4926                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4927                         rc = -EIO;      /* bad smb */
4928                 else {
4929                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4930                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4931                                  get_bcc(&pSMBr->hdr), data_offset);
4932
4933                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4934                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4935                         FSData->f_bsize =
4936                                 le16_to_cpu(response_data->BytesPerSector) *
4937                                 le32_to_cpu(response_data->
4938                                         SectorsPerAllocationUnit);
4939                         FSData->f_blocks =
4940                                le32_to_cpu(response_data->TotalAllocationUnits);
4941                         FSData->f_bfree = FSData->f_bavail =
4942                                 le32_to_cpu(response_data->FreeAllocationUnits);
4943                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4944                              (unsigned long long)FSData->f_blocks,
4945                              (unsigned long long)FSData->f_bfree,
4946                              FSData->f_bsize);
4947                 }
4948         }
4949         cifs_buf_release(pSMB);
4950
4951         if (rc == -EAGAIN)
4952                 goto oldQFSInfoRetry;
4953
4954         return rc;
4955 }
4956
4957 int
4958 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4959                struct kstatfs *FSData)
4960 {
4961 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4962         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4963         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4964         FILE_SYSTEM_INFO *response_data;
4965         int rc = 0;
4966         int bytes_returned = 0;
4967         __u16 params, byte_count;
4968
4969         cFYI(1, "In QFSInfo");
4970 QFSInfoRetry:
4971         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4972                       (void **) &pSMBr);
4973         if (rc)
4974                 return rc;
4975
4976         params = 2;     /* level */
4977         pSMB->TotalDataCount = 0;
4978         pSMB->MaxParameterCount = cpu_to_le16(2);
4979         pSMB->MaxDataCount = cpu_to_le16(1000);
4980         pSMB->MaxSetupCount = 0;
4981         pSMB->Reserved = 0;
4982         pSMB->Flags = 0;
4983         pSMB->Timeout = 0;
4984         pSMB->Reserved2 = 0;
4985         byte_count = params + 1 /* pad */ ;
4986         pSMB->TotalParameterCount = cpu_to_le16(params);
4987         pSMB->ParameterCount = pSMB->TotalParameterCount;
4988         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4989                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4990         pSMB->DataCount = 0;
4991         pSMB->DataOffset = 0;
4992         pSMB->SetupCount = 1;
4993         pSMB->Reserved3 = 0;
4994         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4995         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4996         inc_rfc1001_len(pSMB, byte_count);
4997         pSMB->ByteCount = cpu_to_le16(byte_count);
4998
4999         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5000                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5001         if (rc) {
5002                 cFYI(1, "Send error in QFSInfo = %d", rc);
5003         } else {                /* decode response */
5004                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5005
5006                 if (rc || get_bcc(&pSMBr->hdr) < 24)
5007                         rc = -EIO;      /* bad smb */
5008                 else {
5009                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5010
5011                         response_data =
5012                             (FILE_SYSTEM_INFO
5013                              *) (((char *) &pSMBr->hdr.Protocol) +
5014                                  data_offset);
5015                         FSData->f_bsize =
5016                             le32_to_cpu(response_data->BytesPerSector) *
5017                             le32_to_cpu(response_data->
5018                                         SectorsPerAllocationUnit);
5019                         FSData->f_blocks =
5020                             le64_to_cpu(response_data->TotalAllocationUnits);
5021                         FSData->f_bfree = FSData->f_bavail =
5022                             le64_to_cpu(response_data->FreeAllocationUnits);
5023                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5024                              (unsigned long long)FSData->f_blocks,
5025                              (unsigned long long)FSData->f_bfree,
5026                              FSData->f_bsize);
5027                 }
5028         }
5029         cifs_buf_release(pSMB);
5030
5031         if (rc == -EAGAIN)
5032                 goto QFSInfoRetry;
5033
5034         return rc;
5035 }
5036
5037 int
5038 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5039 {
5040 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5041         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5042         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5043         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5044         int rc = 0;
5045         int bytes_returned = 0;
5046         __u16 params, byte_count;
5047
5048         cFYI(1, "In QFSAttributeInfo");
5049 QFSAttributeRetry:
5050         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5051                       (void **) &pSMBr);
5052         if (rc)
5053                 return rc;
5054
5055         params = 2;     /* level */
5056         pSMB->TotalDataCount = 0;
5057         pSMB->MaxParameterCount = cpu_to_le16(2);
5058         /* BB find exact max SMB PDU from sess structure BB */
5059         pSMB->MaxDataCount = cpu_to_le16(1000);
5060         pSMB->MaxSetupCount = 0;
5061         pSMB->Reserved = 0;
5062         pSMB->Flags = 0;
5063         pSMB->Timeout = 0;
5064         pSMB->Reserved2 = 0;
5065         byte_count = params + 1 /* pad */ ;
5066         pSMB->TotalParameterCount = cpu_to_le16(params);
5067         pSMB->ParameterCount = pSMB->TotalParameterCount;
5068         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5069                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5070         pSMB->DataCount = 0;
5071         pSMB->DataOffset = 0;
5072         pSMB->SetupCount = 1;
5073         pSMB->Reserved3 = 0;
5074         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5075         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5076         inc_rfc1001_len(pSMB, byte_count);
5077         pSMB->ByteCount = cpu_to_le16(byte_count);
5078
5079         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5080                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5081         if (rc) {
5082                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5083         } else {                /* decode response */
5084                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5085
5086                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5087                         /* BB also check if enough bytes returned */
5088                         rc = -EIO;      /* bad smb */
5089                 } else {
5090                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5091                         response_data =
5092                             (FILE_SYSTEM_ATTRIBUTE_INFO
5093                              *) (((char *) &pSMBr->hdr.Protocol) +
5094                                  data_offset);
5095                         memcpy(&tcon->fsAttrInfo, response_data,
5096                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5097                 }
5098         }
5099         cifs_buf_release(pSMB);
5100
5101         if (rc == -EAGAIN)
5102                 goto QFSAttributeRetry;
5103
5104         return rc;
5105 }
5106
5107 int
5108 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5109 {
5110 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5111         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5112         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5113         FILE_SYSTEM_DEVICE_INFO *response_data;
5114         int rc = 0;
5115         int bytes_returned = 0;
5116         __u16 params, byte_count;
5117
5118         cFYI(1, "In QFSDeviceInfo");
5119 QFSDeviceRetry:
5120         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5121                       (void **) &pSMBr);
5122         if (rc)
5123                 return rc;
5124
5125         params = 2;     /* level */
5126         pSMB->TotalDataCount = 0;
5127         pSMB->MaxParameterCount = cpu_to_le16(2);
5128         /* BB find exact max SMB PDU from sess structure BB */
5129         pSMB->MaxDataCount = cpu_to_le16(1000);
5130         pSMB->MaxSetupCount = 0;
5131         pSMB->Reserved = 0;
5132         pSMB->Flags = 0;
5133         pSMB->Timeout = 0;
5134         pSMB->Reserved2 = 0;
5135         byte_count = params + 1 /* pad */ ;
5136         pSMB->TotalParameterCount = cpu_to_le16(params);
5137         pSMB->ParameterCount = pSMB->TotalParameterCount;
5138         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5139                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5140
5141         pSMB->DataCount = 0;
5142         pSMB->DataOffset = 0;
5143         pSMB->SetupCount = 1;
5144         pSMB->Reserved3 = 0;
5145         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5146         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5147         inc_rfc1001_len(pSMB, byte_count);
5148         pSMB->ByteCount = cpu_to_le16(byte_count);
5149
5150         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5151                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5152         if (rc) {
5153                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5154         } else {                /* decode response */
5155                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5156
5157                 if (rc || get_bcc(&pSMBr->hdr) <
5158                           sizeof(FILE_SYSTEM_DEVICE_INFO))
5159                         rc = -EIO;      /* bad smb */
5160                 else {
5161                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5162                         response_data =
5163                             (FILE_SYSTEM_DEVICE_INFO *)
5164                                 (((char *) &pSMBr->hdr.Protocol) +
5165                                  data_offset);
5166                         memcpy(&tcon->fsDevInfo, response_data,
5167                                sizeof(FILE_SYSTEM_DEVICE_INFO));
5168                 }
5169         }
5170         cifs_buf_release(pSMB);
5171
5172         if (rc == -EAGAIN)
5173                 goto QFSDeviceRetry;
5174
5175         return rc;
5176 }
5177
5178 int
5179 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5180 {
5181 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5182         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5183         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5184         FILE_SYSTEM_UNIX_INFO *response_data;
5185         int rc = 0;
5186         int bytes_returned = 0;
5187         __u16 params, byte_count;
5188
5189         cFYI(1, "In QFSUnixInfo");
5190 QFSUnixRetry:
5191         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5192                                    (void **) &pSMB, (void **) &pSMBr);
5193         if (rc)
5194                 return rc;
5195
5196         params = 2;     /* level */
5197         pSMB->TotalDataCount = 0;
5198         pSMB->DataCount = 0;
5199         pSMB->DataOffset = 0;
5200         pSMB->MaxParameterCount = cpu_to_le16(2);
5201         /* BB find exact max SMB PDU from sess structure BB */
5202         pSMB->MaxDataCount = cpu_to_le16(100);
5203         pSMB->MaxSetupCount = 0;
5204         pSMB->Reserved = 0;
5205         pSMB->Flags = 0;
5206         pSMB->Timeout = 0;
5207         pSMB->Reserved2 = 0;
5208         byte_count = params + 1 /* pad */ ;
5209         pSMB->ParameterCount = cpu_to_le16(params);
5210         pSMB->TotalParameterCount = pSMB->ParameterCount;
5211         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5212                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5213         pSMB->SetupCount = 1;
5214         pSMB->Reserved3 = 0;
5215         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5216         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5217         inc_rfc1001_len(pSMB, byte_count);
5218         pSMB->ByteCount = cpu_to_le16(byte_count);
5219
5220         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5221                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5222         if (rc) {
5223                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5224         } else {                /* decode response */
5225                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5226
5227                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5228                         rc = -EIO;      /* bad smb */
5229                 } else {
5230                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5231                         response_data =
5232                             (FILE_SYSTEM_UNIX_INFO
5233                              *) (((char *) &pSMBr->hdr.Protocol) +
5234                                  data_offset);
5235                         memcpy(&tcon->fsUnixInfo, response_data,
5236                                sizeof(FILE_SYSTEM_UNIX_INFO));
5237                 }
5238         }
5239         cifs_buf_release(pSMB);
5240
5241         if (rc == -EAGAIN)
5242                 goto QFSUnixRetry;
5243
5244
5245         return rc;
5246 }
5247
5248 int
5249 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5250 {
5251 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5252         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5253         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5254         int rc = 0;
5255         int bytes_returned = 0;
5256         __u16 params, param_offset, offset, byte_count;
5257
5258         cFYI(1, "In SETFSUnixInfo");
5259 SETFSUnixRetry:
5260         /* BB switch to small buf init to save memory */
5261         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5262                                         (void **) &pSMB, (void **) &pSMBr);
5263         if (rc)
5264                 return rc;
5265
5266         params = 4;     /* 2 bytes zero followed by info level. */
5267         pSMB->MaxSetupCount = 0;
5268         pSMB->Reserved = 0;
5269         pSMB->Flags = 0;
5270         pSMB->Timeout = 0;
5271         pSMB->Reserved2 = 0;
5272         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5273                                 - 4;
5274         offset = param_offset + params;
5275
5276         pSMB->MaxParameterCount = cpu_to_le16(4);
5277         /* BB find exact max SMB PDU from sess structure BB */
5278         pSMB->MaxDataCount = cpu_to_le16(100);
5279         pSMB->SetupCount = 1;
5280         pSMB->Reserved3 = 0;
5281         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5282         byte_count = 1 /* pad */ + params + 12;
5283
5284         pSMB->DataCount = cpu_to_le16(12);
5285         pSMB->ParameterCount = cpu_to_le16(params);
5286         pSMB->TotalDataCount = pSMB->DataCount;
5287         pSMB->TotalParameterCount = pSMB->ParameterCount;
5288         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5289         pSMB->DataOffset = cpu_to_le16(offset);
5290
5291         /* Params. */
5292         pSMB->FileNum = 0;
5293         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5294
5295         /* Data. */
5296         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5297         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5298         pSMB->ClientUnixCap = cpu_to_le64(cap);
5299
5300         inc_rfc1001_len(pSMB, byte_count);
5301         pSMB->ByteCount = cpu_to_le16(byte_count);
5302
5303         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5304                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5305         if (rc) {
5306                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5307         } else {                /* decode response */
5308                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5309                 if (rc)
5310                         rc = -EIO;      /* bad smb */
5311         }
5312         cifs_buf_release(pSMB);
5313
5314         if (rc == -EAGAIN)
5315                 goto SETFSUnixRetry;
5316
5317         return rc;
5318 }
5319
5320
5321
5322 int
5323 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5324                    struct kstatfs *FSData)
5325 {
5326 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5327         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5328         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5329         FILE_SYSTEM_POSIX_INFO *response_data;
5330         int rc = 0;
5331         int bytes_returned = 0;
5332         __u16 params, byte_count;
5333
5334         cFYI(1, "In QFSPosixInfo");
5335 QFSPosixRetry:
5336         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5337                       (void **) &pSMBr);
5338         if (rc)
5339                 return rc;
5340
5341         params = 2;     /* level */
5342         pSMB->TotalDataCount = 0;
5343         pSMB->DataCount = 0;
5344         pSMB->DataOffset = 0;
5345         pSMB->MaxParameterCount = cpu_to_le16(2);
5346         /* BB find exact max SMB PDU from sess structure BB */
5347         pSMB->MaxDataCount = cpu_to_le16(100);
5348         pSMB->MaxSetupCount = 0;
5349         pSMB->Reserved = 0;
5350         pSMB->Flags = 0;
5351         pSMB->Timeout = 0;
5352         pSMB->Reserved2 = 0;
5353         byte_count = params + 1 /* pad */ ;
5354         pSMB->ParameterCount = cpu_to_le16(params);
5355         pSMB->TotalParameterCount = pSMB->ParameterCount;
5356         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5357                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5358         pSMB->SetupCount = 1;
5359         pSMB->Reserved3 = 0;
5360         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5361         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5362         inc_rfc1001_len(pSMB, byte_count);
5363         pSMB->ByteCount = cpu_to_le16(byte_count);
5364
5365         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5366                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5367         if (rc) {
5368                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5369         } else {                /* decode response */
5370                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5371
5372                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5373                         rc = -EIO;      /* bad smb */
5374                 } else {
5375                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5376                         response_data =
5377                             (FILE_SYSTEM_POSIX_INFO
5378                              *) (((char *) &pSMBr->hdr.Protocol) +
5379                                  data_offset);
5380                         FSData->f_bsize =
5381                                         le32_to_cpu(response_data->BlockSize);
5382                         FSData->f_blocks =
5383                                         le64_to_cpu(response_data->TotalBlocks);
5384                         FSData->f_bfree =
5385                             le64_to_cpu(response_data->BlocksAvail);
5386                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5387                                 FSData->f_bavail = FSData->f_bfree;
5388                         } else {
5389                                 FSData->f_bavail =
5390                                     le64_to_cpu(response_data->UserBlocksAvail);
5391                         }
5392                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5393                                 FSData->f_files =
5394                                      le64_to_cpu(response_data->TotalFileNodes);
5395                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5396                                 FSData->f_ffree =
5397                                       le64_to_cpu(response_data->FreeFileNodes);
5398                 }
5399         }
5400         cifs_buf_release(pSMB);
5401
5402         if (rc == -EAGAIN)
5403                 goto QFSPosixRetry;
5404
5405         return rc;
5406 }
5407
5408
5409 /* We can not use write of zero bytes trick to
5410    set file size due to need for large file support.  Also note that
5411    this SetPathInfo is preferred to SetFileInfo based method in next
5412    routine which is only needed to work around a sharing violation bug
5413    in Samba which this routine can run into */
5414
5415 int
5416 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5417               const char *fileName, __u64 size, bool SetAllocation,
5418               const struct nls_table *nls_codepage, int remap)
5419 {
5420         struct smb_com_transaction2_spi_req *pSMB = NULL;
5421         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5422         struct file_end_of_file_info *parm_data;
5423         int name_len;
5424         int rc = 0;
5425         int bytes_returned = 0;
5426         __u16 params, byte_count, data_count, param_offset, offset;
5427
5428         cFYI(1, "In SetEOF");
5429 SetEOFRetry:
5430         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5431                       (void **) &pSMBr);
5432         if (rc)
5433                 return rc;
5434
5435         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5436                 name_len =
5437                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5438                                        PATH_MAX, nls_codepage, remap);
5439                 name_len++;     /* trailing null */
5440                 name_len *= 2;
5441         } else {        /* BB improve the check for buffer overruns BB */
5442                 name_len = strnlen(fileName, PATH_MAX);
5443                 name_len++;     /* trailing null */
5444                 strncpy(pSMB->FileName, fileName, name_len);
5445         }
5446         params = 6 + name_len;
5447         data_count = sizeof(struct file_end_of_file_info);
5448         pSMB->MaxParameterCount = cpu_to_le16(2);
5449         pSMB->MaxDataCount = cpu_to_le16(4100);
5450         pSMB->MaxSetupCount = 0;
5451         pSMB->Reserved = 0;
5452         pSMB->Flags = 0;
5453         pSMB->Timeout = 0;
5454         pSMB->Reserved2 = 0;
5455         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5456                                 InformationLevel) - 4;
5457         offset = param_offset + params;
5458         if (SetAllocation) {
5459                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5460                         pSMB->InformationLevel =
5461                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5462                 else
5463                         pSMB->InformationLevel =
5464                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5465         } else /* Set File Size */  {
5466             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5467                     pSMB->InformationLevel =
5468                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5469             else
5470                     pSMB->InformationLevel =
5471                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5472         }
5473
5474         parm_data =
5475             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5476                                        offset);
5477         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5478         pSMB->DataOffset = cpu_to_le16(offset);
5479         pSMB->SetupCount = 1;
5480         pSMB->Reserved3 = 0;
5481         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5482         byte_count = 3 /* pad */  + params + data_count;
5483         pSMB->DataCount = cpu_to_le16(data_count);
5484         pSMB->TotalDataCount = pSMB->DataCount;
5485         pSMB->ParameterCount = cpu_to_le16(params);
5486         pSMB->TotalParameterCount = pSMB->ParameterCount;
5487         pSMB->Reserved4 = 0;
5488         inc_rfc1001_len(pSMB, byte_count);
5489         parm_data->FileSize = cpu_to_le64(size);
5490         pSMB->ByteCount = cpu_to_le16(byte_count);
5491         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5492                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5493         if (rc)
5494                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5495
5496         cifs_buf_release(pSMB);
5497
5498         if (rc == -EAGAIN)
5499                 goto SetEOFRetry;
5500
5501         return rc;
5502 }
5503
5504 int
5505 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5506                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5507 {
5508         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5509         struct file_end_of_file_info *parm_data;
5510         int rc = 0;
5511         __u16 params, param_offset, offset, byte_count, count;
5512
5513         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5514                         (long long)size);
5515         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5516
5517         if (rc)
5518                 return rc;
5519
5520         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5521         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5522
5523         params = 6;
5524         pSMB->MaxSetupCount = 0;
5525         pSMB->Reserved = 0;
5526         pSMB->Flags = 0;
5527         pSMB->Timeout = 0;
5528         pSMB->Reserved2 = 0;
5529         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5530         offset = param_offset + params;
5531
5532         count = sizeof(struct file_end_of_file_info);
5533         pSMB->MaxParameterCount = cpu_to_le16(2);
5534         /* BB find exact max SMB PDU from sess structure BB */
5535         pSMB->MaxDataCount = cpu_to_le16(1000);
5536         pSMB->SetupCount = 1;
5537         pSMB->Reserved3 = 0;
5538         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5539         byte_count = 3 /* pad */  + params + count;
5540         pSMB->DataCount = cpu_to_le16(count);
5541         pSMB->ParameterCount = cpu_to_le16(params);
5542         pSMB->TotalDataCount = pSMB->DataCount;
5543         pSMB->TotalParameterCount = pSMB->ParameterCount;
5544         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5545         parm_data =
5546                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5547                                 + offset);
5548         pSMB->DataOffset = cpu_to_le16(offset);
5549         parm_data->FileSize = cpu_to_le64(size);
5550         pSMB->Fid = fid;
5551         if (SetAllocation) {
5552                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5553                         pSMB->InformationLevel =
5554                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5555                 else
5556                         pSMB->InformationLevel =
5557                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5558         } else /* Set File Size */  {
5559             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5560                     pSMB->InformationLevel =
5561                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5562             else
5563                     pSMB->InformationLevel =
5564                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5565         }
5566         pSMB->Reserved4 = 0;
5567         inc_rfc1001_len(pSMB, byte_count);
5568         pSMB->ByteCount = cpu_to_le16(byte_count);
5569         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5570         if (rc) {
5571                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5572         }
5573
5574         /* Note: On -EAGAIN error only caller can retry on handle based calls
5575                 since file handle passed in no longer valid */
5576
5577         return rc;
5578 }
5579
5580 /* Some legacy servers such as NT4 require that the file times be set on
5581    an open handle, rather than by pathname - this is awkward due to
5582    potential access conflicts on the open, but it is unavoidable for these
5583    old servers since the only other choice is to go from 100 nanosecond DCE
5584    time and resort to the original setpathinfo level which takes the ancient
5585    DOS time format with 2 second granularity */
5586 int
5587 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5588                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5589 {
5590         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5591         char *data_offset;
5592         int rc = 0;
5593         __u16 params, param_offset, offset, byte_count, count;
5594
5595         cFYI(1, "Set Times (via SetFileInfo)");
5596         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5597
5598         if (rc)
5599                 return rc;
5600
5601         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5602         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5603
5604         params = 6;
5605         pSMB->MaxSetupCount = 0;
5606         pSMB->Reserved = 0;
5607         pSMB->Flags = 0;
5608         pSMB->Timeout = 0;
5609         pSMB->Reserved2 = 0;
5610         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5611         offset = param_offset + params;
5612
5613         data_offset = (char *)pSMB +
5614                         offsetof(struct smb_hdr, Protocol) + offset;
5615
5616         count = sizeof(FILE_BASIC_INFO);
5617         pSMB->MaxParameterCount = cpu_to_le16(2);
5618         /* BB find max SMB PDU from sess */
5619         pSMB->MaxDataCount = cpu_to_le16(1000);
5620         pSMB->SetupCount = 1;
5621         pSMB->Reserved3 = 0;
5622         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5623         byte_count = 3 /* pad */  + params + count;
5624         pSMB->DataCount = cpu_to_le16(count);
5625         pSMB->ParameterCount = cpu_to_le16(params);
5626         pSMB->TotalDataCount = pSMB->DataCount;
5627         pSMB->TotalParameterCount = pSMB->ParameterCount;
5628         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5629         pSMB->DataOffset = cpu_to_le16(offset);
5630         pSMB->Fid = fid;
5631         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5632                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5633         else
5634                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5635         pSMB->Reserved4 = 0;
5636         inc_rfc1001_len(pSMB, byte_count);
5637         pSMB->ByteCount = cpu_to_le16(byte_count);
5638         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5639         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5640         if (rc)
5641                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5642
5643         /* Note: On -EAGAIN error only caller can retry on handle based calls
5644                 since file handle passed in no longer valid */
5645
5646         return rc;
5647 }
5648
5649 int
5650 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5651                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5652 {
5653         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5654         char *data_offset;
5655         int rc = 0;
5656         __u16 params, param_offset, offset, byte_count, count;
5657
5658         cFYI(1, "Set File Disposition (via SetFileInfo)");
5659         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5660
5661         if (rc)
5662                 return rc;
5663
5664         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5665         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5666
5667         params = 6;
5668         pSMB->MaxSetupCount = 0;
5669         pSMB->Reserved = 0;
5670         pSMB->Flags = 0;
5671         pSMB->Timeout = 0;
5672         pSMB->Reserved2 = 0;
5673         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5674         offset = param_offset + params;
5675
5676         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5677
5678         count = 1;
5679         pSMB->MaxParameterCount = cpu_to_le16(2);
5680         /* BB find max SMB PDU from sess */
5681         pSMB->MaxDataCount = cpu_to_le16(1000);
5682         pSMB->SetupCount = 1;
5683         pSMB->Reserved3 = 0;
5684         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5685         byte_count = 3 /* pad */  + params + count;
5686         pSMB->DataCount = cpu_to_le16(count);
5687         pSMB->ParameterCount = cpu_to_le16(params);