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