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