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

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

Version: ~ [ linux-5.8-rc5 ] ~ [ linux-5.7.8 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.51 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.132 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.188 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.230 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.230 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

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

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

osdn.jp