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