Linux Audio

Check our new training course

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