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