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#ifdef CONFIG_HIGHMEM
  90/*
  91 * On arches that have high memory, kmap address space is limited. By
  92 * serializing the kmap operations on those arches, we ensure that we don't
  93 * end up with a bunch of threads in writeback with partially mapped page
  94 * arrays, stuck waiting for kmap to come back. That situation prevents
  95 * progress and can deadlock.
  96 */
  97static DEFINE_MUTEX(cifs_kmap_mutex);
  98
  99static inline void
 100cifs_kmap_lock(void)
 101{
 102        mutex_lock(&cifs_kmap_mutex);
 103}
 104
 105static inline void
 106cifs_kmap_unlock(void)
 107{
 108        mutex_unlock(&cifs_kmap_mutex);
 109}
 110#else /* !CONFIG_HIGHMEM */
 111#define cifs_kmap_lock() do { ; } while(0)
 112#define cifs_kmap_unlock() do { ; } while(0)
 113#endif /* CONFIG_HIGHMEM */
 114
 115/*
 116 * Mark as invalid, all open files on tree connections since they
 117 * were closed when session to server was lost.
 118 */
 119void
 120cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
 121{
 122        struct cifsFileInfo *open_file = NULL;
 123        struct list_head *tmp;
 124        struct list_head *tmp1;
 125
 126        /* list all files open on tree connection and mark them invalid */
 127        spin_lock(&cifs_file_list_lock);
 128        list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
 129                open_file = list_entry(tmp, struct cifsFileInfo, tlist);
 130                open_file->invalidHandle = true;
 131                open_file->oplock_break_cancelled = true;
 132        }
 133        spin_unlock(&cifs_file_list_lock);
 134        /*
 135         * BB Add call to invalidate_inodes(sb) for all superblocks mounted
 136         * to this tcon.
 137         */
 138}
 139
 140/* reconnect the socket, tcon, and smb session if needed */
 141static int
 142cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 143{
 144        int rc;
 145        struct cifs_ses *ses;
 146        struct TCP_Server_Info *server;
 147        struct nls_table *nls_codepage;
 148
 149        /*
 150         * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
 151         * tcp and smb session status done differently for those three - in the
 152         * calling routine
 153         */
 154        if (!tcon)
 155                return 0;
 156
 157        ses = tcon->ses;
 158        server = ses->server;
 159
 160        /*
 161         * only tree disconnect, open, and write, (and ulogoff which does not
 162         * have tcon) are allowed as we start force umount
 163         */
 164        if (tcon->tidStatus == CifsExiting) {
 165                if (smb_command != SMB_COM_WRITE_ANDX &&
 166                    smb_command != SMB_COM_OPEN_ANDX &&
 167                    smb_command != SMB_COM_TREE_DISCONNECT) {
 168                        cFYI(1, "can not send cmd %d while umounting",
 169                                smb_command);
 170                        return -ENODEV;
 171                }
 172        }
 173
 174        /*
 175         * Give demultiplex thread up to 10 seconds to reconnect, should be
 176         * greater than cifs socket timeout which is 7 seconds
 177         */
 178        while (server->tcpStatus == CifsNeedReconnect) {
 179                wait_event_interruptible_timeout(server->response_q,
 180                        (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
 181
 182                /* are we still trying to reconnect? */
 183                if (server->tcpStatus != CifsNeedReconnect)
 184                        break;
 185
 186                /*
 187                 * on "soft" mounts we wait once. Hard mounts keep
 188                 * retrying until process is killed or server comes
 189                 * back on-line
 190                 */
 191                if (!tcon->retry) {
 192                        cFYI(1, "gave up waiting on reconnect in smb_init");
 193                        return -EHOSTDOWN;
 194                }
 195        }
 196
 197        if (!ses->need_reconnect && !tcon->need_reconnect)
 198                return 0;
 199
 200        nls_codepage = load_nls_default();
 201
 202        /*
 203         * need to prevent multiple threads trying to simultaneously
 204         * reconnect the same SMB session
 205         */
 206        mutex_lock(&ses->session_mutex);
 207        rc = cifs_negotiate_protocol(0, ses);
 208        if (rc == 0 && ses->need_reconnect)
 209                rc = cifs_setup_session(0, ses, nls_codepage);
 210
 211        /* do we need to reconnect tcon? */
 212        if (rc || !tcon->need_reconnect) {
 213                mutex_unlock(&ses->session_mutex);
 214                goto out;
 215        }
 216
 217        cifs_mark_open_files_invalid(tcon);
 218        rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
 219        mutex_unlock(&ses->session_mutex);
 220        cFYI(1, "reconnect tcon rc = %d", rc);
 221
 222        if (rc)
 223                goto out;
 224
 225        /*
 226         * FIXME: check if wsize needs updated due to negotiated smb buffer
 227         *        size shrinking
 228         */
 229        atomic_inc(&tconInfoReconnectCount);
 230
 231        /* tell server Unix caps we support */
 232        if (ses->capabilities & CAP_UNIX)
 233                reset_cifs_unix_caps(0, tcon, NULL, NULL);
 234
 235        /*
 236         * Removed call to reopen open files here. It is safer (and faster) to
 237         * reopen files one at a time as needed in read and write.
 238         *
 239         * FIXME: what about file locks? don't we need to reclaim them ASAP?
 240         */
 241
 242out:
 243        /*
 244         * Check if handle based operation so we know whether we can continue
 245         * or not without returning to caller to reset file handle
 246         */
 247        switch (smb_command) {
 248        case SMB_COM_READ_ANDX:
 249        case SMB_COM_WRITE_ANDX:
 250        case SMB_COM_CLOSE:
 251        case SMB_COM_FIND_CLOSE2:
 252        case SMB_COM_LOCKING_ANDX:
 253                rc = -EAGAIN;
 254        }
 255
 256        unload_nls(nls_codepage);
 257        return rc;
 258}
 259
 260/* Allocate and return pointer to an SMB request buffer, and set basic
 261   SMB information in the SMB header.  If the return code is zero, this
 262   function must have filled in request_buf pointer */
 263static int
 264small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
 265                void **request_buf)
 266{
 267        int rc;
 268
 269        rc = cifs_reconnect_tcon(tcon, smb_command);
 270        if (rc)
 271                return rc;
 272
 273        *request_buf = cifs_small_buf_get();
 274        if (*request_buf == NULL) {
 275                /* BB should we add a retry in here if not a writepage? */
 276                return -ENOMEM;
 277        }
 278
 279        header_assemble((struct smb_hdr *) *request_buf, smb_command,
 280                        tcon, wct);
 281
 282        if (tcon != NULL)
 283                cifs_stats_inc(&tcon->num_smbs_sent);
 284
 285        return 0;
 286}
 287
 288int
 289small_smb_init_no_tc(const int smb_command, const int wct,
 290                     struct cifs_ses *ses, void **request_buf)
 291{
 292        int rc;
 293        struct smb_hdr *buffer;
 294
 295        rc = small_smb_init(smb_command, wct, NULL, request_buf);
 296        if (rc)
 297                return rc;
 298
 299        buffer = (struct smb_hdr *)*request_buf;
 300        buffer->Mid = get_next_mid(ses->server);
 301        if (ses->capabilities & CAP_UNICODE)
 302                buffer->Flags2 |= SMBFLG2_UNICODE;
 303        if (ses->capabilities & CAP_STATUS32)
 304                buffer->Flags2 |= SMBFLG2_ERR_STATUS;
 305
 306        /* uid, tid can stay at zero as set in header assemble */
 307
 308        /* BB add support for turning on the signing when
 309        this function is used after 1st of session setup requests */
 310
 311        return rc;
 312}
 313
 314/* If the return code is zero, this function must fill in request_buf pointer */
 315static int
 316__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
 317                        void **request_buf, void **response_buf)
 318{
 319        *request_buf = cifs_buf_get();
 320        if (*request_buf == NULL) {
 321                /* BB should we add a retry in here if not a writepage? */
 322                return -ENOMEM;
 323        }
 324    /* Although the original thought was we needed the response buf for  */
 325    /* potential retries of smb operations it turns out we can determine */
 326    /* from the mid flags when the request buffer can be resent without  */
 327    /* having to use a second distinct buffer for the response */
 328        if (response_buf)
 329                *response_buf = *request_buf;
 330
 331        header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
 332                        wct);
 333
 334        if (tcon != NULL)
 335                cifs_stats_inc(&tcon->num_smbs_sent);
 336
 337        return 0;
 338}
 339
 340/* If the return code is zero, this function must fill in request_buf pointer */
 341static int
 342smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
 343         void **request_buf, void **response_buf)
 344{
 345        int rc;
 346
 347        rc = cifs_reconnect_tcon(tcon, smb_command);
 348        if (rc)
 349                return rc;
 350
 351        return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
 352}
 353
 354static int
 355smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
 356                        void **request_buf, void **response_buf)
 357{
 358        if (tcon->ses->need_reconnect || tcon->need_reconnect)
 359                return -EHOSTDOWN;
 360
 361        return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
 362}
 363
 364static int validate_t2(struct smb_t2_rsp *pSMB)
 365{
 366        unsigned int total_size;
 367
 368        /* check for plausible wct */
 369        if (pSMB->hdr.WordCount < 10)
 370                goto vt2_err;
 371
 372        /* check for parm and data offset going beyond end of smb */
 373        if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
 374            get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
 375                goto vt2_err;
 376
 377        total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
 378        if (total_size >= 512)
 379                goto vt2_err;
 380
 381        /* check that bcc is at least as big as parms + data, and that it is
 382         * less than negotiated smb buffer
 383         */
 384        total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
 385        if (total_size > get_bcc(&pSMB->hdr) ||
 386            total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
 387                goto vt2_err;
 388
 389        return 0;
 390vt2_err:
 391        cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
 392                sizeof(struct smb_t2_rsp) + 16);
 393        return -EINVAL;
 394}
 395
 396int
 397CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 398{
 399        NEGOTIATE_REQ *pSMB;
 400        NEGOTIATE_RSP *pSMBr;
 401        int rc = 0;
 402        int bytes_returned;
 403        int i;
 404        struct TCP_Server_Info *server;
 405        u16 count;
 406        unsigned int secFlags;
 407
 408        if (ses->server)
 409                server = ses->server;
 410        else {
 411                rc = -EIO;
 412                return rc;
 413        }
 414        rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
 415                      (void **) &pSMB, (void **) &pSMBr);
 416        if (rc)
 417                return rc;
 418
 419        /* if any of auth flags (ie not sign or seal) are overriden use them */
 420        if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
 421                secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
 422        else /* if override flags set only sign/seal OR them with global auth */
 423                secFlags = global_secflags | ses->overrideSecFlg;
 424
 425        cFYI(1, "secFlags 0x%x", secFlags);
 426
 427        pSMB->hdr.Mid = get_next_mid(server);
 428        pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
 429
 430        if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
 431                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 432        else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
 433                cFYI(1, "Kerberos only mechanism, enable extended security");
 434                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 435        } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
 436                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 437        else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
 438                cFYI(1, "NTLMSSP only mechanism, enable extended security");
 439                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 440        }
 441
 442        count = 0;
 443        for (i = 0; i < CIFS_NUM_PROT; i++) {
 444                strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
 445                count += strlen(protocols[i].name) + 1;
 446                /* null at end of source and target buffers anyway */
 447        }
 448        inc_rfc1001_len(pSMB, count);
 449        pSMB->ByteCount = cpu_to_le16(count);
 450
 451        rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 452                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 453        if (rc != 0)
 454                goto neg_err_exit;
 455
 456        server->dialect = le16_to_cpu(pSMBr->DialectIndex);
 457        cFYI(1, "Dialect: %d", server->dialect);
 458        /* Check wct = 1 error case */
 459        if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
 460                /* core returns wct = 1, but we do not ask for core - otherwise
 461                small wct just comes when dialect index is -1 indicating we
 462                could not negotiate a common dialect */
 463                rc = -EOPNOTSUPP;
 464                goto neg_err_exit;
 465#ifdef CONFIG_CIFS_WEAK_PW_HASH
 466        } else if ((pSMBr->hdr.WordCount == 13)
 467                        && ((server->dialect == LANMAN_PROT)
 468                                || (server->dialect == LANMAN2_PROT))) {
 469                __s16 tmp;
 470                struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
 471
 472                if ((secFlags & CIFSSEC_MAY_LANMAN) ||
 473                        (secFlags & CIFSSEC_MAY_PLNTXT))
 474                        server->secType = LANMAN;
 475                else {
 476                        cERROR(1, "mount failed weak security disabled"
 477                                   " in /proc/fs/cifs/SecurityFlags");
 478                        rc = -EOPNOTSUPP;
 479                        goto neg_err_exit;
 480                }
 481                server->sec_mode = le16_to_cpu(rsp->SecurityMode);
 482                server->maxReq = min_t(unsigned int,
 483                                       le16_to_cpu(rsp->MaxMpxCount),
 484                                       cifs_max_pending);
 485                set_credits(server, server->maxReq);
 486                server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
 487                server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
 488                /* even though we do not use raw we might as well set this
 489                accurately, in case we ever find a need for it */
 490                if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
 491                        server->max_rw = 0xFF00;
 492                        server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
 493                } else {
 494                        server->max_rw = 0;/* do not need to use raw anyway */
 495                        server->capabilities = CAP_MPX_MODE;
 496                }
 497                tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
 498                if (tmp == -1) {
 499                        /* OS/2 often does not set timezone therefore
 500                         * we must use server time to calc time zone.
 501                         * Could deviate slightly from the right zone.
 502                         * Smallest defined timezone difference is 15 minutes
 503                         * (i.e. Nepal).  Rounding up/down is done to match
 504                         * this requirement.
 505                         */
 506                        int val, seconds, remain, result;
 507                        struct timespec ts, utc;
 508                        utc = CURRENT_TIME;
 509                        ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
 510                                            rsp->SrvTime.Time, 0);
 511                        cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
 512                                (int)ts.tv_sec, (int)utc.tv_sec,
 513                                (int)(utc.tv_sec - ts.tv_sec));
 514                        val = (int)(utc.tv_sec - ts.tv_sec);
 515                        seconds = abs(val);
 516                        result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
 517                        remain = seconds % MIN_TZ_ADJ;
 518                        if (remain >= (MIN_TZ_ADJ / 2))
 519                                result += MIN_TZ_ADJ;
 520                        if (val < 0)
 521                                result = -result;
 522                        server->timeAdj = result;
 523                } else {
 524                        server->timeAdj = (int)tmp;
 525                        server->timeAdj *= 60; /* also in seconds */
 526                }
 527                cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
 528
 529
 530                /* BB get server time for time conversions and add
 531                code to use it and timezone since this is not UTC */
 532
 533                if (rsp->EncryptionKeyLength ==
 534                                cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
 535                        memcpy(ses->server->cryptkey, rsp->EncryptionKey,
 536                                CIFS_CRYPTO_KEY_SIZE);
 537                } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
 538                        rc = -EIO; /* need cryptkey unless plain text */
 539                        goto neg_err_exit;
 540                }
 541
 542                cFYI(1, "LANMAN negotiated");
 543                /* we will not end up setting signing flags - as no signing
 544                was in LANMAN and server did not return the flags on */
 545                goto signing_check;
 546#else /* weak security disabled */
 547        } else if (pSMBr->hdr.WordCount == 13) {
 548                cERROR(1, "mount failed, cifs module not built "
 549                          "with CIFS_WEAK_PW_HASH support");
 550                rc = -EOPNOTSUPP;
 551#endif /* WEAK_PW_HASH */
 552                goto neg_err_exit;
 553        } else if (pSMBr->hdr.WordCount != 17) {
 554                /* unknown wct */
 555                rc = -EOPNOTSUPP;
 556                goto neg_err_exit;
 557        }
 558        /* else wct == 17 NTLM */
 559        server->sec_mode = pSMBr->SecurityMode;
 560        if ((server->sec_mode & SECMODE_USER) == 0)
 561                cFYI(1, "share mode security");
 562
 563        if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
 564#ifdef CONFIG_CIFS_WEAK_PW_HASH
 565                if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
 566#endif /* CIFS_WEAK_PW_HASH */
 567                        cERROR(1, "Server requests plain text password"
 568                                  " but client support disabled");
 569
 570        if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
 571                server->secType = NTLMv2;
 572        else if (secFlags & CIFSSEC_MAY_NTLM)
 573                server->secType = NTLM;
 574        else if (secFlags & CIFSSEC_MAY_NTLMV2)
 575                server->secType = NTLMv2;
 576        else if (secFlags & CIFSSEC_MAY_KRB5)
 577                server->secType = Kerberos;
 578        else if (secFlags & CIFSSEC_MAY_NTLMSSP)
 579                server->secType = RawNTLMSSP;
 580        else if (secFlags & CIFSSEC_MAY_LANMAN)
 581                server->secType = LANMAN;
 582        else {
 583                rc = -EOPNOTSUPP;
 584                cERROR(1, "Invalid security type");
 585                goto neg_err_exit;
 586        }
 587        /* else ... any others ...? */
 588
 589        /* one byte, so no need to convert this or EncryptionKeyLen from
 590           little endian */
 591        server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
 592                               cifs_max_pending);
 593        set_credits(server, server->maxReq);
 594        /* probably no need to store and check maxvcs */
 595        server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
 596        server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
 597        cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
 598        server->capabilities = le32_to_cpu(pSMBr->Capabilities);
 599        server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
 600        server->timeAdj *= 60;
 601        if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
 602                memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
 603                       CIFS_CRYPTO_KEY_SIZE);
 604        } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
 605                        server->capabilities & CAP_EXTENDED_SECURITY) &&
 606                                (pSMBr->EncryptionKeyLength == 0)) {
 607                /* decode security blob */
 608                count = get_bcc(&pSMBr->hdr);
 609                if (count < 16) {
 610                        rc = -EIO;
 611                        goto neg_err_exit;
 612                }
 613                spin_lock(&cifs_tcp_ses_lock);
 614                if (server->srv_count > 1) {
 615                        spin_unlock(&cifs_tcp_ses_lock);
 616                        if (memcmp(server->server_GUID,
 617                                   pSMBr->u.extended_response.
 618                                   GUID, 16) != 0) {
 619                                cFYI(1, "server UID changed");
 620                                memcpy(server->server_GUID,
 621                                        pSMBr->u.extended_response.GUID,
 622                                        16);
 623                        }
 624                } else {
 625                        spin_unlock(&cifs_tcp_ses_lock);
 626                        memcpy(server->server_GUID,
 627                               pSMBr->u.extended_response.GUID, 16);
 628                }
 629
 630                if (count == 16) {
 631                        server->secType = RawNTLMSSP;
 632                } else {
 633                        rc = decode_negTokenInit(pSMBr->u.extended_response.
 634                                                 SecurityBlob, count - 16,
 635                                                 server);
 636                        if (rc == 1)
 637                                rc = 0;
 638                        else
 639                                rc = -EINVAL;
 640                        if (server->secType == Kerberos) {
 641                                if (!server->sec_kerberos &&
 642                                                !server->sec_mskerberos)
 643                                        rc = -EOPNOTSUPP;
 644                        } else if (server->secType == RawNTLMSSP) {
 645                                if (!server->sec_ntlmssp)
 646                                        rc = -EOPNOTSUPP;
 647                        } else
 648                                        rc = -EOPNOTSUPP;
 649                }
 650        } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
 651                rc = -EIO; /* no crypt key only if plain text pwd */
 652                goto neg_err_exit;
 653        } else
 654                server->capabilities &= ~CAP_EXTENDED_SECURITY;
 655
 656#ifdef CONFIG_CIFS_WEAK_PW_HASH
 657signing_check:
 658#endif
 659        if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
 660                /* MUST_SIGN already includes the MAY_SIGN FLAG
 661                   so if this is zero it means that signing is disabled */
 662                cFYI(1, "Signing disabled");
 663                if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
 664                        cERROR(1, "Server requires "
 665                                   "packet signing to be enabled in "
 666                                   "/proc/fs/cifs/SecurityFlags.");
 667                        rc = -EOPNOTSUPP;
 668                }
 669                server->sec_mode &=
 670                        ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
 671        } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
 672                /* signing required */
 673                cFYI(1, "Must sign - secFlags 0x%x", secFlags);
 674                if ((server->sec_mode &
 675                        (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
 676                        cERROR(1, "signing required but server lacks support");
 677                        rc = -EOPNOTSUPP;
 678                } else
 679                        server->sec_mode |= SECMODE_SIGN_REQUIRED;
 680        } else {
 681                /* signing optional ie CIFSSEC_MAY_SIGN */
 682                if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
 683                        server->sec_mode &=
 684                                ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
 685        }
 686
 687neg_err_exit:
 688        cifs_buf_release(pSMB);
 689
 690        cFYI(1, "negprot rc %d", rc);
 691        return rc;
 692}
 693
 694int
 695CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
 696{
 697        struct smb_hdr *smb_buffer;
 698        int rc = 0;
 699
 700        cFYI(1, "In tree disconnect");
 701
 702        /* BB: do we need to check this? These should never be NULL. */
 703        if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
 704                return -EIO;
 705
 706        /*
 707         * No need to return error on this operation if tid invalidated and
 708         * closed on server already e.g. due to tcp session crashing. Also,
 709         * the tcon is no longer on the list, so no need to take lock before
 710         * checking this.
 711         */
 712        if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
 713                return 0;
 714
 715        rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
 716                            (void **)&smb_buffer);
 717        if (rc)
 718                return rc;
 719
 720        rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
 721        if (rc)
 722                cFYI(1, "Tree disconnect failed %d", rc);
 723
 724        /* No need to return error on this operation if tid invalidated and
 725           closed on server already e.g. due to tcp session crashing */
 726        if (rc == -EAGAIN)
 727                rc = 0;
 728
 729        return rc;
 730}
 731
 732/*
 733 * This is a no-op for now. We're not really interested in the reply, but
 734 * rather in the fact that the server sent one and that server->lstrp
 735 * gets updated.
 736 *
 737 * FIXME: maybe we should consider checking that the reply matches request?
 738 */
 739static void
 740cifs_echo_callback(struct mid_q_entry *mid)
 741{
 742        struct TCP_Server_Info *server = mid->callback_data;
 743
 744        DeleteMidQEntry(mid);
 745        add_credits(server, 1, CIFS_ECHO_OP);
 746}
 747
 748int
 749CIFSSMBEcho(struct TCP_Server_Info *server)
 750{
 751        ECHO_REQ *smb;
 752        int rc = 0;
 753        struct kvec iov;
 754
 755        cFYI(1, "In echo request");
 756
 757        rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
 758        if (rc)
 759                return rc;
 760
 761        /* set up echo request */
 762        smb->hdr.Tid = 0xffff;
 763        smb->hdr.WordCount = 1;
 764        put_unaligned_le16(1, &smb->EchoCount);
 765        put_bcc(1, &smb->hdr);
 766        smb->Data[0] = 'a';
 767        inc_rfc1001_len(smb, 3);
 768        iov.iov_base = smb;
 769        iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
 770
 771        rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
 772                             server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
 773        if (rc)
 774                cFYI(1, "Echo request failed: %d", rc);
 775
 776        cifs_small_buf_release(smb);
 777
 778        return rc;
 779}
 780
 781int
 782CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
 783{
 784        LOGOFF_ANDX_REQ *pSMB;
 785        int rc = 0;
 786
 787        cFYI(1, "In SMBLogoff for session disconnect");
 788
 789        /*
 790         * BB: do we need to check validity of ses and server? They should
 791         * always be valid since we have an active reference. If not, that
 792         * should probably be a BUG()
 793         */
 794        if (!ses || !ses->server)
 795                return -EIO;
 796
 797        mutex_lock(&ses->session_mutex);
 798        if (ses->need_reconnect)
 799                goto session_already_dead; /* no need to send SMBlogoff if uid
 800                                              already closed due to reconnect */
 801        rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
 802        if (rc) {
 803                mutex_unlock(&ses->session_mutex);
 804                return rc;
 805        }
 806
 807        pSMB->hdr.Mid = get_next_mid(ses->server);
 808
 809        if (ses->server->sec_mode &
 810                   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 811                        pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 812
 813        pSMB->hdr.Uid = ses->Suid;
 814
 815        pSMB->AndXCommand = 0xFF;
 816        rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
 817session_already_dead:
 818        mutex_unlock(&ses->session_mutex);
 819
 820        /* if session dead then we do not need to do ulogoff,
 821                since server closed smb session, no sense reporting
 822                error */
 823        if (rc == -EAGAIN)
 824                rc = 0;
 825        return rc;
 826}
 827
 828int
 829CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
 830                 const char *fileName, __u16 type,
 831                 const struct nls_table *nls_codepage, int remap)
 832{
 833        TRANSACTION2_SPI_REQ *pSMB = NULL;
 834        TRANSACTION2_SPI_RSP *pSMBr = NULL;
 835        struct unlink_psx_rq *pRqD;
 836        int name_len;
 837        int rc = 0;
 838        int bytes_returned = 0;
 839        __u16 params, param_offset, offset, byte_count;
 840
 841        cFYI(1, "In POSIX delete");
 842PsxDelete:
 843        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 844                      (void **) &pSMBr);
 845        if (rc)
 846                return rc;
 847
 848        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 849                name_len =
 850                    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
 851                                       PATH_MAX, nls_codepage, remap);
 852                name_len++;     /* trailing null */
 853                name_len *= 2;
 854        } else { /* BB add path length overrun check */
 855                name_len = strnlen(fileName, PATH_MAX);
 856                name_len++;     /* trailing null */
 857                strncpy(pSMB->FileName, fileName, name_len);
 858        }
 859
 860        params = 6 + name_len;
 861        pSMB->MaxParameterCount = cpu_to_le16(2);
 862        pSMB->MaxDataCount = 0; /* BB double check this with jra */
 863        pSMB->MaxSetupCount = 0;
 864        pSMB->Reserved = 0;
 865        pSMB->Flags = 0;
 866        pSMB->Timeout = 0;
 867        pSMB->Reserved2 = 0;
 868        param_offset = offsetof(struct smb_com_transaction2_spi_req,
 869                                InformationLevel) - 4;
 870        offset = param_offset + params;
 871
 872        /* Setup pointer to Request Data (inode type) */
 873        pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
 874        pRqD->type = cpu_to_le16(type);
 875        pSMB->ParameterOffset = cpu_to_le16(param_offset);
 876        pSMB->DataOffset = cpu_to_le16(offset);
 877        pSMB->SetupCount = 1;
 878        pSMB->Reserved3 = 0;
 879        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
 880        byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
 881
 882        pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
 883        pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
 884        pSMB->ParameterCount = cpu_to_le16(params);
 885        pSMB->TotalParameterCount = pSMB->ParameterCount;
 886        pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
 887        pSMB->Reserved4 = 0;
 888        inc_rfc1001_len(pSMB, byte_count);
 889        pSMB->ByteCount = cpu_to_le16(byte_count);
 890        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 891                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 892        if (rc)
 893                cFYI(1, "Posix delete returned %d", rc);
 894        cifs_buf_release(pSMB);
 895
 896        cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 897
 898        if (rc == -EAGAIN)
 899                goto PsxDelete;
 900
 901        return rc;
 902}
 903
 904int
 905CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
 906               const char *fileName, const struct nls_table *nls_codepage,
 907               int remap)
 908{
 909        DELETE_FILE_REQ *pSMB = NULL;
 910        DELETE_FILE_RSP *pSMBr = NULL;
 911        int rc = 0;
 912        int bytes_returned;
 913        int name_len;
 914
 915DelFileRetry:
 916        rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
 917                      (void **) &pSMBr);
 918        if (rc)
 919                return rc;
 920
 921        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 922                name_len =
 923                    cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
 924                                       PATH_MAX, nls_codepage, remap);
 925                name_len++;     /* trailing null */
 926                name_len *= 2;
 927        } else {                /* BB improve check for buffer overruns BB */
 928                name_len = strnlen(fileName, PATH_MAX);
 929                name_len++;     /* trailing null */
 930                strncpy(pSMB->fileName, fileName, name_len);
 931        }
 932        pSMB->SearchAttributes =
 933            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
 934        pSMB->BufferFormat = 0x04;
 935        inc_rfc1001_len(pSMB, name_len + 1);
 936        pSMB->ByteCount = cpu_to_le16(name_len + 1);
 937        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 938                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 939        cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 940        if (rc)
 941                cFYI(1, "Error in RMFile = %d", rc);
 942
 943        cifs_buf_release(pSMB);
 944        if (rc == -EAGAIN)
 945                goto DelFileRetry;
 946
 947        return rc;
 948}
 949
 950int
 951CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 952             struct cifs_sb_info *cifs_sb)
 953{
 954        DELETE_DIRECTORY_REQ *pSMB = NULL;
 955        DELETE_DIRECTORY_RSP *pSMBr = NULL;
 956        int rc = 0;
 957        int bytes_returned;
 958        int name_len;
 959        int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 960
 961        cFYI(1, "In CIFSSMBRmDir");
 962RmDirRetry:
 963        rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
 964                      (void **) &pSMBr);
 965        if (rc)
 966                return rc;
 967
 968        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 969                name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
 970                                              PATH_MAX, cifs_sb->local_nls,
 971                                              remap);
 972                name_len++;     /* trailing null */
 973                name_len *= 2;
 974        } else {                /* BB improve check for buffer overruns BB */
 975                name_len = strnlen(name, PATH_MAX);
 976                name_len++;     /* trailing null */
 977                strncpy(pSMB->DirName, name, name_len);
 978        }
 979
 980        pSMB->BufferFormat = 0x04;
 981        inc_rfc1001_len(pSMB, name_len + 1);
 982        pSMB->ByteCount = cpu_to_le16(name_len + 1);
 983        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 984                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 985        cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
 986        if (rc)
 987                cFYI(1, "Error in RMDir = %d", rc);
 988
 989        cifs_buf_release(pSMB);
 990        if (rc == -EAGAIN)
 991                goto RmDirRetry;
 992        return rc;
 993}
 994
 995int
 996CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 997             struct cifs_sb_info *cifs_sb)
 998{
 999        int rc = 0;
1000        CREATE_DIRECTORY_REQ *pSMB = NULL;
1001        CREATE_DIRECTORY_RSP *pSMBr = NULL;
1002        int bytes_returned;
1003        int name_len;
1004        int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
1005
1006        cFYI(1, "In CIFSSMBMkDir");
1007MkDirRetry:
1008        rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1009                      (void **) &pSMBr);
1010        if (rc)
1011                return rc;
1012
1013        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1014                name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1015                                              PATH_MAX, cifs_sb->local_nls,
1016                                              remap);
1017                name_len++;     /* trailing null */
1018                name_len *= 2;
1019        } else {                /* BB improve check for buffer overruns BB */
1020                name_len = strnlen(name, PATH_MAX);
1021                name_len++;     /* trailing null */
1022                strncpy(pSMB->DirName, name, name_len);
1023        }
1024
1025        pSMB->BufferFormat = 0x04;
1026        inc_rfc1001_len(pSMB, name_len + 1);
1027        pSMB->ByteCount = cpu_to_le16(name_len + 1);
1028        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1029                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1030        cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1031        if (rc)
1032                cFYI(1, "Error in Mkdir = %d", rc);
1033
1034        cifs_buf_release(pSMB);
1035        if (rc == -EAGAIN)
1036                goto MkDirRetry;
1037        return rc;
1038}
1039
1040int
1041CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1042                __u32 posix_flags, __u64 mode, __u16 *netfid,
1043                FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1044                const char *name, const struct nls_table *nls_codepage,
1045                int remap)
1046{
1047        TRANSACTION2_SPI_REQ *pSMB = NULL;
1048        TRANSACTION2_SPI_RSP *pSMBr = NULL;
1049        int name_len;
1050        int rc = 0;
1051        int bytes_returned = 0;
1052        __u16 params, param_offset, offset, byte_count, count;
1053        OPEN_PSX_REQ *pdata;
1054        OPEN_PSX_RSP *psx_rsp;
1055
1056        cFYI(1, "In POSIX Create");
1057PsxCreat:
1058        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1059                      (void **) &pSMBr);
1060        if (rc)
1061                return rc;
1062
1063        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1064                name_len =
1065                    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1066                                       PATH_MAX, nls_codepage, remap);
1067                name_len++;     /* trailing null */
1068                name_len *= 2;
1069        } else {        /* BB improve the check for buffer overruns BB */
1070                name_len = strnlen(name, PATH_MAX);
1071                name_len++;     /* trailing null */
1072                strncpy(pSMB->FileName, name, name_len);
1073        }
1074
1075        params = 6 + name_len;
1076        count = sizeof(OPEN_PSX_REQ);
1077        pSMB->MaxParameterCount = cpu_to_le16(2);
1078        pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1079        pSMB->MaxSetupCount = 0;
1080        pSMB->Reserved = 0;
1081        pSMB->Flags = 0;
1082        pSMB->Timeout = 0;
1083        pSMB->Reserved2 = 0;
1084        param_offset = offsetof(struct smb_com_transaction2_spi_req,
1085                                InformationLevel) - 4;
1086        offset = param_offset + params;
1087        pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1088        pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1089        pdata->Permissions = cpu_to_le64(mode);
1090        pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1091        pdata->OpenFlags =  cpu_to_le32(*pOplock);
1092        pSMB->ParameterOffset = cpu_to_le16(param_offset);
1093        pSMB->DataOffset = cpu_to_le16(offset);
1094        pSMB->SetupCount = 1;
1095        pSMB->Reserved3 = 0;
1096        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1097        byte_count = 3 /* pad */  + params + count;
1098
1099        pSMB->DataCount = cpu_to_le16(count);
1100        pSMB->ParameterCount = cpu_to_le16(params);
1101        pSMB->TotalDataCount = pSMB->DataCount;
1102        pSMB->TotalParameterCount = pSMB->ParameterCount;
1103        pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1104        pSMB->Reserved4 = 0;
1105        inc_rfc1001_len(pSMB, byte_count);
1106        pSMB->ByteCount = cpu_to_le16(byte_count);
1107        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1108                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1109        if (rc) {
1110                cFYI(1, "Posix create returned %d", rc);
1111                goto psx_create_err;
1112        }
1113
1114        cFYI(1, "copying inode info");
1115        rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1116
1117        if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1118                rc = -EIO;      /* bad smb */
1119                goto psx_create_err;
1120        }
1121
1122        /* copy return information to pRetData */
1123        psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1124                        + le16_to_cpu(pSMBr->t2.DataOffset));
1125
1126        *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1127        if (netfid)
1128                *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1129        /* Let caller know file was created so we can set the mode. */
1130        /* Do we care about the CreateAction in any other cases? */
1131        if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1132                *pOplock |= CIFS_CREATE_ACTION;
1133        /* check to make sure response data is there */
1134        if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1135                pRetData->Type = cpu_to_le32(-1); /* unknown */
1136                cFYI(DBG2, "unknown type");
1137        } else {
1138                if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1139                                        + sizeof(FILE_UNIX_BASIC_INFO)) {
1140                        cERROR(1, "Open response data too small");
1141                        pRetData->Type = cpu_to_le32(-1);
1142                        goto psx_create_err;
1143                }
1144                memcpy((char *) pRetData,
1145                        (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1146                        sizeof(FILE_UNIX_BASIC_INFO));
1147        }
1148
1149psx_create_err:
1150        cifs_buf_release(pSMB);
1151
1152        if (posix_flags & SMB_O_DIRECTORY)
1153                cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1154        else
1155                cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1156
1157        if (rc == -EAGAIN)
1158                goto PsxCreat;
1159
1160        return rc;
1161}
1162
1163static __u16 convert_disposition(int disposition)
1164{
1165        __u16 ofun = 0;
1166
1167        switch (disposition) {
1168                case FILE_SUPERSEDE:
1169                        ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1170                        break;
1171                case FILE_OPEN:
1172                        ofun = SMBOPEN_OAPPEND;
1173                        break;
1174                case FILE_CREATE:
1175                        ofun = SMBOPEN_OCREATE;
1176                        break;
1177                case FILE_OPEN_IF:
1178                        ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1179                        break;
1180                case FILE_OVERWRITE:
1181                        ofun = SMBOPEN_OTRUNC;
1182                        break;
1183                case FILE_OVERWRITE_IF:
1184                        ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1185                        break;
1186                default:
1187                        cFYI(1, "unknown disposition %d", disposition);
1188                        ofun =  SMBOPEN_OAPPEND; /* regular open */
1189        }
1190        return ofun;
1191}
1192
1193static int
1194access_flags_to_smbopen_mode(const int access_flags)
1195{
1196        int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1197
1198        if (masked_flags == GENERIC_READ)
1199                return SMBOPEN_READ;
1200        else if (masked_flags == GENERIC_WRITE)
1201                return SMBOPEN_WRITE;
1202
1203        /* just go for read/write */
1204        return SMBOPEN_READWRITE;
1205}
1206
1207int
1208SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1209            const char *fileName, const int openDisposition,
1210            const int access_flags, const int create_options, __u16 *netfid,
1211            int *pOplock, FILE_ALL_INFO *pfile_info,
1212            const struct nls_table *nls_codepage, int remap)
1213{
1214        int rc = -EACCES;
1215        OPENX_REQ *pSMB = NULL;
1216        OPENX_RSP *pSMBr = NULL;
1217        int bytes_returned;
1218        int name_len;
1219        __u16 count;
1220
1221OldOpenRetry:
1222        rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1223                      (void **) &pSMBr);
1224        if (rc)
1225                return rc;
1226
1227        pSMB->AndXCommand = 0xFF;       /* none */
1228
1229        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1230                count = 1;      /* account for one byte pad to word boundary */
1231                name_len =
1232                   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1233                                      fileName, PATH_MAX, nls_codepage, remap);
1234                name_len++;     /* trailing null */
1235                name_len *= 2;
1236        } else {                /* BB improve check for buffer overruns BB */
1237                count = 0;      /* no pad */
1238                name_len = strnlen(fileName, PATH_MAX);
1239                name_len++;     /* trailing null */
1240                strncpy(pSMB->fileName, fileName, name_len);
1241        }
1242        if (*pOplock & REQ_OPLOCK)
1243                pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1244        else if (*pOplock & REQ_BATCHOPLOCK)
1245                pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1246
1247        pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1248        pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1249        pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1250        /* set file as system file if special file such
1251           as fifo and server expecting SFU style and
1252           no Unix extensions */
1253
1254        if (create_options & CREATE_OPTION_SPECIAL)
1255                pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1256        else /* BB FIXME BB */
1257                pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1258
1259        if (create_options & CREATE_OPTION_READONLY)
1260                pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1261
1262        /* BB FIXME BB */
1263/*      pSMB->CreateOptions = cpu_to_le32(create_options &
1264                                                 CREATE_OPTIONS_MASK); */
1265        /* BB FIXME END BB */
1266
1267        pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1268        pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1269        count += name_len;
1270        inc_rfc1001_len(pSMB, count);
1271
1272        pSMB->ByteCount = cpu_to_le16(count);
1273        /* long_op set to 1 to allow for oplock break timeouts */
1274        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1275                        (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1276        cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1277        if (rc) {
1278                cFYI(1, "Error in Open = %d", rc);
1279        } else {
1280        /* BB verify if wct == 15 */
1281
1282/*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1283
1284                *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1285                /* Let caller know file was created so we can set the mode. */
1286                /* Do we care about the CreateAction in any other cases? */
1287        /* BB FIXME BB */
1288/*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1289                        *pOplock |= CIFS_CREATE_ACTION; */
1290        /* BB FIXME END */
1291
1292                if (pfile_info) {
1293                        pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1294                        pfile_info->LastAccessTime = 0; /* BB fixme */
1295                        pfile_info->LastWriteTime = 0; /* BB fixme */
1296                        pfile_info->ChangeTime = 0;  /* BB fixme */
1297                        pfile_info->Attributes =
1298                                cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1299                        /* the file_info buf is endian converted by caller */
1300                        pfile_info->AllocationSize =
1301                                cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1302                        pfile_info->EndOfFile = pfile_info->AllocationSize;
1303                        pfile_info->NumberOfLinks = cpu_to_le32(1);
1304                        pfile_info->DeletePending = 0;
1305                }
1306        }
1307
1308        cifs_buf_release(pSMB);
1309        if (rc == -EAGAIN)
1310                goto OldOpenRetry;
1311        return rc;
1312}
1313
1314int
1315CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1316            const char *fileName, const int openDisposition,
1317            const int access_flags, const int create_options, __u16 *netfid,
1318            int *pOplock, FILE_ALL_INFO *pfile_info,
1319            const struct nls_table *nls_codepage, int remap)
1320{
1321        int rc = -EACCES;
1322        OPEN_REQ *pSMB = NULL;
1323        OPEN_RSP *pSMBr = NULL;
1324        int bytes_returned;
1325        int name_len;
1326        __u16 count;
1327
1328openRetry:
1329        rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1330                      (void **) &pSMBr);
1331        if (rc)
1332                return rc;
1333
1334        pSMB->AndXCommand = 0xFF;       /* none */
1335
1336        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1337                count = 1;      /* account for one byte pad to word boundary */
1338                name_len =
1339                    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1340                                       fileName, PATH_MAX, nls_codepage, remap);
1341                name_len++;     /* trailing null */
1342                name_len *= 2;
1343                pSMB->NameLength = cpu_to_le16(name_len);
1344        } else {                /* BB improve check for buffer overruns BB */
1345                count = 0;      /* no pad */
1346                name_len = strnlen(fileName, PATH_MAX);
1347                name_len++;     /* trailing null */
1348                pSMB->NameLength = cpu_to_le16(name_len);
1349                strncpy(pSMB->fileName, fileName, name_len);
1350        }
1351        if (*pOplock & REQ_OPLOCK)
1352                pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1353        else if (*pOplock & REQ_BATCHOPLOCK)
1354                pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1355        pSMB->DesiredAccess = cpu_to_le32(access_flags);
1356        pSMB->AllocationSize = 0;
1357        /* set file as system file if special file such
1358           as fifo and server expecting SFU style and
1359           no Unix extensions */
1360        if (create_options & CREATE_OPTION_SPECIAL)
1361                pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1362        else
1363                pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1364
1365        /* XP does not handle ATTR_POSIX_SEMANTICS */
1366        /* but it helps speed up case sensitive checks for other
1367        servers such as Samba */
1368        if (tcon->ses->capabilities & CAP_UNIX)
1369                pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1370
1371        if (create_options & CREATE_OPTION_READONLY)
1372                pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1373
1374        pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1375        pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1376        pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1377        /* BB Expirement with various impersonation levels and verify */
1378        pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1379        pSMB->SecurityFlags =
1380            SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1381
1382        count += name_len;
1383        inc_rfc1001_len(pSMB, count);
1384
1385        pSMB->ByteCount = cpu_to_le16(count);
1386        /* long_op set to 1 to allow for oplock break timeouts */
1387        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1388                        (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1389        cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1390        if (rc) {
1391                cFYI(1, "Error in Open = %d", rc);
1392        } else {
1393                *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1394                *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1395                /* Let caller know file was created so we can set the mode. */
1396                /* Do we care about the CreateAction in any other cases? */
1397                if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1398                        *pOplock |= CIFS_CREATE_ACTION;
1399                if (pfile_info) {
1400                        memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1401                                36 /* CreationTime to Attributes */);
1402                        /* the file_info buf is endian converted by caller */
1403                        pfile_info->AllocationSize = pSMBr->AllocationSize;
1404                        pfile_info->EndOfFile = pSMBr->EndOfFile;
1405                        pfile_info->NumberOfLinks = cpu_to_le32(1);
1406                        pfile_info->DeletePending = 0;
1407                }
1408        }
1409
1410        cifs_buf_release(pSMB);
1411        if (rc == -EAGAIN)
1412                goto openRetry;
1413        return rc;
1414}
1415
1416/*
1417 * Discard any remaining data in the current SMB. To do this, we borrow the
1418 * current bigbuf.
1419 */
1420static int
1421cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1422{
1423        unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1424        int remaining = rfclen + 4 - server->total_read;
1425        struct cifs_readdata *rdata = mid->callback_data;
1426
1427        while (remaining > 0) {
1428                int length;
1429
1430                length = cifs_read_from_socket(server, server->bigbuf,
1431                                min_t(unsigned int, remaining,
1432                                    CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1433                if (length < 0)
1434                        return length;
1435                server->total_read += length;
1436                remaining -= length;
1437        }
1438
1439        dequeue_mid(mid, rdata->result);
1440        return 0;
1441}
1442
1443static int
1444cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1445{
1446        int length, len;
1447        unsigned int data_offset, data_len;
1448        struct cifs_readdata *rdata = mid->callback_data;
1449        char *buf = server->smallbuf;
1450        unsigned int buflen = get_rfc1002_length(buf) + 4;
1451
1452        cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1453                mid->mid, rdata->offset, rdata->bytes);
1454
1455        /*
1456         * read the rest of READ_RSP header (sans Data array), or whatever we
1457         * can if there's not enough data. At this point, we've read down to
1458         * the Mid.
1459         */
1460        len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1461                                                        HEADER_SIZE(server) + 1;
1462
1463        rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1464        rdata->iov[0].iov_len = len;
1465
1466        length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1467        if (length < 0)
1468                return length;
1469        server->total_read += length;
1470
1471        /* Was the SMB read successful? */
1472        rdata->result = server->ops->map_error(buf, false);
1473        if (rdata->result != 0) {
1474                cFYI(1, "%s: server returned error %d", __func__,
1475                        rdata->result);
1476                return cifs_readv_discard(server, mid);
1477        }
1478
1479        /* Is there enough to get to the rest of the READ_RSP header? */
1480        if (server->total_read < server->vals->read_rsp_size) {
1481                cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1482                        __func__, server->total_read,
1483                        server->vals->read_rsp_size);
1484                rdata->result = -EIO;
1485                return cifs_readv_discard(server, mid);
1486        }
1487
1488        data_offset = server->ops->read_data_offset(buf) + 4;
1489        if (data_offset < server->total_read) {
1490                /*
1491                 * win2k8 sometimes sends an offset of 0 when the read
1492                 * is beyond the EOF. Treat it as if the data starts just after
1493                 * the header.
1494                 */
1495                cFYI(1, "%s: data offset (%u) inside read response header",
1496                        __func__, data_offset);
1497                data_offset = server->total_read;
1498        } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1499                /* data_offset is beyond the end of smallbuf */
1500                cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1501                        __func__, data_offset);
1502                rdata->result = -EIO;
1503                return cifs_readv_discard(server, mid);
1504        }
1505
1506        cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1507                server->total_read, data_offset);
1508
1509        len = data_offset - server->total_read;
1510        if (len > 0) {
1511                /* read any junk before data into the rest of smallbuf */
1512                rdata->iov[0].iov_base = buf + server->total_read;
1513                rdata->iov[0].iov_len = len;
1514                length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1515                if (length < 0)
1516                        return length;
1517                server->total_read += length;
1518        }
1519
1520        /* set up first iov for signature check */
1521        rdata->iov[0].iov_base = buf;
1522        rdata->iov[0].iov_len = server->total_read;
1523        cFYI(1, "0: iov_base=%p iov_len=%zu",
1524                rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1525
1526        /* how much data is in the response? */
1527        data_len = server->ops->read_data_length(buf);
1528        if (data_offset + data_len > buflen) {
1529                /* data_len is corrupt -- discard frame */
1530                rdata->result = -EIO;
1531                return cifs_readv_discard(server, mid);
1532        }
1533
1534        /* marshal up the page array */
1535        cifs_kmap_lock();
1536        len = rdata->marshal_iov(rdata, data_len);
1537        cifs_kmap_unlock();
1538        data_len -= len;
1539
1540        /* issue the read if we have any iovecs left to fill */
1541        if (rdata->nr_iov > 1) {
1542                length = cifs_readv_from_socket(server, &rdata->iov[1],
1543                                                rdata->nr_iov - 1, len);
1544                if (length < 0)
1545                        return length;
1546                server->total_read += length;
1547        } else {
1548                length = 0;
1549        }
1550
1551        rdata->bytes = length;
1552
1553        cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1554                buflen, data_len);
1555
1556        /* discard anything left over */
1557        if (server->total_read < buflen)
1558                return cifs_readv_discard(server, mid);
1559
1560        dequeue_mid(mid, false);
1561        return length;
1562}
1563
1564static void
1565cifs_readv_callback(struct mid_q_entry *mid)
1566{
1567        struct cifs_readdata *rdata = mid->callback_data;
1568        struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1569        struct TCP_Server_Info *server = tcon->ses->server;
1570
1571        cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1572                mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1573
1574        switch (mid->mid_state) {
1575        case MID_RESPONSE_RECEIVED:
1576                /* result already set, check signature */
1577                if (server->sec_mode &
1578                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1579                        int rc = 0;
1580
1581                        rc = cifs_verify_signature(rdata->iov, rdata->nr_iov,
1582                                                   server,
1583                                                   mid->sequence_number + 1);
1584                        if (rc)
1585                                cERROR(1, "SMB signature verification returned "
1586                                       "error = %d", rc);
1587                }
1588                /* FIXME: should this be counted toward the initiating task? */
1589                task_io_account_read(rdata->bytes);
1590                cifs_stats_bytes_read(tcon, rdata->bytes);
1591                break;
1592        case MID_REQUEST_SUBMITTED:
1593        case MID_RETRY_NEEDED:
1594                rdata->result = -EAGAIN;
1595                break;
1596        default:
1597                rdata->result = -EIO;
1598        }
1599
1600        queue_work(cifsiod_wq, &rdata->work);
1601        DeleteMidQEntry(mid);
1602        add_credits(server, 1, 0);
1603}
1604
1605/* cifs_async_readv - send an async write, and set up mid to handle result */
1606int
1607cifs_async_readv(struct cifs_readdata *rdata)
1608{
1609        int rc;
1610        READ_REQ *smb = NULL;
1611        int wct;
1612        struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1613
1614        cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1615                rdata->offset, rdata->bytes);
1616
1617        if (tcon->ses->capabilities & CAP_LARGE_FILES)
1618                wct = 12;
1619        else {
1620                wct = 10; /* old style read */
1621                if ((rdata->offset >> 32) > 0)  {
1622                        /* can not handle this big offset for old */
1623                        return -EIO;
1624                }
1625        }
1626
1627        rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1628        if (rc)
1629                return rc;
1630
1631        smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1632        smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1633
1634        smb->AndXCommand = 0xFF;        /* none */
1635        smb->Fid = rdata->cfile->netfid;
1636        smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1637        if (wct == 12)
1638                smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1639        smb->Remaining = 0;
1640        smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1641        smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1642        if (wct == 12)
1643                smb->ByteCount = 0;
1644        else {
1645                /* old style read */
1646                struct smb_com_readx_req *smbr =
1647                        (struct smb_com_readx_req *)smb;
1648                smbr->ByteCount = 0;
1649        }
1650
1651        /* 4 for RFC1001 length + 1 for BCC */
1652        rdata->iov[0].iov_base = smb;
1653        rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1654
1655        kref_get(&rdata->refcount);
1656        rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1657                             cifs_readv_receive, cifs_readv_callback,
1658                             rdata, 0);
1659
1660        if (rc == 0)
1661                cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1662        else
1663                kref_put(&rdata->refcount, cifs_readdata_release);
1664
1665        cifs_small_buf_release(smb);
1666        return rc;
1667}
1668
1669int
1670CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1671            unsigned int *nbytes, char **buf, int *pbuf_type)
1672{
1673        int rc = -EACCES;
1674        READ_REQ *pSMB = NULL;
1675        READ_RSP *pSMBr = NULL;
1676        char *pReadData = NULL;
1677        int wct;
1678        int resp_buf_type = 0;
1679        struct kvec iov[1];
1680        __u32 pid = io_parms->pid;
1681        __u16 netfid = io_parms->netfid;
1682        __u64 offset = io_parms->offset;
1683        struct cifs_tcon *tcon = io_parms->tcon;
1684        unsigned int count = io_parms->length;
1685
1686        cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1687        if (tcon->ses->capabilities & CAP_LARGE_FILES)
1688                wct = 12;
1689        else {
1690                wct = 10; /* old style read */
1691                if ((offset >> 32) > 0)  {
1692                        /* can not handle this big offset for old */
1693                        return -EIO;
1694                }
1695        }
1696
1697        *nbytes = 0;
1698        rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1699        if (rc)
1700                return rc;
1701
1702        pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1703        pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1704
1705        /* tcon and ses pointer are checked in smb_init */
1706        if (tcon->ses->server == NULL)
1707                return -ECONNABORTED;
1708
1709        pSMB->AndXCommand = 0xFF;       /* none */
1710        pSMB->Fid = netfid;
1711        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1712        if (wct == 12)
1713                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1714
1715        pSMB->Remaining = 0;
1716        pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1717        pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1718        if (wct == 12)
1719                pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1720        else {
1721                /* old style read */
1722                struct smb_com_readx_req *pSMBW =
1723                        (struct smb_com_readx_req *)pSMB;
1724                pSMBW->ByteCount = 0;
1725        }
1726
1727        iov[0].iov_base = (char *)pSMB;
1728        iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1729        rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1730                         &resp_buf_type, CIFS_LOG_ERROR);
1731        cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1732        pSMBr = (READ_RSP *)iov[0].iov_base;
1733        if (rc) {
1734                cERROR(1, "Send error in read = %d", rc);
1735        } else {
1736                int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1737                data_length = data_length << 16;
1738                data_length += le16_to_cpu(pSMBr->DataLength);
1739                *nbytes = data_length;
1740
1741                /*check that DataLength would not go beyond end of SMB */
1742                if ((data_length > CIFSMaxBufSize)
1743                                || (data_length > count)) {
1744                        cFYI(1, "bad length %d for count %d",
1745                                 data_length, count);
1746                        rc = -EIO;
1747                        *nbytes = 0;
1748                } else {
1749                        pReadData = (char *) (&pSMBr->hdr.Protocol) +
1750                                        le16_to_cpu(pSMBr->DataOffset);
1751/*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1752                                cERROR(1, "Faulting on read rc = %d",rc);
1753                                rc = -EFAULT;
1754                        }*/ /* can not use copy_to_user when using page cache*/
1755                        if (*buf)
1756                                memcpy(*buf, pReadData, data_length);
1757                }
1758        }
1759
1760/*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1761        if (*buf) {
1762                if (resp_buf_type == CIFS_SMALL_BUFFER)
1763                        cifs_small_buf_release(iov[0].iov_base);
1764                else if (resp_buf_type == CIFS_LARGE_BUFFER)
1765                        cifs_buf_release(iov[0].iov_base);
1766        } else if (resp_buf_type != CIFS_NO_BUFFER) {
1767                /* return buffer to caller to free */
1768                *buf = iov[0].iov_base;
1769                if (resp_buf_type == CIFS_SMALL_BUFFER)
1770                        *pbuf_type = CIFS_SMALL_BUFFER;
1771                else if (resp_buf_type == CIFS_LARGE_BUFFER)
1772                        *pbuf_type = CIFS_LARGE_BUFFER;
1773        } /* else no valid buffer on return - leave as null */
1774
1775        /* Note: On -EAGAIN error only caller can retry on handle based calls
1776                since file handle passed in no longer valid */
1777        return rc;
1778}
1779
1780
1781int
1782CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1783             unsigned int *nbytes, const char *buf,
1784             const char __user *ubuf, const int long_op)
1785{
1786        int rc = -EACCES;
1787        WRITE_REQ *pSMB = NULL;
1788        WRITE_RSP *pSMBr = NULL;
1789        int bytes_returned, wct;
1790        __u32 bytes_sent;
1791        __u16 byte_count;
1792        __u32 pid = io_parms->pid;
1793        __u16 netfid = io_parms->netfid;
1794        __u64 offset = io_parms->offset;
1795        struct cifs_tcon *tcon = io_parms->tcon;
1796        unsigned int count = io_parms->length;
1797
1798        *nbytes = 0;
1799
1800        /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1801        if (tcon->ses == NULL)
1802                return -ECONNABORTED;
1803
1804        if (tcon->ses->capabilities & CAP_LARGE_FILES)
1805                wct = 14;
1806        else {
1807                wct = 12;
1808                if ((offset >> 32) > 0) {
1809                        /* can not handle big offset for old srv */
1810                        return -EIO;
1811                }
1812        }
1813
1814        rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1815                      (void **) &pSMBr);
1816        if (rc)
1817                return rc;
1818
1819        pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1820        pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1821
1822        /* tcon and ses pointer are checked in smb_init */
1823        if (tcon->ses->server == NULL)
1824                return -ECONNABORTED;
1825
1826        pSMB->AndXCommand = 0xFF;       /* none */
1827        pSMB->Fid = netfid;
1828        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1829        if (wct == 14)
1830                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1831
1832        pSMB->Reserved = 0xFFFFFFFF;
1833        pSMB->WriteMode = 0;
1834        pSMB->Remaining = 0;
1835
1836        /* Can increase buffer size if buffer is big enough in some cases ie we
1837        can send more if LARGE_WRITE_X capability returned by the server and if
1838        our buffer is big enough or if we convert to iovecs on socket writes
1839        and eliminate the copy to the CIFS buffer */
1840        if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1841                bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1842        } else {
1843                bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1844                         & ~0xFF;
1845        }
1846
1847        if (bytes_sent > count)
1848                bytes_sent = count;
1849        pSMB->DataOffset =
1850                cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1851        if (buf)
1852                memcpy(pSMB->Data, buf, bytes_sent);
1853        else if (ubuf) {
1854                if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1855                        cifs_buf_release(pSMB);
1856                        return -EFAULT;
1857                }
1858        } else if (count != 0) {
1859                /* No buffer */
1860                cifs_buf_release(pSMB);
1861                return -EINVAL;
1862        } /* else setting file size with write of zero bytes */
1863        if (wct == 14)
1864                byte_count = bytes_sent + 1; /* pad */
1865        else /* wct == 12 */
1866                byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1867
1868        pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1869        pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1870        inc_rfc1001_len(pSMB, byte_count);
1871
1872        if (wct == 14)
1873                pSMB->ByteCount = cpu_to_le16(byte_count);
1874        else { /* old style write has byte count 4 bytes earlier
1875                  so 4 bytes pad  */
1876                struct smb_com_writex_req *pSMBW =
1877                        (struct smb_com_writex_req *)pSMB;
1878                pSMBW->ByteCount = cpu_to_le16(byte_count);
1879        }
1880
1881        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1882                         (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1883        cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1884        if (rc) {
1885                cFYI(1, "Send error in write = %d", rc);
1886        } else {
1887                *nbytes = le16_to_cpu(pSMBr->CountHigh);
1888                *nbytes = (*nbytes) << 16;
1889                *nbytes += le16_to_cpu(pSMBr->Count);
1890
1891                /*
1892                 * Mask off high 16 bits when bytes written as returned by the
1893                 * server is greater than bytes requested by the client. Some
1894                 * OS/2 servers are known to set incorrect CountHigh values.
1895                 */
1896                if (*nbytes > count)
1897                        *nbytes &= 0xFFFF;
1898        }
1899
1900        cifs_buf_release(pSMB);
1901
1902        /* Note: On -EAGAIN error only caller can retry on handle based calls
1903                since file handle passed in no longer valid */
1904
1905        return rc;
1906}
1907
1908void
1909cifs_writedata_release(struct kref *refcount)
1910{
1911        struct cifs_writedata *wdata = container_of(refcount,
1912                                        struct cifs_writedata, refcount);
1913
1914        if (wdata->cfile)
1915                cifsFileInfo_put(wdata->cfile);
1916
1917        kfree(wdata);
1918}
1919
1920/*
1921 * Write failed with a retryable error. Resend the write request. It's also
1922 * possible that the page was redirtied so re-clean the page.
1923 */
1924static void
1925cifs_writev_requeue(struct cifs_writedata *wdata)
1926{
1927        int i, rc;
1928        struct inode *inode = wdata->cfile->dentry->d_inode;
1929
1930        for (i = 0; i < wdata->nr_pages; i++) {
1931                lock_page(wdata->pages[i]);
1932                clear_page_dirty_for_io(wdata->pages[i]);
1933        }
1934
1935        do {
1936                rc = cifs_async_writev(wdata);
1937        } while (rc == -EAGAIN);
1938
1939        for (i = 0; i < wdata->nr_pages; i++) {
1940                if (rc != 0)
1941                        SetPageError(wdata->pages[i]);
1942                unlock_page(wdata->pages[i]);
1943        }
1944
1945        mapping_set_error(inode->i_mapping, rc);
1946        kref_put(&wdata->refcount, cifs_writedata_release);
1947}
1948
1949void
1950cifs_writev_complete(struct work_struct *work)
1951{
1952        struct cifs_writedata *wdata = container_of(work,
1953                                                struct cifs_writedata, work);
1954        struct inode *inode = wdata->cfile->dentry->d_inode;
1955        int i = 0;
1956
1957        if (wdata->result == 0) {
1958                spin_lock(&inode->i_lock);
1959                cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1960                spin_unlock(&inode->i_lock);
1961                cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1962                                         wdata->bytes);
1963        } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1964                return cifs_writev_requeue(wdata);
1965
1966        for (i = 0; i < wdata->nr_pages; i++) {
1967                struct page *page = wdata->pages[i];
1968                if (wdata->result == -EAGAIN)
1969                        __set_page_dirty_nobuffers(page);
1970                else if (wdata->result < 0)
1971                        SetPageError(page);
1972                end_page_writeback(page);
1973                page_cache_release(page);
1974        }
1975        if (wdata->result != -EAGAIN)
1976                mapping_set_error(inode->i_mapping, wdata->result);
1977        kref_put(&wdata->refcount, cifs_writedata_release);
1978}
1979
1980struct cifs_writedata *
1981cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1982{
1983        struct cifs_writedata *wdata;
1984
1985        /* this would overflow */
1986        if (nr_pages == 0) {
1987                cERROR(1, "%s: called with nr_pages == 0!", __func__);
1988                return NULL;
1989        }
1990
1991        /* writedata + number of page pointers */
1992        wdata = kzalloc(sizeof(*wdata) +
1993                        sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1994        if (wdata != NULL) {
1995                kref_init(&wdata->refcount);
1996                INIT_LIST_HEAD(&wdata->list);
1997                init_completion(&wdata->done);
1998                INIT_WORK(&wdata->work, complete);
1999        }
2000        return wdata;
2001}
2002
2003/*
2004 * Check the mid_state and signature on received buffer (if any), and queue the
2005 * workqueue completion task.
2006 */
2007static void
2008cifs_writev_callback(struct mid_q_entry *mid)
2009{
2010        struct cifs_writedata *wdata = mid->callback_data;
2011        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2012        unsigned int written;
2013        WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2014
2015        switch (mid->mid_state) {
2016        case MID_RESPONSE_RECEIVED:
2017                wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2018                if (wdata->result != 0)
2019                        break;
2020
2021                written = le16_to_cpu(smb->CountHigh);
2022                written <<= 16;
2023                written += le16_to_cpu(smb->Count);
2024                /*
2025                 * Mask off high 16 bits when bytes written as returned
2026                 * by the server is greater than bytes requested by the
2027                 * client. OS/2 servers are known to set incorrect
2028                 * CountHigh values.
2029                 */
2030                if (written > wdata->bytes)
2031                        written &= 0xFFFF;
2032
2033                if (written < wdata->bytes)
2034                        wdata->result = -ENOSPC;
2035                else
2036                        wdata->bytes = written;
2037                break;
2038        case MID_REQUEST_SUBMITTED:
2039        case MID_RETRY_NEEDED:
2040                wdata->result = -EAGAIN;
2041                break;
2042        default:
2043                wdata->result = -EIO;
2044                break;
2045        }
2046
2047        queue_work(cifsiod_wq, &wdata->work);
2048        DeleteMidQEntry(mid);
2049        add_credits(tcon->ses->server, 1, 0);
2050}
2051
2052/* cifs_async_writev - send an async write, and set up mid to handle result */
2053int
2054cifs_async_writev(struct cifs_writedata *wdata)
2055{
2056        int i, rc = -EACCES;
2057        WRITE_REQ *smb = NULL;
2058        int wct;
2059        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2060        struct kvec *iov = NULL;
2061
2062        if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2063                wct = 14;
2064        } else {
2065                wct = 12;
2066                if (wdata->offset >> 32 > 0) {
2067                        /* can not handle big offset for old srv */
2068                        return -EIO;
2069                }
2070        }
2071
2072        rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2073        if (rc)
2074                goto async_writev_out;
2075
2076        /* 1 iov per page + 1 for header */
2077        iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2078        if (iov == NULL) {
2079                rc = -ENOMEM;
2080                goto async_writev_out;
2081        }
2082
2083        smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2084        smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2085
2086        smb->AndXCommand = 0xFF;        /* none */
2087        smb->Fid = wdata->cfile->netfid;
2088        smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2089        if (wct == 14)
2090                smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2091        smb->Reserved = 0xFFFFFFFF;
2092        smb->WriteMode = 0;
2093        smb->Remaining = 0;
2094
2095        smb->DataOffset =
2096            cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2097
2098        /* 4 for RFC1001 length + 1 for BCC */
2099        iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2100        iov[0].iov_base = smb;
2101
2102        /*
2103         * This function should marshal up the page array into the kvec
2104         * array, reserving [0] for the header. It should kmap the pages
2105         * and set the iov_len properly for each one. It may also set
2106         * wdata->bytes too.
2107         */
2108        cifs_kmap_lock();
2109        wdata->marshal_iov(iov, wdata);
2110        cifs_kmap_unlock();
2111
2112        cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2113
2114        smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2115        smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2116
2117        if (wct == 14) {
2118                inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2119                put_bcc(wdata->bytes + 1, &smb->hdr);
2120        } else {
2121                /* wct == 12 */
2122                struct smb_com_writex_req *smbw =
2123                                (struct smb_com_writex_req *)smb;
2124                inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2125                put_bcc(wdata->bytes + 5, &smbw->hdr);
2126                iov[0].iov_len += 4; /* pad bigger by four bytes */
2127        }
2128
2129        kref_get(&wdata->refcount);
2130        rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2131                             NULL, cifs_writev_callback, wdata, 0);
2132
2133        if (rc == 0)
2134                cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2135        else
2136                kref_put(&wdata->refcount, cifs_writedata_release);
2137
2138        /* send is done, unmap pages */
2139        for (i = 0; i < wdata->nr_pages; i++)
2140                kunmap(wdata->pages[i]);
2141
2142async_writev_out:
2143        cifs_small_buf_release(smb);
2144        kfree(iov);
2145        return rc;
2146}
2147
2148int
2149CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2150              unsigned int *nbytes, struct kvec *iov, int n_vec,
2151              const int long_op)
2152{
2153        int rc = -EACCES;
2154        WRITE_REQ *pSMB = NULL;
2155        int wct;
2156        int smb_hdr_len;
2157        int resp_buf_type = 0;
2158        __u32 pid = io_parms->pid;
2159        __u16 netfid = io_parms->netfid;
2160        __u64 offset = io_parms->offset;
2161        struct cifs_tcon *tcon = io_parms->tcon;
2162        unsigned int count = io_parms->length;
2163
2164        *nbytes = 0;
2165
2166        cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2167
2168        if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2169                wct = 14;
2170        } else {
2171                wct = 12;
2172                if ((offset >> 32) > 0) {
2173                        /* can not handle big offset for old srv */
2174                        return -EIO;
2175                }
2176        }
2177        rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2178        if (rc)
2179                return rc;
2180
2181        pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2182        pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2183
2184        /* tcon and ses pointer are checked in smb_init */
2185        if (tcon->ses->server == NULL)
2186                return -ECONNABORTED;
2187
2188        pSMB->AndXCommand = 0xFF;       /* none */
2189        pSMB->Fid = netfid;
2190        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2191        if (wct == 14)
2192                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2193        pSMB->Reserved = 0xFFFFFFFF;
2194        pSMB->WriteMode = 0;
2195        pSMB->Remaining = 0;
2196
2197        pSMB->DataOffset =
2198            cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2199
2200        pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2201        pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2202        /* header + 1 byte pad */
2203        smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2204        if (wct == 14)
2205                inc_rfc1001_len(pSMB, count + 1);
2206        else /* wct == 12 */
2207                inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2208        if (wct == 14)
2209                pSMB->ByteCount = cpu_to_le16(count + 1);
2210        else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2211                struct smb_com_writex_req *pSMBW =
2212                                (struct smb_com_writex_req *)pSMB;
2213                pSMBW->ByteCount = cpu_to_le16(count + 5);
2214        }
2215        iov[0].iov_base = pSMB;
2216        if (wct == 14)
2217                iov[0].iov_len = smb_hdr_len + 4;
2218        else /* wct == 12 pad bigger by four bytes */
2219                iov[0].iov_len = smb_hdr_len + 8;
2220
2221
2222        rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2223                          long_op);
2224        cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2225        if (rc) {
2226                cFYI(1, "Send error Write2 = %d", rc);
2227        } else if (resp_buf_type == 0) {
2228                /* presumably this can not happen, but best to be safe */
2229                rc = -EIO;
2230        } else {
2231                WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2232                *nbytes = le16_to_cpu(pSMBr->CountHigh);
2233                *nbytes = (*nbytes) << 16;
2234                *nbytes += le16_to_cpu(pSMBr->Count);
2235
2236                /*
2237                 * Mask off high 16 bits when bytes written as returned by the
2238                 * server is greater than bytes requested by the client. OS/2
2239                 * servers are known to set incorrect CountHigh values.
2240                 */
2241                if (*nbytes > count)
2242                        *nbytes &= 0xFFFF;
2243        }
2244
2245/*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2246        if (resp_buf_type == CIFS_SMALL_BUFFER)
2247                cifs_small_buf_release(iov[0].iov_base);
2248        else if (resp_buf_type == CIFS_LARGE_BUFFER)
2249                cifs_buf_release(iov[0].iov_base);
2250
2251        /* Note: On -EAGAIN error only caller can retry on handle based calls
2252                since file handle passed in no longer valid */
2253
2254        return rc;
2255}
2256
2257int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2258               const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2259               const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2260{
2261        int rc = 0;
2262        LOCK_REQ *pSMB = NULL;
2263        struct kvec iov[2];
2264        int resp_buf_type;
2265        __u16 count;
2266
2267        cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2268
2269        rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2270        if (rc)
2271                return rc;
2272
2273        pSMB->Timeout = 0;
2274        pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2275        pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2276        pSMB->LockType = lock_type;
2277        pSMB->AndXCommand = 0xFF; /* none */
2278        pSMB->Fid = netfid; /* netfid stays le */
2279
2280        count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2281        inc_rfc1001_len(pSMB, count);
2282        pSMB->ByteCount = cpu_to_le16(count);
2283
2284        iov[0].iov_base = (char *)pSMB;
2285        iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2286                         (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2287        iov[1].iov_base = (char *)buf;
2288        iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2289
2290        cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2291        rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2292        if (rc)
2293                cFYI(1, "Send error in cifs_lockv = %d", rc);
2294
2295        return rc;
2296}
2297
2298int
2299CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2300            const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2301            const __u64 offset, const __u32 numUnlock,
2302            const __u32 numLock, const __u8 lockType,
2303            const bool waitFlag, const __u8 oplock_level)
2304{
2305        int rc = 0;
2306        LOCK_REQ *pSMB = NULL;
2307/*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2308        int bytes_returned;
2309        int flags = 0;
2310        __u16 count;
2311
2312        cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2313        rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2314
2315        if (rc)
2316                return rc;
2317
2318        if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2319                /* no response expected */
2320                flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2321                pSMB->Timeout = 0;
2322        } else if (waitFlag) {
2323                flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2324                pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2325        } else {
2326                pSMB->Timeout = 0;
2327        }
2328
2329        pSMB->NumberOfLocks = cpu_to_le16(numLock);
2330        pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2331        pSMB->LockType = lockType;
2332        pSMB->OplockLevel = oplock_level;
2333        pSMB->AndXCommand = 0xFF;       /* none */
2334        pSMB->Fid = smb_file_id; /* netfid stays le */
2335
2336        if ((numLock != 0) || (numUnlock != 0)) {
2337                pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2338                /* BB where to store pid high? */
2339                pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2340                pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2341                pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2342                pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2343                count = sizeof(LOCKING_ANDX_RANGE);
2344        } else {
2345                /* oplock break */
2346                count = 0;
2347        }
2348        inc_rfc1001_len(pSMB, count);
2349        pSMB->ByteCount = cpu_to_le16(count);
2350
2351        if (waitFlag) {
2352                rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2353                        (struct smb_hdr *) pSMB, &bytes_returned);
2354                cifs_small_buf_release(pSMB);
2355        } else {
2356                rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2357                /* SMB buffer freed by function above */
2358        }
2359        cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2360        if (rc)
2361                cFYI(1, "Send error in Lock = %d", rc);
2362
2363        /* Note: On -EAGAIN error only caller can retry on handle based calls
2364        since file handle passed in no longer valid */
2365        return rc;
2366}
2367
2368int
2369CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2370                const __u16 smb_file_id, const __u32 netpid,
2371                const loff_t start_offset, const __u64 len,
2372                struct file_lock *pLockData, const __u16 lock_type,
2373                const bool waitFlag)
2374{
2375        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2376        struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2377        struct cifs_posix_lock *parm_data;
2378        int rc = 0;
2379        int timeout = 0;
2380        int bytes_returned = 0;
2381        int resp_buf_type = 0;
2382        __u16 params, param_offset, offset, byte_count, count;
2383        struct kvec iov[1];
2384
2385        cFYI(1, "Posix Lock");
2386
2387        rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2388
2389        if (rc)
2390                return rc;
2391
2392        pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2393
2394        params = 6;
2395        pSMB->MaxSetupCount = 0;
2396        pSMB->Reserved = 0;
2397        pSMB->Flags = 0;
2398        pSMB->Reserved2 = 0;
2399        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2400        offset = param_offset + params;
2401
2402        count = sizeof(struct cifs_posix_lock);
2403        pSMB->MaxParameterCount = cpu_to_le16(2);
2404        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2405        pSMB->SetupCount = 1;
2406        pSMB->Reserved3 = 0;
2407        if (pLockData)
2408                pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2409        else
2410                pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2411        byte_count = 3 /* pad */  + params + count;
2412        pSMB->DataCount = cpu_to_le16(count);
2413        pSMB->ParameterCount = cpu_to_le16(params);
2414        pSMB->TotalDataCount = pSMB->DataCount;
2415        pSMB->TotalParameterCount = pSMB->ParameterCount;
2416        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2417        parm_data = (struct cifs_posix_lock *)
2418                        (((char *) &pSMB->hdr.Protocol) + offset);
2419
2420        parm_data->lock_type = cpu_to_le16(lock_type);
2421        if (waitFlag) {
2422                timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2423                parm_data->lock_flags = cpu_to_le16(1);
2424                pSMB->Timeout = cpu_to_le32(-1);
2425        } else
2426                pSMB->Timeout = 0;
2427
2428        parm_data->pid = cpu_to_le32(netpid);
2429        parm_data->start = cpu_to_le64(start_offset);
2430        parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2431
2432        pSMB->DataOffset = cpu_to_le16(offset);
2433        pSMB->Fid = smb_file_id;
2434        pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2435        pSMB->Reserved4 = 0;
2436        inc_rfc1001_len(pSMB, byte_count);
2437        pSMB->ByteCount = cpu_to_le16(byte_count);
2438        if (waitFlag) {
2439                rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2440                        (struct smb_hdr *) pSMBr, &bytes_returned);
2441        } else {
2442                iov[0].iov_base = (char *)pSMB;
2443                iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2444                rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2445                                &resp_buf_type, timeout);
2446                pSMB = NULL; /* request buf already freed by SendReceive2. Do
2447                                not try to free it twice below on exit */
2448                pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2449        }
2450
2451        if (rc) {
2452                cFYI(1, "Send error in Posix Lock = %d", rc);
2453        } else if (pLockData) {
2454                /* lock structure can be returned on get */
2455                __u16 data_offset;
2456                __u16 data_count;
2457                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2458
2459                if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2460                        rc = -EIO;      /* bad smb */
2461                        goto plk_err_exit;
2462                }
2463                data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2464                data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2465                if (data_count < sizeof(struct cifs_posix_lock)) {
2466                        rc = -EIO;
2467                        goto plk_err_exit;
2468                }
2469                parm_data = (struct cifs_posix_lock *)
2470                        ((char *)&pSMBr->hdr.Protocol + data_offset);
2471                if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2472                        pLockData->fl_type = F_UNLCK;
2473                else {
2474                        if (parm_data->lock_type ==
2475                                        __constant_cpu_to_le16(CIFS_RDLCK))
2476                                pLockData->fl_type = F_RDLCK;
2477                        else if (parm_data->lock_type ==
2478                                        __constant_cpu_to_le16(CIFS_WRLCK))
2479                                pLockData->fl_type = F_WRLCK;
2480
2481                        pLockData->fl_start = le64_to_cpu(parm_data->start);
2482                        pLockData->fl_end = pLockData->fl_start +
2483                                        le64_to_cpu(parm_data->length) - 1;
2484                        pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2485                }
2486        }
2487
2488plk_err_exit:
2489        if (pSMB)
2490                cifs_small_buf_release(pSMB);
2491
2492        if (resp_buf_type == CIFS_SMALL_BUFFER)
2493                cifs_small_buf_release(iov[0].iov_base);
2494        else if (resp_buf_type == CIFS_LARGE_BUFFER)
2495                cifs_buf_release(iov[0].iov_base);
2496
2497        /* Note: On -EAGAIN error only caller can retry on handle based calls
2498           since file handle passed in no longer valid */
2499
2500        return rc;
2501}
2502
2503
2504int
2505CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2506{
2507        int rc = 0;
2508        CLOSE_REQ *pSMB = NULL;
2509        cFYI(1, "In CIFSSMBClose");
2510
2511/* do not retry on dead session on close */
2512        rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2513        if (rc == -EAGAIN)
2514                return 0;
2515        if (rc)
2516                return rc;
2517
2518        pSMB->FileID = (__u16) smb_file_id;
2519        pSMB->LastWriteTime = 0xFFFFFFFF;
2520        pSMB->ByteCount = 0;
2521        rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2522        cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2523        if (rc) {
2524                if (rc != -EINTR) {
2525                        /* EINTR is expected when user ctl-c to kill app */
2526                        cERROR(1, "Send error in Close = %d", rc);
2527                }
2528        }
2529
2530        /* Since session is dead, file will be closed on server already */
2531        if (rc == -EAGAIN)
2532                rc = 0;
2533
2534        return rc;
2535}
2536
2537int
2538CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2539{
2540        int rc = 0;
2541        FLUSH_REQ *pSMB = NULL;
2542        cFYI(1, "In CIFSSMBFlush");
2543
2544        rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2545        if (rc)
2546                return rc;
2547
2548        pSMB->FileID = (__u16) smb_file_id;
2549        pSMB->ByteCount = 0;
2550        rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2551        cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2552        if (rc)
2553                cERROR(1, "Send error in Flush = %d", rc);
2554
2555        return rc;
2556}
2557
2558int
2559CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2560              const char *fromName, const char *toName,
2561              const struct nls_table *nls_codepage, int remap)
2562{
2563        int rc = 0;
2564        RENAME_REQ *pSMB = NULL;
2565        RENAME_RSP *pSMBr = NULL;
2566        int bytes_returned;
2567        int name_len, name_len2;
2568        __u16 count;
2569
2570        cFYI(1, "In CIFSSMBRename");
2571renameRetry:
2572        rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2573                      (void **) &pSMBr);
2574        if (rc)
2575                return rc;
2576
2577        pSMB->BufferFormat = 0x04;
2578        pSMB->SearchAttributes =
2579            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2580                        ATTR_DIRECTORY);
2581
2582        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2583                name_len =
2584                    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2585                                       PATH_MAX, nls_codepage, remap);
2586                name_len++;     /* trailing null */
2587                name_len *= 2;
2588                pSMB->OldFileName[name_len] = 0x04;     /* pad */
2589        /* protocol requires ASCII signature byte on Unicode string */
2590                pSMB->OldFileName[name_len + 1] = 0x00;
2591                name_len2 =
2592                    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2593                                       toName, PATH_MAX, nls_codepage, remap);
2594                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2595                name_len2 *= 2; /* convert to bytes */
2596        } else {        /* BB improve the check for buffer overruns BB */
2597                name_len = strnlen(fromName, PATH_MAX);
2598                name_len++;     /* trailing null */
2599                strncpy(pSMB->OldFileName, fromName, name_len);
2600                name_len2 = strnlen(toName, PATH_MAX);
2601                name_len2++;    /* trailing null */
2602                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2603                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2604                name_len2++;    /* trailing null */
2605                name_len2++;    /* signature byte */
2606        }
2607
2608        count = 1 /* 1st signature byte */  + name_len + name_len2;
2609        inc_rfc1001_len(pSMB, count);
2610        pSMB->ByteCount = cpu_to_le16(count);
2611
2612        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2613                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2614        cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2615        if (rc)
2616                cFYI(1, "Send error in rename = %d", rc);
2617
2618        cifs_buf_release(pSMB);
2619
2620        if (rc == -EAGAIN)
2621                goto renameRetry;
2622
2623        return rc;
2624}
2625
2626int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2627                int netfid, const char *target_name,
2628                const struct nls_table *nls_codepage, int remap)
2629{
2630        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2631        struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2632        struct set_file_rename *rename_info;
2633        char *data_offset;
2634        char dummy_string[30];
2635        int rc = 0;
2636        int bytes_returned = 0;
2637        int len_of_str;
2638        __u16 params, param_offset, offset, count, byte_count;
2639
2640        cFYI(1, "Rename to File by handle");
2641        rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2642                        (void **) &pSMBr);
2643        if (rc)
2644                return rc;
2645
2646        params = 6;
2647        pSMB->MaxSetupCount = 0;
2648        pSMB->Reserved = 0;
2649        pSMB->Flags = 0;
2650        pSMB->Timeout = 0;
2651        pSMB->Reserved2 = 0;
2652        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2653        offset = param_offset + params;
2654
2655        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2656        rename_info = (struct set_file_rename *) data_offset;
2657        pSMB->MaxParameterCount = cpu_to_le16(2);
2658        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2659        pSMB->SetupCount = 1;
2660        pSMB->Reserved3 = 0;
2661        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2662        byte_count = 3 /* pad */  + params;
2663        pSMB->ParameterCount = cpu_to_le16(params);
2664        pSMB->TotalParameterCount = pSMB->ParameterCount;
2665        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2666        pSMB->DataOffset = cpu_to_le16(offset);
2667        /* construct random name ".cifs_tmp<inodenum><mid>" */
2668        rename_info->overwrite = cpu_to_le32(1);
2669        rename_info->root_fid  = 0;
2670        /* unicode only call */
2671        if (target_name == NULL) {
2672                sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2673                len_of_str =
2674                        cifsConvertToUTF16((__le16 *)rename_info->target_name,
2675                                        dummy_string, 24, nls_codepage, remap);
2676        } else {
2677                len_of_str =
2678                        cifsConvertToUTF16((__le16 *)rename_info->target_name,
2679                                        target_name, PATH_MAX, nls_codepage,
2680                                        remap);
2681        }
2682        rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2683        count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2684        byte_count += count;
2685        pSMB->DataCount = cpu_to_le16(count);
2686        pSMB->TotalDataCount = pSMB->DataCount;
2687        pSMB->Fid = netfid;
2688        pSMB->InformationLevel =
2689                cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2690        pSMB->Reserved4 = 0;
2691        inc_rfc1001_len(pSMB, byte_count);
2692        pSMB->ByteCount = cpu_to_le16(byte_count);
2693        rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2694                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2695        cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2696        if (rc)
2697                cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2698
2699        cifs_buf_release(pSMB);
2700
2701        /* Note: On -EAGAIN error only caller can retry on handle based calls
2702                since file handle passed in no longer valid */
2703
2704        return rc;
2705}
2706
2707int
2708CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2709            const char *fromName, const __u16 target_tid, const char *toName,
2710            const int flags, const struct nls_table *nls_codepage, int remap)
2711{
2712        int rc = 0;
2713        COPY_REQ *pSMB = NULL;
2714        COPY_RSP *pSMBr = NULL;
2715        int bytes_returned;
2716        int name_len, name_len2;
2717        __u16 count;
2718
2719        cFYI(1, "In CIFSSMBCopy");
2720copyRetry:
2721        rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2722                        (void **) &pSMBr);
2723        if (rc)
2724                return rc;
2725
2726        pSMB->BufferFormat = 0x04;
2727        pSMB->Tid2 = target_tid;
2728
2729        pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2730
2731        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2732                name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2733                                              fromName, PATH_MAX, nls_codepage,
2734                                              remap);
2735                name_len++;     /* trailing null */
2736                name_len *= 2;
2737                pSMB->OldFileName[name_len] = 0x04;     /* pad */
2738                /* protocol requires ASCII signature byte on Unicode string */
2739                pSMB->OldFileName[name_len + 1] = 0x00;
2740                name_len2 =
2741                    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2742                                       toName, PATH_MAX, nls_codepage, remap);
2743                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2744                name_len2 *= 2; /* convert to bytes */
2745        } else {        /* BB improve the check for buffer overruns BB */
2746                name_len = strnlen(fromName, PATH_MAX);
2747                name_len++;     /* trailing null */
2748                strncpy(pSMB->OldFileName, fromName, name_len);
2749                name_len2 = strnlen(toName, PATH_MAX);
2750                name_len2++;    /* trailing null */
2751                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2752                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2753                name_len2++;    /* trailing null */
2754                name_len2++;    /* signature byte */
2755        }
2756
2757        count = 1 /* 1st signature byte */  + name_len + name_len2;
2758        inc_rfc1001_len(pSMB, count);
2759        pSMB->ByteCount = cpu_to_le16(count);
2760
2761        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2762                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2763        if (rc) {
2764                cFYI(1, "Send error in copy = %d with %d files copied",
2765                        rc, le16_to_cpu(pSMBr->CopyCount));
2766        }
2767        cifs_buf_release(pSMB);
2768
2769        if (rc == -EAGAIN)
2770                goto copyRetry;
2771
2772        return rc;
2773}
2774
2775int
2776CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2777                      const char *fromName, const char *toName,
2778                      const struct nls_table *nls_codepage)
2779{
2780        TRANSACTION2_SPI_REQ *pSMB = NULL;
2781        TRANSACTION2_SPI_RSP *pSMBr = NULL;
2782        char *data_offset;
2783        int name_len;
2784        int name_len_target;
2785        int rc = 0;
2786        int bytes_returned = 0;
2787        __u16 params, param_offset, offset, byte_count;
2788
2789        cFYI(1, "In Symlink Unix style");
2790createSymLinkRetry:
2791        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2792                      (void **) &pSMBr);
2793        if (rc)
2794                return rc;
2795
2796        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2797                name_len =
2798                    cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2799                                    /* find define for this maxpathcomponent */
2800                                    PATH_MAX, nls_codepage);
2801                name_len++;     /* trailing null */
2802                name_len *= 2;
2803
2804        } else {        /* BB improve the check for buffer overruns BB */
2805                name_len = strnlen(fromName, PATH_MAX);
2806                name_len++;     /* trailing null */
2807                strncpy(pSMB->FileName, fromName, name_len);
2808        }
2809        params = 6 + name_len;
2810        pSMB->MaxSetupCount = 0;
2811        pSMB->Reserved = 0;
2812        pSMB->Flags = 0;
2813        pSMB->Timeout = 0;
2814        pSMB->Reserved2 = 0;
2815        param_offset = offsetof(struct smb_com_transaction2_spi_req,
2816                                InformationLevel) - 4;
2817        offset = param_offset + params;
2818
2819        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2820        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2821                name_len_target =
2822                    cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2823                                    /* find define for this maxpathcomponent */
2824                                    , nls_codepage);
2825                name_len_target++;      /* trailing null */
2826                name_len_target *= 2;
2827        } else {        /* BB improve the check for buffer overruns BB */
2828                name_len_target = strnlen(toName, PATH_MAX);
2829                name_len_target++;      /* trailing null */
2830                strncpy(data_offset, toName, name_len_target);
2831        }
2832
2833        pSMB->MaxParameterCount = cpu_to_le16(2);
2834        /* BB find exact max on data count below from sess */
2835        pSMB->MaxDataCount = cpu_to_le16(1000);
2836        pSMB->SetupCount = 1;
2837        pSMB->Reserved3 = 0;
2838        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2839        byte_count = 3 /* pad */  + params + name_len_target;
2840        pSMB->DataCount = cpu_to_le16(name_len_target);
2841        pSMB->ParameterCount = cpu_to_le16(params);
2842        pSMB->TotalDataCount = pSMB->DataCount;
2843        pSMB->TotalParameterCount = pSMB->ParameterCount;
2844        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2845        pSMB->DataOffset = cpu_to_le16(offset);
2846        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2847        pSMB->Reserved4 = 0;
2848        inc_rfc1001_len(pSMB, byte_count);
2849        pSMB->ByteCount = cpu_to_le16(byte_count);
2850        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2851                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2852        cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2853        if (rc)
2854                cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2855
2856        cifs_buf_release(pSMB);
2857
2858        if (rc == -EAGAIN)
2859                goto createSymLinkRetry;
2860
2861        return rc;
2862}
2863
2864int
2865CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2866                       const char *fromName, const char *toName,
2867                       const struct nls_table *nls_codepage, int remap)
2868{
2869        TRANSACTION2_SPI_REQ *pSMB = NULL;
2870        TRANSACTION2_SPI_RSP *pSMBr = NULL;
2871        char *data_offset;
2872        int name_len;
2873        int name_len_target;
2874        int rc = 0;
2875        int bytes_returned = 0;
2876        __u16 params, param_offset, offset, byte_count;
2877
2878        cFYI(1, "In Create Hard link Unix style");
2879createHardLinkRetry:
2880        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2881                      (void **) &pSMBr);
2882        if (rc)
2883                return rc;
2884
2885        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2886                name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2887                                              PATH_MAX, nls_codepage, remap);
2888                name_len++;     /* trailing null */
2889                name_len *= 2;
2890
2891        } else {        /* BB improve the check for buffer overruns BB */
2892                name_len = strnlen(toName, PATH_MAX);
2893                name_len++;     /* trailing null */
2894                strncpy(pSMB->FileName, toName, name_len);
2895        }
2896        params = 6 + name_len;
2897        pSMB->MaxSetupCount = 0;
2898        pSMB->Reserved = 0;
2899        pSMB->Flags = 0;
2900        pSMB->Timeout = 0;
2901        pSMB->Reserved2 = 0;
2902        param_offset = offsetof(struct smb_com_transaction2_spi_req,
2903                                InformationLevel) - 4;
2904        offset = param_offset + params;
2905
2906        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2907        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2908                name_len_target =
2909                    cifsConvertToUTF16((__le16 *) data_offset, fromName,
2910                                       PATH_MAX, nls_codepage, remap);
2911                name_len_target++;      /* trailing null */
2912                name_len_target *= 2;
2913        } else {        /* BB improve the check for buffer overruns BB */
2914                name_len_target = strnlen(fromName, PATH_MAX);
2915                name_len_target++;      /* trailing null */
2916                strncpy(data_offset, fromName, name_len_target);
2917        }
2918
2919        pSMB->MaxParameterCount = cpu_to_le16(2);
2920        /* BB find exact max on data count below from sess*/
2921        pSMB->MaxDataCount = cpu_to_le16(1000);
2922        pSMB->SetupCount = 1;
2923        pSMB->Reserved3 = 0;
2924        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2925        byte_count = 3 /* pad */  + params + name_len_target;
2926        pSMB->ParameterCount = cpu_to_le16(params);
2927        pSMB->TotalParameterCount = pSMB->ParameterCount;
2928        pSMB->DataCount = cpu_to_le16(name_len_target);
2929        pSMB->TotalDataCount = pSMB->DataCount;
2930        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2931        pSMB->DataOffset = cpu_to_le16(offset);
2932        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2933        pSMB->Reserved4 = 0;
2934        inc_rfc1001_len(pSMB, byte_count);
2935        pSMB->ByteCount = cpu_to_le16(byte_count);
2936        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2937                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2938        cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2939        if (rc)
2940                cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2941
2942        cifs_buf_release(pSMB);
2943        if (rc == -EAGAIN)
2944                goto createHardLinkRetry;
2945
2946        return rc;
2947}
2948
2949int
2950CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2951                   const char *fromName, const char *toName,
2952                   const struct nls_table *nls_codepage, int remap)
2953{
2954        int rc = 0;
2955        NT_RENAME_REQ *pSMB = NULL;
2956        RENAME_RSP *pSMBr = NULL;
2957        int bytes_returned;
2958        int name_len, name_len2;
2959        __u16 count;
2960
2961        cFYI(1, "In CIFSCreateHardLink");
2962winCreateHardLinkRetry:
2963
2964        rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2965                      (void **) &pSMBr);
2966        if (rc)
2967                return rc;
2968
2969        pSMB->SearchAttributes =
2970            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2971                        ATTR_DIRECTORY);
2972        pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2973        pSMB->ClusterCount = 0;
2974
2975        pSMB->BufferFormat = 0x04;
2976
2977        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2978                name_len =
2979                    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2980                                       PATH_MAX, nls_codepage, remap);
2981                name_len++;     /* trailing null */
2982                name_len *= 2;
2983
2984                /* protocol specifies ASCII buffer format (0x04) for unicode */
2985                pSMB->OldFileName[name_len] = 0x04;
2986                pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2987                name_len2 =
2988                    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2989                                       toName, PATH_MAX, nls_codepage, remap);
2990                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2991                name_len2 *= 2; /* convert to bytes */
2992        } else {        /* BB improve the check for buffer overruns BB */
2993                name_len = strnlen(fromName, PATH_MAX);
2994                name_len++;     /* trailing null */
2995                strncpy(pSMB->OldFileName, fromName, name_len);
2996                name_len2 = strnlen(toName, PATH_MAX);
2997                name_len2++;    /* trailing null */
2998                pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2999                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
3000                name_len2++;    /* trailing null */
3001                name_len2++;    /* signature byte */
3002        }
3003
3004        count = 1 /* string type byte */  + name_len + name_len2;
3005        inc_rfc1001_len(pSMB, count);
3006        pSMB->ByteCount = cpu_to_le16(count);
3007
3008        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3009                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3010        cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3011        if (rc)
3012                cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3013
3014        cifs_buf_release(pSMB);
3015        if (rc == -EAGAIN)
3016                goto winCreateHardLinkRetry;
3017
3018        return rc;
3019}
3020
3021int
3022CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3023                        const unsigned char *searchName, char **symlinkinfo,
3024                        const struct nls_table *nls_codepage)
3025{
3026/* SMB_QUERY_FILE_UNIX_LINK */
3027        TRANSACTION2_QPI_REQ *pSMB = NULL;
3028        TRANSACTION2_QPI_RSP *pSMBr = NULL;
3029        int rc = 0;
3030        int bytes_returned;
3031        int name_len;
3032        __u16 params, byte_count;
3033        char *data_start;
3034
3035        cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3036
3037querySymLinkRetry:
3038        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3039                      (void **) &pSMBr);
3040        if (rc)
3041                return rc;
3042
3043        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3044                name_len =
3045                        cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3046                                        PATH_MAX, nls_codepage);
3047                name_len++;     /* trailing null */
3048                name_len *= 2;
3049        } else {        /* BB improve the check for buffer overruns BB */
3050                name_len = strnlen(searchName, PATH_MAX);
3051                name_len++;     /* trailing null */
3052                strncpy(pSMB->FileName, searchName, name_len);
3053        }
3054
3055        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3056        pSMB->TotalDataCount = 0;
3057        pSMB->MaxParameterCount = cpu_to_le16(2);
3058        pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3059        pSMB->MaxSetupCount = 0;
3060        pSMB->Reserved = 0;
3061        pSMB->Flags = 0;
3062        pSMB->Timeout = 0;
3063        pSMB->Reserved2 = 0;
3064        pSMB->ParameterOffset = cpu_to_le16(offsetof(
3065        struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3066        pSMB->DataCount = 0;
3067        pSMB->DataOffset = 0;
3068        pSMB->SetupCount = 1;
3069        pSMB->Reserved3 = 0;
3070        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3071        byte_count = params + 1 /* pad */ ;
3072        pSMB->TotalParameterCount = cpu_to_le16(params);
3073        pSMB->ParameterCount = pSMB->TotalParameterCount;
3074        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3075        pSMB->Reserved4 = 0;
3076        inc_rfc1001_len(pSMB, byte_count);
3077        pSMB->ByteCount = cpu_to_le16(byte_count);
3078
3079        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3080                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3081        if (rc) {
3082                cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3083        } else {
3084                /* decode response */
3085
3086                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3087                /* BB also check enough total bytes returned */
3088                if (rc || get_bcc(&pSMBr->hdr) < 2)
3089                        rc = -EIO;
3090                else {
3091                        bool is_unicode;
3092                        u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3093
3094                        data_start = ((char *) &pSMBr->hdr.Protocol) +
3095                                           le16_to_cpu(pSMBr->t2.DataOffset);
3096
3097                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3098                                is_unicode = true;
3099                        else
3100                                is_unicode = false;
3101
3102                        /* BB FIXME investigate remapping reserved chars here */
3103                        *symlinkinfo = cifs_strndup_from_utf16(data_start,
3104                                        count, is_unicode, nls_codepage);
3105                        if (!*symlinkinfo)
3106                                rc = -ENOMEM;
3107                }
3108        }
3109        cifs_buf_release(pSMB);
3110        if (rc == -EAGAIN)
3111                goto querySymLinkRetry;
3112        return rc;
3113}
3114
3115#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3116/*
3117 *      Recent Windows versions now create symlinks more frequently
3118 *      and they use the "reparse point" mechanism below.  We can of course
3119 *      do symlinks nicely to Samba and other servers which support the
3120 *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3121 *      "MF" symlinks optionally, but for recent Windows we really need to
3122 *      reenable the code below and fix the cifs_symlink callers to handle this.
3123 *      In the interim this code has been moved to its own config option so
3124 *      it is not compiled in by default until callers fixed up and more tested.
3125 */
3126int
3127CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3128                        const unsigned char *searchName,
3129                        char *symlinkinfo, const int buflen, __u16 fid,
3130                        const struct nls_table *nls_codepage)
3131{
3132        int rc = 0;
3133        int bytes_returned;
3134        struct smb_com_transaction_ioctl_req *pSMB;
3135        struct smb_com_transaction_ioctl_rsp *pSMBr;
3136
3137        cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3138        rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3139                      (void **) &pSMBr);
3140        if (rc)
3141                return rc;
3142
3143        pSMB->TotalParameterCount = 0 ;
3144        pSMB->TotalDataCount = 0;
3145        pSMB->MaxParameterCount = cpu_to_le32(2);
3146        /* BB find exact data count max from sess structure BB */
3147        pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3148        pSMB->MaxSetupCount = 4;
3149        pSMB->Reserved = 0;
3150        pSMB->ParameterOffset = 0;
3151        pSMB->DataCount = 0;
3152        pSMB->DataOffset = 0;
3153        pSMB->SetupCount = 4;
3154        pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3155        pSMB->ParameterCount = pSMB->TotalParameterCount;
3156        pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3157        pSMB->IsFsctl = 1; /* FSCTL */
3158        pSMB->IsRootFlag = 0;
3159        pSMB->Fid = fid; /* file handle always le */
3160        pSMB->ByteCount = 0;
3161
3162        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3163                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3164        if (rc) {
3165                cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3166        } else {                /* decode response */
3167                __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3168                __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3169                if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3170                        /* BB also check enough total bytes returned */
3171                        rc = -EIO;      /* bad smb */
3172                        goto qreparse_out;
3173                }
3174                if (data_count && (data_count < 2048)) {
3175                        char *end_of_smb = 2 /* sizeof byte count */ +
3176                               get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3177
3178                        struct reparse_data *reparse_buf =
3179                                                (struct reparse_data *)
3180                                                ((char *)&pSMBr->hdr.Protocol
3181                                                                 + data_offset);
3182                        if ((char *)reparse_buf >= end_of_smb) {
3183                                rc = -EIO;
3184                                goto qreparse_out;
3185                        }
3186                        if ((reparse_buf->LinkNamesBuf +
3187                                reparse_buf->TargetNameOffset +
3188                                reparse_buf->TargetNameLen) > end_of_smb) {
3189                                cFYI(1, "reparse buf beyond SMB");
3190                                rc = -EIO;
3191                                goto qreparse_out;
3192                        }
3193
3194                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3195                                cifs_from_ucs2(symlinkinfo, (__le16 *)
3196                                                (reparse_buf->LinkNamesBuf +
3197                                                reparse_buf->TargetNameOffset),
3198                                                buflen,
3199                                                reparse_buf->TargetNameLen,
3200                                                nls_codepage, 0);
3201                        } else { /* ASCII names */
3202                                strncpy(symlinkinfo,
3203                                        reparse_buf->LinkNamesBuf +
3204                                        reparse_buf->TargetNameOffset,
3205                                        min_t(const int, buflen,
3206                                           reparse_buf->TargetNameLen));
3207                        }
3208                } else {
3209                        rc = -EIO;
3210                        cFYI(1, "Invalid return data count on "
3211                                 "get reparse info ioctl");
3212                }
3213                symlinkinfo[buflen] = 0; /* just in case so the caller
3214                                        does not go off the end of the buffer */
3215                cFYI(1, "readlink result - %s", symlinkinfo);
3216        }
3217
3218qreparse_out:
3219        cifs_buf_release(pSMB);
3220
3221        /* Note: On -EAGAIN error only caller can retry on handle based calls
3222                since file handle passed in no longer valid */
3223
3224        return rc;
3225}
3226#endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3227
3228#ifdef CONFIG_CIFS_POSIX
3229
3230/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3231static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3232                             struct cifs_posix_ace *cifs_ace)
3233{
3234        /* u8 cifs fields do not need le conversion */
3235        ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3236        ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3237        ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3238        /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3239
3240        return;
3241}
3242
3243/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3244static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3245                               const int acl_type, const int size_of_data_area)
3246{
3247        int size =  0;
3248        int i;
3249        __u16 count;
3250        struct cifs_posix_ace *pACE;
3251        struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3252        posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3253
3254        if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3255                return -EOPNOTSUPP;
3256
3257        if (acl_type & ACL_TYPE_ACCESS) {
3258                count = le16_to_cpu(cifs_acl->access_entry_count);
3259                pACE = &cifs_acl->ace_array[0];
3260                size = sizeof(struct cifs_posix_acl);
3261                size += sizeof(struct cifs_posix_ace) * count;
3262                /* check if we would go beyond end of SMB */
3263                if (size_of_data_area < size) {
3264                        cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3265                                size_of_data_area, size);
3266                        return -EINVAL;
3267                }
3268        } else if (acl_type & ACL_TYPE_DEFAULT) {
3269                count = le16_to_cpu(cifs_acl->access_entry_count);
3270                size = sizeof(struct cifs_posix_acl);
3271                size += sizeof(struct cifs_posix_ace) * count;
3272/* skip past access ACEs to get to default ACEs */
3273                pACE = &cifs_acl->ace_array[count];
3274                count = le16_to_cpu(cifs_acl->default_entry_count);
3275                size += sizeof(struct cifs_posix_ace) * count;
3276                /* check if we would go beyond end of SMB */
3277                if (size_of_data_area < size)
3278                        return -EINVAL;
3279        } else {
3280                /* illegal type */
3281                return -EINVAL;
3282        }
3283
3284        size = posix_acl_xattr_size(count);
3285        if ((buflen == 0) || (local_acl == NULL)) {
3286                /* used to query ACL EA size */
3287        } else if (size > buflen) {
3288                return -ERANGE;
3289        } else /* buffer big enough */ {
3290                local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3291                for (i = 0; i < count ; i++) {
3292                        cifs_convert_ace(&local_acl->a_entries[i], pACE);
3293                        pACE++;
3294                }
3295        }
3296        return size;
3297}
3298
3299static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3300                                     const posix_acl_xattr_entry *local_ace)
3301{
3302        __u16 rc = 0; /* 0 = ACL converted ok */
3303
3304        cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3305        cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3306        /* BB is there a better way to handle the large uid? */
3307        if (local_ace->e_id == cpu_to_le32(-1)) {
3308        /* Probably no need to le convert -1 on any arch but can not hurt */
3309                cifs_ace->cifs_uid = cpu_to_le64(-1);
3310        } else
3311                cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3312        /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3313        return rc;
3314}
3315
3316/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3317static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3318                               const int buflen, const int acl_type)
3319{
3320        __u16 rc = 0;
3321        struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3322        posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3323        int count;
3324        int i;
3325
3326        if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3327                return 0;
3328
3329        count = posix_acl_xattr_count((size_t)buflen);
3330        cFYI(1, "setting acl with %d entries from buf of length %d and "
3331                "version of %d",
3332                count, buflen, le32_to_cpu(local_acl->a_version));
3333        if (le32_to_cpu(local_acl->a_version) != 2) {
3334                cFYI(1, "unknown POSIX ACL version %d",
3335                     le32_to_cpu(local_acl->a_version));
3336                return 0;
3337        }
3338        cifs_acl->version = cpu_to_le16(1);
3339        if (acl_type == ACL_TYPE_ACCESS)
3340                cifs_acl->access_entry_count = cpu_to_le16(count);
3341        else if (acl_type == ACL_TYPE_DEFAULT)
3342                cifs_acl->default_entry_count = cpu_to_le16(count);
3343        else {
3344                cFYI(1, "unknown ACL type %d", acl_type);
3345                return 0;
3346        }
3347        for (i = 0; i < count; i++) {
3348                rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3349                                        &local_acl->a_entries[i]);
3350                if (rc != 0) {
3351                        /* ACE not converted */
3352                        break;
3353                }
3354        }
3355        if (rc == 0) {
3356                rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3357                rc += sizeof(struct cifs_posix_acl);
3358                /* BB add check to make sure ACL does not overflow SMB */
3359        }
3360        return rc;
3361}
3362
3363int
3364CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3365                   const unsigned char *searchName,
3366                   char *acl_inf, const int buflen, const int acl_type,
3367                   const struct nls_table *nls_codepage, int remap)
3368{
3369/* SMB_QUERY_POSIX_ACL */
3370        TRANSACTION2_QPI_REQ *pSMB = NULL;
3371        TRANSACTION2_QPI_RSP *pSMBr = NULL;
3372        int rc = 0;
3373        int bytes_returned;
3374        int name_len;
3375        __u16 params, byte_count;
3376
3377        cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3378
3379queryAclRetry:
3380        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3381                (void **) &pSMBr);
3382        if (rc)
3383                return rc;
3384
3385        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3386                name_len =
3387                        cifsConvertToUTF16((__le16 *) pSMB->FileName,
3388                                           searchName, PATH_MAX, nls_codepage,
3389                                           remap);
3390                name_len++;     /* trailing null */
3391                name_len *= 2;
3392                pSMB->FileName[name_len] = 0;
3393                pSMB->FileName[name_len+1] = 0;
3394        } else {        /* BB improve the check for buffer overruns BB */
3395                name_len = strnlen(searchName, PATH_MAX);
3396                name_len++;     /* trailing null */
3397                strncpy(pSMB->FileName, searchName, name_len);
3398        }
3399
3400        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3401        pSMB->TotalDataCount = 0;
3402        pSMB->MaxParameterCount = cpu_to_le16(2);
3403        /* BB find exact max data count below from sess structure BB */
3404        pSMB->MaxDataCount = cpu_to_le16(4000);
3405        pSMB->MaxSetupCount = 0;
3406        pSMB->Reserved = 0;
3407        pSMB->Flags = 0;
3408        pSMB->Timeout = 0;
3409        pSMB->Reserved2 = 0;
3410        pSMB->ParameterOffset = cpu_to_le16(
3411                offsetof(struct smb_com_transaction2_qpi_req,
3412                         InformationLevel) - 4);
3413        pSMB->DataCount = 0;
3414        pSMB->DataOffset = 0;
3415        pSMB->SetupCount = 1;
3416        pSMB->Reserved3 = 0;
3417        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3418        byte_count = params + 1 /* pad */ ;
3419        pSMB->TotalParameterCount = cpu_to_le16(params);
3420        pSMB->ParameterCount = pSMB->TotalParameterCount;
3421        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3422        pSMB->Reserved4 = 0;
3423        inc_rfc1001_len(pSMB, byte_count);
3424        pSMB->ByteCount = cpu_to_le16(byte_count);
3425
3426        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3427                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3428        cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3429        if (rc) {
3430                cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3431        } else {
3432                /* decode response */
3433
3434                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3435                /* BB also check enough total bytes returned */
3436                if (rc || get_bcc(&pSMBr->hdr) < 2)
3437                        rc = -EIO;      /* bad smb */
3438                else {
3439                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3440                        __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3441                        rc = cifs_copy_posix_acl(acl_inf,
3442                                (char *)&pSMBr->hdr.Protocol+data_offset,
3443                                buflen, acl_type, count);
3444                }
3445        }
3446        cifs_buf_release(pSMB);
3447        if (rc == -EAGAIN)
3448                goto queryAclRetry;
3449        return rc;
3450}
3451
3452int
3453CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3454                   const unsigned char *fileName,
3455                   const char *local_acl, const int buflen,
3456                   const int acl_type,
3457                   const struct nls_table *nls_codepage, int remap)
3458{
3459        struct smb_com_transaction2_spi_req *pSMB = NULL;
3460        struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3461        char *parm_data;
3462        int name_len;
3463        int rc = 0;
3464        int bytes_returned = 0;
3465        __u16 params, byte_count, data_count, param_offset, offset;
3466
3467        cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3468setAclRetry:
3469        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3470                      (void **) &pSMBr);
3471        if (rc)
3472                return rc;
3473        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3474                name_len =
3475                        cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3476                                           PATH_MAX, nls_codepage, remap);
3477                name_len++;     /* trailing null */
3478                name_len *= 2;
3479        } else {        /* BB improve the check for buffer overruns BB */
3480                name_len = strnlen(fileName, PATH_MAX);
3481                name_len++;     /* trailing null */
3482                strncpy(pSMB->FileName, fileName, name_len);
3483        }
3484        params = 6 + name_len;
3485        pSMB->MaxParameterCount = cpu_to_le16(2);
3486        /* BB find max SMB size from sess */
3487        pSMB->MaxDataCount = cpu_to_le16(1000);
3488        pSMB->MaxSetupCount = 0;
3489        pSMB->Reserved = 0;
3490        pSMB->Flags = 0;
3491        pSMB->Timeout = 0;
3492        pSMB->Reserved2 = 0;
3493        param_offset = offsetof(struct smb_com_transaction2_spi_req,
3494                                InformationLevel) - 4;
3495        offset = param_offset + params;
3496        parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3497        pSMB->ParameterOffset = cpu_to_le16(param_offset);
3498
3499        /* convert to on the wire format for POSIX ACL */
3500        data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3501
3502        if (data_count == 0) {
3503                rc = -EOPNOTSUPP;
3504                goto setACLerrorExit;
3505        }
3506        pSMB->DataOffset = cpu_to_le16(offset);
3507        pSMB->SetupCount = 1;
3508        pSMB->Reserved3 = 0;
3509        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3510        pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3511        byte_count = 3 /* pad */  + params + data_count;
3512        pSMB->DataCount = cpu_to_le16(data_count);
3513        pSMB->TotalDataCount = pSMB->DataCount;
3514        pSMB->ParameterCount = cpu_to_le16(params);
3515        pSMB->TotalParameterCount = pSMB->ParameterCount;
3516        pSMB->Reserved4 = 0;
3517        inc_rfc1001_len(pSMB, byte_count);
3518        pSMB->ByteCount = cpu_to_le16(byte_count);
3519        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3520                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3521        if (rc)
3522                cFYI(1, "Set POSIX ACL returned %d", rc);
3523
3524setACLerrorExit:
3525        cifs_buf_release(pSMB);
3526        if (rc == -EAGAIN)
3527                goto setAclRetry;
3528        return rc;
3529}
3530
3531/* BB fix tabs in this function FIXME BB */
3532int
3533CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3534               const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3535{
3536        int rc = 0;
3537        struct smb_t2_qfi_req *pSMB = NULL;
3538        struct smb_t2_qfi_rsp *pSMBr = NULL;
3539        int bytes_returned;
3540        __u16 params, byte_count;
3541
3542        cFYI(1, "In GetExtAttr");
3543        if (tcon == NULL)
3544                return -ENODEV;
3545
3546GetExtAttrRetry:
3547        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3548                        (void **) &pSMBr);
3549        if (rc)
3550                return rc;
3551
3552        params = 2 /* level */ + 2 /* fid */;
3553        pSMB->t2.TotalDataCount = 0;
3554        pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3555        /* BB find exact max data count below from sess structure BB */
3556        pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3557        pSMB->t2.MaxSetupCount = 0;
3558        pSMB->t2.Reserved = 0;
3559        pSMB->t2.Flags = 0;
3560        pSMB->t2.Timeout = 0;
3561        pSMB->t2.Reserved2 = 0;
3562        pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3563                                               Fid) - 4);
3564        pSMB->t2.DataCount = 0;
3565        pSMB->t2.DataOffset = 0;
3566        pSMB->t2.SetupCount = 1;
3567        pSMB->t2.Reserved3 = 0;
3568        pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3569        byte_count = params + 1 /* pad */ ;
3570        pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3571        pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3572        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3573        pSMB->Pad = 0;
3574        pSMB->Fid = netfid;
3575        inc_rfc1001_len(pSMB, byte_count);
3576        pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3577
3578        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3579                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3580        if (rc) {
3581                cFYI(1, "error %d in GetExtAttr", rc);
3582        } else {
3583                /* decode response */
3584                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3585                /* BB also check enough total bytes returned */
3586                if (rc || get_bcc(&pSMBr->hdr) < 2)
3587                        /* If rc should we check for EOPNOSUPP and
3588                           disable the srvino flag? or in caller? */
3589                        rc = -EIO;      /* bad smb */
3590                else {
3591                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3592                        __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3593                        struct file_chattr_info *pfinfo;
3594                        /* BB Do we need a cast or hash here ? */
3595                        if (count != 16) {
3596                                cFYI(1, "Illegal size ret in GetExtAttr");
3597                                rc = -EIO;
3598                                goto GetExtAttrOut;
3599                        }
3600                        pfinfo = (struct file_chattr_info *)
3601                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
3602                        *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3603                        *pMask = le64_to_cpu(pfinfo->mask);
3604                }
3605        }
3606GetExtAttrOut:
3607        cifs_buf_release(pSMB);
3608        if (rc == -EAGAIN)
3609                goto GetExtAttrRetry;
3610        return rc;
3611}
3612
3613#endif /* CONFIG_POSIX */
3614
3615#ifdef CONFIG_CIFS_ACL
3616/*
3617 * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3618 * all NT TRANSACTS that we init here have total parm and data under about 400
3619 * bytes (to fit in small cifs buffer size), which is the case so far, it
3620 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3621 * returned setup area) and MaxParameterCount (returned parms size) must be set
3622 * by caller
3623 */
3624static int
3625smb_init_nttransact(const __u16 sub_command, const int setup_count,
3626                   const int parm_len, struct cifs_tcon *tcon,
3627                   void **ret_buf)
3628{
3629        int rc;
3630        __u32 temp_offset;
3631        struct smb_com_ntransact_req *pSMB;
3632
3633        rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3634                                (void **)&pSMB);
3635        if (rc)
3636                return rc;
3637        *ret_buf = (void *)pSMB;
3638        pSMB->Reserved = 0;
3639        pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3640        pSMB->TotalDataCount  = 0;
3641        pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3642        pSMB->ParameterCount = pSMB->TotalParameterCount;
3643        pSMB->DataCount  = pSMB->TotalDataCount;
3644        temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3645                        (setup_count * 2) - 4 /* for rfc1001 length itself */;
3646        pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3647        pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3648        pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3649        pSMB->SubCommand = cpu_to_le16(sub_command);
3650        return 0;
3651}
3652
3653static int
3654validate_ntransact(char *buf, char **ppparm, char **ppdata,
3655                   __u32 *pparmlen, __u32 *pdatalen)
3656{
3657        char *end_of_smb;
3658        __u32 data_count, data_offset, parm_count, parm_offset;
3659        struct smb_com_ntransact_rsp *pSMBr;
3660        u16 bcc;
3661
3662        *pdatalen = 0;
3663        *pparmlen = 0;
3664
3665        if (buf == NULL)
3666                return -EINVAL;
3667
3668        pSMBr = (struct smb_com_ntransact_rsp *)buf;
3669
3670        bcc = get_bcc(&pSMBr->hdr);
3671        end_of_smb = 2 /* sizeof byte count */ + bcc +
3672                        (char *)&pSMBr->ByteCount;
3673
3674        data_offset = le32_to_cpu(pSMBr->DataOffset);
3675        data_count = le32_to_cpu(pSMBr->DataCount);
3676        parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3677        parm_count = le32_to_cpu(pSMBr->ParameterCount);
3678
3679        *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3680        *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3681
3682        /* should we also check that parm and data areas do not overlap? */
3683        if (*ppparm > end_of_smb) {
3684                cFYI(1, "parms start after end of smb");
3685                return -EINVAL;
3686        } else if (parm_count + *ppparm > end_of_smb) {
3687                cFYI(1, "parm end after end of smb");
3688                return -EINVAL;
3689        } else if (*ppdata > end_of_smb) {
3690                cFYI(1, "data starts after end of smb");
3691                return -EINVAL;
3692        } else if (data_count + *ppdata > end_of_smb) {
3693                cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3694                        *ppdata, data_count, (data_count + *ppdata),
3695                        end_of_smb, pSMBr);
3696                return -EINVAL;
3697        } else if (parm_count + data_count > bcc) {
3698                cFYI(1, "parm count and data count larger than SMB");
3699                return -EINVAL;
3700        }
3701        *pdatalen = data_count;
3702        *pparmlen = parm_count;
3703        return 0;
3704}
3705
3706/* Get Security Descriptor (by handle) from remote server for a file or dir */
3707int
3708CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3709                  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3710{
3711        int rc = 0;
3712        int buf_type = 0;
3713        QUERY_SEC_DESC_REQ *pSMB;
3714        struct kvec iov[1];
3715
3716        cFYI(1, "GetCifsACL");
3717
3718        *pbuflen = 0;
3719        *acl_inf = NULL;
3720
3721        rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3722                        8 /* parm len */, tcon, (void **) &pSMB);
3723        if (rc)
3724                return rc;
3725
3726        pSMB->MaxParameterCount = cpu_to_le32(4);
3727        /* BB TEST with big acls that might need to be e.g. larger than 16K */
3728        pSMB->MaxSetupCount = 0;
3729        pSMB->Fid = fid; /* file handle always le */
3730        pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3731                                     CIFS_ACL_DACL);
3732        pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3733        inc_rfc1001_len(pSMB, 11);
3734        iov[0].iov_base = (char *)pSMB;
3735        iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3736
3737        rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3738                         0);
3739        cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3740        if (rc) {
3741                cFYI(1, "Send error in QuerySecDesc = %d", rc);
3742        } else {                /* decode response */
3743                __le32 *parm;
3744                __u32 parm_len;
3745                __u32 acl_len;
3746                struct smb_com_ntransact_rsp *pSMBr;
3747                char *pdata;
3748
3749/* validate_nttransact */
3750                rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3751                                        &pdata, &parm_len, pbuflen);
3752                if (rc)
3753                        goto qsec_out;
3754                pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3755
3756                cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3757
3758                if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3759                        rc = -EIO;      /* bad smb */
3760                        *pbuflen = 0;
3761                        goto qsec_out;
3762                }
3763
3764/* BB check that data area is minimum length and as big as acl_len */
3765
3766                acl_len = le32_to_cpu(*parm);
3767                if (acl_len != *pbuflen) {
3768                        cERROR(1, "acl length %d does not match %d",
3769                                   acl_len, *pbuflen);
3770                        if (*pbuflen > acl_len)
3771                                *pbuflen = acl_len;
3772                }
3773
3774                /* check if buffer is big enough for the acl
3775                   header followed by the smallest SID */
3776                if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3777                    (*pbuflen >= 64 * 1024)) {
3778                        cERROR(1, "bad acl length %d", *pbuflen);
3779                        rc = -EINVAL;
3780                        *pbuflen = 0;
3781                } else {
3782                        *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3783                        if (*acl_inf == NULL) {
3784                                *pbuflen = 0;
3785                                rc = -ENOMEM;
3786                        }
3787                        memcpy(*acl_inf, pdata, *pbuflen);
3788                }
3789        }
3790qsec_out:
3791        if (buf_type == CIFS_SMALL_BUFFER)
3792                cifs_small_buf_release(iov[0].iov_base);
3793        else if (buf_type == CIFS_LARGE_BUFFER)
3794                cifs_buf_release(iov[0].iov_base);
3795/*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3796        return rc;
3797}
3798
3799int
3800CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3801                        struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3802{
3803        __u16 byte_count, param_count, data_count, param_offset, data_offset;
3804        int rc = 0;
3805        int bytes_returned = 0;
3806        SET_SEC_DESC_REQ *pSMB = NULL;
3807        void *pSMBr;
3808
3809setCifsAclRetry:
3810        rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3811        if (rc)
3812                return rc;
3813
3814        pSMB->MaxSetupCount = 0;
3815        pSMB->Reserved = 0;
3816
3817        param_count = 8;
3818        param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3819        data_count = acllen;
3820        data_offset = param_offset + param_count;
3821        byte_count = 3 /* pad */  + param_count;
3822
3823        pSMB->DataCount = cpu_to_le32(data_count);
3824        pSMB->TotalDataCount = pSMB->DataCount;
3825        pSMB->MaxParameterCount = cpu_to_le32(4);
3826        pSMB->MaxDataCount = cpu_to_le32(16384);
3827        pSMB->ParameterCount = cpu_to_le32(param_count);
3828        pSMB->ParameterOffset = cpu_to_le32(param_offset);
3829        pSMB->TotalParameterCount = pSMB->ParameterCount;
3830        pSMB->DataOffset = cpu_to_le32(data_offset);
3831        pSMB->SetupCount = 0;
3832        pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3833        pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3834
3835        pSMB->Fid = fid; /* file handle always le */
3836        pSMB->Reserved2 = 0;
3837        pSMB->AclFlags = cpu_to_le32(aclflag);
3838
3839        if (pntsd && acllen) {
3840                memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3841                                data_offset, pntsd, acllen);
3842                inc_rfc1001_len(pSMB, byte_count + data_count);
3843        } else
3844                inc_rfc1001_len(pSMB, byte_count);
3845
3846        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3847                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3848
3849        cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3850        if (rc)
3851                cFYI(1, "Set CIFS ACL returned %d", rc);
3852        cifs_buf_release(pSMB);
3853
3854        if (rc == -EAGAIN)
3855                goto setCifsAclRetry;
3856
3857        return (rc);
3858}
3859
3860#endif /* CONFIG_CIFS_ACL */
3861
3862/* Legacy Query Path Information call for lookup to old servers such
3863   as Win9x/WinME */
3864int
3865SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3866                    const char *search_name, FILE_ALL_INFO *data,
3867                    const struct nls_table *nls_codepage, int remap)
3868{
3869        QUERY_INFORMATION_REQ *pSMB;
3870        QUERY_INFORMATION_RSP *pSMBr;
3871        int rc = 0;
3872        int bytes_returned;
3873        int name_len;
3874
3875        cFYI(1, "In SMBQPath path %s", search_name);
3876QInfRetry:
3877        rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3878                      (void **) &pSMBr);
3879        if (rc)
3880                return rc;
3881
3882        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3883                name_len =
3884                        cifsConvertToUTF16((__le16 *) pSMB->FileName,
3885                                           search_name, PATH_MAX, nls_codepage,
3886                                           remap);
3887                name_len++;     /* trailing null */
3888                name_len *= 2;
3889        } else {
3890                name_len = strnlen(search_name, PATH_MAX);
3891                name_len++;     /* trailing null */
3892                strncpy(pSMB->FileName, search_name, name_len);
3893        }
3894        pSMB->BufferFormat = 0x04;
3895        name_len++; /* account for buffer type byte */
3896        inc_rfc1001_len(pSMB, (__u16)name_len);
3897        pSMB->ByteCount = cpu_to_le16(name_len);
3898
3899        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3900                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3901        if (rc) {
3902                cFYI(1, "Send error in QueryInfo = %d", rc);
3903        } else if (data) {
3904                struct timespec ts;
3905                __u32 time = le32_to_cpu(pSMBr->last_write_time);
3906
3907                /* decode response */
3908                /* BB FIXME - add time zone adjustment BB */
3909                memset(data, 0, sizeof(FILE_ALL_INFO));
3910                ts.tv_nsec = 0;
3911                ts.tv_sec = time;
3912                /* decode time fields */
3913                data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3914                data->LastWriteTime = data->ChangeTime;
3915                data->LastAccessTime = 0;
3916                data->AllocationSize =
3917                        cpu_to_le64(le32_to_cpu(pSMBr->size));
3918                data->EndOfFile = data->AllocationSize;
3919                data->Attributes =
3920                        cpu_to_le32(le16_to_cpu(pSMBr->attr));
3921        } else
3922                rc = -EIO; /* bad buffer passed in */
3923
3924        cifs_buf_release(pSMB);
3925
3926        if (rc == -EAGAIN)
3927                goto QInfRetry;
3928
3929        return rc;
3930}
3931
3932int
3933CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3934                 u16 netfid, FILE_ALL_INFO *pFindData)
3935{
3936        struct smb_t2_qfi_req *pSMB = NULL;
3937        struct smb_t2_qfi_rsp *pSMBr = NULL;
3938        int rc = 0;
3939        int bytes_returned;
3940        __u16 params, byte_count;
3941
3942QFileInfoRetry:
3943        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3944                      (void **) &pSMBr);
3945        if (rc)
3946                return rc;
3947
3948        params = 2 /* level */ + 2 /* fid */;
3949        pSMB->t2.TotalDataCount = 0;
3950        pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3951        /* BB find exact max data count below from sess structure BB */
3952        pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3953        pSMB->t2.MaxSetupCount = 0;
3954        pSMB->t2.Reserved = 0;
3955        pSMB->t2.Flags = 0;
3956        pSMB->t2.Timeout = 0;
3957        pSMB->t2.Reserved2 = 0;
3958        pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3959                                               Fid) - 4);
3960        pSMB->t2.DataCount = 0;
3961        pSMB->t2.DataOffset = 0;
3962        pSMB->t2.SetupCount = 1;
3963        pSMB->t2.Reserved3 = 0;
3964        pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3965        byte_count = params + 1 /* pad */ ;
3966        pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3967        pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3968        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3969        pSMB->Pad = 0;
3970        pSMB->Fid = netfid;
3971        inc_rfc1001_len(pSMB, byte_count);
3972
3973        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3974                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3975        if (rc) {
3976                cFYI(1, "Send error in QPathInfo = %d", rc);
3977        } else {                /* decode response */
3978                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3979
3980                if (rc) /* BB add auto retry on EOPNOTSUPP? */
3981                        rc = -EIO;
3982                else if (get_bcc(&pSMBr->hdr) < 40)
3983                        rc = -EIO;      /* bad smb */
3984                else if (pFindData) {
3985                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3986                        memcpy((char *) pFindData,
3987                               (char *) &pSMBr->hdr.Protocol +
3988                               data_offset, sizeof(FILE_ALL_INFO));
3989                } else
3990                    rc = -ENOMEM;
3991        }
3992        cifs_buf_release(pSMB);
3993        if (rc == -EAGAIN)
3994                goto QFileInfoRetry;
3995
3996        return rc;
3997}
3998
3999int
4000CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4001                 const char *search_name, FILE_ALL_INFO *data,
4002                 int legacy /* old style infolevel */,
4003                 const struct nls_table *nls_codepage, int remap)
4004{
4005        /* level 263 SMB_QUERY_FILE_ALL_INFO */
4006        TRANSACTION2_QPI_REQ *pSMB = NULL;
4007        TRANSACTION2_QPI_RSP *pSMBr = NULL;
4008        int rc = 0;
4009        int bytes_returned;
4010        int name_len;
4011        __u16 params, byte_count;
4012
4013        /* cFYI(1, "In QPathInfo path %s", search_name); */
4014QPathInfoRetry:
4015        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4016                      (void **) &pSMBr);
4017        if (rc)
4018                return rc;
4019
4020        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4021                name_len =
4022                    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4023                                       PATH_MAX, nls_codepage, remap);
4024                name_len++;     /* trailing null */
4025                name_len *= 2;
4026        } else {        /* BB improve the check for buffer overruns BB */
4027                name_len = strnlen(search_name, PATH_MAX);
4028                name_len++;     /* trailing null */
4029                strncpy(pSMB->FileName, search_name, name_len);
4030        }
4031
4032        params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4033        pSMB->TotalDataCount = 0;
4034        pSMB->MaxParameterCount = cpu_to_le16(2);
4035        /* BB find exact max SMB PDU from sess structure BB */
4036        pSMB->MaxDataCount = cpu_to_le16(4000);
4037        pSMB->MaxSetupCount = 0;
4038        pSMB->Reserved = 0;
4039        pSMB->Flags = 0;
4040        pSMB->Timeout = 0;
4041        pSMB->Reserved2 = 0;
4042        pSMB->ParameterOffset = cpu_to_le16(offsetof(
4043        struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4044        pSMB->DataCount = 0;
4045        pSMB->DataOffset = 0;
4046        pSMB->SetupCount = 1;
4047        pSMB->Reserved3 = 0;
4048        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4049        byte_count = params + 1 /* pad */ ;
4050        pSMB->TotalParameterCount = cpu_to_le16(params);
4051        pSMB->ParameterCount = pSMB->TotalParameterCount;
4052        if (legacy)
4053                pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4054        else
4055                pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4056        pSMB->Reserved4 = 0;
4057        inc_rfc1001_len(pSMB, byte_count);
4058        pSMB->ByteCount = cpu_to_le16(byte_count);
4059
4060        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4061                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4062        if (rc) {
4063                cFYI(1, "Send error in QPathInfo = %d", rc);
4064        } else {                /* decode response */
4065                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4066
4067                if (rc) /* BB add auto retry on EOPNOTSUPP? */
4068                        rc = -EIO;
4069                else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4070                        rc = -EIO;      /* bad smb */
4071                else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4072                        rc = -EIO;  /* 24 or 26 expected but we do not read
4073                                        last field */
4074                else if (data) {
4075                        int size;
4076                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4077
4078                        /*
4079                         * On legacy responses we do not read the last field,
4080                         * EAsize, fortunately since it varies by subdialect and
4081                         * also note it differs on Set vs Get, ie two bytes or 4
4082                         * bytes depending but we don't care here.
4083                         */
4084                        if (legacy)
4085                                size = sizeof(FILE_INFO_STANDARD);
4086                        else
4087                                size = sizeof(FILE_ALL_INFO);
4088                        memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4089                               data_offset, size);
4090                } else
4091                    rc = -ENOMEM;
4092        }
4093        cifs_buf_release(pSMB);
4094        if (rc == -EAGAIN)
4095                goto QPathInfoRetry;
4096
4097        return rc;
4098}
4099
4100int
4101CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4102                 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4103{
4104        struct smb_t2_qfi_req *pSMB = NULL;
4105        struct smb_t2_qfi_rsp *pSMBr = NULL;
4106        int rc = 0;
4107        int bytes_returned;
4108        __u16 params, byte_count;
4109
4110UnixQFileInfoRetry:
4111        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4112                      (void **) &pSMBr);
4113        if (rc)
4114                return rc;
4115
4116        params = 2 /* level */ + 2 /* fid */;
4117        pSMB->t2.TotalDataCount = 0;
4118        pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4119        /* BB find exact max data count below from sess structure BB */
4120        pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4121        pSMB->t2.MaxSetupCount = 0;
4122        pSMB->t2.Reserved = 0;
4123        pSMB->t2.Flags = 0;
4124        pSMB->t2.Timeout = 0;
4125        pSMB->t2.Reserved2 = 0;
4126        pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4127                                               Fid) - 4);
4128        pSMB->t2.DataCount = 0;
4129        pSMB->t2.DataOffset = 0;
4130        pSMB->t2.SetupCount = 1;
4131        pSMB->t2.Reserved3 = 0;
4132        pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4133        byte_count = params + 1 /* pad */ ;
4134        pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4135        pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4136        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4137        pSMB->Pad = 0;
4138        pSMB->Fid = netfid;
4139        inc_rfc1001_len(pSMB, byte_count);
4140
4141        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4142                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4143        if (rc) {
4144                cFYI(1, "Send error in QPathInfo = %d", rc);
4145        } else {                /* decode response */
4146                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4147
4148                if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4149                        cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4150                                   "Unix Extensions can be disabled on mount "
4151                                   "by specifying the nosfu mount option.");
4152                        rc = -EIO;      /* bad smb */
4153                } else {
4154                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4155                        memcpy((char *) pFindData,
4156                               (char *) &pSMBr->hdr.Protocol +
4157                               data_offset,
4158                               sizeof(FILE_UNIX_BASIC_INFO));
4159                }
4160        }
4161
4162        cifs_buf_release(pSMB);
4163        if (rc == -EAGAIN)
4164                goto UnixQFileInfoRetry;
4165
4166        return rc;
4167}
4168
4169int
4170CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4171                     const unsigned char *searchName,
4172                     FILE_UNIX_BASIC_INFO *pFindData,
4173                     const struct nls_table *nls_codepage, int remap)
4174{
4175/* SMB_QUERY_FILE_UNIX_BASIC */
4176        TRANSACTION2_QPI_REQ *pSMB = NULL;
4177        TRANSACTION2_QPI_RSP *pSMBr = NULL;
4178        int rc = 0;
4179        int bytes_returned = 0;
4180        int name_len;
4181        __u16 params, byte_count;
4182
4183        cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4184UnixQPathInfoRetry:
4185        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4186                      (void **) &pSMBr);
4187        if (rc)
4188                return rc;
4189
4190        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4191                name_len =
4192                    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4193                                       PATH_MAX, nls_codepage, remap);
4194                name_len++;     /* trailing null */
4195                name_len *= 2;
4196        } else {        /* BB improve the check for buffer overruns BB */
4197                name_len = strnlen(searchName, PATH_MAX);
4198                name_len++;     /* trailing null */
4199                strncpy(pSMB->FileName, searchName, name_len);
4200        }
4201
4202        params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4203        pSMB->TotalDataCount = 0;
4204        pSMB->MaxParameterCount = cpu_to_le16(2);
4205        /* BB find exact max SMB PDU from sess structure BB */
4206        pSMB->MaxDataCount = cpu_to_le16(4000);
4207        pSMB->MaxSetupCount = 0;
4208        pSMB->Reserved = 0;
4209        pSMB->Flags = 0;
4210        pSMB->Timeout = 0;
4211        pSMB->Reserved2 = 0;
4212        pSMB->ParameterOffset = cpu_to_le16(offsetof(
4213        struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4214        pSMB->DataCount = 0;
4215        pSMB->DataOffset = 0;
4216        pSMB->SetupCount = 1;
4217        pSMB->Reserved3 = 0;
4218        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4219        byte_count = params + 1 /* pad */ ;
4220        pSMB->TotalParameterCount = cpu_to_le16(params);
4221        pSMB->ParameterCount = pSMB->TotalParameterCount;
4222        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4223        pSMB->Reserved4 = 0;
4224        inc_rfc1001_len(pSMB, byte_count);
4225        pSMB->ByteCount = cpu_to_le16(byte_count);
4226
4227        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4228                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4229        if (rc) {
4230                cFYI(1, "Send error in QPathInfo = %d", rc);
4231        } else {                /* decode response */
4232                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4233
4234                if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4235                        cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4236                                   "Unix Extensions can be disabled on mount "
4237                                   "by specifying the nosfu mount option.");
4238                        rc = -EIO;      /* bad smb */
4239                } else {
4240                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4241                        memcpy((char *) pFindData,
4242                               (char *) &pSMBr->hdr.Protocol +
4243                               data_offset,
4244                               sizeof(FILE_UNIX_BASIC_INFO));
4245                }
4246        }
4247        cifs_buf_release(pSMB);
4248        if (rc == -EAGAIN)
4249                goto UnixQPathInfoRetry;
4250
4251        return rc;
4252}
4253
4254/* xid, tcon, searchName and codepage are input parms, rest are returned */
4255int
4256CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4257              const char *searchName,
4258              const struct nls_table *nls_codepage,
4259              __u16 *pnetfid, __u16 search_flags,
4260              struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4261{
4262/* level 257 SMB_ */
4263        TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4264        TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4265        T2_FFIRST_RSP_PARMS *parms;
4266        int rc = 0;
4267        int bytes_returned = 0;
4268        int name_len;
4269        __u16 params, byte_count;
4270
4271        cFYI(1, "In FindFirst for %s", searchName);
4272
4273findFirstRetry:
4274        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4275                      (void **) &pSMBr);
4276        if (rc)
4277                return rc;
4278
4279        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4280                name_len =
4281                    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4282                                       PATH_MAX, nls_codepage, remap);
4283                /* We can not add the asterik earlier in case
4284                it got remapped to 0xF03A as if it were part of the
4285                directory name instead of a wildcard */
4286                name_len *= 2;
4287                pSMB->FileName[name_len] = dirsep;
4288                pSMB->FileName[name_len+1] = 0;
4289                pSMB->FileName[name_len+2] = '*';
4290                pSMB->FileName[name_len+3] = 0;
4291                name_len += 4; /* now the trailing null */
4292                pSMB->FileName[name_len] = 0; /* null terminate just in case */
4293                pSMB->FileName[name_len+1] = 0;
4294                name_len += 2;
4295        } else {        /* BB add check for overrun of SMB buf BB */
4296                name_len = strnlen(searchName, PATH_MAX);
4297/* BB fix here and in unicode clause above ie
4298                if (name_len > buffersize-header)
4299                        free buffer exit; BB */
4300                strncpy(pSMB->FileName, searchName, name_len);
4301                pSMB->FileName[name_len] = dirsep;
4302                pSMB->FileName[name_len+1] = '*';
4303                pSMB->FileName[name_len+2] = 0;
4304                name_len += 3;
4305        }
4306
4307        params = 12 + name_len /* includes null */ ;
4308        pSMB->TotalDataCount = 0;       /* no EAs */
4309        pSMB->MaxParameterCount = cpu_to_le16(10);
4310        pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4311        pSMB->MaxSetupCount = 0;
4312        pSMB->Reserved = 0;
4313        pSMB->Flags = 0;
4314        pSMB->Timeout = 0;
4315        pSMB->Reserved2 = 0;
4316        byte_count = params + 1 /* pad */ ;
4317        pSMB->TotalParameterCount = cpu_to_le16(params);
4318        pSMB->ParameterCount = pSMB->TotalParameterCount;
4319        pSMB->ParameterOffset = cpu_to_le16(
4320              offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4321                - 4);
4322        pSMB->DataCount = 0;
4323        pSMB->DataOffset = 0;
4324        pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4325        pSMB->Reserved3 = 0;
4326        pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4327        pSMB->SearchAttributes =
4328            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4329                        ATTR_DIRECTORY);
4330        pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4331        pSMB->SearchFlags = cpu_to_le16(search_flags);
4332        pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4333
4334        /* BB what should we set StorageType to? Does it matter? BB */
4335        pSMB->SearchStorageType = 0;
4336        inc_rfc1001_len(pSMB, byte_count);
4337        pSMB->ByteCount = cpu_to_le16(byte_count);
4338
4339        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4340                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4341        cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4342
4343        if (rc) {/* BB add logic to retry regular search if Unix search
4344                        rejected unexpectedly by server */
4345                /* BB Add code to handle unsupported level rc */
4346                cFYI(1, "Error in FindFirst = %d", rc);
4347
4348                cifs_buf_release(pSMB);
4349
4350                /* BB eventually could optimize out free and realloc of buf */
4351                /*    for this case */
4352                if (rc == -EAGAIN)
4353                        goto findFirstRetry;
4354        } else { /* decode response */
4355                /* BB remember to free buffer if error BB */
4356                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4357                if (rc == 0) {
4358                        unsigned int lnoff;
4359
4360                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4361                                psrch_inf->unicode = true;
4362                        else
4363                                psrch_inf->unicode = false;
4364
4365                        psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4366                        psrch_inf->smallBuf = 0;
4367                        psrch_inf->srch_entries_start =
4368                                (char *) &pSMBr->hdr.Protocol +
4369                                        le16_to_cpu(pSMBr->t2.DataOffset);
4370                        parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4371                               le16_to_cpu(pSMBr->t2.ParameterOffset));
4372
4373                        if (parms->EndofSearch)
4374                                psrch_inf->endOfSearch = true;
4375                        else
4376                                psrch_inf->endOfSearch = false;
4377
4378                        psrch_inf->entries_in_buffer =
4379                                        le16_to_cpu(parms->SearchCount);
4380                        psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4381                                psrch_inf->entries_in_buffer;
4382                        lnoff = le16_to_cpu(parms->LastNameOffset);
4383                        if (CIFSMaxBufSize < lnoff) {
4384                                cERROR(1, "ignoring corrupt resume name");
4385                                psrch_inf->last_entry = NULL;
4386                                return rc;
4387                        }
4388
4389                        psrch_inf->last_entry = psrch_inf->srch_entries_start +
4390                                                        lnoff;
4391
4392                        *pnetfid = parms->SearchHandle;
4393                } else {
4394                        cifs_buf_release(pSMB);
4395                }
4396        }
4397
4398        return rc;
4399}
4400
4401int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4402                 __u16 searchHandle, __u16 search_flags,
4403                 struct cifs_search_info *psrch_inf)
4404{
4405        TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4406        TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4407        T2_FNEXT_RSP_PARMS *parms;
4408        char *response_data;
4409        int rc = 0;
4410        int bytes_returned;
4411        unsigned int name_len;
4412        __u16 params, byte_count;
4413
4414        cFYI(1, "In FindNext");
4415
4416        if (psrch_inf->endOfSearch)
4417                return -ENOENT;
4418
4419        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4420                (void **) &pSMBr);
4421        if (rc)
4422                return rc;
4423
4424        params = 14; /* includes 2 bytes of null string, converted to LE below*/
4425        byte_count = 0;
4426        pSMB->TotalDataCount = 0;       /* no EAs */
4427        pSMB->MaxParameterCount = cpu_to_le16(8);
4428        pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4429        pSMB->MaxSetupCount = 0;
4430        pSMB->Reserved = 0;
4431        pSMB->Flags = 0;
4432        pSMB->Timeout = 0;
4433        pSMB->Reserved2 = 0;
4434        pSMB->ParameterOffset =  cpu_to_le16(
4435              offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4436        pSMB->DataCount = 0;
4437        pSMB->DataOffset = 0;
4438        pSMB->SetupCount = 1;
4439        pSMB->Reserved3 = 0;
4440        pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4441        pSMB->SearchHandle = searchHandle;      /* always kept as le */
4442        pSMB->SearchCount =
4443                cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4444        pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4445        pSMB->ResumeKey = psrch_inf->resume_key;
4446        pSMB->SearchFlags = cpu_to_le16(search_flags);
4447
4448        name_len = psrch_inf->resume_name_len;
4449        params += name_len;
4450        if (name_len < PATH_MAX) {
4451                memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4452                byte_count += name_len;
4453                /* 14 byte parm len above enough for 2 byte null terminator */
4454                pSMB->ResumeFileName[name_len] = 0;
4455                pSMB->ResumeFileName[name_len+1] = 0;
4456        } else {
4457                rc = -EINVAL;
4458                goto FNext2_err_exit;
4459        }
4460        byte_count = params + 1 /* pad */ ;
4461        pSMB->TotalParameterCount = cpu_to_le16(params);
4462        pSMB->ParameterCount = pSMB->TotalParameterCount;
4463        inc_rfc1001_len(pSMB, byte_count);
4464        pSMB->ByteCount = cpu_to_le16(byte_count);
4465
4466        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4467                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4468        cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4469        if (rc) {
4470                if (rc == -EBADF) {
4471                        psrch_inf->endOfSearch = true;
4472                        cifs_buf_release(pSMB);
4473                        rc = 0; /* search probably was closed at end of search*/
4474                } else
4475                        cFYI(1, "FindNext returned = %d", rc);
4476        } else {                /* decode response */
4477                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4478
4479                if (rc == 0) {
4480                        unsigned int lnoff;
4481
4482                        /* BB fixme add lock for file (srch_info) struct here */
4483                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4484                                psrch_inf->unicode = true;
4485                        else
4486                                psrch_inf->unicode = false;
4487                        response_data = (char *) &pSMBr->hdr.Protocol +
4488                               le16_to_cpu(pSMBr->t2.ParameterOffset);
4489                        parms = (T2_FNEXT_RSP_PARMS *)response_data;
4490                        response_data = (char *)&pSMBr->hdr.Protocol +
4491                                le16_to_cpu(pSMBr->t2.DataOffset);
4492                        if (psrch_inf->smallBuf)
4493                                cifs_small_buf_release(
4494                                        psrch_inf->ntwrk_buf_start);
4495                        else
4496                                cifs_buf_release(psrch_inf->ntwrk_buf_start);
4497                        psrch_inf->srch_entries_start = response_data;
4498                        psrch_inf->ntwrk_buf_start = (char *)pSMB;
4499                        psrch_inf->smallBuf = 0;
4500                        if (parms->EndofSearch)
4501                                psrch_inf->endOfSearch = true;
4502                        else
4503                                psrch_inf->endOfSearch = false;
4504                        psrch_inf->entries_in_buffer =
4505                                                le16_to_cpu(parms->SearchCount);
4506                        psrch_inf->index_of_last_entry +=
4507                                psrch_inf->entries_in_buffer;
4508                        lnoff = le16_to_cpu(parms->LastNameOffset);
4509                        if (CIFSMaxBufSize < lnoff) {
4510                                cERROR(1, "ignoring corrupt resume name");
4511                                psrch_inf->last_entry = NULL;
4512                                return rc;
4513                        } else
4514                                psrch_inf->last_entry =
4515                                        psrch_inf->srch_entries_start + lnoff;
4516
4517/*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4518            psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4519
4520                        /* BB fixme add unlock here */
4521                }
4522
4523        }
4524
4525        /* BB On error, should we leave previous search buf (and count and
4526        last entry fields) intact or free the previous one? */
4527
4528        /* Note: On -EAGAIN error only caller can retry on handle based calls
4529        since file handle passed in no longer valid */
4530FNext2_err_exit:
4531        if (rc != 0)
4532                cifs_buf_release(pSMB);
4533        return rc;
4534}
4535
4536int
4537CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4538              const __u16 searchHandle)
4539{
4540        int rc = 0;
4541        FINDCLOSE_REQ *pSMB = NULL;
4542
4543        cFYI(1, "In CIFSSMBFindClose");
4544        rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4545
4546        /* no sense returning error if session restarted
4547                as file handle has been closed */
4548        if (rc == -EAGAIN)
4549                return 0;
4550        if (rc)
4551                return rc;
4552
4553        pSMB->FileID = searchHandle;
4554        pSMB->ByteCount = 0;
4555        rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4556        if (rc)
4557                cERROR(1, "Send error in FindClose = %d", rc);
4558
4559        cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4560
4561        /* Since session is dead, search handle closed on server already */
4562        if (rc == -EAGAIN)
4563                rc = 0;
4564
4565        return rc;
4566}
4567
4568int
4569CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4570                      const char *search_name, __u64 *inode_number,
4571                      const struct nls_table *nls_codepage, int remap)
4572{
4573        int rc = 0;
4574        TRANSACTION2_QPI_REQ *pSMB = NULL;
4575        TRANSACTION2_QPI_RSP *pSMBr = NULL;
4576        int name_len, bytes_returned;
4577        __u16 params, byte_count;
4578
4579        cFYI(1, "In GetSrvInodeNum for %s", search_name);
4580        if (tcon == NULL)
4581                return -ENODEV;
4582
4583GetInodeNumberRetry:
4584        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4585                      (void **) &pSMBr);
4586        if (rc)
4587                return rc;
4588
4589        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4590                name_len =
4591                        cifsConvertToUTF16((__le16 *) pSMB->FileName,
4592                                           search_name, PATH_MAX, nls_codepage,
4593                                           remap);
4594                name_len++;     /* trailing null */
4595                name_len *= 2;
4596        } else {        /* BB improve the check for buffer overruns BB */
4597                name_len = strnlen(search_name, PATH_MAX);
4598                name_len++;     /* trailing null */
4599                strncpy(pSMB->FileName, search_name, name_len);
4600        }
4601
4602        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4603        pSMB->TotalDataCount = 0;
4604        pSMB->MaxParameterCount = cpu_to_le16(2);
4605        /* BB find exact max data count below from sess structure BB */
4606        pSMB->MaxDataCount = cpu_to_le16(4000);
4607        pSMB->MaxSetupCount = 0;
4608        pSMB->Reserved = 0;
4609        pSMB->Flags = 0;
4610        pSMB->Timeout = 0;
4611        pSMB->Reserved2 = 0;
4612        pSMB->ParameterOffset = cpu_to_le16(offsetof(
4613                struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4614        pSMB->DataCount = 0;
4615        pSMB->DataOffset = 0;
4616        pSMB->SetupCount = 1;
4617        pSMB->Reserved3 = 0;
4618        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4619        byte_count = params + 1 /* pad */ ;
4620        pSMB->TotalParameterCount = cpu_to_le16(params);
4621        pSMB->ParameterCount = pSMB->TotalParameterCount;
4622        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4623        pSMB->Reserved4 = 0;
4624        inc_rfc1001_len(pSMB, byte_count);
4625        pSMB->ByteCount = cpu_to_le16(byte_count);
4626
4627        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4628                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4629        if (rc) {
4630                cFYI(1, "error %d in QueryInternalInfo", rc);
4631        } else {
4632                /* decode response */
4633                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4634                /* BB also check enough total bytes returned */
4635                if (rc || get_bcc(&pSMBr->hdr) < 2)
4636                        /* If rc should we check for EOPNOSUPP and
4637                        disable the srvino flag? or in caller? */
4638                        rc = -EIO;      /* bad smb */
4639                else {
4640                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4641                        __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4642                        struct file_internal_info *pfinfo;
4643                        /* BB Do we need a cast or hash here ? */
4644                        if (count < 8) {
4645                                cFYI(1, "Illegal size ret in QryIntrnlInf");
4646                                rc = -EIO;
4647                                goto GetInodeNumOut;
4648                        }
4649                        pfinfo = (struct file_internal_info *)
4650                                (data_offset + (char *) &pSMBr->hdr.Protocol);
4651                        *inode_number = le64_to_cpu(pfinfo->UniqueId);
4652                }
4653        }
4654GetInodeNumOut:
4655        cifs_buf_release(pSMB);
4656        if (rc == -EAGAIN)
4657                goto GetInodeNumberRetry;
4658        return rc;
4659}
4660
4661/* parses DFS refferal V3 structure
4662 * caller is responsible for freeing target_nodes
4663 * returns:
4664 *      on success - 0
4665 *      on failure - errno
4666 */
4667static int
4668parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4669                unsigned int *num_of_nodes,
4670                struct dfs_info3_param **target_nodes,
4671                const struct nls_table *nls_codepage, int remap,
4672                const char *searchName)
4673{
4674        int i, rc = 0;
4675        char *data_end;
4676        bool is_unicode;
4677        struct dfs_referral_level_3 *ref;
4678
4679        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4680                is_unicode = true;
4681        else
4682                is_unicode = false;
4683        *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4684
4685        if (*num_of_nodes < 1) {
4686                cERROR(1, "num_referrals: must be at least > 0,"
4687                        "but we get num_referrals = %d", *num_of_nodes);
4688                rc = -EINVAL;
4689                goto parse_DFS_referrals_exit;
4690        }
4691
4692        ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4693        if (ref->VersionNumber != cpu_to_le16(3)) {
4694                cERROR(1, "Referrals of V%d version are not supported,"
4695                        "should be V3", le16_to_cpu(ref->VersionNumber));
4696                rc = -EINVAL;
4697                goto parse_DFS_referrals_exit;
4698        }
4699
4700        /* get the upper boundary of the resp buffer */
4701        data_end = (char *)(&(pSMBr->PathConsumed)) +
4702                                le16_to_cpu(pSMBr->t2.DataCount);
4703
4704        cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4705                        *num_of_nodes,
4706                        le32_to_cpu(pSMBr->DFSFlags));
4707
4708        *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4709                        *num_of_nodes, GFP_KERNEL);
4710        if (*target_nodes == NULL) {
4711                cERROR(1, "Failed to allocate buffer for target_nodes");
4712                rc = -ENOMEM;
4713                goto parse_DFS_referrals_exit;
4714        }
4715
4716        /* collect necessary data from referrals */
4717        for (i = 0; i < *num_of_nodes; i++) {
4718                char *temp;
4719                int max_len;
4720                struct dfs_info3_param *node = (*target_nodes)+i;
4721
4722                node->flags = le32_to_cpu(pSMBr->DFSFlags);
4723                if (is_unicode) {
4724                        __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4725                                                GFP_KERNEL);
4726                        if (tmp == NULL) {
4727                                rc = -ENOMEM;
4728                                goto parse_DFS_referrals_exit;
4729                        }
4730                        cifsConvertToUTF16((__le16 *) tmp, searchName,
4731                                           PATH_MAX, nls_codepage, remap);
4732                        node->path_consumed = cifs_utf16_bytes(tmp,
4733                                        le16_to_cpu(pSMBr->PathConsumed),
4734                                        nls_codepage);
4735                        kfree(tmp);
4736                } else
4737                        node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4738
4739                node->server_type = le16_to_cpu(ref->ServerType);
4740                node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4741
4742                /* copy DfsPath */
4743                temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4744                max_len = data_end - temp;
4745                node->path_name = cifs_strndup_from_utf16(temp, max_len,
4746                                                is_unicode, nls_codepage);
4747                if (!node->path_name) {
4748                        rc = -ENOMEM;
4749                        goto parse_DFS_referrals_exit;
4750                }
4751
4752                /* copy link target UNC */
4753                temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4754                max_len = data_end - temp;
4755                node->node_name = cifs_strndup_from_utf16(temp, max_len,
4756                                                is_unicode, nls_codepage);
4757                if (!node->node_name) {
4758                        rc = -ENOMEM;
4759                        goto parse_DFS_referrals_exit;
4760                }
4761
4762                ref++;
4763        }
4764
4765parse_DFS_referrals_exit:
4766        if (rc) {
4767                free_dfs_info_array(*target_nodes, *num_of_nodes);
4768                *target_nodes = NULL;
4769                *num_of_nodes = 0;
4770        }
4771        return rc;
4772}
4773
4774int
4775CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4776                const char *search_name, struct dfs_info3_param **target_nodes,
4777                unsigned int *num_of_nodes,
4778                const struct nls_table *nls_codepage, int remap)
4779{
4780/* TRANS2_GET_DFS_REFERRAL */
4781        TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4782        TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4783        int rc = 0;
4784        int bytes_returned;
4785        int name_len;
4786        __u16 params, byte_count;
4787        *num_of_nodes = 0;
4788        *target_nodes = NULL;
4789
4790        cFYI(1, "In GetDFSRefer the path %s", search_name);
4791        if (ses == NULL)
4792                return -ENODEV;
4793getDFSRetry:
4794        rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4795                      (void **) &pSMBr);
4796        if (rc)
4797                return rc;
4798
4799        /* server pointer checked in called function,
4800        but should never be null here anyway */
4801        pSMB->hdr.Mid = get_next_mid(ses->server);
4802        pSMB->hdr.Tid = ses->ipc_tid;
4803        pSMB->hdr.Uid = ses->Suid;
4804        if (ses->capabilities & CAP_STATUS32)
4805                pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4806        if (ses->capabilities & CAP_DFS)
4807                pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4808
4809        if (ses->capabilities & CAP_UNICODE) {
4810                pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4811                name_len =
4812                    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4813                                       search_name, PATH_MAX, nls_codepage,
4814                                       remap);
4815                name_len++;     /* trailing null */
4816                name_len *= 2;
4817        } else {        /* BB improve the check for buffer overruns BB */
4818                name_len = strnlen(search_name, PATH_MAX);
4819                name_len++;     /* trailing null */
4820                strncpy(pSMB->RequestFileName, search_name, name_len);
4821        }
4822
4823        if (ses->server) {
4824                if (ses->server->sec_mode &
4825                   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4826                        pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4827        }
4828
4829        pSMB->hdr.Uid = ses->Suid;
4830
4831        params = 2 /* level */  + name_len /*includes null */ ;
4832        pSMB->TotalDataCount = 0;
4833        pSMB->DataCount = 0;
4834        pSMB->DataOffset = 0;
4835        pSMB->MaxParameterCount = 0;
4836        /* BB find exact max SMB PDU from sess structure BB */
4837        pSMB->MaxDataCount = cpu_to_le16(4000);
4838        pSMB->MaxSetupCount = 0;
4839        pSMB->Reserved = 0;
4840        pSMB->Flags = 0;
4841        pSMB->Timeout = 0;
4842        pSMB->Reserved2 = 0;
4843        pSMB->ParameterOffset = cpu_to_le16(offsetof(
4844          struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4845        pSMB->SetupCount = 1;
4846        pSMB->Reserved3 = 0;
4847        pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4848        byte_count = params + 3 /* pad */ ;
4849        pSMB->ParameterCount = cpu_to_le16(params);
4850        pSMB->TotalParameterCount = pSMB->ParameterCount;
4851        pSMB->MaxReferralLevel = cpu_to_le16(3);
4852        inc_rfc1001_len(pSMB, byte_count);
4853        pSMB->ByteCount = cpu_to_le16(byte_count);
4854
4855        rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4856                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4857        if (rc) {
4858                cFYI(1, "Send error in GetDFSRefer = %d", rc);
4859                goto GetDFSRefExit;
4860        }
4861        rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4862
4863        /* BB Also check if enough total bytes returned? */
4864        if (rc || get_bcc(&pSMBr->hdr) < 17) {
4865                rc = -EIO;      /* bad smb */
4866                goto GetDFSRefExit;
4867        }
4868
4869        cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4870                                get_bcc(&pSMBr->hdr),
4871                                le16_to_cpu(pSMBr->t2.DataOffset));
4872
4873        /* parse returned result into more usable form */
4874        rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4875                                 target_nodes, nls_codepage, remap,
4876                                 search_name);
4877
4878GetDFSRefExit:
4879        cifs_buf_release(pSMB);
4880
4881        if (rc == -EAGAIN)
4882                goto getDFSRetry;
4883
4884        return rc;
4885}
4886
4887/* Query File System Info such as free space to old servers such as Win 9x */
4888int
4889SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4890              struct kstatfs *FSData)
4891{
4892/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4893        TRANSACTION2_QFSI_REQ *pSMB = NULL;
4894        TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4895        FILE_SYSTEM_ALLOC_INFO *response_data;
4896        int rc = 0;
4897        int bytes_returned = 0;
4898        __u16 params, byte_count;
4899
4900        cFYI(1, "OldQFSInfo");
4901oldQFSInfoRetry:
4902        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4903                (void **) &pSMBr);
4904        if (rc)
4905                return rc;
4906
4907        params = 2;     /* level */
4908        pSMB->TotalDataCount = 0;
4909        pSMB->MaxParameterCount = cpu_to_le16(2);
4910        pSMB->MaxDataCount = cpu_to_le16(1000);
4911        pSMB->MaxSetupCount = 0;
4912        pSMB->Reserved = 0;
4913        pSMB->Flags = 0;
4914        pSMB->Timeout = 0;
4915        pSMB->Reserved2 = 0;
4916        byte_count = params + 1 /* pad */ ;
4917        pSMB->TotalParameterCount = cpu_to_le16(params);
4918        pSMB->ParameterCount = pSMB->TotalParameterCount;
4919        pSMB->ParameterOffset = cpu_to_le16(offsetof(
4920        struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4921        pSMB->DataCount = 0;
4922        pSMB->DataOffset = 0;
4923        pSMB->SetupCount = 1;
4924        pSMB->Reserved3 = 0;
4925        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4926        pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4927        inc_rfc1001_len(pSMB, byte_count);
4928        pSMB->ByteCount = cpu_to_le16(byte_count);
4929
4930        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4931                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4932        if (rc) {
4933                cFYI(1, "Send error in QFSInfo = %d", rc);
4934        } else {                /* decode response */
4935                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4936
4937                if (rc || get_bcc(&pSMBr->hdr) < 18)
4938                        rc = -EIO;      /* bad smb */
4939                else {
4940                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4941                        cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4942                                 get_bcc(&pSMBr->hdr), data_offset);
4943
4944                        response_data = (FILE_SYSTEM_ALLOC_INFO *)
4945                                (((char *) &pSMBr->hdr.Protocol) + data_offset);
4946                        FSData->f_bsize =
4947                                le16_to_cpu(response_data->BytesPerSector) *
4948                                le32_to_cpu(response_data->
4949                                        SectorsPerAllocationUnit);
4950                        FSData->f_blocks =
4951                               le32_to_cpu(response_data->TotalAllocationUnits);
4952                        FSData->f_bfree = FSData->f_bavail =
4953                                le32_