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