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        /* even though we do not use raw we might as well set this
 467        accurately, in case we ever find a need for it */
 468        if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
 469                server->max_rw = 0xFF00;
 470                server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
 471        } else {
 472                server->max_rw = 0;/* do not need to use raw anyway */
 473                server->capabilities = CAP_MPX_MODE;
 474        }
 475        tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
 476        if (tmp == -1) {
 477                /* OS/2 often does not set timezone therefore
 478                 * we must use server time to calc time zone.
 479                 * Could deviate slightly from the right zone.
 480                 * Smallest defined timezone difference is 15 minutes
 481                 * (i.e. Nepal).  Rounding up/down is done to match
 482                 * this requirement.
 483                 */
 484                int val, seconds, remain, result;
 485                struct timespec ts, utc;
 486                utc = CURRENT_TIME;
 487                ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
 488                                    rsp->SrvTime.Time, 0);
 489                cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
 490                         (int)ts.tv_sec, (int)utc.tv_sec,
 491                         (int)(utc.tv_sec - ts.tv_sec));
 492                val = (int)(utc.tv_sec - ts.tv_sec);
 493                seconds = abs(val);
 494                result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
 495                remain = seconds % MIN_TZ_ADJ;
 496                if (remain >= (MIN_TZ_ADJ / 2))
 497                        result += MIN_TZ_ADJ;
 498                if (val < 0)
 499                        result = -result;
 500                server->timeAdj = result;
 501        } else {
 502                server->timeAdj = (int)tmp;
 503                server->timeAdj *= 60; /* also in seconds */
 504        }
 505        cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
 506
 507
 508        /* BB get server time for time conversions and add
 509        code to use it and timezone since this is not UTC */
 510
 511        if (rsp->EncryptionKeyLength ==
 512                        cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
 513                memcpy(server->cryptkey, rsp->EncryptionKey,
 514                        CIFS_CRYPTO_KEY_SIZE);
 515        } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
 516                return -EIO; /* need cryptkey unless plain text */
 517        }
 518
 519        cifs_dbg(FYI, "LANMAN negotiated\n");
 520        return 0;
 521}
 522#else
 523static inline int
 524decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
 525{
 526        cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
 527        return -EOPNOTSUPP;
 528}
 529#endif
 530
 531static bool
 532should_set_ext_sec_flag(enum securityEnum sectype)
 533{
 534        switch (sectype) {
 535        case RawNTLMSSP:
 536        case Kerberos:
 537                return true;
 538        case Unspecified:
 539                if (global_secflags &
 540                    (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
 541                        return true;
 542                /* Fallthrough */
 543        default:
 544                return false;
 545        }
 546}
 547
 548int
 549CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 550{
 551        NEGOTIATE_REQ *pSMB;
 552        NEGOTIATE_RSP *pSMBr;
 553        int rc = 0;
 554        int bytes_returned;
 555        int i;
 556        struct TCP_Server_Info *server = ses->server;
 557        u16 count;
 558
 559        if (!server) {
 560                WARN(1, "%s: server is NULL!\n", __func__);
 561                return -EIO;
 562        }
 563
 564        rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
 565                      (void **) &pSMB, (void **) &pSMBr);
 566        if (rc)
 567                return rc;
 568
 569        pSMB->hdr.Mid = get_next_mid(server);
 570        pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
 571
 572        if (should_set_ext_sec_flag(ses->sectype)) {
 573                cifs_dbg(FYI, "Requesting extended security.");
 574                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 575        }
 576
 577        count = 0;
 578        for (i = 0; i < CIFS_NUM_PROT; i++) {
 579                strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
 580                count += strlen(protocols[i].name) + 1;
 581                /* null at end of source and target buffers anyway */
 582        }
 583        inc_rfc1001_len(pSMB, count);
 584        pSMB->ByteCount = cpu_to_le16(count);
 585
 586        rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 587                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 588        if (rc != 0)
 589                goto neg_err_exit;
 590
 591        server->dialect = le16_to_cpu(pSMBr->DialectIndex);
 592        cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
 593        /* Check wct = 1 error case */
 594        if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
 595                /* core returns wct = 1, but we do not ask for core - otherwise
 596                small wct just comes when dialect index is -1 indicating we
 597                could not negotiate a common dialect */
 598                rc = -EOPNOTSUPP;
 599                goto neg_err_exit;
 600        } else if (pSMBr->hdr.WordCount == 13) {
 601                server->negflavor = CIFS_NEGFLAVOR_LANMAN;
 602                rc = decode_lanman_negprot_rsp(server, pSMBr);
 603                goto signing_check;
 604        } else if (pSMBr->hdr.WordCount != 17) {
 605                /* unknown wct */
 606                rc = -EOPNOTSUPP;
 607                goto neg_err_exit;
 608        }
 609        /* else wct == 17, NTLM or better */
 610
 611        server->sec_mode = pSMBr->SecurityMode;
 612        if ((server->sec_mode & SECMODE_USER) == 0)
 613                cifs_dbg(FYI, "share mode security\n");
 614
 615        /* one byte, so no need to convert this or EncryptionKeyLen from
 616           little endian */
 617        server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
 618                               cifs_max_pending);
 619        set_credits(server, server->maxReq);
 620        /* probably no need to store and check maxvcs */
 621        server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
 622        server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
 623        cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
 624        server->capabilities = le32_to_cpu(pSMBr->Capabilities);
 625        server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
 626        server->timeAdj *= 60;
 627
 628        if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
 629                server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
 630                memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
 631                       CIFS_CRYPTO_KEY_SIZE);
 632        } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
 633                        server->capabilities & CAP_EXTENDED_SECURITY) &&
 634                                (pSMBr->EncryptionKeyLength == 0)) {
 635                server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
 636                rc = decode_ext_sec_blob(ses, pSMBr);
 637        } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
 638                rc = -EIO; /* no crypt key only if plain text pwd */
 639        } else {
 640                server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
 641                server->capabilities &= ~CAP_EXTENDED_SECURITY;
 642        }
 643
 644signing_check:
 645        if (!rc)
 646                rc = cifs_enable_signing(server, ses->sign);
 647neg_err_exit:
 648        cifs_buf_release(pSMB);
 649
 650        cifs_dbg(FYI, "negprot rc %d\n", rc);
 651        return rc;
 652}
 653
 654int
 655CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
 656{
 657        struct smb_hdr *smb_buffer;
 658        int rc = 0;
 659
 660        cifs_dbg(FYI, "In tree disconnect\n");
 661
 662        /* BB: do we need to check this? These should never be NULL. */
 663        if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
 664                return -EIO;
 665
 666        /*
 667         * No need to return error on this operation if tid invalidated and
 668         * closed on server already e.g. due to tcp session crashing. Also,
 669         * the tcon is no longer on the list, so no need to take lock before
 670         * checking this.
 671         */
 672        if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
 673                return 0;
 674
 675        rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
 676                            (void **)&smb_buffer);
 677        if (rc)
 678                return rc;
 679
 680        rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
 681        if (rc)
 682                cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
 683
 684        /* No need to return error on this operation if tid invalidated and
 685           closed on server already e.g. due to tcp session crashing */
 686        if (rc == -EAGAIN)
 687                rc = 0;
 688
 689        return rc;
 690}
 691
 692/*
 693 * This is a no-op for now. We're not really interested in the reply, but
 694 * rather in the fact that the server sent one and that server->lstrp
 695 * gets updated.
 696 *
 697 * FIXME: maybe we should consider checking that the reply matches request?
 698 */
 699static void
 700cifs_echo_callback(struct mid_q_entry *mid)
 701{
 702        struct TCP_Server_Info *server = mid->callback_data;
 703
 704        DeleteMidQEntry(mid);
 705        add_credits(server, 1, CIFS_ECHO_OP);
 706}
 707
 708int
 709CIFSSMBEcho(struct TCP_Server_Info *server)
 710{
 711        ECHO_REQ *smb;
 712        int rc = 0;
 713        struct kvec iov;
 714        struct smb_rqst rqst = { .rq_iov = &iov,
 715                                 .rq_nvec = 1 };
 716
 717        cifs_dbg(FYI, "In echo request\n");
 718
 719        rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
 720        if (rc)
 721                return rc;
 722
 723        /* set up echo request */
 724        smb->hdr.Tid = 0xffff;
 725        smb->hdr.WordCount = 1;
 726        put_unaligned_le16(1, &smb->EchoCount);
 727        put_bcc(1, &smb->hdr);
 728        smb->Data[0] = 'a';
 729        inc_rfc1001_len(smb, 3);
 730        iov.iov_base = smb;
 731        iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
 732
 733        rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
 734                             server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
 735        if (rc)
 736                cifs_dbg(FYI, "Echo request failed: %d\n", rc);
 737
 738        cifs_small_buf_release(smb);
 739
 740        return rc;
 741}
 742
 743int
 744CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
 745{
 746        LOGOFF_ANDX_REQ *pSMB;
 747        int rc = 0;
 748
 749        cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
 750
 751        /*
 752         * BB: do we need to check validity of ses and server? They should
 753         * always be valid since we have an active reference. If not, that
 754         * should probably be a BUG()
 755         */
 756        if (!ses || !ses->server)
 757                return -EIO;
 758
 759        mutex_lock(&ses->session_mutex);
 760        if (ses->need_reconnect)
 761                goto session_already_dead; /* no need to send SMBlogoff if uid
 762                                              already closed due to reconnect */
 763        rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
 764        if (rc) {
 765                mutex_unlock(&ses->session_mutex);
 766                return rc;
 767        }
 768
 769        pSMB->hdr.Mid = get_next_mid(ses->server);
 770
 771        if (ses->server->sign)
 772                pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 773
 774        pSMB->hdr.Uid = ses->Suid;
 775
 776        pSMB->AndXCommand = 0xFF;
 777        rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
 778session_already_dead:
 779        mutex_unlock(&ses->session_mutex);
 780
 781        /* if session dead then we do not need to do ulogoff,
 782                since server closed smb session, no sense reporting
 783                error */
 784        if (rc == -EAGAIN)
 785                rc = 0;
 786        return rc;
 787}
 788
 789int
 790CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
 791                 const char *fileName, __u16 type,
 792                 const struct nls_table *nls_codepage, int remap)
 793{
 794        TRANSACTION2_SPI_REQ *pSMB = NULL;
 795        TRANSACTION2_SPI_RSP *pSMBr = NULL;
 796        struct unlink_psx_rq *pRqD;
 797        int name_len;
 798        int rc = 0;
 799        int bytes_returned = 0;
 800        __u16 params, param_offset, offset, byte_count;
 801
 802        cifs_dbg(FYI, "In POSIX delete\n");
 803PsxDelete:
 804        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 805                      (void **) &pSMBr);
 806        if (rc)
 807                return rc;
 808
 809        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 810                name_len =
 811                    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
 812                                       PATH_MAX, nls_codepage, remap);
 813                name_len++;     /* trailing null */
 814                name_len *= 2;
 815        } else { /* BB add path length overrun check */
 816                name_len = strnlen(fileName, PATH_MAX);
 817                name_len++;     /* trailing null */
 818                strncpy(pSMB->FileName, fileName, name_len);
 819        }
 820
 821        params = 6 + name_len;
 822        pSMB->MaxParameterCount = cpu_to_le16(2);
 823        pSMB->MaxDataCount = 0; /* BB double check this with jra */
 824        pSMB->MaxSetupCount = 0;
 825        pSMB->Reserved = 0;
 826        pSMB->Flags = 0;
 827        pSMB->Timeout = 0;
 828        pSMB->Reserved2 = 0;
 829        param_offset = offsetof(struct smb_com_transaction2_spi_req,
 830                                InformationLevel) - 4;
 831        offset = param_offset + params;
 832
 833        /* Setup pointer to Request Data (inode type) */
 834        pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
 835        pRqD->type = cpu_to_le16(type);
 836        pSMB->ParameterOffset = cpu_to_le16(param_offset);
 837        pSMB->DataOffset = cpu_to_le16(offset);
 838        pSMB->SetupCount = 1;
 839        pSMB->Reserved3 = 0;
 840        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
 841        byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
 842
 843        pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
 844        pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
 845        pSMB->ParameterCount = cpu_to_le16(params);
 846        pSMB->TotalParameterCount = pSMB->ParameterCount;
 847        pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
 848        pSMB->Reserved4 = 0;
 849        inc_rfc1001_len(pSMB, byte_count);
 850        pSMB->ByteCount = cpu_to_le16(byte_count);
 851        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 852                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 853        if (rc)
 854                cifs_dbg(FYI, "Posix delete returned %d\n", rc);
 855        cifs_buf_release(pSMB);
 856
 857        cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 858
 859        if (rc == -EAGAIN)
 860                goto PsxDelete;
 861
 862        return rc;
 863}
 864
 865int
 866CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 867               struct cifs_sb_info *cifs_sb)
 868{
 869        DELETE_FILE_REQ *pSMB = NULL;
 870        DELETE_FILE_RSP *pSMBr = NULL;
 871        int rc = 0;
 872        int bytes_returned;
 873        int name_len;
 874        int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 875
 876DelFileRetry:
 877        rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
 878                      (void **) &pSMBr);
 879        if (rc)
 880                return rc;
 881
 882        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 883                name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
 884                                              PATH_MAX, cifs_sb->local_nls,
 885                                              remap);
 886                name_len++;     /* trailing null */
 887                name_len *= 2;
 888        } else {                /* BB improve check for buffer overruns BB */
 889                name_len = strnlen(name, PATH_MAX);
 890                name_len++;     /* trailing null */
 891                strncpy(pSMB->fileName, name, name_len);
 892        }
 893        pSMB->SearchAttributes =
 894            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
 895        pSMB->BufferFormat = 0x04;
 896        inc_rfc1001_len(pSMB, name_len + 1);
 897        pSMB->ByteCount = cpu_to_le16(name_len + 1);
 898        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 899                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 900        cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 901        if (rc)
 902                cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
 903
 904        cifs_buf_release(pSMB);
 905        if (rc == -EAGAIN)
 906                goto DelFileRetry;
 907
 908        return rc;
 909}
 910
 911int
 912CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 913             struct cifs_sb_info *cifs_sb)
 914{
 915        DELETE_DIRECTORY_REQ *pSMB = NULL;
 916        DELETE_DIRECTORY_RSP *pSMBr = NULL;
 917        int rc = 0;
 918        int bytes_returned;
 919        int name_len;
 920        int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 921
 922        cifs_dbg(FYI, "In CIFSSMBRmDir\n");
 923RmDirRetry:
 924        rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
 925                      (void **) &pSMBr);
 926        if (rc)
 927                return rc;
 928
 929        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 930                name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
 931                                              PATH_MAX, cifs_sb->local_nls,
 932                                              remap);
 933                name_len++;     /* trailing null */
 934                name_len *= 2;
 935        } else {                /* BB improve check for buffer overruns BB */
 936                name_len = strnlen(name, PATH_MAX);
 937                name_len++;     /* trailing null */
 938                strncpy(pSMB->DirName, name, name_len);
 939        }
 940
 941        pSMB->BufferFormat = 0x04;
 942        inc_rfc1001_len(pSMB, name_len + 1);
 943        pSMB->ByteCount = cpu_to_le16(name_len + 1);
 944        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 945                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 946        cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
 947        if (rc)
 948                cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
 949
 950        cifs_buf_release(pSMB);
 951        if (rc == -EAGAIN)
 952                goto RmDirRetry;
 953        return rc;
 954}
 955
 956int
 957CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 958             struct cifs_sb_info *cifs_sb)
 959{
 960        int rc = 0;
 961        CREATE_DIRECTORY_REQ *pSMB = NULL;
 962        CREATE_DIRECTORY_RSP *pSMBr = NULL;
 963        int bytes_returned;
 964        int name_len;
 965        int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 966
 967        cifs_dbg(FYI, "In CIFSSMBMkDir\n");
 968MkDirRetry:
 969        rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
 970                      (void **) &pSMBr);
 971        if (rc)
 972                return rc;
 973
 974        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 975                name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
 976                                              PATH_MAX, cifs_sb->local_nls,
 977                                              remap);
 978                name_len++;     /* trailing null */
 979                name_len *= 2;
 980        } else {                /* BB improve check for buffer overruns BB */
 981                name_len = strnlen(name, PATH_MAX);
 982                name_len++;     /* trailing null */
 983                strncpy(pSMB->DirName, name, name_len);
 984        }
 985
 986        pSMB->BufferFormat = 0x04;
 987        inc_rfc1001_len(pSMB, name_len + 1);
 988        pSMB->ByteCount = cpu_to_le16(name_len + 1);
 989        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 990                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 991        cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
 992        if (rc)
 993                cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
 994
 995        cifs_buf_release(pSMB);
 996        if (rc == -EAGAIN)
 997                goto MkDirRetry;
 998        return rc;
 999}
1000
1001int
1002CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1003                __u32 posix_flags, __u64 mode, __u16 *netfid,
1004                FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1005                const char *name, const struct nls_table *nls_codepage,
1006                int remap)
1007{
1008        TRANSACTION2_SPI_REQ *pSMB = NULL;
1009        TRANSACTION2_SPI_RSP *pSMBr = NULL;
1010        int name_len;
1011        int rc = 0;
1012        int bytes_returned = 0;
1013        __u16 params, param_offset, offset, byte_count, count;
1014        OPEN_PSX_REQ *pdata;
1015        OPEN_PSX_RSP *psx_rsp;
1016
1017        cifs_dbg(FYI, "In POSIX Create\n");
1018PsxCreat:
1019        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1020                      (void **) &pSMBr);
1021        if (rc)
1022                return rc;
1023
1024        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1025                name_len =
1026                    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1027                                       PATH_MAX, nls_codepage, remap);
1028                name_len++;     /* trailing null */
1029                name_len *= 2;
1030        } else {        /* BB improve the check for buffer overruns BB */
1031                name_len = strnlen(name, PATH_MAX);
1032                name_len++;     /* trailing null */
1033                strncpy(pSMB->FileName, name, name_len);
1034        }
1035
1036        params = 6 + name_len;
1037        count = sizeof(OPEN_PSX_REQ);
1038        pSMB->MaxParameterCount = cpu_to_le16(2);
1039        pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1040        pSMB->MaxSetupCount = 0;
1041        pSMB->Reserved = 0;
1042        pSMB->Flags = 0;
1043        pSMB->Timeout = 0;
1044        pSMB->Reserved2 = 0;
1045        param_offset = offsetof(struct smb_com_transaction2_spi_req,
1046                                InformationLevel) - 4;
1047        offset = param_offset + params;
1048        pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1049        pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1050        pdata->Permissions = cpu_to_le64(mode);
1051        pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1052        pdata->OpenFlags =  cpu_to_le32(*pOplock);
1053        pSMB->ParameterOffset = cpu_to_le16(param_offset);
1054        pSMB->DataOffset = cpu_to_le16(offset);
1055        pSMB->SetupCount = 1;
1056        pSMB->Reserved3 = 0;
1057        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1058        byte_count = 3 /* pad */  + params + count;
1059
1060        pSMB->DataCount = cpu_to_le16(count);
1061        pSMB->ParameterCount = cpu_to_le16(params);
1062        pSMB->TotalDataCount = pSMB->DataCount;
1063        pSMB->TotalParameterCount = pSMB->ParameterCount;
1064        pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1065        pSMB->Reserved4 = 0;
1066        inc_rfc1001_len(pSMB, byte_count);
1067        pSMB->ByteCount = cpu_to_le16(byte_count);
1068        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1069                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1070        if (rc) {
1071                cifs_dbg(FYI, "Posix create returned %d\n", rc);
1072                goto psx_create_err;
1073        }
1074
1075        cifs_dbg(FYI, "copying inode info\n");
1076        rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1077
1078        if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1079                rc = -EIO;      /* bad smb */
1080                goto psx_create_err;
1081        }
1082
1083        /* copy return information to pRetData */
1084        psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1085                        + le16_to_cpu(pSMBr->t2.DataOffset));
1086
1087        *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1088        if (netfid)
1089                *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1090        /* Let caller know file was created so we can set the mode. */
1091        /* Do we care about the CreateAction in any other cases? */
1092        if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1093                *pOplock |= CIFS_CREATE_ACTION;
1094        /* check to make sure response data is there */
1095        if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1096                pRetData->Type = cpu_to_le32(-1); /* unknown */
1097                cifs_dbg(NOISY, "unknown type\n");
1098        } else {
1099                if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1100                                        + sizeof(FILE_UNIX_BASIC_INFO)) {
1101                        cifs_dbg(VFS, "Open response data too small\n");
1102                        pRetData->Type = cpu_to_le32(-1);
1103                        goto psx_create_err;
1104                }
1105                memcpy((char *) pRetData,
1106                        (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1107                        sizeof(FILE_UNIX_BASIC_INFO));
1108        }
1109
1110psx_create_err:
1111        cifs_buf_release(pSMB);
1112
1113        if (posix_flags & SMB_O_DIRECTORY)
1114                cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1115        else
1116                cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1117
1118        if (rc == -EAGAIN)
1119                goto PsxCreat;
1120
1121        return rc;
1122}
1123
1124static __u16 convert_disposition(int disposition)
1125{
1126        __u16 ofun = 0;
1127
1128        switch (disposition) {
1129                case FILE_SUPERSEDE:
1130                        ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1131                        break;
1132                case FILE_OPEN:
1133                        ofun = SMBOPEN_OAPPEND;
1134                        break;
1135                case FILE_CREATE:
1136                        ofun = SMBOPEN_OCREATE;
1137                        break;
1138                case FILE_OPEN_IF:
1139                        ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1140                        break;
1141                case FILE_OVERWRITE:
1142                        ofun = SMBOPEN_OTRUNC;
1143                        break;
1144                case FILE_OVERWRITE_IF:
1145                        ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1146                        break;
1147                default:
1148                        cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1149                        ofun =  SMBOPEN_OAPPEND; /* regular open */
1150        }
1151        return ofun;
1152}
1153
1154static int
1155access_flags_to_smbopen_mode(const int access_flags)
1156{
1157        int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1158
1159        if (masked_flags == GENERIC_READ)
1160                return SMBOPEN_READ;
1161        else if (masked_flags == GENERIC_WRITE)
1162                return SMBOPEN_WRITE;
1163
1164        /* just go for read/write */
1165        return SMBOPEN_READWRITE;
1166}
1167
1168int
1169SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1170            const char *fileName, const int openDisposition,
1171            const int access_flags, const int create_options, __u16 *netfid,
1172            int *pOplock, FILE_ALL_INFO *pfile_info,
1173            const struct nls_table *nls_codepage, int remap)
1174{
1175        int rc = -EACCES;
1176        OPENX_REQ *pSMB = NULL;
1177        OPENX_RSP *pSMBr = NULL;
1178        int bytes_returned;
1179        int name_len;
1180        __u16 count;
1181
1182OldOpenRetry:
1183        rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1184                      (void **) &pSMBr);
1185        if (rc)
1186                return rc;
1187
1188        pSMB->AndXCommand = 0xFF;       /* none */
1189
1190        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1191                count = 1;      /* account for one byte pad to word boundary */
1192                name_len =
1193                   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1194                                      fileName, PATH_MAX, nls_codepage, remap);
1195                name_len++;     /* trailing null */
1196                name_len *= 2;
1197        } else {                /* BB improve check for buffer overruns BB */
1198                count = 0;      /* no pad */
1199                name_len = strnlen(fileName, PATH_MAX);
1200                name_len++;     /* trailing null */
1201                strncpy(pSMB->fileName, fileName, name_len);
1202        }
1203        if (*pOplock & REQ_OPLOCK)
1204                pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1205        else if (*pOplock & REQ_BATCHOPLOCK)
1206                pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1207
1208        pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1209        pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1210        pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1211        /* set file as system file if special file such
1212           as fifo and server expecting SFU style and
1213           no Unix extensions */
1214
1215        if (create_options & CREATE_OPTION_SPECIAL)
1216                pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1217        else /* BB FIXME BB */
1218                pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1219
1220        if (create_options & CREATE_OPTION_READONLY)
1221                pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1222
1223        /* BB FIXME BB */
1224/*      pSMB->CreateOptions = cpu_to_le32(create_options &
1225                                                 CREATE_OPTIONS_MASK); */
1226        /* BB FIXME END BB */
1227
1228        pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1229        pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1230        count += name_len;
1231        inc_rfc1001_len(pSMB, count);
1232
1233        pSMB->ByteCount = cpu_to_le16(count);
1234        /* long_op set to 1 to allow for oplock break timeouts */
1235        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1236                        (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1237        cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1238        if (rc) {
1239                cifs_dbg(FYI, "Error in Open = %d\n", rc);
1240        } else {
1241        /* BB verify if wct == 15 */
1242
1243/*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1244
1245                *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1246                /* Let caller know file was created so we can set the mode. */
1247                /* Do we care about the CreateAction in any other cases? */
1248        /* BB FIXME BB */
1249/*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1250                        *pOplock |= CIFS_CREATE_ACTION; */
1251        /* BB FIXME END */
1252
1253                if (pfile_info) {
1254                        pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1255                        pfile_info->LastAccessTime = 0; /* BB fixme */
1256                        pfile_info->LastWriteTime = 0; /* BB fixme */
1257                        pfile_info->ChangeTime = 0;  /* BB fixme */
1258                        pfile_info->Attributes =
1259                                cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1260                        /* the file_info buf is endian converted by caller */
1261                        pfile_info->AllocationSize =
1262                                cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1263                        pfile_info->EndOfFile = pfile_info->AllocationSize;
1264                        pfile_info->NumberOfLinks = cpu_to_le32(1);
1265                        pfile_info->DeletePending = 0;
1266                }
1267        }
1268
1269        cifs_buf_release(pSMB);
1270        if (rc == -EAGAIN)
1271                goto OldOpenRetry;
1272        return rc;
1273}
1274
1275int
1276CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1277            const char *fileName, const int openDisposition,
1278            const int access_flags, const int create_options, __u16 *netfid,
1279            int *pOplock, FILE_ALL_INFO *pfile_info,
1280            const struct nls_table *nls_codepage, int remap)
1281{
1282        int rc = -EACCES;
1283        OPEN_REQ *pSMB = NULL;
1284        OPEN_RSP *pSMBr = NULL;
1285        int bytes_returned;
1286        int name_len;
1287        __u16 count;
1288
1289openRetry:
1290        rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1291                      (void **) &pSMBr);
1292        if (rc)
1293                return rc;
1294
1295        pSMB->AndXCommand = 0xFF;       /* none */
1296
1297        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1298                count = 1;      /* account for one byte pad to word boundary */
1299                name_len =
1300                    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1301                                       fileName, PATH_MAX, nls_codepage, remap);
1302                name_len++;     /* trailing null */
1303                name_len *= 2;
1304                pSMB->NameLength = cpu_to_le16(name_len);
1305        } else {                /* BB improve check for buffer overruns BB */
1306                count = 0;      /* no pad */
1307                name_len = strnlen(fileName, PATH_MAX);
1308                name_len++;     /* trailing null */
1309                pSMB->NameLength = cpu_to_le16(name_len);
1310                strncpy(pSMB->fileName, fileName, name_len);
1311        }
1312        if (*pOplock & REQ_OPLOCK)
1313                pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1314        else if (*pOplock & REQ_BATCHOPLOCK)
1315                pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1316        pSMB->DesiredAccess = cpu_to_le32(access_flags);
1317        pSMB->AllocationSize = 0;
1318        /* set file as system file if special file such
1319           as fifo and server expecting SFU style and
1320           no Unix extensions */
1321        if (create_options & CREATE_OPTION_SPECIAL)
1322                pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1323        else
1324                pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1325
1326        /* XP does not handle ATTR_POSIX_SEMANTICS */
1327        /* but it helps speed up case sensitive checks for other
1328        servers such as Samba */
1329        if (tcon->ses->capabilities & CAP_UNIX)
1330                pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1331
1332        if (create_options & CREATE_OPTION_READONLY)
1333                pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1334
1335        pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1336        pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1337        pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1338        /* BB Expirement with various impersonation levels and verify */
1339        pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1340        pSMB->SecurityFlags =
1341            SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1342
1343        count += name_len;
1344        inc_rfc1001_len(pSMB, count);
1345
1346        pSMB->ByteCount = cpu_to_le16(count);
1347        /* long_op set to 1 to allow for oplock break timeouts */
1348        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1349                        (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1350        cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1351        if (rc) {
1352                cifs_dbg(FYI, "Error in Open = %d\n", rc);
1353        } else {
1354                *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1355                *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1356                /* Let caller know file was created so we can set the mode. */
1357                /* Do we care about the CreateAction in any other cases? */
1358                if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1359                        *pOplock |= CIFS_CREATE_ACTION;
1360                if (pfile_info) {
1361                        memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1362                                36 /* CreationTime to Attributes */);
1363                        /* the file_info buf is endian converted by caller */
1364                        pfile_info->AllocationSize = pSMBr->AllocationSize;
1365                        pfile_info->EndOfFile = pSMBr->EndOfFile;
1366                        pfile_info->NumberOfLinks = cpu_to_le32(1);
1367                        pfile_info->DeletePending = 0;
1368                }
1369        }
1370
1371        cifs_buf_release(pSMB);
1372        if (rc == -EAGAIN)
1373                goto openRetry;
1374        return rc;
1375}
1376
1377/*
1378 * Discard any remaining data in the current SMB. To do this, we borrow the
1379 * current bigbuf.
1380 */
1381static int
1382cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1383{
1384        unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1385        int remaining = rfclen + 4 - server->total_read;
1386        struct cifs_readdata *rdata = mid->callback_data;
1387
1388        while (remaining > 0) {
1389                int length;
1390
1391                length = cifs_read_from_socket(server, server->bigbuf,
1392                                min_t(unsigned int, remaining,
1393                                    CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1394                if (length < 0)
1395                        return length;
1396                server->total_read += length;
1397                remaining -= length;
1398        }
1399
1400        dequeue_mid(mid, rdata->result);
1401        return 0;
1402}
1403
1404int
1405cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1406{
1407        int length, len;
1408        unsigned int data_offset, data_len;
1409        struct cifs_readdata *rdata = mid->callback_data;
1410        char *buf = server->smallbuf;
1411        unsigned int buflen = get_rfc1002_length(buf) + 4;
1412
1413        cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1414                 __func__, mid->mid, rdata->offset, rdata->bytes);
1415
1416        /*
1417         * read the rest of READ_RSP header (sans Data array), or whatever we
1418         * can if there's not enough data. At this point, we've read down to
1419         * the Mid.
1420         */
1421        len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1422                                                        HEADER_SIZE(server) + 1;
1423
1424        rdata->iov.iov_base = buf + HEADER_SIZE(server) - 1;
1425        rdata->iov.iov_len = len;
1426
1427        length = cifs_readv_from_socket(server, &rdata->iov, 1, len);
1428        if (length < 0)
1429                return length;
1430        server->total_read += length;
1431
1432        /* Was the SMB read successful? */
1433        rdata->result = server->ops->map_error(buf, false);
1434        if (rdata->result != 0) {
1435                cifs_dbg(FYI, "%s: server returned error %d\n",
1436                         __func__, rdata->result);
1437                return cifs_readv_discard(server, mid);
1438        }
1439
1440        /* Is there enough to get to the rest of the READ_RSP header? */
1441        if (server->total_read < server->vals->read_rsp_size) {
1442                cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1443                         __func__, server->total_read,
1444                         server->vals->read_rsp_size);
1445                rdata->result = -EIO;
1446                return cifs_readv_discard(server, mid);
1447        }
1448
1449        data_offset = server->ops->read_data_offset(buf) + 4;
1450        if (data_offset < server->total_read) {
1451                /*
1452                 * win2k8 sometimes sends an offset of 0 when the read
1453                 * is beyond the EOF. Treat it as if the data starts just after
1454                 * the header.
1455                 */
1456                cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1457                         __func__, data_offset);
1458                data_offset = server->total_read;
1459        } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1460                /* data_offset is beyond the end of smallbuf */
1461                cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1462                         __func__, data_offset);
1463                rdata->result = -EIO;
1464                return cifs_readv_discard(server, mid);
1465        }
1466
1467        cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1468                 __func__, server->total_read, data_offset);
1469
1470        len = data_offset - server->total_read;
1471        if (len > 0) {
1472                /* read any junk before data into the rest of smallbuf */
1473                rdata->iov.iov_base = buf + server->total_read;
1474                rdata->iov.iov_len = len;
1475                length = cifs_readv_from_socket(server, &rdata->iov, 1, len);
1476                if (length < 0)
1477                        return length;
1478                server->total_read += length;
1479        }
1480
1481        /* set up first iov for signature check */
1482        rdata->iov.iov_base = buf;
1483        rdata->iov.iov_len = server->total_read;
1484        cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
1485                 rdata->iov.iov_base, rdata->iov.iov_len);
1486
1487        /* how much data is in the response? */
1488        data_len = server->ops->read_data_length(buf);
1489        if (data_offset + data_len > buflen) {
1490                /* data_len is corrupt -- discard frame */
1491                rdata->result = -EIO;
1492                return cifs_readv_discard(server, mid);
1493        }
1494
1495        length = rdata->read_into_pages(server, rdata, data_len);
1496        if (length < 0)
1497                return length;
1498
1499        server->total_read += length;
1500        rdata->bytes = length;
1501
1502        cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1503                 server->total_read, buflen, data_len);
1504
1505        /* discard anything left over */
1506        if (server->total_read < buflen)
1507                return cifs_readv_discard(server, mid);
1508
1509        dequeue_mid(mid, false);
1510        return length;
1511}
1512
1513static void
1514cifs_readv_callback(struct mid_q_entry *mid)
1515{
1516        struct cifs_readdata *rdata = mid->callback_data;
1517        struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1518        struct TCP_Server_Info *server = tcon->ses->server;
1519        struct smb_rqst rqst = { .rq_iov = &rdata->iov,
1520                                 .rq_nvec = 1,
1521                                 .rq_pages = rdata->pages,
1522                                 .rq_npages = rdata->nr_pages,
1523                                 .rq_pagesz = rdata->pagesz,
1524                                 .rq_tailsz = rdata->tailsz };
1525
1526        cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1527                 __func__, mid->mid, mid->mid_state, rdata->result,
1528                 rdata->bytes);
1529
1530        switch (mid->mid_state) {
1531        case MID_RESPONSE_RECEIVED:
1532                /* result already set, check signature */
1533                if (server->sign) {
1534                        int rc = 0;
1535
1536                        rc = cifs_verify_signature(&rqst, server,
1537                                                  mid->sequence_number);
1538                        if (rc)
1539                                cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1540                                         rc);
1541                }
1542                /* FIXME: should this be counted toward the initiating task? */
1543                task_io_account_read(rdata->bytes);
1544                cifs_stats_bytes_read(tcon, rdata->bytes);
1545                break;
1546        case MID_REQUEST_SUBMITTED:
1547        case MID_RETRY_NEEDED:
1548                rdata->result = -EAGAIN;
1549                break;
1550        default:
1551                rdata->result = -EIO;
1552        }
1553
1554        queue_work(cifsiod_wq, &rdata->work);
1555        DeleteMidQEntry(mid);
1556        add_credits(server, 1, 0);
1557}
1558
1559/* cifs_async_readv - send an async write, and set up mid to handle result */
1560int
1561cifs_async_readv(struct cifs_readdata *rdata)
1562{
1563        int rc;
1564        READ_REQ *smb = NULL;
1565        int wct;
1566        struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1567        struct smb_rqst rqst = { .rq_iov = &rdata->iov,
1568                                 .rq_nvec = 1 };
1569
1570        cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1571                 __func__, rdata->offset, rdata->bytes);
1572
1573        if (tcon->ses->capabilities & CAP_LARGE_FILES)
1574                wct = 12;
1575        else {
1576                wct = 10; /* old style read */
1577                if ((rdata->offset >> 32) > 0)  {
1578                        /* can not handle this big offset for old */
1579                        return -EIO;
1580                }
1581        }
1582
1583        rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1584        if (rc)
1585                return rc;
1586
1587        smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1588        smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1589
1590        smb->AndXCommand = 0xFF;        /* none */
1591        smb->Fid = rdata->cfile->fid.netfid;
1592        smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1593        if (wct == 12)
1594                smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1595        smb->Remaining = 0;
1596        smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1597        smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1598        if (wct == 12)
1599                smb->ByteCount = 0;
1600        else {
1601                /* old style read */
1602                struct smb_com_readx_req *smbr =
1603                        (struct smb_com_readx_req *)smb;
1604                smbr->ByteCount = 0;
1605        }
1606
1607        /* 4 for RFC1001 length + 1 for BCC */
1608        rdata->iov.iov_base = smb;
1609        rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1610
1611        kref_get(&rdata->refcount);
1612        rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1613                             cifs_readv_callback, rdata, 0);
1614
1615        if (rc == 0)
1616                cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1617        else
1618                kref_put(&rdata->refcount, cifs_readdata_release);
1619
1620        cifs_small_buf_release(smb);
1621        return rc;
1622}
1623
1624int
1625CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1626            unsigned int *nbytes, char **buf, int *pbuf_type)
1627{
1628        int rc = -EACCES;
1629        READ_REQ *pSMB = NULL;
1630        READ_RSP *pSMBr = NULL;
1631        char *pReadData = NULL;
1632        int wct;
1633        int resp_buf_type = 0;
1634        struct kvec iov[1];
1635        __u32 pid = io_parms->pid;
1636        __u16 netfid = io_parms->netfid;
1637        __u64 offset = io_parms->offset;
1638        struct cifs_tcon *tcon = io_parms->tcon;
1639        unsigned int count = io_parms->length;
1640
1641        cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1642        if (tcon->ses->capabilities & CAP_LARGE_FILES)
1643                wct = 12;
1644        else {
1645                wct = 10; /* old style read */
1646                if ((offset >> 32) > 0)  {
1647                        /* can not handle this big offset for old */
1648                        return -EIO;
1649                }
1650        }
1651
1652        *nbytes = 0;
1653        rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1654        if (rc)
1655                return rc;
1656
1657        pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1658        pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1659
1660        /* tcon and ses pointer are checked in smb_init */
1661        if (tcon->ses->server == NULL)
1662                return -ECONNABORTED;
1663
1664        pSMB->AndXCommand = 0xFF;       /* none */
1665        pSMB->Fid = netfid;
1666        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1667        if (wct == 12)
1668                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1669
1670        pSMB->Remaining = 0;
1671        pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1672        pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1673        if (wct == 12)
1674                pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1675        else {
1676                /* old style read */
1677                struct smb_com_readx_req *pSMBW =
1678                        (struct smb_com_readx_req *)pSMB;
1679                pSMBW->ByteCount = 0;
1680        }
1681
1682        iov[0].iov_base = (char *)pSMB;
1683        iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1684        rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1685                         &resp_buf_type, CIFS_LOG_ERROR);
1686        cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1687        pSMBr = (READ_RSP *)iov[0].iov_base;
1688        if (rc) {
1689                cifs_dbg(VFS, "Send error in read = %d\n", rc);
1690        } else {
1691                int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1692                data_length = data_length << 16;
1693                data_length += le16_to_cpu(pSMBr->DataLength);
1694                *nbytes = data_length;
1695
1696                /*check that DataLength would not go beyond end of SMB */
1697                if ((data_length > CIFSMaxBufSize)
1698                                || (data_length > count)) {
1699                        cifs_dbg(FYI, "bad length %d for count %d\n",
1700                                 data_length, count);
1701                        rc = -EIO;
1702                        *nbytes = 0;
1703                } else {
1704                        pReadData = (char *) (&pSMBr->hdr.Protocol) +
1705                                        le16_to_cpu(pSMBr->DataOffset);
1706/*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1707                                cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1708                                rc = -EFAULT;
1709                        }*/ /* can not use copy_to_user when using page cache*/
1710                        if (*buf)
1711                                memcpy(*buf, pReadData, data_length);
1712                }
1713        }
1714
1715/*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1716        if (*buf) {
1717                if (resp_buf_type == CIFS_SMALL_BUFFER)
1718                        cifs_small_buf_release(iov[0].iov_base);
1719                else if (resp_buf_type == CIFS_LARGE_BUFFER)
1720                        cifs_buf_release(iov[0].iov_base);
1721        } else if (resp_buf_type != CIFS_NO_BUFFER) {
1722                /* return buffer to caller to free */
1723                *buf = iov[0].iov_base;
1724                if (resp_buf_type == CIFS_SMALL_BUFFER)
1725                        *pbuf_type = CIFS_SMALL_BUFFER;
1726                else if (resp_buf_type == CIFS_LARGE_BUFFER)
1727                        *pbuf_type = CIFS_LARGE_BUFFER;
1728        } /* else no valid buffer on return - leave as null */
1729
1730        /* Note: On -EAGAIN error only caller can retry on handle based calls
1731                since file handle passed in no longer valid */
1732        return rc;
1733}
1734
1735
1736int
1737CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1738             unsigned int *nbytes, const char *buf,
1739             const char __user *ubuf, const int long_op)
1740{
1741        int rc = -EACCES;
1742        WRITE_REQ *pSMB = NULL;
1743        WRITE_RSP *pSMBr = NULL;
1744        int bytes_returned, wct;
1745        __u32 bytes_sent;
1746        __u16 byte_count;
1747        __u32 pid = io_parms->pid;
1748        __u16 netfid = io_parms->netfid;
1749        __u64 offset = io_parms->offset;
1750        struct cifs_tcon *tcon = io_parms->tcon;
1751        unsigned int count = io_parms->length;
1752
1753        *nbytes = 0;
1754
1755        /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1756        if (tcon->ses == NULL)
1757                return -ECONNABORTED;
1758
1759        if (tcon->ses->capabilities & CAP_LARGE_FILES)
1760                wct = 14;
1761        else {
1762                wct = 12;
1763                if ((offset >> 32) > 0) {
1764                        /* can not handle big offset for old srv */
1765                        return -EIO;
1766                }
1767        }
1768
1769        rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1770                      (void **) &pSMBr);
1771        if (rc)
1772                return rc;
1773
1774        pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1775        pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1776
1777        /* tcon and ses pointer are checked in smb_init */
1778        if (tcon->ses->server == NULL)
1779                return -ECONNABORTED;
1780
1781        pSMB->AndXCommand = 0xFF;       /* none */
1782        pSMB->Fid = netfid;
1783        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1784        if (wct == 14)
1785                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1786
1787        pSMB->Reserved = 0xFFFFFFFF;
1788        pSMB->WriteMode = 0;
1789        pSMB->Remaining = 0;
1790
1791        /* Can increase buffer size if buffer is big enough in some cases ie we
1792        can send more if LARGE_WRITE_X capability returned by the server and if
1793        our buffer is big enough or if we convert to iovecs on socket writes
1794        and eliminate the copy to the CIFS buffer */
1795        if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1796                bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1797        } else {
1798                bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1799                         & ~0xFF;
1800        }
1801
1802        if (bytes_sent > count)
1803                bytes_sent = count;
1804        pSMB->DataOffset =
1805                cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1806        if (buf)
1807                memcpy(pSMB->Data, buf, bytes_sent);
1808        else if (ubuf) {
1809                if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1810                        cifs_buf_release(pSMB);
1811                        return -EFAULT;
1812                }
1813        } else if (count != 0) {
1814                /* No buffer */
1815                cifs_buf_release(pSMB);
1816                return -EINVAL;
1817        } /* else setting file size with write of zero bytes */
1818        if (wct == 14)
1819                byte_count = bytes_sent + 1; /* pad */
1820        else /* wct == 12 */
1821                byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1822
1823        pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1824        pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1825        inc_rfc1001_len(pSMB, byte_count);
1826
1827        if (wct == 14)
1828                pSMB->ByteCount = cpu_to_le16(byte_count);
1829        else { /* old style write has byte count 4 bytes earlier
1830                  so 4 bytes pad  */
1831                struct smb_com_writex_req *pSMBW =
1832                        (struct smb_com_writex_req *)pSMB;
1833                pSMBW->ByteCount = cpu_to_le16(byte_count);
1834        }
1835
1836        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1837                         (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1838        cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1839        if (rc) {
1840                cifs_dbg(FYI, "Send error in write = %d\n", rc);
1841        } else {
1842                *nbytes = le16_to_cpu(pSMBr->CountHigh);
1843                *nbytes = (*nbytes) << 16;
1844                *nbytes += le16_to_cpu(pSMBr->Count);
1845
1846                /*
1847                 * Mask off high 16 bits when bytes written as returned by the
1848                 * server is greater than bytes requested by the client. Some
1849                 * OS/2 servers are known to set incorrect CountHigh values.
1850                 */
1851                if (*nbytes > count)
1852                        *nbytes &= 0xFFFF;
1853        }
1854
1855        cifs_buf_release(pSMB);
1856
1857        /* Note: On -EAGAIN error only caller can retry on handle based calls
1858                since file handle passed in no longer valid */
1859
1860        return rc;
1861}
1862
1863void
1864cifs_writedata_release(struct kref *refcount)
1865{
1866        struct cifs_writedata *wdata = container_of(refcount,
1867                                        struct cifs_writedata, refcount);
1868
1869        if (wdata->cfile)
1870                cifsFileInfo_put(wdata->cfile);
1871
1872        kfree(wdata);
1873}
1874
1875/*
1876 * Write failed with a retryable error. Resend the write request. It's also
1877 * possible that the page was redirtied so re-clean the page.
1878 */
1879static void
1880cifs_writev_requeue(struct cifs_writedata *wdata)
1881{
1882        int i, rc;
1883        struct inode *inode = wdata->cfile->dentry->d_inode;
1884        struct TCP_Server_Info *server;
1885
1886        for (i = 0; i < wdata->nr_pages; i++) {
1887                lock_page(wdata->pages[i]);
1888                clear_page_dirty_for_io(wdata->pages[i]);
1889        }
1890
1891        do {
1892                server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1893                rc = server->ops->async_writev(wdata);
1894        } while (rc == -EAGAIN);
1895
1896        for (i = 0; i < wdata->nr_pages; i++) {
1897                unlock_page(wdata->pages[i]);
1898                if (rc != 0) {
1899                        SetPageError(wdata->pages[i]);
1900                        end_page_writeback(wdata->pages[i]);
1901                        page_cache_release(wdata->pages[i]);
1902                }
1903        }
1904
1905        mapping_set_error(inode->i_mapping, rc);
1906        kref_put(&wdata->refcount, cifs_writedata_release);
1907}
1908
1909void
1910cifs_writev_complete(struct work_struct *work)
1911{
1912        struct cifs_writedata *wdata = container_of(work,
1913                                                struct cifs_writedata, work);
1914        struct inode *inode = wdata->cfile->dentry->d_inode;
1915        int i = 0;
1916
1917        if (wdata->result == 0) {
1918                spin_lock(&inode->i_lock);
1919                cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1920                spin_unlock(&inode->i_lock);
1921                cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1922                                         wdata->bytes);
1923        } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1924                return cifs_writev_requeue(wdata);
1925
1926        for (i = 0; i < wdata->nr_pages; i++) {
1927                struct page *page = wdata->pages[i];
1928                if (wdata->result == -EAGAIN)
1929                        __set_page_dirty_nobuffers(page);
1930                else if (wdata->result < 0)
1931                        SetPageError(page);
1932                end_page_writeback(page);
1933                page_cache_release(page);
1934        }
1935        if (wdata->result != -EAGAIN)
1936                mapping_set_error(inode->i_mapping, wdata->result);
1937        kref_put(&wdata->refcount, cifs_writedata_release);
1938}
1939
1940struct cifs_writedata *
1941cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1942{
1943        struct cifs_writedata *wdata;
1944
1945        /* this would overflow */
1946        if (nr_pages == 0) {
1947                cifs_dbg(VFS, "%s: called with nr_pages == 0!\n", __func__);
1948                return NULL;
1949        }
1950
1951        /* writedata + number of page pointers */
1952        wdata = kzalloc(sizeof(*wdata) +
1953                        sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1954        if (wdata != NULL) {
1955                kref_init(&wdata->refcount);
1956                INIT_LIST_HEAD(&wdata->list);
1957                init_completion(&wdata->done);
1958                INIT_WORK(&wdata->work, complete);
1959        }
1960        return wdata;
1961}
1962
1963/*
1964 * Check the mid_state and signature on received buffer (if any), and queue the
1965 * workqueue completion task.
1966 */
1967static void
1968cifs_writev_callback(struct mid_q_entry *mid)
1969{
1970        struct cifs_writedata *wdata = mid->callback_data;
1971        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1972        unsigned int written;
1973        WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1974
1975        switch (mid->mid_state) {
1976        case MID_RESPONSE_RECEIVED:
1977                wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1978                if (wdata->result != 0)
1979                        break;
1980
1981                written = le16_to_cpu(smb->CountHigh);
1982                written <<= 16;
1983                written += le16_to_cpu(smb->Count);
1984                /*
1985                 * Mask off high 16 bits when bytes written as returned
1986                 * by the server is greater than bytes requested by the
1987                 * client. OS/2 servers are known to set incorrect
1988                 * CountHigh values.
1989                 */
1990                if (written > wdata->bytes)
1991                        written &= 0xFFFF;
1992
1993                if (written < wdata->bytes)
1994                        wdata->result = -ENOSPC;
1995                else
1996                        wdata->bytes = written;
1997                break;
1998        case MID_REQUEST_SUBMITTED:
1999        case MID_RETRY_NEEDED:
2000                wdata->result = -EAGAIN;
2001                break;
2002        default:
2003                wdata->result = -EIO;
2004                break;
2005        }
2006
2007        queue_work(cifsiod_wq, &wdata->work);
2008        DeleteMidQEntry(mid);
2009        add_credits(tcon->ses->server, 1, 0);
2010}
2011
2012/* cifs_async_writev - send an async write, and set up mid to handle result */
2013int
2014cifs_async_writev(struct cifs_writedata *wdata)
2015{
2016        int rc = -EACCES;
2017        WRITE_REQ *smb = NULL;
2018        int wct;
2019        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2020        struct kvec iov;
2021        struct smb_rqst rqst = { };
2022
2023        if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2024                wct = 14;
2025        } else {
2026                wct = 12;
2027                if (wdata->offset >> 32 > 0) {
2028                        /* can not handle big offset for old srv */
2029                        return -EIO;
2030                }
2031        }
2032
2033        rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2034        if (rc)
2035                goto async_writev_out;
2036
2037        smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2038        smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2039
2040        smb->AndXCommand = 0xFF;        /* none */
2041        smb->Fid = wdata->cfile->fid.netfid;
2042        smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2043        if (wct == 14)
2044                smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2045        smb->Reserved = 0xFFFFFFFF;
2046        smb->WriteMode = 0;
2047        smb->Remaining = 0;
2048
2049        smb->DataOffset =
2050            cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2051
2052        /* 4 for RFC1001 length + 1 for BCC */
2053        iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2054        iov.iov_base = smb;
2055
2056        rqst.rq_iov = &iov;
2057        rqst.rq_nvec = 1;
2058        rqst.rq_pages = wdata->pages;
2059        rqst.rq_npages = wdata->nr_pages;
2060        rqst.rq_pagesz = wdata->pagesz;
2061        rqst.rq_tailsz = wdata->tailsz;
2062
2063        cifs_dbg(FYI, "async write at %llu %u bytes\n",
2064                 wdata->offset, wdata->bytes);
2065
2066        smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2067        smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2068
2069        if (wct == 14) {
2070                inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2071                put_bcc(wdata->bytes + 1, &smb->hdr);
2072        } else {
2073                /* wct == 12 */
2074                struct smb_com_writex_req *smbw =
2075                                (struct smb_com_writex_req *)smb;
2076                inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2077                put_bcc(wdata->bytes + 5, &smbw->hdr);
2078                iov.iov_len += 4; /* pad bigger by four bytes */
2079        }
2080
2081        kref_get(&wdata->refcount);
2082        rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2083                                cifs_writev_callback, wdata, 0);
2084
2085        if (rc == 0)
2086                cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2087        else
2088                kref_put(&wdata->refcount, cifs_writedata_release);
2089
2090async_writev_out:
2091        cifs_small_buf_release(smb);
2092        return rc;
2093}
2094
2095int
2096CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2097              unsigned int *nbytes, struct kvec *iov, int n_vec)
2098{
2099        int rc = -EACCES;
2100        WRITE_REQ *pSMB = NULL;
2101        int wct;
2102        int smb_hdr_len;
2103        int resp_buf_type = 0;
2104        __u32 pid = io_parms->pid;
2105        __u16 netfid = io_parms->netfid;
2106        __u64 offset = io_parms->offset;
2107        struct cifs_tcon *tcon = io_parms->tcon;
2108        unsigned int count = io_parms->length;
2109
2110        *nbytes = 0;
2111
2112        cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2113
2114        if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2115                wct = 14;
2116        } else {
2117                wct = 12;
2118                if ((offset >> 32) > 0) {
2119                        /* can not handle big offset for old srv */
2120                        return -EIO;
2121                }
2122        }
2123        rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2124        if (rc)
2125                return rc;
2126
2127        pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2128        pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2129
2130        /* tcon and ses pointer are checked in smb_init */
2131        if (tcon->ses->server == NULL)
2132                return -ECONNABORTED;
2133
2134        pSMB->AndXCommand = 0xFF;       /* none */
2135        pSMB->Fid = netfid;
2136        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2137        if (wct == 14)
2138                pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2139        pSMB->Reserved = 0xFFFFFFFF;
2140        pSMB->WriteMode = 0;
2141        pSMB->Remaining = 0;
2142
2143        pSMB->DataOffset =
2144            cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2145
2146        pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2147        pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2148        /* header + 1 byte pad */
2149        smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2150        if (wct == 14)
2151                inc_rfc1001_len(pSMB, count + 1);
2152        else /* wct == 12 */
2153                inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2154        if (wct == 14)
2155                pSMB->ByteCount = cpu_to_le16(count + 1);
2156        else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2157                struct smb_com_writex_req *pSMBW =
2158                                (struct smb_com_writex_req *)pSMB;
2159                pSMBW->ByteCount = cpu_to_le16(count + 5);
2160        }
2161        iov[0].iov_base = pSMB;
2162        if (wct == 14)
2163                iov[0].iov_len = smb_hdr_len + 4;
2164        else /* wct == 12 pad bigger by four bytes */
2165                iov[0].iov_len = smb_hdr_len + 8;
2166
2167
2168        rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
2169        cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2170        if (rc) {
2171                cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2172        } else if (resp_buf_type == 0) {
2173                /* presumably this can not happen, but best to be safe */
2174                rc = -EIO;
2175        } else {
2176                WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2177                *nbytes = le16_to_cpu(pSMBr->CountHigh);
2178                *nbytes = (*nbytes) << 16;
2179                *nbytes += le16_to_cpu(pSMBr->Count);
2180
2181                /*
2182                 * Mask off high 16 bits when bytes written as returned by the
2183                 * server is greater than bytes requested by the client. OS/2
2184                 * servers are known to set incorrect CountHigh values.
2185                 */
2186                if (*nbytes > count)
2187                        *nbytes &= 0xFFFF;
2188        }
2189
2190/*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2191        if (resp_buf_type == CIFS_SMALL_BUFFER)
2192                cifs_small_buf_release(iov[0].iov_base);
2193        else if (resp_buf_type == CIFS_LARGE_BUFFER)
2194                cifs_buf_release(iov[0].iov_base);
2195
2196        /* Note: On -EAGAIN error only caller can retry on handle based calls
2197                since file handle passed in no longer valid */
2198
2199        return rc;
2200}
2201
2202int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2203               const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2204               const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2205{
2206        int rc = 0;
2207        LOCK_REQ *pSMB = NULL;
2208        struct kvec iov[2];
2209        int resp_buf_type;
2210        __u16 count;
2211
2212        cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2213                 num_lock, num_unlock);
2214
2215        rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2216        if (rc)
2217                return rc;
2218
2219        pSMB->Timeout = 0;
2220        pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2221        pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2222        pSMB->LockType = lock_type;
2223        pSMB->AndXCommand = 0xFF; /* none */
2224        pSMB->Fid = netfid; /* netfid stays le */
2225
2226        count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2227        inc_rfc1001_len(pSMB, count);
2228        pSMB->ByteCount = cpu_to_le16(count);
2229
2230        iov[0].iov_base = (char *)pSMB;
2231        iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2232                         (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2233        iov[1].iov_base = (char *)buf;
2234        iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2235
2236        cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2237        rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2238        if (rc)
2239                cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2240
2241        return rc;
2242}
2243
2244int
2245CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2246            const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2247            const __u64 offset, const __u32 numUnlock,
2248            const __u32 numLock, const __u8 lockType,
2249            const bool waitFlag, const __u8 oplock_level)
2250{
2251        int rc = 0;
2252        LOCK_REQ *pSMB = NULL;
2253/*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2254        int bytes_returned;
2255        int flags = 0;
2256        __u16 count;
2257
2258        cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2259                 (int)waitFlag, numLock);
2260        rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2261
2262        if (rc)
2263                return rc;
2264
2265        if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2266                /* no response expected */
2267                flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2268                pSMB->Timeout = 0;
2269        } else if (waitFlag) {
2270                flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2271                pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2272        } else {
2273                pSMB->Timeout = 0;
2274        }
2275
2276        pSMB->NumberOfLocks = cpu_to_le16(numLock);
2277        pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2278        pSMB->LockType = lockType;
2279        pSMB->OplockLevel = oplock_level;
2280        pSMB->AndXCommand = 0xFF;       /* none */
2281        pSMB->Fid = smb_file_id; /* netfid stays le */
2282
2283        if ((numLock != 0) || (numUnlock != 0)) {
2284                pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2285                /* BB where to store pid high? */
2286                pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2287                pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2288                pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2289                pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2290                count = sizeof(LOCKING_ANDX_RANGE);
2291        } else {
2292                /* oplock break */
2293                count = 0;
2294        }
2295        inc_rfc1001_len(pSMB, count);
2296        pSMB->ByteCount = cpu_to_le16(count);
2297
2298        if (waitFlag) {
2299                rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2300                        (struct smb_hdr *) pSMB, &bytes_returned);
2301                cifs_small_buf_release(pSMB);
2302        } else {
2303                rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2304                /* SMB buffer freed by function above */
2305        }
2306        cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2307        if (rc)
2308                cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2309
2310        /* Note: On -EAGAIN error only caller can retry on handle based calls
2311        since file handle passed in no longer valid */
2312        return rc;
2313}
2314
2315int
2316CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2317                const __u16 smb_file_id, const __u32 netpid,
2318                const loff_t start_offset, const __u64 len,
2319                struct file_lock *pLockData, const __u16 lock_type,
2320                const bool waitFlag)
2321{
2322        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2323        struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2324        struct cifs_posix_lock *parm_data;
2325        int rc = 0;
2326        int timeout = 0;
2327        int bytes_returned = 0;
2328        int resp_buf_type = 0;
2329        __u16 params, param_offset, offset, byte_count, count;
2330        struct kvec iov[1];
2331
2332        cifs_dbg(FYI, "Posix Lock\n");
2333
2334        rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2335
2336        if (rc)
2337                return rc;
2338
2339        pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2340
2341        params = 6;
2342        pSMB->MaxSetupCount = 0;
2343        pSMB->Reserved = 0;
2344        pSMB->Flags = 0;
2345        pSMB->Reserved2 = 0;
2346        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2347        offset = param_offset + params;
2348
2349        count = sizeof(struct cifs_posix_lock);
2350        pSMB->MaxParameterCount = cpu_to_le16(2);
2351        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2352        pSMB->SetupCount = 1;
2353        pSMB->Reserved3 = 0;
2354        if (pLockData)
2355                pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2356        else
2357                pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2358        byte_count = 3 /* pad */  + params + count;
2359        pSMB->DataCount = cpu_to_le16(count);
2360        pSMB->ParameterCount = cpu_to_le16(params);
2361        pSMB->TotalDataCount = pSMB->DataCount;
2362        pSMB->TotalParameterCount = pSMB->ParameterCount;
2363        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2364        parm_data = (struct cifs_posix_lock *)
2365                        (((char *) &pSMB->hdr.Protocol) + offset);
2366
2367        parm_data->lock_type = cpu_to_le16(lock_type);
2368        if (waitFlag) {
2369                timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2370                parm_data->lock_flags = cpu_to_le16(1);
2371                pSMB->Timeout = cpu_to_le32(-1);
2372        } else
2373                pSMB->Timeout = 0;
2374
2375        parm_data->pid = cpu_to_le32(netpid);
2376        parm_data->start = cpu_to_le64(start_offset);
2377        parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2378
2379        pSMB->DataOffset = cpu_to_le16(offset);
2380        pSMB->Fid = smb_file_id;
2381        pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2382        pSMB->Reserved4 = 0;
2383        inc_rfc1001_len(pSMB, byte_count);
2384        pSMB->ByteCount = cpu_to_le16(byte_count);
2385        if (waitFlag) {
2386                rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2387                        (struct smb_hdr *) pSMBr, &bytes_returned);
2388        } else {
2389                iov[0].iov_base = (char *)pSMB;
2390                iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2391                rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2392                                &resp_buf_type, timeout);
2393                pSMB = NULL; /* request buf already freed by SendReceive2. Do
2394                                not try to free it twice below on exit */
2395                pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2396        }
2397
2398        if (rc) {
2399                cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2400        } else if (pLockData) {
2401                /* lock structure can be returned on get */
2402                __u16 data_offset;
2403                __u16 data_count;
2404                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2405
2406                if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2407                        rc = -EIO;      /* bad smb */
2408                        goto plk_err_exit;
2409                }
2410                data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2411                data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2412                if (data_count < sizeof(struct cifs_posix_lock)) {
2413                        rc = -EIO;
2414                        goto plk_err_exit;
2415                }
2416                parm_data = (struct cifs_posix_lock *)
2417                        ((char *)&pSMBr->hdr.Protocol + data_offset);
2418                if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2419                        pLockData->fl_type = F_UNLCK;
2420                else {
2421                        if (parm_data->lock_type ==
2422                                        __constant_cpu_to_le16(CIFS_RDLCK))
2423                                pLockData->fl_type = F_RDLCK;
2424                        else if (parm_data->lock_type ==
2425                                        __constant_cpu_to_le16(CIFS_WRLCK))
2426                                pLockData->fl_type = F_WRLCK;
2427
2428                        pLockData->fl_start = le64_to_cpu(parm_data->start);
2429                        pLockData->fl_end = pLockData->fl_start +
2430                                        le64_to_cpu(parm_data->length) - 1;
2431                        pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2432                }
2433        }
2434
2435plk_err_exit:
2436        if (pSMB)
2437                cifs_small_buf_release(pSMB);
2438
2439        if (resp_buf_type == CIFS_SMALL_BUFFER)
2440                cifs_small_buf_release(iov[0].iov_base);
2441        else if (resp_buf_type == CIFS_LARGE_BUFFER)
2442                cifs_buf_release(iov[0].iov_base);
2443
2444        /* Note: On -EAGAIN error only caller can retry on handle based calls
2445           since file handle passed in no longer valid */
2446
2447        return rc;
2448}
2449
2450
2451int
2452CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2453{
2454        int rc = 0;
2455        CLOSE_REQ *pSMB = NULL;
2456        cifs_dbg(FYI, "In CIFSSMBClose\n");
2457
2458/* do not retry on dead session on close */
2459        rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2460        if (rc == -EAGAIN)
2461                return 0;
2462        if (rc)
2463                return rc;
2464
2465        pSMB->FileID = (__u16) smb_file_id;
2466        pSMB->LastWriteTime = 0xFFFFFFFF;
2467        pSMB->ByteCount = 0;
2468        rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2469        cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2470        if (rc) {
2471                if (rc != -EINTR) {
2472                        /* EINTR is expected when user ctl-c to kill app */
2473                        cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2474                }
2475        }
2476
2477        /* Since session is dead, file will be closed on server already */
2478        if (rc == -EAGAIN)
2479                rc = 0;
2480
2481        return rc;
2482}
2483
2484int
2485CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2486{
2487        int rc = 0;
2488        FLUSH_REQ *pSMB = NULL;
2489        cifs_dbg(FYI, "In CIFSSMBFlush\n");
2490
2491        rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2492        if (rc)
2493                return rc;
2494
2495        pSMB->FileID = (__u16) smb_file_id;
2496        pSMB->ByteCount = 0;
2497        rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2498        cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2499        if (rc)
2500                cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2501
2502        return rc;
2503}
2504
2505int
2506CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2507              const char *from_name, const char *to_name,
2508              struct cifs_sb_info *cifs_sb)
2509{
2510        int rc = 0;
2511        RENAME_REQ *pSMB = NULL;
2512        RENAME_RSP *pSMBr = NULL;
2513        int bytes_returned;
2514        int name_len, name_len2;
2515        __u16 count;
2516        int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2517
2518        cifs_dbg(FYI, "In CIFSSMBRename\n");
2519renameRetry:
2520        rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2521                      (void **) &pSMBr);
2522        if (rc)
2523                return rc;
2524
2525        pSMB->BufferFormat = 0x04;
2526        pSMB->SearchAttributes =
2527            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2528                        ATTR_DIRECTORY);
2529
2530        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2531                name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2532                                              from_name, PATH_MAX,
2533                                              cifs_sb->local_nls, remap);
2534                name_len++;     /* trailing null */
2535                name_len *= 2;
2536                pSMB->OldFileName[name_len] = 0x04;     /* pad */
2537        /* protocol requires ASCII signature byte on Unicode string */
2538                pSMB->OldFileName[name_len + 1] = 0x00;
2539                name_len2 =
2540                    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2541                                       to_name, PATH_MAX, cifs_sb->local_nls,
2542                                       remap);
2543                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2544                name_len2 *= 2; /* convert to bytes */
2545        } else {        /* BB improve the check for buffer overruns BB */
2546                name_len = strnlen(from_name, PATH_MAX);
2547                name_len++;     /* trailing null */
2548                strncpy(pSMB->OldFileName, from_name, name_len);
2549                name_len2 = strnlen(to_name, PATH_MAX);
2550                name_len2++;    /* trailing null */
2551                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2552                strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2553                name_len2++;    /* trailing null */
2554                name_len2++;    /* signature byte */
2555        }
2556
2557        count = 1 /* 1st signature byte */  + name_len + name_len2;
2558        inc_rfc1001_len(pSMB, count);
2559        pSMB->ByteCount = cpu_to_le16(count);
2560
2561        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2562                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2563        cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2564        if (rc)
2565                cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2566
2567        cifs_buf_release(pSMB);
2568
2569        if (rc == -EAGAIN)
2570                goto renameRetry;
2571
2572        return rc;
2573}
2574
2575int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2576                int netfid, const char *target_name,
2577                const struct nls_table *nls_codepage, int remap)
2578{
2579        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2580        struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2581        struct set_file_rename *rename_info;
2582        char *data_offset;
2583        char dummy_string[30];
2584        int rc = 0;
2585        int bytes_returned = 0;
2586        int len_of_str;
2587        __u16 params, param_offset, offset, count, byte_count;
2588
2589        cifs_dbg(FYI, "Rename to File by handle\n");
2590        rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2591                        (void **) &pSMBr);
2592        if (rc)
2593                return rc;
2594
2595        params = 6;
2596        pSMB->MaxSetupCount = 0;
2597        pSMB->Reserved = 0;
2598        pSMB->Flags = 0;
2599        pSMB->Timeout = 0;
2600        pSMB->Reserved2 = 0;
2601        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2602        offset = param_offset + params;
2603
2604        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2605        rename_info = (struct set_file_rename *) data_offset;
2606        pSMB->MaxParameterCount = cpu_to_le16(2);
2607        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2608        pSMB->SetupCount = 1;
2609        pSMB->Reserved3 = 0;
2610        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2611        byte_count = 3 /* pad */  + params;
2612        pSMB->ParameterCount = cpu_to_le16(params);
2613        pSMB->TotalParameterCount = pSMB->ParameterCount;
2614        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2615        pSMB->DataOffset = cpu_to_le16(offset);
2616        /* construct random name ".cifs_tmp<inodenum><mid>" */
2617        rename_info->overwrite = cpu_to_le32(1);
2618        rename_info->root_fid  = 0;
2619        /* unicode only call */
2620        if (target_name == NULL) {
2621                sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2622                len_of_str =
2623                        cifsConvertToUTF16((__le16 *)rename_info->target_name,
2624                                        dummy_string, 24, nls_codepage, remap);
2625        } else {
2626                len_of_str =
2627                        cifsConvertToUTF16((__le16 *)rename_info->target_name,
2628                                        target_name, PATH_MAX, nls_codepage,
2629                                        remap);
2630        }
2631        rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2632        count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2633        byte_count += count;
2634        pSMB->DataCount = cpu_to_le16(count);
2635        pSMB->TotalDataCount = pSMB->DataCount;
2636        pSMB->Fid = netfid;
2637        pSMB->InformationLevel =
2638                cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2639        pSMB->Reserved4 = 0;
2640        inc_rfc1001_len(pSMB, byte_count);
2641        pSMB->ByteCount = cpu_to_le16(byte_count);
2642        rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2643                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2644        cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2645        if (rc)
2646                cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2647                         rc);
2648
2649        cifs_buf_release(pSMB);
2650
2651        /* Note: On -EAGAIN error only caller can retry on handle based calls
2652                since file handle passed in no longer valid */
2653
2654        return rc;
2655}
2656
2657int
2658CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2659            const char *fromName, const __u16 target_tid, const char *toName,
2660            const int flags, const struct nls_table *nls_codepage, int remap)
2661{
2662        int rc = 0;
2663        COPY_REQ *pSMB = NULL;
2664        COPY_RSP *pSMBr = NULL;
2665        int bytes_returned;
2666        int name_len, name_len2;
2667        __u16 count;
2668
2669        cifs_dbg(FYI, "In CIFSSMBCopy\n");
2670copyRetry:
2671        rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2672                        (void **) &pSMBr);
2673        if (rc)
2674                return rc;
2675
2676        pSMB->BufferFormat = 0x04;
2677        pSMB->Tid2 = target_tid;
2678
2679        pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2680
2681        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2682                name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2683                                              fromName, PATH_MAX, nls_codepage,
2684                                              remap);
2685                name_len++;     /* trailing null */
2686                name_len *= 2;
2687                pSMB->OldFileName[name_len] = 0x04;     /* pad */
2688                /* protocol requires ASCII signature byte on Unicode string */
2689                pSMB->OldFileName[name_len + 1] = 0x00;
2690                name_len2 =
2691                    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2692                                       toName, PATH_MAX, nls_codepage, remap);
2693                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2694                name_len2 *= 2; /* convert to bytes */
2695        } else {        /* BB improve the check for buffer overruns BB */
2696                name_len = strnlen(fromName, PATH_MAX);
2697                name_len++;     /* trailing null */
2698                strncpy(pSMB->OldFileName, fromName, name_len);
2699                name_len2 = strnlen(toName, PATH_MAX);
2700                name_len2++;    /* trailing null */
2701                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2702                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2703                name_len2++;    /* trailing null */
2704                name_len2++;    /* signature byte */
2705        }
2706
2707        count = 1 /* 1st signature byte */  + name_len + name_len2;
2708        inc_rfc1001_len(pSMB, count);
2709        pSMB->ByteCount = cpu_to_le16(count);
2710
2711        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2712                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2713        if (rc) {
2714                cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2715                         rc, le16_to_cpu(pSMBr->CopyCount));
2716        }
2717        cifs_buf_release(pSMB);
2718
2719        if (rc == -EAGAIN)
2720                goto copyRetry;
2721
2722        return rc;
2723}
2724
2725int
2726CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2727                      const char *fromName, const char *toName,
2728                      const struct nls_table *nls_codepage)
2729{
2730        TRANSACTION2_SPI_REQ *pSMB = NULL;
2731        TRANSACTION2_SPI_RSP *pSMBr = NULL;
2732        char *data_offset;
2733        int name_len;
2734        int name_len_target;
2735        int rc = 0;
2736        int bytes_returned = 0;
2737        __u16 params, param_offset, offset, byte_count;
2738
2739        cifs_dbg(FYI, "In Symlink Unix style\n");
2740createSymLinkRetry:
2741        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2742                      (void **) &pSMBr);
2743        if (rc)
2744                return rc;
2745
2746        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2747                name_len =
2748                    cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2749                                    /* find define for this maxpathcomponent */
2750                                    PATH_MAX, nls_codepage);
2751                name_len++;     /* trailing null */
2752                name_len *= 2;
2753
2754        } else {        /* BB improve the check for buffer overruns BB */
2755                name_len = strnlen(fromName, PATH_MAX);
2756                name_len++;     /* trailing null */
2757                strncpy(pSMB->FileName, fromName, name_len);
2758        }
2759        params = 6 + name_len;
2760        pSMB->MaxSetupCount = 0;
2761        pSMB->Reserved = 0;
2762        pSMB->Flags = 0;
2763        pSMB->Timeout = 0;
2764        pSMB->Reserved2 = 0;
2765        param_offset = offsetof(struct smb_com_transaction2_spi_req,
2766                                InformationLevel) - 4;
2767        offset = param_offset + params;
2768
2769        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2770        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2771                name_len_target =
2772                    cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2773                                    /* find define for this maxpathcomponent */
2774                                    , nls_codepage);
2775                name_len_target++;      /* trailing null */
2776                name_len_target *= 2;
2777        } else {        /* BB improve the check for buffer overruns BB */
2778                name_len_target = strnlen(toName, PATH_MAX);
2779                name_len_target++;      /* trailing null */
2780                strncpy(data_offset, toName, name_len_target);
2781        }
2782
2783        pSMB->MaxParameterCount = cpu_to_le16(2);
2784        /* BB find exact max on data count below from sess */
2785        pSMB->MaxDataCount = cpu_to_le16(1000);
2786        pSMB->SetupCount = 1;
2787        pSMB->Reserved3 = 0;
2788        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2789        byte_count = 3 /* pad */  + params + name_len_target;
2790        pSMB->DataCount = cpu_to_le16(name_len_target);
2791        pSMB->ParameterCount = cpu_to_le16(params);
2792        pSMB->TotalDataCount = pSMB->DataCount;
2793        pSMB->TotalParameterCount = pSMB->ParameterCount;
2794        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2795        pSMB->DataOffset = cpu_to_le16(offset);
2796        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2797        pSMB->Reserved4 = 0;
2798        inc_rfc1001_len(pSMB, byte_count);
2799        pSMB->ByteCount = cpu_to_le16(byte_count);
2800        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2801                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2802        cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2803        if (rc)
2804                cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2805                         rc);
2806
2807        cifs_buf_release(pSMB);
2808
2809        if (rc == -EAGAIN)
2810                goto createSymLinkRetry;
2811
2812        return rc;
2813}
2814
2815int
2816CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2817                       const char *fromName, const char *toName,
2818                       const struct nls_table *nls_codepage, int remap)
2819{
2820        TRANSACTION2_SPI_REQ *pSMB = NULL;
2821        TRANSACTION2_SPI_RSP *pSMBr = NULL;
2822        char *data_offset;
2823        int name_len;
2824        int name_len_target;
2825        int rc = 0;
2826        int bytes_returned = 0;
2827        __u16 params, param_offset, offset, byte_count;
2828
2829        cifs_dbg(FYI, "In Create Hard link Unix style\n");
2830createHardLinkRetry:
2831        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2832                      (void **) &pSMBr);
2833        if (rc)
2834                return rc;
2835
2836        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2837                name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2838                                              PATH_MAX, nls_codepage, remap);
2839                name_len++;     /* trailing null */
2840                name_len *= 2;
2841
2842        } else {        /* BB improve the check for buffer overruns BB */
2843                name_len = strnlen(toName, PATH_MAX);
2844                name_len++;     /* trailing null */
2845                strncpy(pSMB->FileName, toName, name_len);
2846        }
2847        params = 6 + name_len;
2848        pSMB->MaxSetupCount = 0;
2849        pSMB->Reserved = 0;
2850        pSMB->Flags = 0;
2851        pSMB->Timeout = 0;
2852        pSMB->Reserved2 = 0;
2853        param_offset = offsetof(struct smb_com_transaction2_spi_req,
2854                                InformationLevel) - 4;
2855        offset = param_offset + params;
2856
2857        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2858        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2859                name_len_target =
2860                    cifsConvertToUTF16((__le16 *) data_offset, fromName,
2861                                       PATH_MAX, nls_codepage, remap);
2862                name_len_target++;      /* trailing null */
2863                name_len_target *= 2;
2864        } else {        /* BB improve the check for buffer overruns BB */
2865                name_len_target = strnlen(fromName, PATH_MAX);
2866                name_len_target++;      /* trailing null */
2867                strncpy(data_offset, fromName, name_len_target);
2868        }
2869
2870        pSMB->MaxParameterCount = cpu_to_le16(2);
2871        /* BB find exact max on data count below from sess*/
2872        pSMB->MaxDataCount = cpu_to_le16(1000);
2873        pSMB->SetupCount = 1;
2874        pSMB->Reserved3 = 0;
2875        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2876        byte_count = 3 /* pad */  + params + name_len_target;
2877        pSMB->ParameterCount = cpu_to_le16(params);
2878        pSMB->TotalParameterCount = pSMB->ParameterCount;
2879        pSMB->DataCount = cpu_to_le16(name_len_target);
2880        pSMB->TotalDataCount = pSMB->DataCount;
2881        pSMB->ParameterOffset = cpu_to_le16(param_offset);
2882        pSMB->DataOffset = cpu_to_le16(offset);
2883        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2884        pSMB->Reserved4 = 0;
2885        inc_rfc1001_len(pSMB, byte_count);
2886        pSMB->ByteCount = cpu_to_le16(byte_count);
2887        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2888                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2889        cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2890        if (rc)
2891                cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2892                         rc);
2893
2894        cifs_buf_release(pSMB);
2895        if (rc == -EAGAIN)
2896                goto createHardLinkRetry;
2897
2898        return rc;
2899}
2900
2901int
2902CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2903                   const char *from_name, const char *to_name,
2904                   struct cifs_sb_info *cifs_sb)
2905{
2906        int rc = 0;
2907        NT_RENAME_REQ *pSMB = NULL;
2908        RENAME_RSP *pSMBr = NULL;
2909        int bytes_returned;
2910        int name_len, name_len2;
2911        __u16 count;
2912        int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2913
2914        cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2915winCreateHardLinkRetry:
2916
2917        rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2918                      (void **) &pSMBr);
2919        if (rc)
2920                return rc;
2921
2922        pSMB->SearchAttributes =
2923            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2924                        ATTR_DIRECTORY);
2925        pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2926        pSMB->ClusterCount = 0;
2927
2928        pSMB->BufferFormat = 0x04;
2929
2930        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2931                name_len =
2932                    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2933                                       PATH_MAX, cifs_sb->local_nls, remap);
2934                name_len++;     /* trailing null */
2935                name_len *= 2;
2936
2937                /* protocol specifies ASCII buffer format (0x04) for unicode */
2938                pSMB->OldFileName[name_len] = 0x04;
2939                pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2940                name_len2 =
2941                    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2942                                       to_name, PATH_MAX, cifs_sb->local_nls,
2943                                       remap);
2944                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2945                name_len2 *= 2; /* convert to bytes */
2946        } else {        /* BB improve the check for buffer overruns BB */
2947                name_len = strnlen(from_name, PATH_MAX);
2948                name_len++;     /* trailing null */
2949                strncpy(pSMB->OldFileName, from_name, name_len);
2950                name_len2 = strnlen(to_name, PATH_MAX);
2951                name_len2++;    /* trailing null */
2952                pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2953                strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2954                name_len2++;    /* trailing null */
2955                name_len2++;    /* signature byte */
2956        }
2957
2958        count = 1 /* string type byte */  + name_len + name_len2;
2959        inc_rfc1001_len(pSMB, count);
2960        pSMB->ByteCount = cpu_to_le16(count);
2961
2962        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2963                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2964        cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2965        if (rc)
2966                cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
2967
2968        cifs_buf_release(pSMB);
2969        if (rc == -EAGAIN)
2970                goto winCreateHardLinkRetry;
2971
2972        return rc;
2973}
2974
2975int
2976CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2977                        const unsigned char *searchName, char **symlinkinfo,
2978                        const struct nls_table *nls_codepage)
2979{
2980/* SMB_QUERY_FILE_UNIX_LINK */
2981        TRANSACTION2_QPI_REQ *pSMB = NULL;
2982        TRANSACTION2_QPI_RSP *pSMBr = NULL;
2983        int rc = 0;
2984        int bytes_returned;
2985        int name_len;
2986        __u16 params, byte_count;
2987        char *data_start;
2988
2989        cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
2990
2991querySymLinkRetry:
2992        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2993                      (void **) &pSMBr);
2994        if (rc)
2995                return rc;
2996
2997        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2998                name_len =
2999                        cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3000                                        PATH_MAX, nls_codepage);
3001                name_len++;     /* trailing null */
3002                name_len *= 2;
3003        } else {        /* BB improve the check for buffer overruns BB */
3004                name_len = strnlen(searchName, PATH_MAX);
3005                name_len++;     /* trailing null */
3006                strncpy(pSMB->FileName, searchName, name_len);
3007        }
3008
3009        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3010        pSMB->TotalDataCount = 0;
3011        pSMB->MaxParameterCount = cpu_to_le16(2);
3012        pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3013        pSMB->MaxSetupCount = 0;
3014        pSMB->Reserved = 0;
3015        pSMB->Flags = 0;
3016        pSMB->Timeout = 0;
3017        pSMB->Reserved2 = 0;
3018        pSMB->ParameterOffset = cpu_to_le16(offsetof(
3019        struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3020        pSMB->DataCount = 0;
3021        pSMB->DataOffset = 0;
3022        pSMB->SetupCount = 1;
3023        pSMB->Reserved3 = 0;
3024        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3025        byte_count = params + 1 /* pad */ ;
3026        pSMB->TotalParameterCount = cpu_to_le16(params);
3027        pSMB->ParameterCount = pSMB->TotalParameterCount;
3028        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3029        pSMB->Reserved4 = 0;
3030        inc_rfc1001_len(pSMB, byte_count);
3031        pSMB->ByteCount = cpu_to_le16(byte_count);
3032
3033        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3034                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3035        if (rc) {
3036                cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3037        } else {
3038                /* decode response */
3039
3040                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3041                /* BB also check enough total bytes returned */
3042                if (rc || get_bcc(&pSMBr->hdr) < 2)
3043                        rc = -EIO;
3044                else {
3045                        bool is_unicode;
3046                        u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3047
3048                        data_start = ((char *) &pSMBr->hdr.Protocol) +
3049                                           le16_to_cpu(pSMBr->t2.DataOffset);
3050
3051                        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3052                                is_unicode = true;
3053                        else
3054                                is_unicode = false;
3055
3056                        /* BB FIXME investigate remapping reserved chars here */
3057                        *symlinkinfo = cifs_strndup_from_utf16(data_start,
3058                                        count, is_unicode, nls_codepage);
3059                        if (!*symlinkinfo)
3060                                rc = -ENOMEM;
3061                }
3062        }
3063        cifs_buf_release(pSMB);
3064        if (rc == -EAGAIN)
3065                goto querySymLinkRetry;
3066        return rc;
3067}
3068
3069/*
3070 *      Recent Windows versions now create symlinks more frequently
3071 *      and they use the "reparse point" mechanism below.  We can of course
3072 *      do symlinks nicely to Samba and other servers which support the
3073 *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3074 *      "MF" symlinks optionally, but for recent Windows we really need to
3075 *      reenable the code below and fix the cifs_symlink callers to handle this.
3076 *      In the interim this code has been moved to its own config option so
3077 *      it is not compiled in by default until callers fixed up and more tested.
3078 */
3079int
3080CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3081                    __u16 fid, char **symlinkinfo,
3082                    const struct nls_table *nls_codepage)
3083{
3084        int rc = 0;
3085        int bytes_returned;
3086        struct smb_com_transaction_ioctl_req *pSMB;
3087        struct smb_com_transaction_ioctl_rsp *pSMBr;
3088        bool is_unicode;
3089        unsigned int sub_len;
3090        char *sub_start;
3091        struct reparse_symlink_data *reparse_buf;
3092        struct reparse_posix_data *posix_buf;
3093        __u32 data_offset, data_count;
3094        char *end_of_smb;
3095
3096        cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3097        rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3098                      (void **) &pSMBr);
3099        if (rc)
3100                return rc;
3101
3102        pSMB->TotalParameterCount = 0 ;
3103        pSMB->TotalDataCount = 0;
3104        pSMB->MaxParameterCount = cpu_to_le32(2);
3105        /* BB find exact data count max from sess structure BB */
3106        pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3107        pSMB->MaxSetupCount = 4;
3108        pSMB->Reserved = 0;
3109        pSMB->ParameterOffset = 0;
3110        pSMB->DataCount = 0;
3111        pSMB->DataOffset = 0;
3112        pSMB->SetupCount = 4;
3113        pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3114        pSMB->ParameterCount = pSMB->TotalParameterCount;
3115        pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3116        pSMB->IsFsctl = 1; /* FSCTL */
3117        pSMB->IsRootFlag = 0;
3118        pSMB->Fid = fid; /* file handle always le */
3119        pSMB->ByteCount = 0;
3120
3121        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3122                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3123        if (rc) {
3124                cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3125                goto qreparse_out;
3126        }
3127
3128        data_offset = le32_to_cpu(pSMBr->DataOffset);
3129        data_count = le32_to_cpu(pSMBr->DataCount);
3130        if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3131                /* BB also check enough total bytes returned */
3132                rc = -EIO;      /* bad smb */
3133                goto qreparse_out;
3134        }
3135        if (!data_count || (data_count > 2048)) {
3136                rc = -EIO;
3137                cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3138                goto qreparse_out;
3139        }
3140        end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3141        reparse_buf = (struct reparse_symlink_data *)
3142                                ((char *)&pSMBr->hdr.Protocol + data_offset);
3143        if ((char *)reparse_buf >= end_of_smb) {
3144                rc = -EIO;
3145                goto qreparse_out;
3146        }
3147        if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3148                cifs_dbg(FYI, "NFS style reparse tag\n");
3149                posix_buf =  (struct reparse_posix_data *)reparse_buf;
3150
3151                if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3152                        cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3153                                 le64_to_cpu(posix_buf->InodeType));
3154                        rc = -EOPNOTSUPP;
3155                        goto qreparse_out;
3156                }
3157                is_unicode = true;
3158                sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3159                if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3160                        cifs_dbg(FYI, "reparse buf beyond SMB\n");
3161                        rc = -EIO;
3162                        goto qreparse_out;
3163                }
3164                *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3165                                sub_len, is_unicode, nls_codepage);
3166                goto qreparse_out;
3167        } else if (reparse_buf->ReparseTag !=
3168                        cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3169                rc = -EOPNOTSUPP;
3170                goto qreparse_out;
3171        }
3172
3173        /* Reparse tag is NTFS symlink */
3174        sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3175                                reparse_buf->PathBuffer;
3176        sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3177        if (sub_start + sub_len > end_of_smb) {
3178                cifs_dbg(FYI, "reparse buf beyond SMB\n");
3179                rc = -EIO;
3180                goto qreparse_out;
3181        }
3182        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3183                is_unicode = true;
3184        else
3185                is_unicode = false;
3186
3187        /* BB FIXME investigate remapping reserved chars here */
3188        *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3189                                               nls_codepage);
3190        if (!*symlinkinfo)
3191                rc = -ENOMEM;
3192qreparse_out:
3193        cifs_buf_release(pSMB);
3194
3195        /*
3196         * Note: On -EAGAIN error only caller can retry on handle based calls
3197         * since file handle passed in no longer valid.
3198         */
3199        return rc;
3200}
3201
3202int
3203CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3204                    __u16 fid)
3205{
3206        int rc = 0;
3207        int bytes_returned;
3208        struct smb_com_transaction_compr_ioctl_req *pSMB;
3209        struct smb_com_transaction_ioctl_rsp *pSMBr;
3210
3211        cifs_dbg(FYI, "Set compression for %u\n", fid);
3212        rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3213                      (void **) &pSMBr);
3214        if (rc)
3215                return rc;
3216
3217        pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3218
3219        pSMB->TotalParameterCount = 0;
3220        pSMB->TotalDataCount = __constant_cpu_to_le32(2);
3221        pSMB->MaxParameterCount = 0;
3222        pSMB->MaxDataCount = 0;
3223        pSMB->MaxSetupCount = 4;
3224        pSMB->Reserved = 0;
3225        pSMB->ParameterOffset = 0;
3226        pSMB->DataCount = __constant_cpu_to_le32(2);
3227        pSMB->DataOffset =
3228                cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3229                                compression_state) - 4);  /* 84 */
3230        pSMB->SetupCount = 4;
3231        pSMB->SubCommand = __constant_cpu_to_le16(NT_TRANSACT_IOCTL);
3232        pSMB->ParameterCount = 0;
3233        pSMB->FunctionCode = __constant_cpu_to_le32(FSCTL_SET_COMPRESSION);
3234        pSMB->IsFsctl = 1; /* FSCTL */
3235        pSMB->IsRootFlag = 0;
3236        pSMB->Fid = fid; /* file handle always le */
3237        /* 3 byte pad, followed by 2 byte compress state */
3238        pSMB->ByteCount = __constant_cpu_to_le16(5);
3239        inc_rfc1001_len(pSMB, 5);
3240
3241        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3242                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3243        if (rc)
3244                cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3245
3246        cifs_buf_release(pSMB);
3247
3248        /*
3249         * Note: On -EAGAIN error only caller can retry on handle based calls
3250         * since file handle passed in no longer valid.
3251         */
3252        return rc;
3253}
3254
3255
3256#ifdef CONFIG_CIFS_POSIX
3257
3258/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3259static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3260                             struct cifs_posix_ace *cifs_ace)
3261{
3262        /* u8 cifs fields do not need le conversion */
3263        ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3264        ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3265        ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3266/*
3267        cifs_dbg(FYI, "perm %d tag %d id %d\n",
3268                 ace->e_perm, ace->e_tag, ace->e_id);
3269*/
3270
3271        return;
3272}
3273
3274/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3275static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3276                               const int acl_type, const int size_of_data_area)
3277{
3278        int size =  0;
3279        int i;
3280        __u16 count;
3281        struct cifs_posix_ace *pACE;
3282        struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3283        posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3284
3285        if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3286                return -EOPNOTSUPP;
3287
3288        if (acl_type & ACL_TYPE_ACCESS) {
3289                count = le16_to_cpu(cifs_acl->access_entry_count);
3290                pACE = &cifs_acl->ace_array[0];
3291                size = sizeof(struct cifs_posix_acl);
3292                size += sizeof(struct cifs_posix_ace) * count;
3293                /* check if we would go beyond end of SMB */
3294                if (size_of_data_area < size) {
3295                        cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3296                                 size_of_data_area, size);
3297                        return -EINVAL;
3298                }
3299        } else if (acl_type & ACL_TYPE_DEFAULT) {
3300                count = le16_to_cpu(cifs_acl->access_entry_count);
3301                size = sizeof(struct cifs_posix_acl);
3302                size += sizeof(struct cifs_posix_ace) * count;
3303/* skip past access ACEs to get to default ACEs */
3304                pACE = &cifs_acl->ace_array[count];
3305                count = le16_to_cpu(cifs_acl->default_entry_count);
3306                size += sizeof(struct cifs_posix_ace) * count;
3307                /* check if we would go beyond end of SMB */
3308                if (size_of_data_area < size)
3309                        return -EINVAL;
3310        } else {
3311                /* illegal type */
3312                return -EINVAL;
3313        }
3314
3315        size = posix_acl_xattr_size(count);
3316        if ((buflen == 0) || (local_acl == NULL)) {
3317                /* used to query ACL EA size */
3318        } else if (size > buflen) {
3319                return -ERANGE;
3320        } else /* buffer big enough */ {
3321                local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3322                for (i = 0; i < count ; i++) {
3323                        cifs_convert_ace(&local_acl->a_entries[i], pACE);
3324                        pACE++;
3325                }
3326        }
3327        return size;
3328}
3329
3330static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3331                                     const posix_acl_xattr_entry *local_ace)
3332{
3333        __u16 rc = 0; /* 0 = ACL converted ok */
3334
3335        cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3336        cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3337        /* BB is there a better way to handle the large uid? */
3338        if (local_ace->e_id == cpu_to_le32(-1)) {
3339        /* Probably no need to le convert -1 on any arch but can not hurt */
3340                cifs_ace->cifs_uid = cpu_to_le64(-1);
3341        } else
3342                cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3343/*
3344        cifs_dbg(FYI, "perm %d tag %d id %d\n",
3345                 ace->e_perm, ace->e_tag, ace->e_id);
3346*/
3347        return rc;
3348}
3349
3350/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3351static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3352                               const int buflen, const int acl_type)
3353{
3354        __u16 rc = 0;
3355        struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3356        posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3357        int count;
3358        int i;
3359
3360        if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3361                return 0;
3362
3363        count = posix_acl_xattr_count((size_t)buflen);
3364        cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3365                 count, buflen, le32_to_cpu(local_acl->a_version));
3366        if (le32_to_cpu(local_acl->a_version) != 2) {
3367                cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3368                         le32_to_cpu(local_acl->a_version));
3369                return 0;
3370        }
3371        cifs_acl->version = cpu_to_le16(1);
3372        if (acl_type == ACL_TYPE_ACCESS) {
3373                cifs_acl->access_entry_count = cpu_to_le16(count);
3374                cifs_acl->default_entry_count = __constant_cpu_to_le16(0xFFFF);
3375        } else if (acl_type == ACL_TYPE_DEFAULT) {
3376                cifs_acl->default_entry_count = cpu_to_le16(count);
3377                cifs_acl->access_entry_count = __constant_cpu_to_le16(0xFFFF);
3378        } else {
3379                cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3380                return 0;
3381        }
3382        for (i = 0; i < count; i++) {
3383                rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3384                                        &local_acl->a_entries[i]);
3385                if (rc != 0) {
3386                        /* ACE not converted */
3387                        break;
3388                }
3389        }
3390        if (rc == 0) {
3391                rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3392                rc += sizeof(struct cifs_posix_acl);
3393                /* BB add check to make sure ACL does not overflow SMB */
3394        }
3395        return rc;
3396}
3397
3398int
3399CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3400                   const unsigned char *searchName,
3401                   char *acl_inf, const int buflen, const int acl_type,
3402                   const struct nls_table *nls_codepage, int remap)
3403{
3404/* SMB_QUERY_POSIX_ACL */
3405        TRANSACTION2_QPI_REQ *pSMB = NULL;
3406        TRANSACTION2_QPI_RSP *pSMBr = NULL;
3407        int rc = 0;
3408        int bytes_returned;
3409        int name_len;
3410        __u16 params, byte_count;
3411
3412        cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3413
3414queryAclRetry:
3415        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3416                (void **) &pSMBr);
3417        if (rc)
3418                return rc;
3419
3420        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3421                name_len =
3422                        cifsConvertToUTF16((__le16 *) pSMB->FileName,
3423                                           searchName, PATH_MAX, nls_codepage,
3424                                           remap);
3425                name_len++;     /* trailing null */
3426                name_len *= 2;
3427                pSMB->FileName[name_len] = 0;
3428                pSMB->FileName[name_len+1] = 0;
3429        } else {        /* BB improve the check for buffer overruns BB */
3430                name_len = strnlen(searchName, PATH_MAX);
3431                name_len++;     /* trailing null */
3432                strncpy(pSMB->FileName, searchName, name_len);
3433        }
3434
3435        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3436        pSMB->TotalDataCount = 0;
3437        pSMB->MaxParameterCount = cpu_to_le16(2);
3438        /* BB find exact max data count below from sess structure BB */
3439        pSMB->MaxDataCount = cpu_to_le16(4000);
3440        pSMB->MaxSetupCount = 0;
3441        pSMB->Reserved = 0;
3442        pSMB->Flags = 0;
3443        pSMB->Timeout = 0;
3444        pSMB->Reserved2 = 0;
3445        pSMB->ParameterOffset = cpu_to_le16(
3446                offsetof(struct smb_com_transaction2_qpi_req,
3447                         InformationLevel) - 4);
3448        pSMB->DataCount = 0;
3449        pSMB->DataOffset = 0;
3450        pSMB->SetupCount = 1;
3451        pSMB->Reserved3 = 0;
3452        pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3453        byte_count = params + 1 /* pad */ ;
3454        pSMB->TotalParameterCount = cpu_to_le16(params);
3455        pSMB->ParameterCount = pSMB->TotalParameterCount;
3456        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3457        pSMB->Reserved4 = 0;
3458        inc_rfc1001_len(pSMB, byte_count);
3459        pSMB->ByteCount = cpu_to_le16(byte_count);
3460
3461        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3462                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3463        cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3464        if (rc) {
3465                cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3466        } else {
3467                /* decode response */
3468
3469                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3470                /* BB also check enough total bytes returned */
3471                if (rc || get_bcc(&pSMBr->hdr) < 2)
3472                        rc = -EIO;      /* bad smb */
3473                else {
3474                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3475                        __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3476                        rc = cifs_copy_posix_acl(acl_inf,
3477                                (char *)&pSMBr->hdr.Protocol+data_offset,
3478                                buflen, acl_type, count);
3479                }
3480        }
3481        cifs_buf_release(pSMB);
3482        if (rc == -EAGAIN)
3483                goto queryAclRetry;
3484        return rc;
3485}
3486
3487int
3488CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3489                   const unsigned char *fileName,
3490                   const char *local_acl, const int buflen,
3491                   const int acl_type,
3492                   const struct nls_table *nls_codepage, int remap)
3493{
3494        struct smb_com_transaction2_spi_req *pSMB = NULL;
3495        struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3496        char *parm_data;
3497        int name_len;
3498        int rc = 0;
3499        int bytes_returned = 0;
3500        __u16 params, byte_count, data_count, param_offset, offset;
3501
3502        cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3503setAclRetry:
3504        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3505                      (void **) &pSMBr);
3506        if (rc)
3507                return rc;
3508        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3509                name_len =
3510                        cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3511                                           PATH_MAX, nls_codepage, remap);
3512                name_len++;     /* trailing null */
3513                name_len *= 2;
3514        } else {        /* BB improve the check for buffer overruns BB */
3515                name_len = strnlen(fileName, PATH_MAX);
3516                name_len++;     /* trailing null */
3517                strncpy(pSMB->FileName, fileName, name_len);
3518        }
3519        params = 6 + name_len;
3520        pSMB->MaxParameterCount = cpu_to_le16(2);
3521        /* BB find max SMB size from sess */
3522        pSMB->MaxDataCount = cpu_to_le16(1000);
3523        pSMB->MaxSetupCount = 0;
3524        pSMB->Reserved = 0;
3525        pSMB->Flags = 0;
3526        pSMB->Timeout = 0;
3527        pSMB->Reserved2 = 0;
3528        param_offset = offsetof(struct smb_com_transaction2_spi_req,
3529                                InformationLevel) - 4;
3530        offset = param_offset + params;
3531        parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3532        pSMB->ParameterOffset = cpu_to_le16(param_offset);
3533
3534        /* convert to on the wire format for POSIX ACL */
3535        data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3536
3537        if (data_count == 0) {
3538                rc = -EOPNOTSUPP;
3539                goto setACLerrorExit;
3540        }
3541        pSMB->DataOffset = cpu_to_le16(offset);
3542        pSMB->SetupCount = 1;
3543        pSMB->Reserved3 = 0;
3544        pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3545        pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3546        byte_count = 3 /* pad */  + params + data_count;
3547        pSMB->DataCount = cpu_to_le16(data_count);
3548        pSMB->TotalDataCount = pSMB->DataCount;
3549        pSMB->ParameterCount = cpu_to_le16(params);
3550        pSMB->TotalParameterCount = pSMB->ParameterCount;
3551        pSMB->Reserved4 = 0;
3552        inc_rfc1001_len(pSMB, byte_count);
3553        pSMB->ByteCount = cpu_to_le16(byte_count);
3554        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3555                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3556        if (rc)
3557                cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3558
3559setACLerrorExit:
3560        cifs_buf_release(pSMB);
3561        if (rc == -EAGAIN)
3562                goto setAclRetry;
3563        return rc;
3564}
3565
3566/* BB fix tabs in this function FIXME BB */
3567int
3568CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3569               const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3570{
3571        int rc = 0;
3572        struct smb_t2_qfi_req *pSMB = NULL;
3573        struct smb_t2_qfi_rsp *pSMBr = NULL;
3574        int bytes_returned;
3575        __u16 params, byte_count;
3576
3577        cifs_dbg(FYI, "In GetExtAttr\n");
3578        if (tcon == NULL)
3579                return -ENODEV;
3580
3581GetExtAttrRetry:
3582        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3583                        (void **) &pSMBr);
3584        if (rc)
3585                return rc;
3586
3587        params = 2 /* level */ + 2 /* fid */;
3588        pSMB->t2.TotalDataCount = 0;
3589        pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3590        /* BB find exact max data count below from sess structure BB */
3591        pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3592        pSMB->t2.MaxSetupCount = 0;
3593        pSMB->t2.Reserved = 0;
3594        pSMB->t2.Flags = 0;
3595        pSMB->t2.Timeout = 0;
3596        pSMB->t2.Reserved2 = 0;
3597        pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3598                                               Fid) - 4);
3599        pSMB->t2.DataCount = 0;
3600        pSMB->t2.DataOffset = 0;
3601        pSMB->t2.SetupCount = 1;
3602        pSMB->t2.Reserved3 = 0;
3603        pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3604        byte_count = params + 1 /* pad */ ;
3605        pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3606        pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3607        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3608        pSMB->Pad = 0;
3609        pSMB->Fid = netfid;
3610        inc_rfc1001_len(pSMB, byte_count);
3611        pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3612
3613        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3614                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3615        if (rc) {
3616                cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3617        } else {
3618                /* decode response */
3619                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3620                /* BB also check enough total bytes returned */
3621                if (rc || get_bcc(&pSMBr->hdr) < 2)
3622                        /* If rc should we check for EOPNOSUPP and
3623                           disable the srvino flag? or in caller? */
3624                        rc = -EIO;      /* bad smb */
3625                else {
3626                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3627                        __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3628                        struct file_chattr_info *pfinfo;
3629                        /* BB Do we need a cast or hash here ? */
3630                        if (count != 16) {
3631                                cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3632                                rc = -EIO;
3633                                goto GetExtAttrOut;
3634                        }
3635                        pfinfo = (struct file_chattr_info *)
3636                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
3637                        *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3638                        *pMask = le64_to_cpu(pfinfo->mask);
3639                }
3640        }
3641GetExtAttrOut:
3642        cifs_buf_release(pSMB);
3643        if (rc == -EAGAIN)
3644                goto GetExtAttrRetry;
3645        return rc;
3646}
3647
3648#endif /* CONFIG_POSIX */
3649
3650#ifdef CONFIG_CIFS_ACL
3651/*
3652 * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3653 * all NT TRANSACTS that we init here have total parm and data under about 400
3654 * bytes (to fit in small cifs buffer size), which is the case so far, it
3655 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3656 * returned setup area) and MaxParameterCount (returned parms size) must be set
3657 * by caller
3658 */
3659static int
3660smb_init_nttransact(const __u16 sub_command, const int setup_count,
3661                   const int parm_len, struct cifs_tcon *tcon,
3662                   void **ret_buf)
3663{
3664        int rc;
3665        __u32 temp_offset;
3666        struct smb_com_ntransact_req *pSMB;
3667
3668        rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3669                                (void **)&pSMB);
3670        if (rc)
3671                return rc;
3672        *ret_buf = (void *)pSMB;
3673        pSMB->Reserved = 0;
3674        pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3675        pSMB->TotalDataCount  = 0;
3676        pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3677        pSMB->ParameterCount = pSMB->TotalParameterCount;
3678        pSMB->DataCount  = pSMB->TotalDataCount;
3679        temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3680                        (setup_count * 2) - 4 /* for rfc1001 length itself */;
3681        pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3682        pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3683        pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3684        pSMB->SubCommand = cpu_to_le16(sub_command);
3685        return 0;
3686}
3687
3688static int
3689validate_ntransact(char *buf, char **ppparm, char **ppdata,
3690                   __u32 *pparmlen, __u32 *pdatalen)
3691{
3692        char *end_of_smb;
3693        __u32 data_count, data_offset, parm_count, parm_offset;
3694        struct smb_com_ntransact_rsp *pSMBr;
3695        u16 bcc;
3696
3697        *pdatalen = 0;
3698        *pparmlen = 0;
3699
3700        if (buf == NULL)
3701                return -EINVAL;
3702
3703        pSMBr = (struct smb_com_ntransact_rsp *)buf;
3704
3705        bcc = get_bcc(&pSMBr->hdr);
3706        end_of_smb = 2 /* sizeof byte count */ + bcc +
3707                        (char *)&pSMBr->ByteCount;
3708
3709        data_offset = le32_to_cpu(pSMBr->DataOffset);
3710        data_count = le32_to_cpu(pSMBr->DataCount);
3711        parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3712        parm_count = le32_to_cpu(pSMBr->ParameterCount);
3713
3714        *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3715        *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3716
3717        /* should we also check that parm and data areas do not overlap? */
3718        if (*ppparm > end_of_smb) {
3719                cifs_dbg(FYI, "parms start after end of smb\n");
3720                return -EINVAL;
3721        } else if (parm_count + *ppparm > end_of_smb) {
3722                cifs_dbg(FYI, "parm end after end of smb\n");
3723                return -EINVAL;
3724        } else if (*ppdata > end_of_smb) {
3725                cifs_dbg(FYI, "data starts after end of smb\n");
3726                return -EINVAL;
3727        } else if (data_count + *ppdata > end_of_smb) {
3728                cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3729                         *ppdata, data_count, (data_count + *ppdata),
3730                         end_of_smb, pSMBr);
3731                return -EINVAL;
3732        } else if (parm_count + data_count > bcc) {
3733                cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3734                return -EINVAL;
3735        }
3736        *pdatalen = data_count;
3737        *pparmlen = parm_count;
3738        return 0;
3739}
3740
3741/* Get Security Descriptor (by handle) from remote server for a file or dir */
3742int
3743CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3744                  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3745{
3746        int rc = 0;
3747        int buf_type = 0;
3748        QUERY_SEC_DESC_REQ *pSMB;
3749        struct kvec iov[1];
3750
3751        cifs_dbg(FYI, "GetCifsACL\n");
3752
3753        *pbuflen = 0;
3754        *acl_inf = NULL;
3755
3756        rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3757                        8 /* parm len */, tcon, (void **) &pSMB);
3758        if (rc)
3759                return rc;
3760
3761        pSMB->MaxParameterCount = cpu_to_le32(4);
3762        /* BB TEST with big acls that might need to be e.g. larger than 16K */
3763        pSMB->MaxSetupCount = 0;
3764        pSMB->Fid = fid; /* file handle always le */
3765        pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3766                                     CIFS_ACL_DACL);
3767        pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3768        inc_rfc1001_len(pSMB, 11);
3769        iov[0].iov_base = (char *)pSMB;
3770        iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3771
3772        rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3773                         0);
3774        cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3775        if (rc) {
3776                cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3777        } else {                /* decode response */
3778                __le32 *parm;
3779                __u32 parm_len;
3780                __u32 acl_len;
3781                struct smb_com_ntransact_rsp *pSMBr;
3782                char *pdata;
3783
3784/* validate_nttransact */
3785                rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3786                                        &pdata, &parm_len, pbuflen);
3787                if (rc)
3788                        goto qsec_out;
3789                pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3790
3791                cifs_dbg(FYI, "smb %p parm %p data %p\n",
3792                         pSMBr, parm, *acl_inf);
3793
3794                if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3795                        rc = -EIO;      /* bad smb */
3796                        *pbuflen = 0;
3797                        goto qsec_out;
3798                }
3799
3800/* BB check that data area is minimum length and as big as acl_len */
3801
3802                acl_len = le32_to_cpu(*parm);
3803                if (acl_len != *pbuflen) {
3804                        cifs_dbg(VFS, "acl length %d does not match %d\n",
3805                                 acl_len, *pbuflen);
3806                        if (*pbuflen > acl_len)
3807                                *pbuflen = acl_len;
3808                }
3809
3810                /* check if buffer is big enough for the acl
3811                   header followed by the smallest SID */
3812                if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3813                    (*pbuflen >= 64 * 1024)) {
3814                        cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3815                        rc = -EINVAL;
3816                        *pbuflen = 0;
3817                } else {
3818                        *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3819                        if (*acl_inf == NULL) {
3820                                *pbuflen = 0;
3821                                rc = -ENOMEM;
3822                        }
3823                }
3824        }
3825qsec_out:
3826        if (buf_type == CIFS_SMALL_BUFFER)
3827                cifs_small_buf_release(iov[0].iov_base);
3828        else if (buf_type == CIFS_LARGE_BUFFER)
3829                cifs_buf_release(iov[0].iov_base);
3830/*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3831        return rc;
3832}
3833
3834int
3835CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3836                        struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3837{
3838        __u16 byte_count, param_count, data_count, param_offset, data_offset;
3839        int rc = 0;
3840        int bytes_returned = 0;
3841        SET_SEC_DESC_REQ *pSMB = NULL;
3842        void *pSMBr;
3843
3844setCifsAclRetry:
3845        rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3846        if (rc)
3847                return rc;
3848
3849        pSMB->MaxSetupCount = 0;
3850        pSMB->Reserved = 0;
3851
3852        param_count = 8;
3853        param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3854        data_count = acllen;
3855        data_offset = param_offset + param_count;
3856        byte_count = 3 /* pad */  + param_count;
3857
3858        pSMB->DataCount = cpu_to_le32(data_count);
3859        pSMB->TotalDataCount = pSMB->DataCount;
3860        pSMB->MaxParameterCount = cpu_to_le32(4);
3861        pSMB->MaxDataCount = cpu_to_le32(16384);
3862        pSMB->ParameterCount = cpu_to_le32(param_count);
3863        pSMB->ParameterOffset = cpu_to_le32(param_offset);
3864        pSMB->TotalParameterCount = pSMB->ParameterCount;
3865        pSMB->DataOffset = cpu_to_le32(data_offset);
3866        pSMB->SetupCount = 0;
3867        pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3868        pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3869
3870        pSMB->Fid = fid; /* file handle always le */
3871        pSMB->Reserved2 = 0;
3872        pSMB->AclFlags = cpu_to_le32(aclflag);
3873
3874        if (pntsd && acllen) {
3875                memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3876                                data_offset, pntsd, acllen);
3877                inc_rfc1001_len(pSMB, byte_count + data_count);
3878        } else
3879                inc_rfc1001_len(pSMB, byte_count);
3880
3881        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3882                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3883
3884        cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3885                 bytes_returned, rc);
3886        if (rc)
3887                cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3888        cifs_buf_release(pSMB);
3889
3890        if (rc == -EAGAIN)
3891                goto setCifsAclRetry;
3892
3893        return (rc);
3894}
3895
3896#endif /* CONFIG_CIFS_ACL */
3897
3898/* Legacy Query Path Information call for lookup to old servers such
3899   as Win9x/WinME */
3900int
3901SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3902                    const char *search_name, FILE_ALL_INFO *data,
3903                    const struct nls_table *nls_codepage, int remap)
3904{
3905        QUERY_INFORMATION_REQ *pSMB;
3906        QUERY_INFORMATION_RSP *pSMBr;
3907        int rc = 0;
3908        int bytes_returned;
3909        int name_len;
3910
3911        cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3912QInfRetry:
3913        rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3914                      (void **) &pSMBr);
3915        if (rc)
3916                return rc;
3917
3918        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3919                name_len =
3920                        cifsConvertToUTF16((__le16 *) pSMB->FileName,
3921                                           search_name, PATH_MAX, nls_codepage,
3922                                           remap);
3923                name_len++;     /* trailing null */
3924                name_len *= 2;
3925        } else {
3926                name_len = strnlen(search_name, PATH_MAX);
3927                name_len++;     /* trailing null */
3928                strncpy(pSMB->FileName, search_name, name_len);
3929        }
3930        pSMB->BufferFormat = 0x04;
3931        name_len++; /* account for buffer type byte */
3932        inc_rfc1001_len(pSMB, (__u16)name_len);
3933        pSMB->ByteCount = cpu_to_le16(name_len);
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 QueryInfo = %d\n", rc);
3939        } else if (data) {
3940                struct timespec ts;
3941                __u32 time = le32_to_cpu(pSMBr->last_write_time);
3942
3943                /* decode response */
3944                /* BB FIXME - add time zone adjustment BB */
3945                memset(data, 0, sizeof(FILE_ALL_INFO));
3946                ts.tv_nsec = 0;
3947                ts.tv_sec = time;
3948                /* decode time fields */
3949                data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3950                data->LastWriteTime = data->ChangeTime;
3951                data->LastAccessTime = 0;
3952                data->AllocationSize =
3953                        cpu_to_le64(le32_to_cpu(pSMBr->size));
3954                data->EndOfFile = data->AllocationSize;
3955                data->Attributes =
3956                        cpu_to_le32(le16_to_cpu(pSMBr->attr));
3957        } else
3958                rc = -EIO; /* bad buffer passed in */
3959
3960        cifs_buf_release(pSMB);
3961
3962        if (rc == -EAGAIN)
3963                goto QInfRetry;
3964
3965        return rc;
3966}
3967
3968int
3969CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3970                 u16 netfid, FILE_ALL_INFO *pFindData)
3971{
3972        struct smb_t2_qfi_req *pSMB = NULL;
3973        struct smb_t2_qfi_rsp *pSMBr = NULL;
3974        int rc = 0;
3975        int bytes_returned;
3976        __u16 params, byte_count;
3977
3978QFileInfoRetry:
3979        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3980                      (void **) &pSMBr);
3981        if (rc)
3982                return rc;
3983
3984        params = 2 /* level */ + 2 /* fid */;
3985        pSMB->t2.TotalDataCount = 0;
3986        pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3987        /* BB find exact max data count below from sess structure BB */
3988        pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3989        pSMB->t2.MaxSetupCount = 0;
3990        pSMB->t2.Reserved = 0;
3991        pSMB->t2.Flags = 0;
3992        pSMB->t2.Timeout = 0;
3993        pSMB->t2.Reserved2 = 0;
3994        pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3995                                               Fid) - 4);
3996        pSMB->t2.DataCount = 0;
3997        pSMB->t2.DataOffset = 0;
3998        pSMB->t2.SetupCount = 1;
3999        pSMB->t2.Reserved3 = 0;
4000        pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4001        byte_count = params + 1 /* pad */ ;
4002        pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4003        pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4004        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4005        pSMB->Pad = 0;
4006        pSMB->Fid = netfid;
4007        inc_rfc1001_len(pSMB, byte_count);
4008        pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4009
4010        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4011                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4012        if (rc) {
4013                cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4014        } else {                /* decode response */
4015                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4016
4017                if (rc) /* BB add auto retry on EOPNOTSUPP? */
4018                        rc = -EIO;
4019                else if (get_bcc(&pSMBr->hdr) < 40)
4020                        rc = -EIO;      /* bad smb */
4021                else if (pFindData) {
4022                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4023                        memcpy((char *) pFindData,
4024                               (char *) &pSMBr->hdr.Protocol +
4025                               data_offset, sizeof(FILE_ALL_INFO));
4026                } else
4027                    rc = -ENOMEM;
4028        }
4029        cifs_buf_release(pSMB);
4030        if (rc == -EAGAIN)
4031                goto QFileInfoRetry;
4032
4033        return rc;
4034}
4035
4036int
4037CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4038                 const char *search_name, FILE_ALL_INFO *data,
4039                 int legacy /* old style infolevel */,
4040                 const struct nls_table *nls_codepage, int remap)
4041{
4042        /* level 263 SMB_QUERY_FILE_ALL_INFO */
4043        TRANSACTION2_QPI_REQ *pSMB = NULL;
4044        TRANSACTION2_QPI_RSP *pSMBr = NULL;
4045        int rc = 0;
4046        int bytes_returned;
4047        int name_len;
4048        __u16 params, byte_count;
4049
4050        /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4051QPathInfoRetry:
4052        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4053                      (void **) &pSMBr);
4054        if (rc)
4055                return rc;
4056
4057        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4058                name_len =
4059                    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4060                                       PATH_MAX, nls_codepage, remap);
4061                name_len++;     /* trailing null */
4062                name_len *= 2;
4063        } else {        /* BB improve the check for buffer overruns BB */
4064                name_len = strnlen(search_name, PATH_MAX);
4065                name_len++;     /* trailing null */
4066                strncpy(pSMB->FileName, search_name, name_len);
4067        }
4068
4069        params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4070        pSMB->TotalDataCount = 0;
4071        pSMB->MaxParameterCount = cpu_to_le16(2);
4072        /* BB find exact max SMB PDU from sess structure BB */
4073        pSMB->MaxDataCount = cpu_to_le16(4000);
4074        pSMB->MaxSetupCount = 0;
4075        pSMB->Reserved = 0;
4076        pSMB->Flags = 0;
4077        pSMB->Timeout = 0;
4078        pSMB->Reserved2 = 0;
4079        pSMB->ParameterOffset = cpu_to_le16(offsetof(
4080        struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4081        pSMB->DataCount = 0;
4082        pSMB->DataOffset =