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