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