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