Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: LGPL-2.1
0002 /*
0003  *
0004  *   Copyright (C) International Business Machines  Corp., 2002,2010
0005  *   Author(s): Steve French (sfrench@us.ibm.com)
0006  *
0007  *   Contains the routines for constructing the SMB PDUs themselves
0008  *
0009  */
0010 
0011  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
0012  /* These are mostly routines that operate on a pathname, or on a tree id     */
0013  /* (mounted volume), but there are eight handle based routines which must be */
0014  /* treated slightly differently for reconnection purposes since we never     */
0015  /* want to reuse a stale file handle and only the caller knows the file info */
0016 
0017 #include <linux/fs.h>
0018 #include <linux/kernel.h>
0019 #include <linux/vfs.h>
0020 #include <linux/slab.h>
0021 #include <linux/posix_acl_xattr.h>
0022 #include <linux/pagemap.h>
0023 #include <linux/swap.h>
0024 #include <linux/task_io_accounting_ops.h>
0025 #include <linux/uaccess.h>
0026 #include "cifspdu.h"
0027 #include "cifsglob.h"
0028 #include "cifsacl.h"
0029 #include "cifsproto.h"
0030 #include "cifs_unicode.h"
0031 #include "cifs_debug.h"
0032 #include "fscache.h"
0033 #include "smbdirect.h"
0034 #ifdef CONFIG_CIFS_DFS_UPCALL
0035 #include "dfs_cache.h"
0036 #endif
0037 
0038 #ifdef CONFIG_CIFS_POSIX
0039 static struct {
0040     int index;
0041     char *name;
0042 } protocols[] = {
0043     {CIFS_PROT, "\2NT LM 0.12"},
0044     {POSIX_PROT, "\2POSIX 2"},
0045     {BAD_PROT, "\2"}
0046 };
0047 #else
0048 static struct {
0049     int index;
0050     char *name;
0051 } protocols[] = {
0052     {CIFS_PROT, "\2NT LM 0.12"},
0053     {BAD_PROT, "\2"}
0054 };
0055 #endif
0056 
0057 /* define the number of elements in the cifs dialect array */
0058 #ifdef CONFIG_CIFS_POSIX
0059 #define CIFS_NUM_PROT 2
0060 #else /* not posix */
0061 #define CIFS_NUM_PROT 1
0062 #endif /* CIFS_POSIX */
0063 
0064 
0065 /* reconnect the socket, tcon, and smb session if needed */
0066 static int
0067 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
0068 {
0069     int rc;
0070     struct cifs_ses *ses;
0071     struct TCP_Server_Info *server;
0072     struct nls_table *nls_codepage;
0073     int retries;
0074 
0075     /*
0076      * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
0077      * tcp and smb session status done differently for those three - in the
0078      * calling routine
0079      */
0080     if (!tcon)
0081         return 0;
0082 
0083     ses = tcon->ses;
0084     server = ses->server;
0085 
0086     /*
0087      * only tree disconnect, open, and write, (and ulogoff which does not
0088      * have tcon) are allowed as we start force umount
0089      */
0090     spin_lock(&tcon->tc_lock);
0091     if (tcon->status == TID_EXITING) {
0092         if (smb_command != SMB_COM_WRITE_ANDX &&
0093             smb_command != SMB_COM_OPEN_ANDX &&
0094             smb_command != SMB_COM_TREE_DISCONNECT) {
0095             spin_unlock(&tcon->tc_lock);
0096             cifs_dbg(FYI, "can not send cmd %d while umounting\n",
0097                  smb_command);
0098             return -ENODEV;
0099         }
0100     }
0101     spin_unlock(&tcon->tc_lock);
0102 
0103     retries = server->nr_targets;
0104 
0105     /*
0106      * Give demultiplex thread up to 10 seconds to each target available for
0107      * reconnect -- should be greater than cifs socket timeout which is 7
0108      * seconds.
0109      */
0110     while (server->tcpStatus == CifsNeedReconnect) {
0111         rc = wait_event_interruptible_timeout(server->response_q,
0112                               (server->tcpStatus != CifsNeedReconnect),
0113                               10 * HZ);
0114         if (rc < 0) {
0115             cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n",
0116                  __func__);
0117             return -ERESTARTSYS;
0118         }
0119 
0120         /* are we still trying to reconnect? */
0121         spin_lock(&server->srv_lock);
0122         if (server->tcpStatus != CifsNeedReconnect) {
0123             spin_unlock(&server->srv_lock);
0124             break;
0125         }
0126         spin_unlock(&server->srv_lock);
0127 
0128         if (retries && --retries)
0129             continue;
0130 
0131         /*
0132          * on "soft" mounts we wait once. Hard mounts keep
0133          * retrying until process is killed or server comes
0134          * back on-line
0135          */
0136         if (!tcon->retry) {
0137             cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
0138             return -EHOSTDOWN;
0139         }
0140         retries = server->nr_targets;
0141     }
0142 
0143     spin_lock(&ses->chan_lock);
0144     if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
0145         spin_unlock(&ses->chan_lock);
0146         return 0;
0147     }
0148     spin_unlock(&ses->chan_lock);
0149 
0150     nls_codepage = load_nls_default();
0151 
0152     /*
0153      * Recheck after acquire mutex. If another thread is negotiating
0154      * and the server never sends an answer the socket will be closed
0155      * and tcpStatus set to reconnect.
0156      */
0157     spin_lock(&server->srv_lock);
0158     if (server->tcpStatus == CifsNeedReconnect) {
0159         spin_unlock(&server->srv_lock);
0160         rc = -EHOSTDOWN;
0161         goto out;
0162     }
0163     spin_unlock(&server->srv_lock);
0164 
0165     /*
0166      * need to prevent multiple threads trying to simultaneously
0167      * reconnect the same SMB session
0168      */
0169     spin_lock(&ses->chan_lock);
0170     if (!cifs_chan_needs_reconnect(ses, server)) {
0171         spin_unlock(&ses->chan_lock);
0172 
0173         /* this means that we only need to tree connect */
0174         if (tcon->need_reconnect)
0175             goto skip_sess_setup;
0176 
0177         rc = -EHOSTDOWN;
0178         goto out;
0179     }
0180     spin_unlock(&ses->chan_lock);
0181 
0182     mutex_lock(&ses->session_mutex);
0183     rc = cifs_negotiate_protocol(0, ses, server);
0184     if (!rc)
0185         rc = cifs_setup_session(0, ses, server, nls_codepage);
0186 
0187     /* do we need to reconnect tcon? */
0188     if (rc || !tcon->need_reconnect) {
0189         mutex_unlock(&ses->session_mutex);
0190         goto out;
0191     }
0192 
0193 skip_sess_setup:
0194     cifs_mark_open_files_invalid(tcon);
0195     rc = cifs_tree_connect(0, tcon, nls_codepage);
0196     mutex_unlock(&ses->session_mutex);
0197     cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
0198 
0199     if (rc) {
0200         pr_warn_once("reconnect tcon failed rc = %d\n", rc);
0201         goto out;
0202     }
0203 
0204     atomic_inc(&tconInfoReconnectCount);
0205 
0206     /* tell server Unix caps we support */
0207     if (cap_unix(ses))
0208         reset_cifs_unix_caps(0, tcon, NULL, NULL);
0209 
0210     /*
0211      * Removed call to reopen open files here. It is safer (and faster) to
0212      * reopen files one at a time as needed in read and write.
0213      *
0214      * FIXME: what about file locks? don't we need to reclaim them ASAP?
0215      */
0216 
0217 out:
0218     /*
0219      * Check if handle based operation so we know whether we can continue
0220      * or not without returning to caller to reset file handle
0221      */
0222     switch (smb_command) {
0223     case SMB_COM_READ_ANDX:
0224     case SMB_COM_WRITE_ANDX:
0225     case SMB_COM_CLOSE:
0226     case SMB_COM_FIND_CLOSE2:
0227     case SMB_COM_LOCKING_ANDX:
0228         rc = -EAGAIN;
0229     }
0230 
0231     unload_nls(nls_codepage);
0232     return rc;
0233 }
0234 
0235 /* Allocate and return pointer to an SMB request buffer, and set basic
0236    SMB information in the SMB header.  If the return code is zero, this
0237    function must have filled in request_buf pointer */
0238 static int
0239 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
0240         void **request_buf)
0241 {
0242     int rc;
0243 
0244     rc = cifs_reconnect_tcon(tcon, smb_command);
0245     if (rc)
0246         return rc;
0247 
0248     *request_buf = cifs_small_buf_get();
0249     if (*request_buf == NULL) {
0250         /* BB should we add a retry in here if not a writepage? */
0251         return -ENOMEM;
0252     }
0253 
0254     header_assemble((struct smb_hdr *) *request_buf, smb_command,
0255             tcon, wct);
0256 
0257     if (tcon != NULL)
0258         cifs_stats_inc(&tcon->num_smbs_sent);
0259 
0260     return 0;
0261 }
0262 
0263 int
0264 small_smb_init_no_tc(const int smb_command, const int wct,
0265              struct cifs_ses *ses, void **request_buf)
0266 {
0267     int rc;
0268     struct smb_hdr *buffer;
0269 
0270     rc = small_smb_init(smb_command, wct, NULL, request_buf);
0271     if (rc)
0272         return rc;
0273 
0274     buffer = (struct smb_hdr *)*request_buf;
0275     buffer->Mid = get_next_mid(ses->server);
0276     if (ses->capabilities & CAP_UNICODE)
0277         buffer->Flags2 |= SMBFLG2_UNICODE;
0278     if (ses->capabilities & CAP_STATUS32)
0279         buffer->Flags2 |= SMBFLG2_ERR_STATUS;
0280 
0281     /* uid, tid can stay at zero as set in header assemble */
0282 
0283     /* BB add support for turning on the signing when
0284     this function is used after 1st of session setup requests */
0285 
0286     return rc;
0287 }
0288 
0289 /* If the return code is zero, this function must fill in request_buf pointer */
0290 static int
0291 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
0292             void **request_buf, void **response_buf)
0293 {
0294     *request_buf = cifs_buf_get();
0295     if (*request_buf == NULL) {
0296         /* BB should we add a retry in here if not a writepage? */
0297         return -ENOMEM;
0298     }
0299     /* Although the original thought was we needed the response buf for  */
0300     /* potential retries of smb operations it turns out we can determine */
0301     /* from the mid flags when the request buffer can be resent without  */
0302     /* having to use a second distinct buffer for the response */
0303     if (response_buf)
0304         *response_buf = *request_buf;
0305 
0306     header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
0307             wct);
0308 
0309     if (tcon != NULL)
0310         cifs_stats_inc(&tcon->num_smbs_sent);
0311 
0312     return 0;
0313 }
0314 
0315 /* If the return code is zero, this function must fill in request_buf pointer */
0316 static int
0317 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
0318      void **request_buf, void **response_buf)
0319 {
0320     int rc;
0321 
0322     rc = cifs_reconnect_tcon(tcon, smb_command);
0323     if (rc)
0324         return rc;
0325 
0326     return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
0327 }
0328 
0329 static int
0330 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
0331             void **request_buf, void **response_buf)
0332 {
0333     spin_lock(&tcon->ses->chan_lock);
0334     if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
0335         tcon->need_reconnect) {
0336         spin_unlock(&tcon->ses->chan_lock);
0337         return -EHOSTDOWN;
0338     }
0339     spin_unlock(&tcon->ses->chan_lock);
0340 
0341     return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
0342 }
0343 
0344 static int validate_t2(struct smb_t2_rsp *pSMB)
0345 {
0346     unsigned int total_size;
0347 
0348     /* check for plausible wct */
0349     if (pSMB->hdr.WordCount < 10)
0350         goto vt2_err;
0351 
0352     /* check for parm and data offset going beyond end of smb */
0353     if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
0354         get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
0355         goto vt2_err;
0356 
0357     total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
0358     if (total_size >= 512)
0359         goto vt2_err;
0360 
0361     /* check that bcc is at least as big as parms + data, and that it is
0362      * less than negotiated smb buffer
0363      */
0364     total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
0365     if (total_size > get_bcc(&pSMB->hdr) ||
0366         total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
0367         goto vt2_err;
0368 
0369     return 0;
0370 vt2_err:
0371     cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
0372         sizeof(struct smb_t2_rsp) + 16);
0373     return -EINVAL;
0374 }
0375 
0376 static int
0377 decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
0378 {
0379     int rc = 0;
0380     u16 count;
0381     char    *guid = pSMBr->u.extended_response.GUID;
0382     struct TCP_Server_Info *server = ses->server;
0383 
0384     count = get_bcc(&pSMBr->hdr);
0385     if (count < SMB1_CLIENT_GUID_SIZE)
0386         return -EIO;
0387 
0388     spin_lock(&cifs_tcp_ses_lock);
0389     if (server->srv_count > 1) {
0390         spin_unlock(&cifs_tcp_ses_lock);
0391         if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
0392             cifs_dbg(FYI, "server UID changed\n");
0393             memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
0394         }
0395     } else {
0396         spin_unlock(&cifs_tcp_ses_lock);
0397         memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
0398     }
0399 
0400     if (count == SMB1_CLIENT_GUID_SIZE) {
0401         server->sec_ntlmssp = true;
0402     } else {
0403         count -= SMB1_CLIENT_GUID_SIZE;
0404         rc = decode_negTokenInit(
0405             pSMBr->u.extended_response.SecurityBlob, count, server);
0406         if (rc != 1)
0407             return -EINVAL;
0408     }
0409 
0410     return 0;
0411 }
0412 
0413 static bool
0414 should_set_ext_sec_flag(enum securityEnum sectype)
0415 {
0416     switch (sectype) {
0417     case RawNTLMSSP:
0418     case Kerberos:
0419         return true;
0420     case Unspecified:
0421         if (global_secflags &
0422             (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
0423             return true;
0424         fallthrough;
0425     default:
0426         return false;
0427     }
0428 }
0429 
0430 int
0431 CIFSSMBNegotiate(const unsigned int xid,
0432          struct cifs_ses *ses,
0433          struct TCP_Server_Info *server)
0434 {
0435     NEGOTIATE_REQ *pSMB;
0436     NEGOTIATE_RSP *pSMBr;
0437     int rc = 0;
0438     int bytes_returned;
0439     int i;
0440     u16 count;
0441 
0442     if (!server) {
0443         WARN(1, "%s: server is NULL!\n", __func__);
0444         return -EIO;
0445     }
0446 
0447     rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
0448               (void **) &pSMB, (void **) &pSMBr);
0449     if (rc)
0450         return rc;
0451 
0452     pSMB->hdr.Mid = get_next_mid(server);
0453     pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
0454 
0455     if (should_set_ext_sec_flag(ses->sectype)) {
0456         cifs_dbg(FYI, "Requesting extended security\n");
0457         pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
0458     }
0459 
0460     count = 0;
0461     /*
0462      * We know that all the name entries in the protocols array
0463      * are short (< 16 bytes anyway) and are NUL terminated.
0464      */
0465     for (i = 0; i < CIFS_NUM_PROT; i++) {
0466         size_t len = strlen(protocols[i].name) + 1;
0467 
0468         memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
0469         count += len;
0470     }
0471     inc_rfc1001_len(pSMB, count);
0472     pSMB->ByteCount = cpu_to_le16(count);
0473 
0474     rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
0475              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0476     if (rc != 0)
0477         goto neg_err_exit;
0478 
0479     server->dialect = le16_to_cpu(pSMBr->DialectIndex);
0480     cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
0481     /* Check wct = 1 error case */
0482     if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
0483         /* core returns wct = 1, but we do not ask for core - otherwise
0484         small wct just comes when dialect index is -1 indicating we
0485         could not negotiate a common dialect */
0486         rc = -EOPNOTSUPP;
0487         goto neg_err_exit;
0488     } else if (pSMBr->hdr.WordCount != 17) {
0489         /* unknown wct */
0490         rc = -EOPNOTSUPP;
0491         goto neg_err_exit;
0492     }
0493     /* else wct == 17, NTLM or better */
0494 
0495     server->sec_mode = pSMBr->SecurityMode;
0496     if ((server->sec_mode & SECMODE_USER) == 0)
0497         cifs_dbg(FYI, "share mode security\n");
0498 
0499     /* one byte, so no need to convert this or EncryptionKeyLen from
0500        little endian */
0501     server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
0502                    cifs_max_pending);
0503     set_credits(server, server->maxReq);
0504     /* probably no need to store and check maxvcs */
0505     server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
0506     /* set up max_read for readahead check */
0507     server->max_read = server->maxBuf;
0508     server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
0509     cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
0510     server->capabilities = le32_to_cpu(pSMBr->Capabilities);
0511     server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
0512     server->timeAdj *= 60;
0513 
0514     if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
0515         server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
0516         memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
0517                CIFS_CRYPTO_KEY_SIZE);
0518     } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
0519             server->capabilities & CAP_EXTENDED_SECURITY) {
0520         server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
0521         rc = decode_ext_sec_blob(ses, pSMBr);
0522     } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
0523         rc = -EIO; /* no crypt key only if plain text pwd */
0524     } else {
0525         server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
0526         server->capabilities &= ~CAP_EXTENDED_SECURITY;
0527     }
0528 
0529     if (!rc)
0530         rc = cifs_enable_signing(server, ses->sign);
0531 neg_err_exit:
0532     cifs_buf_release(pSMB);
0533 
0534     cifs_dbg(FYI, "negprot rc %d\n", rc);
0535     return rc;
0536 }
0537 
0538 int
0539 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
0540 {
0541     struct smb_hdr *smb_buffer;
0542     int rc = 0;
0543 
0544     cifs_dbg(FYI, "In tree disconnect\n");
0545 
0546     /* BB: do we need to check this? These should never be NULL. */
0547     if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
0548         return -EIO;
0549 
0550     /*
0551      * No need to return error on this operation if tid invalidated and
0552      * closed on server already e.g. due to tcp session crashing. Also,
0553      * the tcon is no longer on the list, so no need to take lock before
0554      * checking this.
0555      */
0556     spin_lock(&tcon->ses->chan_lock);
0557     if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
0558         spin_unlock(&tcon->ses->chan_lock);
0559         return -EIO;
0560     }
0561     spin_unlock(&tcon->ses->chan_lock);
0562 
0563     rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
0564                 (void **)&smb_buffer);
0565     if (rc)
0566         return rc;
0567 
0568     rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
0569     cifs_small_buf_release(smb_buffer);
0570     if (rc)
0571         cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
0572 
0573     /* No need to return error on this operation if tid invalidated and
0574        closed on server already e.g. due to tcp session crashing */
0575     if (rc == -EAGAIN)
0576         rc = 0;
0577 
0578     return rc;
0579 }
0580 
0581 /*
0582  * This is a no-op for now. We're not really interested in the reply, but
0583  * rather in the fact that the server sent one and that server->lstrp
0584  * gets updated.
0585  *
0586  * FIXME: maybe we should consider checking that the reply matches request?
0587  */
0588 static void
0589 cifs_echo_callback(struct mid_q_entry *mid)
0590 {
0591     struct TCP_Server_Info *server = mid->callback_data;
0592     struct cifs_credits credits = { .value = 1, .instance = 0 };
0593 
0594     release_mid(mid);
0595     add_credits(server, &credits, CIFS_ECHO_OP);
0596 }
0597 
0598 int
0599 CIFSSMBEcho(struct TCP_Server_Info *server)
0600 {
0601     ECHO_REQ *smb;
0602     int rc = 0;
0603     struct kvec iov[2];
0604     struct smb_rqst rqst = { .rq_iov = iov,
0605                  .rq_nvec = 2 };
0606 
0607     cifs_dbg(FYI, "In echo request\n");
0608 
0609     rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
0610     if (rc)
0611         return rc;
0612 
0613     if (server->capabilities & CAP_UNICODE)
0614         smb->hdr.Flags2 |= SMBFLG2_UNICODE;
0615 
0616     /* set up echo request */
0617     smb->hdr.Tid = 0xffff;
0618     smb->hdr.WordCount = 1;
0619     put_unaligned_le16(1, &smb->EchoCount);
0620     put_bcc(1, &smb->hdr);
0621     smb->Data[0] = 'a';
0622     inc_rfc1001_len(smb, 3);
0623 
0624     iov[0].iov_len = 4;
0625     iov[0].iov_base = smb;
0626     iov[1].iov_len = get_rfc1002_length(smb);
0627     iov[1].iov_base = (char *)smb + 4;
0628 
0629     rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
0630                  server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
0631     if (rc)
0632         cifs_dbg(FYI, "Echo request failed: %d\n", rc);
0633 
0634     cifs_small_buf_release(smb);
0635 
0636     return rc;
0637 }
0638 
0639 int
0640 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
0641 {
0642     LOGOFF_ANDX_REQ *pSMB;
0643     int rc = 0;
0644 
0645     cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
0646 
0647     /*
0648      * BB: do we need to check validity of ses and server? They should
0649      * always be valid since we have an active reference. If not, that
0650      * should probably be a BUG()
0651      */
0652     if (!ses || !ses->server)
0653         return -EIO;
0654 
0655     mutex_lock(&ses->session_mutex);
0656     spin_lock(&ses->chan_lock);
0657     if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
0658         spin_unlock(&ses->chan_lock);
0659         goto session_already_dead; /* no need to send SMBlogoff if uid
0660                           already closed due to reconnect */
0661     }
0662     spin_unlock(&ses->chan_lock);
0663 
0664     rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
0665     if (rc) {
0666         mutex_unlock(&ses->session_mutex);
0667         return rc;
0668     }
0669 
0670     pSMB->hdr.Mid = get_next_mid(ses->server);
0671 
0672     if (ses->server->sign)
0673         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
0674 
0675     pSMB->hdr.Uid = ses->Suid;
0676 
0677     pSMB->AndXCommand = 0xFF;
0678     rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
0679     cifs_small_buf_release(pSMB);
0680 session_already_dead:
0681     mutex_unlock(&ses->session_mutex);
0682 
0683     /* if session dead then we do not need to do ulogoff,
0684         since server closed smb session, no sense reporting
0685         error */
0686     if (rc == -EAGAIN)
0687         rc = 0;
0688     return rc;
0689 }
0690 
0691 int
0692 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
0693          const char *fileName, __u16 type,
0694          const struct nls_table *nls_codepage, int remap)
0695 {
0696     TRANSACTION2_SPI_REQ *pSMB = NULL;
0697     TRANSACTION2_SPI_RSP *pSMBr = NULL;
0698     struct unlink_psx_rq *pRqD;
0699     int name_len;
0700     int rc = 0;
0701     int bytes_returned = 0;
0702     __u16 params, param_offset, offset, byte_count;
0703 
0704     cifs_dbg(FYI, "In POSIX delete\n");
0705 PsxDelete:
0706     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
0707               (void **) &pSMBr);
0708     if (rc)
0709         return rc;
0710 
0711     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0712         name_len =
0713             cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
0714                        PATH_MAX, nls_codepage, remap);
0715         name_len++; /* trailing null */
0716         name_len *= 2;
0717     } else {
0718         name_len = copy_path_name(pSMB->FileName, fileName);
0719     }
0720 
0721     params = 6 + name_len;
0722     pSMB->MaxParameterCount = cpu_to_le16(2);
0723     pSMB->MaxDataCount = 0; /* BB double check this with jra */
0724     pSMB->MaxSetupCount = 0;
0725     pSMB->Reserved = 0;
0726     pSMB->Flags = 0;
0727     pSMB->Timeout = 0;
0728     pSMB->Reserved2 = 0;
0729     param_offset = offsetof(struct smb_com_transaction2_spi_req,
0730                 InformationLevel) - 4;
0731     offset = param_offset + params;
0732 
0733     /* Setup pointer to Request Data (inode type).
0734      * Note that SMB offsets are from the beginning of SMB which is 4 bytes
0735      * in, after RFC1001 field
0736      */
0737     pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
0738     pRqD->type = cpu_to_le16(type);
0739     pSMB->ParameterOffset = cpu_to_le16(param_offset);
0740     pSMB->DataOffset = cpu_to_le16(offset);
0741     pSMB->SetupCount = 1;
0742     pSMB->Reserved3 = 0;
0743     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
0744     byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
0745 
0746     pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
0747     pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
0748     pSMB->ParameterCount = cpu_to_le16(params);
0749     pSMB->TotalParameterCount = pSMB->ParameterCount;
0750     pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
0751     pSMB->Reserved4 = 0;
0752     inc_rfc1001_len(pSMB, byte_count);
0753     pSMB->ByteCount = cpu_to_le16(byte_count);
0754     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0755              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0756     if (rc)
0757         cifs_dbg(FYI, "Posix delete returned %d\n", rc);
0758     cifs_buf_release(pSMB);
0759 
0760     cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
0761 
0762     if (rc == -EAGAIN)
0763         goto PsxDelete;
0764 
0765     return rc;
0766 }
0767 
0768 int
0769 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
0770            struct cifs_sb_info *cifs_sb)
0771 {
0772     DELETE_FILE_REQ *pSMB = NULL;
0773     DELETE_FILE_RSP *pSMBr = NULL;
0774     int rc = 0;
0775     int bytes_returned;
0776     int name_len;
0777     int remap = cifs_remap(cifs_sb);
0778 
0779 DelFileRetry:
0780     rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
0781               (void **) &pSMBr);
0782     if (rc)
0783         return rc;
0784 
0785     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0786         name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
0787                           PATH_MAX, cifs_sb->local_nls,
0788                           remap);
0789         name_len++; /* trailing null */
0790         name_len *= 2;
0791     } else {
0792         name_len = copy_path_name(pSMB->fileName, name);
0793     }
0794     pSMB->SearchAttributes =
0795         cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
0796     pSMB->BufferFormat = 0x04;
0797     inc_rfc1001_len(pSMB, name_len + 1);
0798     pSMB->ByteCount = cpu_to_le16(name_len + 1);
0799     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0800              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0801     cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
0802     if (rc)
0803         cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
0804 
0805     cifs_buf_release(pSMB);
0806     if (rc == -EAGAIN)
0807         goto DelFileRetry;
0808 
0809     return rc;
0810 }
0811 
0812 int
0813 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
0814          struct cifs_sb_info *cifs_sb)
0815 {
0816     DELETE_DIRECTORY_REQ *pSMB = NULL;
0817     DELETE_DIRECTORY_RSP *pSMBr = NULL;
0818     int rc = 0;
0819     int bytes_returned;
0820     int name_len;
0821     int remap = cifs_remap(cifs_sb);
0822 
0823     cifs_dbg(FYI, "In CIFSSMBRmDir\n");
0824 RmDirRetry:
0825     rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
0826               (void **) &pSMBr);
0827     if (rc)
0828         return rc;
0829 
0830     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0831         name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
0832                           PATH_MAX, cifs_sb->local_nls,
0833                           remap);
0834         name_len++; /* trailing null */
0835         name_len *= 2;
0836     } else {
0837         name_len = copy_path_name(pSMB->DirName, name);
0838     }
0839 
0840     pSMB->BufferFormat = 0x04;
0841     inc_rfc1001_len(pSMB, name_len + 1);
0842     pSMB->ByteCount = cpu_to_le16(name_len + 1);
0843     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0844              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0845     cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
0846     if (rc)
0847         cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
0848 
0849     cifs_buf_release(pSMB);
0850     if (rc == -EAGAIN)
0851         goto RmDirRetry;
0852     return rc;
0853 }
0854 
0855 int
0856 CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
0857          struct cifs_tcon *tcon, const char *name,
0858          struct cifs_sb_info *cifs_sb)
0859 {
0860     int rc = 0;
0861     CREATE_DIRECTORY_REQ *pSMB = NULL;
0862     CREATE_DIRECTORY_RSP *pSMBr = NULL;
0863     int bytes_returned;
0864     int name_len;
0865     int remap = cifs_remap(cifs_sb);
0866 
0867     cifs_dbg(FYI, "In CIFSSMBMkDir\n");
0868 MkDirRetry:
0869     rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
0870               (void **) &pSMBr);
0871     if (rc)
0872         return rc;
0873 
0874     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0875         name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
0876                           PATH_MAX, cifs_sb->local_nls,
0877                           remap);
0878         name_len++; /* trailing null */
0879         name_len *= 2;
0880     } else {
0881         name_len = copy_path_name(pSMB->DirName, name);
0882     }
0883 
0884     pSMB->BufferFormat = 0x04;
0885     inc_rfc1001_len(pSMB, name_len + 1);
0886     pSMB->ByteCount = cpu_to_le16(name_len + 1);
0887     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0888              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0889     cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
0890     if (rc)
0891         cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
0892 
0893     cifs_buf_release(pSMB);
0894     if (rc == -EAGAIN)
0895         goto MkDirRetry;
0896     return rc;
0897 }
0898 
0899 int
0900 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
0901         __u32 posix_flags, __u64 mode, __u16 *netfid,
0902         FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
0903         const char *name, const struct nls_table *nls_codepage,
0904         int remap)
0905 {
0906     TRANSACTION2_SPI_REQ *pSMB = NULL;
0907     TRANSACTION2_SPI_RSP *pSMBr = NULL;
0908     int name_len;
0909     int rc = 0;
0910     int bytes_returned = 0;
0911     __u16 params, param_offset, offset, byte_count, count;
0912     OPEN_PSX_REQ *pdata;
0913     OPEN_PSX_RSP *psx_rsp;
0914 
0915     cifs_dbg(FYI, "In POSIX Create\n");
0916 PsxCreat:
0917     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
0918               (void **) &pSMBr);
0919     if (rc)
0920         return rc;
0921 
0922     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
0923         name_len =
0924             cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
0925                        PATH_MAX, nls_codepage, remap);
0926         name_len++; /* trailing null */
0927         name_len *= 2;
0928     } else {
0929         name_len = copy_path_name(pSMB->FileName, name);
0930     }
0931 
0932     params = 6 + name_len;
0933     count = sizeof(OPEN_PSX_REQ);
0934     pSMB->MaxParameterCount = cpu_to_le16(2);
0935     pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
0936     pSMB->MaxSetupCount = 0;
0937     pSMB->Reserved = 0;
0938     pSMB->Flags = 0;
0939     pSMB->Timeout = 0;
0940     pSMB->Reserved2 = 0;
0941     param_offset = offsetof(struct smb_com_transaction2_spi_req,
0942                 InformationLevel) - 4;
0943     offset = param_offset + params;
0944     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
0945     pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
0946     pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
0947     pdata->Permissions = cpu_to_le64(mode);
0948     pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
0949     pdata->OpenFlags =  cpu_to_le32(*pOplock);
0950     pSMB->ParameterOffset = cpu_to_le16(param_offset);
0951     pSMB->DataOffset = cpu_to_le16(offset);
0952     pSMB->SetupCount = 1;
0953     pSMB->Reserved3 = 0;
0954     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
0955     byte_count = 3 /* pad */  + params + count;
0956 
0957     pSMB->DataCount = cpu_to_le16(count);
0958     pSMB->ParameterCount = cpu_to_le16(params);
0959     pSMB->TotalDataCount = pSMB->DataCount;
0960     pSMB->TotalParameterCount = pSMB->ParameterCount;
0961     pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
0962     pSMB->Reserved4 = 0;
0963     inc_rfc1001_len(pSMB, byte_count);
0964     pSMB->ByteCount = cpu_to_le16(byte_count);
0965     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
0966              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
0967     if (rc) {
0968         cifs_dbg(FYI, "Posix create returned %d\n", rc);
0969         goto psx_create_err;
0970     }
0971 
0972     cifs_dbg(FYI, "copying inode info\n");
0973     rc = validate_t2((struct smb_t2_rsp *)pSMBr);
0974 
0975     if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
0976         rc = -EIO;  /* bad smb */
0977         goto psx_create_err;
0978     }
0979 
0980     /* copy return information to pRetData */
0981     psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
0982             + le16_to_cpu(pSMBr->t2.DataOffset));
0983 
0984     *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
0985     if (netfid)
0986         *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
0987     /* Let caller know file was created so we can set the mode. */
0988     /* Do we care about the CreateAction in any other cases? */
0989     if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
0990         *pOplock |= CIFS_CREATE_ACTION;
0991     /* check to make sure response data is there */
0992     if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
0993         pRetData->Type = cpu_to_le32(-1); /* unknown */
0994         cifs_dbg(NOISY, "unknown type\n");
0995     } else {
0996         if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
0997                     + sizeof(FILE_UNIX_BASIC_INFO)) {
0998             cifs_dbg(VFS, "Open response data too small\n");
0999             pRetData->Type = cpu_to_le32(-1);
1000             goto psx_create_err;
1001         }
1002         memcpy((char *) pRetData,
1003             (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1004             sizeof(FILE_UNIX_BASIC_INFO));
1005     }
1006 
1007 psx_create_err:
1008     cifs_buf_release(pSMB);
1009 
1010     if (posix_flags & SMB_O_DIRECTORY)
1011         cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1012     else
1013         cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1014 
1015     if (rc == -EAGAIN)
1016         goto PsxCreat;
1017 
1018     return rc;
1019 }
1020 
1021 static __u16 convert_disposition(int disposition)
1022 {
1023     __u16 ofun = 0;
1024 
1025     switch (disposition) {
1026         case FILE_SUPERSEDE:
1027             ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1028             break;
1029         case FILE_OPEN:
1030             ofun = SMBOPEN_OAPPEND;
1031             break;
1032         case FILE_CREATE:
1033             ofun = SMBOPEN_OCREATE;
1034             break;
1035         case FILE_OPEN_IF:
1036             ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1037             break;
1038         case FILE_OVERWRITE:
1039             ofun = SMBOPEN_OTRUNC;
1040             break;
1041         case FILE_OVERWRITE_IF:
1042             ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1043             break;
1044         default:
1045             cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1046             ofun =  SMBOPEN_OAPPEND; /* regular open */
1047     }
1048     return ofun;
1049 }
1050 
1051 static int
1052 access_flags_to_smbopen_mode(const int access_flags)
1053 {
1054     int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1055 
1056     if (masked_flags == GENERIC_READ)
1057         return SMBOPEN_READ;
1058     else if (masked_flags == GENERIC_WRITE)
1059         return SMBOPEN_WRITE;
1060 
1061     /* just go for read/write */
1062     return SMBOPEN_READWRITE;
1063 }
1064 
1065 int
1066 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1067         const char *fileName, const int openDisposition,
1068         const int access_flags, const int create_options, __u16 *netfid,
1069         int *pOplock, FILE_ALL_INFO *pfile_info,
1070         const struct nls_table *nls_codepage, int remap)
1071 {
1072     int rc;
1073     OPENX_REQ *pSMB = NULL;
1074     OPENX_RSP *pSMBr = NULL;
1075     int bytes_returned;
1076     int name_len;
1077     __u16 count;
1078 
1079 OldOpenRetry:
1080     rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1081               (void **) &pSMBr);
1082     if (rc)
1083         return rc;
1084 
1085     pSMB->AndXCommand = 0xFF;       /* none */
1086 
1087     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1088         count = 1;      /* account for one byte pad to word boundary */
1089         name_len =
1090            cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1091                       fileName, PATH_MAX, nls_codepage, remap);
1092         name_len++;     /* trailing null */
1093         name_len *= 2;
1094     } else {
1095         count = 0;      /* no pad */
1096         name_len = copy_path_name(pSMB->fileName, fileName);
1097     }
1098     if (*pOplock & REQ_OPLOCK)
1099         pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1100     else if (*pOplock & REQ_BATCHOPLOCK)
1101         pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1102 
1103     pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1104     pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1105     pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1106     /* set file as system file if special file such
1107        as fifo and server expecting SFU style and
1108        no Unix extensions */
1109 
1110     if (create_options & CREATE_OPTION_SPECIAL)
1111         pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1112     else /* BB FIXME BB */
1113         pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1114 
1115     if (create_options & CREATE_OPTION_READONLY)
1116         pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1117 
1118     /* BB FIXME BB */
1119 /*  pSMB->CreateOptions = cpu_to_le32(create_options &
1120                          CREATE_OPTIONS_MASK); */
1121     /* BB FIXME END BB */
1122 
1123     pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1124     pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1125     count += name_len;
1126     inc_rfc1001_len(pSMB, count);
1127 
1128     pSMB->ByteCount = cpu_to_le16(count);
1129     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1130             (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1131     cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1132     if (rc) {
1133         cifs_dbg(FYI, "Error in Open = %d\n", rc);
1134     } else {
1135     /* BB verify if wct == 15 */
1136 
1137 /*      *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1138 
1139         *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1140         /* Let caller know file was created so we can set the mode. */
1141         /* Do we care about the CreateAction in any other cases? */
1142     /* BB FIXME BB */
1143 /*      if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1144             *pOplock |= CIFS_CREATE_ACTION; */
1145     /* BB FIXME END */
1146 
1147         if (pfile_info) {
1148             pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1149             pfile_info->LastAccessTime = 0; /* BB fixme */
1150             pfile_info->LastWriteTime = 0; /* BB fixme */
1151             pfile_info->ChangeTime = 0;  /* BB fixme */
1152             pfile_info->Attributes =
1153                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1154             /* the file_info buf is endian converted by caller */
1155             pfile_info->AllocationSize =
1156                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1157             pfile_info->EndOfFile = pfile_info->AllocationSize;
1158             pfile_info->NumberOfLinks = cpu_to_le32(1);
1159             pfile_info->DeletePending = 0;
1160         }
1161     }
1162 
1163     cifs_buf_release(pSMB);
1164     if (rc == -EAGAIN)
1165         goto OldOpenRetry;
1166     return rc;
1167 }
1168 
1169 int
1170 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1171       FILE_ALL_INFO *buf)
1172 {
1173     int rc;
1174     OPEN_REQ *req = NULL;
1175     OPEN_RSP *rsp = NULL;
1176     int bytes_returned;
1177     int name_len;
1178     __u16 count;
1179     struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1180     struct cifs_tcon *tcon = oparms->tcon;
1181     int remap = cifs_remap(cifs_sb);
1182     const struct nls_table *nls = cifs_sb->local_nls;
1183     int create_options = oparms->create_options;
1184     int desired_access = oparms->desired_access;
1185     int disposition = oparms->disposition;
1186     const char *path = oparms->path;
1187 
1188 openRetry:
1189     rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1190               (void **)&rsp);
1191     if (rc)
1192         return rc;
1193 
1194     /* no commands go after this */
1195     req->AndXCommand = 0xFF;
1196 
1197     if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1198         /* account for one byte pad to word boundary */
1199         count = 1;
1200         name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1201                           path, PATH_MAX, nls, remap);
1202         /* trailing null */
1203         name_len++;
1204         name_len *= 2;
1205         req->NameLength = cpu_to_le16(name_len);
1206     } else {
1207         /* BB improve check for buffer overruns BB */
1208         /* no pad */
1209         count = 0;
1210         name_len = copy_path_name(req->fileName, path);
1211         req->NameLength = cpu_to_le16(name_len);
1212     }
1213 
1214     if (*oplock & REQ_OPLOCK)
1215         req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1216     else if (*oplock & REQ_BATCHOPLOCK)
1217         req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1218 
1219     req->DesiredAccess = cpu_to_le32(desired_access);
1220     req->AllocationSize = 0;
1221 
1222     /*
1223      * Set file as system file if special file such as fifo and server
1224      * expecting SFU style and no Unix extensions.
1225      */
1226     if (create_options & CREATE_OPTION_SPECIAL)
1227         req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1228     else
1229         req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1230 
1231     /*
1232      * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1233      * sensitive checks for other servers such as Samba.
1234      */
1235     if (tcon->ses->capabilities & CAP_UNIX)
1236         req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1237 
1238     if (create_options & CREATE_OPTION_READONLY)
1239         req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1240 
1241     req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1242     req->CreateDisposition = cpu_to_le32(disposition);
1243     req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1244 
1245     /* BB Expirement with various impersonation levels and verify */
1246     req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1247     req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1248 
1249     count += name_len;
1250     inc_rfc1001_len(req, count);
1251 
1252     req->ByteCount = cpu_to_le16(count);
1253     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1254              (struct smb_hdr *)rsp, &bytes_returned, 0);
1255     cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1256     if (rc) {
1257         cifs_dbg(FYI, "Error in Open = %d\n", rc);
1258         cifs_buf_release(req);
1259         if (rc == -EAGAIN)
1260             goto openRetry;
1261         return rc;
1262     }
1263 
1264     /* 1 byte no need to le_to_cpu */
1265     *oplock = rsp->OplockLevel;
1266     /* cifs fid stays in le */
1267     oparms->fid->netfid = rsp->Fid;
1268     oparms->fid->access = desired_access;
1269 
1270     /* Let caller know file was created so we can set the mode. */
1271     /* Do we care about the CreateAction in any other cases? */
1272     if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1273         *oplock |= CIFS_CREATE_ACTION;
1274 
1275     if (buf) {
1276         /* copy from CreationTime to Attributes */
1277         memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1278         /* the file_info buf is endian converted by caller */
1279         buf->AllocationSize = rsp->AllocationSize;
1280         buf->EndOfFile = rsp->EndOfFile;
1281         buf->NumberOfLinks = cpu_to_le32(1);
1282         buf->DeletePending = 0;
1283     }
1284 
1285     cifs_buf_release(req);
1286     return rc;
1287 }
1288 
1289 static void
1290 cifs_readv_callback(struct mid_q_entry *mid)
1291 {
1292     struct cifs_readdata *rdata = mid->callback_data;
1293     struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1294     struct TCP_Server_Info *server = tcon->ses->server;
1295     struct smb_rqst rqst = { .rq_iov = rdata->iov,
1296                  .rq_nvec = 2,
1297                  .rq_pages = rdata->pages,
1298                  .rq_offset = rdata->page_offset,
1299                  .rq_npages = rdata->nr_pages,
1300                  .rq_pagesz = rdata->pagesz,
1301                  .rq_tailsz = rdata->tailsz };
1302     struct cifs_credits credits = { .value = 1, .instance = 0 };
1303 
1304     cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1305          __func__, mid->mid, mid->mid_state, rdata->result,
1306          rdata->bytes);
1307 
1308     switch (mid->mid_state) {
1309     case MID_RESPONSE_RECEIVED:
1310         /* result already set, check signature */
1311         if (server->sign) {
1312             int rc = 0;
1313 
1314             rc = cifs_verify_signature(&rqst, server,
1315                           mid->sequence_number);
1316             if (rc)
1317                 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1318                      rc);
1319         }
1320         /* FIXME: should this be counted toward the initiating task? */
1321         task_io_account_read(rdata->got_bytes);
1322         cifs_stats_bytes_read(tcon, rdata->got_bytes);
1323         break;
1324     case MID_REQUEST_SUBMITTED:
1325     case MID_RETRY_NEEDED:
1326         rdata->result = -EAGAIN;
1327         if (server->sign && rdata->got_bytes)
1328             /* reset bytes number since we can not check a sign */
1329             rdata->got_bytes = 0;
1330         /* FIXME: should this be counted toward the initiating task? */
1331         task_io_account_read(rdata->got_bytes);
1332         cifs_stats_bytes_read(tcon, rdata->got_bytes);
1333         break;
1334     default:
1335         rdata->result = -EIO;
1336     }
1337 
1338     queue_work(cifsiod_wq, &rdata->work);
1339     release_mid(mid);
1340     add_credits(server, &credits, 0);
1341 }
1342 
1343 /* cifs_async_readv - send an async write, and set up mid to handle result */
1344 int
1345 cifs_async_readv(struct cifs_readdata *rdata)
1346 {
1347     int rc;
1348     READ_REQ *smb = NULL;
1349     int wct;
1350     struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1351     struct smb_rqst rqst = { .rq_iov = rdata->iov,
1352                  .rq_nvec = 2 };
1353 
1354     cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1355          __func__, rdata->offset, rdata->bytes);
1356 
1357     if (tcon->ses->capabilities & CAP_LARGE_FILES)
1358         wct = 12;
1359     else {
1360         wct = 10; /* old style read */
1361         if ((rdata->offset >> 32) > 0)  {
1362             /* can not handle this big offset for old */
1363             return -EIO;
1364         }
1365     }
1366 
1367     rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1368     if (rc)
1369         return rc;
1370 
1371     smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1372     smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1373 
1374     smb->AndXCommand = 0xFF;    /* none */
1375     smb->Fid = rdata->cfile->fid.netfid;
1376     smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1377     if (wct == 12)
1378         smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1379     smb->Remaining = 0;
1380     smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1381     smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1382     if (wct == 12)
1383         smb->ByteCount = 0;
1384     else {
1385         /* old style read */
1386         struct smb_com_readx_req *smbr =
1387             (struct smb_com_readx_req *)smb;
1388         smbr->ByteCount = 0;
1389     }
1390 
1391     /* 4 for RFC1001 length + 1 for BCC */
1392     rdata->iov[0].iov_base = smb;
1393     rdata->iov[0].iov_len = 4;
1394     rdata->iov[1].iov_base = (char *)smb + 4;
1395     rdata->iov[1].iov_len = get_rfc1002_length(smb);
1396 
1397     kref_get(&rdata->refcount);
1398     rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1399                  cifs_readv_callback, NULL, rdata, 0, NULL);
1400 
1401     if (rc == 0)
1402         cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1403     else
1404         kref_put(&rdata->refcount, cifs_readdata_release);
1405 
1406     cifs_small_buf_release(smb);
1407     return rc;
1408 }
1409 
1410 int
1411 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1412         unsigned int *nbytes, char **buf, int *pbuf_type)
1413 {
1414     int rc = -EACCES;
1415     READ_REQ *pSMB = NULL;
1416     READ_RSP *pSMBr = NULL;
1417     char *pReadData = NULL;
1418     int wct;
1419     int resp_buf_type = 0;
1420     struct kvec iov[1];
1421     struct kvec rsp_iov;
1422     __u32 pid = io_parms->pid;
1423     __u16 netfid = io_parms->netfid;
1424     __u64 offset = io_parms->offset;
1425     struct cifs_tcon *tcon = io_parms->tcon;
1426     unsigned int count = io_parms->length;
1427 
1428     cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1429     if (tcon->ses->capabilities & CAP_LARGE_FILES)
1430         wct = 12;
1431     else {
1432         wct = 10; /* old style read */
1433         if ((offset >> 32) > 0)  {
1434             /* can not handle this big offset for old */
1435             return -EIO;
1436         }
1437     }
1438 
1439     *nbytes = 0;
1440     rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1441     if (rc)
1442         return rc;
1443 
1444     pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1445     pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1446 
1447     /* tcon and ses pointer are checked in smb_init */
1448     if (tcon->ses->server == NULL)
1449         return -ECONNABORTED;
1450 
1451     pSMB->AndXCommand = 0xFF;       /* none */
1452     pSMB->Fid = netfid;
1453     pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1454     if (wct == 12)
1455         pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1456 
1457     pSMB->Remaining = 0;
1458     pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1459     pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1460     if (wct == 12)
1461         pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1462     else {
1463         /* old style read */
1464         struct smb_com_readx_req *pSMBW =
1465             (struct smb_com_readx_req *)pSMB;
1466         pSMBW->ByteCount = 0;
1467     }
1468 
1469     iov[0].iov_base = (char *)pSMB;
1470     iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1471     rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1472               CIFS_LOG_ERROR, &rsp_iov);
1473     cifs_small_buf_release(pSMB);
1474     cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1475     pSMBr = (READ_RSP *)rsp_iov.iov_base;
1476     if (rc) {
1477         cifs_dbg(VFS, "Send error in read = %d\n", rc);
1478     } else {
1479         int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1480         data_length = data_length << 16;
1481         data_length += le16_to_cpu(pSMBr->DataLength);
1482         *nbytes = data_length;
1483 
1484         /*check that DataLength would not go beyond end of SMB */
1485         if ((data_length > CIFSMaxBufSize)
1486                 || (data_length > count)) {
1487             cifs_dbg(FYI, "bad length %d for count %d\n",
1488                  data_length, count);
1489             rc = -EIO;
1490             *nbytes = 0;
1491         } else {
1492             pReadData = (char *) (&pSMBr->hdr.Protocol) +
1493                     le16_to_cpu(pSMBr->DataOffset);
1494 /*          if (rc = copy_to_user(buf, pReadData, data_length)) {
1495                 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1496                 rc = -EFAULT;
1497             }*/ /* can not use copy_to_user when using page cache*/
1498             if (*buf)
1499                 memcpy(*buf, pReadData, data_length);
1500         }
1501     }
1502 
1503     if (*buf) {
1504         free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1505     } else if (resp_buf_type != CIFS_NO_BUFFER) {
1506         /* return buffer to caller to free */
1507         *buf = rsp_iov.iov_base;
1508         if (resp_buf_type == CIFS_SMALL_BUFFER)
1509             *pbuf_type = CIFS_SMALL_BUFFER;
1510         else if (resp_buf_type == CIFS_LARGE_BUFFER)
1511             *pbuf_type = CIFS_LARGE_BUFFER;
1512     } /* else no valid buffer on return - leave as null */
1513 
1514     /* Note: On -EAGAIN error only caller can retry on handle based calls
1515         since file handle passed in no longer valid */
1516     return rc;
1517 }
1518 
1519 
1520 int
1521 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1522          unsigned int *nbytes, const char *buf)
1523 {
1524     int rc = -EACCES;
1525     WRITE_REQ *pSMB = NULL;
1526     WRITE_RSP *pSMBr = NULL;
1527     int bytes_returned, wct;
1528     __u32 bytes_sent;
1529     __u16 byte_count;
1530     __u32 pid = io_parms->pid;
1531     __u16 netfid = io_parms->netfid;
1532     __u64 offset = io_parms->offset;
1533     struct cifs_tcon *tcon = io_parms->tcon;
1534     unsigned int count = io_parms->length;
1535 
1536     *nbytes = 0;
1537 
1538     /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1539     if (tcon->ses == NULL)
1540         return -ECONNABORTED;
1541 
1542     if (tcon->ses->capabilities & CAP_LARGE_FILES)
1543         wct = 14;
1544     else {
1545         wct = 12;
1546         if ((offset >> 32) > 0) {
1547             /* can not handle big offset for old srv */
1548             return -EIO;
1549         }
1550     }
1551 
1552     rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1553               (void **) &pSMBr);
1554     if (rc)
1555         return rc;
1556 
1557     pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1558     pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1559 
1560     /* tcon and ses pointer are checked in smb_init */
1561     if (tcon->ses->server == NULL)
1562         return -ECONNABORTED;
1563 
1564     pSMB->AndXCommand = 0xFF;   /* none */
1565     pSMB->Fid = netfid;
1566     pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1567     if (wct == 14)
1568         pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1569 
1570     pSMB->Reserved = 0xFFFFFFFF;
1571     pSMB->WriteMode = 0;
1572     pSMB->Remaining = 0;
1573 
1574     /* Can increase buffer size if buffer is big enough in some cases ie we
1575     can send more if LARGE_WRITE_X capability returned by the server and if
1576     our buffer is big enough or if we convert to iovecs on socket writes
1577     and eliminate the copy to the CIFS buffer */
1578     if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1579         bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1580     } else {
1581         bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1582              & ~0xFF;
1583     }
1584 
1585     if (bytes_sent > count)
1586         bytes_sent = count;
1587     pSMB->DataOffset =
1588         cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1589     if (buf)
1590         memcpy(pSMB->Data, buf, bytes_sent);
1591     else if (count != 0) {
1592         /* No buffer */
1593         cifs_buf_release(pSMB);
1594         return -EINVAL;
1595     } /* else setting file size with write of zero bytes */
1596     if (wct == 14)
1597         byte_count = bytes_sent + 1; /* pad */
1598     else /* wct == 12 */
1599         byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1600 
1601     pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1602     pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1603     inc_rfc1001_len(pSMB, byte_count);
1604 
1605     if (wct == 14)
1606         pSMB->ByteCount = cpu_to_le16(byte_count);
1607     else { /* old style write has byte count 4 bytes earlier
1608           so 4 bytes pad  */
1609         struct smb_com_writex_req *pSMBW =
1610             (struct smb_com_writex_req *)pSMB;
1611         pSMBW->ByteCount = cpu_to_le16(byte_count);
1612     }
1613 
1614     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1615              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1616     cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1617     if (rc) {
1618         cifs_dbg(FYI, "Send error in write = %d\n", rc);
1619     } else {
1620         *nbytes = le16_to_cpu(pSMBr->CountHigh);
1621         *nbytes = (*nbytes) << 16;
1622         *nbytes += le16_to_cpu(pSMBr->Count);
1623 
1624         /*
1625          * Mask off high 16 bits when bytes written as returned by the
1626          * server is greater than bytes requested by the client. Some
1627          * OS/2 servers are known to set incorrect CountHigh values.
1628          */
1629         if (*nbytes > count)
1630             *nbytes &= 0xFFFF;
1631     }
1632 
1633     cifs_buf_release(pSMB);
1634 
1635     /* Note: On -EAGAIN error only caller can retry on handle based calls
1636         since file handle passed in no longer valid */
1637 
1638     return rc;
1639 }
1640 
1641 /*
1642  * Check the mid_state and signature on received buffer (if any), and queue the
1643  * workqueue completion task.
1644  */
1645 static void
1646 cifs_writev_callback(struct mid_q_entry *mid)
1647 {
1648     struct cifs_writedata *wdata = mid->callback_data;
1649     struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1650     unsigned int written;
1651     WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1652     struct cifs_credits credits = { .value = 1, .instance = 0 };
1653 
1654     switch (mid->mid_state) {
1655     case MID_RESPONSE_RECEIVED:
1656         wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1657         if (wdata->result != 0)
1658             break;
1659 
1660         written = le16_to_cpu(smb->CountHigh);
1661         written <<= 16;
1662         written += le16_to_cpu(smb->Count);
1663         /*
1664          * Mask off high 16 bits when bytes written as returned
1665          * by the server is greater than bytes requested by the
1666          * client. OS/2 servers are known to set incorrect
1667          * CountHigh values.
1668          */
1669         if (written > wdata->bytes)
1670             written &= 0xFFFF;
1671 
1672         if (written < wdata->bytes)
1673             wdata->result = -ENOSPC;
1674         else
1675             wdata->bytes = written;
1676         break;
1677     case MID_REQUEST_SUBMITTED:
1678     case MID_RETRY_NEEDED:
1679         wdata->result = -EAGAIN;
1680         break;
1681     default:
1682         wdata->result = -EIO;
1683         break;
1684     }
1685 
1686     queue_work(cifsiod_wq, &wdata->work);
1687     release_mid(mid);
1688     add_credits(tcon->ses->server, &credits, 0);
1689 }
1690 
1691 /* cifs_async_writev - send an async write, and set up mid to handle result */
1692 int
1693 cifs_async_writev(struct cifs_writedata *wdata,
1694           void (*release)(struct kref *kref))
1695 {
1696     int rc = -EACCES;
1697     WRITE_REQ *smb = NULL;
1698     int wct;
1699     struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1700     struct kvec iov[2];
1701     struct smb_rqst rqst = { };
1702 
1703     if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1704         wct = 14;
1705     } else {
1706         wct = 12;
1707         if (wdata->offset >> 32 > 0) {
1708             /* can not handle big offset for old srv */
1709             return -EIO;
1710         }
1711     }
1712 
1713     rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
1714     if (rc)
1715         goto async_writev_out;
1716 
1717     smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
1718     smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
1719 
1720     smb->AndXCommand = 0xFF;    /* none */
1721     smb->Fid = wdata->cfile->fid.netfid;
1722     smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
1723     if (wct == 14)
1724         smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
1725     smb->Reserved = 0xFFFFFFFF;
1726     smb->WriteMode = 0;
1727     smb->Remaining = 0;
1728 
1729     smb->DataOffset =
1730         cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1731 
1732     /* 4 for RFC1001 length + 1 for BCC */
1733     iov[0].iov_len = 4;
1734     iov[0].iov_base = smb;
1735     iov[1].iov_len = get_rfc1002_length(smb) + 1;
1736     iov[1].iov_base = (char *)smb + 4;
1737 
1738     rqst.rq_iov = iov;
1739     rqst.rq_nvec = 2;
1740     rqst.rq_pages = wdata->pages;
1741     rqst.rq_offset = wdata->page_offset;
1742     rqst.rq_npages = wdata->nr_pages;
1743     rqst.rq_pagesz = wdata->pagesz;
1744     rqst.rq_tailsz = wdata->tailsz;
1745 
1746     cifs_dbg(FYI, "async write at %llu %u bytes\n",
1747          wdata->offset, wdata->bytes);
1748 
1749     smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
1750     smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
1751 
1752     if (wct == 14) {
1753         inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
1754         put_bcc(wdata->bytes + 1, &smb->hdr);
1755     } else {
1756         /* wct == 12 */
1757         struct smb_com_writex_req *smbw =
1758                 (struct smb_com_writex_req *)smb;
1759         inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
1760         put_bcc(wdata->bytes + 5, &smbw->hdr);
1761         iov[1].iov_len += 4; /* pad bigger by four bytes */
1762     }
1763 
1764     kref_get(&wdata->refcount);
1765     rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
1766                  cifs_writev_callback, NULL, wdata, 0, NULL);
1767 
1768     if (rc == 0)
1769         cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1770     else
1771         kref_put(&wdata->refcount, release);
1772 
1773 async_writev_out:
1774     cifs_small_buf_release(smb);
1775     return rc;
1776 }
1777 
1778 int
1779 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
1780           unsigned int *nbytes, struct kvec *iov, int n_vec)
1781 {
1782     int rc;
1783     WRITE_REQ *pSMB = NULL;
1784     int wct;
1785     int smb_hdr_len;
1786     int resp_buf_type = 0;
1787     __u32 pid = io_parms->pid;
1788     __u16 netfid = io_parms->netfid;
1789     __u64 offset = io_parms->offset;
1790     struct cifs_tcon *tcon = io_parms->tcon;
1791     unsigned int count = io_parms->length;
1792     struct kvec rsp_iov;
1793 
1794     *nbytes = 0;
1795 
1796     cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
1797 
1798     if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1799         wct = 14;
1800     } else {
1801         wct = 12;
1802         if ((offset >> 32) > 0) {
1803             /* can not handle big offset for old srv */
1804             return -EIO;
1805         }
1806     }
1807     rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1808     if (rc)
1809         return rc;
1810 
1811     pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1812     pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1813 
1814     /* tcon and ses pointer are checked in smb_init */
1815     if (tcon->ses->server == NULL)
1816         return -ECONNABORTED;
1817 
1818     pSMB->AndXCommand = 0xFF;   /* none */
1819     pSMB->Fid = netfid;
1820     pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1821     if (wct == 14)
1822         pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1823     pSMB->Reserved = 0xFFFFFFFF;
1824     pSMB->WriteMode = 0;
1825     pSMB->Remaining = 0;
1826 
1827     pSMB->DataOffset =
1828         cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1829 
1830     pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1831     pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1832     /* header + 1 byte pad */
1833     smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1834     if (wct == 14)
1835         inc_rfc1001_len(pSMB, count + 1);
1836     else /* wct == 12 */
1837         inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
1838     if (wct == 14)
1839         pSMB->ByteCount = cpu_to_le16(count + 1);
1840     else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1841         struct smb_com_writex_req *pSMBW =
1842                 (struct smb_com_writex_req *)pSMB;
1843         pSMBW->ByteCount = cpu_to_le16(count + 5);
1844     }
1845     iov[0].iov_base = pSMB;
1846     if (wct == 14)
1847         iov[0].iov_len = smb_hdr_len + 4;
1848     else /* wct == 12 pad bigger by four bytes */
1849         iov[0].iov_len = smb_hdr_len + 8;
1850 
1851     rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
1852               &rsp_iov);
1853     cifs_small_buf_release(pSMB);
1854     cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1855     if (rc) {
1856         cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
1857     } else if (resp_buf_type == 0) {
1858         /* presumably this can not happen, but best to be safe */
1859         rc = -EIO;
1860     } else {
1861         WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
1862         *nbytes = le16_to_cpu(pSMBr->CountHigh);
1863         *nbytes = (*nbytes) << 16;
1864         *nbytes += le16_to_cpu(pSMBr->Count);
1865 
1866         /*
1867          * Mask off high 16 bits when bytes written as returned by the
1868          * server is greater than bytes requested by the client. OS/2
1869          * servers are known to set incorrect CountHigh values.
1870          */
1871         if (*nbytes > count)
1872             *nbytes &= 0xFFFF;
1873     }
1874 
1875     free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1876 
1877     /* Note: On -EAGAIN error only caller can retry on handle based calls
1878         since file handle passed in no longer valid */
1879 
1880     return rc;
1881 }
1882 
1883 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
1884            const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
1885            const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
1886 {
1887     int rc = 0;
1888     LOCK_REQ *pSMB = NULL;
1889     struct kvec iov[2];
1890     struct kvec rsp_iov;
1891     int resp_buf_type;
1892     __u16 count;
1893 
1894     cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
1895          num_lock, num_unlock);
1896 
1897     rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1898     if (rc)
1899         return rc;
1900 
1901     pSMB->Timeout = 0;
1902     pSMB->NumberOfLocks = cpu_to_le16(num_lock);
1903     pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
1904     pSMB->LockType = lock_type;
1905     pSMB->AndXCommand = 0xFF; /* none */
1906     pSMB->Fid = netfid; /* netfid stays le */
1907 
1908     count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1909     inc_rfc1001_len(pSMB, count);
1910     pSMB->ByteCount = cpu_to_le16(count);
1911 
1912     iov[0].iov_base = (char *)pSMB;
1913     iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
1914              (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1915     iov[1].iov_base = (char *)buf;
1916     iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1917 
1918     cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
1919     rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
1920               CIFS_NO_RSP_BUF, &rsp_iov);
1921     cifs_small_buf_release(pSMB);
1922     if (rc)
1923         cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
1924 
1925     return rc;
1926 }
1927 
1928 int
1929 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
1930         const __u16 smb_file_id, const __u32 netpid, const __u64 len,
1931         const __u64 offset, const __u32 numUnlock,
1932         const __u32 numLock, const __u8 lockType,
1933         const bool waitFlag, const __u8 oplock_level)
1934 {
1935     int rc = 0;
1936     LOCK_REQ *pSMB = NULL;
1937 /*  LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1938     int bytes_returned;
1939     int flags = 0;
1940     __u16 count;
1941 
1942     cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
1943          (int)waitFlag, numLock);
1944     rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1945 
1946     if (rc)
1947         return rc;
1948 
1949     if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1950         /* no response expected */
1951         flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
1952         pSMB->Timeout = 0;
1953     } else if (waitFlag) {
1954         flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1955         pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1956     } else {
1957         pSMB->Timeout = 0;
1958     }
1959 
1960     pSMB->NumberOfLocks = cpu_to_le16(numLock);
1961     pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1962     pSMB->LockType = lockType;
1963     pSMB->OplockLevel = oplock_level;
1964     pSMB->AndXCommand = 0xFF;   /* none */
1965     pSMB->Fid = smb_file_id; /* netfid stays le */
1966 
1967     if ((numLock != 0) || (numUnlock != 0)) {
1968         pSMB->Locks[0].Pid = cpu_to_le16(netpid);
1969         /* BB where to store pid high? */
1970         pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1971         pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1972         pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1973         pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1974         count = sizeof(LOCKING_ANDX_RANGE);
1975     } else {
1976         /* oplock break */
1977         count = 0;
1978     }
1979     inc_rfc1001_len(pSMB, count);
1980     pSMB->ByteCount = cpu_to_le16(count);
1981 
1982     if (waitFlag)
1983         rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1984             (struct smb_hdr *) pSMB, &bytes_returned);
1985     else
1986         rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
1987     cifs_small_buf_release(pSMB);
1988     cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
1989     if (rc)
1990         cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
1991 
1992     /* Note: On -EAGAIN error only caller can retry on handle based calls
1993     since file handle passed in no longer valid */
1994     return rc;
1995 }
1996 
1997 int
1998 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
1999         const __u16 smb_file_id, const __u32 netpid,
2000         const loff_t start_offset, const __u64 len,
2001         struct file_lock *pLockData, const __u16 lock_type,
2002         const bool waitFlag)
2003 {
2004     struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2005     struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2006     struct cifs_posix_lock *parm_data;
2007     int rc = 0;
2008     int timeout = 0;
2009     int bytes_returned = 0;
2010     int resp_buf_type = 0;
2011     __u16 params, param_offset, offset, byte_count, count;
2012     struct kvec iov[1];
2013     struct kvec rsp_iov;
2014 
2015     cifs_dbg(FYI, "Posix Lock\n");
2016 
2017     rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2018 
2019     if (rc)
2020         return rc;
2021 
2022     pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2023 
2024     params = 6;
2025     pSMB->MaxSetupCount = 0;
2026     pSMB->Reserved = 0;
2027     pSMB->Flags = 0;
2028     pSMB->Reserved2 = 0;
2029     param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2030     offset = param_offset + params;
2031 
2032     count = sizeof(struct cifs_posix_lock);
2033     pSMB->MaxParameterCount = cpu_to_le16(2);
2034     pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2035     pSMB->SetupCount = 1;
2036     pSMB->Reserved3 = 0;
2037     if (pLockData)
2038         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2039     else
2040         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2041     byte_count = 3 /* pad */  + params + count;
2042     pSMB->DataCount = cpu_to_le16(count);
2043     pSMB->ParameterCount = cpu_to_le16(params);
2044     pSMB->TotalDataCount = pSMB->DataCount;
2045     pSMB->TotalParameterCount = pSMB->ParameterCount;
2046     pSMB->ParameterOffset = cpu_to_le16(param_offset);
2047     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2048     parm_data = (struct cifs_posix_lock *)
2049             (((char *)pSMB) + offset + 4);
2050 
2051     parm_data->lock_type = cpu_to_le16(lock_type);
2052     if (waitFlag) {
2053         timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2054         parm_data->lock_flags = cpu_to_le16(1);
2055         pSMB->Timeout = cpu_to_le32(-1);
2056     } else
2057         pSMB->Timeout = 0;
2058 
2059     parm_data->pid = cpu_to_le32(netpid);
2060     parm_data->start = cpu_to_le64(start_offset);
2061     parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2062 
2063     pSMB->DataOffset = cpu_to_le16(offset);
2064     pSMB->Fid = smb_file_id;
2065     pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2066     pSMB->Reserved4 = 0;
2067     inc_rfc1001_len(pSMB, byte_count);
2068     pSMB->ByteCount = cpu_to_le16(byte_count);
2069     if (waitFlag) {
2070         rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2071             (struct smb_hdr *) pSMBr, &bytes_returned);
2072     } else {
2073         iov[0].iov_base = (char *)pSMB;
2074         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2075         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2076                 &resp_buf_type, timeout, &rsp_iov);
2077         pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2078     }
2079     cifs_small_buf_release(pSMB);
2080 
2081     if (rc) {
2082         cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2083     } else if (pLockData) {
2084         /* lock structure can be returned on get */
2085         __u16 data_offset;
2086         __u16 data_count;
2087         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2088 
2089         if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2090             rc = -EIO;      /* bad smb */
2091             goto plk_err_exit;
2092         }
2093         data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2094         data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2095         if (data_count < sizeof(struct cifs_posix_lock)) {
2096             rc = -EIO;
2097             goto plk_err_exit;
2098         }
2099         parm_data = (struct cifs_posix_lock *)
2100             ((char *)&pSMBr->hdr.Protocol + data_offset);
2101         if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2102             pLockData->fl_type = F_UNLCK;
2103         else {
2104             if (parm_data->lock_type ==
2105                     cpu_to_le16(CIFS_RDLCK))
2106                 pLockData->fl_type = F_RDLCK;
2107             else if (parm_data->lock_type ==
2108                     cpu_to_le16(CIFS_WRLCK))
2109                 pLockData->fl_type = F_WRLCK;
2110 
2111             pLockData->fl_start = le64_to_cpu(parm_data->start);
2112             pLockData->fl_end = pLockData->fl_start +
2113                 (le64_to_cpu(parm_data->length) ?
2114                  le64_to_cpu(parm_data->length) - 1 : 0);
2115             pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2116         }
2117     }
2118 
2119 plk_err_exit:
2120     free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2121 
2122     /* Note: On -EAGAIN error only caller can retry on handle based calls
2123        since file handle passed in no longer valid */
2124 
2125     return rc;
2126 }
2127 
2128 
2129 int
2130 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2131 {
2132     int rc = 0;
2133     CLOSE_REQ *pSMB = NULL;
2134     cifs_dbg(FYI, "In CIFSSMBClose\n");
2135 
2136 /* do not retry on dead session on close */
2137     rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2138     if (rc == -EAGAIN)
2139         return 0;
2140     if (rc)
2141         return rc;
2142 
2143     pSMB->FileID = (__u16) smb_file_id;
2144     pSMB->LastWriteTime = 0xFFFFFFFF;
2145     pSMB->ByteCount = 0;
2146     rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2147     cifs_small_buf_release(pSMB);
2148     cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2149     if (rc) {
2150         if (rc != -EINTR) {
2151             /* EINTR is expected when user ctl-c to kill app */
2152             cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2153         }
2154     }
2155 
2156     /* Since session is dead, file will be closed on server already */
2157     if (rc == -EAGAIN)
2158         rc = 0;
2159 
2160     return rc;
2161 }
2162 
2163 int
2164 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2165 {
2166     int rc = 0;
2167     FLUSH_REQ *pSMB = NULL;
2168     cifs_dbg(FYI, "In CIFSSMBFlush\n");
2169 
2170     rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2171     if (rc)
2172         return rc;
2173 
2174     pSMB->FileID = (__u16) smb_file_id;
2175     pSMB->ByteCount = 0;
2176     rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2177     cifs_small_buf_release(pSMB);
2178     cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2179     if (rc)
2180         cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2181 
2182     return rc;
2183 }
2184 
2185 int
2186 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2187           const char *from_name, const char *to_name,
2188           struct cifs_sb_info *cifs_sb)
2189 {
2190     int rc = 0;
2191     RENAME_REQ *pSMB = NULL;
2192     RENAME_RSP *pSMBr = NULL;
2193     int bytes_returned;
2194     int name_len, name_len2;
2195     __u16 count;
2196     int remap = cifs_remap(cifs_sb);
2197 
2198     cifs_dbg(FYI, "In CIFSSMBRename\n");
2199 renameRetry:
2200     rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2201               (void **) &pSMBr);
2202     if (rc)
2203         return rc;
2204 
2205     pSMB->BufferFormat = 0x04;
2206     pSMB->SearchAttributes =
2207         cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2208             ATTR_DIRECTORY);
2209 
2210     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2211         name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2212                           from_name, PATH_MAX,
2213                           cifs_sb->local_nls, remap);
2214         name_len++; /* trailing null */
2215         name_len *= 2;
2216         pSMB->OldFileName[name_len] = 0x04; /* pad */
2217     /* protocol requires ASCII signature byte on Unicode string */
2218         pSMB->OldFileName[name_len + 1] = 0x00;
2219         name_len2 =
2220             cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2221                        to_name, PATH_MAX, cifs_sb->local_nls,
2222                        remap);
2223         name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2224         name_len2 *= 2; /* convert to bytes */
2225     } else {
2226         name_len = copy_path_name(pSMB->OldFileName, from_name);
2227         name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2228         pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2229         name_len2++;    /* signature byte */
2230     }
2231 
2232     count = 1 /* 1st signature byte */  + name_len + name_len2;
2233     inc_rfc1001_len(pSMB, count);
2234     pSMB->ByteCount = cpu_to_le16(count);
2235 
2236     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2237              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2238     cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2239     if (rc)
2240         cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2241 
2242     cifs_buf_release(pSMB);
2243 
2244     if (rc == -EAGAIN)
2245         goto renameRetry;
2246 
2247     return rc;
2248 }
2249 
2250 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2251         int netfid, const char *target_name,
2252         const struct nls_table *nls_codepage, int remap)
2253 {
2254     struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2255     struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2256     struct set_file_rename *rename_info;
2257     char *data_offset;
2258     char dummy_string[30];
2259     int rc = 0;
2260     int bytes_returned = 0;
2261     int len_of_str;
2262     __u16 params, param_offset, offset, count, byte_count;
2263 
2264     cifs_dbg(FYI, "Rename to File by handle\n");
2265     rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2266             (void **) &pSMBr);
2267     if (rc)
2268         return rc;
2269 
2270     params = 6;
2271     pSMB->MaxSetupCount = 0;
2272     pSMB->Reserved = 0;
2273     pSMB->Flags = 0;
2274     pSMB->Timeout = 0;
2275     pSMB->Reserved2 = 0;
2276     param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2277     offset = param_offset + params;
2278 
2279     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2280     data_offset = (char *)(pSMB) + offset + 4;
2281     rename_info = (struct set_file_rename *) data_offset;
2282     pSMB->MaxParameterCount = cpu_to_le16(2);
2283     pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2284     pSMB->SetupCount = 1;
2285     pSMB->Reserved3 = 0;
2286     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2287     byte_count = 3 /* pad */  + params;
2288     pSMB->ParameterCount = cpu_to_le16(params);
2289     pSMB->TotalParameterCount = pSMB->ParameterCount;
2290     pSMB->ParameterOffset = cpu_to_le16(param_offset);
2291     pSMB->DataOffset = cpu_to_le16(offset);
2292     /* construct random name ".cifs_tmp<inodenum><mid>" */
2293     rename_info->overwrite = cpu_to_le32(1);
2294     rename_info->root_fid  = 0;
2295     /* unicode only call */
2296     if (target_name == NULL) {
2297         sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2298         len_of_str =
2299             cifsConvertToUTF16((__le16 *)rename_info->target_name,
2300                     dummy_string, 24, nls_codepage, remap);
2301     } else {
2302         len_of_str =
2303             cifsConvertToUTF16((__le16 *)rename_info->target_name,
2304                     target_name, PATH_MAX, nls_codepage,
2305                     remap);
2306     }
2307     rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2308     count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2309     byte_count += count;
2310     pSMB->DataCount = cpu_to_le16(count);
2311     pSMB->TotalDataCount = pSMB->DataCount;
2312     pSMB->Fid = netfid;
2313     pSMB->InformationLevel =
2314         cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2315     pSMB->Reserved4 = 0;
2316     inc_rfc1001_len(pSMB, byte_count);
2317     pSMB->ByteCount = cpu_to_le16(byte_count);
2318     rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2319              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2320     cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2321     if (rc)
2322         cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2323              rc);
2324 
2325     cifs_buf_release(pSMB);
2326 
2327     /* Note: On -EAGAIN error only caller can retry on handle based calls
2328         since file handle passed in no longer valid */
2329 
2330     return rc;
2331 }
2332 
2333 int
2334 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2335         const char *fromName, const __u16 target_tid, const char *toName,
2336         const int flags, const struct nls_table *nls_codepage, int remap)
2337 {
2338     int rc = 0;
2339     COPY_REQ *pSMB = NULL;
2340     COPY_RSP *pSMBr = NULL;
2341     int bytes_returned;
2342     int name_len, name_len2;
2343     __u16 count;
2344 
2345     cifs_dbg(FYI, "In CIFSSMBCopy\n");
2346 copyRetry:
2347     rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2348             (void **) &pSMBr);
2349     if (rc)
2350         return rc;
2351 
2352     pSMB->BufferFormat = 0x04;
2353     pSMB->Tid2 = target_tid;
2354 
2355     pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2356 
2357     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2358         name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2359                           fromName, PATH_MAX, nls_codepage,
2360                           remap);
2361         name_len++;     /* trailing null */
2362         name_len *= 2;
2363         pSMB->OldFileName[name_len] = 0x04;     /* pad */
2364         /* protocol requires ASCII signature byte on Unicode string */
2365         pSMB->OldFileName[name_len + 1] = 0x00;
2366         name_len2 =
2367             cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2368                        toName, PATH_MAX, nls_codepage, remap);
2369         name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2370         name_len2 *= 2; /* convert to bytes */
2371     } else {
2372         name_len = copy_path_name(pSMB->OldFileName, fromName);
2373         pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2374         name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2375         name_len2++;    /* signature byte */
2376     }
2377 
2378     count = 1 /* 1st signature byte */  + name_len + name_len2;
2379     inc_rfc1001_len(pSMB, count);
2380     pSMB->ByteCount = cpu_to_le16(count);
2381 
2382     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2383         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2384     if (rc) {
2385         cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2386              rc, le16_to_cpu(pSMBr->CopyCount));
2387     }
2388     cifs_buf_release(pSMB);
2389 
2390     if (rc == -EAGAIN)
2391         goto copyRetry;
2392 
2393     return rc;
2394 }
2395 
2396 int
2397 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2398               const char *fromName, const char *toName,
2399               const struct nls_table *nls_codepage, int remap)
2400 {
2401     TRANSACTION2_SPI_REQ *pSMB = NULL;
2402     TRANSACTION2_SPI_RSP *pSMBr = NULL;
2403     char *data_offset;
2404     int name_len;
2405     int name_len_target;
2406     int rc = 0;
2407     int bytes_returned = 0;
2408     __u16 params, param_offset, offset, byte_count;
2409 
2410     cifs_dbg(FYI, "In Symlink Unix style\n");
2411 createSymLinkRetry:
2412     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2413               (void **) &pSMBr);
2414     if (rc)
2415         return rc;
2416 
2417     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2418         name_len =
2419             cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2420                 /* find define for this maxpathcomponent */
2421                     PATH_MAX, nls_codepage, remap);
2422         name_len++; /* trailing null */
2423         name_len *= 2;
2424 
2425     } else {
2426         name_len = copy_path_name(pSMB->FileName, fromName);
2427     }
2428     params = 6 + name_len;
2429     pSMB->MaxSetupCount = 0;
2430     pSMB->Reserved = 0;
2431     pSMB->Flags = 0;
2432     pSMB->Timeout = 0;
2433     pSMB->Reserved2 = 0;
2434     param_offset = offsetof(struct smb_com_transaction2_spi_req,
2435                 InformationLevel) - 4;
2436     offset = param_offset + params;
2437 
2438     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2439     data_offset = (char *)pSMB + offset + 4;
2440     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2441         name_len_target =
2442             cifsConvertToUTF16((__le16 *) data_offset, toName,
2443                 /* find define for this maxpathcomponent */
2444                     PATH_MAX, nls_codepage, remap);
2445         name_len_target++;  /* trailing null */
2446         name_len_target *= 2;
2447     } else {
2448         name_len_target = copy_path_name(data_offset, toName);
2449     }
2450 
2451     pSMB->MaxParameterCount = cpu_to_le16(2);
2452     /* BB find exact max on data count below from sess */
2453     pSMB->MaxDataCount = cpu_to_le16(1000);
2454     pSMB->SetupCount = 1;
2455     pSMB->Reserved3 = 0;
2456     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2457     byte_count = 3 /* pad */  + params + name_len_target;
2458     pSMB->DataCount = cpu_to_le16(name_len_target);
2459     pSMB->ParameterCount = cpu_to_le16(params);
2460     pSMB->TotalDataCount = pSMB->DataCount;
2461     pSMB->TotalParameterCount = pSMB->ParameterCount;
2462     pSMB->ParameterOffset = cpu_to_le16(param_offset);
2463     pSMB->DataOffset = cpu_to_le16(offset);
2464     pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2465     pSMB->Reserved4 = 0;
2466     inc_rfc1001_len(pSMB, byte_count);
2467     pSMB->ByteCount = cpu_to_le16(byte_count);
2468     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2469              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2470     cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2471     if (rc)
2472         cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2473              rc);
2474 
2475     cifs_buf_release(pSMB);
2476 
2477     if (rc == -EAGAIN)
2478         goto createSymLinkRetry;
2479 
2480     return rc;
2481 }
2482 
2483 int
2484 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2485                const char *fromName, const char *toName,
2486                const struct nls_table *nls_codepage, int remap)
2487 {
2488     TRANSACTION2_SPI_REQ *pSMB = NULL;
2489     TRANSACTION2_SPI_RSP *pSMBr = NULL;
2490     char *data_offset;
2491     int name_len;
2492     int name_len_target;
2493     int rc = 0;
2494     int bytes_returned = 0;
2495     __u16 params, param_offset, offset, byte_count;
2496 
2497     cifs_dbg(FYI, "In Create Hard link Unix style\n");
2498 createHardLinkRetry:
2499     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2500               (void **) &pSMBr);
2501     if (rc)
2502         return rc;
2503 
2504     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2505         name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2506                           PATH_MAX, nls_codepage, remap);
2507         name_len++; /* trailing null */
2508         name_len *= 2;
2509 
2510     } else {
2511         name_len = copy_path_name(pSMB->FileName, toName);
2512     }
2513     params = 6 + name_len;
2514     pSMB->MaxSetupCount = 0;
2515     pSMB->Reserved = 0;
2516     pSMB->Flags = 0;
2517     pSMB->Timeout = 0;
2518     pSMB->Reserved2 = 0;
2519     param_offset = offsetof(struct smb_com_transaction2_spi_req,
2520                 InformationLevel) - 4;
2521     offset = param_offset + params;
2522 
2523     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2524     data_offset = (char *)pSMB + offset + 4;
2525     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2526         name_len_target =
2527             cifsConvertToUTF16((__le16 *) data_offset, fromName,
2528                        PATH_MAX, nls_codepage, remap);
2529         name_len_target++;  /* trailing null */
2530         name_len_target *= 2;
2531     } else {
2532         name_len_target = copy_path_name(data_offset, fromName);
2533     }
2534 
2535     pSMB->MaxParameterCount = cpu_to_le16(2);
2536     /* BB find exact max on data count below from sess*/
2537     pSMB->MaxDataCount = cpu_to_le16(1000);
2538     pSMB->SetupCount = 1;
2539     pSMB->Reserved3 = 0;
2540     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2541     byte_count = 3 /* pad */  + params + name_len_target;
2542     pSMB->ParameterCount = cpu_to_le16(params);
2543     pSMB->TotalParameterCount = pSMB->ParameterCount;
2544     pSMB->DataCount = cpu_to_le16(name_len_target);
2545     pSMB->TotalDataCount = pSMB->DataCount;
2546     pSMB->ParameterOffset = cpu_to_le16(param_offset);
2547     pSMB->DataOffset = cpu_to_le16(offset);
2548     pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2549     pSMB->Reserved4 = 0;
2550     inc_rfc1001_len(pSMB, byte_count);
2551     pSMB->ByteCount = cpu_to_le16(byte_count);
2552     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2553              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2554     cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2555     if (rc)
2556         cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2557              rc);
2558 
2559     cifs_buf_release(pSMB);
2560     if (rc == -EAGAIN)
2561         goto createHardLinkRetry;
2562 
2563     return rc;
2564 }
2565 
2566 int
2567 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2568            const char *from_name, const char *to_name,
2569            struct cifs_sb_info *cifs_sb)
2570 {
2571     int rc = 0;
2572     NT_RENAME_REQ *pSMB = NULL;
2573     RENAME_RSP *pSMBr = NULL;
2574     int bytes_returned;
2575     int name_len, name_len2;
2576     __u16 count;
2577     int remap = cifs_remap(cifs_sb);
2578 
2579     cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2580 winCreateHardLinkRetry:
2581 
2582     rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2583               (void **) &pSMBr);
2584     if (rc)
2585         return rc;
2586 
2587     pSMB->SearchAttributes =
2588         cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2589             ATTR_DIRECTORY);
2590     pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2591     pSMB->ClusterCount = 0;
2592 
2593     pSMB->BufferFormat = 0x04;
2594 
2595     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2596         name_len =
2597             cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2598                        PATH_MAX, cifs_sb->local_nls, remap);
2599         name_len++; /* trailing null */
2600         name_len *= 2;
2601 
2602         /* protocol specifies ASCII buffer format (0x04) for unicode */
2603         pSMB->OldFileName[name_len] = 0x04;
2604         pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2605         name_len2 =
2606             cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2607                        to_name, PATH_MAX, cifs_sb->local_nls,
2608                        remap);
2609         name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2610         name_len2 *= 2; /* convert to bytes */
2611     } else {
2612         name_len = copy_path_name(pSMB->OldFileName, from_name);
2613         pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2614         name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2615         name_len2++;    /* signature byte */
2616     }
2617 
2618     count = 1 /* string type byte */  + name_len + name_len2;
2619     inc_rfc1001_len(pSMB, count);
2620     pSMB->ByteCount = cpu_to_le16(count);
2621 
2622     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2623              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2624     cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2625     if (rc)
2626         cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
2627 
2628     cifs_buf_release(pSMB);
2629     if (rc == -EAGAIN)
2630         goto winCreateHardLinkRetry;
2631 
2632     return rc;
2633 }
2634 
2635 int
2636 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2637             const unsigned char *searchName, char **symlinkinfo,
2638             const struct nls_table *nls_codepage, int remap)
2639 {
2640 /* SMB_QUERY_FILE_UNIX_LINK */
2641     TRANSACTION2_QPI_REQ *pSMB = NULL;
2642     TRANSACTION2_QPI_RSP *pSMBr = NULL;
2643     int rc = 0;
2644     int bytes_returned;
2645     int name_len;
2646     __u16 params, byte_count;
2647     char *data_start;
2648 
2649     cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
2650 
2651 querySymLinkRetry:
2652     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2653               (void **) &pSMBr);
2654     if (rc)
2655         return rc;
2656 
2657     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2658         name_len =
2659             cifsConvertToUTF16((__le16 *) pSMB->FileName,
2660                        searchName, PATH_MAX, nls_codepage,
2661                        remap);
2662         name_len++; /* trailing null */
2663         name_len *= 2;
2664     } else {
2665         name_len = copy_path_name(pSMB->FileName, searchName);
2666     }
2667 
2668     params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2669     pSMB->TotalDataCount = 0;
2670     pSMB->MaxParameterCount = cpu_to_le16(2);
2671     pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2672     pSMB->MaxSetupCount = 0;
2673     pSMB->Reserved = 0;
2674     pSMB->Flags = 0;
2675     pSMB->Timeout = 0;
2676     pSMB->Reserved2 = 0;
2677     pSMB->ParameterOffset = cpu_to_le16(offsetof(
2678     struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2679     pSMB->DataCount = 0;
2680     pSMB->DataOffset = 0;
2681     pSMB->SetupCount = 1;
2682     pSMB->Reserved3 = 0;
2683     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2684     byte_count = params + 1 /* pad */ ;
2685     pSMB->TotalParameterCount = cpu_to_le16(params);
2686     pSMB->ParameterCount = pSMB->TotalParameterCount;
2687     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2688     pSMB->Reserved4 = 0;
2689     inc_rfc1001_len(pSMB, byte_count);
2690     pSMB->ByteCount = cpu_to_le16(byte_count);
2691 
2692     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2693              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2694     if (rc) {
2695         cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
2696     } else {
2697         /* decode response */
2698 
2699         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2700         /* BB also check enough total bytes returned */
2701         if (rc || get_bcc(&pSMBr->hdr) < 2)
2702             rc = -EIO;
2703         else {
2704             bool is_unicode;
2705             u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2706 
2707             data_start = ((char *) &pSMBr->hdr.Protocol) +
2708                        le16_to_cpu(pSMBr->t2.DataOffset);
2709 
2710             if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2711                 is_unicode = true;
2712             else
2713                 is_unicode = false;
2714 
2715             /* BB FIXME investigate remapping reserved chars here */
2716             *symlinkinfo = cifs_strndup_from_utf16(data_start,
2717                     count, is_unicode, nls_codepage);
2718             if (!*symlinkinfo)
2719                 rc = -ENOMEM;
2720         }
2721     }
2722     cifs_buf_release(pSMB);
2723     if (rc == -EAGAIN)
2724         goto querySymLinkRetry;
2725     return rc;
2726 }
2727 
2728 /*
2729  *  Recent Windows versions now create symlinks more frequently
2730  *  and they use the "reparse point" mechanism below.  We can of course
2731  *  do symlinks nicely to Samba and other servers which support the
2732  *  CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2733  *  "MF" symlinks optionally, but for recent Windows we really need to
2734  *  reenable the code below and fix the cifs_symlink callers to handle this.
2735  *  In the interim this code has been moved to its own config option so
2736  *  it is not compiled in by default until callers fixed up and more tested.
2737  */
2738 int
2739 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2740             __u16 fid, char **symlinkinfo,
2741             const struct nls_table *nls_codepage)
2742 {
2743     int rc = 0;
2744     int bytes_returned;
2745     struct smb_com_transaction_ioctl_req *pSMB;
2746     struct smb_com_transaction_ioctl_rsp *pSMBr;
2747     bool is_unicode;
2748     unsigned int sub_len;
2749     char *sub_start;
2750     struct reparse_symlink_data *reparse_buf;
2751     struct reparse_posix_data *posix_buf;
2752     __u32 data_offset, data_count;
2753     char *end_of_smb;
2754 
2755     cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
2756     rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2757               (void **) &pSMBr);
2758     if (rc)
2759         return rc;
2760 
2761     pSMB->TotalParameterCount = 0 ;
2762     pSMB->TotalDataCount = 0;
2763     pSMB->MaxParameterCount = cpu_to_le32(2);
2764     /* BB find exact data count max from sess structure BB */
2765     pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
2766     pSMB->MaxSetupCount = 4;
2767     pSMB->Reserved = 0;
2768     pSMB->ParameterOffset = 0;
2769     pSMB->DataCount = 0;
2770     pSMB->DataOffset = 0;
2771     pSMB->SetupCount = 4;
2772     pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2773     pSMB->ParameterCount = pSMB->TotalParameterCount;
2774     pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2775     pSMB->IsFsctl = 1; /* FSCTL */
2776     pSMB->IsRootFlag = 0;
2777     pSMB->Fid = fid; /* file handle always le */
2778     pSMB->ByteCount = 0;
2779 
2780     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2781              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2782     if (rc) {
2783         cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
2784         goto qreparse_out;
2785     }
2786 
2787     data_offset = le32_to_cpu(pSMBr->DataOffset);
2788     data_count = le32_to_cpu(pSMBr->DataCount);
2789     if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
2790         /* BB also check enough total bytes returned */
2791         rc = -EIO;  /* bad smb */
2792         goto qreparse_out;
2793     }
2794     if (!data_count || (data_count > 2048)) {
2795         rc = -EIO;
2796         cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
2797         goto qreparse_out;
2798     }
2799     end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
2800     reparse_buf = (struct reparse_symlink_data *)
2801                 ((char *)&pSMBr->hdr.Protocol + data_offset);
2802     if ((char *)reparse_buf >= end_of_smb) {
2803         rc = -EIO;
2804         goto qreparse_out;
2805     }
2806     if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
2807         cifs_dbg(FYI, "NFS style reparse tag\n");
2808         posix_buf =  (struct reparse_posix_data *)reparse_buf;
2809 
2810         if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
2811             cifs_dbg(FYI, "unsupported file type 0x%llx\n",
2812                  le64_to_cpu(posix_buf->InodeType));
2813             rc = -EOPNOTSUPP;
2814             goto qreparse_out;
2815         }
2816         is_unicode = true;
2817         sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
2818         if (posix_buf->PathBuffer + sub_len > end_of_smb) {
2819             cifs_dbg(FYI, "reparse buf beyond SMB\n");
2820             rc = -EIO;
2821             goto qreparse_out;
2822         }
2823         *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
2824                 sub_len, is_unicode, nls_codepage);
2825         goto qreparse_out;
2826     } else if (reparse_buf->ReparseTag !=
2827             cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
2828         rc = -EOPNOTSUPP;
2829         goto qreparse_out;
2830     }
2831 
2832     /* Reparse tag is NTFS symlink */
2833     sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
2834                 reparse_buf->PathBuffer;
2835     sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
2836     if (sub_start + sub_len > end_of_smb) {
2837         cifs_dbg(FYI, "reparse buf beyond SMB\n");
2838         rc = -EIO;
2839         goto qreparse_out;
2840     }
2841     if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2842         is_unicode = true;
2843     else
2844         is_unicode = false;
2845 
2846     /* BB FIXME investigate remapping reserved chars here */
2847     *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
2848                            nls_codepage);
2849     if (!*symlinkinfo)
2850         rc = -ENOMEM;
2851 qreparse_out:
2852     cifs_buf_release(pSMB);
2853 
2854     /*
2855      * Note: On -EAGAIN error only caller can retry on handle based calls
2856      * since file handle passed in no longer valid.
2857      */
2858     return rc;
2859 }
2860 
2861 int
2862 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
2863             __u16 fid)
2864 {
2865     int rc = 0;
2866     int bytes_returned;
2867     struct smb_com_transaction_compr_ioctl_req *pSMB;
2868     struct smb_com_transaction_ioctl_rsp *pSMBr;
2869 
2870     cifs_dbg(FYI, "Set compression for %u\n", fid);
2871     rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2872               (void **) &pSMBr);
2873     if (rc)
2874         return rc;
2875 
2876     pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
2877 
2878     pSMB->TotalParameterCount = 0;
2879     pSMB->TotalDataCount = cpu_to_le32(2);
2880     pSMB->MaxParameterCount = 0;
2881     pSMB->MaxDataCount = 0;
2882     pSMB->MaxSetupCount = 4;
2883     pSMB->Reserved = 0;
2884     pSMB->ParameterOffset = 0;
2885     pSMB->DataCount = cpu_to_le32(2);
2886     pSMB->DataOffset =
2887         cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
2888                 compression_state) - 4);  /* 84 */
2889     pSMB->SetupCount = 4;
2890     pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2891     pSMB->ParameterCount = 0;
2892     pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
2893     pSMB->IsFsctl = 1; /* FSCTL */
2894     pSMB->IsRootFlag = 0;
2895     pSMB->Fid = fid; /* file handle always le */
2896     /* 3 byte pad, followed by 2 byte compress state */
2897     pSMB->ByteCount = cpu_to_le16(5);
2898     inc_rfc1001_len(pSMB, 5);
2899 
2900     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2901              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2902     if (rc)
2903         cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
2904 
2905     cifs_buf_release(pSMB);
2906 
2907     /*
2908      * Note: On -EAGAIN error only caller can retry on handle based calls
2909      * since file handle passed in no longer valid.
2910      */
2911     return rc;
2912 }
2913 
2914 
2915 #ifdef CONFIG_CIFS_POSIX
2916 
2917 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2918 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
2919                  struct cifs_posix_ace *cifs_ace)
2920 {
2921     /* u8 cifs fields do not need le conversion */
2922     ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2923     ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
2924     ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2925 /*
2926     cifs_dbg(FYI, "perm %d tag %d id %d\n",
2927          ace->e_perm, ace->e_tag, ace->e_id);
2928 */
2929 
2930     return;
2931 }
2932 
2933 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2934 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2935                    const int acl_type, const int size_of_data_area)
2936 {
2937     int size =  0;
2938     int i;
2939     __u16 count;
2940     struct cifs_posix_ace *pACE;
2941     struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2942     struct posix_acl_xattr_header *local_acl = (void *)trgt;
2943 
2944     if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2945         return -EOPNOTSUPP;
2946 
2947     if (acl_type == ACL_TYPE_ACCESS) {
2948         count = le16_to_cpu(cifs_acl->access_entry_count);
2949         pACE = &cifs_acl->ace_array[0];
2950         size = sizeof(struct cifs_posix_acl);
2951         size += sizeof(struct cifs_posix_ace) * count;
2952         /* check if we would go beyond end of SMB */
2953         if (size_of_data_area < size) {
2954             cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
2955                  size_of_data_area, size);
2956             return -EINVAL;
2957         }
2958     } else if (acl_type == ACL_TYPE_DEFAULT) {
2959         count = le16_to_cpu(cifs_acl->access_entry_count);
2960         size = sizeof(struct cifs_posix_acl);
2961         size += sizeof(struct cifs_posix_ace) * count;
2962 /* skip past access ACEs to get to default ACEs */
2963         pACE = &cifs_acl->ace_array[count];
2964         count = le16_to_cpu(cifs_acl->default_entry_count);
2965         size += sizeof(struct cifs_posix_ace) * count;
2966         /* check if we would go beyond end of SMB */
2967         if (size_of_data_area < size)
2968             return -EINVAL;
2969     } else {
2970         /* illegal type */
2971         return -EINVAL;
2972     }
2973 
2974     size = posix_acl_xattr_size(count);
2975     if ((buflen == 0) || (local_acl == NULL)) {
2976         /* used to query ACL EA size */
2977     } else if (size > buflen) {
2978         return -ERANGE;
2979     } else /* buffer big enough */ {
2980         struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
2981 
2982         local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2983         for (i = 0; i < count ; i++) {
2984             cifs_convert_ace(&ace[i], pACE);
2985             pACE++;
2986         }
2987     }
2988     return size;
2989 }
2990 
2991 static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2992                      const struct posix_acl_xattr_entry *local_ace)
2993 {
2994     cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2995     cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
2996     /* BB is there a better way to handle the large uid? */
2997     if (local_ace->e_id == cpu_to_le32(-1)) {
2998     /* Probably no need to le convert -1 on any arch but can not hurt */
2999         cifs_ace->cifs_uid = cpu_to_le64(-1);
3000     } else
3001         cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3002 /*
3003     cifs_dbg(FYI, "perm %d tag %d id %d\n",
3004          ace->e_perm, ace->e_tag, ace->e_id);
3005 */
3006 }
3007 
3008 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3009 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3010                    const int buflen, const int acl_type)
3011 {
3012     __u16 rc = 0;
3013     struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3014     struct posix_acl_xattr_header *local_acl = (void *)pACL;
3015     struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3016     int count;
3017     int i;
3018 
3019     if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3020         return 0;
3021 
3022     count = posix_acl_xattr_count((size_t)buflen);
3023     cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3024          count, buflen, le32_to_cpu(local_acl->a_version));
3025     if (le32_to_cpu(local_acl->a_version) != 2) {
3026         cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3027              le32_to_cpu(local_acl->a_version));
3028         return 0;
3029     }
3030     cifs_acl->version = cpu_to_le16(1);
3031     if (acl_type == ACL_TYPE_ACCESS) {
3032         cifs_acl->access_entry_count = cpu_to_le16(count);
3033         cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3034     } else if (acl_type == ACL_TYPE_DEFAULT) {
3035         cifs_acl->default_entry_count = cpu_to_le16(count);
3036         cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3037     } else {
3038         cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3039         return 0;
3040     }
3041     for (i = 0; i < count; i++)
3042         convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3043     if (rc == 0) {
3044         rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3045         rc += sizeof(struct cifs_posix_acl);
3046         /* BB add check to make sure ACL does not overflow SMB */
3047     }
3048     return rc;
3049 }
3050 
3051 int
3052 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3053            const unsigned char *searchName,
3054            char *acl_inf, const int buflen, const int acl_type,
3055            const struct nls_table *nls_codepage, int remap)
3056 {
3057 /* SMB_QUERY_POSIX_ACL */
3058     TRANSACTION2_QPI_REQ *pSMB = NULL;
3059     TRANSACTION2_QPI_RSP *pSMBr = NULL;
3060     int rc = 0;
3061     int bytes_returned;
3062     int name_len;
3063     __u16 params, byte_count;
3064 
3065     cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3066 
3067 queryAclRetry:
3068     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3069         (void **) &pSMBr);
3070     if (rc)
3071         return rc;
3072 
3073     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3074         name_len =
3075             cifsConvertToUTF16((__le16 *) pSMB->FileName,
3076                        searchName, PATH_MAX, nls_codepage,
3077                        remap);
3078         name_len++;     /* trailing null */
3079         name_len *= 2;
3080         pSMB->FileName[name_len] = 0;
3081         pSMB->FileName[name_len+1] = 0;
3082     } else {
3083         name_len = copy_path_name(pSMB->FileName, searchName);
3084     }
3085 
3086     params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3087     pSMB->TotalDataCount = 0;
3088     pSMB->MaxParameterCount = cpu_to_le16(2);
3089     /* BB find exact max data count below from sess structure BB */
3090     pSMB->MaxDataCount = cpu_to_le16(4000);
3091     pSMB->MaxSetupCount = 0;
3092     pSMB->Reserved = 0;
3093     pSMB->Flags = 0;
3094     pSMB->Timeout = 0;
3095     pSMB->Reserved2 = 0;
3096     pSMB->ParameterOffset = cpu_to_le16(
3097         offsetof(struct smb_com_transaction2_qpi_req,
3098              InformationLevel) - 4);
3099     pSMB->DataCount = 0;
3100     pSMB->DataOffset = 0;
3101     pSMB->SetupCount = 1;
3102     pSMB->Reserved3 = 0;
3103     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3104     byte_count = params + 1 /* pad */ ;
3105     pSMB->TotalParameterCount = cpu_to_le16(params);
3106     pSMB->ParameterCount = pSMB->TotalParameterCount;
3107     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3108     pSMB->Reserved4 = 0;
3109     inc_rfc1001_len(pSMB, byte_count);
3110     pSMB->ByteCount = cpu_to_le16(byte_count);
3111 
3112     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3113         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3114     cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3115     if (rc) {
3116         cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3117     } else {
3118         /* decode response */
3119 
3120         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3121         /* BB also check enough total bytes returned */
3122         if (rc || get_bcc(&pSMBr->hdr) < 2)
3123             rc = -EIO;      /* bad smb */
3124         else {
3125             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3126             __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3127             rc = cifs_copy_posix_acl(acl_inf,
3128                 (char *)&pSMBr->hdr.Protocol+data_offset,
3129                 buflen, acl_type, count);
3130         }
3131     }
3132     cifs_buf_release(pSMB);
3133     if (rc == -EAGAIN)
3134         goto queryAclRetry;
3135     return rc;
3136 }
3137 
3138 int
3139 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3140            const unsigned char *fileName,
3141            const char *local_acl, const int buflen,
3142            const int acl_type,
3143            const struct nls_table *nls_codepage, int remap)
3144 {
3145     struct smb_com_transaction2_spi_req *pSMB = NULL;
3146     struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3147     char *parm_data;
3148     int name_len;
3149     int rc = 0;
3150     int bytes_returned = 0;
3151     __u16 params, byte_count, data_count, param_offset, offset;
3152 
3153     cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3154 setAclRetry:
3155     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3156               (void **) &pSMBr);
3157     if (rc)
3158         return rc;
3159     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3160         name_len =
3161             cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3162                        PATH_MAX, nls_codepage, remap);
3163         name_len++;     /* trailing null */
3164         name_len *= 2;
3165     } else {
3166         name_len = copy_path_name(pSMB->FileName, fileName);
3167     }
3168     params = 6 + name_len;
3169     pSMB->MaxParameterCount = cpu_to_le16(2);
3170     /* BB find max SMB size from sess */
3171     pSMB->MaxDataCount = cpu_to_le16(1000);
3172     pSMB->MaxSetupCount = 0;
3173     pSMB->Reserved = 0;
3174     pSMB->Flags = 0;
3175     pSMB->Timeout = 0;
3176     pSMB->Reserved2 = 0;
3177     param_offset = offsetof(struct smb_com_transaction2_spi_req,
3178                 InformationLevel) - 4;
3179     offset = param_offset + params;
3180     parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3181     pSMB->ParameterOffset = cpu_to_le16(param_offset);
3182 
3183     /* convert to on the wire format for POSIX ACL */
3184     data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3185 
3186     if (data_count == 0) {
3187         rc = -EOPNOTSUPP;
3188         goto setACLerrorExit;
3189     }
3190     pSMB->DataOffset = cpu_to_le16(offset);
3191     pSMB->SetupCount = 1;
3192     pSMB->Reserved3 = 0;
3193     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3194     pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3195     byte_count = 3 /* pad */  + params + data_count;
3196     pSMB->DataCount = cpu_to_le16(data_count);
3197     pSMB->TotalDataCount = pSMB->DataCount;
3198     pSMB->ParameterCount = cpu_to_le16(params);
3199     pSMB->TotalParameterCount = pSMB->ParameterCount;
3200     pSMB->Reserved4 = 0;
3201     inc_rfc1001_len(pSMB, byte_count);
3202     pSMB->ByteCount = cpu_to_le16(byte_count);
3203     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3204              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3205     if (rc)
3206         cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3207 
3208 setACLerrorExit:
3209     cifs_buf_release(pSMB);
3210     if (rc == -EAGAIN)
3211         goto setAclRetry;
3212     return rc;
3213 }
3214 
3215 int
3216 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3217            const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3218 {
3219     int rc = 0;
3220     struct smb_t2_qfi_req *pSMB = NULL;
3221     struct smb_t2_qfi_rsp *pSMBr = NULL;
3222     int bytes_returned;
3223     __u16 params, byte_count;
3224 
3225     cifs_dbg(FYI, "In GetExtAttr\n");
3226     if (tcon == NULL)
3227         return -ENODEV;
3228 
3229 GetExtAttrRetry:
3230     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3231               (void **) &pSMBr);
3232     if (rc)
3233         return rc;
3234 
3235     params = 2 /* level */ + 2 /* fid */;
3236     pSMB->t2.TotalDataCount = 0;
3237     pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3238     /* BB find exact max data count below from sess structure BB */
3239     pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3240     pSMB->t2.MaxSetupCount = 0;
3241     pSMB->t2.Reserved = 0;
3242     pSMB->t2.Flags = 0;
3243     pSMB->t2.Timeout = 0;
3244     pSMB->t2.Reserved2 = 0;
3245     pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3246                            Fid) - 4);
3247     pSMB->t2.DataCount = 0;
3248     pSMB->t2.DataOffset = 0;
3249     pSMB->t2.SetupCount = 1;
3250     pSMB->t2.Reserved3 = 0;
3251     pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3252     byte_count = params + 1 /* pad */ ;
3253     pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3254     pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3255     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3256     pSMB->Pad = 0;
3257     pSMB->Fid = netfid;
3258     inc_rfc1001_len(pSMB, byte_count);
3259     pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3260 
3261     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3262              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3263     if (rc) {
3264         cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3265     } else {
3266         /* decode response */
3267         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3268         /* BB also check enough total bytes returned */
3269         if (rc || get_bcc(&pSMBr->hdr) < 2)
3270             /* If rc should we check for EOPNOSUPP and
3271                disable the srvino flag? or in caller? */
3272             rc = -EIO;      /* bad smb */
3273         else {
3274             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3275             __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3276             struct file_chattr_info *pfinfo;
3277 
3278             if (count != 16) {
3279                 cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3280                 rc = -EIO;
3281                 goto GetExtAttrOut;
3282             }
3283             pfinfo = (struct file_chattr_info *)
3284                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3285             *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3286             *pMask = le64_to_cpu(pfinfo->mask);
3287         }
3288     }
3289 GetExtAttrOut:
3290     cifs_buf_release(pSMB);
3291     if (rc == -EAGAIN)
3292         goto GetExtAttrRetry;
3293     return rc;
3294 }
3295 
3296 #endif /* CONFIG_POSIX */
3297 
3298 /*
3299  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3300  * all NT TRANSACTS that we init here have total parm and data under about 400
3301  * bytes (to fit in small cifs buffer size), which is the case so far, it
3302  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3303  * returned setup area) and MaxParameterCount (returned parms size) must be set
3304  * by caller
3305  */
3306 static int
3307 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3308            const int parm_len, struct cifs_tcon *tcon,
3309            void **ret_buf)
3310 {
3311     int rc;
3312     __u32 temp_offset;
3313     struct smb_com_ntransact_req *pSMB;
3314 
3315     rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3316                 (void **)&pSMB);
3317     if (rc)
3318         return rc;
3319     *ret_buf = (void *)pSMB;
3320     pSMB->Reserved = 0;
3321     pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3322     pSMB->TotalDataCount  = 0;
3323     pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3324     pSMB->ParameterCount = pSMB->TotalParameterCount;
3325     pSMB->DataCount  = pSMB->TotalDataCount;
3326     temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3327             (setup_count * 2) - 4 /* for rfc1001 length itself */;
3328     pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3329     pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3330     pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3331     pSMB->SubCommand = cpu_to_le16(sub_command);
3332     return 0;
3333 }
3334 
3335 static int
3336 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3337            __u32 *pparmlen, __u32 *pdatalen)
3338 {
3339     char *end_of_smb;
3340     __u32 data_count, data_offset, parm_count, parm_offset;
3341     struct smb_com_ntransact_rsp *pSMBr;
3342     u16 bcc;
3343 
3344     *pdatalen = 0;
3345     *pparmlen = 0;
3346 
3347     if (buf == NULL)
3348         return -EINVAL;
3349 
3350     pSMBr = (struct smb_com_ntransact_rsp *)buf;
3351 
3352     bcc = get_bcc(&pSMBr->hdr);
3353     end_of_smb = 2 /* sizeof byte count */ + bcc +
3354             (char *)&pSMBr->ByteCount;
3355 
3356     data_offset = le32_to_cpu(pSMBr->DataOffset);
3357     data_count = le32_to_cpu(pSMBr->DataCount);
3358     parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3359     parm_count = le32_to_cpu(pSMBr->ParameterCount);
3360 
3361     *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3362     *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3363 
3364     /* should we also check that parm and data areas do not overlap? */
3365     if (*ppparm > end_of_smb) {
3366         cifs_dbg(FYI, "parms start after end of smb\n");
3367         return -EINVAL;
3368     } else if (parm_count + *ppparm > end_of_smb) {
3369         cifs_dbg(FYI, "parm end after end of smb\n");
3370         return -EINVAL;
3371     } else if (*ppdata > end_of_smb) {
3372         cifs_dbg(FYI, "data starts after end of smb\n");
3373         return -EINVAL;
3374     } else if (data_count + *ppdata > end_of_smb) {
3375         cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3376              *ppdata, data_count, (data_count + *ppdata),
3377              end_of_smb, pSMBr);
3378         return -EINVAL;
3379     } else if (parm_count + data_count > bcc) {
3380         cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3381         return -EINVAL;
3382     }
3383     *pdatalen = data_count;
3384     *pparmlen = parm_count;
3385     return 0;
3386 }
3387 
3388 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3389 int
3390 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3391           struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3392 {
3393     int rc = 0;
3394     int buf_type = 0;
3395     QUERY_SEC_DESC_REQ *pSMB;
3396     struct kvec iov[1];
3397     struct kvec rsp_iov;
3398 
3399     cifs_dbg(FYI, "GetCifsACL\n");
3400 
3401     *pbuflen = 0;
3402     *acl_inf = NULL;
3403 
3404     rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3405             8 /* parm len */, tcon, (void **) &pSMB);
3406     if (rc)
3407         return rc;
3408 
3409     pSMB->MaxParameterCount = cpu_to_le32(4);
3410     /* BB TEST with big acls that might need to be e.g. larger than 16K */
3411     pSMB->MaxSetupCount = 0;
3412     pSMB->Fid = fid; /* file handle always le */
3413     pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3414                      CIFS_ACL_DACL);
3415     pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3416     inc_rfc1001_len(pSMB, 11);
3417     iov[0].iov_base = (char *)pSMB;
3418     iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3419 
3420     rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3421               0, &rsp_iov);
3422     cifs_small_buf_release(pSMB);
3423     cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3424     if (rc) {
3425         cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3426     } else {                /* decode response */
3427         __le32 *parm;
3428         __u32 parm_len;
3429         __u32 acl_len;
3430         struct smb_com_ntransact_rsp *pSMBr;
3431         char *pdata;
3432 
3433 /* validate_nttransact */
3434         rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3435                     &pdata, &parm_len, pbuflen);
3436         if (rc)
3437             goto qsec_out;
3438         pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3439 
3440         cifs_dbg(FYI, "smb %p parm %p data %p\n",
3441              pSMBr, parm, *acl_inf);
3442 
3443         if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3444             rc = -EIO;      /* bad smb */
3445             *pbuflen = 0;
3446             goto qsec_out;
3447         }
3448 
3449 /* BB check that data area is minimum length and as big as acl_len */
3450 
3451         acl_len = le32_to_cpu(*parm);
3452         if (acl_len != *pbuflen) {
3453             cifs_dbg(VFS, "acl length %d does not match %d\n",
3454                  acl_len, *pbuflen);
3455             if (*pbuflen > acl_len)
3456                 *pbuflen = acl_len;
3457         }
3458 
3459         /* check if buffer is big enough for the acl
3460            header followed by the smallest SID */
3461         if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3462             (*pbuflen >= 64 * 1024)) {
3463             cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3464             rc = -EINVAL;
3465             *pbuflen = 0;
3466         } else {
3467             *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3468             if (*acl_inf == NULL) {
3469                 *pbuflen = 0;
3470                 rc = -ENOMEM;
3471             }
3472         }
3473     }
3474 qsec_out:
3475     free_rsp_buf(buf_type, rsp_iov.iov_base);
3476     return rc;
3477 }
3478 
3479 int
3480 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3481             struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3482 {
3483     __u16 byte_count, param_count, data_count, param_offset, data_offset;
3484     int rc = 0;
3485     int bytes_returned = 0;
3486     SET_SEC_DESC_REQ *pSMB = NULL;
3487     void *pSMBr;
3488 
3489 setCifsAclRetry:
3490     rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3491     if (rc)
3492         return rc;
3493 
3494     pSMB->MaxSetupCount = 0;
3495     pSMB->Reserved = 0;
3496 
3497     param_count = 8;
3498     param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3499     data_count = acllen;
3500     data_offset = param_offset + param_count;
3501     byte_count = 3 /* pad */  + param_count;
3502 
3503     pSMB->DataCount = cpu_to_le32(data_count);
3504     pSMB->TotalDataCount = pSMB->DataCount;
3505     pSMB->MaxParameterCount = cpu_to_le32(4);
3506     pSMB->MaxDataCount = cpu_to_le32(16384);
3507     pSMB->ParameterCount = cpu_to_le32(param_count);
3508     pSMB->ParameterOffset = cpu_to_le32(param_offset);
3509     pSMB->TotalParameterCount = pSMB->ParameterCount;
3510     pSMB->DataOffset = cpu_to_le32(data_offset);
3511     pSMB->SetupCount = 0;
3512     pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3513     pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3514 
3515     pSMB->Fid = fid; /* file handle always le */
3516     pSMB->Reserved2 = 0;
3517     pSMB->AclFlags = cpu_to_le32(aclflag);
3518 
3519     if (pntsd && acllen) {
3520         memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3521                 data_offset, pntsd, acllen);
3522         inc_rfc1001_len(pSMB, byte_count + data_count);
3523     } else
3524         inc_rfc1001_len(pSMB, byte_count);
3525 
3526     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3527         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3528 
3529     cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3530          bytes_returned, rc);
3531     if (rc)
3532         cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3533     cifs_buf_release(pSMB);
3534 
3535     if (rc == -EAGAIN)
3536         goto setCifsAclRetry;
3537 
3538     return (rc);
3539 }
3540 
3541 
3542 /* Legacy Query Path Information call for lookup to old servers such
3543    as Win9x/WinME */
3544 int
3545 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3546             const char *search_name, FILE_ALL_INFO *data,
3547             const struct nls_table *nls_codepage, int remap)
3548 {
3549     QUERY_INFORMATION_REQ *pSMB;
3550     QUERY_INFORMATION_RSP *pSMBr;
3551     int rc = 0;
3552     int bytes_returned;
3553     int name_len;
3554 
3555     cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3556 QInfRetry:
3557     rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3558               (void **) &pSMBr);
3559     if (rc)
3560         return rc;
3561 
3562     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3563         name_len =
3564             cifsConvertToUTF16((__le16 *) pSMB->FileName,
3565                        search_name, PATH_MAX, nls_codepage,
3566                        remap);
3567         name_len++;     /* trailing null */
3568         name_len *= 2;
3569     } else {
3570         name_len = copy_path_name(pSMB->FileName, search_name);
3571     }
3572     pSMB->BufferFormat = 0x04;
3573     name_len++; /* account for buffer type byte */
3574     inc_rfc1001_len(pSMB, (__u16)name_len);
3575     pSMB->ByteCount = cpu_to_le16(name_len);
3576 
3577     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3578              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3579     if (rc) {
3580         cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
3581     } else if (data) {
3582         struct timespec64 ts;
3583         __u32 time = le32_to_cpu(pSMBr->last_write_time);
3584 
3585         /* decode response */
3586         /* BB FIXME - add time zone adjustment BB */
3587         memset(data, 0, sizeof(FILE_ALL_INFO));
3588         ts.tv_nsec = 0;
3589         ts.tv_sec = time;
3590         /* decode time fields */
3591         data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3592         data->LastWriteTime = data->ChangeTime;
3593         data->LastAccessTime = 0;
3594         data->AllocationSize =
3595             cpu_to_le64(le32_to_cpu(pSMBr->size));
3596         data->EndOfFile = data->AllocationSize;
3597         data->Attributes =
3598             cpu_to_le32(le16_to_cpu(pSMBr->attr));
3599     } else
3600         rc = -EIO; /* bad buffer passed in */
3601 
3602     cifs_buf_release(pSMB);
3603 
3604     if (rc == -EAGAIN)
3605         goto QInfRetry;
3606 
3607     return rc;
3608 }
3609 
3610 int
3611 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3612          u16 netfid, FILE_ALL_INFO *pFindData)
3613 {
3614     struct smb_t2_qfi_req *pSMB = NULL;
3615     struct smb_t2_qfi_rsp *pSMBr = NULL;
3616     int rc = 0;
3617     int bytes_returned;
3618     __u16 params, byte_count;
3619 
3620 QFileInfoRetry:
3621     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3622               (void **) &pSMBr);
3623     if (rc)
3624         return rc;
3625 
3626     params = 2 /* level */ + 2 /* fid */;
3627     pSMB->t2.TotalDataCount = 0;
3628     pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3629     /* BB find exact max data count below from sess structure BB */
3630     pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3631     pSMB->t2.MaxSetupCount = 0;
3632     pSMB->t2.Reserved = 0;
3633     pSMB->t2.Flags = 0;
3634     pSMB->t2.Timeout = 0;
3635     pSMB->t2.Reserved2 = 0;
3636     pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3637                            Fid) - 4);
3638     pSMB->t2.DataCount = 0;
3639     pSMB->t2.DataOffset = 0;
3640     pSMB->t2.SetupCount = 1;
3641     pSMB->t2.Reserved3 = 0;
3642     pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3643     byte_count = params + 1 /* pad */ ;
3644     pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3645     pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3646     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3647     pSMB->Pad = 0;
3648     pSMB->Fid = netfid;
3649     inc_rfc1001_len(pSMB, byte_count);
3650     pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3651 
3652     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3653              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3654     if (rc) {
3655         cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
3656     } else {        /* decode response */
3657         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3658 
3659         if (rc) /* BB add auto retry on EOPNOTSUPP? */
3660             rc = -EIO;
3661         else if (get_bcc(&pSMBr->hdr) < 40)
3662             rc = -EIO;  /* bad smb */
3663         else if (pFindData) {
3664             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3665             memcpy((char *) pFindData,
3666                    (char *) &pSMBr->hdr.Protocol +
3667                    data_offset, sizeof(FILE_ALL_INFO));
3668         } else
3669             rc = -ENOMEM;
3670     }
3671     cifs_buf_release(pSMB);
3672     if (rc == -EAGAIN)
3673         goto QFileInfoRetry;
3674 
3675     return rc;
3676 }
3677 
3678 int
3679 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3680          const char *search_name, FILE_ALL_INFO *data,
3681          int legacy /* old style infolevel */,
3682          const struct nls_table *nls_codepage, int remap)
3683 {
3684     /* level 263 SMB_QUERY_FILE_ALL_INFO */
3685     TRANSACTION2_QPI_REQ *pSMB = NULL;
3686     TRANSACTION2_QPI_RSP *pSMBr = NULL;
3687     int rc = 0;
3688     int bytes_returned;
3689     int name_len;
3690     __u16 params, byte_count;
3691 
3692     /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
3693 QPathInfoRetry:
3694     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3695               (void **) &pSMBr);
3696     if (rc)
3697         return rc;
3698 
3699     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3700         name_len =
3701             cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
3702                        PATH_MAX, nls_codepage, remap);
3703         name_len++; /* trailing null */
3704         name_len *= 2;
3705     } else {
3706         name_len = copy_path_name(pSMB->FileName, search_name);
3707     }
3708 
3709     params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3710     pSMB->TotalDataCount = 0;
3711     pSMB->MaxParameterCount = cpu_to_le16(2);
3712     /* BB find exact max SMB PDU from sess structure BB */
3713     pSMB->MaxDataCount = cpu_to_le16(4000);
3714     pSMB->MaxSetupCount = 0;
3715     pSMB->Reserved = 0;
3716     pSMB->Flags = 0;
3717     pSMB->Timeout = 0;
3718     pSMB->Reserved2 = 0;
3719     pSMB->ParameterOffset = cpu_to_le16(offsetof(
3720     struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3721     pSMB->DataCount = 0;
3722     pSMB->DataOffset = 0;
3723     pSMB->SetupCount = 1;
3724     pSMB->Reserved3 = 0;
3725     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3726     byte_count = params + 1 /* pad */ ;
3727     pSMB->TotalParameterCount = cpu_to_le16(params);
3728     pSMB->ParameterCount = pSMB->TotalParameterCount;
3729     if (legacy)
3730         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3731     else
3732         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3733     pSMB->Reserved4 = 0;
3734     inc_rfc1001_len(pSMB, byte_count);
3735     pSMB->ByteCount = cpu_to_le16(byte_count);
3736 
3737     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3738              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3739     if (rc) {
3740         cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
3741     } else {        /* decode response */
3742         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3743 
3744         if (rc) /* BB add auto retry on EOPNOTSUPP? */
3745             rc = -EIO;
3746         else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
3747             rc = -EIO;  /* bad smb */
3748         else if (legacy && get_bcc(&pSMBr->hdr) < 24)
3749             rc = -EIO;  /* 24 or 26 expected but we do not read
3750                     last field */
3751         else if (data) {
3752             int size;
3753             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3754 
3755             /*
3756              * On legacy responses we do not read the last field,
3757              * EAsize, fortunately since it varies by subdialect and
3758              * also note it differs on Set vs Get, ie two bytes or 4
3759              * bytes depending but we don't care here.
3760              */
3761             if (legacy)
3762                 size = sizeof(FILE_INFO_STANDARD);
3763             else
3764                 size = sizeof(FILE_ALL_INFO);
3765             memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
3766                    data_offset, size);
3767         } else
3768             rc = -ENOMEM;
3769     }
3770     cifs_buf_release(pSMB);
3771     if (rc == -EAGAIN)
3772         goto QPathInfoRetry;
3773 
3774     return rc;
3775 }
3776 
3777 int
3778 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3779          u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3780 {
3781     struct smb_t2_qfi_req *pSMB = NULL;
3782     struct smb_t2_qfi_rsp *pSMBr = NULL;
3783     int rc = 0;
3784     int bytes_returned;
3785     __u16 params, byte_count;
3786 
3787 UnixQFileInfoRetry:
3788     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3789               (void **) &pSMBr);
3790     if (rc)
3791         return rc;
3792 
3793     params = 2 /* level */ + 2 /* fid */;
3794     pSMB->t2.TotalDataCount = 0;
3795     pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3796     /* BB find exact max data count below from sess structure BB */
3797     pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3798     pSMB->t2.MaxSetupCount = 0;
3799     pSMB->t2.Reserved = 0;
3800     pSMB->t2.Flags = 0;
3801     pSMB->t2.Timeout = 0;
3802     pSMB->t2.Reserved2 = 0;
3803     pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3804                            Fid) - 4);
3805     pSMB->t2.DataCount = 0;
3806     pSMB->t2.DataOffset = 0;
3807     pSMB->t2.SetupCount = 1;
3808     pSMB->t2.Reserved3 = 0;
3809     pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3810     byte_count = params + 1 /* pad */ ;
3811     pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3812     pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3813     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3814     pSMB->Pad = 0;
3815     pSMB->Fid = netfid;
3816     inc_rfc1001_len(pSMB, byte_count);
3817     pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3818 
3819     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3820              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3821     if (rc) {
3822         cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
3823     } else {        /* decode response */
3824         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3825 
3826         if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3827             cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
3828             rc = -EIO;  /* bad smb */
3829         } else {
3830             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3831             memcpy((char *) pFindData,
3832                    (char *) &pSMBr->hdr.Protocol +
3833                    data_offset,
3834                    sizeof(FILE_UNIX_BASIC_INFO));
3835         }
3836     }
3837 
3838     cifs_buf_release(pSMB);
3839     if (rc == -EAGAIN)
3840         goto UnixQFileInfoRetry;
3841 
3842     return rc;
3843 }
3844 
3845 int
3846 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3847              const unsigned char *searchName,
3848              FILE_UNIX_BASIC_INFO *pFindData,
3849              const struct nls_table *nls_codepage, int remap)
3850 {
3851 /* SMB_QUERY_FILE_UNIX_BASIC */
3852     TRANSACTION2_QPI_REQ *pSMB = NULL;
3853     TRANSACTION2_QPI_RSP *pSMBr = NULL;
3854     int rc = 0;
3855     int bytes_returned = 0;
3856     int name_len;
3857     __u16 params, byte_count;
3858 
3859     cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
3860 UnixQPathInfoRetry:
3861     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3862               (void **) &pSMBr);
3863     if (rc)
3864         return rc;
3865 
3866     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3867         name_len =
3868             cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3869                        PATH_MAX, nls_codepage, remap);
3870         name_len++; /* trailing null */
3871         name_len *= 2;
3872     } else {
3873         name_len = copy_path_name(pSMB->FileName, searchName);
3874     }
3875 
3876     params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3877     pSMB->TotalDataCount = 0;
3878     pSMB->MaxParameterCount = cpu_to_le16(2);
3879     /* BB find exact max SMB PDU from sess structure BB */
3880     pSMB->MaxDataCount = cpu_to_le16(4000);
3881     pSMB->MaxSetupCount = 0;
3882     pSMB->Reserved = 0;
3883     pSMB->Flags = 0;
3884     pSMB->Timeout = 0;
3885     pSMB->Reserved2 = 0;
3886     pSMB->ParameterOffset = cpu_to_le16(offsetof(
3887     struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3888     pSMB->DataCount = 0;
3889     pSMB->DataOffset = 0;
3890     pSMB->SetupCount = 1;
3891     pSMB->Reserved3 = 0;
3892     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3893     byte_count = params + 1 /* pad */ ;
3894     pSMB->TotalParameterCount = cpu_to_le16(params);
3895     pSMB->ParameterCount = pSMB->TotalParameterCount;
3896     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3897     pSMB->Reserved4 = 0;
3898     inc_rfc1001_len(pSMB, byte_count);
3899     pSMB->ByteCount = cpu_to_le16(byte_count);
3900 
3901     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3902              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3903     if (rc) {
3904         cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
3905     } else {        /* decode response */
3906         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3907 
3908         if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3909             cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
3910             rc = -EIO;  /* bad smb */
3911         } else {
3912             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3913             memcpy((char *) pFindData,
3914                    (char *) &pSMBr->hdr.Protocol +
3915                    data_offset,
3916                    sizeof(FILE_UNIX_BASIC_INFO));
3917         }
3918     }
3919     cifs_buf_release(pSMB);
3920     if (rc == -EAGAIN)
3921         goto UnixQPathInfoRetry;
3922 
3923     return rc;
3924 }
3925 
3926 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3927 int
3928 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
3929           const char *searchName, struct cifs_sb_info *cifs_sb,
3930           __u16 *pnetfid, __u16 search_flags,
3931           struct cifs_search_info *psrch_inf, bool msearch)
3932 {
3933 /* level 257 SMB_ */
3934     TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3935     TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3936     T2_FFIRST_RSP_PARMS *parms;
3937     int rc = 0;
3938     int bytes_returned = 0;
3939     int name_len, remap;
3940     __u16 params, byte_count;
3941     struct nls_table *nls_codepage;
3942 
3943     cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
3944 
3945 findFirstRetry:
3946     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3947               (void **) &pSMBr);
3948     if (rc)
3949         return rc;
3950 
3951     nls_codepage = cifs_sb->local_nls;
3952     remap = cifs_remap(cifs_sb);
3953 
3954     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3955         name_len =
3956             cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3957                        PATH_MAX, nls_codepage, remap);
3958         /* We can not add the asterik earlier in case
3959         it got remapped to 0xF03A as if it were part of the
3960         directory name instead of a wildcard */
3961         name_len *= 2;
3962         if (msearch) {
3963             pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
3964             pSMB->FileName[name_len+1] = 0;
3965             pSMB->FileName[name_len+2] = '*';
3966             pSMB->FileName[name_len+3] = 0;
3967             name_len += 4; /* now the trailing null */
3968             /* null terminate just in case */
3969             pSMB->FileName[name_len] = 0;
3970             pSMB->FileName[name_len+1] = 0;
3971             name_len += 2;
3972         }
3973     } else {
3974         name_len = copy_path_name(pSMB->FileName, searchName);
3975         if (msearch) {
3976             if (WARN_ON_ONCE(name_len > PATH_MAX-2))
3977                 name_len = PATH_MAX-2;
3978             /* overwrite nul byte */
3979             pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
3980             pSMB->FileName[name_len] = '*';
3981             pSMB->FileName[name_len+1] = 0;
3982             name_len += 2;
3983         }
3984     }
3985 
3986     params = 12 + name_len /* includes null */ ;
3987     pSMB->TotalDataCount = 0;   /* no EAs */
3988     pSMB->MaxParameterCount = cpu_to_le16(10);
3989     pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
3990     pSMB->MaxSetupCount = 0;
3991     pSMB->Reserved = 0;
3992     pSMB->Flags = 0;
3993     pSMB->Timeout = 0;
3994     pSMB->Reserved2 = 0;
3995     byte_count = params + 1 /* pad */ ;
3996     pSMB->TotalParameterCount = cpu_to_le16(params);
3997     pSMB->ParameterCount = pSMB->TotalParameterCount;
3998     pSMB->ParameterOffset = cpu_to_le16(
3999           offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4000         - 4);
4001     pSMB->DataCount = 0;
4002     pSMB->DataOffset = 0;
4003     pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4004     pSMB->Reserved3 = 0;
4005     pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4006     pSMB->SearchAttributes =
4007         cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4008             ATTR_DIRECTORY);
4009     pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4010     pSMB->SearchFlags = cpu_to_le16(search_flags);
4011     pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4012 
4013     /* BB what should we set StorageType to? Does it matter? BB */
4014     pSMB->SearchStorageType = 0;
4015     inc_rfc1001_len(pSMB, byte_count);
4016     pSMB->ByteCount = cpu_to_le16(byte_count);
4017 
4018     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4019              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4020     cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4021 
4022     if (rc) {/* BB add logic to retry regular search if Unix search
4023             rejected unexpectedly by server */
4024         /* BB Add code to handle unsupported level rc */
4025         cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4026 
4027         cifs_buf_release(pSMB);
4028 
4029         /* BB eventually could optimize out free and realloc of buf */
4030         /*    for this case */
4031         if (rc == -EAGAIN)
4032             goto findFirstRetry;
4033     } else { /* decode response */
4034         /* BB remember to free buffer if error BB */
4035         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4036         if (rc == 0) {
4037             unsigned int lnoff;
4038 
4039             if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4040                 psrch_inf->unicode = true;
4041             else
4042                 psrch_inf->unicode = false;
4043 
4044             psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4045             psrch_inf->smallBuf = false;
4046             psrch_inf->srch_entries_start =
4047                 (char *) &pSMBr->hdr.Protocol +
4048                     le16_to_cpu(pSMBr->t2.DataOffset);
4049             parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4050                    le16_to_cpu(pSMBr->t2.ParameterOffset));
4051 
4052             if (parms->EndofSearch)
4053                 psrch_inf->endOfSearch = true;
4054             else
4055                 psrch_inf->endOfSearch = false;
4056 
4057             psrch_inf->entries_in_buffer =
4058                     le16_to_cpu(parms->SearchCount);
4059             psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4060                 psrch_inf->entries_in_buffer;
4061             lnoff = le16_to_cpu(parms->LastNameOffset);
4062             if (CIFSMaxBufSize < lnoff) {
4063                 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4064                 psrch_inf->last_entry = NULL;
4065                 return rc;
4066             }
4067 
4068             psrch_inf->last_entry = psrch_inf->srch_entries_start +
4069                             lnoff;
4070 
4071             if (pnetfid)
4072                 *pnetfid = parms->SearchHandle;
4073         } else {
4074             cifs_buf_release(pSMB);
4075         }
4076     }
4077 
4078     return rc;
4079 }
4080 
4081 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4082          __u16 searchHandle, __u16 search_flags,
4083          struct cifs_search_info *psrch_inf)
4084 {
4085     TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4086     TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4087     T2_FNEXT_RSP_PARMS *parms;
4088     char *response_data;
4089     int rc = 0;
4090     int bytes_returned;
4091     unsigned int name_len;
4092     __u16 params, byte_count;
4093 
4094     cifs_dbg(FYI, "In FindNext\n");
4095 
4096     if (psrch_inf->endOfSearch)
4097         return -ENOENT;
4098 
4099     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4100         (void **) &pSMBr);
4101     if (rc)
4102         return rc;
4103 
4104     params = 14; /* includes 2 bytes of null string, converted to LE below*/
4105     byte_count = 0;
4106     pSMB->TotalDataCount = 0;       /* no EAs */
4107     pSMB->MaxParameterCount = cpu_to_le16(8);
4108     pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4109     pSMB->MaxSetupCount = 0;
4110     pSMB->Reserved = 0;
4111     pSMB->Flags = 0;
4112     pSMB->Timeout = 0;
4113     pSMB->Reserved2 = 0;
4114     pSMB->ParameterOffset =  cpu_to_le16(
4115           offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4116     pSMB->DataCount = 0;
4117     pSMB->DataOffset = 0;
4118     pSMB->SetupCount = 1;
4119     pSMB->Reserved3 = 0;
4120     pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4121     pSMB->SearchHandle = searchHandle;      /* always kept as le */
4122     pSMB->SearchCount =
4123         cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4124     pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4125     pSMB->ResumeKey = psrch_inf->resume_key;
4126     pSMB->SearchFlags = cpu_to_le16(search_flags);
4127 
4128     name_len = psrch_inf->resume_name_len;
4129     params += name_len;
4130     if (name_len < PATH_MAX) {
4131         memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4132         byte_count += name_len;
4133         /* 14 byte parm len above enough for 2 byte null terminator */
4134         pSMB->ResumeFileName[name_len] = 0;
4135         pSMB->ResumeFileName[name_len+1] = 0;
4136     } else {
4137         rc = -EINVAL;
4138         goto FNext2_err_exit;
4139     }
4140     byte_count = params + 1 /* pad */ ;
4141     pSMB->TotalParameterCount = cpu_to_le16(params);
4142     pSMB->ParameterCount = pSMB->TotalParameterCount;
4143     inc_rfc1001_len(pSMB, byte_count);
4144     pSMB->ByteCount = cpu_to_le16(byte_count);
4145 
4146     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4147             (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4148     cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4149     if (rc) {
4150         if (rc == -EBADF) {
4151             psrch_inf->endOfSearch = true;
4152             cifs_buf_release(pSMB);
4153             rc = 0; /* search probably was closed at end of search*/
4154         } else
4155             cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4156     } else {                /* decode response */
4157         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4158 
4159         if (rc == 0) {
4160             unsigned int lnoff;
4161 
4162             /* BB fixme add lock for file (srch_info) struct here */
4163             if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4164                 psrch_inf->unicode = true;
4165             else
4166                 psrch_inf->unicode = false;
4167             response_data = (char *) &pSMBr->hdr.Protocol +
4168                    le16_to_cpu(pSMBr->t2.ParameterOffset);
4169             parms = (T2_FNEXT_RSP_PARMS *)response_data;
4170             response_data = (char *)&pSMBr->hdr.Protocol +
4171                 le16_to_cpu(pSMBr->t2.DataOffset);
4172             if (psrch_inf->smallBuf)
4173                 cifs_small_buf_release(
4174                     psrch_inf->ntwrk_buf_start);
4175             else
4176                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4177             psrch_inf->srch_entries_start = response_data;
4178             psrch_inf->ntwrk_buf_start = (char *)pSMB;
4179             psrch_inf->smallBuf = false;
4180             if (parms->EndofSearch)
4181                 psrch_inf->endOfSearch = true;
4182             else
4183                 psrch_inf->endOfSearch = false;
4184             psrch_inf->entries_in_buffer =
4185                         le16_to_cpu(parms->SearchCount);
4186             psrch_inf->index_of_last_entry +=
4187                 psrch_inf->entries_in_buffer;
4188             lnoff = le16_to_cpu(parms->LastNameOffset);
4189             if (CIFSMaxBufSize < lnoff) {
4190                 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4191                 psrch_inf->last_entry = NULL;
4192                 return rc;
4193             } else
4194                 psrch_inf->last_entry =
4195                     psrch_inf->srch_entries_start + lnoff;
4196 
4197 /*  cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4198     psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4199 
4200             /* BB fixme add unlock here */
4201         }
4202 
4203     }
4204 
4205     /* BB On error, should we leave previous search buf (and count and
4206     last entry fields) intact or free the previous one? */
4207 
4208     /* Note: On -EAGAIN error only caller can retry on handle based calls
4209     since file handle passed in no longer valid */
4210 FNext2_err_exit:
4211     if (rc != 0)
4212         cifs_buf_release(pSMB);
4213     return rc;
4214 }
4215 
4216 int
4217 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4218           const __u16 searchHandle)
4219 {
4220     int rc = 0;
4221     FINDCLOSE_REQ *pSMB = NULL;
4222 
4223     cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4224     rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4225 
4226     /* no sense returning error if session restarted
4227         as file handle has been closed */
4228     if (rc == -EAGAIN)
4229         return 0;
4230     if (rc)
4231         return rc;
4232 
4233     pSMB->FileID = searchHandle;
4234     pSMB->ByteCount = 0;
4235     rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4236     cifs_small_buf_release(pSMB);
4237     if (rc)
4238         cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4239 
4240     cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4241 
4242     /* Since session is dead, search handle closed on server already */
4243     if (rc == -EAGAIN)
4244         rc = 0;
4245 
4246     return rc;
4247 }
4248 
4249 int
4250 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4251               const char *search_name, __u64 *inode_number,
4252               const struct nls_table *nls_codepage, int remap)
4253 {
4254     int rc = 0;
4255     TRANSACTION2_QPI_REQ *pSMB = NULL;
4256     TRANSACTION2_QPI_RSP *pSMBr = NULL;
4257     int name_len, bytes_returned;
4258     __u16 params, byte_count;
4259 
4260     cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4261     if (tcon == NULL)
4262         return -ENODEV;
4263 
4264 GetInodeNumberRetry:
4265     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4266               (void **) &pSMBr);
4267     if (rc)
4268         return rc;
4269 
4270     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4271         name_len =
4272             cifsConvertToUTF16((__le16 *) pSMB->FileName,
4273                        search_name, PATH_MAX, nls_codepage,
4274                        remap);
4275         name_len++;     /* trailing null */
4276         name_len *= 2;
4277     } else {
4278         name_len = copy_path_name(pSMB->FileName, search_name);
4279     }
4280 
4281     params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4282     pSMB->TotalDataCount = 0;
4283     pSMB->MaxParameterCount = cpu_to_le16(2);
4284     /* BB find exact max data count below from sess structure BB */
4285     pSMB->MaxDataCount = cpu_to_le16(4000);
4286     pSMB->MaxSetupCount = 0;
4287     pSMB->Reserved = 0;
4288     pSMB->Flags = 0;
4289     pSMB->Timeout = 0;
4290     pSMB->Reserved2 = 0;
4291     pSMB->ParameterOffset = cpu_to_le16(offsetof(
4292         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4293     pSMB->DataCount = 0;
4294     pSMB->DataOffset = 0;
4295     pSMB->SetupCount = 1;
4296     pSMB->Reserved3 = 0;
4297     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4298     byte_count = params + 1 /* pad */ ;
4299     pSMB->TotalParameterCount = cpu_to_le16(params);
4300     pSMB->ParameterCount = pSMB->TotalParameterCount;
4301     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4302     pSMB->Reserved4 = 0;
4303     inc_rfc1001_len(pSMB, byte_count);
4304     pSMB->ByteCount = cpu_to_le16(byte_count);
4305 
4306     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4307         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4308     if (rc) {
4309         cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4310     } else {
4311         /* decode response */
4312         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4313         /* BB also check enough total bytes returned */
4314         if (rc || get_bcc(&pSMBr->hdr) < 2)
4315             /* If rc should we check for EOPNOSUPP and
4316             disable the srvino flag? or in caller? */
4317             rc = -EIO;      /* bad smb */
4318         else {
4319             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4320             __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4321             struct file_internal_info *pfinfo;
4322             /* BB Do we need a cast or hash here ? */
4323             if (count < 8) {
4324                 cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4325                 rc = -EIO;
4326                 goto GetInodeNumOut;
4327             }
4328             pfinfo = (struct file_internal_info *)
4329                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4330             *inode_number = le64_to_cpu(pfinfo->UniqueId);
4331         }
4332     }
4333 GetInodeNumOut:
4334     cifs_buf_release(pSMB);
4335     if (rc == -EAGAIN)
4336         goto GetInodeNumberRetry;
4337     return rc;
4338 }
4339 
4340 int
4341 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4342         const char *search_name, struct dfs_info3_param **target_nodes,
4343         unsigned int *num_of_nodes,
4344         const struct nls_table *nls_codepage, int remap)
4345 {
4346 /* TRANS2_GET_DFS_REFERRAL */
4347     TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4348     TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4349     int rc = 0;
4350     int bytes_returned;
4351     int name_len;
4352     __u16 params, byte_count;
4353     *num_of_nodes = 0;
4354     *target_nodes = NULL;
4355 
4356     cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4357     if (ses == NULL || ses->tcon_ipc == NULL)
4358         return -ENODEV;
4359 
4360 getDFSRetry:
4361     rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4362               (void **) &pSMBr);
4363     if (rc)
4364         return rc;
4365 
4366     /* server pointer checked in called function,
4367     but should never be null here anyway */
4368     pSMB->hdr.Mid = get_next_mid(ses->server);
4369     pSMB->hdr.Tid = ses->tcon_ipc->tid;
4370     pSMB->hdr.Uid = ses->Suid;
4371     if (ses->capabilities & CAP_STATUS32)
4372         pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4373     if (ses->capabilities & CAP_DFS)
4374         pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4375 
4376     if (ses->capabilities & CAP_UNICODE) {
4377         pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4378         name_len =
4379             cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4380                        search_name, PATH_MAX, nls_codepage,
4381                        remap);
4382         name_len++; /* trailing null */
4383         name_len *= 2;
4384     } else {    /* BB improve the check for buffer overruns BB */
4385         name_len = copy_path_name(pSMB->RequestFileName, search_name);
4386     }
4387 
4388     if (ses->server->sign)
4389         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4390 
4391     pSMB->hdr.Uid = ses->Suid;
4392 
4393     params = 2 /* level */  + name_len /*includes null */ ;
4394     pSMB->TotalDataCount = 0;
4395     pSMB->DataCount = 0;
4396     pSMB->DataOffset = 0;
4397     pSMB->MaxParameterCount = 0;
4398     /* BB find exact max SMB PDU from sess structure BB */
4399     pSMB->MaxDataCount = cpu_to_le16(4000);
4400     pSMB->MaxSetupCount = 0;
4401     pSMB->Reserved = 0;
4402     pSMB->Flags = 0;
4403     pSMB->Timeout = 0;
4404     pSMB->Reserved2 = 0;
4405     pSMB->ParameterOffset = cpu_to_le16(offsetof(
4406       struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4407     pSMB->SetupCount = 1;
4408     pSMB->Reserved3 = 0;
4409     pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4410     byte_count = params + 3 /* pad */ ;
4411     pSMB->ParameterCount = cpu_to_le16(params);
4412     pSMB->TotalParameterCount = pSMB->ParameterCount;
4413     pSMB->MaxReferralLevel = cpu_to_le16(3);
4414     inc_rfc1001_len(pSMB, byte_count);
4415     pSMB->ByteCount = cpu_to_le16(byte_count);
4416 
4417     rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4418              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4419     if (rc) {
4420         cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4421         goto GetDFSRefExit;
4422     }
4423     rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4424 
4425     /* BB Also check if enough total bytes returned? */
4426     if (rc || get_bcc(&pSMBr->hdr) < 17) {
4427         rc = -EIO;      /* bad smb */
4428         goto GetDFSRefExit;
4429     }
4430 
4431     cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
4432          get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4433 
4434     /* parse returned result into more usable form */
4435     rc = parse_dfs_referrals(&pSMBr->dfs_data,
4436                  le16_to_cpu(pSMBr->t2.DataCount),
4437                  num_of_nodes, target_nodes, nls_codepage,
4438                  remap, search_name,
4439                  (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4440 
4441 GetDFSRefExit:
4442     cifs_buf_release(pSMB);
4443 
4444     if (rc == -EAGAIN)
4445         goto getDFSRetry;
4446 
4447     return rc;
4448 }
4449 
4450 /* Query File System Info such as free space to old servers such as Win 9x */
4451 int
4452 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4453           struct kstatfs *FSData)
4454 {
4455 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4456     TRANSACTION2_QFSI_REQ *pSMB = NULL;
4457     TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4458     FILE_SYSTEM_ALLOC_INFO *response_data;
4459     int rc = 0;
4460     int bytes_returned = 0;
4461     __u16 params, byte_count;
4462 
4463     cifs_dbg(FYI, "OldQFSInfo\n");
4464 oldQFSInfoRetry:
4465     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4466         (void **) &pSMBr);
4467     if (rc)
4468         return rc;
4469 
4470     params = 2;     /* level */
4471     pSMB->TotalDataCount = 0;
4472     pSMB->MaxParameterCount = cpu_to_le16(2);
4473     pSMB->MaxDataCount = cpu_to_le16(1000);
4474     pSMB->MaxSetupCount = 0;
4475     pSMB->Reserved = 0;
4476     pSMB->Flags = 0;
4477     pSMB->Timeout = 0;
4478     pSMB->Reserved2 = 0;
4479     byte_count = params + 1 /* pad */ ;
4480     pSMB->TotalParameterCount = cpu_to_le16(params);
4481     pSMB->ParameterCount = pSMB->TotalParameterCount;
4482     pSMB->ParameterOffset = cpu_to_le16(offsetof(
4483     struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4484     pSMB->DataCount = 0;
4485     pSMB->DataOffset = 0;
4486     pSMB->SetupCount = 1;
4487     pSMB->Reserved3 = 0;
4488     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4489     pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4490     inc_rfc1001_len(pSMB, byte_count);
4491     pSMB->ByteCount = cpu_to_le16(byte_count);
4492 
4493     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4494         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4495     if (rc) {
4496         cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4497     } else {                /* decode response */
4498         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4499 
4500         if (rc || get_bcc(&pSMBr->hdr) < 18)
4501             rc = -EIO;      /* bad smb */
4502         else {
4503             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4504             cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
4505                  get_bcc(&pSMBr->hdr), data_offset);
4506 
4507             response_data = (FILE_SYSTEM_ALLOC_INFO *)
4508                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4509             FSData->f_bsize =
4510                 le16_to_cpu(response_data->BytesPerSector) *
4511                 le32_to_cpu(response_data->
4512                     SectorsPerAllocationUnit);
4513             /*
4514              * much prefer larger but if server doesn't report
4515              * a valid size than 4K is a reasonable minimum
4516              */
4517             if (FSData->f_bsize < 512)
4518                 FSData->f_bsize = 4096;
4519 
4520             FSData->f_blocks =
4521                    le32_to_cpu(response_data->TotalAllocationUnits);
4522             FSData->f_bfree = FSData->f_bavail =
4523                 le32_to_cpu(response_data->FreeAllocationUnits);
4524             cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4525                  (unsigned long long)FSData->f_blocks,
4526                  (unsigned long long)FSData->f_bfree,
4527                  FSData->f_bsize);
4528         }
4529     }
4530     cifs_buf_release(pSMB);
4531 
4532     if (rc == -EAGAIN)
4533         goto oldQFSInfoRetry;
4534 
4535     return rc;
4536 }
4537 
4538 int
4539 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4540            struct kstatfs *FSData)
4541 {
4542 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4543     TRANSACTION2_QFSI_REQ *pSMB = NULL;
4544     TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4545     FILE_SYSTEM_INFO *response_data;
4546     int rc = 0;
4547     int bytes_returned = 0;
4548     __u16 params, byte_count;
4549 
4550     cifs_dbg(FYI, "In QFSInfo\n");
4551 QFSInfoRetry:
4552     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4553               (void **) &pSMBr);
4554     if (rc)
4555         return rc;
4556 
4557     params = 2; /* level */
4558     pSMB->TotalDataCount = 0;
4559     pSMB->MaxParameterCount = cpu_to_le16(2);
4560     pSMB->MaxDataCount = cpu_to_le16(1000);
4561     pSMB->MaxSetupCount = 0;
4562     pSMB->Reserved = 0;
4563     pSMB->Flags = 0;
4564     pSMB->Timeout = 0;
4565     pSMB->Reserved2 = 0;
4566     byte_count = params + 1 /* pad */ ;
4567     pSMB->TotalParameterCount = cpu_to_le16(params);
4568     pSMB->ParameterCount = pSMB->TotalParameterCount;
4569     pSMB->ParameterOffset = cpu_to_le16(offsetof(
4570         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4571     pSMB->DataCount = 0;
4572     pSMB->DataOffset = 0;
4573     pSMB->SetupCount = 1;
4574     pSMB->Reserved3 = 0;
4575     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4576     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4577     inc_rfc1001_len(pSMB, byte_count);
4578     pSMB->ByteCount = cpu_to_le16(byte_count);
4579 
4580     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4581              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4582     if (rc) {
4583         cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4584     } else {        /* decode response */
4585         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4586 
4587         if (rc || get_bcc(&pSMBr->hdr) < 24)
4588             rc = -EIO;  /* bad smb */
4589         else {
4590             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4591 
4592             response_data =
4593                 (FILE_SYSTEM_INFO
4594                  *) (((char *) &pSMBr->hdr.Protocol) +
4595                  data_offset);
4596             FSData->f_bsize =
4597                 le32_to_cpu(response_data->BytesPerSector) *
4598                 le32_to_cpu(response_data->
4599                     SectorsPerAllocationUnit);
4600             /*
4601              * much prefer larger but if server doesn't report
4602              * a valid size than 4K is a reasonable minimum
4603              */
4604             if (FSData->f_bsize < 512)
4605                 FSData->f_bsize = 4096;
4606 
4607             FSData->f_blocks =
4608                 le64_to_cpu(response_data->TotalAllocationUnits);
4609             FSData->f_bfree = FSData->f_bavail =
4610                 le64_to_cpu(response_data->FreeAllocationUnits);
4611             cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4612                  (unsigned long long)FSData->f_blocks,
4613                  (unsigned long long)FSData->f_bfree,
4614                  FSData->f_bsize);
4615         }
4616     }
4617     cifs_buf_release(pSMB);
4618 
4619     if (rc == -EAGAIN)
4620         goto QFSInfoRetry;
4621 
4622     return rc;
4623 }
4624 
4625 int
4626 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
4627 {
4628 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4629     TRANSACTION2_QFSI_REQ *pSMB = NULL;
4630     TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4631     FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4632     int rc = 0;
4633     int bytes_returned = 0;
4634     __u16 params, byte_count;
4635 
4636     cifs_dbg(FYI, "In QFSAttributeInfo\n");
4637 QFSAttributeRetry:
4638     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4639               (void **) &pSMBr);
4640     if (rc)
4641         return rc;
4642 
4643     params = 2; /* level */
4644     pSMB->TotalDataCount = 0;
4645     pSMB->MaxParameterCount = cpu_to_le16(2);
4646     /* BB find exact max SMB PDU from sess structure BB */
4647     pSMB->MaxDataCount = cpu_to_le16(1000);
4648     pSMB->MaxSetupCount = 0;
4649     pSMB->Reserved = 0;
4650     pSMB->Flags = 0;
4651     pSMB->Timeout = 0;
4652     pSMB->Reserved2 = 0;
4653     byte_count = params + 1 /* pad */ ;
4654     pSMB->TotalParameterCount = cpu_to_le16(params);
4655     pSMB->ParameterCount = pSMB->TotalParameterCount;
4656     pSMB->ParameterOffset = cpu_to_le16(offsetof(
4657         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4658     pSMB->DataCount = 0;
4659     pSMB->DataOffset = 0;
4660     pSMB->SetupCount = 1;
4661     pSMB->Reserved3 = 0;
4662     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4663     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4664     inc_rfc1001_len(pSMB, byte_count);
4665     pSMB->ByteCount = cpu_to_le16(byte_count);
4666 
4667     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4668              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4669     if (rc) {
4670         cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
4671     } else {        /* decode response */
4672         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4673 
4674         if (rc || get_bcc(&pSMBr->hdr) < 13) {
4675             /* BB also check if enough bytes returned */
4676             rc = -EIO;  /* bad smb */
4677         } else {
4678             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4679             response_data =
4680                 (FILE_SYSTEM_ATTRIBUTE_INFO
4681                  *) (((char *) &pSMBr->hdr.Protocol) +
4682                  data_offset);
4683             memcpy(&tcon->fsAttrInfo, response_data,
4684                    sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4685         }
4686     }
4687     cifs_buf_release(pSMB);
4688 
4689     if (rc == -EAGAIN)
4690         goto QFSAttributeRetry;
4691 
4692     return rc;
4693 }
4694 
4695 int
4696 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
4697 {
4698 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4699     TRANSACTION2_QFSI_REQ *pSMB = NULL;
4700     TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4701     FILE_SYSTEM_DEVICE_INFO *response_data;
4702     int rc = 0;
4703     int bytes_returned = 0;
4704     __u16 params, byte_count;
4705 
4706     cifs_dbg(FYI, "In QFSDeviceInfo\n");
4707 QFSDeviceRetry:
4708     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4709               (void **) &pSMBr);
4710     if (rc)
4711         return rc;
4712 
4713     params = 2; /* level */
4714     pSMB->TotalDataCount = 0;
4715     pSMB->MaxParameterCount = cpu_to_le16(2);
4716     /* BB find exact max SMB PDU from sess structure BB */
4717     pSMB->MaxDataCount = cpu_to_le16(1000);
4718     pSMB->MaxSetupCount = 0;
4719     pSMB->Reserved = 0;
4720     pSMB->Flags = 0;
4721     pSMB->Timeout = 0;
4722     pSMB->Reserved2 = 0;
4723     byte_count = params + 1 /* pad */ ;
4724     pSMB->TotalParameterCount = cpu_to_le16(params);
4725     pSMB->ParameterCount = pSMB->TotalParameterCount;
4726     pSMB->ParameterOffset = cpu_to_le16(offsetof(
4727         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4728 
4729     pSMB->DataCount = 0;
4730     pSMB->DataOffset = 0;
4731     pSMB->SetupCount = 1;
4732     pSMB->Reserved3 = 0;
4733     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4734     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4735     inc_rfc1001_len(pSMB, byte_count);
4736     pSMB->ByteCount = cpu_to_le16(byte_count);
4737 
4738     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4739              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4740     if (rc) {
4741         cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
4742     } else {        /* decode response */
4743         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4744 
4745         if (rc || get_bcc(&pSMBr->hdr) <
4746               sizeof(FILE_SYSTEM_DEVICE_INFO))
4747             rc = -EIO;  /* bad smb */
4748         else {
4749             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4750             response_data =
4751                 (FILE_SYSTEM_DEVICE_INFO *)
4752                 (((char *) &pSMBr->hdr.Protocol) +
4753                  data_offset);
4754             memcpy(&tcon->fsDevInfo, response_data,
4755                    sizeof(FILE_SYSTEM_DEVICE_INFO));
4756         }
4757     }
4758     cifs_buf_release(pSMB);
4759 
4760     if (rc == -EAGAIN)
4761         goto QFSDeviceRetry;
4762 
4763     return rc;
4764 }
4765 
4766 int
4767 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
4768 {
4769 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4770     TRANSACTION2_QFSI_REQ *pSMB = NULL;
4771     TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4772     FILE_SYSTEM_UNIX_INFO *response_data;
4773     int rc = 0;
4774     int bytes_returned = 0;
4775     __u16 params, byte_count;
4776 
4777     cifs_dbg(FYI, "In QFSUnixInfo\n");
4778 QFSUnixRetry:
4779     rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4780                    (void **) &pSMB, (void **) &pSMBr);
4781     if (rc)
4782         return rc;
4783 
4784     params = 2; /* level */
4785     pSMB->TotalDataCount = 0;
4786     pSMB->DataCount = 0;
4787     pSMB->DataOffset = 0;
4788     pSMB->MaxParameterCount = cpu_to_le16(2);
4789     /* BB find exact max SMB PDU from sess structure BB */
4790     pSMB->MaxDataCount = cpu_to_le16(100);
4791     pSMB->MaxSetupCount = 0;
4792     pSMB->Reserved = 0;
4793     pSMB->Flags = 0;
4794     pSMB->Timeout = 0;
4795     pSMB->Reserved2 = 0;
4796     byte_count = params + 1 /* pad */ ;
4797     pSMB->ParameterCount = cpu_to_le16(params);
4798     pSMB->TotalParameterCount = pSMB->ParameterCount;
4799     pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4800             smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4801     pSMB->SetupCount = 1;
4802     pSMB->Reserved3 = 0;
4803     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4804     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4805     inc_rfc1001_len(pSMB, byte_count);
4806     pSMB->ByteCount = cpu_to_le16(byte_count);
4807 
4808     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4809              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4810     if (rc) {
4811         cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
4812     } else {        /* decode response */
4813         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4814 
4815         if (rc || get_bcc(&pSMBr->hdr) < 13) {
4816             rc = -EIO;  /* bad smb */
4817         } else {
4818             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4819             response_data =
4820                 (FILE_SYSTEM_UNIX_INFO
4821                  *) (((char *) &pSMBr->hdr.Protocol) +
4822                  data_offset);
4823             memcpy(&tcon->fsUnixInfo, response_data,
4824                    sizeof(FILE_SYSTEM_UNIX_INFO));
4825         }
4826     }
4827     cifs_buf_release(pSMB);
4828 
4829     if (rc == -EAGAIN)
4830         goto QFSUnixRetry;
4831 
4832 
4833     return rc;
4834 }
4835 
4836 int
4837 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
4838 {
4839 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4840     TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4841     TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4842     int rc = 0;
4843     int bytes_returned = 0;
4844     __u16 params, param_offset, offset, byte_count;
4845 
4846     cifs_dbg(FYI, "In SETFSUnixInfo\n");
4847 SETFSUnixRetry:
4848     /* BB switch to small buf init to save memory */
4849     rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4850                     (void **) &pSMB, (void **) &pSMBr);
4851     if (rc)
4852         return rc;
4853 
4854     params = 4; /* 2 bytes zero followed by info level. */
4855     pSMB->MaxSetupCount = 0;
4856     pSMB->Reserved = 0;
4857     pSMB->Flags = 0;
4858     pSMB->Timeout = 0;
4859     pSMB->Reserved2 = 0;
4860     param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4861                 - 4;
4862     offset = param_offset + params;
4863 
4864     pSMB->MaxParameterCount = cpu_to_le16(4);
4865     /* BB find exact max SMB PDU from sess structure BB */
4866     pSMB->MaxDataCount = cpu_to_le16(100);
4867     pSMB->SetupCount = 1;
4868     pSMB->Reserved3 = 0;
4869     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4870     byte_count = 1 /* pad */ + params + 12;
4871 
4872     pSMB->DataCount = cpu_to_le16(12);
4873     pSMB->ParameterCount = cpu_to_le16(params);
4874     pSMB->TotalDataCount = pSMB->DataCount;
4875     pSMB->TotalParameterCount = pSMB->ParameterCount;
4876     pSMB->ParameterOffset = cpu_to_le16(param_offset);
4877     pSMB->DataOffset = cpu_to_le16(offset);
4878 
4879     /* Params. */
4880     pSMB->FileNum = 0;
4881     pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4882 
4883     /* Data. */
4884     pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4885     pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4886     pSMB->ClientUnixCap = cpu_to_le64(cap);
4887 
4888     inc_rfc1001_len(pSMB, byte_count);
4889     pSMB->ByteCount = cpu_to_le16(byte_count);
4890 
4891     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4892              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4893     if (rc) {
4894         cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
4895     } else {        /* decode response */
4896         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4897         if (rc)
4898             rc = -EIO;  /* bad smb */
4899     }
4900     cifs_buf_release(pSMB);
4901 
4902     if (rc == -EAGAIN)
4903         goto SETFSUnixRetry;
4904 
4905     return rc;
4906 }
4907 
4908 
4909 
4910 int
4911 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
4912            struct kstatfs *FSData)
4913 {
4914 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
4915     TRANSACTION2_QFSI_REQ *pSMB = NULL;
4916     TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4917     FILE_SYSTEM_POSIX_INFO *response_data;
4918     int rc = 0;
4919     int bytes_returned = 0;
4920     __u16 params, byte_count;
4921 
4922     cifs_dbg(FYI, "In QFSPosixInfo\n");
4923 QFSPosixRetry:
4924     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4925               (void **) &pSMBr);
4926     if (rc)
4927         return rc;
4928 
4929     params = 2; /* level */
4930     pSMB->TotalDataCount = 0;
4931     pSMB->DataCount = 0;
4932     pSMB->DataOffset = 0;
4933     pSMB->MaxParameterCount = cpu_to_le16(2);
4934     /* BB find exact max SMB PDU from sess structure BB */
4935     pSMB->MaxDataCount = cpu_to_le16(100);
4936     pSMB->MaxSetupCount = 0;
4937     pSMB->Reserved = 0;
4938     pSMB->Flags = 0;
4939     pSMB->Timeout = 0;
4940     pSMB->Reserved2 = 0;
4941     byte_count = params + 1 /* pad */ ;
4942     pSMB->ParameterCount = cpu_to_le16(params);
4943     pSMB->TotalParameterCount = pSMB->ParameterCount;
4944     pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4945             smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4946     pSMB->SetupCount = 1;
4947     pSMB->Reserved3 = 0;
4948     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4949     pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4950     inc_rfc1001_len(pSMB, byte_count);
4951     pSMB->ByteCount = cpu_to_le16(byte_count);
4952 
4953     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4954              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4955     if (rc) {
4956         cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
4957     } else {        /* decode response */
4958         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4959 
4960         if (rc || get_bcc(&pSMBr->hdr) < 13) {
4961             rc = -EIO;  /* bad smb */
4962         } else {
4963             __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4964             response_data =
4965                 (FILE_SYSTEM_POSIX_INFO
4966                  *) (((char *) &pSMBr->hdr.Protocol) +
4967                  data_offset);
4968             FSData->f_bsize =
4969                     le32_to_cpu(response_data->BlockSize);
4970             /*
4971              * much prefer larger but if server doesn't report
4972              * a valid size than 4K is a reasonable minimum
4973              */
4974             if (FSData->f_bsize < 512)
4975                 FSData->f_bsize = 4096;
4976 
4977             FSData->f_blocks =
4978                     le64_to_cpu(response_data->TotalBlocks);
4979             FSData->f_bfree =
4980                 le64_to_cpu(response_data->BlocksAvail);
4981             if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4982                 FSData->f_bavail = FSData->f_bfree;
4983             } else {
4984                 FSData->f_bavail =
4985                     le64_to_cpu(response_data->UserBlocksAvail);
4986             }
4987             if (response_data->TotalFileNodes != cpu_to_le64(-1))
4988                 FSData->f_files =
4989                      le64_to_cpu(response_data->TotalFileNodes);
4990             if (response_data->FreeFileNodes != cpu_to_le64(-1))
4991                 FSData->f_ffree =
4992                       le64_to_cpu(response_data->FreeFileNodes);
4993         }
4994     }
4995     cifs_buf_release(pSMB);
4996 
4997     if (rc == -EAGAIN)
4998         goto QFSPosixRetry;
4999 
5000     return rc;
5001 }
5002 
5003 
5004 /*
5005  * We can not use write of zero bytes trick to set file size due to need for
5006  * large file support. Also note that this SetPathInfo is preferred to
5007  * SetFileInfo based method in next routine which is only needed to work around
5008  * a sharing violation bugin Samba which this routine can run into.
5009  */
5010 int
5011 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5012           const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5013           bool set_allocation)
5014 {
5015     struct smb_com_transaction2_spi_req *pSMB = NULL;
5016     struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5017     struct file_end_of_file_info *parm_data;
5018     int name_len;
5019     int rc = 0;
5020     int bytes_returned = 0;
5021     int remap = cifs_remap(cifs_sb);
5022 
5023     __u16 params, byte_count, data_count, param_offset, offset;
5024 
5025     cifs_dbg(FYI, "In SetEOF\n");
5026 SetEOFRetry:
5027     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5028               (void **) &pSMBr);
5029     if (rc)
5030         return rc;
5031 
5032     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5033         name_len =
5034             cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5035                        PATH_MAX, cifs_sb->local_nls, remap);
5036         name_len++; /* trailing null */
5037         name_len *= 2;
5038     } else {
5039         name_len = copy_path_name(pSMB->FileName, file_name);
5040     }
5041     params = 6 + name_len;
5042     data_count = sizeof(struct file_end_of_file_info);
5043     pSMB->MaxParameterCount = cpu_to_le16(2);
5044     pSMB->MaxDataCount = cpu_to_le16(4100);
5045     pSMB->MaxSetupCount = 0;
5046     pSMB->Reserved = 0;
5047     pSMB->Flags = 0;
5048     pSMB->Timeout = 0;
5049     pSMB->Reserved2 = 0;
5050     param_offset = offsetof(struct smb_com_transaction2_spi_req,
5051                 InformationLevel) - 4;
5052     offset = param_offset + params;
5053     if (set_allocation) {
5054         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5055             pSMB->InformationLevel =
5056                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5057         else
5058             pSMB->InformationLevel =
5059                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5060     } else /* Set File Size */  {
5061         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5062             pSMB->InformationLevel =
5063                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5064         else
5065             pSMB->InformationLevel =
5066                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5067     }
5068 
5069     parm_data =
5070         (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5071                        offset);
5072     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5073     pSMB->DataOffset = cpu_to_le16(offset);
5074     pSMB->SetupCount = 1;
5075     pSMB->Reserved3 = 0;
5076     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5077     byte_count = 3 /* pad */  + params + data_count;
5078     pSMB->DataCount = cpu_to_le16(data_count);
5079     pSMB->TotalDataCount = pSMB->DataCount;
5080     pSMB->ParameterCount = cpu_to_le16(params);
5081     pSMB->TotalParameterCount = pSMB->ParameterCount;
5082     pSMB->Reserved4 = 0;
5083     inc_rfc1001_len(pSMB, byte_count);
5084     parm_data->FileSize = cpu_to_le64(size);
5085     pSMB->ByteCount = cpu_to_le16(byte_count);
5086     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5087              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5088     if (rc)
5089         cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5090 
5091     cifs_buf_release(pSMB);
5092 
5093     if (rc == -EAGAIN)
5094         goto SetEOFRetry;
5095 
5096     return rc;
5097 }
5098 
5099 int
5100 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5101            struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5102 {
5103     struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5104     struct file_end_of_file_info *parm_data;
5105     int rc = 0;
5106     __u16 params, param_offset, offset, byte_count, count;
5107 
5108     cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5109          (long long)size);
5110     rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5111 
5112     if (rc)
5113         return rc;
5114 
5115     pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5116     pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5117 
5118     params = 6;
5119     pSMB->MaxSetupCount = 0;
5120     pSMB->Reserved = 0;
5121     pSMB->Flags = 0;
5122     pSMB->Timeout = 0;
5123     pSMB->Reserved2 = 0;
5124     param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5125     offset = param_offset + params;
5126 
5127     count = sizeof(struct file_end_of_file_info);
5128     pSMB->MaxParameterCount = cpu_to_le16(2);
5129     /* BB find exact max SMB PDU from sess structure BB */
5130     pSMB->MaxDataCount = cpu_to_le16(1000);
5131     pSMB->SetupCount = 1;
5132     pSMB->Reserved3 = 0;
5133     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5134     byte_count = 3 /* pad */  + params + count;
5135     pSMB->DataCount = cpu_to_le16(count);
5136     pSMB->ParameterCount = cpu_to_le16(params);
5137     pSMB->TotalDataCount = pSMB->DataCount;
5138     pSMB->TotalParameterCount = pSMB->ParameterCount;
5139     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5140     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5141     parm_data =
5142         (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
5143     pSMB->DataOffset = cpu_to_le16(offset);
5144     parm_data->FileSize = cpu_to_le64(size);
5145     pSMB->Fid = cfile->fid.netfid;
5146     if (set_allocation) {
5147         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5148             pSMB->InformationLevel =
5149                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5150         else
5151             pSMB->InformationLevel =
5152                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5153     } else /* Set File Size */  {
5154         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5155             pSMB->InformationLevel =
5156                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5157         else
5158             pSMB->InformationLevel =
5159                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5160     }
5161     pSMB->Reserved4 = 0;
5162     inc_rfc1001_len(pSMB, byte_count);
5163     pSMB->ByteCount = cpu_to_le16(byte_count);
5164     rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5165     cifs_small_buf_release(pSMB);
5166     if (rc) {
5167         cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5168              rc);
5169     }
5170 
5171     /* Note: On -EAGAIN error only caller can retry on handle based calls
5172         since file handle passed in no longer valid */
5173 
5174     return rc;
5175 }
5176 
5177 /* Some legacy servers such as NT4 require that the file times be set on
5178    an open handle, rather than by pathname - this is awkward due to
5179    potential access conflicts on the open, but it is unavoidable for these
5180    old servers since the only other choice is to go from 100 nanosecond DCE
5181    time and resort to the original setpathinfo level which takes the ancient
5182    DOS time format with 2 second granularity */
5183 int
5184 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5185             const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5186 {
5187     struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5188     char *data_offset;
5189     int rc = 0;
5190     __u16 params, param_offset, offset, byte_count, count;
5191 
5192     cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5193     rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5194 
5195     if (rc)
5196         return rc;
5197 
5198     pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5199     pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5200 
5201     params = 6;
5202     pSMB->MaxSetupCount = 0;
5203     pSMB->Reserved = 0;
5204     pSMB->Flags = 0;
5205     pSMB->Timeout = 0;
5206     pSMB->Reserved2 = 0;
5207     param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5208     offset = param_offset + params;
5209 
5210     data_offset = (char *)pSMB +
5211             offsetof(struct smb_hdr, Protocol) + offset;
5212 
5213     count = sizeof(FILE_BASIC_INFO);
5214     pSMB->MaxParameterCount = cpu_to_le16(2);
5215     /* BB find max SMB PDU from sess */
5216     pSMB->MaxDataCount = cpu_to_le16(1000);
5217     pSMB->SetupCount = 1;
5218     pSMB->Reserved3 = 0;
5219     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5220     byte_count = 3 /* pad */  + params + count;
5221     pSMB->DataCount = cpu_to_le16(count);
5222     pSMB->ParameterCount = cpu_to_le16(params);
5223     pSMB->TotalDataCount = pSMB->DataCount;
5224     pSMB->TotalParameterCount = pSMB->ParameterCount;
5225     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5226     pSMB->DataOffset = cpu_to_le16(offset);
5227     pSMB->Fid = fid;
5228     if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5229         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5230     else
5231         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5232     pSMB->Reserved4 = 0;
5233     inc_rfc1001_len(pSMB, byte_count);
5234     pSMB->ByteCount = cpu_to_le16(byte_count);
5235     memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5236     rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5237     cifs_small_buf_release(pSMB);
5238     if (rc)
5239         cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5240              rc);
5241 
5242     /* Note: On -EAGAIN error only caller can retry on handle based calls
5243         since file handle passed in no longer valid */
5244 
5245     return rc;
5246 }
5247 
5248 int
5249 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5250               bool delete_file, __u16 fid, __u32 pid_of_opener)
5251 {
5252     struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5253     char *data_offset;
5254     int rc = 0;
5255     __u16 params, param_offset, offset, byte_count, count;
5256 
5257     cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5258     rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5259 
5260     if (rc)
5261         return rc;
5262 
5263     pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5264     pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5265 
5266     params = 6;
5267     pSMB->MaxSetupCount = 0;
5268     pSMB->Reserved = 0;
5269     pSMB->Flags = 0;
5270     pSMB->Timeout = 0;
5271     pSMB->Reserved2 = 0;
5272     param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5273     offset = param_offset + params;
5274 
5275     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5276     data_offset = (char *)(pSMB) + offset + 4;
5277 
5278     count = 1;
5279     pSMB->MaxParameterCount = cpu_to_le16(2);
5280     /* BB find max SMB PDU from sess */
5281     pSMB->MaxDataCount = cpu_to_le16(1000);
5282     pSMB->SetupCount = 1;
5283     pSMB->Reserved3 = 0;
5284     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5285     byte_count = 3 /* pad */  + params + count;
5286     pSMB->DataCount = cpu_to_le16(count);
5287     pSMB->ParameterCount = cpu_to_le16(params);
5288     pSMB->TotalDataCount = pSMB->DataCount;
5289     pSMB->TotalParameterCount = pSMB->ParameterCount;
5290     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5291     pSMB->DataOffset = cpu_to_le16(offset);
5292     pSMB->Fid = fid;
5293     pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5294     pSMB->Reserved4 = 0;
5295     inc_rfc1001_len(pSMB, byte_count);
5296     pSMB->ByteCount = cpu_to_le16(byte_count);
5297     *data_offset = delete_file ? 1 : 0;
5298     rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5299     cifs_small_buf_release(pSMB);
5300     if (rc)
5301         cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5302 
5303     return rc;
5304 }
5305 
5306 static int
5307 CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5308              const char *fileName, const FILE_BASIC_INFO *data,
5309              const struct nls_table *nls_codepage,
5310              struct cifs_sb_info *cifs_sb)
5311 {
5312     int oplock = 0;
5313     struct cifs_open_parms oparms;
5314     struct cifs_fid fid;
5315     int rc;
5316 
5317     oparms.tcon = tcon;
5318     oparms.cifs_sb = cifs_sb;
5319     oparms.desired_access = GENERIC_WRITE;
5320     oparms.create_options = cifs_create_options(cifs_sb, 0);
5321     oparms.disposition = FILE_OPEN;
5322     oparms.path = fileName;
5323     oparms.fid = &fid;
5324     oparms.reconnect = false;
5325 
5326     rc = CIFS_open(xid, &oparms, &oplock, NULL);
5327     if (rc)
5328         goto out;
5329 
5330     rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5331     CIFSSMBClose(xid, tcon, fid.netfid);
5332 out:
5333 
5334     return rc;
5335 }
5336 
5337 int
5338 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5339            const char *fileName, const FILE_BASIC_INFO *data,
5340            const struct nls_table *nls_codepage,
5341              struct cifs_sb_info *cifs_sb)
5342 {
5343     TRANSACTION2_SPI_REQ *pSMB = NULL;
5344     TRANSACTION2_SPI_RSP *pSMBr = NULL;
5345     int name_len;
5346     int rc = 0;
5347     int bytes_returned = 0;
5348     char *data_offset;
5349     __u16 params, param_offset, offset, byte_count, count;
5350     int remap = cifs_remap(cifs_sb);
5351 
5352     cifs_dbg(FYI, "In SetTimes\n");
5353 
5354 SetTimesRetry:
5355     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5356               (void **) &pSMBr);
5357     if (rc)
5358         return rc;
5359 
5360     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5361         name_len =
5362             cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5363                        PATH_MAX, nls_codepage, remap);
5364         name_len++; /* trailing null */
5365         name_len *= 2;
5366     } else {
5367         name_len = copy_path_name(pSMB->FileName, fileName);
5368     }
5369 
5370     params = 6 + name_len;
5371     count = sizeof(FILE_BASIC_INFO);
5372     pSMB->MaxParameterCount = cpu_to_le16(2);
5373     /* BB find max SMB PDU from sess structure BB */
5374     pSMB->MaxDataCount = cpu_to_le16(1000);
5375     pSMB->MaxSetupCount = 0;
5376     pSMB->Reserved = 0;
5377     pSMB->Flags = 0;
5378     pSMB->Timeout = 0;
5379     pSMB->Reserved2 = 0;
5380     param_offset = offsetof(struct smb_com_transaction2_spi_req,
5381                 InformationLevel) - 4;
5382     offset = param_offset + params;
5383     data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5384     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5385     pSMB->DataOffset = cpu_to_le16(offset);
5386     pSMB->SetupCount = 1;
5387     pSMB->Reserved3 = 0;
5388     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5389     byte_count = 3 /* pad */  + params + count;
5390 
5391     pSMB->DataCount = cpu_to_le16(count);
5392     pSMB->ParameterCount = cpu_to_le16(params);
5393     pSMB->TotalDataCount = pSMB->DataCount;
5394     pSMB->TotalParameterCount = pSMB->ParameterCount;
5395     if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5396         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5397     else
5398         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5399     pSMB->Reserved4 = 0;
5400     inc_rfc1001_len(pSMB, byte_count);
5401     memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5402     pSMB->ByteCount = cpu_to_le16(byte_count);
5403     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5404              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5405     if (rc)
5406         cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5407 
5408     cifs_buf_release(pSMB);
5409 
5410     if (rc == -EAGAIN)
5411         goto SetTimesRetry;
5412 
5413     if (rc == -EOPNOTSUPP)
5414         return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5415                         nls_codepage, cifs_sb);
5416 
5417     return rc;
5418 }
5419 
5420 static void
5421 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5422             const struct cifs_unix_set_info_args *args)
5423 {
5424     u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5425     u64 mode = args->mode;
5426 
5427     if (uid_valid(args->uid))
5428         uid = from_kuid(&init_user_ns, args->uid);
5429     if (gid_valid(args->gid))
5430         gid = from_kgid(&init_user_ns, args->gid);
5431 
5432     /*
5433      * Samba server ignores set of file size to zero due to bugs in some
5434      * older clients, but we should be precise - we use SetFileSize to
5435      * set file size and do not want to truncate file size to zero
5436      * accidentally as happened on one Samba server beta by putting
5437      * zero instead of -1 here
5438      */
5439     data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5440     data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5441     data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5442     data_offset->LastAccessTime = cpu_to_le64(args->atime);
5443     data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5444     data_offset->Uid = cpu_to_le64(uid);
5445     data_offset->Gid = cpu_to_le64(gid);
5446     /* better to leave device as zero when it is  */
5447     data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5448     data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5449     data_offset->Permissions = cpu_to_le64(mode);
5450 
5451     if (S_ISREG(mode))
5452         data_offset->Type = cpu_to_le32(UNIX_FILE);
5453     else if (S_ISDIR(mode))
5454         data_offset->Type = cpu_to_le32(UNIX_DIR);
5455     else if (S_ISLNK(mode))
5456         data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5457     else if (S_ISCHR(mode))
5458         data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5459     else if (S_ISBLK(mode))
5460         data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5461     else if (S_ISFIFO(mode))
5462         data_offset->Type = cpu_to_le32(UNIX_FIFO);
5463     else if (S_ISSOCK(mode))
5464         data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5465 }
5466 
5467 int
5468 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5469                const struct cifs_unix_set_info_args *args,
5470                u16 fid, u32 pid_of_opener)
5471 {
5472     struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5473     char *data_offset;
5474     int rc = 0;
5475     u16 params, param_offset, offset, byte_count, count;
5476 
5477     cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5478     rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5479 
5480     if (rc)
5481         return rc;
5482 
5483     pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5484     pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5485 
5486     params = 6;
5487     pSMB->MaxSetupCount = 0;
5488     pSMB->Reserved = 0;
5489     pSMB->Flags = 0;
5490     pSMB->Timeout = 0;
5491     pSMB->Reserved2 = 0;
5492     param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5493     offset = param_offset + params;
5494 
5495     data_offset = (char *)pSMB +
5496             offsetof(struct smb_hdr, Protocol) + offset;
5497 
5498     count = sizeof(FILE_UNIX_BASIC_INFO);
5499 
5500     pSMB->MaxParameterCount = cpu_to_le16(2);
5501     /* BB find max SMB PDU from sess */
5502     pSMB->MaxDataCount = cpu_to_le16(1000);
5503     pSMB->SetupCount = 1;
5504     pSMB->Reserved3 = 0;
5505     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5506     byte_count = 3 /* pad */  + params + count;
5507     pSMB->DataCount = cpu_to_le16(count);
5508     pSMB->ParameterCount = cpu_to_le16(params);
5509     pSMB->TotalDataCount = pSMB->DataCount;
5510     pSMB->TotalParameterCount = pSMB->ParameterCount;
5511     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5512     pSMB->DataOffset = cpu_to_le16(offset);
5513     pSMB->Fid = fid;
5514     pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5515     pSMB->Reserved4 = 0;
5516     inc_rfc1001_len(pSMB, byte_count);
5517     pSMB->ByteCount = cpu_to_le16(byte_count);
5518 
5519     cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5520 
5521     rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5522     cifs_small_buf_release(pSMB);
5523     if (rc)
5524         cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5525              rc);
5526 
5527     /* Note: On -EAGAIN error only caller can retry on handle based calls
5528         since file handle passed in no longer valid */
5529 
5530     return rc;
5531 }
5532 
5533 int
5534 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5535                const char *file_name,
5536                const struct cifs_unix_set_info_args *args,
5537                const struct nls_table *nls_codepage, int remap)
5538 {
5539     TRANSACTION2_SPI_REQ *pSMB = NULL;
5540     TRANSACTION2_SPI_RSP *pSMBr = NULL;
5541     int name_len;
5542     int rc = 0;
5543     int bytes_returned = 0;
5544     FILE_UNIX_BASIC_INFO *data_offset;
5545     __u16 params, param_offset, offset, count, byte_count;
5546 
5547     cifs_dbg(FYI, "In SetUID/GID/Mode\n");
5548 setPermsRetry:
5549     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5550               (void **) &pSMBr);
5551     if (rc)
5552         return rc;
5553 
5554     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5555         name_len =
5556             cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5557                        PATH_MAX, nls_codepage, remap);
5558         name_len++; /* trailing null */
5559         name_len *= 2;
5560     } else {
5561         name_len = copy_path_name(pSMB->FileName, file_name);
5562     }
5563 
5564     params = 6 + name_len;
5565     count = sizeof(FILE_UNIX_BASIC_INFO);
5566     pSMB->MaxParameterCount = cpu_to_le16(2);
5567     /* BB find max SMB PDU from sess structure BB */
5568     pSMB->MaxDataCount = cpu_to_le16(1000);
5569     pSMB->MaxSetupCount = 0;
5570     pSMB->Reserved = 0;
5571     pSMB->Flags = 0;
5572     pSMB->Timeout = 0;
5573     pSMB->Reserved2 = 0;
5574     param_offset = offsetof(struct smb_com_transaction2_spi_req,
5575                 InformationLevel) - 4;
5576     offset = param_offset + params;
5577     /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5578     data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
5579     memset(data_offset, 0, count);
5580     pSMB->DataOffset = cpu_to_le16(offset);
5581     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5582     pSMB->SetupCount = 1;
5583     pSMB->Reserved3 = 0;
5584     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5585     byte_count = 3 /* pad */  + params + count;
5586     pSMB->ParameterCount = cpu_to_le16(params);
5587     pSMB->DataCount = cpu_to_le16(count);
5588     pSMB->TotalParameterCount = pSMB->ParameterCount;
5589     pSMB->TotalDataCount = pSMB->DataCount;
5590     pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5591     pSMB->Reserved4 = 0;
5592     inc_rfc1001_len(pSMB, byte_count);
5593 
5594     cifs_fill_unix_set_info(data_offset, args);
5595 
5596     pSMB->ByteCount = cpu_to_le16(byte_count);
5597     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5598              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5599     if (rc)
5600         cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
5601 
5602     cifs_buf_release(pSMB);
5603     if (rc == -EAGAIN)
5604         goto setPermsRetry;
5605     return rc;
5606 }
5607 
5608 #ifdef CONFIG_CIFS_XATTR
5609 /*
5610  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5611  * function used by listxattr and getxattr type calls. When ea_name is set,
5612  * it looks for that attribute name and stuffs that value into the EAData
5613  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5614  * buffer. In both cases, the return value is either the length of the
5615  * resulting data or a negative error code. If EAData is a NULL pointer then
5616  * the data isn't copied to it, but the length is returned.
5617  */
5618 ssize_t
5619 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
5620         const unsigned char *searchName, const unsigned char *ea_name,
5621         char *EAData, size_t buf_size,
5622         struct cifs_sb_info *cifs_sb)
5623 {
5624         /* BB assumes one setup word */
5625     TRANSACTION2_QPI_REQ *pSMB = NULL;
5626     TRANSACTION2_QPI_RSP *pSMBr = NULL;
5627     int remap = cifs_remap(cifs_sb);
5628     struct nls_table *nls_codepage = cifs_sb->local_nls;
5629     int rc = 0;
5630     int bytes_returned;
5631     int list_len;
5632     struct fealist *ea_response_data;
5633     struct fea *temp_fea;
5634     char *temp_ptr;
5635     char *end_of_smb;
5636     __u16 params, byte_count, data_offset;
5637     unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
5638 
5639     cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
5640 QAllEAsRetry:
5641     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5642               (void **) &pSMBr);
5643     if (rc)
5644         return rc;
5645 
5646     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5647         list_len =
5648             cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
5649                        PATH_MAX, nls_codepage, remap);
5650         list_len++; /* trailing null */
5651         list_len *= 2;
5652     } else {
5653         list_len = copy_path_name(pSMB->FileName, searchName);
5654     }
5655 
5656     params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5657     pSMB->TotalDataCount = 0;
5658     pSMB->MaxParameterCount = cpu_to_le16(2);
5659     /* BB find exact max SMB PDU from sess structure BB */
5660     pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5661     pSMB->MaxSetupCount = 0;
5662     pSMB->Reserved = 0;
5663     pSMB->Flags = 0;
5664     pSMB->Timeout = 0;
5665     pSMB->Reserved2 = 0;
5666     pSMB->ParameterOffset = cpu_to_le16(offsetof(
5667     struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5668     pSMB->DataCount = 0;
5669     pSMB->DataOffset = 0;
5670     pSMB->SetupCount = 1;
5671     pSMB->Reserved3 = 0;
5672     pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5673     byte_count = params + 1 /* pad */ ;
5674     pSMB->TotalParameterCount = cpu_to_le16(params);
5675     pSMB->ParameterCount = pSMB->TotalParameterCount;
5676     pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5677     pSMB->Reserved4 = 0;
5678     inc_rfc1001_len(pSMB, byte_count);
5679     pSMB->ByteCount = cpu_to_le16(byte_count);
5680 
5681     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5682              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5683     if (rc) {
5684         cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
5685         goto QAllEAsOut;
5686     }
5687 
5688 
5689     /* BB also check enough total bytes returned */
5690     /* BB we need to improve the validity checking
5691     of these trans2 responses */
5692 
5693     rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5694     if (rc || get_bcc(&pSMBr->hdr) < 4) {
5695         rc = -EIO;  /* bad smb */
5696         goto QAllEAsOut;
5697     }
5698 
5699     /* check that length of list is not more than bcc */
5700     /* check that each entry does not go beyond length
5701        of list */
5702     /* check that each element of each entry does not
5703        go beyond end of list */
5704     /* validate_trans2_offsets() */
5705     /* BB check if start of smb + data_offset > &bcc+ bcc */
5706 
5707     data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5708     ea_response_data = (struct fealist *)
5709                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5710 
5711     list_len = le32_to_cpu(ea_response_data->list_len);
5712     cifs_dbg(FYI, "ea length %d\n", list_len);
5713     if (list_len <= 8) {
5714         cifs_dbg(FYI, "empty EA list returned from server\n");
5715         /* didn't find the named attribute */
5716         if (ea_name)
5717             rc = -ENODATA;
5718         goto QAllEAsOut;
5719     }
5720 
5721     /* make sure list_len doesn't go past end of SMB */
5722     end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5723     if ((char *)ea_response_data + list_len > end_of_smb) {
5724         cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
5725         rc = -EIO;
5726         goto QAllEAsOut;
5727     }
5728 
5729     /* account for ea list len */
5730     list_len -= 4;
5731     temp_fea = ea_response_data->list;
5732     temp_ptr = (char *)temp_fea;
5733     while (list_len > 0) {
5734         unsigned int name_len;
5735         __u16 value_len;
5736 
5737         list_len -= 4;
5738         temp_ptr += 4;
5739         /* make sure we can read name_len and value_len */
5740         if (list_len < 0) {
5741             cifs_dbg(FYI, "EA entry goes beyond length of list\n");
5742             rc = -EIO;
5743             goto QAllEAsOut;
5744         }
5745 
5746         name_len = temp_fea->name_len;
5747         value_len = le16_to_cpu(temp_fea->value_len);
5748         list_len -= name_len + 1 + value_len;
5749         if (list_len < 0) {
5750             cifs_dbg(FYI, "EA entry goes beyond length of list\n");
5751             rc = -EIO;
5752             goto QAllEAsOut;
5753         }
5754 
5755         if (ea_name) {
5756             if (ea_name_len == name_len &&
5757                 memcmp(ea_name, temp_ptr, name_len) == 0) {
5758                 temp_ptr += name_len + 1;
5759                 rc = value_len;
5760                 if (buf_size == 0)
5761                     goto QAllEAsOut;
5762                 if ((size_t)value_len > buf_size) {
5763                     rc = -ERANGE;
5764                     goto QAllEAsOut;
5765                 }
5766                 memcpy(EAData, temp_ptr, value_len);
5767                 goto QAllEAsOut;
5768             }
5769         } else {
5770             /* account for prefix user. and trailing null */
5771             rc += (5 + 1 + name_len);
5772             if (rc < (int) buf_size) {
5773                 memcpy(EAData, "user.", 5);
5774                 EAData += 5;
5775                 memcpy(EAData, temp_ptr, name_len);
5776                 EAData += name_len;
5777                 /* null terminate name */
5778                 *EAData = 0;
5779                 ++EAData;
5780             } else if (buf_size == 0) {
5781                 /* skip copy - calc size only */
5782             } else {
5783                 /* stop before overrun buffer */
5784                 rc = -ERANGE;
5785                 break;
5786             }
5787         }
5788         temp_ptr += name_len + 1 + value_len;
5789         temp_fea = (struct fea *)temp_ptr;
5790     }
5791 
5792     /* didn't find the named attribute */
5793     if (ea_name)
5794         rc = -ENODATA;
5795 
5796 QAllEAsOut:
5797     cifs_buf_release(pSMB);
5798     if (rc == -EAGAIN)
5799         goto QAllEAsRetry;
5800 
5801     return (ssize_t)rc;
5802 }
5803 
5804 int
5805 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
5806          const char *fileName, const char *ea_name, const void *ea_value,
5807          const __u16 ea_value_len, const struct nls_table *nls_codepage,
5808          struct cifs_sb_info *cifs_sb)
5809 {
5810     struct smb_com_transaction2_spi_req *pSMB = NULL;
5811     struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5812     struct fealist *parm_data;
5813     int name_len;
5814     int rc = 0;
5815     int bytes_returned = 0;
5816     __u16 params, param_offset, byte_count, offset, count;
5817     int remap = cifs_remap(cifs_sb);
5818 
5819     cifs_dbg(FYI, "In SetEA\n");
5820 SetEARetry:
5821     rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5822               (void **) &pSMBr);
5823     if (rc)
5824         return rc;
5825 
5826     if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5827         name_len =
5828             cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5829                        PATH_MAX, nls_codepage, remap);
5830         name_len++; /* trailing null */
5831         name_len *= 2;
5832     } else {
5833         name_len = copy_path_name(pSMB->FileName, fileName);
5834     }
5835 
5836     params = 6 + name_len;
5837 
5838     /* done calculating parms using name_len of file name,
5839     now use name_len to calculate length of ea name
5840     we are going to create in the inode xattrs */
5841     if (ea_name == NULL)
5842         name_len = 0;
5843     else
5844         name_len = strnlen(ea_name, 255);
5845 
5846     count = sizeof(*parm_data) + ea_value_len + name_len;
5847     pSMB->MaxParameterCount = cpu_to_le16(2);
5848     /* BB find max SMB PDU from sess */
5849     pSMB->MaxDataCount = cpu_to_le16(1000);
5850     pSMB->MaxSetupCount = 0;
5851     pSMB->Reserved = 0;
5852     pSMB->Flags = 0;
5853     pSMB->Timeout = 0;
5854     pSMB->Reserved2 = 0;
5855     param_offset = offsetof(struct smb_com_transaction2_spi_req,
5856                 InformationLevel) - 4;
5857     offset = param_offset + params;
5858     pSMB->InformationLevel =
5859         cpu_to_le16(SMB_SET_FILE_EA);
5860 
5861     parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
5862     pSMB->ParameterOffset = cpu_to_le16(param_offset);
5863     pSMB->DataOffset = cpu_to_le16(offset);
5864     pSMB->SetupCount = 1;
5865     pSMB->Reserved3 = 0;
5866     pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5867     byte_count = 3 /* pad */  + params + count;
5868     pSMB->DataCount = cpu_to_le16(count);
5869     parm_data->list_len = cpu_to_le32(count);
5870     parm_data->list[0].EA_flags = 0;
5871     /* we checked above that name len is less than 255 */
5872     parm_data->list[0].name_len = (__u8)name_len;
5873     /* EA names are always ASCII */
5874     if (ea_name)
5875         strncpy(parm_data->list[0].name, ea_name, name_len);
5876     parm_data->list[0].name[name_len] = 0;
5877     parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5878     /* caller ensures that ea_value_len is less than 64K but
5879     we need to ensure that it fits within the smb */
5880 
5881     /*BB add length check to see if it would fit in
5882          negotiated SMB buffer size BB */
5883     /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5884     if (ea_value_len)
5885         memcpy(parm_data->list[0].name+name_len+1,
5886                ea_value, ea_value_len);
5887 
5888     pSMB->TotalDataCount = pSMB->DataCount;
5889     pSMB->ParameterCount = cpu_to_le16(params);
5890     pSMB->TotalParameterCount = pSMB->ParameterCount;
5891     pSMB->Reserved4 = 0;
5892     inc_rfc1001_len(pSMB, byte_count);
5893     pSMB->ByteCount = cpu_to_le16(byte_count);
5894     rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5895              (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5896     if (rc)
5897         cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
5898 
5899     cifs_buf_release(pSMB);
5900 
5901     if (rc == -EAGAIN)
5902         goto SetEARetry;
5903 
5904     return rc;
5905 }
5906 #endif