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