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