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