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

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

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