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