CIFS: Move protocol specific tcon/tdis code to ops struct
[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(const 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 = 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 unsigned 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, CIFS_ECHO_OP);
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, CIFS_ASYNC_OP | CIFS_ECHO_OP);
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 unsigned 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, 0);
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, 0);
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, 0);
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, 0);
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 flags = 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                 /* no response expected */
2310                 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2311                 pSMB->Timeout = 0;
2312         } else if (waitFlag) {
2313                 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2314                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2315         } else {
2316                 pSMB->Timeout = 0;
2317         }
2318
2319         pSMB->NumberOfLocks = cpu_to_le16(numLock);
2320         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2321         pSMB->LockType = lockType;
2322         pSMB->OplockLevel = oplock_level;
2323         pSMB->AndXCommand = 0xFF;       /* none */
2324         pSMB->Fid = smb_file_id; /* netfid stays le */
2325
2326         if ((numLock != 0) || (numUnlock != 0)) {
2327                 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2328                 /* BB where to store pid high? */
2329                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2330                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2331                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2332                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2333                 count = sizeof(LOCKING_ANDX_RANGE);
2334         } else {
2335                 /* oplock break */
2336                 count = 0;
2337         }
2338         inc_rfc1001_len(pSMB, count);
2339         pSMB->ByteCount = cpu_to_le16(count);
2340
2341         if (waitFlag) {
2342                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2343                         (struct smb_hdr *) pSMB, &bytes_returned);
2344                 cifs_small_buf_release(pSMB);
2345         } else {
2346                 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2347                 /* SMB buffer freed by function above */
2348         }
2349         cifs_stats_inc(&tcon->num_locks);
2350         if (rc)
2351                 cFYI(1, "Send error in Lock = %d", rc);
2352
2353         /* Note: On -EAGAIN error only caller can retry on handle based calls
2354         since file handle passed in no longer valid */
2355         return rc;
2356 }
2357
2358 int
2359 CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
2360                 const __u16 smb_file_id, const __u32 netpid,
2361                 const loff_t start_offset, const __u64 len,
2362                 struct file_lock *pLockData, const __u16 lock_type,
2363                 const bool waitFlag)
2364 {
2365         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2366         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2367         struct cifs_posix_lock *parm_data;
2368         int rc = 0;
2369         int timeout = 0;
2370         int bytes_returned = 0;
2371         int resp_buf_type = 0;
2372         __u16 params, param_offset, offset, byte_count, count;
2373         struct kvec iov[1];
2374
2375         cFYI(1, "Posix Lock");
2376
2377         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2378
2379         if (rc)
2380                 return rc;
2381
2382         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2383
2384         params = 6;
2385         pSMB->MaxSetupCount = 0;
2386         pSMB->Reserved = 0;
2387         pSMB->Flags = 0;
2388         pSMB->Reserved2 = 0;
2389         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2390         offset = param_offset + params;
2391
2392         count = sizeof(struct cifs_posix_lock);
2393         pSMB->MaxParameterCount = cpu_to_le16(2);
2394         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2395         pSMB->SetupCount = 1;
2396         pSMB->Reserved3 = 0;
2397         if (pLockData)
2398                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2399         else
2400                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2401         byte_count = 3 /* pad */  + params + count;
2402         pSMB->DataCount = cpu_to_le16(count);
2403         pSMB->ParameterCount = cpu_to_le16(params);
2404         pSMB->TotalDataCount = pSMB->DataCount;
2405         pSMB->TotalParameterCount = pSMB->ParameterCount;
2406         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2407         parm_data = (struct cifs_posix_lock *)
2408                         (((char *) &pSMB->hdr.Protocol) + offset);
2409
2410         parm_data->lock_type = cpu_to_le16(lock_type);
2411         if (waitFlag) {
2412                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2413                 parm_data->lock_flags = cpu_to_le16(1);
2414                 pSMB->Timeout = cpu_to_le32(-1);
2415         } else
2416                 pSMB->Timeout = 0;
2417
2418         parm_data->pid = cpu_to_le32(netpid);
2419         parm_data->start = cpu_to_le64(start_offset);
2420         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2421
2422         pSMB->DataOffset = cpu_to_le16(offset);
2423         pSMB->Fid = smb_file_id;
2424         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2425         pSMB->Reserved4 = 0;
2426         inc_rfc1001_len(pSMB, byte_count);
2427         pSMB->ByteCount = cpu_to_le16(byte_count);
2428         if (waitFlag) {
2429                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2430                         (struct smb_hdr *) pSMBr, &bytes_returned);
2431         } else {
2432                 iov[0].iov_base = (char *)pSMB;
2433                 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2434                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2435                                 &resp_buf_type, timeout);
2436                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2437                                 not try to free it twice below on exit */
2438                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2439         }
2440
2441         if (rc) {
2442                 cFYI(1, "Send error in Posix Lock = %d", rc);
2443         } else if (pLockData) {
2444                 /* lock structure can be returned on get */
2445                 __u16 data_offset;
2446                 __u16 data_count;
2447                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2448
2449                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2450                         rc = -EIO;      /* bad smb */
2451                         goto plk_err_exit;
2452                 }
2453                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2454                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2455                 if (data_count < sizeof(struct cifs_posix_lock)) {
2456                         rc = -EIO;
2457                         goto plk_err_exit;
2458                 }
2459                 parm_data = (struct cifs_posix_lock *)
2460                         ((char *)&pSMBr->hdr.Protocol + data_offset);
2461                 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2462                         pLockData->fl_type = F_UNLCK;
2463                 else {
2464                         if (parm_data->lock_type ==
2465                                         __constant_cpu_to_le16(CIFS_RDLCK))
2466                                 pLockData->fl_type = F_RDLCK;
2467                         else if (parm_data->lock_type ==
2468                                         __constant_cpu_to_le16(CIFS_WRLCK))
2469                                 pLockData->fl_type = F_WRLCK;
2470
2471                         pLockData->fl_start = le64_to_cpu(parm_data->start);
2472                         pLockData->fl_end = pLockData->fl_start +
2473                                         le64_to_cpu(parm_data->length) - 1;
2474                         pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2475                 }
2476         }
2477
2478 plk_err_exit:
2479         if (pSMB)
2480                 cifs_small_buf_release(pSMB);
2481
2482         if (resp_buf_type == CIFS_SMALL_BUFFER)
2483                 cifs_small_buf_release(iov[0].iov_base);
2484         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2485                 cifs_buf_release(iov[0].iov_base);
2486
2487         /* Note: On -EAGAIN error only caller can retry on handle based calls
2488            since file handle passed in no longer valid */
2489
2490         return rc;
2491 }
2492
2493
2494 int
2495 CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2496 {
2497         int rc = 0;
2498         CLOSE_REQ *pSMB = NULL;
2499         cFYI(1, "In CIFSSMBClose");
2500
2501 /* do not retry on dead session on close */
2502         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2503         if (rc == -EAGAIN)
2504                 return 0;
2505         if (rc)
2506                 return rc;
2507
2508         pSMB->FileID = (__u16) smb_file_id;
2509         pSMB->LastWriteTime = 0xFFFFFFFF;
2510         pSMB->ByteCount = 0;
2511         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2512         cifs_stats_inc(&tcon->num_closes);
2513         if (rc) {
2514                 if (rc != -EINTR) {
2515                         /* EINTR is expected when user ctl-c to kill app */
2516                         cERROR(1, "Send error in Close = %d", rc);
2517                 }
2518         }
2519
2520         /* Since session is dead, file will be closed on server already */
2521         if (rc == -EAGAIN)
2522                 rc = 0;
2523
2524         return rc;
2525 }
2526
2527 int
2528 CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2529 {
2530         int rc = 0;
2531         FLUSH_REQ *pSMB = NULL;
2532         cFYI(1, "In CIFSSMBFlush");
2533
2534         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2535         if (rc)
2536                 return rc;
2537
2538         pSMB->FileID = (__u16) smb_file_id;
2539         pSMB->ByteCount = 0;
2540         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2541         cifs_stats_inc(&tcon->num_flushes);
2542         if (rc)
2543                 cERROR(1, "Send error in Flush = %d", rc);
2544
2545         return rc;
2546 }
2547
2548 int
2549 CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
2550               const char *fromName, const char *toName,
2551               const struct nls_table *nls_codepage, int remap)
2552 {
2553         int rc = 0;
2554         RENAME_REQ *pSMB = NULL;
2555         RENAME_RSP *pSMBr = NULL;
2556         int bytes_returned;
2557         int name_len, name_len2;
2558         __u16 count;
2559
2560         cFYI(1, "In CIFSSMBRename");
2561 renameRetry:
2562         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2563                       (void **) &pSMBr);
2564         if (rc)
2565                 return rc;
2566
2567         pSMB->BufferFormat = 0x04;
2568         pSMB->SearchAttributes =
2569             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2570                         ATTR_DIRECTORY);
2571
2572         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2573                 name_len =
2574                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2575                                        PATH_MAX, nls_codepage, remap);
2576                 name_len++;     /* trailing null */
2577                 name_len *= 2;
2578                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2579         /* protocol requires ASCII signature byte on Unicode string */
2580                 pSMB->OldFileName[name_len + 1] = 0x00;
2581                 name_len2 =
2582                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2583                                        toName, PATH_MAX, nls_codepage, remap);
2584                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2585                 name_len2 *= 2; /* convert to bytes */
2586         } else {        /* BB improve the check for buffer overruns BB */
2587                 name_len = strnlen(fromName, PATH_MAX);
2588                 name_len++;     /* trailing null */
2589                 strncpy(pSMB->OldFileName, fromName, name_len);
2590                 name_len2 = strnlen(toName, PATH_MAX);
2591                 name_len2++;    /* trailing null */
2592                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2593                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2594                 name_len2++;    /* trailing null */
2595                 name_len2++;    /* signature byte */
2596         }
2597
2598         count = 1 /* 1st signature byte */  + name_len + name_len2;
2599         inc_rfc1001_len(pSMB, count);
2600         pSMB->ByteCount = cpu_to_le16(count);
2601
2602         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2603                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2604         cifs_stats_inc(&tcon->num_renames);
2605         if (rc)
2606                 cFYI(1, "Send error in rename = %d", rc);
2607
2608         cifs_buf_release(pSMB);
2609
2610         if (rc == -EAGAIN)
2611                 goto renameRetry;
2612
2613         return rc;
2614 }
2615
2616 int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
2617                 int netfid, const char *target_name,
2618                 const struct nls_table *nls_codepage, int remap)
2619 {
2620         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2621         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2622         struct set_file_rename *rename_info;
2623         char *data_offset;
2624         char dummy_string[30];
2625         int rc = 0;
2626         int bytes_returned = 0;
2627         int len_of_str;
2628         __u16 params, param_offset, offset, count, byte_count;
2629
2630         cFYI(1, "Rename to File by handle");
2631         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2632                         (void **) &pSMBr);
2633         if (rc)
2634                 return rc;
2635
2636         params = 6;
2637         pSMB->MaxSetupCount = 0;
2638         pSMB->Reserved = 0;
2639         pSMB->Flags = 0;
2640         pSMB->Timeout = 0;
2641         pSMB->Reserved2 = 0;
2642         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2643         offset = param_offset + params;
2644
2645         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2646         rename_info = (struct set_file_rename *) data_offset;
2647         pSMB->MaxParameterCount = cpu_to_le16(2);
2648         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2649         pSMB->SetupCount = 1;
2650         pSMB->Reserved3 = 0;
2651         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2652         byte_count = 3 /* pad */  + params;
2653         pSMB->ParameterCount = cpu_to_le16(params);
2654         pSMB->TotalParameterCount = pSMB->ParameterCount;
2655         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2656         pSMB->DataOffset = cpu_to_le16(offset);
2657         /* construct random name ".cifs_tmp<inodenum><mid>" */
2658         rename_info->overwrite = cpu_to_le32(1);
2659         rename_info->root_fid  = 0;
2660         /* unicode only call */
2661         if (target_name == NULL) {
2662                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2663                 len_of_str =
2664                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2665                                         dummy_string, 24, nls_codepage, remap);
2666         } else {
2667                 len_of_str =
2668                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2669                                         target_name, PATH_MAX, nls_codepage,
2670                                         remap);
2671         }
2672         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2673         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2674         byte_count += count;
2675         pSMB->DataCount = cpu_to_le16(count);
2676         pSMB->TotalDataCount = pSMB->DataCount;
2677         pSMB->Fid = netfid;
2678         pSMB->InformationLevel =
2679                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2680         pSMB->Reserved4 = 0;
2681         inc_rfc1001_len(pSMB, byte_count);
2682         pSMB->ByteCount = cpu_to_le16(byte_count);
2683         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2684                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2685         cifs_stats_inc(&pTcon->num_t2renames);
2686         if (rc)
2687                 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2688
2689         cifs_buf_release(pSMB);
2690
2691         /* Note: On -EAGAIN error only caller can retry on handle based calls
2692                 since file handle passed in no longer valid */
2693
2694         return rc;
2695 }
2696
2697 int
2698 CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
2699             const __u16 target_tid, const char *toName, const int flags,
2700             const struct nls_table *nls_codepage, int remap)
2701 {
2702         int rc = 0;
2703         COPY_REQ *pSMB = NULL;
2704         COPY_RSP *pSMBr = NULL;
2705         int bytes_returned;
2706         int name_len, name_len2;
2707         __u16 count;
2708
2709         cFYI(1, "In CIFSSMBCopy");
2710 copyRetry:
2711         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2712                         (void **) &pSMBr);
2713         if (rc)
2714                 return rc;
2715
2716         pSMB->BufferFormat = 0x04;
2717         pSMB->Tid2 = target_tid;
2718
2719         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2720
2721         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2722                 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2723                                               fromName, PATH_MAX, nls_codepage,
2724                                               remap);
2725                 name_len++;     /* trailing null */
2726                 name_len *= 2;
2727                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2728                 /* protocol requires ASCII signature byte on Unicode string */
2729                 pSMB->OldFileName[name_len + 1] = 0x00;
2730                 name_len2 =
2731                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2732                                        toName, PATH_MAX, nls_codepage, remap);
2733                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2734                 name_len2 *= 2; /* convert to bytes */
2735         } else {        /* BB improve the check for buffer overruns BB */
2736                 name_len = strnlen(fromName, PATH_MAX);
2737                 name_len++;     /* trailing null */
2738                 strncpy(pSMB->OldFileName, fromName, name_len);
2739                 name_len2 = strnlen(toName, PATH_MAX);
2740                 name_len2++;    /* trailing null */
2741                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2742                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2743                 name_len2++;    /* trailing null */
2744                 name_len2++;    /* signature byte */
2745         }
2746
2747         count = 1 /* 1st signature byte */  + name_len + name_len2;
2748         inc_rfc1001_len(pSMB, count);
2749         pSMB->ByteCount = cpu_to_le16(count);
2750
2751         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2752                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2753         if (rc) {
2754                 cFYI(1, "Send error in copy = %d with %d files copied",
2755                         rc, le16_to_cpu(pSMBr->CopyCount));
2756         }
2757         cifs_buf_release(pSMB);
2758
2759         if (rc == -EAGAIN)
2760                 goto copyRetry;
2761
2762         return rc;
2763 }
2764
2765 int
2766 CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
2767                       const char *fromName, const char *toName,
2768                       const struct nls_table *nls_codepage)
2769 {
2770         TRANSACTION2_SPI_REQ *pSMB = NULL;
2771         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2772         char *data_offset;
2773         int name_len;
2774         int name_len_target;
2775         int rc = 0;
2776         int bytes_returned = 0;
2777         __u16 params, param_offset, offset, byte_count;
2778
2779         cFYI(1, "In Symlink Unix style");
2780 createSymLinkRetry:
2781         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2782                       (void **) &pSMBr);
2783         if (rc)
2784                 return rc;
2785
2786         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2787                 name_len =
2788                     cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2789                                     /* find define for this maxpathcomponent */
2790                                     PATH_MAX, nls_codepage);
2791                 name_len++;     /* trailing null */
2792                 name_len *= 2;
2793
2794         } else {        /* BB improve the check for buffer overruns BB */
2795                 name_len = strnlen(fromName, PATH_MAX);
2796                 name_len++;     /* trailing null */
2797                 strncpy(pSMB->FileName, fromName, name_len);
2798         }
2799         params = 6 + name_len;
2800         pSMB->MaxSetupCount = 0;
2801         pSMB->Reserved = 0;
2802         pSMB->Flags = 0;
2803         pSMB->Timeout = 0;
2804         pSMB->Reserved2 = 0;
2805         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2806                                 InformationLevel) - 4;
2807         offset = param_offset + params;
2808
2809         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2810         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2811                 name_len_target =
2812                     cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2813                                     /* find define for this maxpathcomponent */
2814                                     , nls_codepage);
2815                 name_len_target++;      /* trailing null */
2816                 name_len_target *= 2;
2817         } else {        /* BB improve the check for buffer overruns BB */
2818                 name_len_target = strnlen(toName, PATH_MAX);
2819                 name_len_target++;      /* trailing null */
2820                 strncpy(data_offset, toName, name_len_target);
2821         }
2822
2823         pSMB->MaxParameterCount = cpu_to_le16(2);
2824         /* BB find exact max on data count below from sess */
2825         pSMB->MaxDataCount = cpu_to_le16(1000);
2826         pSMB->SetupCount = 1;
2827         pSMB->Reserved3 = 0;
2828         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2829         byte_count = 3 /* pad */  + params + name_len_target;
2830         pSMB->DataCount = cpu_to_le16(name_len_target);
2831         pSMB->ParameterCount = cpu_to_le16(params);
2832         pSMB->TotalDataCount = pSMB->DataCount;
2833         pSMB->TotalParameterCount = pSMB->ParameterCount;
2834         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2835         pSMB->DataOffset = cpu_to_le16(offset);
2836         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2837         pSMB->Reserved4 = 0;
2838         inc_rfc1001_len(pSMB, byte_count);
2839         pSMB->ByteCount = cpu_to_le16(byte_count);
2840         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2841                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2842         cifs_stats_inc(&tcon->num_symlinks);
2843         if (rc)
2844                 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2845
2846         cifs_buf_release(pSMB);
2847
2848         if (rc == -EAGAIN)
2849                 goto createSymLinkRetry;
2850
2851         return rc;
2852 }
2853
2854 int
2855 CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
2856                        const char *fromName, const char *toName,
2857                        const struct nls_table *nls_codepage, int remap)
2858 {
2859         TRANSACTION2_SPI_REQ *pSMB = NULL;
2860         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2861         char *data_offset;
2862         int name_len;
2863         int name_len_target;
2864         int rc = 0;
2865         int bytes_returned = 0;
2866         __u16 params, param_offset, offset, byte_count;
2867
2868         cFYI(1, "In Create Hard link Unix style");
2869 createHardLinkRetry:
2870         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2871                       (void **) &pSMBr);
2872         if (rc)
2873                 return rc;
2874
2875         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2876                 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2877                                               PATH_MAX, nls_codepage, remap);
2878                 name_len++;     /* trailing null */
2879                 name_len *= 2;
2880
2881         } else {        /* BB improve the check for buffer overruns BB */
2882                 name_len = strnlen(toName, PATH_MAX);
2883                 name_len++;     /* trailing null */
2884                 strncpy(pSMB->FileName, toName, name_len);
2885         }
2886         params = 6 + name_len;
2887         pSMB->MaxSetupCount = 0;
2888         pSMB->Reserved = 0;
2889         pSMB->Flags = 0;
2890         pSMB->Timeout = 0;
2891         pSMB->Reserved2 = 0;
2892         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2893                                 InformationLevel) - 4;
2894         offset = param_offset + params;
2895
2896         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2897         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2898                 name_len_target =
2899                     cifsConvertToUTF16((__le16 *) data_offset, fromName,
2900                                        PATH_MAX, nls_codepage, remap);
2901                 name_len_target++;      /* trailing null */
2902                 name_len_target *= 2;
2903         } else {        /* BB improve the check for buffer overruns BB */
2904                 name_len_target = strnlen(fromName, PATH_MAX);
2905                 name_len_target++;      /* trailing null */
2906                 strncpy(data_offset, fromName, name_len_target);
2907         }
2908
2909         pSMB->MaxParameterCount = cpu_to_le16(2);
2910         /* BB find exact max on data count below from sess*/
2911         pSMB->MaxDataCount = cpu_to_le16(1000);
2912         pSMB->SetupCount = 1;
2913         pSMB->Reserved3 = 0;
2914         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2915         byte_count = 3 /* pad */  + params + name_len_target;
2916         pSMB->ParameterCount = cpu_to_le16(params);
2917         pSMB->TotalParameterCount = pSMB->ParameterCount;
2918         pSMB->DataCount = cpu_to_le16(name_len_target);
2919         pSMB->TotalDataCount = pSMB->DataCount;
2920         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2921         pSMB->DataOffset = cpu_to_le16(offset);
2922         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2923         pSMB->Reserved4 = 0;
2924         inc_rfc1001_len(pSMB, byte_count);
2925         pSMB->ByteCount = cpu_to_le16(byte_count);
2926         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2927                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2928         cifs_stats_inc(&tcon->num_hardlinks);
2929         if (rc)
2930                 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2931
2932         cifs_buf_release(pSMB);
2933         if (rc == -EAGAIN)
2934                 goto createHardLinkRetry;
2935
2936         return rc;
2937 }
2938
2939 int
2940 CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
2941                    const char *fromName, const char *toName,
2942                    const struct nls_table *nls_codepage, int remap)
2943 {
2944         int rc = 0;
2945         NT_RENAME_REQ *pSMB = NULL;
2946         RENAME_RSP *pSMBr = NULL;
2947         int bytes_returned;
2948         int name_len, name_len2;
2949         __u16 count;
2950
2951         cFYI(1, "In CIFSCreateHardLink");
2952 winCreateHardLinkRetry:
2953
2954         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2955                       (void **) &pSMBr);
2956         if (rc)
2957                 return rc;
2958
2959         pSMB->SearchAttributes =
2960             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2961                         ATTR_DIRECTORY);
2962         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2963         pSMB->ClusterCount = 0;
2964
2965         pSMB->BufferFormat = 0x04;
2966
2967         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2968                 name_len =
2969                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2970                                        PATH_MAX, nls_codepage, remap);
2971                 name_len++;     /* trailing null */
2972                 name_len *= 2;
2973
2974                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2975                 pSMB->OldFileName[name_len] = 0x04;
2976                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2977                 name_len2 =
2978                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2979                                        toName, PATH_MAX, nls_codepage, remap);
2980                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2981                 name_len2 *= 2; /* convert to bytes */
2982         } else {        /* BB improve the check for buffer overruns BB */
2983                 name_len = strnlen(fromName, PATH_MAX);
2984                 name_len++;     /* trailing null */
2985                 strncpy(pSMB->OldFileName, fromName, name_len);
2986                 name_len2 = strnlen(toName, PATH_MAX);
2987                 name_len2++;    /* trailing null */
2988                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2989                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2990                 name_len2++;    /* trailing null */
2991                 name_len2++;    /* signature byte */
2992         }
2993
2994         count = 1 /* string type byte */  + name_len + name_len2;
2995         inc_rfc1001_len(pSMB, count);
2996         pSMB->ByteCount = cpu_to_le16(count);
2997
2998         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2999                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3000         cifs_stats_inc(&tcon->num_hardlinks);
3001         if (rc)
3002                 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3003
3004         cifs_buf_release(pSMB);
3005         if (rc == -EAGAIN)
3006                 goto winCreateHardLinkRetry;
3007
3008         return rc;
3009 }
3010
3011 int
3012 CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
3013                         const unsigned char *searchName, char **symlinkinfo,
3014                         const struct nls_table *nls_codepage)
3015 {
3016 /* SMB_QUERY_FILE_UNIX_LINK */
3017         TRANSACTION2_QPI_REQ *pSMB = NULL;
3018         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3019         int rc = 0;
3020         int bytes_returned;
3021         int name_len;
3022         __u16 params, byte_count;
3023         char *data_start;
3024
3025         cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3026
3027 querySymLinkRetry:
3028         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3029                       (void **) &pSMBr);
3030         if (rc)
3031                 return rc;
3032
3033         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3034                 name_len =
3035                         cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3036                                         PATH_MAX, nls_codepage);
3037                 name_len++;     /* trailing null */
3038                 name_len *= 2;
3039         } else {        /* BB improve the check for buffer overruns BB */
3040                 name_len = strnlen(searchName, PATH_MAX);
3041                 name_len++;     /* trailing null */
3042                 strncpy(pSMB->FileName, searchName, name_len);
3043         }
3044
3045         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3046         pSMB->TotalDataCount = 0;
3047         pSMB->MaxParameterCount = cpu_to_le16(2);
3048         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3049         pSMB->MaxSetupCount = 0;
3050         pSMB->Reserved = 0;
3051         pSMB->Flags = 0;
3052         pSMB->Timeout = 0;
3053         pSMB->Reserved2 = 0;
3054         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3055         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3056         pSMB->DataCount = 0;
3057         pSMB->DataOffset = 0;
3058         pSMB->SetupCount = 1;
3059         pSMB->Reserved3 = 0;
3060         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3061         byte_count = params + 1 /* pad */ ;
3062         pSMB->TotalParameterCount = cpu_to_le16(params);
3063         pSMB->ParameterCount = pSMB->TotalParameterCount;
3064         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3065         pSMB->Reserved4 = 0;
3066         inc_rfc1001_len(pSMB, byte_count);
3067         pSMB->ByteCount = cpu_to_le16(byte_count);
3068
3069         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3070                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3071         if (rc) {
3072                 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3073         } else {
3074                 /* decode response */
3075
3076                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3077                 /* BB also check enough total bytes returned */
3078                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3079                         rc = -EIO;
3080                 else {
3081                         bool is_unicode;
3082                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3083
3084                         data_start = ((char *) &pSMBr->hdr.Protocol) +
3085                                            le16_to_cpu(pSMBr->t2.DataOffset);
3086
3087                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3088                                 is_unicode = true;
3089                         else
3090                                 is_unicode = false;
3091
3092                         /* BB FIXME investigate remapping reserved chars here */
3093                         *symlinkinfo = cifs_strndup_from_utf16(data_start,
3094                                         count, is_unicode, nls_codepage);
3095                         if (!*symlinkinfo)
3096                                 rc = -ENOMEM;
3097                 }
3098         }
3099         cifs_buf_release(pSMB);
3100         if (rc == -EAGAIN)
3101                 goto querySymLinkRetry;
3102         return rc;
3103 }
3104
3105 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3106 /*
3107  *      Recent Windows versions now create symlinks more frequently
3108  *      and they use the "reparse point" mechanism below.  We can of course
3109  *      do symlinks nicely to Samba and other servers which support the
3110  *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3111  *      "MF" symlinks optionally, but for recent Windows we really need to
3112  *      reenable the code below and fix the cifs_symlink callers to handle this.
3113  *      In the interim this code has been moved to its own config option so
3114  *      it is not compiled in by default until callers fixed up and more tested.
3115  */
3116 int
3117 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
3118                         const unsigned char *searchName,
3119                         char *symlinkinfo, const int buflen, __u16 fid,
3120                         const struct nls_table *nls_codepage)
3121 {
3122         int rc = 0;
3123         int bytes_returned;
3124         struct smb_com_transaction_ioctl_req *pSMB;
3125         struct smb_com_transaction_ioctl_rsp *pSMBr;
3126
3127         cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3128         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3129                       (void **) &pSMBr);
3130         if (rc)
3131                 return rc;
3132
3133         pSMB->TotalParameterCount = 0 ;
3134         pSMB->TotalDataCount = 0;
3135         pSMB->MaxParameterCount = cpu_to_le32(2);
3136         /* BB find exact data count max from sess structure BB */
3137         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3138         pSMB->MaxSetupCount = 4;
3139         pSMB->Reserved = 0;
3140         pSMB->ParameterOffset = 0;
3141         pSMB->DataCount = 0;
3142         pSMB->DataOffset = 0;
3143         pSMB->SetupCount = 4;
3144         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3145         pSMB->ParameterCount = pSMB->TotalParameterCount;
3146         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3147         pSMB->IsFsctl = 1; /* FSCTL */
3148         pSMB->IsRootFlag = 0;
3149         pSMB->Fid = fid; /* file handle always le */
3150         pSMB->ByteCount = 0;
3151
3152         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3153                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3154         if (rc) {
3155                 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3156         } else {                /* decode response */
3157                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3158                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3159                 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3160                         /* BB also check enough total bytes returned */
3161                         rc = -EIO;      /* bad smb */
3162                         goto qreparse_out;
3163                 }
3164                 if (data_count && (data_count < 2048)) {
3165                         char *end_of_smb = 2 /* sizeof byte count */ +
3166                                get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3167
3168                         struct reparse_data *reparse_buf =
3169                                                 (struct reparse_data *)
3170                                                 ((char *)&pSMBr->hdr.Protocol
3171                                                                  + data_offset);
3172                         if ((char *)reparse_buf >= end_of_smb) {
3173                                 rc = -EIO;
3174                                 goto qreparse_out;
3175                         }
3176                         if ((reparse_buf->LinkNamesBuf +
3177                                 reparse_buf->TargetNameOffset +
3178                                 reparse_buf->TargetNameLen) > end_of_smb) {
3179                                 cFYI(1, "reparse buf beyond SMB");
3180                                 rc = -EIO;
3181                                 goto qreparse_out;
3182                         }
3183
3184                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3185                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
3186                                                 (reparse_buf->LinkNamesBuf +
3187                                                 reparse_buf->TargetNameOffset),
3188                                                 buflen,
3189                                                 reparse_buf->TargetNameLen,
3190                                                 nls_codepage, 0);
3191                         } else { /* ASCII names */
3192                                 strncpy(symlinkinfo,
3193                                         reparse_buf->LinkNamesBuf +
3194                                         reparse_buf->TargetNameOffset,
3195                                         min_t(const int, buflen,
3196                                            reparse_buf->TargetNameLen));
3197                         }
3198                 } else {
3199                         rc = -EIO;
3200                         cFYI(1, "Invalid return data count on "
3201                                  "get reparse info ioctl");
3202                 }
3203                 symlinkinfo[buflen] = 0; /* just in case so the caller
3204                                         does not go off the end of the buffer */
3205                 cFYI(1, "readlink result - %s", symlinkinfo);
3206         }
3207
3208 qreparse_out:
3209         cifs_buf_release(pSMB);
3210
3211         /* Note: On -EAGAIN error only caller can retry on handle based calls
3212                 since file handle passed in no longer valid */
3213
3214         return rc;
3215 }
3216 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3217
3218 #ifdef CONFIG_CIFS_POSIX
3219
3220 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3221 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3222                              struct cifs_posix_ace *cifs_ace)
3223 {
3224         /* u8 cifs fields do not need le conversion */
3225         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3226         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3227         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3228         /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3229
3230         return;
3231 }
3232
3233 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3234 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3235                                const int acl_type, const int size_of_data_area)
3236 {
3237         int size =  0;
3238         int i;
3239         __u16 count;
3240         struct cifs_posix_ace *pACE;
3241         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3242         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3243
3244         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3245                 return -EOPNOTSUPP;
3246
3247         if (acl_type & ACL_TYPE_ACCESS) {
3248                 count = le16_to_cpu(cifs_acl->access_entry_count);
3249                 pACE = &cifs_acl->ace_array[0];
3250                 size = sizeof(struct cifs_posix_acl);
3251                 size += sizeof(struct cifs_posix_ace) * count;
3252                 /* check if we would go beyond end of SMB */
3253                 if (size_of_data_area < size) {
3254                         cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3255                                 size_of_data_area, size);
3256                         return -EINVAL;
3257                 }
3258         } else if (acl_type & ACL_TYPE_DEFAULT) {
3259                 count = le16_to_cpu(cifs_acl->access_entry_count);
3260                 size = sizeof(struct cifs_posix_acl);
3261                 size += sizeof(struct cifs_posix_ace) * count;
3262 /* skip past access ACEs to get to default ACEs */
3263                 pACE = &cifs_acl->ace_array[count];
3264                 count = le16_to_cpu(cifs_acl->default_entry_count);
3265                 size += sizeof(struct cifs_posix_ace) * count;
3266                 /* check if we would go beyond end of SMB */
3267                 if (size_of_data_area < size)
3268                         return -EINVAL;
3269         } else {
3270                 /* illegal type */
3271                 return -EINVAL;
3272         }
3273
3274         size = posix_acl_xattr_size(count);
3275         if ((buflen == 0) || (local_acl == NULL)) {
3276                 /* used to query ACL EA size */
3277         } else if (size > buflen) {
3278                 return -ERANGE;
3279         } else /* buffer big enough */ {
3280                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3281                 for (i = 0; i < count ; i++) {
3282                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
3283                         pACE++;
3284                 }
3285         }
3286         return size;
3287 }
3288
3289 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3290                                      const posix_acl_xattr_entry *local_ace)
3291 {
3292         __u16 rc = 0; /* 0 = ACL converted ok */
3293
3294         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3295         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3296         /* BB is there a better way to handle the large uid? */
3297         if (local_ace->e_id == cpu_to_le32(-1)) {
3298         /* Probably no need to le convert -1 on any arch but can not hurt */
3299                 cifs_ace->cifs_uid = cpu_to_le64(-1);
3300         } else
3301                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3302         /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3303         return rc;
3304 }
3305
3306 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3307 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3308                                const int buflen, const int acl_type)
3309 {
3310         __u16 rc = 0;
3311         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3312         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3313         int count;
3314         int i;
3315
3316         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3317                 return 0;
3318
3319         count = posix_acl_xattr_count((size_t)buflen);
3320         cFYI(1, "setting acl with %d entries from buf of length %d and "
3321                 "version of %d",
3322                 count, buflen, le32_to_cpu(local_acl->a_version));
3323         if (le32_to_cpu(local_acl->a_version) != 2) {
3324                 cFYI(1, "unknown POSIX ACL version %d",
3325                      le32_to_cpu(local_acl->a_version));
3326                 return 0;
3327         }
3328         cifs_acl->version = cpu_to_le16(1);
3329         if (acl_type == ACL_TYPE_ACCESS)
3330                 cifs_acl->access_entry_count = cpu_to_le16(count);
3331         else if (acl_type == ACL_TYPE_DEFAULT)
3332                 cifs_acl->default_entry_count = cpu_to_le16(count);
3333         else {
3334                 cFYI(1, "unknown ACL type %d", acl_type);
3335                 return 0;
3336         }
3337         for (i = 0; i < count; i++) {
3338                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3339                                         &local_acl->a_entries[i]);
3340                 if (rc != 0) {
3341                         /* ACE not converted */
3342                         break;
3343                 }
3344         }
3345         if (rc == 0) {
3346                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3347                 rc += sizeof(struct cifs_posix_acl);
3348                 /* BB add check to make sure ACL does not overflow SMB */
3349         }
3350         return rc;
3351 }
3352
3353 int
3354 CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3355                    const unsigned char *searchName,
3356                    char *acl_inf, const int buflen, const int acl_type,
3357                    const struct nls_table *nls_codepage, int remap)
3358 {
3359 /* SMB_QUERY_POSIX_ACL */
3360         TRANSACTION2_QPI_REQ *pSMB = NULL;
3361         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3362         int rc = 0;
3363         int bytes_returned;
3364         int name_len;
3365         __u16 params, byte_count;
3366
3367         cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3368
3369 queryAclRetry:
3370         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3371                 (void **) &pSMBr);
3372         if (rc)
3373                 return rc;
3374
3375         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3376                 name_len =
3377                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3378                                            searchName, PATH_MAX, nls_codepage,
3379                                            remap);
3380                 name_len++;     /* trailing null */
3381                 name_len *= 2;
3382                 pSMB->FileName[name_len] = 0;
3383                 pSMB->FileName[name_len+1] = 0;
3384         } else {        /* BB improve the check for buffer overruns BB */
3385                 name_len = strnlen(searchName, PATH_MAX);
3386                 name_len++;     /* trailing null */
3387                 strncpy(pSMB->FileName, searchName, name_len);
3388         }
3389
3390         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3391         pSMB->TotalDataCount = 0;
3392         pSMB->MaxParameterCount = cpu_to_le16(2);
3393         /* BB find exact max data count below from sess structure BB */
3394         pSMB->MaxDataCount = cpu_to_le16(4000);
3395         pSMB->MaxSetupCount = 0;
3396         pSMB->Reserved = 0;
3397         pSMB->Flags = 0;
3398         pSMB->Timeout = 0;
3399         pSMB->Reserved2 = 0;
3400         pSMB->ParameterOffset = cpu_to_le16(
3401                 offsetof(struct smb_com_transaction2_qpi_req,
3402                          InformationLevel) - 4);
3403         pSMB->DataCount = 0;
3404         pSMB->DataOffset = 0;
3405         pSMB->SetupCount = 1;
3406         pSMB->Reserved3 = 0;
3407         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3408         byte_count = params + 1 /* pad */ ;
3409         pSMB->TotalParameterCount = cpu_to_le16(params);
3410         pSMB->ParameterCount = pSMB->TotalParameterCount;
3411         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3412         pSMB->Reserved4 = 0;
3413         inc_rfc1001_len(pSMB, byte_count);
3414         pSMB->ByteCount = cpu_to_le16(byte_count);
3415
3416         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3417                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3418         cifs_stats_inc(&tcon->num_acl_get);
3419         if (rc) {
3420                 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3421         } else {
3422                 /* decode response */
3423
3424                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3425                 /* BB also check enough total bytes returned */
3426                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3427                         rc = -EIO;      /* bad smb */
3428                 else {
3429                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3430                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3431                         rc = cifs_copy_posix_acl(acl_inf,
3432                                 (char *)&pSMBr->hdr.Protocol+data_offset,
3433                                 buflen, acl_type, count);
3434                 }
3435         }
3436         cifs_buf_release(pSMB);
3437         if (rc == -EAGAIN)
3438                 goto queryAclRetry;
3439         return rc;
3440 }
3441
3442 int
3443 CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3444                    const unsigned char *fileName,
3445                    const char *local_acl, const int buflen,
3446                    const int acl_type,
3447                    const struct nls_table *nls_codepage, int remap)
3448 {
3449         struct smb_com_transaction2_spi_req *pSMB = NULL;
3450         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3451         char *parm_data;
3452         int name_len;
3453         int rc = 0;
3454         int bytes_returned = 0;
3455         __u16 params, byte_count, data_count, param_offset, offset;
3456
3457         cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3458 setAclRetry:
3459         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3460                       (void **) &pSMBr);
3461         if (rc)
3462                 return rc;
3463         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3464                 name_len =
3465                         cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3466                                            PATH_MAX, nls_codepage, remap);
3467                 name_len++;     /* trailing null */
3468                 name_len *= 2;
3469         } else {        /* BB improve the check for buffer overruns BB */
3470                 name_len = strnlen(fileName, PATH_MAX);
3471                 name_len++;     /* trailing null */
3472                 strncpy(pSMB->FileName, fileName, name_len);
3473         }
3474         params = 6 + name_len;
3475         pSMB->MaxParameterCount = cpu_to_le16(2);
3476         /* BB find max SMB size from sess */
3477         pSMB->MaxDataCount = cpu_to_le16(1000);
3478         pSMB->MaxSetupCount = 0;
3479         pSMB->Reserved = 0;
3480         pSMB->Flags = 0;
3481         pSMB->Timeout = 0;
3482         pSMB->Reserved2 = 0;
3483         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3484                                 InformationLevel) - 4;
3485         offset = param_offset + params;
3486         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3487         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3488
3489         /* convert to on the wire format for POSIX ACL */
3490         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3491
3492         if (data_count == 0) {
3493                 rc = -EOPNOTSUPP;
3494                 goto setACLerrorExit;
3495         }
3496         pSMB->DataOffset = cpu_to_le16(offset);
3497         pSMB->SetupCount = 1;
3498         pSMB->Reserved3 = 0;
3499         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3500         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3501         byte_count = 3 /* pad */  + params + data_count;
3502         pSMB->DataCount = cpu_to_le16(data_count);
3503         pSMB->TotalDataCount = pSMB->DataCount;
3504         pSMB->ParameterCount = cpu_to_le16(params);
3505         pSMB->TotalParameterCount = pSMB->ParameterCount;
3506         pSMB->Reserved4 = 0;
3507         inc_rfc1001_len(pSMB, byte_count);
3508         pSMB->ByteCount = cpu_to_le16(byte_count);
3509         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3510                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3511         if (rc)
3512                 cFYI(1, "Set POSIX ACL returned %d", rc);
3513
3514 setACLerrorExit:
3515         cifs_buf_release(pSMB);
3516         if (rc == -EAGAIN)
3517                 goto setAclRetry;
3518         return rc;
3519 }
3520
3521 /* BB fix tabs in this function FIXME BB */
3522 int
3523 CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3524                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3525 {
3526         int rc = 0;
3527         struct smb_t2_qfi_req *pSMB = NULL;
3528         struct smb_t2_qfi_rsp *pSMBr = NULL;
3529         int bytes_returned;
3530         __u16 params, byte_count;
3531
3532         cFYI(1, "In GetExtAttr");
3533         if (tcon == NULL)
3534                 return -ENODEV;
3535
3536 GetExtAttrRetry:
3537         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3538                         (void **) &pSMBr);
3539         if (rc)
3540                 return rc;
3541
3542         params = 2 /* level */ + 2 /* fid */;
3543         pSMB->t2.TotalDataCount = 0;
3544         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3545         /* BB find exact max data count below from sess structure BB */
3546         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3547         pSMB->t2.MaxSetupCount = 0;
3548         pSMB->t2.Reserved = 0;
3549         pSMB->t2.Flags = 0;
3550         pSMB->t2.Timeout = 0;
3551         pSMB->t2.Reserved2 = 0;
3552         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3553                                                Fid) - 4);
3554         pSMB->t2.DataCount = 0;
3555         pSMB->t2.DataOffset = 0;
3556         pSMB->t2.SetupCount = 1;
3557         pSMB->t2.Reserved3 = 0;
3558         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3559         byte_count = params + 1 /* pad */ ;
3560         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3561         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3562         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3563         pSMB->Pad = 0;
3564         pSMB->Fid = netfid;
3565         inc_rfc1001_len(pSMB, byte_count);
3566         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3567
3568         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3569                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3570         if (rc) {
3571                 cFYI(1, "error %d in GetExtAttr", rc);
3572         } else {
3573                 /* decode response */
3574                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3575                 /* BB also check enough total bytes returned */
3576                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3577                         /* If rc should we check for EOPNOSUPP and
3578                            disable the srvino flag? or in caller? */
3579                         rc = -EIO;      /* bad smb */
3580                 else {
3581                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3582                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3583                         struct file_chattr_info *pfinfo;
3584                         /* BB Do we need a cast or hash here ? */
3585                         if (count != 16) {
3586                                 cFYI(1, "Illegal size ret in GetExtAttr");
3587                                 rc = -EIO;
3588                                 goto GetExtAttrOut;
3589                         }
3590                         pfinfo = (struct file_chattr_info *)
3591                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3592                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3593                         *pMask = le64_to_cpu(pfinfo->mask);
3594                 }
3595         }
3596 GetExtAttrOut:
3597         cifs_buf_release(pSMB);
3598         if (rc == -EAGAIN)
3599                 goto GetExtAttrRetry;
3600         return rc;
3601 }
3602
3603 #endif /* CONFIG_POSIX */
3604
3605 #ifdef CONFIG_CIFS_ACL
3606 /*
3607  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3608  * all NT TRANSACTS that we init here have total parm and data under about 400
3609  * bytes (to fit in small cifs buffer size), which is the case so far, it
3610  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3611  * returned setup area) and MaxParameterCount (returned parms size) must be set
3612  * by caller
3613  */
3614 static int
3615 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3616                    const int parm_len, struct cifs_tcon *tcon,
3617                    void **ret_buf)
3618 {
3619         int rc;
3620         __u32 temp_offset;
3621         struct smb_com_ntransact_req *pSMB;
3622
3623         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3624                                 (void **)&pSMB);
3625         if (rc)
3626                 return rc;
3627         *ret_buf = (void *)pSMB;
3628         pSMB->Reserved = 0;
3629         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3630         pSMB->TotalDataCount  = 0;
3631         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3632         pSMB->ParameterCount = pSMB->TotalParameterCount;
3633         pSMB->DataCount  = pSMB->TotalDataCount;
3634         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3635                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
3636         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3637         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3638         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3639         pSMB->SubCommand = cpu_to_le16(sub_command);
3640         return 0;
3641 }
3642
3643 static int
3644 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3645                    __u32 *pparmlen, __u32 *pdatalen)
3646 {
3647         char *end_of_smb;
3648         __u32 data_count, data_offset, parm_count, parm_offset;
3649         struct smb_com_ntransact_rsp *pSMBr;
3650         u16 bcc;
3651
3652         *pdatalen = 0;
3653         *pparmlen = 0;
3654
3655         if (buf == NULL)
3656                 return -EINVAL;
3657
3658         pSMBr = (struct smb_com_ntransact_rsp *)buf;
3659
3660         bcc = get_bcc(&pSMBr->hdr);
3661         end_of_smb = 2 /* sizeof byte count */ + bcc +
3662                         (char *)&pSMBr->ByteCount;
3663
3664         data_offset = le32_to_cpu(pSMBr->DataOffset);
3665         data_count = le32_to_cpu(pSMBr->DataCount);
3666         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3667         parm_count = le32_to_cpu(pSMBr->ParameterCount);
3668
3669         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3670         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3671
3672         /* should we also check that parm and data areas do not overlap? */
3673         if (*ppparm > end_of_smb) {
3674                 cFYI(1, "parms start after end of smb");
3675                 return -EINVAL;
3676         } else if (parm_count + *ppparm > end_of_smb) {
3677                 cFYI(1, "parm end after end of smb");
3678                 return -EINVAL;
3679         } else if (*ppdata > end_of_smb) {
3680                 cFYI(1, "data starts after end of smb");
3681                 return -EINVAL;
3682         } else if (data_count + *ppdata > end_of_smb) {
3683                 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3684                         *ppdata, data_count, (data_count + *ppdata),
3685                         end_of_smb, pSMBr);
3686                 return -EINVAL;
3687         } else if (parm_count + data_count > bcc) {
3688                 cFYI(1, "parm count and data count larger than SMB");
3689                 return -EINVAL;
3690         }
3691         *pdatalen = data_count;
3692         *pparmlen = parm_count;
3693         return 0;
3694 }
3695
3696 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3697 int
3698 CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3699                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3700 {
3701         int rc = 0;
3702         int buf_type = 0;
3703         QUERY_SEC_DESC_REQ *pSMB;
3704         struct kvec iov[1];
3705
3706         cFYI(1, "GetCifsACL");
3707
3708         *pbuflen = 0;
3709         *acl_inf = NULL;
3710
3711         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3712                         8 /* parm len */, tcon, (void **) &pSMB);
3713         if (rc)
3714                 return rc;
3715
3716         pSMB->MaxParameterCount = cpu_to_le32(4);
3717         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3718         pSMB->MaxSetupCount = 0;
3719         pSMB->Fid = fid; /* file handle always le */
3720         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3721                                      CIFS_ACL_DACL);
3722         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3723         inc_rfc1001_len(pSMB, 11);
3724         iov[0].iov_base = (char *)pSMB;
3725         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3726
3727         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3728                          0);
3729         cifs_stats_inc(&tcon->num_acl_get);
3730         if (rc) {
3731                 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3732         } else {                /* decode response */
3733                 __le32 *parm;
3734                 __u32 parm_len;
3735                 __u32 acl_len;
3736                 struct smb_com_ntransact_rsp *pSMBr;
3737                 char *pdata;
3738
3739 /* validate_nttransact */
3740                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3741                                         &pdata, &parm_len, pbuflen);
3742                 if (rc)
3743                         goto qsec_out;
3744                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3745
3746                 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3747
3748                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3749                         rc = -EIO;      /* bad smb */
3750                         *pbuflen = 0;
3751                         goto qsec_out;
3752                 }
3753
3754 /* BB check that data area is minimum length and as big as acl_len */
3755
3756                 acl_len = le32_to_cpu(*parm);
3757                 if (acl_len != *pbuflen) {
3758                         cERROR(1, "acl length %d does not match %d",
3759                                    acl_len, *pbuflen);
3760                         if (*pbuflen > acl_len)
3761                                 *pbuflen = acl_len;
3762                 }
3763
3764                 /* check if buffer is big enough for the acl
3765                    header followed by the smallest SID */
3766                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3767                     (*pbuflen >= 64 * 1024)) {
3768                         cERROR(1, "bad acl length %d", *pbuflen);
3769                         rc = -EINVAL;
3770                         *pbuflen = 0;
3771                 } else {
3772                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3773                         if (*acl_inf == NULL) {
3774                                 *pbuflen = 0;
3775                                 rc = -ENOMEM;
3776                         }
3777                         memcpy(*acl_inf, pdata, *pbuflen);
3778                 }
3779         }
3780 qsec_out:
3781         if (buf_type == CIFS_SMALL_BUFFER)
3782                 cifs_small_buf_release(iov[0].iov_base);
3783         else if (buf_type == CIFS_LARGE_BUFFER)
3784                 cifs_buf_release(iov[0].iov_base);
3785 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3786         return rc;
3787 }
3788
3789 int
3790 CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3791                         struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3792 {
3793         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3794         int rc = 0;
3795         int bytes_returned = 0;
3796         SET_SEC_DESC_REQ *pSMB = NULL;
3797         void *pSMBr;
3798
3799 setCifsAclRetry:
3800         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3801         if (rc)
3802                 return rc;
3803
3804         pSMB->MaxSetupCount = 0;
3805         pSMB->Reserved = 0;
3806
3807         param_count = 8;
3808         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3809         data_count = acllen;
3810         data_offset = param_offset + param_count;
3811         byte_count = 3 /* pad */  + param_count;
3812
3813         pSMB->DataCount = cpu_to_le32(data_count);
3814         pSMB->TotalDataCount = pSMB->DataCount;
3815         pSMB->MaxParameterCount = cpu_to_le32(4);
3816         pSMB->MaxDataCount = cpu_to_le32(16384);
3817         pSMB->ParameterCount = cpu_to_le32(param_count);
3818         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3819         pSMB->TotalParameterCount = pSMB->ParameterCount;
3820         pSMB->DataOffset = cpu_to_le32(data_offset);
3821         pSMB->SetupCount = 0;
3822         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3823         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3824
3825         pSMB->Fid = fid; /* file handle always le */
3826         pSMB->Reserved2 = 0;
3827         pSMB->AclFlags = cpu_to_le32(aclflag);
3828
3829         if (pntsd && acllen) {
3830                 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3831                                 data_offset, pntsd, acllen);
3832                 inc_rfc1001_len(pSMB, byte_count + data_count);
3833         } else
3834                 inc_rfc1001_len(pSMB, byte_count);
3835
3836         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3837                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3838
3839         cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3840         if (rc)
3841                 cFYI(1, "Set CIFS ACL returned %d", rc);
3842         cifs_buf_release(pSMB);
3843
3844         if (rc == -EAGAIN)
3845                 goto setCifsAclRetry;
3846
3847         return (rc);
3848 }
3849
3850 #endif /* CONFIG_CIFS_ACL */
3851
3852 /* Legacy Query Path Information call for lookup to old servers such
3853    as Win9x/WinME */
3854 int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3855                         const unsigned char *searchName,
3856                         FILE_ALL_INFO *pFinfo,
3857                         const struct nls_table *nls_codepage, int remap)
3858 {
3859         QUERY_INFORMATION_REQ *pSMB;
3860         QUERY_INFORMATION_RSP *pSMBr;
3861         int rc = 0;
3862         int bytes_returned;
3863         int name_len;
3864
3865         cFYI(1, "In SMBQPath path %s", searchName);
3866 QInfRetry:
3867         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3868                       (void **) &pSMBr);
3869         if (rc)
3870                 return rc;
3871
3872         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3873                 name_len =
3874                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3875                                            searchName, PATH_MAX, nls_codepage,
3876                                            remap);
3877                 name_len++;     /* trailing null */
3878                 name_len *= 2;
3879         } else {
3880                 name_len = strnlen(searchName, PATH_MAX);
3881                 name_len++;     /* trailing null */
3882                 strncpy(pSMB->FileName, searchName, name_len);
3883         }
3884         pSMB->BufferFormat = 0x04;
3885         name_len++; /* account for buffer type byte */
3886         inc_rfc1001_len(pSMB, (__u16)name_len);
3887         pSMB->ByteCount = cpu_to_le16(name_len);
3888
3889         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3890                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3891         if (rc) {
3892                 cFYI(1, "Send error in QueryInfo = %d", rc);
3893         } else if (pFinfo) {
3894                 struct timespec ts;
3895                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3896
3897                 /* decode response */
3898                 /* BB FIXME - add time zone adjustment BB */
3899                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3900                 ts.tv_nsec = 0;
3901                 ts.tv_sec = time;
3902                 /* decode time fields */
3903                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3904                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3905                 pFinfo->LastAccessTime = 0;
3906                 pFinfo->AllocationSize =
3907                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3908                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3909                 pFinfo->Attributes =
3910                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3911         } else
3912                 rc = -EIO; /* bad buffer passed in */
3913
3914         cifs_buf_release(pSMB);
3915
3916         if (rc == -EAGAIN)
3917                 goto QInfRetry;
3918
3919         return rc;
3920 }
3921
3922 int
3923 CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
3924                  u16 netfid, FILE_ALL_INFO *pFindData)
3925 {
3926         struct smb_t2_qfi_req *pSMB = NULL;
3927         struct smb_t2_qfi_rsp *pSMBr = NULL;
3928         int rc = 0;
3929         int bytes_returned;
3930         __u16 params, byte_count;
3931
3932 QFileInfoRetry:
3933         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3934                       (void **) &pSMBr);
3935         if (rc)
3936                 return rc;
3937
3938         params = 2 /* level */ + 2 /* fid */;
3939         pSMB->t2.TotalDataCount = 0;
3940         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3941         /* BB find exact max data count below from sess structure BB */
3942         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3943         pSMB->t2.MaxSetupCount = 0;
3944         pSMB->t2.Reserved = 0;
3945         pSMB->t2.Flags = 0;
3946         pSMB->t2.Timeout = 0;
3947         pSMB->t2.Reserved2 = 0;
3948         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3949                                                Fid) - 4);
3950         pSMB->t2.DataCount = 0;
3951         pSMB->t2.DataOffset = 0;
3952         pSMB->t2.SetupCount = 1;
3953         pSMB->t2.Reserved3 = 0;
3954         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3955         byte_count = params + 1 /* pad */ ;
3956         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3957         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3958         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3959         pSMB->Pad = 0;
3960         pSMB->Fid = netfid;
3961         inc_rfc1001_len(pSMB, byte_count);
3962
3963         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3964                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3965         if (rc) {
3966                 cFYI(1, "Send error in QPathInfo = %d", rc);
3967         } else {                /* decode response */
3968                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3969
3970                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3971                         rc = -EIO;
3972                 else if (get_bcc(&pSMBr->hdr) < 40)
3973                         rc = -EIO;      /* bad smb */
3974                 else if (pFindData) {
3975                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3976                         memcpy((char *) pFindData,
3977                                (char *) &pSMBr->hdr.Protocol +
3978                                data_offset, sizeof(FILE_ALL_INFO));
3979                 } else
3980                     rc = -ENOMEM;
3981         }
3982         cifs_buf_release(pSMB);
3983         if (rc == -EAGAIN)
3984                 goto QFileInfoRetry;
3985
3986         return rc;
3987 }
3988
3989 int
3990 CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
3991                  const unsigned char *searchName,
3992                  FILE_ALL_INFO *pFindData,
3993                  int legacy /* old style infolevel */,
3994                  const struct nls_table *nls_codepage, int remap)
3995 {
3996 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3997         TRANSACTION2_QPI_REQ *pSMB = NULL;
3998         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3999         int rc = 0;
4000         int bytes_returned;
4001         int name_len;
4002         __u16 params, byte_count;
4003
4004 /* cFYI(1, "In QPathInfo path %s", searchName); */
4005 QPathInfoRetry:
4006         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4007                       (void **) &pSMBr);
4008         if (rc)
4009                 return rc;
4010
4011         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4012                 name_len =
4013                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4014                                        PATH_MAX, nls_codepage, remap);
4015                 name_len++;     /* trailing null */
4016                 name_len *= 2;
4017         } else {        /* BB improve the check for buffer overruns BB */
4018                 name_len = strnlen(searchName, PATH_MAX);
4019                 name_len++;     /* trailing null */
4020                 strncpy(pSMB->FileName, searchName, name_len);
4021         }
4022
4023         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4024         pSMB->TotalDataCount = 0;
4025         pSMB->MaxParameterCount = cpu_to_le16(2);
4026         /* BB find exact max SMB PDU from sess structure BB */
4027         pSMB->MaxDataCount = cpu_to_le16(4000);
4028         pSMB->MaxSetupCount = 0;
4029         pSMB->Reserved = 0;
4030         pSMB->Flags = 0;
4031         pSMB->Timeout = 0;
4032         pSMB->Reserved2 = 0;
4033         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4034         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4035         pSMB->DataCount = 0;
4036         pSMB->DataOffset = 0;
4037         pSMB->SetupCount = 1;
4038         pSMB->Reserved3 = 0;
4039         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4040         byte_count = params + 1 /* pad */ ;
4041         pSMB->TotalParameterCount = cpu_to_le16(params);
4042         pSMB->ParameterCount = pSMB->TotalParameterCount;
4043         if (legacy)
4044                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4045         else
4046                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4047         pSMB->Reserved4 = 0;
4048         inc_rfc1001_len(pSMB, byte_count);
4049         pSMB->ByteCount = cpu_to_le16(byte_count);
4050
4051         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4052                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4053         if (rc) {
4054                 cFYI(1, "Send error in QPathInfo = %d", rc);
4055         } else {                /* decode response */
4056                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4057
4058                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4059                         rc = -EIO;
4060                 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4061                         rc = -EIO;      /* bad smb */
4062                 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4063                         rc = -EIO;  /* 24 or 26 expected but we do not read
4064                                         last field */
4065                 else if (pFindData) {
4066                         int size;
4067                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4068
4069                         /* On legacy responses we do not read the last field,
4070                         EAsize, fortunately since it varies by subdialect and
4071                         also note it differs on Set vs. Get, ie two bytes or 4
4072                         bytes depending but we don't care here */
4073                         if (legacy)
4074                                 size = sizeof(FILE_INFO_STANDARD);
4075                         else
4076                                 size = sizeof(FILE_ALL_INFO);
4077                         memcpy((char *) pFindData,
4078                                (char *) &pSMBr->hdr.Protocol +
4079                                data_offset, size);
4080                 } else
4081                     rc = -ENOMEM;
4082         }
4083         cifs_buf_release(pSMB);
4084         if (rc == -EAGAIN)
4085                 goto QPathInfoRetry;
4086
4087         return rc;
4088 }
4089
4090 int
4091 CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
4092                  u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4093 {
4094         struct smb_t2_qfi_req *pSMB = NULL;
4095         struct smb_t2_qfi_rsp *pSMBr = NULL;
4096         int rc = 0;
4097         int bytes_returned;
4098         __u16 params, byte_count;
4099
4100 UnixQFileInfoRetry:
4101         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4102                       (void **) &pSMBr);
4103         if (rc)
4104                 return rc;
4105
4106         params = 2 /* level */ + 2 /* fid */;
4107         pSMB->t2.TotalDataCount = 0;
4108         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4109         /* BB find exact max data count below from sess structure BB */
4110         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4111         pSMB->t2.MaxSetupCount = 0;
4112         pSMB->t2.Reserved = 0;
4113         pSMB->t2.Flags = 0;
4114         pSMB->t2.Timeout = 0;
4115         pSMB->t2.Reserved2 = 0;
4116         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4117                                                Fid) - 4);
4118         pSMB->t2.DataCount = 0;
4119         pSMB->t2.DataOffset = 0;
4120         pSMB->t2.SetupCount = 1;
4121         pSMB->t2.Reserved3 = 0;
4122         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4123         byte_count = params + 1 /* pad */ ;
4124         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4125         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4126         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4127         pSMB->Pad = 0;
4128         pSMB->Fid = netfid;
4129         inc_rfc1001_len(pSMB, byte_count);
4130
4131         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4132                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4133         if (rc) {
4134                 cFYI(1, "Send error in QPathInfo = %d", rc);
4135         } else {                /* decode response */
4136                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4137
4138                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4139                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4140                                    "Unix Extensions can be disabled on mount "
4141                                    "by specifying the nosfu mount option.");
4142                         rc = -EIO;      /* bad smb */
4143                 } else {
4144                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4145                         memcpy((char *) pFindData,
4146                                (char *) &pSMBr->hdr.Protocol +
4147                                data_offset,
4148                                sizeof(FILE_UNIX_BASIC_INFO));
4149                 }
4150         }
4151
4152         cifs_buf_release(pSMB);
4153         if (rc == -EAGAIN)
4154                 goto UnixQFileInfoRetry;
4155
4156         return rc;
4157 }
4158
4159 int
4160 CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
4161                      const unsigned char *searchName,
4162                      FILE_UNIX_BASIC_INFO *pFindData,
4163                      const struct nls_table *nls_codepage, int remap)
4164 {
4165 /* SMB_QUERY_FILE_UNIX_BASIC */
4166         TRANSACTION2_QPI_REQ *pSMB = NULL;
4167         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4168         int rc = 0;
4169         int bytes_returned = 0;
4170         int name_len;
4171         __u16 params, byte_count;
4172
4173         cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4174 UnixQPathInfoRetry:
4175         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4176                       (void **) &pSMBr);
4177         if (rc)
4178                 return rc;
4179
4180         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4181                 name_len =
4182                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4183                                        PATH_MAX, nls_codepage, remap);
4184                 name_len++;     /* trailing null */
4185                 name_len *= 2;
4186         } else {        /* BB improve the check for buffer overruns BB */
4187                 name_len = strnlen(searchName, PATH_MAX);
4188                 name_len++;     /* trailing null */
4189                 strncpy(pSMB->FileName, searchName, name_len);
4190         }
4191
4192         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4193         pSMB->TotalDataCount = 0;
4194         pSMB->MaxParameterCount = cpu_to_le16(2);
4195         /* BB find exact max SMB PDU from sess structure BB */
4196         pSMB->MaxDataCount = cpu_to_le16(4000);
4197         pSMB->MaxSetupCount = 0;
4198         pSMB->Reserved = 0;
4199         pSMB->Flags = 0;
4200         pSMB->Timeout = 0;
4201         pSMB->Reserved2 = 0;
4202         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4203         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4204         pSMB->DataCount = 0;
4205         pSMB->DataOffset = 0;
4206         pSMB->SetupCount = 1;
4207         pSMB->Reserved3 = 0;
4208         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4209         byte_count = params + 1 /* pad */ ;
4210         pSMB->TotalParameterCount = cpu_to_le16(params);
4211         pSMB->ParameterCount = pSMB->TotalParameterCount;
4212         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4213         pSMB->Reserved4 = 0;
4214         inc_rfc1001_len(pSMB, byte_count);
4215         pSMB->ByteCount = cpu_to_le16(byte_count);
4216
4217         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4218                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4219         if (rc) {
4220                 cFYI(1, "Send error in QPathInfo = %d", rc);
4221         } else {                /* decode response */
4222                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4223
4224                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4225                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4226                                    "Unix Extensions can be disabled on mount "
4227                                    "by specifying the nosfu mount option.");
4228                         rc = -EIO;      /* bad smb */
4229                 } else {
4230                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4231                         memcpy((char *) pFindData,
4232                                (char *) &pSMBr->hdr.Protocol +
4233                                data_offset,
4234                                sizeof(FILE_UNIX_BASIC_INFO));
4235                 }
4236         }
4237         cifs_buf_release(pSMB);
4238         if (rc == -EAGAIN)
4239                 goto UnixQPathInfoRetry;
4240
4241         return rc;
4242 }
4243
4244 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4245 int
4246 CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4247               const char *searchName,
4248               const struct nls_table *nls_codepage,
4249               __u16 *pnetfid, __u16 search_flags,
4250               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4251 {
4252 /* level 257 SMB_ */
4253         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4254         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4255         T2_FFIRST_RSP_PARMS *parms;
4256         int rc = 0;
4257         int bytes_returned = 0;
4258         int name_len;
4259         __u16 params, byte_count;
4260
4261         cFYI(1, "In FindFirst for %s", searchName);
4262
4263 findFirstRetry:
4264         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4265                       (void **) &pSMBr);
4266         if (rc)
4267                 return rc;
4268
4269         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4270                 name_len =
4271                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4272                                        PATH_MAX, nls_codepage, remap);
4273                 /* We can not add the asterik earlier in case
4274                 it got remapped to 0xF03A as if it were part of the
4275                 directory name instead of a wildcard */
4276                 name_len *= 2;
4277                 pSMB->FileName[name_len] = dirsep;
4278                 pSMB->FileName[name_len+1] = 0;
4279                 pSMB->FileName[name_len+2] = '*';
4280                 pSMB->FileName[name_len+3] = 0;
4281                 name_len += 4; /* now the trailing null */
4282                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4283                 pSMB->FileName[name_len+1] = 0;
4284                 name_len += 2;
4285         } else {        /* BB add check for overrun of SMB buf BB */
4286                 name_len = strnlen(searchName, PATH_MAX);
4287 /* BB fix here and in unicode clause above ie
4288                 if (name_len > buffersize-header)
4289                         free buffer exit; BB */
4290                 strncpy(pSMB->FileName, searchName, name_len);
4291                 pSMB->FileName[name_len] = dirsep;
4292                 pSMB->FileName[name_len+1] = '*';
4293                 pSMB->FileName[name_len+2] = 0;
4294                 name_len += 3;
4295         }
4296
4297         params = 12 + name_len /* includes null */ ;
4298         pSMB->TotalDataCount = 0;       /* no EAs */
4299         pSMB->MaxParameterCount = cpu_to_le16(10);
4300         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4301         pSMB->MaxSetupCount = 0;
4302         pSMB->Reserved = 0;
4303         pSMB->Flags = 0;
4304         pSMB->Timeout = 0;
4305         pSMB->Reserved2 = 0;
4306         byte_count = params + 1 /* pad */ ;
4307         pSMB->TotalParameterCount = cpu_to_le16(params);
4308         pSMB->ParameterCount = pSMB->TotalParameterCount;
4309         pSMB->ParameterOffset = cpu_to_le16(
4310               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4311                 - 4);
4312         pSMB->DataCount = 0;
4313         pSMB->DataOffset = 0;
4314         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4315         pSMB->Reserved3 = 0;
4316         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4317         pSMB->SearchAttributes =
4318             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4319                         ATTR_DIRECTORY);
4320         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4321         pSMB->SearchFlags = cpu_to_le16(search_flags);
4322         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4323
4324         /* BB what should we set StorageType to? Does it matter? BB */
4325         pSMB->SearchStorageType = 0;
4326         inc_rfc1001_len(pSMB, byte_count);
4327         pSMB->ByteCount = cpu_to_le16(byte_count);
4328
4329         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4330                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4331         cifs_stats_inc(&tcon->num_ffirst);
4332
4333         if (rc) {/* BB add logic to retry regular search if Unix search
4334                         rejected unexpectedly by server */
4335                 /* BB Add code to handle unsupported level rc */
4336                 cFYI(1, "Error in FindFirst = %d", rc);
4337
4338                 cifs_buf_release(pSMB);
4339
4340                 /* BB eventually could optimize out free and realloc of buf */
4341                 /*    for this case */
4342                 if (rc == -EAGAIN)
4343                         goto findFirstRetry;
4344         } else { /* decode response */
4345                 /* BB remember to free buffer if error BB */
4346                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4347                 if (rc == 0) {
4348                         unsigned int lnoff;
4349
4350                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4351                                 psrch_inf->unicode = true;
4352                         else
4353                                 psrch_inf->unicode = false;
4354
4355                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4356                         psrch_inf->smallBuf = 0;
4357                         psrch_inf->srch_entries_start =
4358                                 (char *) &pSMBr->hdr.Protocol +
4359                                         le16_to_cpu(pSMBr->t2.DataOffset);
4360                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4361                                le16_to_cpu(pSMBr->t2.ParameterOffset));
4362
4363                         if (parms->EndofSearch)
4364                                 psrch_inf->endOfSearch = true;
4365                         else
4366                                 psrch_inf->endOfSearch = false;
4367
4368                         psrch_inf->entries_in_buffer =
4369                                         le16_to_cpu(parms->SearchCount);
4370                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4371                                 psrch_inf->entries_in_buffer;
4372                         lnoff = le16_to_cpu(parms->LastNameOffset);
4373                         if (CIFSMaxBufSize < lnoff) {
4374                                 cERROR(1, "ignoring corrupt resume name");
4375                                 psrch_inf->last_entry = NULL;
4376                                 return rc;
4377                         }
4378
4379                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
4380                                                         lnoff;
4381
4382                         *pnetfid = parms->SearchHandle;
4383                 } else {
4384                         cifs_buf_release(pSMB);
4385                 }
4386         }
4387
4388         return rc;
4389 }
4390
4391 int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
4392                  __u16 search_flags, struct cifs_search_info *psrch_inf)
4393 {
4394         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4395         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4396         T2_FNEXT_RSP_PARMS *parms;
4397         char *response_data;
4398         int rc = 0;
4399         int bytes_returned;
4400         unsigned int name_len;
4401         __u16 params, byte_count;
4402
4403         cFYI(1, "In FindNext");
4404
4405         if (psrch_inf->endOfSearch)
4406                 return -ENOENT;
4407
4408         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4409                 (void **) &pSMBr);
4410         if (rc)
4411                 return rc;
4412
4413         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4414         byte_count = 0;
4415         pSMB->TotalDataCount = 0;       /* no EAs */
4416         pSMB->MaxParameterCount = cpu_to_le16(8);
4417         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4418         pSMB->MaxSetupCount = 0;
4419         pSMB->Reserved = 0;
4420         pSMB->Flags = 0;
4421         pSMB->Timeout = 0;
4422         pSMB->Reserved2 = 0;
4423         pSMB->ParameterOffset =  cpu_to_le16(
4424               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4425         pSMB->DataCount = 0;
4426         pSMB->DataOffset = 0;
4427         pSMB->SetupCount = 1;
4428         pSMB->Reserved3 = 0;
4429         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4430         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4431         pSMB->SearchCount =
4432                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4433         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4434         pSMB->ResumeKey = psrch_inf->resume_key;
4435         pSMB->SearchFlags = cpu_to_le16(search_flags);
4436
4437         name_len = psrch_inf->resume_name_len;
4438         params += name_len;
4439         if (name_len < PATH_MAX) {
4440                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4441                 byte_count += name_len;
4442                 /* 14 byte parm len above enough for 2 byte null terminator */
4443                 pSMB->ResumeFileName[name_len] = 0;
4444                 pSMB->ResumeFileName[name_len+1] = 0;
4445         } else {
4446                 rc = -EINVAL;
4447                 goto FNext2_err_exit;
4448         }
4449         byte_count = params + 1 /* pad */ ;
4450         pSMB->TotalParameterCount = cpu_to_le16(params);
4451         pSMB->ParameterCount = pSMB->TotalParameterCount;
4452         inc_rfc1001_len(pSMB, byte_count);
4453         pSMB->ByteCount = cpu_to_le16(byte_count);
4454
4455         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4456                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4457         cifs_stats_inc(&tcon->num_fnext);
4458         if (rc) {
4459                 if (rc == -EBADF) {
4460                         psrch_inf->endOfSearch = true;
4461                         cifs_buf_release(pSMB);
4462                         rc = 0; /* search probably was closed at end of search*/
4463                 } else
4464                         cFYI(1, "FindNext returned = %d", rc);
4465         } else {                /* decode response */
4466                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4467
4468                 if (rc == 0) {
4469                         unsigned int lnoff;
4470
4471                         /* BB fixme add lock for file (srch_info) struct here */
4472                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4473                                 psrch_inf->unicode = true;
4474                         else
4475                                 psrch_inf->unicode = false;
4476                         response_data = (char *) &pSMBr->hdr.Protocol +
4477                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4478                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4479                         response_data = (char *)&pSMBr->hdr.Protocol +
4480                                 le16_to_cpu(pSMBr->t2.DataOffset);
4481                         if (psrch_inf->smallBuf)
4482                                 cifs_small_buf_release(
4483                                         psrch_inf->ntwrk_buf_start);
4484                         else
4485                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4486                         psrch_inf->srch_entries_start = response_data;
4487                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4488                         psrch_inf->smallBuf = 0;
4489                         if (parms->EndofSearch)
4490                                 psrch_inf->endOfSearch = true;
4491                         else
4492                                 psrch_inf->endOfSearch = false;
4493                         psrch_inf->entries_in_buffer =
4494                                                 le16_to_cpu(parms->SearchCount);
4495                         psrch_inf->index_of_last_entry +=
4496                                 psrch_inf->entries_in_buffer;
4497                         lnoff = le16_to_cpu(parms->LastNameOffset);
4498                         if (CIFSMaxBufSize < lnoff) {
4499                                 cERROR(1, "ignoring corrupt resume name");
4500                                 psrch_inf->last_entry = NULL;
4501                                 return rc;
4502                         } else
4503                                 psrch_inf->last_entry =
4504                                         psrch_inf->srch_entries_start + lnoff;
4505
4506 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4507             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4508
4509                         /* BB fixme add unlock here */
4510                 }
4511
4512         }
4513
4514         /* BB On error, should we leave previous search buf (and count and
4515         last entry fields) intact or free the previous one? */
4516
4517         /* Note: On -EAGAIN error only caller can retry on handle based calls
4518         since file handle passed in no longer valid */
4519 FNext2_err_exit:
4520         if (rc != 0)
4521                 cifs_buf_release(pSMB);
4522         return rc;
4523 }
4524
4525 int
4526 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4527               const __u16 searchHandle)
4528 {
4529         int rc = 0;
4530         FINDCLOSE_REQ *pSMB = NULL;
4531
4532         cFYI(1, "In CIFSSMBFindClose");
4533         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4534
4535         /* no sense returning error if session restarted
4536                 as file handle has been closed */
4537         if (rc == -EAGAIN)
4538                 return 0;
4539         if (rc)
4540                 return rc;
4541
4542         pSMB->FileID = searchHandle;
4543         pSMB->ByteCount = 0;
4544         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4545         if (rc)
4546                 cERROR(1, "Send error in FindClose = %d", rc);
4547
4548         cifs_stats_inc(&tcon->num_fclose);
4549
4550         /* Since session is dead, search handle closed on server already */
4551         if (rc == -EAGAIN)
4552                 rc = 0;
4553
4554         return rc;
4555 }
4556
4557 int
4558 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4559                       const unsigned char *searchName,
4560                       __u64 *inode_number,
4561                       const struct nls_table *nls_codepage, int remap)
4562 {
4563         int rc = 0;
4564         TRANSACTION2_QPI_REQ *pSMB = NULL;
4565         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4566         int name_len, bytes_returned;
4567         __u16 params, byte_count;
4568
4569         cFYI(1, "In GetSrvInodeNum for %s", searchName);
4570         if (tcon == NULL)
4571                 return -ENODEV;
4572
4573 GetInodeNumberRetry:
4574         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4575                       (void **) &pSMBr);
4576         if (rc)
4577                 return rc;
4578
4579         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4580                 name_len =
4581                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
4582                                            searchName, PATH_MAX, nls_codepage,
4583                                            remap);
4584                 name_len++;     /* trailing null */
4585                 name_len *= 2;
4586         } else {        /* BB improve the check for buffer overruns BB */
4587                 name_len = strnlen(searchName, PATH_MAX);
4588                 name_len++;     /* trailing null */
4589                 strncpy(pSMB->FileName, searchName, name_len);
4590         }
4591
4592         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4593         pSMB->TotalDataCount = 0;
4594         pSMB->MaxParameterCount = cpu_to_le16(2);
4595         /* BB find exact max data count below from sess structure BB */
4596         pSMB->MaxDataCount = cpu_to_le16(4000);
4597         pSMB->MaxSetupCount = 0;
4598         pSMB->Reserved = 0;
4599         pSMB->Flags = 0;
4600         pSMB->Timeout = 0;
4601         pSMB->Reserved2 = 0;
4602         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4603                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4604         pSMB->DataCount = 0;
4605         pSMB->DataOffset = 0;
4606         pSMB->SetupCount = 1;
4607         pSMB->Reserved3 = 0;
4608         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4609         byte_count = params + 1 /* pad */ ;
4610         pSMB->TotalParameterCount = cpu_to_le16(params);
4611         pSMB->ParameterCount = pSMB->TotalParameterCount;
4612         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4613         pSMB->Reserved4 = 0;
4614         inc_rfc1001_len(pSMB, byte_count);
4615         pSMB->ByteCount = cpu_to_le16(byte_count);
4616
4617         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4618                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4619         if (rc) {
4620                 cFYI(1, "error %d in QueryInternalInfo", rc);
4621         } else {
4622                 /* decode response */
4623                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4624                 /* BB also check enough total bytes returned */
4625                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4626                         /* If rc should we check for EOPNOSUPP and
4627                         disable the srvino flag? or in caller? */
4628                         rc = -EIO;      /* bad smb */
4629                 else {
4630                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4631                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4632                         struct file_internal_info *pfinfo;
4633                         /* BB Do we need a cast or hash here ? */
4634                         if (count < 8) {
4635                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4636                                 rc = -EIO;
4637                                 goto GetInodeNumOut;
4638                         }
4639                         pfinfo = (struct file_internal_info *)
4640                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4641                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4642                 }
4643         }
4644 GetInodeNumOut:
4645         cifs_buf_release(pSMB);
4646         if (rc == -EAGAIN)
4647                 goto GetInodeNumberRetry;
4648         return rc;
4649 }
4650
4651 /* parses DFS refferal V3 structure
4652  * caller is responsible for freeing target_nodes
4653  * returns:
4654  *      on success - 0
4655  *      on failure - errno
4656  */
4657 static int
4658 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4659                 unsigned int *num_of_nodes,
4660                 struct dfs_info3_param **target_nodes,
4661                 const struct nls_table *nls_codepage, int remap,
4662                 const char *searchName)
4663 {
4664         int i, rc = 0;
4665         char *data_end;
4666         bool is_unicode;
4667         struct dfs_referral_level_3 *ref;
4668
4669         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4670                 is_unicode = true;
4671         else
4672                 is_unicode = false;
4673         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4674
4675         if (*num_of_nodes < 1) {
4676                 cERROR(1, "num_referrals: must be at least > 0,"
4677                         "but we get num_referrals = %d", *num_of_nodes);
4678                 rc = -EINVAL;
4679                 goto parse_DFS_referrals_exit;
4680         }
4681
4682         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4683         if (ref->VersionNumber != cpu_to_le16(3)) {
4684                 cERROR(1, "Referrals of V%d version are not supported,"
4685                         "should be V3", le16_to_cpu(ref->VersionNumber));
4686                 rc = -EINVAL;
4687                 goto parse_DFS_referrals_exit;
4688         }
4689
4690         /* get the upper boundary of the resp buffer */
4691         data_end = (char *)(&(pSMBr->PathConsumed)) +
4692                                 le16_to_cpu(pSMBr->t2.DataCount);
4693
4694         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4695                         *num_of_nodes,
4696                         le32_to_cpu(pSMBr->DFSFlags));
4697
4698         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4699                         *num_of_nodes, GFP_KERNEL);
4700         if (*target_nodes == NULL) {
4701                 cERROR(1, "Failed to allocate buffer for target_nodes");
4702                 rc = -ENOMEM;
4703                 goto parse_DFS_referrals_exit;
4704         }
4705
4706         /* collect necessary data from referrals */
4707         for (i = 0; i < *num_of_nodes; i++) {
4708                 char *temp;
4709                 int max_len;
4710                 struct dfs_info3_param *node = (*target_nodes)+i;
4711
4712                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4713                 if (is_unicode) {
4714                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4715                                                 GFP_KERNEL);
4716                         if (tmp == NULL) {
4717                                 rc = -ENOMEM;
4718                                 goto parse_DFS_referrals_exit;
4719                         }
4720                         cifsConvertToUTF16((__le16 *) tmp, searchName,
4721                                            PATH_MAX, nls_codepage, remap);
4722                         node->path_consumed = cifs_utf16_bytes(tmp,
4723                                         le16_to_cpu(pSMBr->PathConsumed),
4724                                         nls_codepage);
4725                         kfree(tmp);
4726                 } else
4727                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4728
4729                 node->server_type = le16_to_cpu(ref->ServerType);
4730                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4731
4732                 /* copy DfsPath */
4733                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4734                 max_len = data_end - temp;
4735                 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4736                                                 is_unicode, nls_codepage);
4737                 if (!node->path_name) {
4738                         rc = -ENOMEM;
4739                         goto parse_DFS_referrals_exit;
4740                 }
4741
4742                 /* copy link target UNC */
4743                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4744                 max_len = data_end - temp;
4745                 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4746                                                 is_unicode, nls_codepage);
4747                 if (!node->node_name) {
4748                         rc = -ENOMEM;
4749                         goto parse_DFS_referrals_exit;
4750                 }
4751
4752                 ref++;
4753         }
4754
4755 parse_DFS_referrals_exit:
4756         if (rc) {
4757                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4758                 *target_nodes = NULL;
4759                 *num_of_nodes = 0;
4760         }
4761         return rc;
4762 }
4763
4764 int
4765 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4766                 const unsigned char *searchName,
4767                 struct dfs_info3_param **target_nodes,
4768                 unsigned int *num_of_nodes,
4769                 const struct nls_table *nls_codepage, int remap)
4770 {
4771 /* TRANS2_GET_DFS_REFERRAL */
4772         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4773         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4774         int rc = 0;
4775         int bytes_returned;
4776         int name_len;
4777         __u16 params, byte_count;
4778         *num_of_nodes = 0;
4779         *target_nodes = NULL;
4780
4781         cFYI(1, "In GetDFSRefer the path %s", searchName);
4782         if (ses == NULL)
4783                 return -ENODEV;
4784 getDFSRetry:
4785         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4786                       (void **) &pSMBr);
4787         if (rc)
4788                 return rc;
4789
4790         /* server pointer checked in called function,
4791         but should never be null here anyway */
4792         pSMB->hdr.Mid = get_next_mid(ses->server);
4793         pSMB->hdr.Tid = ses->ipc_tid;
4794         pSMB->hdr.Uid = ses->Suid;
4795         if (ses->capabilities & CAP_STATUS32)
4796                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4797         if (ses->capabilities & CAP_DFS)
4798                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4799
4800         if (ses->capabilities & CAP_UNICODE) {
4801                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4802                 name_len =
4803                     cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4804                                        searchName, PATH_MAX, nls_codepage,
4805                                        remap);
4806                 name_len++;     /* trailing null */
4807                 name_len *= 2;
4808         } else {        /* BB improve the check for buffer overruns BB */
4809                 name_len = strnlen(searchName, PATH_MAX);
4810                 name_len++;     /* trailing null */
4811                 strncpy(pSMB->RequestFileName, searchName, name_len);
4812         }
4813
4814         if (ses->server) {
4815                 if (ses->server->sec_mode &
4816                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4817                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4818         }
4819
4820         pSMB->hdr.Uid = ses->Suid;
4821
4822         params = 2 /* level */  + name_len /*includes null */ ;
4823         pSMB->TotalDataCount = 0;
4824         pSMB->DataCount = 0;
4825         pSMB->DataOffset = 0;
4826         pSMB->MaxParameterCount = 0;
4827         /* BB find exact max SMB PDU from sess structure BB */
4828         pSMB->MaxDataCount = cpu_to_le16(4000);
4829         pSMB->MaxSetupCount = 0;
4830         pSMB->Reserved = 0;
4831         pSMB->Flags = 0;
4832         pSMB->Timeout = 0;
4833         pSMB->Reserved2 = 0;
4834         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4835           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4836         pSMB->SetupCount = 1;
4837         pSMB->Reserved3 = 0;
4838         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4839         byte_count = params + 3 /* pad */ ;
4840         pSMB->ParameterCount = cpu_to_le16(params);
4841         pSMB->TotalParameterCount = pSMB->ParameterCount;
4842         pSMB->MaxReferralLevel = cpu_to_le16(3);
4843         inc_rfc1001_len(pSMB, byte_count);
4844         pSMB->ByteCount = cpu_to_le16(byte_count);
4845
4846         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4847                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4848         if (rc) {
4849                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4850                 goto GetDFSRefExit;
4851         }
4852         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4853
4854         /* BB Also check if enough total bytes returned? */
4855         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4856                 rc = -EIO;      /* bad smb */
4857                 goto GetDFSRefExit;
4858         }
4859
4860         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4861                                 get_bcc(&pSMBr->hdr),
4862                                 le16_to_cpu(pSMBr->t2.DataOffset));
4863
4864         /* parse returned result into more usable form */
4865         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4866                                  target_nodes, nls_codepage, remap,
4867                                  searchName);
4868
4869 GetDFSRefExit:
4870         cifs_buf_release(pSMB);
4871
4872         if (rc == -EAGAIN)
4873                 goto getDFSRetry;
4874
4875         return rc;
4876 }
4877
4878 /* Query File System Info such as free space to old servers such as Win 9x */
4879 int
4880 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4881 {
4882 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4883         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4884         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4885         FILE_SYSTEM_ALLOC_INFO *response_data;
4886         int rc = 0;
4887         int bytes_returned = 0;
4888         __u16 params, byte_count;
4889
4890         cFYI(1, "OldQFSInfo");
4891 oldQFSInfoRetry:
4892         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4893                 (void **) &pSMBr);
4894         if (rc)
4895                 return rc;
4896
4897         params = 2;     /* level */
4898         pSMB->TotalDataCount = 0;
4899         pSMB->MaxParameterCount = cpu_to_le16(2);
4900         pSMB->MaxDataCount = cpu_to_le16(1000);
4901         pSMB->MaxSetupCount = 0;
4902         pSMB->Reserved = 0;
4903         pSMB->Flags = 0;
4904         pSMB->Timeout = 0;
4905         pSMB->Reserved2 = 0;
4906         byte_count = params + 1 /* pad */ ;
4907         pSMB->TotalParameterCount = cpu_to_le16(params);
4908         pSMB->ParameterCount = pSMB->TotalParameterCount;
4909         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4910         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4911         pSMB->DataCount = 0;
4912         pSMB->DataOffset = 0;
4913         pSMB->SetupCount = 1;
4914         pSMB->Reserved3 = 0;
4915         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4916         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4917         inc_rfc1001_len(pSMB, byte_count);
4918         pSMB->ByteCount = cpu_to_le16(byte_count);
4919
4920         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4921                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4922         if (rc) {
4923                 cFYI(1, "Send error in QFSInfo = %d", rc);
4924         } else {                /* decode response */
4925                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4926
4927                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4928                         rc = -EIO;      /* bad smb */
4929                 else {
4930                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4931                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4932                                  get_bcc(&pSMBr->hdr), data_offset);
4933
4934                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4935                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4936                         FSData->f_bsize =
4937                                 le16_to_cpu(response_data->BytesPerSector) *
4938                                 le32_to_cpu(response_data->
4939                                         SectorsPerAllocationUnit);
4940                         FSData->f_blocks =
4941                                le32_to_cpu(response_data->TotalAllocationUnits);
4942                         FSData->f_bfree = FSData->f_bavail =
4943                                 le32_to_cpu(response_data->FreeAllocationUnits);
4944                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4945                              (unsigned long long)FSData->f_blocks,
4946                              (unsigned long long)FSData->f_bfree,
4947                              FSData->f_bsize);
4948                 }
4949         }
4950         cifs_buf_release(pSMB);
4951
4952         if (rc == -EAGAIN)
4953                 goto oldQFSInfoRetry;
4954
4955         return rc;
4956 }
4957
4958 int
4959 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4960 {
4961 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4962         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4963         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4964         FILE_SYSTEM_INFO *response_data;
4965         int rc = 0;
4966         int bytes_returned = 0;
4967         __u16 params, byte_count;
4968
4969         cFYI(1, "In QFSInfo");
4970 QFSInfoRetry:
4971         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4972                       (void **) &pSMBr);
4973         if (rc)
4974                 return rc;
4975
4976         params = 2;     /* level */
4977         pSMB->TotalDataCount = 0;
4978         pSMB->MaxParameterCount = cpu_to_le16(2);
4979         pSMB->MaxDataCount = cpu_to_le16(1000);
4980         pSMB->MaxSetupCount = 0;
4981         pSMB->Reserved = 0;
4982         pSMB->Flags = 0;
4983         pSMB->Timeout = 0;
4984         pSMB->Reserved2 = 0;
4985         byte_count = params + 1 /* pad */ ;
4986         pSMB->TotalParameterCount = cpu_to_le16(params);
4987         pSMB->ParameterCount = pSMB->TotalParameterCount;
4988         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4989                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4990         pSMB->DataCount = 0;
4991         pSMB->DataOffset = 0;
4992         pSMB->SetupCount = 1;
4993         pSMB->Reserved3 = 0;
4994         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4995         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4996         inc_rfc1001_len(pSMB, byte_count);
4997         pSMB->ByteCount = cpu_to_le16(byte_count);
4998
4999         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5000                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5001         if (rc) {
5002                 cFYI(1, "Send error in QFSInfo = %d", rc);
5003         } else {                /* decode response */
5004                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5005
5006                 if (rc || get_bcc(&pSMBr->hdr) < 24)
5007                         rc = -EIO;      /* bad smb */
5008                 else {
5009                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5010
5011                         response_data =
5012                             (FILE_SYSTEM_INFO
5013                              *) (((char *) &pSMBr->hdr.Protocol) +
5014                                  data_offset);
5015                         FSData->f_bsize =
5016                             le32_to_cpu(response_data->BytesPerSector) *
5017                             le32_to_cpu(response_data->
5018                                         SectorsPerAllocationUnit);
5019                         FSData->f_blocks =
5020                             le64_to_cpu(response_data->TotalAllocationUnits);
5021                         FSData->f_bfree = FSData->f_bavail =
5022                             le64_to_cpu(response_data->FreeAllocationUnits);
5023                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5024                              (unsigned long long)FSData->f_blocks,
5025                              (unsigned long long)FSData->f_bfree,
5026                              FSData->f_bsize);
5027                 }
5028         }
5029         cifs_buf_release(pSMB);
5030
5031         if (rc == -EAGAIN)
5032                 goto QFSInfoRetry;
5033
5034         return rc;
5035 }
5036
5037 int
5038 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
5039 {
5040 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5041         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5042         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5043         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5044         int rc = 0;
5045         int bytes_returned = 0;
5046         __u16 params, byte_count;
5047
5048         cFYI(1, "In QFSAttributeInfo");
5049 QFSAttributeRetry:
5050         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5051                       (void **) &pSMBr);
5052         if (rc)
5053                 return rc;
5054
5055         params = 2;     /* level */
5056         pSMB->TotalDataCount = 0;
5057         pSMB->MaxParameterCount = cpu_to_le16(2);
5058         /* BB find exact max SMB PDU from sess structure BB */
5059         pSMB->MaxDataCount = cpu_to_le16(1000);
5060         pSMB->MaxSetupCount = 0;
5061         pSMB->Reserved = 0;
5062         pSMB->Flags = 0;
5063         pSMB->Timeout = 0;
5064         pSMB->Reserved2 = 0;
5065         byte_count = params + 1 /* pad */ ;
5066         pSMB->TotalParameterCount = cpu_to_le16(params);
5067         pSMB->ParameterCount = pSMB->TotalParameterCount;
5068         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5069                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5070         pSMB->DataCount = 0;
5071         pSMB->DataOffset = 0;
5072         pSMB->SetupCount = 1;
5073         pSMB->Reserved3 = 0;
5074         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5075         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5076         inc_rfc1001_len(pSMB, byte_count);
5077         pSMB->ByteCount = cpu_to_le16(byte_count);
5078
5079         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5080                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5081         if (rc) {
5082                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5083         } else {                /* decode response */
5084                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5085
5086                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5087                         /* BB also check if enough bytes returned */
5088                         rc = -EIO;      /* bad smb */
5089                 } else {
5090                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5091                         response_data =
5092                             (FILE_SYSTEM_ATTRIBUTE_INFO
5093                              *) (((char *) &pSMBr->hdr.Protocol) +
5094                                  data_offset);
5095                         memcpy(&tcon->fsAttrInfo, response_data,
5096                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5097                 }
5098         }
5099         cifs_buf_release(pSMB);
5100
5101         if (rc == -EAGAIN)
5102                 goto QFSAttributeRetry;
5103
5104         return rc;
5105 }
5106
5107 int
5108 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
5109 {
5110 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5111         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5112         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5113         FILE_SYSTEM_DEVICE_INFO *response_data;
5114         int rc = 0;
5115         int bytes_returned = 0;
5116         __u16 params, byte_count;
5117
5118         cFYI(1, "In QFSDeviceInfo");
5119 QFSDeviceRetry:
5120         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5121                       (void **) &pSMBr);
5122         if (rc)
5123                 return rc;
5124
5125         params = 2;     /* level */
5126         pSMB->TotalDataCount = 0;
5127         pSMB->MaxParameterCount = cpu_to_le16(2);
5128         /* BB find exact max SMB PDU from sess structure BB */
5129         pSMB->MaxDataCount = cpu_to_le16(1000);
5130         pSMB->MaxSetupCount = 0;
5131         pSMB->Reserved = 0;
5132         pSMB->Flags = 0;
5133         pSMB->Timeout = 0;
5134         pSMB->Reserved2 = 0;
5135         byte_count = params + 1 /* pad */ ;
5136         pSMB->TotalParameterCount = cpu_to_le16(params);
5137         pSMB->ParameterCount = pSMB->TotalParameterCount;
5138         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5139                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5140
5141         pSMB->DataCount = 0;
5142         pSMB->DataOffset = 0;
5143         pSMB->SetupCount = 1;
5144         pSMB->Reserved3 = 0;
5145         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5146         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5147         inc_rfc1001_len(pSMB, byte_count);
5148         pSMB->ByteCount = cpu_to_le16(byte_count);
5149
5150         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5151                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5152         if (rc) {
5153                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5154         } else {                /* decode response */
5155                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5156
5157                 if (rc || get_bcc(&pSMBr->hdr) <
5158                           sizeof(FILE_SYSTEM_DEVICE_INFO))
5159                         rc = -EIO;      /* bad smb */
5160                 else {
5161                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5162                         response_data =
5163                             (FILE_SYSTEM_DEVICE_INFO *)
5164                                 (((char *) &pSMBr->hdr.Protocol) +
5165                                  data_offset);
5166                         memcpy(&tcon->fsDevInfo, response_data,
5167                                sizeof(FILE_SYSTEM_DEVICE_INFO));
5168                 }
5169         }
5170         cifs_buf_release(pSMB);
5171
5172         if (rc == -EAGAIN)
5173                 goto QFSDeviceRetry;
5174
5175         return rc;
5176 }
5177
5178 int
5179 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
5180 {
5181 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5182         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5183         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5184         FILE_SYSTEM_UNIX_INFO *response_data;
5185         int rc = 0;
5186         int bytes_returned = 0;
5187         __u16 params, byte_count;
5188
5189         cFYI(1, "In QFSUnixInfo");
5190 QFSUnixRetry:
5191         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5192                                    (void **) &pSMB, (void **) &pSMBr);
5193         if (rc)
5194                 return rc;
5195
5196         params = 2;     /* level */
5197         pSMB->TotalDataCount = 0;
5198         pSMB->DataCount = 0;
5199         pSMB->DataOffset = 0;
5200         pSMB->MaxParameterCount = cpu_to_le16(2);
5201         /* BB find exact max SMB PDU from sess structure BB */
5202         pSMB->MaxDataCount = cpu_to_le16(100);
5203         pSMB->MaxSetupCount = 0;
5204         pSMB->Reserved = 0;
5205         pSMB->Flags = 0;
5206         pSMB->Timeout = 0;
5207         pSMB->Reserved2 = 0;
5208         byte_count = params + 1 /* pad */ ;
5209         pSMB->ParameterCount = cpu_to_le16(params);
5210         pSMB->TotalParameterCount = pSMB->ParameterCount;
5211         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5212                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5213         pSMB->SetupCount = 1;
5214         pSMB->Reserved3 = 0;
5215         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5216         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5217         inc_rfc1001_len(pSMB, byte_count);
5218         pSMB->ByteCount = cpu_to_le16(byte_count);
5219
5220         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5221                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5222         if (rc) {
5223                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5224         } else {                /* decode response */
5225                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5226
5227                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5228                         rc = -EIO;      /* bad smb */
5229                 } else {
5230                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5231                         response_data =
5232                             (FILE_SYSTEM_UNIX_INFO
5233                              *) (((char *) &pSMBr->hdr.Protocol) +
5234                                  data_offset);
5235                         memcpy(&tcon->fsUnixInfo, response_data,
5236                                sizeof(FILE_SYSTEM_UNIX_INFO));
5237                 }
5238         }
5239         cifs_buf_release(pSMB);
5240
5241         if (rc == -EAGAIN)
5242                 goto QFSUnixRetry;
5243
5244
5245         return rc;
5246 }
5247
5248 int
5249 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
5250 {
5251 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5252         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5253         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5254         int rc = 0;
5255         int bytes_returned = 0;
5256         __u16 params, param_offset, offset, byte_count;
5257
5258         cFYI(1, "In SETFSUnixInfo");
5259 SETFSUnixRetry:
5260         /* BB switch to small buf init to save memory */
5261         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5262                                         (void **) &pSMB, (void **) &pSMBr);
5263         if (rc)
5264                 return rc;
5265
5266         params = 4;     /* 2 bytes zero followed by info level. */
5267         pSMB->MaxSetupCount = 0;
5268         pSMB->Reserved = 0;
5269         pSMB->Flags = 0;
5270         pSMB->Timeout = 0;
5271         pSMB->Reserved2 = 0;
5272         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5273                                 - 4;
5274         offset = param_offset + params;
5275
5276         pSMB->MaxParameterCount = cpu_to_le16(4);
5277         /* BB find exact max SMB PDU from sess structure BB */
5278         pSMB->MaxDataCount = cpu_to_le16(100);
5279         pSMB->SetupCount = 1;
5280         pSMB->Reserved3 = 0;
5281         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5282         byte_count = 1 /* pad */ + params + 12;
5283
5284         pSMB->DataCount = cpu_to_le16(12);
5285         pSMB->ParameterCount = cpu_to_le16(params);
5286         pSMB->TotalDataCount = pSMB->DataCount;
5287         pSMB->TotalParameterCount = pSMB->ParameterCount;
5288         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5289         pSMB->DataOffset = cpu_to_le16(offset);
5290
5291         /* Params. */
5292         pSMB->FileNum = 0;
5293         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5294
5295         /* Data. */
5296         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5297         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5298         pSMB->ClientUnixCap = cpu_to_le64(cap);
5299
5300         inc_rfc1001_len(pSMB, byte_count);
5301         pSMB->ByteCount = cpu_to_le16(byte_count);
5302
5303         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5304                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5305         if (rc) {
5306                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5307         } else {                /* decode response */
5308                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5309                 if (rc)
5310                         rc = -EIO;      /* bad smb */
5311         }
5312         cifs_buf_release(pSMB);
5313
5314         if (rc == -EAGAIN)
5315                 goto SETFSUnixRetry;
5316
5317         return rc;
5318 }
5319
5320
5321
5322 int
5323 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5324                    struct kstatfs *FSData)
5325 {
5326 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5327         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5328         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5329         FILE_SYSTEM_POSIX_INFO *response_data;
5330         int rc = 0;
5331         int bytes_returned = 0;
5332         __u16 params, byte_count;
5333
5334         cFYI(1, "In QFSPosixInfo");
5335 QFSPosixRetry:
5336         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5337                       (void **) &pSMBr);
5338         if (rc)
5339                 return rc;
5340
5341         params = 2;     /* level */
5342         pSMB->TotalDataCount = 0;
5343         pSMB->DataCount = 0;
5344         pSMB->DataOffset = 0;
5345         pSMB->MaxParameterCount = cpu_to_le16(2);
5346         /* BB find exact max SMB PDU from sess structure BB */
5347         pSMB->MaxDataCount = cpu_to_le16(100);
5348         pSMB->MaxSetupCount = 0;
5349         pSMB->Reserved = 0;
5350         pSMB->Flags = 0;
5351         pSMB->Timeout = 0;
5352         pSMB->Reserved2 = 0;
5353         byte_count = params + 1 /* pad */ ;
5354         pSMB->ParameterCount = cpu_to_le16(params);
5355         pSMB->TotalParameterCount = pSMB->ParameterCount;
5356         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5357                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5358         pSMB->SetupCount = 1;
5359         pSMB->Reserved3 = 0;
5360         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5361         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5362         inc_rfc1001_len(pSMB, byte_count);
5363         pSMB->ByteCount = cpu_to_le16(byte_count);
5364
5365         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5366                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5367         if (rc) {
5368                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5369         } else {                /* decode response */
5370                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5371
5372                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5373                         rc = -EIO;      /* bad smb */
5374                 } else {
5375                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5376                         response_data =
5377                             (FILE_SYSTEM_POSIX_INFO
5378                              *) (((char *) &pSMBr->hdr.Protocol) +
5379                                  data_offset);
5380                         FSData->f_bsize =
5381                                         le32_to_cpu(response_data->BlockSize);
5382                         FSData->f_blocks =
5383                                         le64_to_cpu(response_data->TotalBlocks);
5384                         FSData->f_bfree =
5385                             le64_to_cpu(response_data->BlocksAvail);
5386                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5387                                 FSData->f_bavail = FSData->f_bfree;
5388                         } else {
5389                                 FSData->f_bavail =
5390                                     le64_to_cpu(response_data->UserBlocksAvail);
5391                         }
5392                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5393                                 FSData->f_files =
5394                                      le64_to_cpu(response_data->TotalFileNodes);
5395                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5396                                 FSData->f_ffree =
5397                                       le64_to_cpu(response_data->FreeFileNodes);
5398                 }
5399         }
5400         cifs_buf_release(pSMB);
5401
5402         if (rc == -EAGAIN)
5403                 goto QFSPosixRetry;
5404
5405         return rc;
5406 }
5407
5408
5409 /* We can not use write of zero bytes trick to
5410    set file size due to need for large file support.  Also note that
5411    this SetPathInfo is preferred to SetFileInfo based method in next
5412    routine which is only needed to work around a sharing violation bug
5413    in Samba which this routine can run into */
5414
5415 int
5416 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5417               __u64 size, bool SetAllocation,
5418               const struct nls_table *nls_codepage, int remap)
5419 {
5420         struct smb_com_transaction2_spi_req *pSMB = NULL;
5421         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5422         struct file_end_of_file_info *parm_data;
5423         int name_len;
5424         int rc = 0;
5425         int bytes_returned = 0;
5426         __u16 params, byte_count, data_count, param_offset, offset;
5427
5428         cFYI(1, "In SetEOF");
5429 SetEOFRetry:
5430         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5431                       (void **) &pSMBr);
5432         if (rc)
5433                 return rc;
5434
5435         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5436                 name_len =
5437                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5438                                        PATH_MAX, nls_codepage, remap);
5439                 name_len++;     /* trailing null */
5440                 name_len *= 2;
5441         } else {        /* BB improve the check for buffer overruns BB */
5442                 name_len = strnlen(fileName, PATH_MAX);
5443                 name_len++;     /* trailing null */
5444                 strncpy(pSMB->FileName, fileName, name_len);
5445         }
5446         params = 6 + name_len;
5447         data_count = sizeof(struct file_end_of_file_info);
5448         pSMB->MaxParameterCount = cpu_to_le16(2);
5449         pSMB->MaxDataCount = cpu_to_le16(4100);
5450         pSMB->MaxSetupCount = 0;
5451         pSMB->Reserved = 0;
5452         pSMB->Flags = 0;
5453         pSMB->Timeout = 0;
5454         pSMB->Reserved2 = 0;
5455         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5456                                 InformationLevel) - 4;
5457         offset = param_offset + params;
5458         if (SetAllocation) {
5459                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5460                         pSMB->InformationLevel =
5461                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5462                 else
5463                         pSMB->InformationLevel =
5464                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5465         } else /* Set File Size */  {
5466             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5467                     pSMB->InformationLevel =
5468                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5469             else
5470                     pSMB->InformationLevel =
5471                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5472         }
5473
5474         parm_data =
5475             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5476                                        offset);
5477         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5478         pSMB->DataOffset = cpu_to_le16(offset);
5479         pSMB->SetupCount = 1;
5480         pSMB->Reserved3 = 0;
5481         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5482         byte_count = 3 /* pad */  + params + data_count;
5483         pSMB->DataCount = cpu_to_le16(data_count);
5484         pSMB->TotalDataCount = pSMB->DataCount;
5485         pSMB->ParameterCount = cpu_to_le16(params);
5486         pSMB->TotalParameterCount = pSMB->ParameterCount;
5487         pSMB->Reserved4 = 0;
5488         inc_rfc1001_len(pSMB, byte_count);
5489         parm_data->FileSize = cpu_to_le64(size);
5490         pSMB->ByteCount = cpu_to_le16(byte_count);
5491         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5492                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5493         if (rc)
5494                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5495
5496         cifs_buf_release(pSMB);
5497
5498         if (rc == -EAGAIN)
5499                 goto SetEOFRetry;
5500
5501         return rc;
5502 }
5503
5504 int
5505 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5506                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5507 {
5508         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5509         struct file_end_of_file_info *parm_data;
5510         int rc = 0;
5511         __u16 params, param_offset, offset, byte_count, count;
5512
5513         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5514                         (long long)size);
5515         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5516
5517         if (rc)
5518                 return rc;
5519
5520         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5521         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5522
5523         params = 6;
5524         pSMB->MaxSetupCount = 0;
5525         pSMB->Reserved = 0;
5526         pSMB->Flags = 0;
5527         pSMB->Timeout = 0;
5528         pSMB->Reserved2 = 0;
5529         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5530         offset = param_offset + params;
5531
5532         count = sizeof(struct file_end_of_file_info);
5533         pSMB->MaxParameterCount = cpu_to_le16(2);
5534         /* BB find exact max SMB PDU from sess structure BB */
5535         pSMB->MaxDataCount = cpu_to_le16(1000);
5536         pSMB->SetupCount = 1;
5537         pSMB->Reserved3 = 0;
5538         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5539         byte_count = 3 /* pad */  + params + count;
5540         pSMB->DataCount = cpu_to_le16(count);
5541         pSMB->ParameterCount = cpu_to_le16(params);
5542         pSMB->TotalDataCount = pSMB->DataCount;
5543         pSMB->TotalParameterCount = pSMB->ParameterCount;
5544         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5545         parm_data =
5546                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5547                                 + offset);
5548         pSMB->DataOffset = cpu_to_le16(offset);
5549         parm_data->FileSize = cpu_to_le64(size);
5550         pSMB->Fid = fid;
5551         if (SetAllocation) {
5552                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5553                         pSMB->InformationLevel =
5554                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5555                 else
5556                         pSMB->InformationLevel =
5557                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5558         } else /* Set File Size */  {
5559             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5560                     pSMB->InformationLevel =
5561                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5562             else
5563                     pSMB->InformationLevel =
5564                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5565         }
5566         pSMB->Reserved4 = 0;
5567         inc_rfc1001_len(pSMB, byte_count);
5568         pSMB->ByteCount = cpu_to_le16(byte_count);
5569         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5570         if (rc) {
5571                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5572         }
5573
5574         /* Note: On -EAGAIN error only caller can retry on handle based calls
5575                 since file handle passed in no longer valid */
5576
5577         return rc;
5578 }
5579
5580 /* Some legacy servers such as NT4 require that the file times be set on
5581    an open handle, rather than by pathname - this is awkward due to
5582    potential access conflicts on the open, but it is unavoidable for these
5583    old servers since the only other choice is to go from 100 nanosecond DCE
5584    time and resort to the original setpathinfo level which takes the ancient
5585    DOS time format with 2 second granularity */
5586 int
5587 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5588                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5589 {
5590         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5591         char *data_offset;
5592         int rc = 0;
5593         __u16 params, param_offset, offset, byte_count, count;
5594
5595         cFYI(1, "Set Times (via SetFileInfo)");
5596         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5597
5598         if (rc)
5599                 return rc;
5600
5601         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5602         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5603
5604         params = 6;
5605         pSMB->MaxSetupCount = 0;
5606         pSMB->Reserved = 0;
5607         pSMB->Flags = 0;
5608         pSMB->Timeout = 0;
5609         pSMB->Reserved2 = 0;
5610         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5611         offset = param_offset + params;
5612
5613         data_offset = (char *)pSMB +
5614                         offsetof(struct smb_hdr, Protocol) + offset;
5615
5616         count = sizeof(FILE_BASIC_INFO);
5617         pSMB->MaxParameterCount = cpu_to_le16(2);
5618         /* BB find max SMB PDU from sess */
5619         pSMB->MaxDataCount = cpu_to_le16(1000);
5620         pSMB->SetupCount = 1;
5621         pSMB->Reserved3 = 0;
5622         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5623         byte_count = 3 /* pad */  + params + count;
5624         pSMB->DataCount = cpu_to_le16(count);
5625         pSMB->ParameterCount = cpu_to_le16(params);
5626         pSMB->TotalDataCount = pSMB->DataCount;
5627         pSMB->TotalParameterCount = pSMB->ParameterCount;
5628         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5629         pSMB->DataOffset = cpu_to_le16(offset);
5630         pSMB->Fid = fid;
5631         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5632                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5633         else
5634                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5635         pSMB->Reserved4 = 0;
5636         inc_rfc1001_len(pSMB, byte_count);
5637         pSMB->ByteCount = cpu_to_le16(byte_count);
5638         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5639         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5640         if (rc)
5641                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5642
5643         /* Note: On -EAGAIN error only caller can retry on handle based calls
5644                 since file handle passed in no longer valid */
5645
5646         return rc;
5647 }
5648
5649 int
5650 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5651                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5652 {
5653         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5654         char *data_offset;
5655         int rc = 0;
5656         __u16 params, param_offset, offset, byte_count, count;
5657
5658         cFYI(1, "Set File Disposition (via SetFileInfo)");
5659         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5660
5661         if (rc)
5662                 return rc;
5663
5664         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5665         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5666
5667         params = 6;
5668         pSMB->MaxSetupCount = 0;
5669         pSMB->Reserved = 0;
5670         pSMB->Flags = 0;
5671         pSMB->Timeout = 0;
5672         pSMB->Reserved2 = 0;
5673         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5674         offset = param_offset + params;
5675
5676         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5677
5678         count = 1;
5679         pSMB->MaxParameterCount = cpu_to_le16(2);
5680         /* BB find max SMB PDU from sess */
5681         pSMB->MaxDataCount = cpu_to_le16(1000);
5682         pSMB->SetupCount = 1;
5683         pSMB->Reserved3 = 0;
5684         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5685         byte_count = 3 /* pad */  + params + count;
5686         pSMB->DataCount = cpu_to_le16(count);
5687         pSMB->ParameterCount = cpu_to_le16(params);
5688         pSMB->TotalDataCount = pSMB->DataCount;
5689         pSMB->TotalParameterCount = pSMB->ParameterCount;
5690         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5691         pSMB->DataOffset = cpu_to_le16(offset);
5692         pSMB->Fid = fid;
5693         pSMB->I