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