~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/cifs/cifssmb.c

Version: ~ [ linux-5.16 ] ~ [ linux-5.15.13 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.90 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.170 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.224 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.261 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.296 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.298 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp