Linux Audio

Check our new training course

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