Linux Audio

Check our new training course

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