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

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

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