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