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