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