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