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