Linux Audio

Check our new training course

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