xref: /kernel/linux/linux-6.6/fs/smb/client/cifssmb.c (revision 62306a36)
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 "cifspdu.h"
28#include "cifsfs.h"
29#include "cifsglob.h"
30#include "cifsacl.h"
31#include "cifsproto.h"
32#include "cifs_unicode.h"
33#include "cifs_debug.h"
34#include "fscache.h"
35#include "smbdirect.h"
36#ifdef CONFIG_CIFS_DFS_UPCALL
37#include "dfs_cache.h"
38#endif
39
40#ifdef CONFIG_CIFS_POSIX
41static struct {
42	int index;
43	char *name;
44} protocols[] = {
45	{CIFS_PROT, "\2NT LM 0.12"},
46	{POSIX_PROT, "\2POSIX 2"},
47	{BAD_PROT, "\2"}
48};
49#else
50static struct {
51	int index;
52	char *name;
53} protocols[] = {
54	{CIFS_PROT, "\2NT LM 0.12"},
55	{BAD_PROT, "\2"}
56};
57#endif
58
59/* define the number of elements in the cifs dialect array */
60#ifdef CONFIG_CIFS_POSIX
61#define CIFS_NUM_PROT 2
62#else /* not posix */
63#define CIFS_NUM_PROT 1
64#endif /* CIFS_POSIX */
65
66
67/* reconnect the socket, tcon, and smb session if needed */
68static int
69cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
70{
71	int rc;
72	struct cifs_ses *ses;
73	struct TCP_Server_Info *server;
74	struct nls_table *nls_codepage = NULL;
75
76	/*
77	 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
78	 * tcp and smb session status done differently for those three - in the
79	 * calling routine
80	 */
81	if (!tcon)
82		return 0;
83
84	ses = tcon->ses;
85	server = ses->server;
86
87	/*
88	 * only tree disconnect, open, and write, (and ulogoff which does not
89	 * have tcon) are allowed as we start umount
90	 */
91	spin_lock(&tcon->tc_lock);
92	if (tcon->status == TID_EXITING) {
93		if (smb_command != SMB_COM_TREE_DISCONNECT) {
94			spin_unlock(&tcon->tc_lock);
95			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
96				 smb_command);
97			return -ENODEV;
98		}
99	}
100	spin_unlock(&tcon->tc_lock);
101
102again:
103	rc = cifs_wait_for_server_reconnect(server, tcon->retry);
104	if (rc)
105		return rc;
106
107	spin_lock(&ses->chan_lock);
108	if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
109		spin_unlock(&ses->chan_lock);
110		return 0;
111	}
112	spin_unlock(&ses->chan_lock);
113
114	mutex_lock(&ses->session_mutex);
115	/*
116	 * Recheck after acquire mutex. If another thread is negotiating
117	 * and the server never sends an answer the socket will be closed
118	 * and tcpStatus set to reconnect.
119	 */
120	spin_lock(&server->srv_lock);
121	if (server->tcpStatus == CifsNeedReconnect) {
122		spin_unlock(&server->srv_lock);
123		mutex_unlock(&ses->session_mutex);
124
125		if (tcon->retry)
126			goto again;
127		rc = -EHOSTDOWN;
128		goto out;
129	}
130	spin_unlock(&server->srv_lock);
131
132	nls_codepage = ses->local_nls;
133
134	/*
135	 * need to prevent multiple threads trying to simultaneously
136	 * reconnect the same SMB session
137	 */
138	spin_lock(&ses->ses_lock);
139	spin_lock(&ses->chan_lock);
140	if (!cifs_chan_needs_reconnect(ses, server) &&
141	    ses->ses_status == SES_GOOD) {
142		spin_unlock(&ses->chan_lock);
143		spin_unlock(&ses->ses_lock);
144
145		/* this means that we only need to tree connect */
146		if (tcon->need_reconnect)
147			goto skip_sess_setup;
148
149		mutex_unlock(&ses->session_mutex);
150		goto out;
151	}
152	spin_unlock(&ses->chan_lock);
153	spin_unlock(&ses->ses_lock);
154
155	rc = cifs_negotiate_protocol(0, ses, server);
156	if (!rc)
157		rc = cifs_setup_session(0, ses, server, nls_codepage);
158
159	/* do we need to reconnect tcon? */
160	if (rc || !tcon->need_reconnect) {
161		mutex_unlock(&ses->session_mutex);
162		goto out;
163	}
164
165skip_sess_setup:
166	cifs_mark_open_files_invalid(tcon);
167	rc = cifs_tree_connect(0, tcon, nls_codepage);
168	mutex_unlock(&ses->session_mutex);
169	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
170
171	if (rc) {
172		pr_warn_once("reconnect tcon failed rc = %d\n", rc);
173		goto out;
174	}
175
176	atomic_inc(&tconInfoReconnectCount);
177
178	/* tell server Unix caps we support */
179	if (cap_unix(ses))
180		reset_cifs_unix_caps(0, tcon, NULL, NULL);
181
182	/*
183	 * Removed call to reopen open files here. It is safer (and faster) to
184	 * reopen files one at a time as needed in read and write.
185	 *
186	 * FIXME: what about file locks? don't we need to reclaim them ASAP?
187	 */
188
189out:
190	/*
191	 * Check if handle based operation so we know whether we can continue
192	 * or not without returning to caller to reset file handle
193	 */
194	switch (smb_command) {
195	case SMB_COM_READ_ANDX:
196	case SMB_COM_WRITE_ANDX:
197	case SMB_COM_CLOSE:
198	case SMB_COM_FIND_CLOSE2:
199	case SMB_COM_LOCKING_ANDX:
200		rc = -EAGAIN;
201	}
202
203	return rc;
204}
205
206/* Allocate and return pointer to an SMB request buffer, and set basic
207   SMB information in the SMB header.  If the return code is zero, this
208   function must have filled in request_buf pointer */
209static int
210small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
211		void **request_buf)
212{
213	int rc;
214
215	rc = cifs_reconnect_tcon(tcon, smb_command);
216	if (rc)
217		return rc;
218
219	*request_buf = cifs_small_buf_get();
220	if (*request_buf == NULL) {
221		/* BB should we add a retry in here if not a writepage? */
222		return -ENOMEM;
223	}
224
225	header_assemble((struct smb_hdr *) *request_buf, smb_command,
226			tcon, wct);
227
228	if (tcon != NULL)
229		cifs_stats_inc(&tcon->num_smbs_sent);
230
231	return 0;
232}
233
234int
235small_smb_init_no_tc(const int smb_command, const int wct,
236		     struct cifs_ses *ses, void **request_buf)
237{
238	int rc;
239	struct smb_hdr *buffer;
240
241	rc = small_smb_init(smb_command, wct, NULL, request_buf);
242	if (rc)
243		return rc;
244
245	buffer = (struct smb_hdr *)*request_buf;
246	buffer->Mid = get_next_mid(ses->server);
247	if (ses->capabilities & CAP_UNICODE)
248		buffer->Flags2 |= SMBFLG2_UNICODE;
249	if (ses->capabilities & CAP_STATUS32)
250		buffer->Flags2 |= SMBFLG2_ERR_STATUS;
251
252	/* uid, tid can stay at zero as set in header assemble */
253
254	/* BB add support for turning on the signing when
255	this function is used after 1st of session setup requests */
256
257	return rc;
258}
259
260/* If the return code is zero, this function must fill in request_buf pointer */
261static int
262__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
263			void **request_buf, void **response_buf)
264{
265	*request_buf = cifs_buf_get();
266	if (*request_buf == NULL) {
267		/* BB should we add a retry in here if not a writepage? */
268		return -ENOMEM;
269	}
270    /* Although the original thought was we needed the response buf for  */
271    /* potential retries of smb operations it turns out we can determine */
272    /* from the mid flags when the request buffer can be resent without  */
273    /* having to use a second distinct buffer for the response */
274	if (response_buf)
275		*response_buf = *request_buf;
276
277	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
278			wct);
279
280	if (tcon != NULL)
281		cifs_stats_inc(&tcon->num_smbs_sent);
282
283	return 0;
284}
285
286/* If the return code is zero, this function must fill in request_buf pointer */
287static int
288smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
289	 void **request_buf, void **response_buf)
290{
291	int rc;
292
293	rc = cifs_reconnect_tcon(tcon, smb_command);
294	if (rc)
295		return rc;
296
297	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
298}
299
300static int
301smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
302			void **request_buf, void **response_buf)
303{
304	spin_lock(&tcon->ses->chan_lock);
305	if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
306	    tcon->need_reconnect) {
307		spin_unlock(&tcon->ses->chan_lock);
308		return -EHOSTDOWN;
309	}
310	spin_unlock(&tcon->ses->chan_lock);
311
312	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
313}
314
315static int validate_t2(struct smb_t2_rsp *pSMB)
316{
317	unsigned int total_size;
318
319	/* check for plausible wct */
320	if (pSMB->hdr.WordCount < 10)
321		goto vt2_err;
322
323	/* check for parm and data offset going beyond end of smb */
324	if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
325	    get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
326		goto vt2_err;
327
328	total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
329	if (total_size >= 512)
330		goto vt2_err;
331
332	/* check that bcc is at least as big as parms + data, and that it is
333	 * less than negotiated smb buffer
334	 */
335	total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
336	if (total_size > get_bcc(&pSMB->hdr) ||
337	    total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
338		goto vt2_err;
339
340	return 0;
341vt2_err:
342	cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
343		sizeof(struct smb_t2_rsp) + 16);
344	return -EINVAL;
345}
346
347static int
348decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
349{
350	int	rc = 0;
351	u16	count;
352	char	*guid = pSMBr->u.extended_response.GUID;
353	struct TCP_Server_Info *server = ses->server;
354
355	count = get_bcc(&pSMBr->hdr);
356	if (count < SMB1_CLIENT_GUID_SIZE)
357		return -EIO;
358
359	spin_lock(&cifs_tcp_ses_lock);
360	if (server->srv_count > 1) {
361		spin_unlock(&cifs_tcp_ses_lock);
362		if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
363			cifs_dbg(FYI, "server UID changed\n");
364			memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
365		}
366	} else {
367		spin_unlock(&cifs_tcp_ses_lock);
368		memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
369	}
370
371	if (count == SMB1_CLIENT_GUID_SIZE) {
372		server->sec_ntlmssp = true;
373	} else {
374		count -= SMB1_CLIENT_GUID_SIZE;
375		rc = decode_negTokenInit(
376			pSMBr->u.extended_response.SecurityBlob, count, server);
377		if (rc != 1)
378			return -EINVAL;
379	}
380
381	return 0;
382}
383
384static bool
385should_set_ext_sec_flag(enum securityEnum sectype)
386{
387	switch (sectype) {
388	case RawNTLMSSP:
389	case Kerberos:
390		return true;
391	case Unspecified:
392		if (global_secflags &
393		    (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
394			return true;
395		fallthrough;
396	default:
397		return false;
398	}
399}
400
401int
402CIFSSMBNegotiate(const unsigned int xid,
403		 struct cifs_ses *ses,
404		 struct TCP_Server_Info *server)
405{
406	NEGOTIATE_REQ *pSMB;
407	NEGOTIATE_RSP *pSMBr;
408	int rc = 0;
409	int bytes_returned;
410	int i;
411	u16 count;
412
413	if (!server) {
414		WARN(1, "%s: server is NULL!\n", __func__);
415		return -EIO;
416	}
417
418	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
419		      (void **) &pSMB, (void **) &pSMBr);
420	if (rc)
421		return rc;
422
423	pSMB->hdr.Mid = get_next_mid(server);
424	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
425
426	if (should_set_ext_sec_flag(ses->sectype)) {
427		cifs_dbg(FYI, "Requesting extended security\n");
428		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
429	}
430
431	count = 0;
432	/*
433	 * We know that all the name entries in the protocols array
434	 * are short (< 16 bytes anyway) and are NUL terminated.
435	 */
436	for (i = 0; i < CIFS_NUM_PROT; i++) {
437		size_t len = strlen(protocols[i].name) + 1;
438
439		memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);
440		count += len;
441	}
442	inc_rfc1001_len(pSMB, count);
443	pSMB->ByteCount = cpu_to_le16(count);
444
445	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
446			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
447	if (rc != 0)
448		goto neg_err_exit;
449
450	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
451	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
452	/* Check wct = 1 error case */
453	if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
454		/* core returns wct = 1, but we do not ask for core - otherwise
455		small wct just comes when dialect index is -1 indicating we
456		could not negotiate a common dialect */
457		rc = -EOPNOTSUPP;
458		goto neg_err_exit;
459	} else if (pSMBr->hdr.WordCount != 17) {
460		/* unknown wct */
461		rc = -EOPNOTSUPP;
462		goto neg_err_exit;
463	}
464	/* else wct == 17, NTLM or better */
465
466	server->sec_mode = pSMBr->SecurityMode;
467	if ((server->sec_mode & SECMODE_USER) == 0)
468		cifs_dbg(FYI, "share mode security\n");
469
470	/* one byte, so no need to convert this or EncryptionKeyLen from
471	   little endian */
472	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
473			       cifs_max_pending);
474	set_credits(server, server->maxReq);
475	/* probably no need to store and check maxvcs */
476	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
477	/* set up max_read for readahead check */
478	server->max_read = server->maxBuf;
479	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
480	cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
481	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
482	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
483	server->timeAdj *= 60;
484
485	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
486		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
487		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
488		       CIFS_CRYPTO_KEY_SIZE);
489	} else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
490			server->capabilities & CAP_EXTENDED_SECURITY) {
491		server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
492		rc = decode_ext_sec_blob(ses, pSMBr);
493	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
494		rc = -EIO; /* no crypt key only if plain text pwd */
495	} else {
496		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
497		server->capabilities &= ~CAP_EXTENDED_SECURITY;
498	}
499
500	if (!rc)
501		rc = cifs_enable_signing(server, ses->sign);
502neg_err_exit:
503	cifs_buf_release(pSMB);
504
505	cifs_dbg(FYI, "negprot rc %d\n", rc);
506	return rc;
507}
508
509int
510CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
511{
512	struct smb_hdr *smb_buffer;
513	int rc = 0;
514
515	cifs_dbg(FYI, "In tree disconnect\n");
516
517	/* BB: do we need to check this? These should never be NULL. */
518	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
519		return -EIO;
520
521	/*
522	 * No need to return error on this operation if tid invalidated and
523	 * closed on server already e.g. due to tcp session crashing. Also,
524	 * the tcon is no longer on the list, so no need to take lock before
525	 * checking this.
526	 */
527	spin_lock(&tcon->ses->chan_lock);
528	if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
529		spin_unlock(&tcon->ses->chan_lock);
530		return -EIO;
531	}
532	spin_unlock(&tcon->ses->chan_lock);
533
534	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
535			    (void **)&smb_buffer);
536	if (rc)
537		return rc;
538
539	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
540	cifs_small_buf_release(smb_buffer);
541	if (rc)
542		cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
543
544	/* No need to return error on this operation if tid invalidated and
545	   closed on server already e.g. due to tcp session crashing */
546	if (rc == -EAGAIN)
547		rc = 0;
548
549	return rc;
550}
551
552/*
553 * This is a no-op for now. We're not really interested in the reply, but
554 * rather in the fact that the server sent one and that server->lstrp
555 * gets updated.
556 *
557 * FIXME: maybe we should consider checking that the reply matches request?
558 */
559static void
560cifs_echo_callback(struct mid_q_entry *mid)
561{
562	struct TCP_Server_Info *server = mid->callback_data;
563	struct cifs_credits credits = { .value = 1, .instance = 0 };
564
565	release_mid(mid);
566	add_credits(server, &credits, CIFS_ECHO_OP);
567}
568
569int
570CIFSSMBEcho(struct TCP_Server_Info *server)
571{
572	ECHO_REQ *smb;
573	int rc = 0;
574	struct kvec iov[2];
575	struct smb_rqst rqst = { .rq_iov = iov,
576				 .rq_nvec = 2 };
577
578	cifs_dbg(FYI, "In echo request\n");
579
580	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
581	if (rc)
582		return rc;
583
584	if (server->capabilities & CAP_UNICODE)
585		smb->hdr.Flags2 |= SMBFLG2_UNICODE;
586
587	/* set up echo request */
588	smb->hdr.Tid = 0xffff;
589	smb->hdr.WordCount = 1;
590	put_unaligned_le16(1, &smb->EchoCount);
591	put_bcc(1, &smb->hdr);
592	smb->Data[0] = 'a';
593	inc_rfc1001_len(smb, 3);
594
595	iov[0].iov_len = 4;
596	iov[0].iov_base = smb;
597	iov[1].iov_len = get_rfc1002_length(smb);
598	iov[1].iov_base = (char *)smb + 4;
599
600	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
601			     server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
602	if (rc)
603		cifs_dbg(FYI, "Echo request failed: %d\n", rc);
604
605	cifs_small_buf_release(smb);
606
607	return rc;
608}
609
610int
611CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
612{
613	LOGOFF_ANDX_REQ *pSMB;
614	int rc = 0;
615
616	cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
617
618	/*
619	 * BB: do we need to check validity of ses and server? They should
620	 * always be valid since we have an active reference. If not, that
621	 * should probably be a BUG()
622	 */
623	if (!ses || !ses->server)
624		return -EIO;
625
626	mutex_lock(&ses->session_mutex);
627	spin_lock(&ses->chan_lock);
628	if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
629		spin_unlock(&ses->chan_lock);
630		goto session_already_dead; /* no need to send SMBlogoff if uid
631					      already closed due to reconnect */
632	}
633	spin_unlock(&ses->chan_lock);
634
635	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
636	if (rc) {
637		mutex_unlock(&ses->session_mutex);
638		return rc;
639	}
640
641	pSMB->hdr.Mid = get_next_mid(ses->server);
642
643	if (ses->server->sign)
644		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
645
646	pSMB->hdr.Uid = ses->Suid;
647
648	pSMB->AndXCommand = 0xFF;
649	rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
650	cifs_small_buf_release(pSMB);
651session_already_dead:
652	mutex_unlock(&ses->session_mutex);
653
654	/* if session dead then we do not need to do ulogoff,
655		since server closed smb session, no sense reporting
656		error */
657	if (rc == -EAGAIN)
658		rc = 0;
659	return rc;
660}
661
662int
663CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
664		 const char *fileName, __u16 type,
665		 const struct nls_table *nls_codepage, int remap)
666{
667	TRANSACTION2_SPI_REQ *pSMB = NULL;
668	TRANSACTION2_SPI_RSP *pSMBr = NULL;
669	struct unlink_psx_rq *pRqD;
670	int name_len;
671	int rc = 0;
672	int bytes_returned = 0;
673	__u16 params, param_offset, offset, byte_count;
674
675	cifs_dbg(FYI, "In POSIX delete\n");
676PsxDelete:
677	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
678		      (void **) &pSMBr);
679	if (rc)
680		return rc;
681
682	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
683		name_len =
684		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
685				       PATH_MAX, nls_codepage, remap);
686		name_len++;	/* trailing null */
687		name_len *= 2;
688	} else {
689		name_len = copy_path_name(pSMB->FileName, fileName);
690	}
691
692	params = 6 + name_len;
693	pSMB->MaxParameterCount = cpu_to_le16(2);
694	pSMB->MaxDataCount = 0; /* BB double check this with jra */
695	pSMB->MaxSetupCount = 0;
696	pSMB->Reserved = 0;
697	pSMB->Flags = 0;
698	pSMB->Timeout = 0;
699	pSMB->Reserved2 = 0;
700	param_offset = offsetof(struct smb_com_transaction2_spi_req,
701				InformationLevel) - 4;
702	offset = param_offset + params;
703
704	/* Setup pointer to Request Data (inode type).
705	 * Note that SMB offsets are from the beginning of SMB which is 4 bytes
706	 * in, after RFC1001 field
707	 */
708	pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
709	pRqD->type = cpu_to_le16(type);
710	pSMB->ParameterOffset = cpu_to_le16(param_offset);
711	pSMB->DataOffset = cpu_to_le16(offset);
712	pSMB->SetupCount = 1;
713	pSMB->Reserved3 = 0;
714	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
715	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
716
717	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
718	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
719	pSMB->ParameterCount = cpu_to_le16(params);
720	pSMB->TotalParameterCount = pSMB->ParameterCount;
721	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
722	pSMB->Reserved4 = 0;
723	inc_rfc1001_len(pSMB, byte_count);
724	pSMB->ByteCount = cpu_to_le16(byte_count);
725	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
726			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
727	if (rc)
728		cifs_dbg(FYI, "Posix delete returned %d\n", rc);
729	cifs_buf_release(pSMB);
730
731	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
732
733	if (rc == -EAGAIN)
734		goto PsxDelete;
735
736	return rc;
737}
738
739int
740CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
741	       struct cifs_sb_info *cifs_sb)
742{
743	DELETE_FILE_REQ *pSMB = NULL;
744	DELETE_FILE_RSP *pSMBr = NULL;
745	int rc = 0;
746	int bytes_returned;
747	int name_len;
748	int remap = cifs_remap(cifs_sb);
749
750DelFileRetry:
751	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
752		      (void **) &pSMBr);
753	if (rc)
754		return rc;
755
756	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
757		name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
758					      PATH_MAX, cifs_sb->local_nls,
759					      remap);
760		name_len++;	/* trailing null */
761		name_len *= 2;
762	} else {
763		name_len = copy_path_name(pSMB->fileName, name);
764	}
765	pSMB->SearchAttributes =
766	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
767	pSMB->BufferFormat = 0x04;
768	inc_rfc1001_len(pSMB, name_len + 1);
769	pSMB->ByteCount = cpu_to_le16(name_len + 1);
770	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
771			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
772	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
773	if (rc)
774		cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
775
776	cifs_buf_release(pSMB);
777	if (rc == -EAGAIN)
778		goto DelFileRetry;
779
780	return rc;
781}
782
783int
784CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
785	     struct cifs_sb_info *cifs_sb)
786{
787	DELETE_DIRECTORY_REQ *pSMB = NULL;
788	DELETE_DIRECTORY_RSP *pSMBr = NULL;
789	int rc = 0;
790	int bytes_returned;
791	int name_len;
792	int remap = cifs_remap(cifs_sb);
793
794	cifs_dbg(FYI, "In CIFSSMBRmDir\n");
795RmDirRetry:
796	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
797		      (void **) &pSMBr);
798	if (rc)
799		return rc;
800
801	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
802		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
803					      PATH_MAX, cifs_sb->local_nls,
804					      remap);
805		name_len++;	/* trailing null */
806		name_len *= 2;
807	} else {
808		name_len = copy_path_name(pSMB->DirName, name);
809	}
810
811	pSMB->BufferFormat = 0x04;
812	inc_rfc1001_len(pSMB, name_len + 1);
813	pSMB->ByteCount = cpu_to_le16(name_len + 1);
814	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
815			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
816	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
817	if (rc)
818		cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
819
820	cifs_buf_release(pSMB);
821	if (rc == -EAGAIN)
822		goto RmDirRetry;
823	return rc;
824}
825
826int
827CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
828	     struct cifs_tcon *tcon, const char *name,
829	     struct cifs_sb_info *cifs_sb)
830{
831	int rc = 0;
832	CREATE_DIRECTORY_REQ *pSMB = NULL;
833	CREATE_DIRECTORY_RSP *pSMBr = NULL;
834	int bytes_returned;
835	int name_len;
836	int remap = cifs_remap(cifs_sb);
837
838	cifs_dbg(FYI, "In CIFSSMBMkDir\n");
839MkDirRetry:
840	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
841		      (void **) &pSMBr);
842	if (rc)
843		return rc;
844
845	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
846		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
847					      PATH_MAX, cifs_sb->local_nls,
848					      remap);
849		name_len++;	/* trailing null */
850		name_len *= 2;
851	} else {
852		name_len = copy_path_name(pSMB->DirName, name);
853	}
854
855	pSMB->BufferFormat = 0x04;
856	inc_rfc1001_len(pSMB, name_len + 1);
857	pSMB->ByteCount = cpu_to_le16(name_len + 1);
858	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
859			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
860	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
861	if (rc)
862		cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
863
864	cifs_buf_release(pSMB);
865	if (rc == -EAGAIN)
866		goto MkDirRetry;
867	return rc;
868}
869
870int
871CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
872		__u32 posix_flags, __u64 mode, __u16 *netfid,
873		FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
874		const char *name, const struct nls_table *nls_codepage,
875		int remap)
876{
877	TRANSACTION2_SPI_REQ *pSMB = NULL;
878	TRANSACTION2_SPI_RSP *pSMBr = NULL;
879	int name_len;
880	int rc = 0;
881	int bytes_returned = 0;
882	__u16 params, param_offset, offset, byte_count, count;
883	OPEN_PSX_REQ *pdata;
884	OPEN_PSX_RSP *psx_rsp;
885
886	cifs_dbg(FYI, "In POSIX Create\n");
887PsxCreat:
888	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
889		      (void **) &pSMBr);
890	if (rc)
891		return rc;
892
893	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
894		name_len =
895		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
896				       PATH_MAX, nls_codepage, remap);
897		name_len++;	/* trailing null */
898		name_len *= 2;
899	} else {
900		name_len = copy_path_name(pSMB->FileName, name);
901	}
902
903	params = 6 + name_len;
904	count = sizeof(OPEN_PSX_REQ);
905	pSMB->MaxParameterCount = cpu_to_le16(2);
906	pSMB->MaxDataCount = cpu_to_le16(1000);	/* large enough */
907	pSMB->MaxSetupCount = 0;
908	pSMB->Reserved = 0;
909	pSMB->Flags = 0;
910	pSMB->Timeout = 0;
911	pSMB->Reserved2 = 0;
912	param_offset = offsetof(struct smb_com_transaction2_spi_req,
913				InformationLevel) - 4;
914	offset = param_offset + params;
915	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
916	pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
917	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
918	pdata->Permissions = cpu_to_le64(mode);
919	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
920	pdata->OpenFlags =  cpu_to_le32(*pOplock);
921	pSMB->ParameterOffset = cpu_to_le16(param_offset);
922	pSMB->DataOffset = cpu_to_le16(offset);
923	pSMB->SetupCount = 1;
924	pSMB->Reserved3 = 0;
925	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
926	byte_count = 3 /* pad */  + params + count;
927
928	pSMB->DataCount = cpu_to_le16(count);
929	pSMB->ParameterCount = cpu_to_le16(params);
930	pSMB->TotalDataCount = pSMB->DataCount;
931	pSMB->TotalParameterCount = pSMB->ParameterCount;
932	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
933	pSMB->Reserved4 = 0;
934	inc_rfc1001_len(pSMB, byte_count);
935	pSMB->ByteCount = cpu_to_le16(byte_count);
936	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
937			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
938	if (rc) {
939		cifs_dbg(FYI, "Posix create returned %d\n", rc);
940		goto psx_create_err;
941	}
942
943	cifs_dbg(FYI, "copying inode info\n");
944	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
945
946	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
947		rc = -EIO;	/* bad smb */
948		goto psx_create_err;
949	}
950
951	/* copy return information to pRetData */
952	psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
953			+ le16_to_cpu(pSMBr->t2.DataOffset));
954
955	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
956	if (netfid)
957		*netfid = psx_rsp->Fid;   /* cifs fid stays in le */
958	/* Let caller know file was created so we can set the mode. */
959	/* Do we care about the CreateAction in any other cases? */
960	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
961		*pOplock |= CIFS_CREATE_ACTION;
962	/* check to make sure response data is there */
963	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
964		pRetData->Type = cpu_to_le32(-1); /* unknown */
965		cifs_dbg(NOISY, "unknown type\n");
966	} else {
967		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
968					+ sizeof(FILE_UNIX_BASIC_INFO)) {
969			cifs_dbg(VFS, "Open response data too small\n");
970			pRetData->Type = cpu_to_le32(-1);
971			goto psx_create_err;
972		}
973		memcpy((char *) pRetData,
974			(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
975			sizeof(FILE_UNIX_BASIC_INFO));
976	}
977
978psx_create_err:
979	cifs_buf_release(pSMB);
980
981	if (posix_flags & SMB_O_DIRECTORY)
982		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
983	else
984		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
985
986	if (rc == -EAGAIN)
987		goto PsxCreat;
988
989	return rc;
990}
991
992static __u16 convert_disposition(int disposition)
993{
994	__u16 ofun = 0;
995
996	switch (disposition) {
997		case FILE_SUPERSEDE:
998			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
999			break;
1000		case FILE_OPEN:
1001			ofun = SMBOPEN_OAPPEND;
1002			break;
1003		case FILE_CREATE:
1004			ofun = SMBOPEN_OCREATE;
1005			break;
1006		case FILE_OPEN_IF:
1007			ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1008			break;
1009		case FILE_OVERWRITE:
1010			ofun = SMBOPEN_OTRUNC;
1011			break;
1012		case FILE_OVERWRITE_IF:
1013			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1014			break;
1015		default:
1016			cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1017			ofun =  SMBOPEN_OAPPEND; /* regular open */
1018	}
1019	return ofun;
1020}
1021
1022static int
1023access_flags_to_smbopen_mode(const int access_flags)
1024{
1025	int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1026
1027	if (masked_flags == GENERIC_READ)
1028		return SMBOPEN_READ;
1029	else if (masked_flags == GENERIC_WRITE)
1030		return SMBOPEN_WRITE;
1031
1032	/* just go for read/write */
1033	return SMBOPEN_READWRITE;
1034}
1035
1036int
1037SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1038	    const char *fileName, const int openDisposition,
1039	    const int access_flags, const int create_options, __u16 *netfid,
1040	    int *pOplock, FILE_ALL_INFO *pfile_info,
1041	    const struct nls_table *nls_codepage, int remap)
1042{
1043	int rc;
1044	OPENX_REQ *pSMB = NULL;
1045	OPENX_RSP *pSMBr = NULL;
1046	int bytes_returned;
1047	int name_len;
1048	__u16 count;
1049
1050OldOpenRetry:
1051	rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1052		      (void **) &pSMBr);
1053	if (rc)
1054		return rc;
1055
1056	pSMB->AndXCommand = 0xFF;       /* none */
1057
1058	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1059		count = 1;      /* account for one byte pad to word boundary */
1060		name_len =
1061		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1062				      fileName, PATH_MAX, nls_codepage, remap);
1063		name_len++;     /* trailing null */
1064		name_len *= 2;
1065	} else {
1066		count = 0;      /* no pad */
1067		name_len = copy_path_name(pSMB->fileName, fileName);
1068	}
1069	if (*pOplock & REQ_OPLOCK)
1070		pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1071	else if (*pOplock & REQ_BATCHOPLOCK)
1072		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1073
1074	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1075	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1076	pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1077	/* set file as system file if special file such
1078	   as fifo and server expecting SFU style and
1079	   no Unix extensions */
1080
1081	if (create_options & CREATE_OPTION_SPECIAL)
1082		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1083	else /* BB FIXME BB */
1084		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1085
1086	if (create_options & CREATE_OPTION_READONLY)
1087		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1088
1089	/* BB FIXME BB */
1090/*	pSMB->CreateOptions = cpu_to_le32(create_options &
1091						 CREATE_OPTIONS_MASK); */
1092	/* BB FIXME END BB */
1093
1094	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1095	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1096	count += name_len;
1097	inc_rfc1001_len(pSMB, count);
1098
1099	pSMB->ByteCount = cpu_to_le16(count);
1100	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
1102	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1103	if (rc) {
1104		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1105	} else {
1106	/* BB verify if wct == 15 */
1107
1108/*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1109
1110		*netfid = pSMBr->Fid;   /* cifs fid stays in le */
1111		/* Let caller know file was created so we can set the mode. */
1112		/* Do we care about the CreateAction in any other cases? */
1113	/* BB FIXME BB */
1114/*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1115			*pOplock |= CIFS_CREATE_ACTION; */
1116	/* BB FIXME END */
1117
1118		if (pfile_info) {
1119			pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1120			pfile_info->LastAccessTime = 0; /* BB fixme */
1121			pfile_info->LastWriteTime = 0; /* BB fixme */
1122			pfile_info->ChangeTime = 0;  /* BB fixme */
1123			pfile_info->Attributes =
1124				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1125			/* the file_info buf is endian converted by caller */
1126			pfile_info->AllocationSize =
1127				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1128			pfile_info->EndOfFile = pfile_info->AllocationSize;
1129			pfile_info->NumberOfLinks = cpu_to_le32(1);
1130			pfile_info->DeletePending = 0;
1131		}
1132	}
1133
1134	cifs_buf_release(pSMB);
1135	if (rc == -EAGAIN)
1136		goto OldOpenRetry;
1137	return rc;
1138}
1139
1140int
1141CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1142	  FILE_ALL_INFO *buf)
1143{
1144	int rc;
1145	OPEN_REQ *req = NULL;
1146	OPEN_RSP *rsp = NULL;
1147	int bytes_returned;
1148	int name_len;
1149	__u16 count;
1150	struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1151	struct cifs_tcon *tcon = oparms->tcon;
1152	int remap = cifs_remap(cifs_sb);
1153	const struct nls_table *nls = cifs_sb->local_nls;
1154	int create_options = oparms->create_options;
1155	int desired_access = oparms->desired_access;
1156	int disposition = oparms->disposition;
1157	const char *path = oparms->path;
1158
1159openRetry:
1160	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1161		      (void **)&rsp);
1162	if (rc)
1163		return rc;
1164
1165	/* no commands go after this */
1166	req->AndXCommand = 0xFF;
1167
1168	if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1169		/* account for one byte pad to word boundary */
1170		count = 1;
1171		name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1172					      path, PATH_MAX, nls, remap);
1173		/* trailing null */
1174		name_len++;
1175		name_len *= 2;
1176		req->NameLength = cpu_to_le16(name_len);
1177	} else {
1178		/* BB improve check for buffer overruns BB */
1179		/* no pad */
1180		count = 0;
1181		name_len = copy_path_name(req->fileName, path);
1182		req->NameLength = cpu_to_le16(name_len);
1183	}
1184
1185	if (*oplock & REQ_OPLOCK)
1186		req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1187	else if (*oplock & REQ_BATCHOPLOCK)
1188		req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1189
1190	req->DesiredAccess = cpu_to_le32(desired_access);
1191	req->AllocationSize = 0;
1192
1193	/*
1194	 * Set file as system file if special file such as fifo and server
1195	 * expecting SFU style and no Unix extensions.
1196	 */
1197	if (create_options & CREATE_OPTION_SPECIAL)
1198		req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1199	else
1200		req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1201
1202	/*
1203	 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1204	 * sensitive checks for other servers such as Samba.
1205	 */
1206	if (tcon->ses->capabilities & CAP_UNIX)
1207		req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1208
1209	if (create_options & CREATE_OPTION_READONLY)
1210		req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1211
1212	req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1213	req->CreateDisposition = cpu_to_le32(disposition);
1214	req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1215
1216	/* BB Expirement with various impersonation levels and verify */
1217	req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1218	req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1219
1220	count += name_len;
1221	inc_rfc1001_len(req, count);
1222
1223	req->ByteCount = cpu_to_le16(count);
1224	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1225			 (struct smb_hdr *)rsp, &bytes_returned, 0);
1226	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1227	if (rc) {
1228		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1229		cifs_buf_release(req);
1230		if (rc == -EAGAIN)
1231			goto openRetry;
1232		return rc;
1233	}
1234
1235	/* 1 byte no need to le_to_cpu */
1236	*oplock = rsp->OplockLevel;
1237	/* cifs fid stays in le */
1238	oparms->fid->netfid = rsp->Fid;
1239	oparms->fid->access = desired_access;
1240
1241	/* Let caller know file was created so we can set the mode. */
1242	/* Do we care about the CreateAction in any other cases? */
1243	if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1244		*oplock |= CIFS_CREATE_ACTION;
1245
1246	if (buf) {
1247		/* copy commonly used attributes */
1248		memcpy(&buf->common_attributes,
1249		       &rsp->common_attributes,
1250		       sizeof(buf->common_attributes));
1251		/* the file_info buf is endian converted by caller */
1252		buf->AllocationSize = rsp->AllocationSize;
1253		buf->EndOfFile = rsp->EndOfFile;
1254		buf->NumberOfLinks = cpu_to_le32(1);
1255		buf->DeletePending = 0;
1256	}
1257
1258	cifs_buf_release(req);
1259	return rc;
1260}
1261
1262static void
1263cifs_readv_callback(struct mid_q_entry *mid)
1264{
1265	struct cifs_readdata *rdata = mid->callback_data;
1266	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1267	struct TCP_Server_Info *server = tcon->ses->server;
1268	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1269				 .rq_nvec = 2,
1270				 .rq_iter_size = iov_iter_count(&rdata->iter),
1271				 .rq_iter = rdata->iter };
1272	struct cifs_credits credits = { .value = 1, .instance = 0 };
1273
1274	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1275		 __func__, mid->mid, mid->mid_state, rdata->result,
1276		 rdata->bytes);
1277
1278	switch (mid->mid_state) {
1279	case MID_RESPONSE_RECEIVED:
1280		/* result already set, check signature */
1281		if (server->sign) {
1282			int rc = 0;
1283
1284			rc = cifs_verify_signature(&rqst, server,
1285						  mid->sequence_number);
1286			if (rc)
1287				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1288					 rc);
1289		}
1290		/* FIXME: should this be counted toward the initiating task? */
1291		task_io_account_read(rdata->got_bytes);
1292		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1293		break;
1294	case MID_REQUEST_SUBMITTED:
1295	case MID_RETRY_NEEDED:
1296		rdata->result = -EAGAIN;
1297		if (server->sign && rdata->got_bytes)
1298			/* reset bytes number since we can not check a sign */
1299			rdata->got_bytes = 0;
1300		/* FIXME: should this be counted toward the initiating task? */
1301		task_io_account_read(rdata->got_bytes);
1302		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1303		break;
1304	default:
1305		rdata->result = -EIO;
1306	}
1307
1308	queue_work(cifsiod_wq, &rdata->work);
1309	release_mid(mid);
1310	add_credits(server, &credits, 0);
1311}
1312
1313/* cifs_async_readv - send an async write, and set up mid to handle result */
1314int
1315cifs_async_readv(struct cifs_readdata *rdata)
1316{
1317	int rc;
1318	READ_REQ *smb = NULL;
1319	int wct;
1320	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1321	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1322				 .rq_nvec = 2 };
1323
1324	cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1325		 __func__, rdata->offset, rdata->bytes);
1326
1327	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1328		wct = 12;
1329	else {
1330		wct = 10; /* old style read */
1331		if ((rdata->offset >> 32) > 0)  {
1332			/* can not handle this big offset for old */
1333			return -EIO;
1334		}
1335	}
1336
1337	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1338	if (rc)
1339		return rc;
1340
1341	smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1342	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1343
1344	smb->AndXCommand = 0xFF;	/* none */
1345	smb->Fid = rdata->cfile->fid.netfid;
1346	smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1347	if (wct == 12)
1348		smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1349	smb->Remaining = 0;
1350	smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1351	smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1352	if (wct == 12)
1353		smb->ByteCount = 0;
1354	else {
1355		/* old style read */
1356		struct smb_com_readx_req *smbr =
1357			(struct smb_com_readx_req *)smb;
1358		smbr->ByteCount = 0;
1359	}
1360
1361	/* 4 for RFC1001 length + 1 for BCC */
1362	rdata->iov[0].iov_base = smb;
1363	rdata->iov[0].iov_len = 4;
1364	rdata->iov[1].iov_base = (char *)smb + 4;
1365	rdata->iov[1].iov_len = get_rfc1002_length(smb);
1366
1367	kref_get(&rdata->refcount);
1368	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1369			     cifs_readv_callback, NULL, rdata, 0, NULL);
1370
1371	if (rc == 0)
1372		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1373	else
1374		kref_put(&rdata->refcount, cifs_readdata_release);
1375
1376	cifs_small_buf_release(smb);
1377	return rc;
1378}
1379
1380int
1381CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1382	    unsigned int *nbytes, char **buf, int *pbuf_type)
1383{
1384	int rc = -EACCES;
1385	READ_REQ *pSMB = NULL;
1386	READ_RSP *pSMBr = NULL;
1387	char *pReadData = NULL;
1388	int wct;
1389	int resp_buf_type = 0;
1390	struct kvec iov[1];
1391	struct kvec rsp_iov;
1392	__u32 pid = io_parms->pid;
1393	__u16 netfid = io_parms->netfid;
1394	__u64 offset = io_parms->offset;
1395	struct cifs_tcon *tcon = io_parms->tcon;
1396	unsigned int count = io_parms->length;
1397
1398	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1399	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1400		wct = 12;
1401	else {
1402		wct = 10; /* old style read */
1403		if ((offset >> 32) > 0)  {
1404			/* can not handle this big offset for old */
1405			return -EIO;
1406		}
1407	}
1408
1409	*nbytes = 0;
1410	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1411	if (rc)
1412		return rc;
1413
1414	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1415	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1416
1417	/* tcon and ses pointer are checked in smb_init */
1418	if (tcon->ses->server == NULL)
1419		return -ECONNABORTED;
1420
1421	pSMB->AndXCommand = 0xFF;       /* none */
1422	pSMB->Fid = netfid;
1423	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1424	if (wct == 12)
1425		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1426
1427	pSMB->Remaining = 0;
1428	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1429	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1430	if (wct == 12)
1431		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1432	else {
1433		/* old style read */
1434		struct smb_com_readx_req *pSMBW =
1435			(struct smb_com_readx_req *)pSMB;
1436		pSMBW->ByteCount = 0;
1437	}
1438
1439	iov[0].iov_base = (char *)pSMB;
1440	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1441	rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1442			  CIFS_LOG_ERROR, &rsp_iov);
1443	cifs_small_buf_release(pSMB);
1444	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1445	pSMBr = (READ_RSP *)rsp_iov.iov_base;
1446	if (rc) {
1447		cifs_dbg(VFS, "Send error in read = %d\n", rc);
1448	} else {
1449		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1450		data_length = data_length << 16;
1451		data_length += le16_to_cpu(pSMBr->DataLength);
1452		*nbytes = data_length;
1453
1454		/*check that DataLength would not go beyond end of SMB */
1455		if ((data_length > CIFSMaxBufSize)
1456				|| (data_length > count)) {
1457			cifs_dbg(FYI, "bad length %d for count %d\n",
1458				 data_length, count);
1459			rc = -EIO;
1460			*nbytes = 0;
1461		} else {
1462			pReadData = (char *) (&pSMBr->hdr.Protocol) +
1463					le16_to_cpu(pSMBr->DataOffset);
1464/*			if (rc = copy_to_user(buf, pReadData, data_length)) {
1465				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1466				rc = -EFAULT;
1467			}*/ /* can not use copy_to_user when using page cache*/
1468			if (*buf)
1469				memcpy(*buf, pReadData, data_length);
1470		}
1471	}
1472
1473	if (*buf) {
1474		free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1475	} else if (resp_buf_type != CIFS_NO_BUFFER) {
1476		/* return buffer to caller to free */
1477		*buf = rsp_iov.iov_base;
1478		if (resp_buf_type == CIFS_SMALL_BUFFER)
1479			*pbuf_type = CIFS_SMALL_BUFFER;
1480		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1481			*pbuf_type = CIFS_LARGE_BUFFER;
1482	} /* else no valid buffer on return - leave as null */
1483
1484	/* Note: On -EAGAIN error only caller can retry on handle based calls
1485		since file handle passed in no longer valid */
1486	return rc;
1487}
1488
1489
1490int
1491CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1492	     unsigned int *nbytes, const char *buf)
1493{
1494	int rc = -EACCES;
1495	WRITE_REQ *pSMB = NULL;
1496	WRITE_RSP *pSMBr = NULL;
1497	int bytes_returned, wct;
1498	__u32 bytes_sent;
1499	__u16 byte_count;
1500	__u32 pid = io_parms->pid;
1501	__u16 netfid = io_parms->netfid;
1502	__u64 offset = io_parms->offset;
1503	struct cifs_tcon *tcon = io_parms->tcon;
1504	unsigned int count = io_parms->length;
1505
1506	*nbytes = 0;
1507
1508	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1509	if (tcon->ses == NULL)
1510		return -ECONNABORTED;
1511
1512	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1513		wct = 14;
1514	else {
1515		wct = 12;
1516		if ((offset >> 32) > 0) {
1517			/* can not handle big offset for old srv */
1518			return -EIO;
1519		}
1520	}
1521
1522	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1523		      (void **) &pSMBr);
1524	if (rc)
1525		return rc;
1526
1527	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1528	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1529
1530	/* tcon and ses pointer are checked in smb_init */
1531	if (tcon->ses->server == NULL)
1532		return -ECONNABORTED;
1533
1534	pSMB->AndXCommand = 0xFF;	/* none */
1535	pSMB->Fid = netfid;
1536	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1537	if (wct == 14)
1538		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1539
1540	pSMB->Reserved = 0xFFFFFFFF;
1541	pSMB->WriteMode = 0;
1542	pSMB->Remaining = 0;
1543
1544	/* Can increase buffer size if buffer is big enough in some cases ie we
1545	can send more if LARGE_WRITE_X capability returned by the server and if
1546	our buffer is big enough or if we convert to iovecs on socket writes
1547	and eliminate the copy to the CIFS buffer */
1548	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1549		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1550	} else {
1551		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1552			 & ~0xFF;
1553	}
1554
1555	if (bytes_sent > count)
1556		bytes_sent = count;
1557	pSMB->DataOffset =
1558		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1559	if (buf)
1560		memcpy(pSMB->Data, buf, bytes_sent);
1561	else if (count != 0) {
1562		/* No buffer */
1563		cifs_buf_release(pSMB);
1564		return -EINVAL;
1565	} /* else setting file size with write of zero bytes */
1566	if (wct == 14)
1567		byte_count = bytes_sent + 1; /* pad */
1568	else /* wct == 12 */
1569		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1570
1571	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1572	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1573	inc_rfc1001_len(pSMB, byte_count);
1574
1575	if (wct == 14)
1576		pSMB->ByteCount = cpu_to_le16(byte_count);
1577	else { /* old style write has byte count 4 bytes earlier
1578		  so 4 bytes pad  */
1579		struct smb_com_writex_req *pSMBW =
1580			(struct smb_com_writex_req *)pSMB;
1581		pSMBW->ByteCount = cpu_to_le16(byte_count);
1582	}
1583
1584	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1585			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1586	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1587	if (rc) {
1588		cifs_dbg(FYI, "Send error in write = %d\n", rc);
1589	} else {
1590		*nbytes = le16_to_cpu(pSMBr->CountHigh);
1591		*nbytes = (*nbytes) << 16;
1592		*nbytes += le16_to_cpu(pSMBr->Count);
1593
1594		/*
1595		 * Mask off high 16 bits when bytes written as returned by the
1596		 * server is greater than bytes requested by the client. Some
1597		 * OS/2 servers are known to set incorrect CountHigh values.
1598		 */
1599		if (*nbytes > count)
1600			*nbytes &= 0xFFFF;
1601	}
1602
1603	cifs_buf_release(pSMB);
1604
1605	/* Note: On -EAGAIN error only caller can retry on handle based calls
1606		since file handle passed in no longer valid */
1607
1608	return rc;
1609}
1610
1611/*
1612 * Check the mid_state and signature on received buffer (if any), and queue the
1613 * workqueue completion task.
1614 */
1615static void
1616cifs_writev_callback(struct mid_q_entry *mid)
1617{
1618	struct cifs_writedata *wdata = mid->callback_data;
1619	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1620	unsigned int written;
1621	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1622	struct cifs_credits credits = { .value = 1, .instance = 0 };
1623
1624	switch (mid->mid_state) {
1625	case MID_RESPONSE_RECEIVED:
1626		wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1627		if (wdata->result != 0)
1628			break;
1629
1630		written = le16_to_cpu(smb->CountHigh);
1631		written <<= 16;
1632		written += le16_to_cpu(smb->Count);
1633		/*
1634		 * Mask off high 16 bits when bytes written as returned
1635		 * by the server is greater than bytes requested by the
1636		 * client. OS/2 servers are known to set incorrect
1637		 * CountHigh values.
1638		 */
1639		if (written > wdata->bytes)
1640			written &= 0xFFFF;
1641
1642		if (written < wdata->bytes)
1643			wdata->result = -ENOSPC;
1644		else
1645			wdata->bytes = written;
1646		break;
1647	case MID_REQUEST_SUBMITTED:
1648	case MID_RETRY_NEEDED:
1649		wdata->result = -EAGAIN;
1650		break;
1651	default:
1652		wdata->result = -EIO;
1653		break;
1654	}
1655
1656	queue_work(cifsiod_wq, &wdata->work);
1657	release_mid(mid);
1658	add_credits(tcon->ses->server, &credits, 0);
1659}
1660
1661/* cifs_async_writev - send an async write, and set up mid to handle result */
1662int
1663cifs_async_writev(struct cifs_writedata *wdata,
1664		  void (*release)(struct kref *kref))
1665{
1666	int rc = -EACCES;
1667	WRITE_REQ *smb = NULL;
1668	int wct;
1669	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1670	struct kvec iov[2];
1671	struct smb_rqst rqst = { };
1672
1673	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1674		wct = 14;
1675	} else {
1676		wct = 12;
1677		if (wdata->offset >> 32 > 0) {
1678			/* can not handle big offset for old srv */
1679			return -EIO;
1680		}
1681	}
1682
1683	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
1684	if (rc)
1685		goto async_writev_out;
1686
1687	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
1688	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
1689
1690	smb->AndXCommand = 0xFF;	/* none */
1691	smb->Fid = wdata->cfile->fid.netfid;
1692	smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
1693	if (wct == 14)
1694		smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
1695	smb->Reserved = 0xFFFFFFFF;
1696	smb->WriteMode = 0;
1697	smb->Remaining = 0;
1698
1699	smb->DataOffset =
1700	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1701
1702	/* 4 for RFC1001 length + 1 for BCC */
1703	iov[0].iov_len = 4;
1704	iov[0].iov_base = smb;
1705	iov[1].iov_len = get_rfc1002_length(smb) + 1;
1706	iov[1].iov_base = (char *)smb + 4;
1707
1708	rqst.rq_iov = iov;
1709	rqst.rq_nvec = 2;
1710	rqst.rq_iter = wdata->iter;
1711	rqst.rq_iter_size = iov_iter_count(&wdata->iter);
1712
1713	cifs_dbg(FYI, "async write at %llu %u bytes\n",
1714		 wdata->offset, wdata->bytes);
1715
1716	smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
1717	smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
1718
1719	if (wct == 14) {
1720		inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
1721		put_bcc(wdata->bytes + 1, &smb->hdr);
1722	} else {
1723		/* wct == 12 */
1724		struct smb_com_writex_req *smbw =
1725				(struct smb_com_writex_req *)smb;
1726		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
1727		put_bcc(wdata->bytes + 5, &smbw->hdr);
1728		iov[1].iov_len += 4; /* pad bigger by four bytes */
1729	}
1730
1731	kref_get(&wdata->refcount);
1732	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
1733			     cifs_writev_callback, NULL, wdata, 0, NULL);
1734
1735	if (rc == 0)
1736		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1737	else
1738		kref_put(&wdata->refcount, release);
1739
1740async_writev_out:
1741	cifs_small_buf_release(smb);
1742	return rc;
1743}
1744
1745int
1746CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
1747	      unsigned int *nbytes, struct kvec *iov, int n_vec)
1748{
1749	int rc;
1750	WRITE_REQ *pSMB = NULL;
1751	int wct;
1752	int smb_hdr_len;
1753	int resp_buf_type = 0;
1754	__u32 pid = io_parms->pid;
1755	__u16 netfid = io_parms->netfid;
1756	__u64 offset = io_parms->offset;
1757	struct cifs_tcon *tcon = io_parms->tcon;
1758	unsigned int count = io_parms->length;
1759	struct kvec rsp_iov;
1760
1761	*nbytes = 0;
1762
1763	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
1764
1765	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1766		wct = 14;
1767	} else {
1768		wct = 12;
1769		if ((offset >> 32) > 0) {
1770			/* can not handle big offset for old srv */
1771			return -EIO;
1772		}
1773	}
1774	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1775	if (rc)
1776		return rc;
1777
1778	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1779	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1780
1781	/* tcon and ses pointer are checked in smb_init */
1782	if (tcon->ses->server == NULL)
1783		return -ECONNABORTED;
1784
1785	pSMB->AndXCommand = 0xFF;	/* none */
1786	pSMB->Fid = netfid;
1787	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1788	if (wct == 14)
1789		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1790	pSMB->Reserved = 0xFFFFFFFF;
1791	pSMB->WriteMode = 0;
1792	pSMB->Remaining = 0;
1793
1794	pSMB->DataOffset =
1795	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1796
1797	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1798	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1799	/* header + 1 byte pad */
1800	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1801	if (wct == 14)
1802		inc_rfc1001_len(pSMB, count + 1);
1803	else /* wct == 12 */
1804		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
1805	if (wct == 14)
1806		pSMB->ByteCount = cpu_to_le16(count + 1);
1807	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1808		struct smb_com_writex_req *pSMBW =
1809				(struct smb_com_writex_req *)pSMB;
1810		pSMBW->ByteCount = cpu_to_le16(count + 5);
1811	}
1812	iov[0].iov_base = pSMB;
1813	if (wct == 14)
1814		iov[0].iov_len = smb_hdr_len + 4;
1815	else /* wct == 12 pad bigger by four bytes */
1816		iov[0].iov_len = smb_hdr_len + 8;
1817
1818	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
1819			  &rsp_iov);
1820	cifs_small_buf_release(pSMB);
1821	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1822	if (rc) {
1823		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
1824	} else if (resp_buf_type == 0) {
1825		/* presumably this can not happen, but best to be safe */
1826		rc = -EIO;
1827	} else {
1828		WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
1829		*nbytes = le16_to_cpu(pSMBr->CountHigh);
1830		*nbytes = (*nbytes) << 16;
1831		*nbytes += le16_to_cpu(pSMBr->Count);
1832
1833		/*
1834		 * Mask off high 16 bits when bytes written as returned by the
1835		 * server is greater than bytes requested by the client. OS/2
1836		 * servers are known to set incorrect CountHigh values.
1837		 */
1838		if (*nbytes > count)
1839			*nbytes &= 0xFFFF;
1840	}
1841
1842	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1843
1844	/* Note: On -EAGAIN error only caller can retry on handle based calls
1845		since file handle passed in no longer valid */
1846
1847	return rc;
1848}
1849
1850int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
1851	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
1852	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
1853{
1854	int rc = 0;
1855	LOCK_REQ *pSMB = NULL;
1856	struct kvec iov[2];
1857	struct kvec rsp_iov;
1858	int resp_buf_type;
1859	__u16 count;
1860
1861	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
1862		 num_lock, num_unlock);
1863
1864	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1865	if (rc)
1866		return rc;
1867
1868	pSMB->Timeout = 0;
1869	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
1870	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
1871	pSMB->LockType = lock_type;
1872	pSMB->AndXCommand = 0xFF; /* none */
1873	pSMB->Fid = netfid; /* netfid stays le */
1874
1875	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1876	inc_rfc1001_len(pSMB, count);
1877	pSMB->ByteCount = cpu_to_le16(count);
1878
1879	iov[0].iov_base = (char *)pSMB;
1880	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
1881			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1882	iov[1].iov_base = (char *)buf;
1883	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
1884
1885	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
1886	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
1887			  CIFS_NO_RSP_BUF, &rsp_iov);
1888	cifs_small_buf_release(pSMB);
1889	if (rc)
1890		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
1891
1892	return rc;
1893}
1894
1895int
1896CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
1897	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
1898	    const __u64 offset, const __u32 numUnlock,
1899	    const __u32 numLock, const __u8 lockType,
1900	    const bool waitFlag, const __u8 oplock_level)
1901{
1902	int rc = 0;
1903	LOCK_REQ *pSMB = NULL;
1904/*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1905	int bytes_returned;
1906	int flags = 0;
1907	__u16 count;
1908
1909	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
1910		 (int)waitFlag, numLock);
1911	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1912
1913	if (rc)
1914		return rc;
1915
1916	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1917		/* no response expected */
1918		flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
1919		pSMB->Timeout = 0;
1920	} else if (waitFlag) {
1921		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1922		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1923	} else {
1924		pSMB->Timeout = 0;
1925	}
1926
1927	pSMB->NumberOfLocks = cpu_to_le16(numLock);
1928	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1929	pSMB->LockType = lockType;
1930	pSMB->OplockLevel = oplock_level;
1931	pSMB->AndXCommand = 0xFF;	/* none */
1932	pSMB->Fid = smb_file_id; /* netfid stays le */
1933
1934	if ((numLock != 0) || (numUnlock != 0)) {
1935		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
1936		/* BB where to store pid high? */
1937		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1938		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1939		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1940		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1941		count = sizeof(LOCKING_ANDX_RANGE);
1942	} else {
1943		/* oplock break */
1944		count = 0;
1945	}
1946	inc_rfc1001_len(pSMB, count);
1947	pSMB->ByteCount = cpu_to_le16(count);
1948
1949	if (waitFlag)
1950		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1951			(struct smb_hdr *) pSMB, &bytes_returned);
1952	else
1953		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
1954	cifs_small_buf_release(pSMB);
1955	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
1956	if (rc)
1957		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
1958
1959	/* Note: On -EAGAIN error only caller can retry on handle based calls
1960	since file handle passed in no longer valid */
1961	return rc;
1962}
1963
1964int
1965CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
1966		const __u16 smb_file_id, const __u32 netpid,
1967		const loff_t start_offset, const __u64 len,
1968		struct file_lock *pLockData, const __u16 lock_type,
1969		const bool waitFlag)
1970{
1971	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1972	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1973	struct cifs_posix_lock *parm_data;
1974	int rc = 0;
1975	int timeout = 0;
1976	int bytes_returned = 0;
1977	int resp_buf_type = 0;
1978	__u16 params, param_offset, offset, byte_count, count;
1979	struct kvec iov[1];
1980	struct kvec rsp_iov;
1981
1982	cifs_dbg(FYI, "Posix Lock\n");
1983
1984	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1985
1986	if (rc)
1987		return rc;
1988
1989	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1990
1991	params = 6;
1992	pSMB->MaxSetupCount = 0;
1993	pSMB->Reserved = 0;
1994	pSMB->Flags = 0;
1995	pSMB->Reserved2 = 0;
1996	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1997	offset = param_offset + params;
1998
1999	count = sizeof(struct cifs_posix_lock);
2000	pSMB->MaxParameterCount = cpu_to_le16(2);
2001	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2002	pSMB->SetupCount = 1;
2003	pSMB->Reserved3 = 0;
2004	if (pLockData)
2005		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2006	else
2007		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2008	byte_count = 3 /* pad */  + params + count;
2009	pSMB->DataCount = cpu_to_le16(count);
2010	pSMB->ParameterCount = cpu_to_le16(params);
2011	pSMB->TotalDataCount = pSMB->DataCount;
2012	pSMB->TotalParameterCount = pSMB->ParameterCount;
2013	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2014	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2015	parm_data = (struct cifs_posix_lock *)
2016			(((char *)pSMB) + offset + 4);
2017
2018	parm_data->lock_type = cpu_to_le16(lock_type);
2019	if (waitFlag) {
2020		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2021		parm_data->lock_flags = cpu_to_le16(1);
2022		pSMB->Timeout = cpu_to_le32(-1);
2023	} else
2024		pSMB->Timeout = 0;
2025
2026	parm_data->pid = cpu_to_le32(netpid);
2027	parm_data->start = cpu_to_le64(start_offset);
2028	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2029
2030	pSMB->DataOffset = cpu_to_le16(offset);
2031	pSMB->Fid = smb_file_id;
2032	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2033	pSMB->Reserved4 = 0;
2034	inc_rfc1001_len(pSMB, byte_count);
2035	pSMB->ByteCount = cpu_to_le16(byte_count);
2036	if (waitFlag) {
2037		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2038			(struct smb_hdr *) pSMBr, &bytes_returned);
2039	} else {
2040		iov[0].iov_base = (char *)pSMB;
2041		iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2042		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2043				&resp_buf_type, timeout, &rsp_iov);
2044		pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2045	}
2046	cifs_small_buf_release(pSMB);
2047
2048	if (rc) {
2049		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2050	} else if (pLockData) {
2051		/* lock structure can be returned on get */
2052		__u16 data_offset;
2053		__u16 data_count;
2054		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2055
2056		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2057			rc = -EIO;      /* bad smb */
2058			goto plk_err_exit;
2059		}
2060		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2061		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2062		if (data_count < sizeof(struct cifs_posix_lock)) {
2063			rc = -EIO;
2064			goto plk_err_exit;
2065		}
2066		parm_data = (struct cifs_posix_lock *)
2067			((char *)&pSMBr->hdr.Protocol + data_offset);
2068		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2069			pLockData->fl_type = F_UNLCK;
2070		else {
2071			if (parm_data->lock_type ==
2072					cpu_to_le16(CIFS_RDLCK))
2073				pLockData->fl_type = F_RDLCK;
2074			else if (parm_data->lock_type ==
2075					cpu_to_le16(CIFS_WRLCK))
2076				pLockData->fl_type = F_WRLCK;
2077
2078			pLockData->fl_start = le64_to_cpu(parm_data->start);
2079			pLockData->fl_end = pLockData->fl_start +
2080				(le64_to_cpu(parm_data->length) ?
2081				 le64_to_cpu(parm_data->length) - 1 : 0);
2082			pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2083		}
2084	}
2085
2086plk_err_exit:
2087	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2088
2089	/* Note: On -EAGAIN error only caller can retry on handle based calls
2090	   since file handle passed in no longer valid */
2091
2092	return rc;
2093}
2094
2095
2096int
2097CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2098{
2099	int rc = 0;
2100	CLOSE_REQ *pSMB = NULL;
2101	cifs_dbg(FYI, "In CIFSSMBClose\n");
2102
2103/* do not retry on dead session on close */
2104	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2105	if (rc == -EAGAIN)
2106		return 0;
2107	if (rc)
2108		return rc;
2109
2110	pSMB->FileID = (__u16) smb_file_id;
2111	pSMB->LastWriteTime = 0xFFFFFFFF;
2112	pSMB->ByteCount = 0;
2113	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2114	cifs_small_buf_release(pSMB);
2115	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2116	if (rc) {
2117		if (rc != -EINTR) {
2118			/* EINTR is expected when user ctl-c to kill app */
2119			cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2120		}
2121	}
2122
2123	/* Since session is dead, file will be closed on server already */
2124	if (rc == -EAGAIN)
2125		rc = 0;
2126
2127	return rc;
2128}
2129
2130int
2131CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2132{
2133	int rc = 0;
2134	FLUSH_REQ *pSMB = NULL;
2135	cifs_dbg(FYI, "In CIFSSMBFlush\n");
2136
2137	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2138	if (rc)
2139		return rc;
2140
2141	pSMB->FileID = (__u16) smb_file_id;
2142	pSMB->ByteCount = 0;
2143	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2144	cifs_small_buf_release(pSMB);
2145	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2146	if (rc)
2147		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2148
2149	return rc;
2150}
2151
2152int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2153		  struct dentry *source_dentry,
2154		  const char *from_name, const char *to_name,
2155		  struct cifs_sb_info *cifs_sb)
2156{
2157	int rc = 0;
2158	RENAME_REQ *pSMB = NULL;
2159	RENAME_RSP *pSMBr = NULL;
2160	int bytes_returned;
2161	int name_len, name_len2;
2162	__u16 count;
2163	int remap = cifs_remap(cifs_sb);
2164
2165	cifs_dbg(FYI, "In CIFSSMBRename\n");
2166renameRetry:
2167	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2168		      (void **) &pSMBr);
2169	if (rc)
2170		return rc;
2171
2172	pSMB->BufferFormat = 0x04;
2173	pSMB->SearchAttributes =
2174	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2175			ATTR_DIRECTORY);
2176
2177	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2178		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2179					      from_name, PATH_MAX,
2180					      cifs_sb->local_nls, remap);
2181		name_len++;	/* trailing null */
2182		name_len *= 2;
2183		pSMB->OldFileName[name_len] = 0x04;	/* pad */
2184	/* protocol requires ASCII signature byte on Unicode string */
2185		pSMB->OldFileName[name_len + 1] = 0x00;
2186		name_len2 =
2187		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2188				       to_name, PATH_MAX, cifs_sb->local_nls,
2189				       remap);
2190		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2191		name_len2 *= 2;	/* convert to bytes */
2192	} else {
2193		name_len = copy_path_name(pSMB->OldFileName, from_name);
2194		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2195		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2196		name_len2++;	/* signature byte */
2197	}
2198
2199	count = 1 /* 1st signature byte */  + name_len + name_len2;
2200	inc_rfc1001_len(pSMB, count);
2201	pSMB->ByteCount = cpu_to_le16(count);
2202
2203	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2204			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2205	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2206	if (rc)
2207		cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2208
2209	cifs_buf_release(pSMB);
2210
2211	if (rc == -EAGAIN)
2212		goto renameRetry;
2213
2214	return rc;
2215}
2216
2217int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2218		int netfid, const char *target_name,
2219		const struct nls_table *nls_codepage, int remap)
2220{
2221	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2222	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2223	struct set_file_rename *rename_info;
2224	char *data_offset;
2225	char dummy_string[30];
2226	int rc = 0;
2227	int bytes_returned = 0;
2228	int len_of_str;
2229	__u16 params, param_offset, offset, count, byte_count;
2230
2231	cifs_dbg(FYI, "Rename to File by handle\n");
2232	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2233			(void **) &pSMBr);
2234	if (rc)
2235		return rc;
2236
2237	params = 6;
2238	pSMB->MaxSetupCount = 0;
2239	pSMB->Reserved = 0;
2240	pSMB->Flags = 0;
2241	pSMB->Timeout = 0;
2242	pSMB->Reserved2 = 0;
2243	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2244	offset = param_offset + params;
2245
2246	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2247	data_offset = (char *)(pSMB) + offset + 4;
2248	rename_info = (struct set_file_rename *) data_offset;
2249	pSMB->MaxParameterCount = cpu_to_le16(2);
2250	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2251	pSMB->SetupCount = 1;
2252	pSMB->Reserved3 = 0;
2253	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2254	byte_count = 3 /* pad */  + params;
2255	pSMB->ParameterCount = cpu_to_le16(params);
2256	pSMB->TotalParameterCount = pSMB->ParameterCount;
2257	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2258	pSMB->DataOffset = cpu_to_le16(offset);
2259	/* construct random name ".cifs_tmp<inodenum><mid>" */
2260	rename_info->overwrite = cpu_to_le32(1);
2261	rename_info->root_fid  = 0;
2262	/* unicode only call */
2263	if (target_name == NULL) {
2264		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2265		len_of_str =
2266			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2267					dummy_string, 24, nls_codepage, remap);
2268	} else {
2269		len_of_str =
2270			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2271					target_name, PATH_MAX, nls_codepage,
2272					remap);
2273	}
2274	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2275	count = sizeof(struct set_file_rename) + (2 * len_of_str);
2276	byte_count += count;
2277	pSMB->DataCount = cpu_to_le16(count);
2278	pSMB->TotalDataCount = pSMB->DataCount;
2279	pSMB->Fid = netfid;
2280	pSMB->InformationLevel =
2281		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2282	pSMB->Reserved4 = 0;
2283	inc_rfc1001_len(pSMB, byte_count);
2284	pSMB->ByteCount = cpu_to_le16(byte_count);
2285	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2286			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2287	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2288	if (rc)
2289		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2290			 rc);
2291
2292	cifs_buf_release(pSMB);
2293
2294	/* Note: On -EAGAIN error only caller can retry on handle based calls
2295		since file handle passed in no longer valid */
2296
2297	return rc;
2298}
2299
2300int
2301CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2302	    const char *fromName, const __u16 target_tid, const char *toName,
2303	    const int flags, const struct nls_table *nls_codepage, int remap)
2304{
2305	int rc = 0;
2306	COPY_REQ *pSMB = NULL;
2307	COPY_RSP *pSMBr = NULL;
2308	int bytes_returned;
2309	int name_len, name_len2;
2310	__u16 count;
2311
2312	cifs_dbg(FYI, "In CIFSSMBCopy\n");
2313copyRetry:
2314	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2315			(void **) &pSMBr);
2316	if (rc)
2317		return rc;
2318
2319	pSMB->BufferFormat = 0x04;
2320	pSMB->Tid2 = target_tid;
2321
2322	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2323
2324	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2325		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2326					      fromName, PATH_MAX, nls_codepage,
2327					      remap);
2328		name_len++;     /* trailing null */
2329		name_len *= 2;
2330		pSMB->OldFileName[name_len] = 0x04;     /* pad */
2331		/* protocol requires ASCII signature byte on Unicode string */
2332		pSMB->OldFileName[name_len + 1] = 0x00;
2333		name_len2 =
2334		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2335				       toName, PATH_MAX, nls_codepage, remap);
2336		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2337		name_len2 *= 2; /* convert to bytes */
2338	} else {
2339		name_len = copy_path_name(pSMB->OldFileName, fromName);
2340		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2341		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2342		name_len2++;    /* signature byte */
2343	}
2344
2345	count = 1 /* 1st signature byte */  + name_len + name_len2;
2346	inc_rfc1001_len(pSMB, count);
2347	pSMB->ByteCount = cpu_to_le16(count);
2348
2349	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2350		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
2351	if (rc) {
2352		cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2353			 rc, le16_to_cpu(pSMBr->CopyCount));
2354	}
2355	cifs_buf_release(pSMB);
2356
2357	if (rc == -EAGAIN)
2358		goto copyRetry;
2359
2360	return rc;
2361}
2362
2363int
2364CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2365		      const char *fromName, const char *toName,
2366		      const struct nls_table *nls_codepage, int remap)
2367{
2368	TRANSACTION2_SPI_REQ *pSMB = NULL;
2369	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2370	char *data_offset;
2371	int name_len;
2372	int name_len_target;
2373	int rc = 0;
2374	int bytes_returned = 0;
2375	__u16 params, param_offset, offset, byte_count;
2376
2377	cifs_dbg(FYI, "In Symlink Unix style\n");
2378createSymLinkRetry:
2379	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2380		      (void **) &pSMBr);
2381	if (rc)
2382		return rc;
2383
2384	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2385		name_len =
2386		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2387				/* find define for this maxpathcomponent */
2388					PATH_MAX, nls_codepage, remap);
2389		name_len++;	/* trailing null */
2390		name_len *= 2;
2391
2392	} else {
2393		name_len = copy_path_name(pSMB->FileName, fromName);
2394	}
2395	params = 6 + name_len;
2396	pSMB->MaxSetupCount = 0;
2397	pSMB->Reserved = 0;
2398	pSMB->Flags = 0;
2399	pSMB->Timeout = 0;
2400	pSMB->Reserved2 = 0;
2401	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2402				InformationLevel) - 4;
2403	offset = param_offset + params;
2404
2405	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2406	data_offset = (char *)pSMB + offset + 4;
2407	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2408		name_len_target =
2409		    cifsConvertToUTF16((__le16 *) data_offset, toName,
2410				/* find define for this maxpathcomponent */
2411					PATH_MAX, nls_codepage, remap);
2412		name_len_target++;	/* trailing null */
2413		name_len_target *= 2;
2414	} else {
2415		name_len_target = copy_path_name(data_offset, toName);
2416	}
2417
2418	pSMB->MaxParameterCount = cpu_to_le16(2);
2419	/* BB find exact max on data count below from sess */
2420	pSMB->MaxDataCount = cpu_to_le16(1000);
2421	pSMB->SetupCount = 1;
2422	pSMB->Reserved3 = 0;
2423	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2424	byte_count = 3 /* pad */  + params + name_len_target;
2425	pSMB->DataCount = cpu_to_le16(name_len_target);
2426	pSMB->ParameterCount = cpu_to_le16(params);
2427	pSMB->TotalDataCount = pSMB->DataCount;
2428	pSMB->TotalParameterCount = pSMB->ParameterCount;
2429	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2430	pSMB->DataOffset = cpu_to_le16(offset);
2431	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2432	pSMB->Reserved4 = 0;
2433	inc_rfc1001_len(pSMB, byte_count);
2434	pSMB->ByteCount = cpu_to_le16(byte_count);
2435	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2436			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2437	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2438	if (rc)
2439		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2440			 rc);
2441
2442	cifs_buf_release(pSMB);
2443
2444	if (rc == -EAGAIN)
2445		goto createSymLinkRetry;
2446
2447	return rc;
2448}
2449
2450int
2451CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2452		       const char *fromName, const char *toName,
2453		       const struct nls_table *nls_codepage, int remap)
2454{
2455	TRANSACTION2_SPI_REQ *pSMB = NULL;
2456	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2457	char *data_offset;
2458	int name_len;
2459	int name_len_target;
2460	int rc = 0;
2461	int bytes_returned = 0;
2462	__u16 params, param_offset, offset, byte_count;
2463
2464	cifs_dbg(FYI, "In Create Hard link Unix style\n");
2465createHardLinkRetry:
2466	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2467		      (void **) &pSMBr);
2468	if (rc)
2469		return rc;
2470
2471	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2472		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2473					      PATH_MAX, nls_codepage, remap);
2474		name_len++;	/* trailing null */
2475		name_len *= 2;
2476
2477	} else {
2478		name_len = copy_path_name(pSMB->FileName, toName);
2479	}
2480	params = 6 + name_len;
2481	pSMB->MaxSetupCount = 0;
2482	pSMB->Reserved = 0;
2483	pSMB->Flags = 0;
2484	pSMB->Timeout = 0;
2485	pSMB->Reserved2 = 0;
2486	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2487				InformationLevel) - 4;
2488	offset = param_offset + params;
2489
2490	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2491	data_offset = (char *)pSMB + offset + 4;
2492	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2493		name_len_target =
2494		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
2495				       PATH_MAX, nls_codepage, remap);
2496		name_len_target++;	/* trailing null */
2497		name_len_target *= 2;
2498	} else {
2499		name_len_target = copy_path_name(data_offset, fromName);
2500	}
2501
2502	pSMB->MaxParameterCount = cpu_to_le16(2);
2503	/* BB find exact max on data count below from sess*/
2504	pSMB->MaxDataCount = cpu_to_le16(1000);
2505	pSMB->SetupCount = 1;
2506	pSMB->Reserved3 = 0;
2507	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2508	byte_count = 3 /* pad */  + params + name_len_target;
2509	pSMB->ParameterCount = cpu_to_le16(params);
2510	pSMB->TotalParameterCount = pSMB->ParameterCount;
2511	pSMB->DataCount = cpu_to_le16(name_len_target);
2512	pSMB->TotalDataCount = pSMB->DataCount;
2513	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2514	pSMB->DataOffset = cpu_to_le16(offset);
2515	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2516	pSMB->Reserved4 = 0;
2517	inc_rfc1001_len(pSMB, byte_count);
2518	pSMB->ByteCount = cpu_to_le16(byte_count);
2519	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2520			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2521	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2522	if (rc)
2523		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2524			 rc);
2525
2526	cifs_buf_release(pSMB);
2527	if (rc == -EAGAIN)
2528		goto createHardLinkRetry;
2529
2530	return rc;
2531}
2532
2533int CIFSCreateHardLink(const unsigned int xid,
2534		       struct cifs_tcon *tcon,
2535		       struct dentry *source_dentry,
2536		       const char *from_name, const char *to_name,
2537		       struct cifs_sb_info *cifs_sb)
2538{
2539	int rc = 0;
2540	NT_RENAME_REQ *pSMB = NULL;
2541	RENAME_RSP *pSMBr = NULL;
2542	int bytes_returned;
2543	int name_len, name_len2;
2544	__u16 count;
2545	int remap = cifs_remap(cifs_sb);
2546
2547	cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2548winCreateHardLinkRetry:
2549
2550	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2551		      (void **) &pSMBr);
2552	if (rc)
2553		return rc;
2554
2555	pSMB->SearchAttributes =
2556	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2557			ATTR_DIRECTORY);
2558	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2559	pSMB->ClusterCount = 0;
2560
2561	pSMB->BufferFormat = 0x04;
2562
2563	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2564		name_len =
2565		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2566				       PATH_MAX, cifs_sb->local_nls, remap);
2567		name_len++;	/* trailing null */
2568		name_len *= 2;
2569
2570		/* protocol specifies ASCII buffer format (0x04) for unicode */
2571		pSMB->OldFileName[name_len] = 0x04;
2572		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2573		name_len2 =
2574		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2575				       to_name, PATH_MAX, cifs_sb->local_nls,
2576				       remap);
2577		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2578		name_len2 *= 2;	/* convert to bytes */
2579	} else {
2580		name_len = copy_path_name(pSMB->OldFileName, from_name);
2581		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
2582		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2583		name_len2++;	/* signature byte */
2584	}
2585
2586	count = 1 /* string type byte */  + name_len + name_len2;
2587	inc_rfc1001_len(pSMB, count);
2588	pSMB->ByteCount = cpu_to_le16(count);
2589
2590	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2591			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2592	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2593	if (rc)
2594		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
2595
2596	cifs_buf_release(pSMB);
2597	if (rc == -EAGAIN)
2598		goto winCreateHardLinkRetry;
2599
2600	return rc;
2601}
2602
2603int
2604CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2605			const unsigned char *searchName, char **symlinkinfo,
2606			const struct nls_table *nls_codepage, int remap)
2607{
2608/* SMB_QUERY_FILE_UNIX_LINK */
2609	TRANSACTION2_QPI_REQ *pSMB = NULL;
2610	TRANSACTION2_QPI_RSP *pSMBr = NULL;
2611	int rc = 0;
2612	int bytes_returned;
2613	int name_len;
2614	__u16 params, byte_count;
2615	char *data_start;
2616
2617	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
2618
2619querySymLinkRetry:
2620	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2621		      (void **) &pSMBr);
2622	if (rc)
2623		return rc;
2624
2625	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2626		name_len =
2627			cifsConvertToUTF16((__le16 *) pSMB->FileName,
2628					   searchName, PATH_MAX, nls_codepage,
2629					   remap);
2630		name_len++;	/* trailing null */
2631		name_len *= 2;
2632	} else {
2633		name_len = copy_path_name(pSMB->FileName, searchName);
2634	}
2635
2636	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2637	pSMB->TotalDataCount = 0;
2638	pSMB->MaxParameterCount = cpu_to_le16(2);
2639	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2640	pSMB->MaxSetupCount = 0;
2641	pSMB->Reserved = 0;
2642	pSMB->Flags = 0;
2643	pSMB->Timeout = 0;
2644	pSMB->Reserved2 = 0;
2645	pSMB->ParameterOffset = cpu_to_le16(offsetof(
2646	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2647	pSMB->DataCount = 0;
2648	pSMB->DataOffset = 0;
2649	pSMB->SetupCount = 1;
2650	pSMB->Reserved3 = 0;
2651	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2652	byte_count = params + 1 /* pad */ ;
2653	pSMB->TotalParameterCount = cpu_to_le16(params);
2654	pSMB->ParameterCount = pSMB->TotalParameterCount;
2655	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2656	pSMB->Reserved4 = 0;
2657	inc_rfc1001_len(pSMB, byte_count);
2658	pSMB->ByteCount = cpu_to_le16(byte_count);
2659
2660	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2661			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2662	if (rc) {
2663		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
2664	} else {
2665		/* decode response */
2666
2667		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2668		/* BB also check enough total bytes returned */
2669		if (rc || get_bcc(&pSMBr->hdr) < 2)
2670			rc = -EIO;
2671		else {
2672			bool is_unicode;
2673			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2674
2675			data_start = ((char *) &pSMBr->hdr.Protocol) +
2676					   le16_to_cpu(pSMBr->t2.DataOffset);
2677
2678			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2679				is_unicode = true;
2680			else
2681				is_unicode = false;
2682
2683			/* BB FIXME investigate remapping reserved chars here */
2684			*symlinkinfo = cifs_strndup_from_utf16(data_start,
2685					count, is_unicode, nls_codepage);
2686			if (!*symlinkinfo)
2687				rc = -ENOMEM;
2688		}
2689	}
2690	cifs_buf_release(pSMB);
2691	if (rc == -EAGAIN)
2692		goto querySymLinkRetry;
2693	return rc;
2694}
2695
2696int cifs_query_reparse_point(const unsigned int xid,
2697			     struct cifs_tcon *tcon,
2698			     struct cifs_sb_info *cifs_sb,
2699			     const char *full_path,
2700			     u32 *tag, struct kvec *rsp,
2701			     int *rsp_buftype)
2702{
2703	struct cifs_open_parms oparms;
2704	TRANSACT_IOCTL_REQ *io_req = NULL;
2705	TRANSACT_IOCTL_RSP *io_rsp = NULL;
2706	struct cifs_fid fid;
2707	__u32 data_offset, data_count;
2708	__u8 *start, *end;
2709	int io_rsp_len;
2710	int oplock = 0;
2711	int rc;
2712
2713	cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
2714
2715	if (cap_unix(tcon->ses))
2716		return -EOPNOTSUPP;
2717
2718	oparms = (struct cifs_open_parms) {
2719		.tcon = tcon,
2720		.cifs_sb = cifs_sb,
2721		.desired_access = FILE_READ_ATTRIBUTES,
2722		.create_options = cifs_create_options(cifs_sb,
2723						      OPEN_REPARSE_POINT),
2724		.disposition = FILE_OPEN,
2725		.path = full_path,
2726		.fid = &fid,
2727	};
2728
2729	rc = CIFS_open(xid, &oparms, &oplock, NULL);
2730	if (rc)
2731		return rc;
2732
2733	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,
2734		      (void **)&io_req, (void **)&io_rsp);
2735	if (rc)
2736		goto error;
2737
2738	io_req->TotalParameterCount = 0;
2739	io_req->TotalDataCount = 0;
2740	io_req->MaxParameterCount = cpu_to_le32(2);
2741	/* BB find exact data count max from sess structure BB */
2742	io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
2743	io_req->MaxSetupCount = 4;
2744	io_req->Reserved = 0;
2745	io_req->ParameterOffset = 0;
2746	io_req->DataCount = 0;
2747	io_req->DataOffset = 0;
2748	io_req->SetupCount = 4;
2749	io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2750	io_req->ParameterCount = io_req->TotalParameterCount;
2751	io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2752	io_req->IsFsctl = 1;
2753	io_req->IsRootFlag = 0;
2754	io_req->Fid = fid.netfid;
2755	io_req->ByteCount = 0;
2756
2757	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req,
2758			 (struct smb_hdr *)io_rsp, &io_rsp_len, 0);
2759	if (rc)
2760		goto error;
2761
2762	data_offset = le32_to_cpu(io_rsp->DataOffset);
2763	data_count = le32_to_cpu(io_rsp->DataCount);
2764	if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||
2765	    !data_count || data_count > 2048) {
2766		rc = -EIO;
2767		goto error;
2768	}
2769
2770	end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
2771	start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
2772	if (start >= end) {
2773		rc = -EIO;
2774		goto error;
2775	}
2776
2777	*tag = le32_to_cpu(((struct reparse_data_buffer *)start)->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 conver 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 cifs_ntsd **acl_inf, __u32 *pbuflen)
3379{
3380	int rc = 0;
3381	int buf_type = 0;
3382	QUERY_SEC_DESC_REQ *pSMB;
3383	struct kvec iov[1];
3384	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);
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 cifs_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 cifs_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 asterik 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_no_reconnect(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)
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->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 */
5848	if (ea_name)
5849		strncpy(parm_data->list.name, ea_name, name_len);
5850	parm_data->list.name[name_len] = '\0';
5851	parm_data->list.value_len = cpu_to_le16(ea_value_len);
5852	/* caller ensures that ea_value_len is less than 64K but
5853	we need to ensure that it fits within the smb */
5854
5855	/*BB add length check to see if it would fit in
5856	     negotiated SMB buffer size BB */
5857	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
5858	if (ea_value_len)
5859		memcpy(parm_data->list.name + name_len + 1,
5860		       ea_value, ea_value_len);
5861
5862	pSMB->TotalDataCount = pSMB->DataCount;
5863	pSMB->ParameterCount = cpu_to_le16(params);
5864	pSMB->TotalParameterCount = pSMB->ParameterCount;
5865	pSMB->Reserved4 = 0;
5866	inc_rfc1001_len(pSMB, byte_count);
5867	pSMB->ByteCount = cpu_to_le16(byte_count);
5868	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5869			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5870	if (rc)
5871		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
5872
5873	cifs_buf_release(pSMB);
5874
5875	if (rc == -EAGAIN)
5876		goto SetEARetry;
5877
5878	return rc;
5879}
5880#endif
5881