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

TOMOYO Linux Cross Reference
Linux/fs/smb/client/cifssmb.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

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

sflogo.php