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