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

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

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