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