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