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)1461 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1462 {
1463 	int length;
1464 	struct cifs_readdata *rdata = mid->callback_data;
1465 
1466 	length = cifs_discard_remaining_data(server);
1467 	dequeue_mid(mid, rdata->result);
1468 	mid->resp_buf = server->smallbuf;
1469 	server->smallbuf = NULL;
1470 	return length;
1471 }
1472 
1473 int
cifs_readv_receive(struct TCP_Server_Info * server,struct mid_q_entry * mid)1474 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1475 {
1476 	int length, len;
1477 	unsigned int data_offset, data_len;
1478 	struct cifs_readdata *rdata = mid->callback_data;
1479 	char *buf = server->smallbuf;
1480 	unsigned int buflen = server->pdu_size +
1481 		server->vals->header_preamble_size;
1482 	bool use_rdma_mr = false;
1483 
1484 	cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1485 		 __func__, mid->mid, rdata->offset, rdata->bytes);
1486 
1487 	/*
1488 	 * read the rest of READ_RSP header (sans Data array), or whatever we
1489 	 * can if there's not enough data. At this point, we've read down to
1490 	 * the Mid.
1491 	 */
1492 	len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1493 							HEADER_SIZE(server) + 1;
1494 
1495 	length = cifs_read_from_socket(server,
1496 				       buf + HEADER_SIZE(server) - 1, len);
1497 	if (length < 0)
1498 		return length;
1499 	server->total_read += length;
1500 
1501 	if (server->ops->is_session_expired &&
1502 	    server->ops->is_session_expired(buf)) {
1503 		cifs_reconnect(server);
1504 		wake_up(&server->response_q);
1505 		return -1;
1506 	}
1507 
1508 	if (server->ops->is_status_pending &&
1509 	    server->ops->is_status_pending(buf, server, 0)) {
1510 		cifs_discard_remaining_data(server);
1511 		return -1;
1512 	}
1513 
1514 	/* Was the SMB read successful? */
1515 	rdata->result = server->ops->map_error(buf, false);
1516 	if (rdata->result != 0) {
1517 		cifs_dbg(FYI, "%s: server returned error %d\n",
1518 			 __func__, rdata->result);
1519 		return cifs_readv_discard(server, mid);
1520 	}
1521 
1522 	/* Is there enough to get to the rest of the READ_RSP header? */
1523 	if (server->total_read < server->vals->read_rsp_size) {
1524 		cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1525 			 __func__, server->total_read,
1526 			 server->vals->read_rsp_size);
1527 		rdata->result = -EIO;
1528 		return cifs_readv_discard(server, mid);
1529 	}
1530 
1531 	data_offset = server->ops->read_data_offset(buf) +
1532 		server->vals->header_preamble_size;
1533 	if (data_offset < server->total_read) {
1534 		/*
1535 		 * win2k8 sometimes sends an offset of 0 when the read
1536 		 * is beyond the EOF. Treat it as if the data starts just after
1537 		 * the header.
1538 		 */
1539 		cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1540 			 __func__, data_offset);
1541 		data_offset = server->total_read;
1542 	} else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1543 		/* data_offset is beyond the end of smallbuf */
1544 		cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1545 			 __func__, data_offset);
1546 		rdata->result = -EIO;
1547 		return cifs_readv_discard(server, mid);
1548 	}
1549 
1550 	cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1551 		 __func__, server->total_read, data_offset);
1552 
1553 	len = data_offset - server->total_read;
1554 	if (len > 0) {
1555 		/* read any junk before data into the rest of smallbuf */
1556 		length = cifs_read_from_socket(server,
1557 					       buf + server->total_read, len);
1558 		if (length < 0)
1559 			return length;
1560 		server->total_read += length;
1561 	}
1562 
1563 	/* set up first iov for signature check */
1564 	rdata->iov[0].iov_base = buf;
1565 	rdata->iov[0].iov_len = 4;
1566 	rdata->iov[1].iov_base = buf + 4;
1567 	rdata->iov[1].iov_len = server->total_read - 4;
1568 	cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1569 		 rdata->iov[0].iov_base, server->total_read);
1570 
1571 	/* how much data is in the response? */
1572 #ifdef CONFIG_CIFS_SMB_DIRECT
1573 	use_rdma_mr = rdata->mr;
1574 #endif
1575 	data_len = server->ops->read_data_length(buf, use_rdma_mr);
1576 	if (!use_rdma_mr && (data_offset + data_len > buflen)) {
1577 		/* data_len is corrupt -- discard frame */
1578 		rdata->result = -EIO;
1579 		return cifs_readv_discard(server, mid);
1580 	}
1581 
1582 	length = rdata->read_into_pages(server, rdata, data_len);
1583 	if (length < 0)
1584 		return length;
1585 
1586 	server->total_read += length;
1587 
1588 	cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1589 		 server->total_read, buflen, data_len);
1590 
1591 	/* discard anything left over */
1592 	if (server->total_read < buflen)
1593 		return cifs_readv_discard(server, mid);
1594 
1595 	dequeue_mid(mid, false);
1596 	mid->resp_buf = server->smallbuf;
1597 	server->smallbuf = NULL;
1598 	return length;
1599 }
1600 
1601 static void
cifs_readv_callback(struct mid_q_entry * mid)1602 cifs_readv_callback(struct mid_q_entry *mid)
1603 {
1604 	struct cifs_readdata *rdata = mid->callback_data;
1605 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1606 	struct TCP_Server_Info *server = tcon->ses->server;
1607 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1608 				 .rq_nvec = 2,
1609 				 .rq_pages = rdata->pages,
1610 				 .rq_npages = rdata->nr_pages,
1611 				 .rq_pagesz = rdata->pagesz,
1612 				 .rq_tailsz = rdata->tailsz };
1613 
1614 	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1615 		 __func__, mid->mid, mid->mid_state, rdata->result,
1616 		 rdata->bytes);
1617 
1618 	switch (mid->mid_state) {
1619 	case MID_RESPONSE_RECEIVED:
1620 		/* result already set, check signature */
1621 		if (server->sign) {
1622 			int rc = 0;
1623 
1624 			rc = cifs_verify_signature(&rqst, server,
1625 						  mid->sequence_number);
1626 			if (rc)
1627 				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1628 					 rc);
1629 		}
1630 		/* FIXME: should this be counted toward the initiating task? */
1631 		task_io_account_read(rdata->got_bytes);
1632 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1633 		break;
1634 	case MID_REQUEST_SUBMITTED:
1635 	case MID_RETRY_NEEDED:
1636 		rdata->result = -EAGAIN;
1637 		if (server->sign && rdata->got_bytes)
1638 			/* reset bytes number since we can not check a sign */
1639 			rdata->got_bytes = 0;
1640 		/* FIXME: should this be counted toward the initiating task? */
1641 		task_io_account_read(rdata->got_bytes);
1642 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1643 		break;
1644 	default:
1645 		rdata->result = -EIO;
1646 	}
1647 
1648 	queue_work(cifsiod_wq, &rdata->work);
1649 	DeleteMidQEntry(mid);
1650 	add_credits(server, 1, 0);
1651 }
1652 
1653 /* cifs_async_readv - send an async write, and set up mid to handle result */
1654 int
cifs_async_readv(struct cifs_readdata * rdata)1655 cifs_async_readv(struct cifs_readdata *rdata)
1656 {
1657 	int rc;
1658 	READ_REQ *smb = NULL;
1659 	int wct;
1660 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1661 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1662 				 .rq_nvec = 2 };
1663 
1664 	cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1665 		 __func__, rdata->offset, rdata->bytes);
1666 
1667 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1668 		wct = 12;
1669 	else {
1670 		wct = 10; /* old style read */
1671 		if ((rdata->offset >> 32) > 0)  {
1672 			/* can not handle this big offset for old */
1673 			return -EIO;
1674 		}
1675 	}
1676 
1677 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1678 	if (rc)
1679 		return rc;
1680 
1681 	smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1682 	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1683 
1684 	smb->AndXCommand = 0xFF;	/* none */
1685 	smb->Fid = rdata->cfile->fid.netfid;
1686 	smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1687 	if (wct == 12)
1688 		smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1689 	smb->Remaining = 0;
1690 	smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1691 	smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1692 	if (wct == 12)
1693 		smb->ByteCount = 0;
1694 	else {
1695 		/* old style read */
1696 		struct smb_com_readx_req *smbr =
1697 			(struct smb_com_readx_req *)smb;
1698 		smbr->ByteCount = 0;
1699 	}
1700 
1701 	/* 4 for RFC1001 length + 1 for BCC */
1702 	rdata->iov[0].iov_base = smb;
1703 	rdata->iov[0].iov_len = 4;
1704 	rdata->iov[1].iov_base = (char *)smb + 4;
1705 	rdata->iov[1].iov_len = get_rfc1002_length(smb);
1706 
1707 	kref_get(&rdata->refcount);
1708 	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1709 			     cifs_readv_callback, NULL, rdata, 0);
1710 
1711 	if (rc == 0)
1712 		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1713 	else
1714 		kref_put(&rdata->refcount, cifs_readdata_release);
1715 
1716 	cifs_small_buf_release(smb);
1717 	return rc;
1718 }
1719 
1720 int
CIFSSMBRead(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,char ** buf,int * pbuf_type)1721 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1722 	    unsigned int *nbytes, char **buf, int *pbuf_type)
1723 {
1724 	int rc = -EACCES;
1725 	READ_REQ *pSMB = NULL;
1726 	READ_RSP *pSMBr = NULL;
1727 	char *pReadData = NULL;
1728 	int wct;
1729 	int resp_buf_type = 0;
1730 	struct kvec iov[1];
1731 	struct kvec rsp_iov;
1732 	__u32 pid = io_parms->pid;
1733 	__u16 netfid = io_parms->netfid;
1734 	__u64 offset = io_parms->offset;
1735 	struct cifs_tcon *tcon = io_parms->tcon;
1736 	unsigned int count = io_parms->length;
1737 
1738 	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1739 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1740 		wct = 12;
1741 	else {
1742 		wct = 10; /* old style read */
1743 		if ((offset >> 32) > 0)  {
1744 			/* can not handle this big offset for old */
1745 			return -EIO;
1746 		}
1747 	}
1748 
1749 	*nbytes = 0;
1750 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1751 	if (rc)
1752 		return rc;
1753 
1754 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1755 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1756 
1757 	/* tcon and ses pointer are checked in smb_init */
1758 	if (tcon->ses->server == NULL)
1759 		return -ECONNABORTED;
1760 
1761 	pSMB->AndXCommand = 0xFF;       /* none */
1762 	pSMB->Fid = netfid;
1763 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1764 	if (wct == 12)
1765 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1766 
1767 	pSMB->Remaining = 0;
1768 	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1769 	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1770 	if (wct == 12)
1771 		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1772 	else {
1773 		/* old style read */
1774 		struct smb_com_readx_req *pSMBW =
1775 			(struct smb_com_readx_req *)pSMB;
1776 		pSMBW->ByteCount = 0;
1777 	}
1778 
1779 	iov[0].iov_base = (char *)pSMB;
1780 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1781 	rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1782 			  CIFS_LOG_ERROR, &rsp_iov);
1783 	cifs_small_buf_release(pSMB);
1784 	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1785 	pSMBr = (READ_RSP *)rsp_iov.iov_base;
1786 	if (rc) {
1787 		cifs_dbg(VFS, "Send error in read = %d\n", rc);
1788 	} else {
1789 		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1790 		data_length = data_length << 16;
1791 		data_length += le16_to_cpu(pSMBr->DataLength);
1792 		*nbytes = data_length;
1793 
1794 		/*check that DataLength would not go beyond end of SMB */
1795 		if ((data_length > CIFSMaxBufSize)
1796 				|| (data_length > count)) {
1797 			cifs_dbg(FYI, "bad length %d for count %d\n",
1798 				 data_length, count);
1799 			rc = -EIO;
1800 			*nbytes = 0;
1801 		} else {
1802 			pReadData = (char *) (&pSMBr->hdr.Protocol) +
1803 					le16_to_cpu(pSMBr->DataOffset);
1804 /*			if (rc = copy_to_user(buf, pReadData, data_length)) {
1805 				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1806 				rc = -EFAULT;
1807 			}*/ /* can not use copy_to_user when using page cache*/
1808 			if (*buf)
1809 				memcpy(*buf, pReadData, data_length);
1810 		}
1811 	}
1812 
1813 	if (*buf) {
1814 		free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1815 	} else if (resp_buf_type != CIFS_NO_BUFFER) {
1816 		/* return buffer to caller to free */
1817 		*buf = rsp_iov.iov_base;
1818 		if (resp_buf_type == CIFS_SMALL_BUFFER)
1819 			*pbuf_type = CIFS_SMALL_BUFFER;
1820 		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1821 			*pbuf_type = CIFS_LARGE_BUFFER;
1822 	} /* else no valid buffer on return - leave as null */
1823 
1824 	/* Note: On -EAGAIN error only caller can retry on handle based calls
1825 		since file handle passed in no longer valid */
1826 	return rc;
1827 }
1828 
1829 
1830 int
CIFSSMBWrite(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,const char * buf)1831 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1832 	     unsigned int *nbytes, const char *buf)
1833 {
1834 	int rc = -EACCES;
1835 	WRITE_REQ *pSMB = NULL;
1836 	WRITE_RSP *pSMBr = NULL;
1837 	int bytes_returned, wct;
1838 	__u32 bytes_sent;
1839 	__u16 byte_count;
1840 	__u32 pid = io_parms->pid;
1841 	__u16 netfid = io_parms->netfid;
1842 	__u64 offset = io_parms->offset;
1843 	struct cifs_tcon *tcon = io_parms->tcon;
1844 	unsigned int count = io_parms->length;
1845 
1846 	*nbytes = 0;
1847 
1848 	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1849 	if (tcon->ses == NULL)
1850 		return -ECONNABORTED;
1851 
1852 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1853 		wct = 14;
1854 	else {
1855 		wct = 12;
1856 		if ((offset >> 32) > 0) {
1857 			/* can not handle big offset for old srv */
1858 			return -EIO;
1859 		}
1860 	}
1861 
1862 	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1863 		      (void **) &pSMBr);
1864 	if (rc)
1865 		return rc;
1866 
1867 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1868 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1869 
1870 	/* tcon and ses pointer are checked in smb_init */
1871 	if (tcon->ses->server == NULL)
1872 		return -ECONNABORTED;
1873 
1874 	pSMB->AndXCommand = 0xFF;	/* none */
1875 	pSMB->Fid = netfid;
1876 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1877 	if (wct == 14)
1878 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1879 
1880 	pSMB->Reserved = 0xFFFFFFFF;
1881 	pSMB->WriteMode = 0;
1882 	pSMB->Remaining = 0;
1883 
1884 	/* Can increase buffer size if buffer is big enough in some cases ie we
1885 	can send more if LARGE_WRITE_X capability returned by the server and if
1886 	our buffer is big enough or if we convert to iovecs on socket writes
1887 	and eliminate the copy to the CIFS buffer */
1888 	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1889 		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1890 	} else {
1891 		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1892 			 & ~0xFF;
1893 	}
1894 
1895 	if (bytes_sent > count)
1896 		bytes_sent = count;
1897 	pSMB->DataOffset =
1898 		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1899 	if (buf)
1900 		memcpy(pSMB->Data, buf, bytes_sent);
1901 	else if (count != 0) {
1902 		/* No buffer */
1903 		cifs_buf_release(pSMB);
1904 		return -EINVAL;
1905 	} /* else setting file size with write of zero bytes */
1906 	if (wct == 14)
1907 		byte_count = bytes_sent + 1; /* pad */
1908 	else /* wct == 12 */
1909 		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1910 
1911 	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1912 	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1913 	inc_rfc1001_len(pSMB, byte_count);
1914 
1915 	if (wct == 14)
1916 		pSMB->ByteCount = cpu_to_le16(byte_count);
1917 	else { /* old style write has byte count 4 bytes earlier
1918 		  so 4 bytes pad  */
1919 		struct smb_com_writex_req *pSMBW =
1920 			(struct smb_com_writex_req *)pSMB;
1921 		pSMBW->ByteCount = cpu_to_le16(byte_count);
1922 	}
1923 
1924 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1925 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1926 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1927 	if (rc) {
1928 		cifs_dbg(FYI, "Send error in write = %d\n", rc);
1929 	} else {
1930 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
1931 		*nbytes = (*nbytes) << 16;
1932 		*nbytes += le16_to_cpu(pSMBr->Count);
1933 
1934 		/*
1935 		 * Mask off high 16 bits when bytes written as returned by the
1936 		 * server is greater than bytes requested by the client. Some
1937 		 * OS/2 servers are known to set incorrect CountHigh values.
1938 		 */
1939 		if (*nbytes > count)
1940 			*nbytes &= 0xFFFF;
1941 	}
1942 
1943 	cifs_buf_release(pSMB);
1944 
1945 	/* Note: On -EAGAIN error only caller can retry on handle based calls
1946 		since file handle passed in no longer valid */
1947 
1948 	return rc;
1949 }
1950 
1951 void
cifs_writedata_release(struct kref * refcount)1952 cifs_writedata_release(struct kref *refcount)
1953 {
1954 	struct cifs_writedata *wdata = container_of(refcount,
1955 					struct cifs_writedata, refcount);
1956 #ifdef CONFIG_CIFS_SMB_DIRECT
1957 	if (wdata->mr) {
1958 		smbd_deregister_mr(wdata->mr);
1959 		wdata->mr = NULL;
1960 	}
1961 #endif
1962 
1963 	if (wdata->cfile)
1964 		cifsFileInfo_put(wdata->cfile);
1965 
1966 	kvfree(wdata->pages);
1967 	kfree(wdata);
1968 }
1969 
1970 /*
1971  * Write failed with a retryable error. Resend the write request. It's also
1972  * possible that the page was redirtied so re-clean the page.
1973  */
1974 static void
cifs_writev_requeue(struct cifs_writedata * wdata)1975 cifs_writev_requeue(struct cifs_writedata *wdata)
1976 {
1977 	int i, rc = 0;
1978 	struct inode *inode = d_inode(wdata->cfile->dentry);
1979 	struct TCP_Server_Info *server;
1980 	unsigned int rest_len;
1981 
1982 	server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1983 	i = 0;
1984 	rest_len = wdata->bytes;
1985 	do {
1986 		struct cifs_writedata *wdata2;
1987 		unsigned int j, nr_pages, wsize, tailsz, cur_len;
1988 
1989 		wsize = server->ops->wp_retry_size(inode);
1990 		if (wsize < rest_len) {
1991 			nr_pages = wsize / PAGE_SIZE;
1992 			if (!nr_pages) {
1993 				rc = -ENOTSUPP;
1994 				break;
1995 			}
1996 			cur_len = nr_pages * PAGE_SIZE;
1997 			tailsz = PAGE_SIZE;
1998 		} else {
1999 			nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
2000 			cur_len = rest_len;
2001 			tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
2002 		}
2003 
2004 		wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
2005 		if (!wdata2) {
2006 			rc = -ENOMEM;
2007 			break;
2008 		}
2009 
2010 		for (j = 0; j < nr_pages; j++) {
2011 			wdata2->pages[j] = wdata->pages[i + j];
2012 			lock_page(wdata2->pages[j]);
2013 			clear_page_dirty_for_io(wdata2->pages[j]);
2014 		}
2015 
2016 		wdata2->sync_mode = wdata->sync_mode;
2017 		wdata2->nr_pages = nr_pages;
2018 		wdata2->offset = page_offset(wdata2->pages[0]);
2019 		wdata2->pagesz = PAGE_SIZE;
2020 		wdata2->tailsz = tailsz;
2021 		wdata2->bytes = cur_len;
2022 
2023 		wdata2->cfile = find_writable_file(CIFS_I(inode), false);
2024 		if (!wdata2->cfile) {
2025 			cifs_dbg(VFS, "No writable handles for inode\n");
2026 			rc = -EBADF;
2027 			break;
2028 		}
2029 		wdata2->pid = wdata2->cfile->pid;
2030 		rc = server->ops->async_writev(wdata2, cifs_writedata_release);
2031 
2032 		for (j = 0; j < nr_pages; j++) {
2033 			unlock_page(wdata2->pages[j]);
2034 			if (rc != 0 && rc != -EAGAIN) {
2035 				SetPageError(wdata2->pages[j]);
2036 				end_page_writeback(wdata2->pages[j]);
2037 				put_page(wdata2->pages[j]);
2038 			}
2039 		}
2040 
2041 		if (rc) {
2042 			kref_put(&wdata2->refcount, cifs_writedata_release);
2043 			if (rc == -EAGAIN)
2044 				continue;
2045 			break;
2046 		}
2047 
2048 		rest_len -= cur_len;
2049 		i += nr_pages;
2050 	} while (i < wdata->nr_pages);
2051 
2052 	mapping_set_error(inode->i_mapping, rc);
2053 	kref_put(&wdata->refcount, cifs_writedata_release);
2054 }
2055 
2056 void
cifs_writev_complete(struct work_struct * work)2057 cifs_writev_complete(struct work_struct *work)
2058 {
2059 	struct cifs_writedata *wdata = container_of(work,
2060 						struct cifs_writedata, work);
2061 	struct inode *inode = d_inode(wdata->cfile->dentry);
2062 	int i = 0;
2063 
2064 	if (wdata->result == 0) {
2065 		spin_lock(&inode->i_lock);
2066 		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2067 		spin_unlock(&inode->i_lock);
2068 		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2069 					 wdata->bytes);
2070 	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2071 		return cifs_writev_requeue(wdata);
2072 
2073 	for (i = 0; i < wdata->nr_pages; i++) {
2074 		struct page *page = wdata->pages[i];
2075 		if (wdata->result == -EAGAIN)
2076 			__set_page_dirty_nobuffers(page);
2077 		else if (wdata->result < 0)
2078 			SetPageError(page);
2079 		end_page_writeback(page);
2080 		put_page(page);
2081 	}
2082 	if (wdata->result != -EAGAIN)
2083 		mapping_set_error(inode->i_mapping, wdata->result);
2084 	kref_put(&wdata->refcount, cifs_writedata_release);
2085 }
2086 
2087 struct cifs_writedata *
cifs_writedata_alloc(unsigned int nr_pages,work_func_t complete)2088 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2089 {
2090 	struct page **pages =
2091 		kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
2092 	if (pages)
2093 		return cifs_writedata_direct_alloc(pages, complete);
2094 
2095 	return NULL;
2096 }
2097 
2098 struct cifs_writedata *
cifs_writedata_direct_alloc(struct page ** pages,work_func_t complete)2099 cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
2100 {
2101 	struct cifs_writedata *wdata;
2102 
2103 	wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
2104 	if (wdata != NULL) {
2105 		wdata->pages = pages;
2106 		kref_init(&wdata->refcount);
2107 		INIT_LIST_HEAD(&wdata->list);
2108 		init_completion(&wdata->done);
2109 		INIT_WORK(&wdata->work, complete);
2110 	}
2111 	return wdata;
2112 }
2113 
2114 /*
2115  * Check the mid_state and signature on received buffer (if any), and queue the
2116  * workqueue completion task.
2117  */
2118 static void
cifs_writev_callback(struct mid_q_entry * mid)2119 cifs_writev_callback(struct mid_q_entry *mid)
2120 {
2121 	struct cifs_writedata *wdata = mid->callback_data;
2122 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2123 	unsigned int written;
2124 	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2125 
2126 	switch (mid->mid_state) {
2127 	case MID_RESPONSE_RECEIVED:
2128 		wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2129 		if (wdata->result != 0)
2130 			break;
2131 
2132 		written = le16_to_cpu(smb->CountHigh);
2133 		written <<= 16;
2134 		written += le16_to_cpu(smb->Count);
2135 		/*
2136 		 * Mask off high 16 bits when bytes written as returned
2137 		 * by the server is greater than bytes requested by the
2138 		 * client. OS/2 servers are known to set incorrect
2139 		 * CountHigh values.
2140 		 */
2141 		if (written > wdata->bytes)
2142 			written &= 0xFFFF;
2143 
2144 		if (written < wdata->bytes)
2145 			wdata->result = -ENOSPC;
2146 		else
2147 			wdata->bytes = written;
2148 		break;
2149 	case MID_REQUEST_SUBMITTED:
2150 	case MID_RETRY_NEEDED:
2151 		wdata->result = -EAGAIN;
2152 		break;
2153 	default:
2154 		wdata->result = -EIO;
2155 		break;
2156 	}
2157 
2158 	queue_work(cifsiod_wq, &wdata->work);
2159 	DeleteMidQEntry(mid);
2160 	add_credits(tcon->ses->server, 1, 0);
2161 }
2162 
2163 /* cifs_async_writev - send an async write, and set up mid to handle result */
2164 int
cifs_async_writev(struct cifs_writedata * wdata,void (* release)(struct kref * kref))2165 cifs_async_writev(struct cifs_writedata *wdata,
2166 		  void (*release)(struct kref *kref))
2167 {
2168 	int rc = -EACCES;
2169 	WRITE_REQ *smb = NULL;
2170 	int wct;
2171 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2172 	struct kvec iov[2];
2173 	struct smb_rqst rqst = { };
2174 
2175 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2176 		wct = 14;
2177 	} else {
2178 		wct = 12;
2179 		if (wdata->offset >> 32 > 0) {
2180 			/* can not handle big offset for old srv */
2181 			return -EIO;
2182 		}
2183 	}
2184 
2185 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2186 	if (rc)
2187 		goto async_writev_out;
2188 
2189 	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2190 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2191 
2192 	smb->AndXCommand = 0xFF;	/* none */
2193 	smb->Fid = wdata->cfile->fid.netfid;
2194 	smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2195 	if (wct == 14)
2196 		smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2197 	smb->Reserved = 0xFFFFFFFF;
2198 	smb->WriteMode = 0;
2199 	smb->Remaining = 0;
2200 
2201 	smb->DataOffset =
2202 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2203 
2204 	/* 4 for RFC1001 length + 1 for BCC */
2205 	iov[0].iov_len = 4;
2206 	iov[0].iov_base = smb;
2207 	iov[1].iov_len = get_rfc1002_length(smb) + 1;
2208 	iov[1].iov_base = (char *)smb + 4;
2209 
2210 	rqst.rq_iov = iov;
2211 	rqst.rq_nvec = 2;
2212 	rqst.rq_pages = wdata->pages;
2213 	rqst.rq_npages = wdata->nr_pages;
2214 	rqst.rq_pagesz = wdata->pagesz;
2215 	rqst.rq_tailsz = wdata->tailsz;
2216 
2217 	cifs_dbg(FYI, "async write at %llu %u bytes\n",
2218 		 wdata->offset, wdata->bytes);
2219 
2220 	smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2221 	smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2222 
2223 	if (wct == 14) {
2224 		inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2225 		put_bcc(wdata->bytes + 1, &smb->hdr);
2226 	} else {
2227 		/* wct == 12 */
2228 		struct smb_com_writex_req *smbw =
2229 				(struct smb_com_writex_req *)smb;
2230 		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2231 		put_bcc(wdata->bytes + 5, &smbw->hdr);
2232 		iov[1].iov_len += 4; /* pad bigger by four bytes */
2233 	}
2234 
2235 	kref_get(&wdata->refcount);
2236 	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2237 				cifs_writev_callback, NULL, wdata, 0);
2238 
2239 	if (rc == 0)
2240 		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2241 	else
2242 		kref_put(&wdata->refcount, release);
2243 
2244 async_writev_out:
2245 	cifs_small_buf_release(smb);
2246 	return rc;
2247 }
2248 
2249 int
CIFSSMBWrite2(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,struct kvec * iov,int n_vec)2250 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2251 	      unsigned int *nbytes, struct kvec *iov, int n_vec)
2252 {
2253 	int rc = -EACCES;
2254 	WRITE_REQ *pSMB = NULL;
2255 	int wct;
2256 	int smb_hdr_len;
2257 	int resp_buf_type = 0;
2258 	__u32 pid = io_parms->pid;
2259 	__u16 netfid = io_parms->netfid;
2260 	__u64 offset = io_parms->offset;
2261 	struct cifs_tcon *tcon = io_parms->tcon;
2262 	unsigned int count = io_parms->length;
2263 	struct kvec rsp_iov;
2264 
2265 	*nbytes = 0;
2266 
2267 	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2268 
2269 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2270 		wct = 14;
2271 	} else {
2272 		wct = 12;
2273 		if ((offset >> 32) > 0) {
2274 			/* can not handle big offset for old srv */
2275 			return -EIO;
2276 		}
2277 	}
2278 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2279 	if (rc)
2280 		return rc;
2281 
2282 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2283 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2284 
2285 	/* tcon and ses pointer are checked in smb_init */
2286 	if (tcon->ses->server == NULL)
2287 		return -ECONNABORTED;
2288 
2289 	pSMB->AndXCommand = 0xFF;	/* none */
2290 	pSMB->Fid = netfid;
2291 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2292 	if (wct == 14)
2293 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2294 	pSMB->Reserved = 0xFFFFFFFF;
2295 	pSMB->WriteMode = 0;
2296 	pSMB->Remaining = 0;
2297 
2298 	pSMB->DataOffset =
2299 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2300 
2301 	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2302 	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2303 	/* header + 1 byte pad */
2304 	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2305 	if (wct == 14)
2306 		inc_rfc1001_len(pSMB, count + 1);
2307 	else /* wct == 12 */
2308 		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2309 	if (wct == 14)
2310 		pSMB->ByteCount = cpu_to_le16(count + 1);
2311 	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2312 		struct smb_com_writex_req *pSMBW =
2313 				(struct smb_com_writex_req *)pSMB;
2314 		pSMBW->ByteCount = cpu_to_le16(count + 5);
2315 	}
2316 	iov[0].iov_base = pSMB;
2317 	if (wct == 14)
2318 		iov[0].iov_len = smb_hdr_len + 4;
2319 	else /* wct == 12 pad bigger by four bytes */
2320 		iov[0].iov_len = smb_hdr_len + 8;
2321 
2322 	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2323 			  &rsp_iov);
2324 	cifs_small_buf_release(pSMB);
2325 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2326 	if (rc) {
2327 		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2328 	} else if (resp_buf_type == 0) {
2329 		/* presumably this can not happen, but best to be safe */
2330 		rc = -EIO;
2331 	} else {
2332 		WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2333 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
2334 		*nbytes = (*nbytes) << 16;
2335 		*nbytes += le16_to_cpu(pSMBr->Count);
2336 
2337 		/*
2338 		 * Mask off high 16 bits when bytes written as returned by the
2339 		 * server is greater than bytes requested by the client. OS/2
2340 		 * servers are known to set incorrect CountHigh values.
2341 		 */
2342 		if (*nbytes > count)
2343 			*nbytes &= 0xFFFF;
2344 	}
2345 
2346 	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2347 
2348 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2349 		since file handle passed in no longer valid */
2350 
2351 	return rc;
2352 }
2353 
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)2354 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2355 	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2356 	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2357 {
2358 	int rc = 0;
2359 	LOCK_REQ *pSMB = NULL;
2360 	struct kvec iov[2];
2361 	struct kvec rsp_iov;
2362 	int resp_buf_type;
2363 	__u16 count;
2364 
2365 	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2366 		 num_lock, num_unlock);
2367 
2368 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2369 	if (rc)
2370 		return rc;
2371 
2372 	pSMB->Timeout = 0;
2373 	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2374 	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2375 	pSMB->LockType = lock_type;
2376 	pSMB->AndXCommand = 0xFF; /* none */
2377 	pSMB->Fid = netfid; /* netfid stays le */
2378 
2379 	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2380 	inc_rfc1001_len(pSMB, count);
2381 	pSMB->ByteCount = cpu_to_le16(count);
2382 
2383 	iov[0].iov_base = (char *)pSMB;
2384 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2385 			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2386 	iov[1].iov_base = (char *)buf;
2387 	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2388 
2389 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2390 	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP,
2391 			  &rsp_iov);
2392 	cifs_small_buf_release(pSMB);
2393 	if (rc)
2394 		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2395 
2396 	return rc;
2397 }
2398 
2399 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)2400 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2401 	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2402 	    const __u64 offset, const __u32 numUnlock,
2403 	    const __u32 numLock, const __u8 lockType,
2404 	    const bool waitFlag, const __u8 oplock_level)
2405 {
2406 	int rc = 0;
2407 	LOCK_REQ *pSMB = NULL;
2408 /*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2409 	int bytes_returned;
2410 	int flags = 0;
2411 	__u16 count;
2412 
2413 	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2414 		 (int)waitFlag, numLock);
2415 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2416 
2417 	if (rc)
2418 		return rc;
2419 
2420 	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2421 		/* no response expected */
2422 		flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2423 		pSMB->Timeout = 0;
2424 	} else if (waitFlag) {
2425 		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2426 		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2427 	} else {
2428 		pSMB->Timeout = 0;
2429 	}
2430 
2431 	pSMB->NumberOfLocks = cpu_to_le16(numLock);
2432 	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2433 	pSMB->LockType = lockType;
2434 	pSMB->OplockLevel = oplock_level;
2435 	pSMB->AndXCommand = 0xFF;	/* none */
2436 	pSMB->Fid = smb_file_id; /* netfid stays le */
2437 
2438 	if ((numLock != 0) || (numUnlock != 0)) {
2439 		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2440 		/* BB where to store pid high? */
2441 		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2442 		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2443 		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2444 		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2445 		count = sizeof(LOCKING_ANDX_RANGE);
2446 	} else {
2447 		/* oplock break */
2448 		count = 0;
2449 	}
2450 	inc_rfc1001_len(pSMB, count);
2451 	pSMB->ByteCount = cpu_to_le16(count);
2452 
2453 	if (waitFlag)
2454 		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2455 			(struct smb_hdr *) pSMB, &bytes_returned);
2456 	else
2457 		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2458 	cifs_small_buf_release(pSMB);
2459 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2460 	if (rc)
2461 		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2462 
2463 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2464 	since file handle passed in no longer valid */
2465 	return rc;
2466 }
2467 
2468 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)2469 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2470 		const __u16 smb_file_id, const __u32 netpid,
2471 		const loff_t start_offset, const __u64 len,
2472 		struct file_lock *pLockData, const __u16 lock_type,
2473 		const bool waitFlag)
2474 {
2475 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2476 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2477 	struct cifs_posix_lock *parm_data;
2478 	int rc = 0;
2479 	int timeout = 0;
2480 	int bytes_returned = 0;
2481 	int resp_buf_type = 0;
2482 	__u16 params, param_offset, offset, byte_count, count;
2483 	struct kvec iov[1];
2484 	struct kvec rsp_iov;
2485 
2486 	cifs_dbg(FYI, "Posix Lock\n");
2487 
2488 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2489 
2490 	if (rc)
2491 		return rc;
2492 
2493 	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2494 
2495 	params = 6;
2496 	pSMB->MaxSetupCount = 0;
2497 	pSMB->Reserved = 0;
2498 	pSMB->Flags = 0;
2499 	pSMB->Reserved2 = 0;
2500 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2501 	offset = param_offset + params;
2502 
2503 	count = sizeof(struct cifs_posix_lock);
2504 	pSMB->MaxParameterCount = cpu_to_le16(2);
2505 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2506 	pSMB->SetupCount = 1;
2507 	pSMB->Reserved3 = 0;
2508 	if (pLockData)
2509 		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2510 	else
2511 		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2512 	byte_count = 3 /* pad */  + params + count;
2513 	pSMB->DataCount = cpu_to_le16(count);
2514 	pSMB->ParameterCount = cpu_to_le16(params);
2515 	pSMB->TotalDataCount = pSMB->DataCount;
2516 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2517 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2518 	parm_data = (struct cifs_posix_lock *)
2519 			(((char *) &pSMB->hdr.Protocol) + offset);
2520 
2521 	parm_data->lock_type = cpu_to_le16(lock_type);
2522 	if (waitFlag) {
2523 		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2524 		parm_data->lock_flags = cpu_to_le16(1);
2525 		pSMB->Timeout = cpu_to_le32(-1);
2526 	} else
2527 		pSMB->Timeout = 0;
2528 
2529 	parm_data->pid = cpu_to_le32(netpid);
2530 	parm_data->start = cpu_to_le64(start_offset);
2531 	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2532 
2533 	pSMB->DataOffset = cpu_to_le16(offset);
2534 	pSMB->Fid = smb_file_id;
2535 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2536 	pSMB->Reserved4 = 0;
2537 	inc_rfc1001_len(pSMB, byte_count);
2538 	pSMB->ByteCount = cpu_to_le16(byte_count);
2539 	if (waitFlag) {
2540 		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2541 			(struct smb_hdr *) pSMBr, &bytes_returned);
2542 	} else {
2543 		iov[0].iov_base = (char *)pSMB;
2544 		iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2545 		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2546 				&resp_buf_type, timeout, &rsp_iov);
2547 		pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2548 	}
2549 	cifs_small_buf_release(pSMB);
2550 
2551 	if (rc) {
2552 		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2553 	} else if (pLockData) {
2554 		/* lock structure can be returned on get */
2555 		__u16 data_offset;
2556 		__u16 data_count;
2557 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2558 
2559 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2560 			rc = -EIO;      /* bad smb */
2561 			goto plk_err_exit;
2562 		}
2563 		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2564 		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2565 		if (data_count < sizeof(struct cifs_posix_lock)) {
2566 			rc = -EIO;
2567 			goto plk_err_exit;
2568 		}
2569 		parm_data = (struct cifs_posix_lock *)
2570 			((char *)&pSMBr->hdr.Protocol + data_offset);
2571 		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2572 			pLockData->fl_type = F_UNLCK;
2573 		else {
2574 			if (parm_data->lock_type ==
2575 					cpu_to_le16(CIFS_RDLCK))
2576 				pLockData->fl_type = F_RDLCK;
2577 			else if (parm_data->lock_type ==
2578 					cpu_to_le16(CIFS_WRLCK))
2579 				pLockData->fl_type = F_WRLCK;
2580 
2581 			pLockData->fl_start = le64_to_cpu(parm_data->start);
2582 			pLockData->fl_end = pLockData->fl_start +
2583 					le64_to_cpu(parm_data->length) - 1;
2584 			pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2585 		}
2586 	}
2587 
2588 plk_err_exit:
2589 	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2590 
2591 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2592 	   since file handle passed in no longer valid */
2593 
2594 	return rc;
2595 }
2596 
2597 
2598 int
CIFSSMBClose(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2599 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2600 {
2601 	int rc = 0;
2602 	CLOSE_REQ *pSMB = NULL;
2603 	cifs_dbg(FYI, "In CIFSSMBClose\n");
2604 
2605 /* do not retry on dead session on close */
2606 	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2607 	if (rc == -EAGAIN)
2608 		return 0;
2609 	if (rc)
2610 		return rc;
2611 
2612 	pSMB->FileID = (__u16) smb_file_id;
2613 	pSMB->LastWriteTime = 0xFFFFFFFF;
2614 	pSMB->ByteCount = 0;
2615 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2616 	cifs_small_buf_release(pSMB);
2617 	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2618 	if (rc) {
2619 		if (rc != -EINTR) {
2620 			/* EINTR is expected when user ctl-c to kill app */
2621 			cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2622 		}
2623 	}
2624 
2625 	/* Since session is dead, file will be closed on server already */
2626 	if (rc == -EAGAIN)
2627 		rc = 0;
2628 
2629 	return rc;
2630 }
2631 
2632 int
CIFSSMBFlush(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2633 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2634 {
2635 	int rc = 0;
2636 	FLUSH_REQ *pSMB = NULL;
2637 	cifs_dbg(FYI, "In CIFSSMBFlush\n");
2638 
2639 	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2640 	if (rc)
2641 		return rc;
2642 
2643 	pSMB->FileID = (__u16) smb_file_id;
2644 	pSMB->ByteCount = 0;
2645 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2646 	cifs_small_buf_release(pSMB);
2647 	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2648 	if (rc)
2649 		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2650 
2651 	return rc;
2652 }
2653 
2654 int
CIFSSMBRename(const unsigned int xid,struct cifs_tcon * tcon,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)2655 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2656 	      const char *from_name, const char *to_name,
2657 	      struct cifs_sb_info *cifs_sb)
2658 {
2659 	int rc = 0;
2660 	RENAME_REQ *pSMB = NULL;
2661 	RENAME_RSP *pSMBr = NULL;
2662 	int bytes_returned;
2663 	int name_len, name_len2;
2664 	__u16 count;
2665 	int remap = cifs_remap(cifs_sb);
2666 
2667 	cifs_dbg(FYI, "In CIFSSMBRename\n");
2668 renameRetry:
2669 	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2670 		      (void **) &pSMBr);
2671 	if (rc)
2672 		return rc;
2673 
2674 	pSMB->BufferFormat = 0x04;
2675 	pSMB->SearchAttributes =
2676 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2677 			ATTR_DIRECTORY);
2678 
2679 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2680 		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2681 					      from_name, PATH_MAX,
2682 					      cifs_sb->local_nls, remap);
2683 		name_len++;	/* trailing null */
2684 		name_len *= 2;
2685 		pSMB->OldFileName[name_len] = 0x04;	/* pad */
2686 	/* protocol requires ASCII signature byte on Unicode string */
2687 		pSMB->OldFileName[name_len + 1] = 0x00;
2688 		name_len2 =
2689 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2690 				       to_name, PATH_MAX, cifs_sb->local_nls,
2691 				       remap);
2692 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2693 		name_len2 *= 2;	/* convert to bytes */
2694 	} else {	/* BB improve the check for buffer overruns BB */
2695 		name_len = strnlen(from_name, PATH_MAX);
2696 		name_len++;	/* trailing null */
2697 		strncpy(pSMB->OldFileName, from_name, name_len);
2698 		name_len2 = strnlen(to_name, PATH_MAX);
2699 		name_len2++;	/* trailing null */
2700 		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2701 		strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2702 		name_len2++;	/* trailing null */
2703 		name_len2++;	/* signature byte */
2704 	}
2705 
2706 	count = 1 /* 1st signature byte */  + name_len + name_len2;
2707 	inc_rfc1001_len(pSMB, count);
2708 	pSMB->ByteCount = cpu_to_le16(count);
2709 
2710 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2711 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2712 	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2713 	if (rc)
2714 		cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2715 
2716 	cifs_buf_release(pSMB);
2717 
2718 	if (rc == -EAGAIN)
2719 		goto renameRetry;
2720 
2721 	return rc;
2722 }
2723 
CIFSSMBRenameOpenFile(const unsigned int xid,struct cifs_tcon * pTcon,int netfid,const char * target_name,const struct nls_table * nls_codepage,int remap)2724 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2725 		int netfid, const char *target_name,
2726 		const struct nls_table *nls_codepage, int remap)
2727 {
2728 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2729 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2730 	struct set_file_rename *rename_info;
2731 	char *data_offset;
2732 	char dummy_string[30];
2733 	int rc = 0;
2734 	int bytes_returned = 0;
2735 	int len_of_str;
2736 	__u16 params, param_offset, offset, count, byte_count;
2737 
2738 	cifs_dbg(FYI, "Rename to File by handle\n");
2739 	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2740 			(void **) &pSMBr);
2741 	if (rc)
2742 		return rc;
2743 
2744 	params = 6;
2745 	pSMB->MaxSetupCount = 0;
2746 	pSMB->Reserved = 0;
2747 	pSMB->Flags = 0;
2748 	pSMB->Timeout = 0;
2749 	pSMB->Reserved2 = 0;
2750 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2751 	offset = param_offset + params;
2752 
2753 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2754 	rename_info = (struct set_file_rename *) data_offset;
2755 	pSMB->MaxParameterCount = cpu_to_le16(2);
2756 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2757 	pSMB->SetupCount = 1;
2758 	pSMB->Reserved3 = 0;
2759 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2760 	byte_count = 3 /* pad */  + params;
2761 	pSMB->ParameterCount = cpu_to_le16(params);
2762 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2763 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2764 	pSMB->DataOffset = cpu_to_le16(offset);
2765 	/* construct random name ".cifs_tmp<inodenum><mid>" */
2766 	rename_info->overwrite = cpu_to_le32(1);
2767 	rename_info->root_fid  = 0;
2768 	/* unicode only call */
2769 	if (target_name == NULL) {
2770 		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2771 		len_of_str =
2772 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2773 					dummy_string, 24, nls_codepage, remap);
2774 	} else {
2775 		len_of_str =
2776 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2777 					target_name, PATH_MAX, nls_codepage,
2778 					remap);
2779 	}
2780 	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2781 	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2782 	byte_count += count;
2783 	pSMB->DataCount = cpu_to_le16(count);
2784 	pSMB->TotalDataCount = pSMB->DataCount;
2785 	pSMB->Fid = netfid;
2786 	pSMB->InformationLevel =
2787 		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2788 	pSMB->Reserved4 = 0;
2789 	inc_rfc1001_len(pSMB, byte_count);
2790 	pSMB->ByteCount = cpu_to_le16(byte_count);
2791 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2792 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2793 	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2794 	if (rc)
2795 		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2796 			 rc);
2797 
2798 	cifs_buf_release(pSMB);
2799 
2800 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2801 		since file handle passed in no longer valid */
2802 
2803 	return rc;
2804 }
2805 
2806 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)2807 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2808 	    const char *fromName, const __u16 target_tid, const char *toName,
2809 	    const int flags, const struct nls_table *nls_codepage, int remap)
2810 {
2811 	int rc = 0;
2812 	COPY_REQ *pSMB = NULL;
2813 	COPY_RSP *pSMBr = NULL;
2814 	int bytes_returned;
2815 	int name_len, name_len2;
2816 	__u16 count;
2817 
2818 	cifs_dbg(FYI, "In CIFSSMBCopy\n");
2819 copyRetry:
2820 	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2821 			(void **) &pSMBr);
2822 	if (rc)
2823 		return rc;
2824 
2825 	pSMB->BufferFormat = 0x04;
2826 	pSMB->Tid2 = target_tid;
2827 
2828 	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2829 
2830 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2831 		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2832 					      fromName, PATH_MAX, nls_codepage,
2833 					      remap);
2834 		name_len++;     /* trailing null */
2835 		name_len *= 2;
2836 		pSMB->OldFileName[name_len] = 0x04;     /* pad */
2837 		/* protocol requires ASCII signature byte on Unicode string */
2838 		pSMB->OldFileName[name_len + 1] = 0x00;
2839 		name_len2 =
2840 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2841 				       toName, PATH_MAX, nls_codepage, remap);
2842 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2843 		name_len2 *= 2; /* convert to bytes */
2844 	} else { 	/* BB improve the check for buffer overruns BB */
2845 		name_len = strnlen(fromName, PATH_MAX);
2846 		name_len++;     /* trailing null */
2847 		strncpy(pSMB->OldFileName, fromName, name_len);
2848 		name_len2 = strnlen(toName, PATH_MAX);
2849 		name_len2++;    /* trailing null */
2850 		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2851 		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2852 		name_len2++;    /* trailing null */
2853 		name_len2++;    /* signature byte */
2854 	}
2855 
2856 	count = 1 /* 1st signature byte */  + name_len + name_len2;
2857 	inc_rfc1001_len(pSMB, count);
2858 	pSMB->ByteCount = cpu_to_le16(count);
2859 
2860 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2861 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
2862 	if (rc) {
2863 		cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2864 			 rc, le16_to_cpu(pSMBr->CopyCount));
2865 	}
2866 	cifs_buf_release(pSMB);
2867 
2868 	if (rc == -EAGAIN)
2869 		goto copyRetry;
2870 
2871 	return rc;
2872 }
2873 
2874 int
CIFSUnixCreateSymLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2875 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2876 		      const char *fromName, const char *toName,
2877 		      const struct nls_table *nls_codepage, int remap)
2878 {
2879 	TRANSACTION2_SPI_REQ *pSMB = NULL;
2880 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2881 	char *data_offset;
2882 	int name_len;
2883 	int name_len_target;
2884 	int rc = 0;
2885 	int bytes_returned = 0;
2886 	__u16 params, param_offset, offset, byte_count;
2887 
2888 	cifs_dbg(FYI, "In Symlink Unix style\n");
2889 createSymLinkRetry:
2890 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2891 		      (void **) &pSMBr);
2892 	if (rc)
2893 		return rc;
2894 
2895 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2896 		name_len =
2897 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2898 				/* find define for this maxpathcomponent */
2899 					PATH_MAX, nls_codepage, remap);
2900 		name_len++;	/* trailing null */
2901 		name_len *= 2;
2902 
2903 	} else {	/* BB improve the check for buffer overruns BB */
2904 		name_len = strnlen(fromName, PATH_MAX);
2905 		name_len++;	/* trailing null */
2906 		strncpy(pSMB->FileName, fromName, name_len);
2907 	}
2908 	params = 6 + name_len;
2909 	pSMB->MaxSetupCount = 0;
2910 	pSMB->Reserved = 0;
2911 	pSMB->Flags = 0;
2912 	pSMB->Timeout = 0;
2913 	pSMB->Reserved2 = 0;
2914 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2915 				InformationLevel) - 4;
2916 	offset = param_offset + params;
2917 
2918 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2919 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2920 		name_len_target =
2921 		    cifsConvertToUTF16((__le16 *) data_offset, toName,
2922 				/* find define for this maxpathcomponent */
2923 					PATH_MAX, nls_codepage, remap);
2924 		name_len_target++;	/* trailing null */
2925 		name_len_target *= 2;
2926 	} else {	/* BB improve the check for buffer overruns BB */
2927 		name_len_target = strnlen(toName, PATH_MAX);
2928 		name_len_target++;	/* trailing null */
2929 		strncpy(data_offset, toName, name_len_target);
2930 	}
2931 
2932 	pSMB->MaxParameterCount = cpu_to_le16(2);
2933 	/* BB find exact max on data count below from sess */
2934 	pSMB->MaxDataCount = cpu_to_le16(1000);
2935 	pSMB->SetupCount = 1;
2936 	pSMB->Reserved3 = 0;
2937 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2938 	byte_count = 3 /* pad */  + params + name_len_target;
2939 	pSMB->DataCount = cpu_to_le16(name_len_target);
2940 	pSMB->ParameterCount = cpu_to_le16(params);
2941 	pSMB->TotalDataCount = pSMB->DataCount;
2942 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2943 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2944 	pSMB->DataOffset = cpu_to_le16(offset);
2945 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2946 	pSMB->Reserved4 = 0;
2947 	inc_rfc1001_len(pSMB, byte_count);
2948 	pSMB->ByteCount = cpu_to_le16(byte_count);
2949 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2950 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2951 	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2952 	if (rc)
2953 		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2954 			 rc);
2955 
2956 	cifs_buf_release(pSMB);
2957 
2958 	if (rc == -EAGAIN)
2959 		goto createSymLinkRetry;
2960 
2961 	return rc;
2962 }
2963 
2964 int
CIFSUnixCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2965 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2966 		       const char *fromName, const char *toName,
2967 		       const struct nls_table *nls_codepage, int remap)
2968 {
2969 	TRANSACTION2_SPI_REQ *pSMB = NULL;
2970 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2971 	char *data_offset;
2972 	int name_len;
2973 	int name_len_target;
2974 	int rc = 0;
2975 	int bytes_returned = 0;
2976 	__u16 params, param_offset, offset, byte_count;
2977 
2978 	cifs_dbg(FYI, "In Create Hard link Unix style\n");
2979 createHardLinkRetry:
2980 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2981 		      (void **) &pSMBr);
2982 	if (rc)
2983 		return rc;
2984 
2985 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2986 		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2987 					      PATH_MAX, nls_codepage, remap);
2988 		name_len++;	/* trailing null */
2989 		name_len *= 2;
2990 
2991 	} else {	/* BB improve the check for buffer overruns BB */
2992 		name_len = strnlen(toName, PATH_MAX);
2993 		name_len++;	/* trailing null */
2994 		strncpy(pSMB->FileName, toName, name_len);
2995 	}
2996 	params = 6 + name_len;
2997 	pSMB->MaxSetupCount = 0;
2998 	pSMB->Reserved = 0;
2999 	pSMB->Flags = 0;
3000 	pSMB->Timeout = 0;
3001 	pSMB->Reserved2 = 0;
3002 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3003 				InformationLevel) - 4;
3004 	offset = param_offset + params;
3005 
3006 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3007 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3008 		name_len_target =
3009 		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
3010 				       PATH_MAX, nls_codepage, remap);
3011 		name_len_target++;	/* trailing null */
3012 		name_len_target *= 2;
3013 	} else {	/* BB improve the check for buffer overruns BB */
3014 		name_len_target = strnlen(fromName, PATH_MAX);
3015 		name_len_target++;	/* trailing null */
3016 		strncpy(data_offset, fromName, name_len_target);
3017 	}
3018 
3019 	pSMB->MaxParameterCount = cpu_to_le16(2);
3020 	/* BB find exact max on data count below from sess*/
3021 	pSMB->MaxDataCount = cpu_to_le16(1000);
3022 	pSMB->SetupCount = 1;
3023 	pSMB->Reserved3 = 0;
3024 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3025 	byte_count = 3 /* pad */  + params + name_len_target;
3026 	pSMB->ParameterCount = cpu_to_le16(params);
3027 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3028 	pSMB->DataCount = cpu_to_le16(name_len_target);
3029 	pSMB->TotalDataCount = pSMB->DataCount;
3030 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3031 	pSMB->DataOffset = cpu_to_le16(offset);
3032 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3033 	pSMB->Reserved4 = 0;
3034 	inc_rfc1001_len(pSMB, byte_count);
3035 	pSMB->ByteCount = cpu_to_le16(byte_count);
3036 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3037 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3038 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3039 	if (rc)
3040 		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
3041 			 rc);
3042 
3043 	cifs_buf_release(pSMB);
3044 	if (rc == -EAGAIN)
3045 		goto createHardLinkRetry;
3046 
3047 	return rc;
3048 }
3049 
3050 int
CIFSCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)3051 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3052 		   const char *from_name, const char *to_name,
3053 		   struct cifs_sb_info *cifs_sb)
3054 {
3055 	int rc = 0;
3056 	NT_RENAME_REQ *pSMB = NULL;
3057 	RENAME_RSP *pSMBr = NULL;
3058 	int bytes_returned;
3059 	int name_len, name_len2;
3060 	__u16 count;
3061 	int remap = cifs_remap(cifs_sb);
3062 
3063 	cifs_dbg(FYI, "In CIFSCreateHardLink\n");
3064 winCreateHardLinkRetry:
3065 
3066 	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3067 		      (void **) &pSMBr);
3068 	if (rc)
3069 		return rc;
3070 
3071 	pSMB->SearchAttributes =
3072 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3073 			ATTR_DIRECTORY);
3074 	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3075 	pSMB->ClusterCount = 0;
3076 
3077 	pSMB->BufferFormat = 0x04;
3078 
3079 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3080 		name_len =
3081 		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3082 				       PATH_MAX, cifs_sb->local_nls, remap);
3083 		name_len++;	/* trailing null */
3084 		name_len *= 2;
3085 
3086 		/* protocol specifies ASCII buffer format (0x04) for unicode */
3087 		pSMB->OldFileName[name_len] = 0x04;
3088 		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3089 		name_len2 =
3090 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3091 				       to_name, PATH_MAX, cifs_sb->local_nls,
3092 				       remap);
3093 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
3094 		name_len2 *= 2;	/* convert to bytes */
3095 	} else {	/* BB improve the check for buffer overruns BB */
3096 		name_len = strnlen(from_name, PATH_MAX);
3097 		name_len++;	/* trailing null */
3098 		strncpy(pSMB->OldFileName, from_name, name_len);
3099 		name_len2 = strnlen(to_name, PATH_MAX);
3100 		name_len2++;	/* trailing null */
3101 		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
3102 		strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
3103 		name_len2++;	/* trailing null */
3104 		name_len2++;	/* signature byte */
3105 	}
3106 
3107 	count = 1 /* string type byte */  + name_len + name_len2;
3108 	inc_rfc1001_len(pSMB, count);
3109 	pSMB->ByteCount = cpu_to_le16(count);
3110 
3111 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3112 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3113 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3114 	if (rc)
3115 		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3116 
3117 	cifs_buf_release(pSMB);
3118 	if (rc == -EAGAIN)
3119 		goto winCreateHardLinkRetry;
3120 
3121 	return rc;
3122 }
3123 
3124 int
CIFSSMBUnixQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char ** symlinkinfo,const struct nls_table * nls_codepage,int remap)3125 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3126 			const unsigned char *searchName, char **symlinkinfo,
3127 			const struct nls_table *nls_codepage, int remap)
3128 {
3129 /* SMB_QUERY_FILE_UNIX_LINK */
3130 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3131 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3132 	int rc = 0;
3133 	int bytes_returned;
3134 	int name_len;
3135 	__u16 params, byte_count;
3136 	char *data_start;
3137 
3138 	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3139 
3140 querySymLinkRetry:
3141 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3142 		      (void **) &pSMBr);
3143 	if (rc)
3144 		return rc;
3145 
3146 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3147 		name_len =
3148 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3149 					   searchName, PATH_MAX, nls_codepage,
3150 					   remap);
3151 		name_len++;	/* trailing null */
3152 		name_len *= 2;
3153 	} else {	/* BB improve the check for buffer overruns BB */
3154 		name_len = strnlen(searchName, PATH_MAX);
3155 		name_len++;	/* trailing null */
3156 		strncpy(pSMB->FileName, searchName, name_len);
3157 	}
3158 
3159 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3160 	pSMB->TotalDataCount = 0;
3161 	pSMB->MaxParameterCount = cpu_to_le16(2);
3162 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3163 	pSMB->MaxSetupCount = 0;
3164 	pSMB->Reserved = 0;
3165 	pSMB->Flags = 0;
3166 	pSMB->Timeout = 0;
3167 	pSMB->Reserved2 = 0;
3168 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
3169 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3170 	pSMB->DataCount = 0;
3171 	pSMB->DataOffset = 0;
3172 	pSMB->SetupCount = 1;
3173 	pSMB->Reserved3 = 0;
3174 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3175 	byte_count = params + 1 /* pad */ ;
3176 	pSMB->TotalParameterCount = cpu_to_le16(params);
3177 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3178 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3179 	pSMB->Reserved4 = 0;
3180 	inc_rfc1001_len(pSMB, byte_count);
3181 	pSMB->ByteCount = cpu_to_le16(byte_count);
3182 
3183 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3184 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3185 	if (rc) {
3186 		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3187 	} else {
3188 		/* decode response */
3189 
3190 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3191 		/* BB also check enough total bytes returned */
3192 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3193 			rc = -EIO;
3194 		else {
3195 			bool is_unicode;
3196 			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3197 
3198 			data_start = ((char *) &pSMBr->hdr.Protocol) +
3199 					   le16_to_cpu(pSMBr->t2.DataOffset);
3200 
3201 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3202 				is_unicode = true;
3203 			else
3204 				is_unicode = false;
3205 
3206 			/* BB FIXME investigate remapping reserved chars here */
3207 			*symlinkinfo = cifs_strndup_from_utf16(data_start,
3208 					count, is_unicode, nls_codepage);
3209 			if (!*symlinkinfo)
3210 				rc = -ENOMEM;
3211 		}
3212 	}
3213 	cifs_buf_release(pSMB);
3214 	if (rc == -EAGAIN)
3215 		goto querySymLinkRetry;
3216 	return rc;
3217 }
3218 
3219 /*
3220  *	Recent Windows versions now create symlinks more frequently
3221  *	and they use the "reparse point" mechanism below.  We can of course
3222  *	do symlinks nicely to Samba and other servers which support the
3223  *	CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3224  *	"MF" symlinks optionally, but for recent Windows we really need to
3225  *	reenable the code below and fix the cifs_symlink callers to handle this.
3226  *	In the interim this code has been moved to its own config option so
3227  *	it is not compiled in by default until callers fixed up and more tested.
3228  */
3229 int
CIFSSMBQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,char ** symlinkinfo,const struct nls_table * nls_codepage)3230 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3231 		    __u16 fid, char **symlinkinfo,
3232 		    const struct nls_table *nls_codepage)
3233 {
3234 	int rc = 0;
3235 	int bytes_returned;
3236 	struct smb_com_transaction_ioctl_req *pSMB;
3237 	struct smb_com_transaction_ioctl_rsp *pSMBr;
3238 	bool is_unicode;
3239 	unsigned int sub_len;
3240 	char *sub_start;
3241 	struct reparse_symlink_data *reparse_buf;
3242 	struct reparse_posix_data *posix_buf;
3243 	__u32 data_offset, data_count;
3244 	char *end_of_smb;
3245 
3246 	cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3247 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3248 		      (void **) &pSMBr);
3249 	if (rc)
3250 		return rc;
3251 
3252 	pSMB->TotalParameterCount = 0 ;
3253 	pSMB->TotalDataCount = 0;
3254 	pSMB->MaxParameterCount = cpu_to_le32(2);
3255 	/* BB find exact data count max from sess structure BB */
3256 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3257 	pSMB->MaxSetupCount = 4;
3258 	pSMB->Reserved = 0;
3259 	pSMB->ParameterOffset = 0;
3260 	pSMB->DataCount = 0;
3261 	pSMB->DataOffset = 0;
3262 	pSMB->SetupCount = 4;
3263 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3264 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3265 	pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3266 	pSMB->IsFsctl = 1; /* FSCTL */
3267 	pSMB->IsRootFlag = 0;
3268 	pSMB->Fid = fid; /* file handle always le */
3269 	pSMB->ByteCount = 0;
3270 
3271 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3272 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3273 	if (rc) {
3274 		cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3275 		goto qreparse_out;
3276 	}
3277 
3278 	data_offset = le32_to_cpu(pSMBr->DataOffset);
3279 	data_count = le32_to_cpu(pSMBr->DataCount);
3280 	if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3281 		/* BB also check enough total bytes returned */
3282 		rc = -EIO;	/* bad smb */
3283 		goto qreparse_out;
3284 	}
3285 	if (!data_count || (data_count > 2048)) {
3286 		rc = -EIO;
3287 		cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3288 		goto qreparse_out;
3289 	}
3290 	end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3291 	reparse_buf = (struct reparse_symlink_data *)
3292 				((char *)&pSMBr->hdr.Protocol + data_offset);
3293 	if ((char *)reparse_buf >= end_of_smb) {
3294 		rc = -EIO;
3295 		goto qreparse_out;
3296 	}
3297 	if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3298 		cifs_dbg(FYI, "NFS style reparse tag\n");
3299 		posix_buf =  (struct reparse_posix_data *)reparse_buf;
3300 
3301 		if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3302 			cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3303 				 le64_to_cpu(posix_buf->InodeType));
3304 			rc = -EOPNOTSUPP;
3305 			goto qreparse_out;
3306 		}
3307 		is_unicode = true;
3308 		sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3309 		if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3310 			cifs_dbg(FYI, "reparse buf beyond SMB\n");
3311 			rc = -EIO;
3312 			goto qreparse_out;
3313 		}
3314 		*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3315 				sub_len, is_unicode, nls_codepage);
3316 		goto qreparse_out;
3317 	} else if (reparse_buf->ReparseTag !=
3318 			cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3319 		rc = -EOPNOTSUPP;
3320 		goto qreparse_out;
3321 	}
3322 
3323 	/* Reparse tag is NTFS symlink */
3324 	sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3325 				reparse_buf->PathBuffer;
3326 	sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3327 	if (sub_start + sub_len > end_of_smb) {
3328 		cifs_dbg(FYI, "reparse buf beyond SMB\n");
3329 		rc = -EIO;
3330 		goto qreparse_out;
3331 	}
3332 	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3333 		is_unicode = true;
3334 	else
3335 		is_unicode = false;
3336 
3337 	/* BB FIXME investigate remapping reserved chars here */
3338 	*symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3339 					       nls_codepage);
3340 	if (!*symlinkinfo)
3341 		rc = -ENOMEM;
3342 qreparse_out:
3343 	cifs_buf_release(pSMB);
3344 
3345 	/*
3346 	 * Note: On -EAGAIN error only caller can retry on handle based calls
3347 	 * since file handle passed in no longer valid.
3348 	 */
3349 	return rc;
3350 }
3351 
3352 int
CIFSSMB_set_compression(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid)3353 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3354 		    __u16 fid)
3355 {
3356 	int rc = 0;
3357 	int bytes_returned;
3358 	struct smb_com_transaction_compr_ioctl_req *pSMB;
3359 	struct smb_com_transaction_ioctl_rsp *pSMBr;
3360 
3361 	cifs_dbg(FYI, "Set compression for %u\n", fid);
3362 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3363 		      (void **) &pSMBr);
3364 	if (rc)
3365 		return rc;
3366 
3367 	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3368 
3369 	pSMB->TotalParameterCount = 0;
3370 	pSMB->TotalDataCount = cpu_to_le32(2);
3371 	pSMB->MaxParameterCount = 0;
3372 	pSMB->MaxDataCount = 0;
3373 	pSMB->MaxSetupCount = 4;
3374 	pSMB->Reserved = 0;
3375 	pSMB->ParameterOffset = 0;
3376 	pSMB->DataCount = cpu_to_le32(2);
3377 	pSMB->DataOffset =
3378 		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3379 				compression_state) - 4);  /* 84 */
3380 	pSMB->SetupCount = 4;
3381 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3382 	pSMB->ParameterCount = 0;
3383 	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3384 	pSMB->IsFsctl = 1; /* FSCTL */
3385 	pSMB->IsRootFlag = 0;
3386 	pSMB->Fid = fid; /* file handle always le */
3387 	/* 3 byte pad, followed by 2 byte compress state */
3388 	pSMB->ByteCount = cpu_to_le16(5);
3389 	inc_rfc1001_len(pSMB, 5);
3390 
3391 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3392 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3393 	if (rc)
3394 		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3395 
3396 	cifs_buf_release(pSMB);
3397 
3398 	/*
3399 	 * Note: On -EAGAIN error only caller can retry on handle based calls
3400 	 * since file handle passed in no longer valid.
3401 	 */
3402 	return rc;
3403 }
3404 
3405 
3406 #ifdef CONFIG_CIFS_POSIX
3407 
3408 /*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)3409 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3410 			     struct cifs_posix_ace *cifs_ace)
3411 {
3412 	/* u8 cifs fields do not need le conversion */
3413 	ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3414 	ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3415 	ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3416 /*
3417 	cifs_dbg(FYI, "perm %d tag %d id %d\n",
3418 		 ace->e_perm, ace->e_tag, ace->e_id);
3419 */
3420 
3421 	return;
3422 }
3423 
3424 /* 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)3425 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3426 			       const int acl_type, const int size_of_data_area)
3427 {
3428 	int size =  0;
3429 	int i;
3430 	__u16 count;
3431 	struct cifs_posix_ace *pACE;
3432 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3433 	struct posix_acl_xattr_header *local_acl = (void *)trgt;
3434 
3435 	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3436 		return -EOPNOTSUPP;
3437 
3438 	if (acl_type == ACL_TYPE_ACCESS) {
3439 		count = le16_to_cpu(cifs_acl->access_entry_count);
3440 		pACE = &cifs_acl->ace_array[0];
3441 		size = sizeof(struct cifs_posix_acl);
3442 		size += sizeof(struct cifs_posix_ace) * count;
3443 		/* check if we would go beyond end of SMB */
3444 		if (size_of_data_area < size) {
3445 			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3446 				 size_of_data_area, size);
3447 			return -EINVAL;
3448 		}
3449 	} else if (acl_type == ACL_TYPE_DEFAULT) {
3450 		count = le16_to_cpu(cifs_acl->access_entry_count);
3451 		size = sizeof(struct cifs_posix_acl);
3452 		size += sizeof(struct cifs_posix_ace) * count;
3453 /* skip past access ACEs to get to default ACEs */
3454 		pACE = &cifs_acl->ace_array[count];
3455 		count = le16_to_cpu(cifs_acl->default_entry_count);
3456 		size += sizeof(struct cifs_posix_ace) * count;
3457 		/* check if we would go beyond end of SMB */
3458 		if (size_of_data_area < size)
3459 			return -EINVAL;
3460 	} else {
3461 		/* illegal type */
3462 		return -EINVAL;
3463 	}
3464 
3465 	size = posix_acl_xattr_size(count);
3466 	if ((buflen == 0) || (local_acl == NULL)) {
3467 		/* used to query ACL EA size */
3468 	} else if (size > buflen) {
3469 		return -ERANGE;
3470 	} else /* buffer big enough */ {
3471 		struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3472 
3473 		local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3474 		for (i = 0; i < count ; i++) {
3475 			cifs_convert_ace(&ace[i], pACE);
3476 			pACE++;
3477 		}
3478 	}
3479 	return size;
3480 }
3481 
convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,const struct posix_acl_xattr_entry * local_ace)3482 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3483 				     const struct posix_acl_xattr_entry *local_ace)
3484 {
3485 	__u16 rc = 0; /* 0 = ACL converted ok */
3486 
3487 	cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3488 	cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3489 	/* BB is there a better way to handle the large uid? */
3490 	if (local_ace->e_id == cpu_to_le32(-1)) {
3491 	/* Probably no need to le convert -1 on any arch but can not hurt */
3492 		cifs_ace->cifs_uid = cpu_to_le64(-1);
3493 	} else
3494 		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3495 /*
3496 	cifs_dbg(FYI, "perm %d tag %d id %d\n",
3497 		 ace->e_perm, ace->e_tag, ace->e_id);
3498 */
3499 	return rc;
3500 }
3501 
3502 /* 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)3503 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3504 			       const int buflen, const int acl_type)
3505 {
3506 	__u16 rc = 0;
3507 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3508 	struct posix_acl_xattr_header *local_acl = (void *)pACL;
3509 	struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3510 	int count;
3511 	int i;
3512 
3513 	if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3514 		return 0;
3515 
3516 	count = posix_acl_xattr_count((size_t)buflen);
3517 	cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3518 		 count, buflen, le32_to_cpu(local_acl->a_version));
3519 	if (le32_to_cpu(local_acl->a_version) != 2) {
3520 		cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3521 			 le32_to_cpu(local_acl->a_version));
3522 		return 0;
3523 	}
3524 	cifs_acl->version = cpu_to_le16(1);
3525 	if (acl_type == ACL_TYPE_ACCESS) {
3526 		cifs_acl->access_entry_count = cpu_to_le16(count);
3527 		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3528 	} else if (acl_type == ACL_TYPE_DEFAULT) {
3529 		cifs_acl->default_entry_count = cpu_to_le16(count);
3530 		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3531 	} else {
3532 		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3533 		return 0;
3534 	}
3535 	for (i = 0; i < count; i++) {
3536 		rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3537 		if (rc != 0) {
3538 			/* ACE not converted */
3539 			break;
3540 		}
3541 	}
3542 	if (rc == 0) {
3543 		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3544 		rc += sizeof(struct cifs_posix_acl);
3545 		/* BB add check to make sure ACL does not overflow SMB */
3546 	}
3547 	return rc;
3548 }
3549 
3550 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)3551 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3552 		   const unsigned char *searchName,
3553 		   char *acl_inf, const int buflen, const int acl_type,
3554 		   const struct nls_table *nls_codepage, int remap)
3555 {
3556 /* SMB_QUERY_POSIX_ACL */
3557 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3558 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3559 	int rc = 0;
3560 	int bytes_returned;
3561 	int name_len;
3562 	__u16 params, byte_count;
3563 
3564 	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3565 
3566 queryAclRetry:
3567 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3568 		(void **) &pSMBr);
3569 	if (rc)
3570 		return rc;
3571 
3572 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3573 		name_len =
3574 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3575 					   searchName, PATH_MAX, nls_codepage,
3576 					   remap);
3577 		name_len++;     /* trailing null */
3578 		name_len *= 2;
3579 		pSMB->FileName[name_len] = 0;
3580 		pSMB->FileName[name_len+1] = 0;
3581 	} else {	/* BB improve the check for buffer overruns BB */
3582 		name_len = strnlen(searchName, PATH_MAX);
3583 		name_len++;     /* trailing null */
3584 		strncpy(pSMB->FileName, searchName, name_len);
3585 	}
3586 
3587 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3588 	pSMB->TotalDataCount = 0;
3589 	pSMB->MaxParameterCount = cpu_to_le16(2);
3590 	/* BB find exact max data count below from sess structure BB */
3591 	pSMB->MaxDataCount = cpu_to_le16(4000);
3592 	pSMB->MaxSetupCount = 0;
3593 	pSMB->Reserved = 0;
3594 	pSMB->Flags = 0;
3595 	pSMB->Timeout = 0;
3596 	pSMB->Reserved2 = 0;
3597 	pSMB->ParameterOffset = cpu_to_le16(
3598 		offsetof(struct smb_com_transaction2_qpi_req,
3599 			 InformationLevel) - 4);
3600 	pSMB->DataCount = 0;
3601 	pSMB->DataOffset = 0;
3602 	pSMB->SetupCount = 1;
3603 	pSMB->Reserved3 = 0;
3604 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3605 	byte_count = params + 1 /* pad */ ;
3606 	pSMB->TotalParameterCount = cpu_to_le16(params);
3607 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3608 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3609 	pSMB->Reserved4 = 0;
3610 	inc_rfc1001_len(pSMB, byte_count);
3611 	pSMB->ByteCount = cpu_to_le16(byte_count);
3612 
3613 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3614 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3615 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3616 	if (rc) {
3617 		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3618 	} else {
3619 		/* decode response */
3620 
3621 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3622 		/* BB also check enough total bytes returned */
3623 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3624 			rc = -EIO;      /* bad smb */
3625 		else {
3626 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3627 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3628 			rc = cifs_copy_posix_acl(acl_inf,
3629 				(char *)&pSMBr->hdr.Protocol+data_offset,
3630 				buflen, acl_type, count);
3631 		}
3632 	}
3633 	cifs_buf_release(pSMB);
3634 	if (rc == -EAGAIN)
3635 		goto queryAclRetry;
3636 	return rc;
3637 }
3638 
3639 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)3640 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3641 		   const unsigned char *fileName,
3642 		   const char *local_acl, const int buflen,
3643 		   const int acl_type,
3644 		   const struct nls_table *nls_codepage, int remap)
3645 {
3646 	struct smb_com_transaction2_spi_req *pSMB = NULL;
3647 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3648 	char *parm_data;
3649 	int name_len;
3650 	int rc = 0;
3651 	int bytes_returned = 0;
3652 	__u16 params, byte_count, data_count, param_offset, offset;
3653 
3654 	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3655 setAclRetry:
3656 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3657 		      (void **) &pSMBr);
3658 	if (rc)
3659 		return rc;
3660 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3661 		name_len =
3662 			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3663 					   PATH_MAX, nls_codepage, remap);
3664 		name_len++;     /* trailing null */
3665 		name_len *= 2;
3666 	} else {	/* BB improve the check for buffer overruns BB */
3667 		name_len = strnlen(fileName, PATH_MAX);
3668 		name_len++;     /* trailing null */
3669 		strncpy(pSMB->FileName, fileName, name_len);
3670 	}
3671 	params = 6 + name_len;
3672 	pSMB->MaxParameterCount = cpu_to_le16(2);
3673 	/* BB find max SMB size from sess */
3674 	pSMB->MaxDataCount = cpu_to_le16(1000);
3675 	pSMB->MaxSetupCount = 0;
3676 	pSMB->Reserved = 0;
3677 	pSMB->Flags = 0;
3678 	pSMB->Timeout = 0;
3679 	pSMB->Reserved2 = 0;
3680 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3681 				InformationLevel) - 4;
3682 	offset = param_offset + params;
3683 	parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3684 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3685 
3686 	/* convert to on the wire format for POSIX ACL */
3687 	data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3688 
3689 	if (data_count == 0) {
3690 		rc = -EOPNOTSUPP;
3691 		goto setACLerrorExit;
3692 	}
3693 	pSMB->DataOffset = cpu_to_le16(offset);
3694 	pSMB->SetupCount = 1;
3695 	pSMB->Reserved3 = 0;
3696 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3697 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3698 	byte_count = 3 /* pad */  + params + data_count;
3699 	pSMB->DataCount = cpu_to_le16(data_count);
3700 	pSMB->TotalDataCount = pSMB->DataCount;
3701 	pSMB->ParameterCount = cpu_to_le16(params);
3702 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3703 	pSMB->Reserved4 = 0;
3704 	inc_rfc1001_len(pSMB, byte_count);
3705 	pSMB->ByteCount = cpu_to_le16(byte_count);
3706 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3707 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3708 	if (rc)
3709 		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3710 
3711 setACLerrorExit:
3712 	cifs_buf_release(pSMB);
3713 	if (rc == -EAGAIN)
3714 		goto setAclRetry;
3715 	return rc;
3716 }
3717 
3718 /* BB fix tabs in this function FIXME BB */
3719 int
CIFSGetExtAttr(const unsigned int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3720 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3721 	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3722 {
3723 	int rc = 0;
3724 	struct smb_t2_qfi_req *pSMB = NULL;
3725 	struct smb_t2_qfi_rsp *pSMBr = NULL;
3726 	int bytes_returned;
3727 	__u16 params, byte_count;
3728 
3729 	cifs_dbg(FYI, "In GetExtAttr\n");
3730 	if (tcon == NULL)
3731 		return -ENODEV;
3732 
3733 GetExtAttrRetry:
3734 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3735 			(void **) &pSMBr);
3736 	if (rc)
3737 		return rc;
3738 
3739 	params = 2 /* level */ + 2 /* fid */;
3740 	pSMB->t2.TotalDataCount = 0;
3741 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3742 	/* BB find exact max data count below from sess structure BB */
3743 	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3744 	pSMB->t2.MaxSetupCount = 0;
3745 	pSMB->t2.Reserved = 0;
3746 	pSMB->t2.Flags = 0;
3747 	pSMB->t2.Timeout = 0;
3748 	pSMB->t2.Reserved2 = 0;
3749 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3750 					       Fid) - 4);
3751 	pSMB->t2.DataCount = 0;
3752 	pSMB->t2.DataOffset = 0;
3753 	pSMB->t2.SetupCount = 1;
3754 	pSMB->t2.Reserved3 = 0;
3755 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3756 	byte_count = params + 1 /* pad */ ;
3757 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3758 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3759 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3760 	pSMB->Pad = 0;
3761 	pSMB->Fid = netfid;
3762 	inc_rfc1001_len(pSMB, byte_count);
3763 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3764 
3765 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3766 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3767 	if (rc) {
3768 		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3769 	} else {
3770 		/* decode response */
3771 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3772 		/* BB also check enough total bytes returned */
3773 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3774 			/* If rc should we check for EOPNOSUPP and
3775 			   disable the srvino flag? or in caller? */
3776 			rc = -EIO;      /* bad smb */
3777 		else {
3778 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3779 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3780 			struct file_chattr_info *pfinfo;
3781 			/* BB Do we need a cast or hash here ? */
3782 			if (count != 16) {
3783 				cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3784 				rc = -EIO;
3785 				goto GetExtAttrOut;
3786 			}
3787 			pfinfo = (struct file_chattr_info *)
3788 				 (data_offset + (char *) &pSMBr->hdr.Protocol);
3789 			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
3790 			*pMask = le64_to_cpu(pfinfo->mask);
3791 		}
3792 	}
3793 GetExtAttrOut:
3794 	cifs_buf_release(pSMB);
3795 	if (rc == -EAGAIN)
3796 		goto GetExtAttrRetry;
3797 	return rc;
3798 }
3799 
3800 #endif /* CONFIG_POSIX */
3801 
3802 #ifdef CONFIG_CIFS_ACL
3803 /*
3804  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3805  * all NT TRANSACTS that we init here have total parm and data under about 400
3806  * bytes (to fit in small cifs buffer size), which is the case so far, it
3807  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3808  * returned setup area) and MaxParameterCount (returned parms size) must be set
3809  * by caller
3810  */
3811 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3812 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3813 		   const int parm_len, struct cifs_tcon *tcon,
3814 		   void **ret_buf)
3815 {
3816 	int rc;
3817 	__u32 temp_offset;
3818 	struct smb_com_ntransact_req *pSMB;
3819 
3820 	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3821 				(void **)&pSMB);
3822 	if (rc)
3823 		return rc;
3824 	*ret_buf = (void *)pSMB;
3825 	pSMB->Reserved = 0;
3826 	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3827 	pSMB->TotalDataCount  = 0;
3828 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3829 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3830 	pSMB->DataCount  = pSMB->TotalDataCount;
3831 	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3832 			(setup_count * 2) - 4 /* for rfc1001 length itself */;
3833 	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3834 	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3835 	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3836 	pSMB->SubCommand = cpu_to_le16(sub_command);
3837 	return 0;
3838 }
3839 
3840 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3841 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3842 		   __u32 *pparmlen, __u32 *pdatalen)
3843 {
3844 	char *end_of_smb;
3845 	__u32 data_count, data_offset, parm_count, parm_offset;
3846 	struct smb_com_ntransact_rsp *pSMBr;
3847 	u16 bcc;
3848 
3849 	*pdatalen = 0;
3850 	*pparmlen = 0;
3851 
3852 	if (buf == NULL)
3853 		return -EINVAL;
3854 
3855 	pSMBr = (struct smb_com_ntransact_rsp *)buf;
3856 
3857 	bcc = get_bcc(&pSMBr->hdr);
3858 	end_of_smb = 2 /* sizeof byte count */ + bcc +
3859 			(char *)&pSMBr->ByteCount;
3860 
3861 	data_offset = le32_to_cpu(pSMBr->DataOffset);
3862 	data_count = le32_to_cpu(pSMBr->DataCount);
3863 	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3864 	parm_count = le32_to_cpu(pSMBr->ParameterCount);
3865 
3866 	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3867 	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3868 
3869 	/* should we also check that parm and data areas do not overlap? */
3870 	if (*ppparm > end_of_smb) {
3871 		cifs_dbg(FYI, "parms start after end of smb\n");
3872 		return -EINVAL;
3873 	} else if (parm_count + *ppparm > end_of_smb) {
3874 		cifs_dbg(FYI, "parm end after end of smb\n");
3875 		return -EINVAL;
3876 	} else if (*ppdata > end_of_smb) {
3877 		cifs_dbg(FYI, "data starts after end of smb\n");
3878 		return -EINVAL;
3879 	} else if (data_count + *ppdata > end_of_smb) {
3880 		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3881 			 *ppdata, data_count, (data_count + *ppdata),
3882 			 end_of_smb, pSMBr);
3883 		return -EINVAL;
3884 	} else if (parm_count + data_count > bcc) {
3885 		cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3886 		return -EINVAL;
3887 	}
3888 	*pdatalen = data_count;
3889 	*pparmlen = parm_count;
3890 	return 0;
3891 }
3892 
3893 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3894 int
CIFSSMBGetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd ** acl_inf,__u32 * pbuflen)3895 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3896 		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3897 {
3898 	int rc = 0;
3899 	int buf_type = 0;
3900 	QUERY_SEC_DESC_REQ *pSMB;
3901 	struct kvec iov[1];
3902 	struct kvec rsp_iov;
3903 
3904 	cifs_dbg(FYI, "GetCifsACL\n");
3905 
3906 	*pbuflen = 0;
3907 	*acl_inf = NULL;
3908 
3909 	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3910 			8 /* parm len */, tcon, (void **) &pSMB);
3911 	if (rc)
3912 		return rc;
3913 
3914 	pSMB->MaxParameterCount = cpu_to_le32(4);
3915 	/* BB TEST with big acls that might need to be e.g. larger than 16K */
3916 	pSMB->MaxSetupCount = 0;
3917 	pSMB->Fid = fid; /* file handle always le */
3918 	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3919 				     CIFS_ACL_DACL);
3920 	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3921 	inc_rfc1001_len(pSMB, 11);
3922 	iov[0].iov_base = (char *)pSMB;
3923 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3924 
3925 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3926 			  0, &rsp_iov);
3927 	cifs_small_buf_release(pSMB);
3928 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3929 	if (rc) {
3930 		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3931 	} else {                /* decode response */
3932 		__le32 *parm;
3933 		__u32 parm_len;
3934 		__u32 acl_len;
3935 		struct smb_com_ntransact_rsp *pSMBr;
3936 		char *pdata;
3937 
3938 /* validate_nttransact */
3939 		rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3940 					&pdata, &parm_len, pbuflen);
3941 		if (rc)
3942 			goto qsec_out;
3943 		pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3944 
3945 		cifs_dbg(FYI, "smb %p parm %p data %p\n",
3946 			 pSMBr, parm, *acl_inf);
3947 
3948 		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3949 			rc = -EIO;      /* bad smb */
3950 			*pbuflen = 0;
3951 			goto qsec_out;
3952 		}
3953 
3954 /* BB check that data area is minimum length and as big as acl_len */
3955 
3956 		acl_len = le32_to_cpu(*parm);
3957 		if (acl_len != *pbuflen) {
3958 			cifs_dbg(VFS, "acl length %d does not match %d\n",
3959 				 acl_len, *pbuflen);
3960 			if (*pbuflen > acl_len)
3961 				*pbuflen = acl_len;
3962 		}
3963 
3964 		/* check if buffer is big enough for the acl
3965 		   header followed by the smallest SID */
3966 		if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3967 		    (*pbuflen >= 64 * 1024)) {
3968 			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3969 			rc = -EINVAL;
3970 			*pbuflen = 0;
3971 		} else {
3972 			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3973 			if (*acl_inf == NULL) {
3974 				*pbuflen = 0;
3975 				rc = -ENOMEM;
3976 			}
3977 		}
3978 	}
3979 qsec_out:
3980 	free_rsp_buf(buf_type, rsp_iov.iov_base);
3981 	return rc;
3982 }
3983 
3984 int
CIFSSMBSetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd * pntsd,__u32 acllen,int aclflag)3985 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3986 			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3987 {
3988 	__u16 byte_count, param_count, data_count, param_offset, data_offset;
3989 	int rc = 0;
3990 	int bytes_returned = 0;
3991 	SET_SEC_DESC_REQ *pSMB = NULL;
3992 	void *pSMBr;
3993 
3994 setCifsAclRetry:
3995 	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3996 	if (rc)
3997 		return rc;
3998 
3999 	pSMB->MaxSetupCount = 0;
4000 	pSMB->Reserved = 0;
4001 
4002 	param_count = 8;
4003 	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
4004 	data_count = acllen;
4005 	data_offset = param_offset + param_count;
4006 	byte_count = 3 /* pad */  + param_count;
4007 
4008 	pSMB->DataCount = cpu_to_le32(data_count);
4009 	pSMB->TotalDataCount = pSMB->DataCount;
4010 	pSMB->MaxParameterCount = cpu_to_le32(4);
4011 	pSMB->MaxDataCount = cpu_to_le32(16384);
4012 	pSMB->ParameterCount = cpu_to_le32(param_count);
4013 	pSMB->ParameterOffset = cpu_to_le32(param_offset);
4014 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4015 	pSMB->DataOffset = cpu_to_le32(data_offset);
4016 	pSMB->SetupCount = 0;
4017 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
4018 	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
4019 
4020 	pSMB->Fid = fid; /* file handle always le */
4021 	pSMB->Reserved2 = 0;
4022 	pSMB->AclFlags = cpu_to_le32(aclflag);
4023 
4024 	if (pntsd && acllen) {
4025 		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
4026 				data_offset, pntsd, acllen);
4027 		inc_rfc1001_len(pSMB, byte_count + data_count);
4028 	} else
4029 		inc_rfc1001_len(pSMB, byte_count);
4030 
4031 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4032 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4033 
4034 	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
4035 		 bytes_returned, rc);
4036 	if (rc)
4037 		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
4038 	cifs_buf_release(pSMB);
4039 
4040 	if (rc == -EAGAIN)
4041 		goto setCifsAclRetry;
4042 
4043 	return (rc);
4044 }
4045 
4046 #endif /* CONFIG_CIFS_ACL */
4047 
4048 /* Legacy Query Path Information call for lookup to old servers such
4049    as Win9x/WinME */
4050 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)4051 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
4052 		    const char *search_name, FILE_ALL_INFO *data,
4053 		    const struct nls_table *nls_codepage, int remap)
4054 {
4055 	QUERY_INFORMATION_REQ *pSMB;
4056 	QUERY_INFORMATION_RSP *pSMBr;
4057 	int rc = 0;
4058 	int bytes_returned;
4059 	int name_len;
4060 
4061 	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
4062 QInfRetry:
4063 	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4064 		      (void **) &pSMBr);
4065 	if (rc)
4066 		return rc;
4067 
4068 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4069 		name_len =
4070 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4071 					   search_name, PATH_MAX, nls_codepage,
4072 					   remap);
4073 		name_len++;     /* trailing null */
4074 		name_len *= 2;
4075 	} else {
4076 		name_len = strnlen(search_name, PATH_MAX);
4077 		name_len++;     /* trailing null */
4078 		strncpy(pSMB->FileName, search_name, name_len);
4079 	}
4080 	pSMB->BufferFormat = 0x04;
4081 	name_len++; /* account for buffer type byte */
4082 	inc_rfc1001_len(pSMB, (__u16)name_len);
4083 	pSMB->ByteCount = cpu_to_le16(name_len);
4084 
4085 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4086 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4087 	if (rc) {
4088 		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4089 	} else if (data) {
4090 		struct timespec64 ts;
4091 		__u32 time = le32_to_cpu(pSMBr->last_write_time);
4092 
4093 		/* decode response */
4094 		/* BB FIXME - add time zone adjustment BB */
4095 		memset(data, 0, sizeof(FILE_ALL_INFO));
4096 		ts.tv_nsec = 0;
4097 		ts.tv_sec = time;
4098 		/* decode time fields */
4099 		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4100 		data->LastWriteTime = data->ChangeTime;
4101 		data->LastAccessTime = 0;
4102 		data->AllocationSize =
4103 			cpu_to_le64(le32_to_cpu(pSMBr->size));
4104 		data->EndOfFile = data->AllocationSize;
4105 		data->Attributes =
4106 			cpu_to_le32(le16_to_cpu(pSMBr->attr));
4107 	} else
4108 		rc = -EIO; /* bad buffer passed in */
4109 
4110 	cifs_buf_release(pSMB);
4111 
4112 	if (rc == -EAGAIN)
4113 		goto QInfRetry;
4114 
4115 	return rc;
4116 }
4117 
4118 int
CIFSSMBQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)4119 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4120 		 u16 netfid, FILE_ALL_INFO *pFindData)
4121 {
4122 	struct smb_t2_qfi_req *pSMB = NULL;
4123 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4124 	int rc = 0;
4125 	int bytes_returned;
4126 	__u16 params, byte_count;
4127 
4128 QFileInfoRetry:
4129 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4130 		      (void **) &pSMBr);
4131 	if (rc)
4132 		return rc;
4133 
4134 	params = 2 /* level */ + 2 /* fid */;
4135 	pSMB->t2.TotalDataCount = 0;
4136 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4137 	/* BB find exact max data count below from sess structure BB */
4138 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4139 	pSMB->t2.MaxSetupCount = 0;
4140 	pSMB->t2.Reserved = 0;
4141 	pSMB->t2.Flags = 0;
4142 	pSMB->t2.Timeout = 0;
4143 	pSMB->t2.Reserved2 = 0;
4144 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4145 					       Fid) - 4);
4146 	pSMB->t2.DataCount = 0;
4147 	pSMB->t2.DataOffset = 0;
4148 	pSMB->t2.SetupCount = 1;
4149 	pSMB->t2.Reserved3 = 0;
4150 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4151 	byte_count = params + 1 /* pad */ ;
4152 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4153 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4154 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4155 	pSMB->Pad = 0;
4156 	pSMB->Fid = netfid;
4157 	inc_rfc1001_len(pSMB, byte_count);
4158 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4159 
4160 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4161 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4162 	if (rc) {
4163 		cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4164 	} else {		/* decode response */
4165 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4166 
4167 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4168 			rc = -EIO;
4169 		else if (get_bcc(&pSMBr->hdr) < 40)
4170 			rc = -EIO;	/* bad smb */
4171 		else if (pFindData) {
4172 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4173 			memcpy((char *) pFindData,
4174 			       (char *) &pSMBr->hdr.Protocol +
4175 			       data_offset, sizeof(FILE_ALL_INFO));
4176 		} else
4177 		    rc = -ENOMEM;
4178 	}
4179 	cifs_buf_release(pSMB);
4180 	if (rc == -EAGAIN)
4181 		goto QFileInfoRetry;
4182 
4183 	return rc;
4184 }
4185 
4186 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)4187 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4188 		 const char *search_name, FILE_ALL_INFO *data,
4189 		 int legacy /* old style infolevel */,
4190 		 const struct nls_table *nls_codepage, int remap)
4191 {
4192 	/* level 263 SMB_QUERY_FILE_ALL_INFO */
4193 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4194 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4195 	int rc = 0;
4196 	int bytes_returned;
4197 	int name_len;
4198 	__u16 params, byte_count;
4199 
4200 	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4201 QPathInfoRetry:
4202 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4203 		      (void **) &pSMBr);
4204 	if (rc)
4205 		return rc;
4206 
4207 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4208 		name_len =
4209 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4210 				       PATH_MAX, nls_codepage, remap);
4211 		name_len++;	/* trailing null */
4212 		name_len *= 2;
4213 	} else {	/* BB improve the check for buffer overruns BB */
4214 		name_len = strnlen(search_name, PATH_MAX);
4215 		name_len++;	/* trailing null */
4216 		strncpy(pSMB->FileName, search_name, name_len);
4217 	}
4218 
4219 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4220 	pSMB->TotalDataCount = 0;
4221 	pSMB->MaxParameterCount = cpu_to_le16(2);
4222 	/* BB find exact max SMB PDU from sess structure BB */
4223 	pSMB->MaxDataCount = cpu_to_le16(4000);
4224 	pSMB->MaxSetupCount = 0;
4225 	pSMB->Reserved = 0;
4226 	pSMB->Flags = 0;
4227 	pSMB->Timeout = 0;
4228 	pSMB->Reserved2 = 0;
4229 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4230 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4231 	pSMB->DataCount = 0;
4232 	pSMB->DataOffset = 0;
4233 	pSMB->SetupCount = 1;
4234 	pSMB->Reserved3 = 0;
4235 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4236 	byte_count = params + 1 /* pad */ ;
4237 	pSMB->TotalParameterCount = cpu_to_le16(params);
4238 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4239 	if (legacy)
4240 		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4241 	else
4242 		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4243 	pSMB->Reserved4 = 0;
4244 	inc_rfc1001_len(pSMB, byte_count);
4245 	pSMB->ByteCount = cpu_to_le16(byte_count);
4246 
4247 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4248 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4249 	if (rc) {
4250 		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4251 	} else {		/* decode response */
4252 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4253 
4254 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4255 			rc = -EIO;
4256 		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4257 			rc = -EIO;	/* bad smb */
4258 		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4259 			rc = -EIO;  /* 24 or 26 expected but we do not read
4260 					last field */
4261 		else if (data) {
4262 			int size;
4263 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4264 
4265 			/*
4266 			 * On legacy responses we do not read the last field,
4267 			 * EAsize, fortunately since it varies by subdialect and
4268 			 * also note it differs on Set vs Get, ie two bytes or 4
4269 			 * bytes depending but we don't care here.
4270 			 */
4271 			if (legacy)
4272 				size = sizeof(FILE_INFO_STANDARD);
4273 			else
4274 				size = sizeof(FILE_ALL_INFO);
4275 			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4276 			       data_offset, size);
4277 		} else
4278 		    rc = -ENOMEM;
4279 	}
4280 	cifs_buf_release(pSMB);
4281 	if (rc == -EAGAIN)
4282 		goto QPathInfoRetry;
4283 
4284 	return rc;
4285 }
4286 
4287 int
CIFSSMBUnixQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)4288 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4289 		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4290 {
4291 	struct smb_t2_qfi_req *pSMB = NULL;
4292 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4293 	int rc = 0;
4294 	int bytes_returned;
4295 	__u16 params, byte_count;
4296 
4297 UnixQFileInfoRetry:
4298 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4299 		      (void **) &pSMBr);
4300 	if (rc)
4301 		return rc;
4302 
4303 	params = 2 /* level */ + 2 /* fid */;
4304 	pSMB->t2.TotalDataCount = 0;
4305 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4306 	/* BB find exact max data count below from sess structure BB */
4307 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4308 	pSMB->t2.MaxSetupCount = 0;
4309 	pSMB->t2.Reserved = 0;
4310 	pSMB->t2.Flags = 0;
4311 	pSMB->t2.Timeout = 0;
4312 	pSMB->t2.Reserved2 = 0;
4313 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4314 					       Fid) - 4);
4315 	pSMB->t2.DataCount = 0;
4316 	pSMB->t2.DataOffset = 0;
4317 	pSMB->t2.SetupCount = 1;
4318 	pSMB->t2.Reserved3 = 0;
4319 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4320 	byte_count = params + 1 /* pad */ ;
4321 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4322 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4323 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4324 	pSMB->Pad = 0;
4325 	pSMB->Fid = netfid;
4326 	inc_rfc1001_len(pSMB, byte_count);
4327 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4328 
4329 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4330 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4331 	if (rc) {
4332 		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4333 	} else {		/* decode response */
4334 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4335 
4336 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4337 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4338 			rc = -EIO;	/* bad smb */
4339 		} else {
4340 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4341 			memcpy((char *) pFindData,
4342 			       (char *) &pSMBr->hdr.Protocol +
4343 			       data_offset,
4344 			       sizeof(FILE_UNIX_BASIC_INFO));
4345 		}
4346 	}
4347 
4348 	cifs_buf_release(pSMB);
4349 	if (rc == -EAGAIN)
4350 		goto UnixQFileInfoRetry;
4351 
4352 	return rc;
4353 }
4354 
4355 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)4356 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4357 		     const unsigned char *searchName,
4358 		     FILE_UNIX_BASIC_INFO *pFindData,
4359 		     const struct nls_table *nls_codepage, int remap)
4360 {
4361 /* SMB_QUERY_FILE_UNIX_BASIC */
4362 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4363 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4364 	int rc = 0;
4365 	int bytes_returned = 0;
4366 	int name_len;
4367 	__u16 params, byte_count;
4368 
4369 	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4370 UnixQPathInfoRetry:
4371 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4372 		      (void **) &pSMBr);
4373 	if (rc)
4374 		return rc;
4375 
4376 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4377 		name_len =
4378 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4379 				       PATH_MAX, nls_codepage, remap);
4380 		name_len++;	/* trailing null */
4381 		name_len *= 2;
4382 	} else {	/* BB improve the check for buffer overruns BB */
4383 		name_len = strnlen(searchName, PATH_MAX);
4384 		name_len++;	/* trailing null */
4385 		strncpy(pSMB->FileName, searchName, name_len);
4386 	}
4387 
4388 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4389 	pSMB->TotalDataCount = 0;
4390 	pSMB->MaxParameterCount = cpu_to_le16(2);
4391 	/* BB find exact max SMB PDU from sess structure BB */
4392 	pSMB->MaxDataCount = cpu_to_le16(4000);
4393 	pSMB->MaxSetupCount = 0;
4394 	pSMB->Reserved = 0;
4395 	pSMB->Flags = 0;
4396 	pSMB->Timeout = 0;
4397 	pSMB->Reserved2 = 0;
4398 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4399 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4400 	pSMB->DataCount = 0;
4401 	pSMB->DataOffset = 0;
4402 	pSMB->SetupCount = 1;
4403 	pSMB->Reserved3 = 0;
4404 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4405 	byte_count = params + 1 /* pad */ ;
4406 	pSMB->TotalParameterCount = cpu_to_le16(params);
4407 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4408 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4409 	pSMB->Reserved4 = 0;
4410 	inc_rfc1001_len(pSMB, byte_count);
4411 	pSMB->ByteCount = cpu_to_le16(byte_count);
4412 
4413 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4414 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4415 	if (rc) {
4416 		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4417 	} else {		/* decode response */
4418 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4419 
4420 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4421 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4422 			rc = -EIO;	/* bad smb */
4423 		} else {
4424 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4425 			memcpy((char *) pFindData,
4426 			       (char *) &pSMBr->hdr.Protocol +
4427 			       data_offset,
4428 			       sizeof(FILE_UNIX_BASIC_INFO));
4429 		}
4430 	}
4431 	cifs_buf_release(pSMB);
4432 	if (rc == -EAGAIN)
4433 		goto UnixQPathInfoRetry;
4434 
4435 	return rc;
4436 }
4437 
4438 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4439 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)4440 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4441 	      const char *searchName, struct cifs_sb_info *cifs_sb,
4442 	      __u16 *pnetfid, __u16 search_flags,
4443 	      struct cifs_search_info *psrch_inf, bool msearch)
4444 {
4445 /* level 257 SMB_ */
4446 	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4447 	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4448 	T2_FFIRST_RSP_PARMS *parms;
4449 	int rc = 0;
4450 	int bytes_returned = 0;
4451 	int name_len, remap;
4452 	__u16 params, byte_count;
4453 	struct nls_table *nls_codepage;
4454 
4455 	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4456 
4457 findFirstRetry:
4458 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4459 		      (void **) &pSMBr);
4460 	if (rc)
4461 		return rc;
4462 
4463 	nls_codepage = cifs_sb->local_nls;
4464 	remap = cifs_remap(cifs_sb);
4465 
4466 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4467 		name_len =
4468 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4469 				       PATH_MAX, nls_codepage, remap);
4470 		/* We can not add the asterik earlier in case
4471 		it got remapped to 0xF03A as if it were part of the
4472 		directory name instead of a wildcard */
4473 		name_len *= 2;
4474 		if (msearch) {
4475 			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4476 			pSMB->FileName[name_len+1] = 0;
4477 			pSMB->FileName[name_len+2] = '*';
4478 			pSMB->FileName[name_len+3] = 0;
4479 			name_len += 4; /* now the trailing null */
4480 			/* null terminate just in case */
4481 			pSMB->FileName[name_len] = 0;
4482 			pSMB->FileName[name_len+1] = 0;
4483 			name_len += 2;
4484 		}
4485 	} else {	/* BB add check for overrun of SMB buf BB */
4486 		name_len = strnlen(searchName, PATH_MAX);
4487 /* BB fix here and in unicode clause above ie
4488 		if (name_len > buffersize-header)
4489 			free buffer exit; BB */
4490 		strncpy(pSMB->FileName, searchName, name_len);
4491 		if (msearch) {
4492 			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4493 			pSMB->FileName[name_len+1] = '*';
4494 			pSMB->FileName[name_len+2] = 0;
4495 			name_len += 3;
4496 		}
4497 	}
4498 
4499 	params = 12 + name_len /* includes null */ ;
4500 	pSMB->TotalDataCount = 0;	/* no EAs */
4501 	pSMB->MaxParameterCount = cpu_to_le16(10);
4502 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4503 	pSMB->MaxSetupCount = 0;
4504 	pSMB->Reserved = 0;
4505 	pSMB->Flags = 0;
4506 	pSMB->Timeout = 0;
4507 	pSMB->Reserved2 = 0;
4508 	byte_count = params + 1 /* pad */ ;
4509 	pSMB->TotalParameterCount = cpu_to_le16(params);
4510 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4511 	pSMB->ParameterOffset = cpu_to_le16(
4512 	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4513 		- 4);
4514 	pSMB->DataCount = 0;
4515 	pSMB->DataOffset = 0;
4516 	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
4517 	pSMB->Reserved3 = 0;
4518 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4519 	pSMB->SearchAttributes =
4520 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4521 			ATTR_DIRECTORY);
4522 	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4523 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4524 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4525 
4526 	/* BB what should we set StorageType to? Does it matter? BB */
4527 	pSMB->SearchStorageType = 0;
4528 	inc_rfc1001_len(pSMB, byte_count);
4529 	pSMB->ByteCount = cpu_to_le16(byte_count);
4530 
4531 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4532 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4533 	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4534 
4535 	if (rc) {/* BB add logic to retry regular search if Unix search
4536 			rejected unexpectedly by server */
4537 		/* BB Add code to handle unsupported level rc */
4538 		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4539 
4540 		cifs_buf_release(pSMB);
4541 
4542 		/* BB eventually could optimize out free and realloc of buf */
4543 		/*    for this case */
4544 		if (rc == -EAGAIN)
4545 			goto findFirstRetry;
4546 	} else { /* decode response */
4547 		/* BB remember to free buffer if error BB */
4548 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4549 		if (rc == 0) {
4550 			unsigned int lnoff;
4551 
4552 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4553 				psrch_inf->unicode = true;
4554 			else
4555 				psrch_inf->unicode = false;
4556 
4557 			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4558 			psrch_inf->smallBuf = 0;
4559 			psrch_inf->srch_entries_start =
4560 				(char *) &pSMBr->hdr.Protocol +
4561 					le16_to_cpu(pSMBr->t2.DataOffset);
4562 			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4563 			       le16_to_cpu(pSMBr->t2.ParameterOffset));
4564 
4565 			if (parms->EndofSearch)
4566 				psrch_inf->endOfSearch = true;
4567 			else
4568 				psrch_inf->endOfSearch = false;
4569 
4570 			psrch_inf->entries_in_buffer =
4571 					le16_to_cpu(parms->SearchCount);
4572 			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4573 				psrch_inf->entries_in_buffer;
4574 			lnoff = le16_to_cpu(parms->LastNameOffset);
4575 			if (CIFSMaxBufSize < lnoff) {
4576 				cifs_dbg(VFS, "ignoring corrupt resume name\n");
4577 				psrch_inf->last_entry = NULL;
4578 				return rc;
4579 			}
4580 
4581 			psrch_inf->last_entry = psrch_inf->srch_entries_start +
4582 							lnoff;
4583 
4584 			if (pnetfid)
4585 				*pnetfid = parms->SearchHandle;
4586 		} else {
4587 			cifs_buf_release(pSMB);
4588 		}
4589 	}
4590 
4591 	return rc;
4592 }
4593 
CIFSFindNext(const unsigned int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4594 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4595 		 __u16 searchHandle, __u16 search_flags,
4596 		 struct cifs_search_info *psrch_inf)
4597 {
4598 	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4599 	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4600 	T2_FNEXT_RSP_PARMS *parms;
4601 	char *response_data;
4602 	int rc = 0;
4603 	int bytes_returned;
4604 	unsigned int name_len;
4605 	__u16 params, byte_count;
4606 
4607 	cifs_dbg(FYI, "In FindNext\n");
4608 
4609 	if (psrch_inf->endOfSearch)
4610 		return -ENOENT;
4611 
4612 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4613 		(void **) &pSMBr);
4614 	if (rc)
4615 		return rc;
4616 
4617 	params = 14; /* includes 2 bytes of null string, converted to LE below*/
4618 	byte_count = 0;
4619 	pSMB->TotalDataCount = 0;       /* no EAs */
4620 	pSMB->MaxParameterCount = cpu_to_le16(8);
4621 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4622 	pSMB->MaxSetupCount = 0;
4623 	pSMB->Reserved = 0;
4624 	pSMB->Flags = 0;
4625 	pSMB->Timeout = 0;
4626 	pSMB->Reserved2 = 0;
4627 	pSMB->ParameterOffset =  cpu_to_le16(
4628 	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4629 	pSMB->DataCount = 0;
4630 	pSMB->DataOffset = 0;
4631 	pSMB->SetupCount = 1;
4632 	pSMB->Reserved3 = 0;
4633 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4634 	pSMB->SearchHandle = searchHandle;      /* always kept as le */
4635 	pSMB->SearchCount =
4636 		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4637 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4638 	pSMB->ResumeKey = psrch_inf->resume_key;
4639 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4640 
4641 	name_len = psrch_inf->resume_name_len;
4642 	params += name_len;
4643 	if (name_len < PATH_MAX) {
4644 		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4645 		byte_count += name_len;
4646 		/* 14 byte parm len above enough for 2 byte null terminator */
4647 		pSMB->ResumeFileName[name_len] = 0;
4648 		pSMB->ResumeFileName[name_len+1] = 0;
4649 	} else {
4650 		rc = -EINVAL;
4651 		goto FNext2_err_exit;
4652 	}
4653 	byte_count = params + 1 /* pad */ ;
4654 	pSMB->TotalParameterCount = cpu_to_le16(params);
4655 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4656 	inc_rfc1001_len(pSMB, byte_count);
4657 	pSMB->ByteCount = cpu_to_le16(byte_count);
4658 
4659 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4660 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4661 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4662 	if (rc) {
4663 		if (rc == -EBADF) {
4664 			psrch_inf->endOfSearch = true;
4665 			cifs_buf_release(pSMB);
4666 			rc = 0; /* search probably was closed at end of search*/
4667 		} else
4668 			cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4669 	} else {                /* decode response */
4670 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4671 
4672 		if (rc == 0) {
4673 			unsigned int lnoff;
4674 
4675 			/* BB fixme add lock for file (srch_info) struct here */
4676 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4677 				psrch_inf->unicode = true;
4678 			else
4679 				psrch_inf->unicode = false;
4680 			response_data = (char *) &pSMBr->hdr.Protocol +
4681 			       le16_to_cpu(pSMBr->t2.ParameterOffset);
4682 			parms = (T2_FNEXT_RSP_PARMS *)response_data;
4683 			response_data = (char *)&pSMBr->hdr.Protocol +
4684 				le16_to_cpu(pSMBr->t2.DataOffset);
4685 			if (psrch_inf->smallBuf)
4686 				cifs_small_buf_release(
4687 					psrch_inf->ntwrk_buf_start);
4688 			else
4689 				cifs_buf_release(psrch_inf->ntwrk_buf_start);
4690 			psrch_inf->srch_entries_start = response_data;
4691 			psrch_inf->ntwrk_buf_start = (char *)pSMB;
4692 			psrch_inf->smallBuf = 0;
4693 			if (parms->EndofSearch)
4694 				psrch_inf->endOfSearch = true;
4695 			else
4696 				psrch_inf->endOfSearch = false;
4697 			psrch_inf->entries_in_buffer =
4698 						le16_to_cpu(parms->SearchCount);
4699 			psrch_inf->index_of_last_entry +=
4700 				psrch_inf->entries_in_buffer;
4701 			lnoff = le16_to_cpu(parms->LastNameOffset);
4702 			if (CIFSMaxBufSize < lnoff) {
4703 				cifs_dbg(VFS, "ignoring corrupt resume name\n");
4704 				psrch_inf->last_entry = NULL;
4705 				return rc;
4706 			} else
4707 				psrch_inf->last_entry =
4708 					psrch_inf->srch_entries_start + lnoff;
4709 
4710 /*  cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4711     psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4712 
4713 			/* BB fixme add unlock here */
4714 		}
4715 
4716 	}
4717 
4718 	/* BB On error, should we leave previous search buf (and count and
4719 	last entry fields) intact or free the previous one? */
4720 
4721 	/* Note: On -EAGAIN error only caller can retry on handle based calls
4722 	since file handle passed in no longer valid */
4723 FNext2_err_exit:
4724 	if (rc != 0)
4725 		cifs_buf_release(pSMB);
4726 	return rc;
4727 }
4728 
4729 int
CIFSFindClose(const unsigned int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4730 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4731 	      const __u16 searchHandle)
4732 {
4733 	int rc = 0;
4734 	FINDCLOSE_REQ *pSMB = NULL;
4735 
4736 	cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4737 	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4738 
4739 	/* no sense returning error if session restarted
4740 		as file handle has been closed */
4741 	if (rc == -EAGAIN)
4742 		return 0;
4743 	if (rc)
4744 		return rc;
4745 
4746 	pSMB->FileID = searchHandle;
4747 	pSMB->ByteCount = 0;
4748 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4749 	cifs_small_buf_release(pSMB);
4750 	if (rc)
4751 		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4752 
4753 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4754 
4755 	/* Since session is dead, search handle closed on server already */
4756 	if (rc == -EAGAIN)
4757 		rc = 0;
4758 
4759 	return rc;
4760 }
4761 
4762 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)4763 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4764 		      const char *search_name, __u64 *inode_number,
4765 		      const struct nls_table *nls_codepage, int remap)
4766 {
4767 	int rc = 0;
4768 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4769 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4770 	int name_len, bytes_returned;
4771 	__u16 params, byte_count;
4772 
4773 	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4774 	if (tcon == NULL)
4775 		return -ENODEV;
4776 
4777 GetInodeNumberRetry:
4778 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4779 		      (void **) &pSMBr);
4780 	if (rc)
4781 		return rc;
4782 
4783 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4784 		name_len =
4785 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4786 					   search_name, PATH_MAX, nls_codepage,
4787 					   remap);
4788 		name_len++;     /* trailing null */
4789 		name_len *= 2;
4790 	} else {	/* BB improve the check for buffer overruns BB */
4791 		name_len = strnlen(search_name, PATH_MAX);
4792 		name_len++;     /* trailing null */
4793 		strncpy(pSMB->FileName, search_name, name_len);
4794 	}
4795 
4796 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4797 	pSMB->TotalDataCount = 0;
4798 	pSMB->MaxParameterCount = cpu_to_le16(2);
4799 	/* BB find exact max data count below from sess structure BB */
4800 	pSMB->MaxDataCount = cpu_to_le16(4000);
4801 	pSMB->MaxSetupCount = 0;
4802 	pSMB->Reserved = 0;
4803 	pSMB->Flags = 0;
4804 	pSMB->Timeout = 0;
4805 	pSMB->Reserved2 = 0;
4806 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4807 		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4808 	pSMB->DataCount = 0;
4809 	pSMB->DataOffset = 0;
4810 	pSMB->SetupCount = 1;
4811 	pSMB->Reserved3 = 0;
4812 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4813 	byte_count = params + 1 /* pad */ ;
4814 	pSMB->TotalParameterCount = cpu_to_le16(params);
4815 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4816 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4817 	pSMB->Reserved4 = 0;
4818 	inc_rfc1001_len(pSMB, byte_count);
4819 	pSMB->ByteCount = cpu_to_le16(byte_count);
4820 
4821 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4822 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4823 	if (rc) {
4824 		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4825 	} else {
4826 		/* decode response */
4827 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4828 		/* BB also check enough total bytes returned */
4829 		if (rc || get_bcc(&pSMBr->hdr) < 2)
4830 			/* If rc should we check for EOPNOSUPP and
4831 			disable the srvino flag? or in caller? */
4832 			rc = -EIO;      /* bad smb */
4833 		else {
4834 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4835 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4836 			struct file_internal_info *pfinfo;
4837 			/* BB Do we need a cast or hash here ? */
4838 			if (count < 8) {
4839 				cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4840 				rc = -EIO;
4841 				goto GetInodeNumOut;
4842 			}
4843 			pfinfo = (struct file_internal_info *)
4844 				(data_offset + (char *) &pSMBr->hdr.Protocol);
4845 			*inode_number = le64_to_cpu(pfinfo->UniqueId);
4846 		}
4847 	}
4848 GetInodeNumOut:
4849 	cifs_buf_release(pSMB);
4850 	if (rc == -EAGAIN)
4851 		goto GetInodeNumberRetry;
4852 	return rc;
4853 }
4854 
4855 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)4856 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4857 		const char *search_name, struct dfs_info3_param **target_nodes,
4858 		unsigned int *num_of_nodes,
4859 		const struct nls_table *nls_codepage, int remap)
4860 {
4861 /* TRANS2_GET_DFS_REFERRAL */
4862 	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4863 	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4864 	int rc = 0;
4865 	int bytes_returned;
4866 	int name_len;
4867 	__u16 params, byte_count;
4868 	*num_of_nodes = 0;
4869 	*target_nodes = NULL;
4870 
4871 	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4872 	if (ses == NULL || ses->tcon_ipc == NULL)
4873 		return -ENODEV;
4874 
4875 getDFSRetry:
4876 	rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4877 		      (void **) &pSMBr);
4878 	if (rc)
4879 		return rc;
4880 
4881 	/* server pointer checked in called function,
4882 	but should never be null here anyway */
4883 	pSMB->hdr.Mid = get_next_mid(ses->server);
4884 	pSMB->hdr.Tid = ses->tcon_ipc->tid;
4885 	pSMB->hdr.Uid = ses->Suid;
4886 	if (ses->capabilities & CAP_STATUS32)
4887 		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4888 	if (ses->capabilities & CAP_DFS)
4889 		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4890 
4891 	if (ses->capabilities & CAP_UNICODE) {
4892 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4893 		name_len =
4894 		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4895 				       search_name, PATH_MAX, nls_codepage,
4896 				       remap);
4897 		name_len++;	/* trailing null */
4898 		name_len *= 2;
4899 	} else {	/* BB improve the check for buffer overruns BB */
4900 		name_len = strnlen(search_name, PATH_MAX);
4901 		name_len++;	/* trailing null */
4902 		strncpy(pSMB->RequestFileName, search_name, name_len);
4903 	}
4904 
4905 	if (ses->server->sign)
4906 		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4907 
4908 	pSMB->hdr.Uid = ses->Suid;
4909 
4910 	params = 2 /* level */  + name_len /*includes null */ ;
4911 	pSMB->TotalDataCount = 0;
4912 	pSMB->DataCount = 0;
4913 	pSMB->DataOffset = 0;
4914 	pSMB->MaxParameterCount = 0;
4915 	/* BB find exact max SMB PDU from sess structure BB */
4916 	pSMB->MaxDataCount = cpu_to_le16(4000);
4917 	pSMB->MaxSetupCount = 0;
4918 	pSMB->Reserved = 0;
4919 	pSMB->Flags = 0;
4920 	pSMB->Timeout = 0;
4921 	pSMB->Reserved2 = 0;
4922 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4923 	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4924 	pSMB->SetupCount = 1;
4925 	pSMB->Reserved3 = 0;
4926 	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4927 	byte_count = params + 3 /* pad */ ;
4928 	pSMB->ParameterCount = cpu_to_le16(params);
4929 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4930 	pSMB->MaxReferralLevel = cpu_to_le16(3);
4931 	inc_rfc1001_len(pSMB, byte_count);
4932 	pSMB->ByteCount = cpu_to_le16(byte_count);
4933 
4934 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4935 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4936 	if (rc) {
4937 		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4938 		goto GetDFSRefExit;
4939 	}
4940 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4941 
4942 	/* BB Also check if enough total bytes returned? */
4943 	if (rc || get_bcc(&pSMBr->hdr) < 17) {
4944 		rc = -EIO;      /* bad smb */
4945 		goto GetDFSRefExit;
4946 	}
4947 
4948 	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
4949 		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4950 
4951 	/* parse returned result into more usable form */
4952 	rc = parse_dfs_referrals(&pSMBr->dfs_data,
4953 				 le16_to_cpu(pSMBr->t2.DataCount),
4954 				 num_of_nodes, target_nodes, nls_codepage,
4955 				 remap, search_name,
4956 				 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4957 
4958 GetDFSRefExit:
4959 	cifs_buf_release(pSMB);
4960 
4961 	if (rc == -EAGAIN)
4962 		goto getDFSRetry;
4963 
4964 	return rc;
4965 }
4966 
4967 /* Query File System Info such as free space to old servers such as Win 9x */
4968 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4969 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4970 	      struct kstatfs *FSData)
4971 {
4972 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4973 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4974 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4975 	FILE_SYSTEM_ALLOC_INFO *response_data;
4976 	int rc = 0;
4977 	int bytes_returned = 0;
4978 	__u16 params, byte_count;
4979 
4980 	cifs_dbg(FYI, "OldQFSInfo\n");
4981 oldQFSInfoRetry:
4982 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4983 		(void **) &pSMBr);
4984 	if (rc)
4985 		return rc;
4986 
4987 	params = 2;     /* level */
4988 	pSMB->TotalDataCount = 0;
4989 	pSMB->MaxParameterCount = cpu_to_le16(2);
4990 	pSMB->MaxDataCount = cpu_to_le16(1000);
4991 	pSMB->MaxSetupCount = 0;
4992 	pSMB->Reserved = 0;
4993 	pSMB->Flags = 0;
4994 	pSMB->Timeout = 0;
4995 	pSMB->Reserved2 = 0;
4996 	byte_count = params + 1 /* pad */ ;
4997 	pSMB->TotalParameterCount = cpu_to_le16(params);
4998 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4999 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5000 	struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5001 	pSMB->DataCount = 0;
5002 	pSMB->DataOffset = 0;
5003 	pSMB->SetupCount = 1;
5004 	pSMB->Reserved3 = 0;
5005 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5006 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
5007 	inc_rfc1001_len(pSMB, byte_count);
5008 	pSMB->ByteCount = cpu_to_le16(byte_count);
5009 
5010 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5011 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
5012 	if (rc) {
5013 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5014 	} else {                /* decode response */
5015 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5016 
5017 		if (rc || get_bcc(&pSMBr->hdr) < 18)
5018 			rc = -EIO;      /* bad smb */
5019 		else {
5020 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5021 			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
5022 				 get_bcc(&pSMBr->hdr), data_offset);
5023 
5024 			response_data = (FILE_SYSTEM_ALLOC_INFO *)
5025 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
5026 			FSData->f_bsize =
5027 				le16_to_cpu(response_data->BytesPerSector) *
5028 				le32_to_cpu(response_data->
5029 					SectorsPerAllocationUnit);
5030 			FSData->f_blocks =
5031 			       le32_to_cpu(response_data->TotalAllocationUnits);
5032 			FSData->f_bfree = FSData->f_bavail =
5033 				le32_to_cpu(response_data->FreeAllocationUnits);
5034 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
5035 				 (unsigned long long)FSData->f_blocks,
5036 				 (unsigned long long)FSData->f_bfree,
5037 				 FSData->f_bsize);
5038 		}
5039 	}
5040 	cifs_buf_release(pSMB);
5041 
5042 	if (rc == -EAGAIN)
5043 		goto oldQFSInfoRetry;
5044 
5045 	return rc;
5046 }
5047 
5048 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5049 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5050 	       struct kstatfs *FSData)
5051 {
5052 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5053 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5054 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5055 	FILE_SYSTEM_INFO *response_data;
5056 	int rc = 0;
5057 	int bytes_returned = 0;
5058 	__u16 params, byte_count;
5059 
5060 	cifs_dbg(FYI, "In QFSInfo\n");
5061 QFSInfoRetry:
5062 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5063 		      (void **) &pSMBr);
5064 	if (rc)
5065 		return rc;
5066 
5067 	params = 2;	/* level */
5068 	pSMB->TotalDataCount = 0;
5069 	pSMB->MaxParameterCount = cpu_to_le16(2);
5070 	pSMB->MaxDataCount = cpu_to_le16(1000);
5071 	pSMB->MaxSetupCount = 0;
5072 	pSMB->Reserved = 0;
5073 	pSMB->Flags = 0;
5074 	pSMB->Timeout = 0;
5075 	pSMB->Reserved2 = 0;
5076 	byte_count = params + 1 /* pad */ ;
5077 	pSMB->TotalParameterCount = cpu_to_le16(params);
5078 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5079 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5080 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5081 	pSMB->DataCount = 0;
5082 	pSMB->DataOffset = 0;
5083 	pSMB->SetupCount = 1;
5084 	pSMB->Reserved3 = 0;
5085 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5086 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5087 	inc_rfc1001_len(pSMB, byte_count);
5088 	pSMB->ByteCount = cpu_to_le16(byte_count);
5089 
5090 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5091 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5092 	if (rc) {
5093 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5094 	} else {		/* decode response */
5095 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5096 
5097 		if (rc || get_bcc(&pSMBr->hdr) < 24)
5098 			rc = -EIO;	/* bad smb */
5099 		else {
5100 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5101 
5102 			response_data =
5103 			    (FILE_SYSTEM_INFO
5104 			     *) (((char *) &pSMBr->hdr.Protocol) +
5105 				 data_offset);
5106 			FSData->f_bsize =
5107 			    le32_to_cpu(response_data->BytesPerSector) *
5108 			    le32_to_cpu(response_data->
5109 					SectorsPerAllocationUnit);
5110 			FSData->f_blocks =
5111 			    le64_to_cpu(response_data->TotalAllocationUnits);
5112 			FSData->f_bfree = FSData->f_bavail =
5113 			    le64_to_cpu(response_data->FreeAllocationUnits);
5114 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
5115 				 (unsigned long long)FSData->f_blocks,
5116 				 (unsigned long long)FSData->f_bfree,
5117 				 FSData->f_bsize);
5118 		}
5119 	}
5120 	cifs_buf_release(pSMB);
5121 
5122 	if (rc == -EAGAIN)
5123 		goto QFSInfoRetry;
5124 
5125 	return rc;
5126 }
5127 
5128 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)5129 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5130 {
5131 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5132 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5133 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5134 	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5135 	int rc = 0;
5136 	int bytes_returned = 0;
5137 	__u16 params, byte_count;
5138 
5139 	cifs_dbg(FYI, "In QFSAttributeInfo\n");
5140 QFSAttributeRetry:
5141 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5142 		      (void **) &pSMBr);
5143 	if (rc)
5144 		return rc;
5145 
5146 	params = 2;	/* level */
5147 	pSMB->TotalDataCount = 0;
5148 	pSMB->MaxParameterCount = cpu_to_le16(2);
5149 	/* BB find exact max SMB PDU from sess structure BB */
5150 	pSMB->MaxDataCount = cpu_to_le16(1000);
5151 	pSMB->MaxSetupCount = 0;
5152 	pSMB->Reserved = 0;
5153 	pSMB->Flags = 0;
5154 	pSMB->Timeout = 0;
5155 	pSMB->Reserved2 = 0;
5156 	byte_count = params + 1 /* pad */ ;
5157 	pSMB->TotalParameterCount = cpu_to_le16(params);
5158 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5159 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5160 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5161 	pSMB->DataCount = 0;
5162 	pSMB->DataOffset = 0;
5163 	pSMB->SetupCount = 1;
5164 	pSMB->Reserved3 = 0;
5165 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5166 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5167 	inc_rfc1001_len(pSMB, byte_count);
5168 	pSMB->ByteCount = cpu_to_le16(byte_count);
5169 
5170 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5171 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5172 	if (rc) {
5173 		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5174 	} else {		/* decode response */
5175 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5176 
5177 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5178 			/* BB also check if enough bytes returned */
5179 			rc = -EIO;	/* bad smb */
5180 		} else {
5181 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5182 			response_data =
5183 			    (FILE_SYSTEM_ATTRIBUTE_INFO
5184 			     *) (((char *) &pSMBr->hdr.Protocol) +
5185 				 data_offset);
5186 			memcpy(&tcon->fsAttrInfo, response_data,
5187 			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5188 		}
5189 	}
5190 	cifs_buf_release(pSMB);
5191 
5192 	if (rc == -EAGAIN)
5193 		goto QFSAttributeRetry;
5194 
5195 	return rc;
5196 }
5197 
5198 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)5199 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5200 {
5201 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5202 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5203 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5204 	FILE_SYSTEM_DEVICE_INFO *response_data;
5205 	int rc = 0;
5206 	int bytes_returned = 0;
5207 	__u16 params, byte_count;
5208 
5209 	cifs_dbg(FYI, "In QFSDeviceInfo\n");
5210 QFSDeviceRetry:
5211 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5212 		      (void **) &pSMBr);
5213 	if (rc)
5214 		return rc;
5215 
5216 	params = 2;	/* level */
5217 	pSMB->TotalDataCount = 0;
5218 	pSMB->MaxParameterCount = cpu_to_le16(2);
5219 	/* BB find exact max SMB PDU from sess structure BB */
5220 	pSMB->MaxDataCount = cpu_to_le16(1000);
5221 	pSMB->MaxSetupCount = 0;
5222 	pSMB->Reserved = 0;
5223 	pSMB->Flags = 0;
5224 	pSMB->Timeout = 0;
5225 	pSMB->Reserved2 = 0;
5226 	byte_count = params + 1 /* pad */ ;
5227 	pSMB->TotalParameterCount = cpu_to_le16(params);
5228 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5229 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5230 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5231 
5232 	pSMB->DataCount = 0;
5233 	pSMB->DataOffset = 0;
5234 	pSMB->SetupCount = 1;
5235 	pSMB->Reserved3 = 0;
5236 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5237 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5238 	inc_rfc1001_len(pSMB, byte_count);
5239 	pSMB->ByteCount = cpu_to_le16(byte_count);
5240 
5241 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5242 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5243 	if (rc) {
5244 		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5245 	} else {		/* decode response */
5246 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5247 
5248 		if (rc || get_bcc(&pSMBr->hdr) <
5249 			  sizeof(FILE_SYSTEM_DEVICE_INFO))
5250 			rc = -EIO;	/* bad smb */
5251 		else {
5252 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5253 			response_data =
5254 			    (FILE_SYSTEM_DEVICE_INFO *)
5255 				(((char *) &pSMBr->hdr.Protocol) +
5256 				 data_offset);
5257 			memcpy(&tcon->fsDevInfo, response_data,
5258 			       sizeof(FILE_SYSTEM_DEVICE_INFO));
5259 		}
5260 	}
5261 	cifs_buf_release(pSMB);
5262 
5263 	if (rc == -EAGAIN)
5264 		goto QFSDeviceRetry;
5265 
5266 	return rc;
5267 }
5268 
5269 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)5270 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5271 {
5272 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5273 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5274 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5275 	FILE_SYSTEM_UNIX_INFO *response_data;
5276 	int rc = 0;
5277 	int bytes_returned = 0;
5278 	__u16 params, byte_count;
5279 
5280 	cifs_dbg(FYI, "In QFSUnixInfo\n");
5281 QFSUnixRetry:
5282 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5283 				   (void **) &pSMB, (void **) &pSMBr);
5284 	if (rc)
5285 		return rc;
5286 
5287 	params = 2;	/* level */
5288 	pSMB->TotalDataCount = 0;
5289 	pSMB->DataCount = 0;
5290 	pSMB->DataOffset = 0;
5291 	pSMB->MaxParameterCount = cpu_to_le16(2);
5292 	/* BB find exact max SMB PDU from sess structure BB */
5293 	pSMB->MaxDataCount = cpu_to_le16(100);
5294 	pSMB->MaxSetupCount = 0;
5295 	pSMB->Reserved = 0;
5296 	pSMB->Flags = 0;
5297 	pSMB->Timeout = 0;
5298 	pSMB->Reserved2 = 0;
5299 	byte_count = params + 1 /* pad */ ;
5300 	pSMB->ParameterCount = cpu_to_le16(params);
5301 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5302 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5303 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5304 	pSMB->SetupCount = 1;
5305 	pSMB->Reserved3 = 0;
5306 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5307 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5308 	inc_rfc1001_len(pSMB, byte_count);
5309 	pSMB->ByteCount = cpu_to_le16(byte_count);
5310 
5311 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5312 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5313 	if (rc) {
5314 		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5315 	} else {		/* decode response */
5316 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5317 
5318 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5319 			rc = -EIO;	/* bad smb */
5320 		} else {
5321 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5322 			response_data =
5323 			    (FILE_SYSTEM_UNIX_INFO
5324 			     *) (((char *) &pSMBr->hdr.Protocol) +
5325 				 data_offset);
5326 			memcpy(&tcon->fsUnixInfo, response_data,
5327 			       sizeof(FILE_SYSTEM_UNIX_INFO));
5328 		}
5329 	}
5330 	cifs_buf_release(pSMB);
5331 
5332 	if (rc == -EAGAIN)
5333 		goto QFSUnixRetry;
5334 
5335 
5336 	return rc;
5337 }
5338 
5339 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)5340 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5341 {
5342 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5343 	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5344 	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5345 	int rc = 0;
5346 	int bytes_returned = 0;
5347 	__u16 params, param_offset, offset, byte_count;
5348 
5349 	cifs_dbg(FYI, "In SETFSUnixInfo\n");
5350 SETFSUnixRetry:
5351 	/* BB switch to small buf init to save memory */
5352 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5353 					(void **) &pSMB, (void **) &pSMBr);
5354 	if (rc)
5355 		return rc;
5356 
5357 	params = 4;	/* 2 bytes zero followed by info level. */
5358 	pSMB->MaxSetupCount = 0;
5359 	pSMB->Reserved = 0;
5360 	pSMB->Flags = 0;
5361 	pSMB->Timeout = 0;
5362 	pSMB->Reserved2 = 0;
5363 	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5364 				- 4;
5365 	offset = param_offset + params;
5366 
5367 	pSMB->MaxParameterCount = cpu_to_le16(4);
5368 	/* BB find exact max SMB PDU from sess structure BB */
5369 	pSMB->MaxDataCount = cpu_to_le16(100);
5370 	pSMB->SetupCount = 1;
5371 	pSMB->Reserved3 = 0;
5372 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5373 	byte_count = 1 /* pad */ + params + 12;
5374 
5375 	pSMB->DataCount = cpu_to_le16(12);
5376 	pSMB->ParameterCount = cpu_to_le16(params);
5377 	pSMB->TotalDataCount = pSMB->DataCount;
5378 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5379 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5380 	pSMB->DataOffset = cpu_to_le16(offset);
5381 
5382 	/* Params. */
5383 	pSMB->FileNum = 0;
5384 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5385 
5386 	/* Data. */
5387 	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5388 	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5389 	pSMB->ClientUnixCap = cpu_to_le64(cap);
5390 
5391 	inc_rfc1001_len(pSMB, byte_count);
5392 	pSMB->ByteCount = cpu_to_le16(byte_count);
5393 
5394 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5395 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5396 	if (rc) {
5397 		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5398 	} else {		/* decode response */
5399 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5400 		if (rc)
5401 			rc = -EIO;	/* bad smb */
5402 	}
5403 	cifs_buf_release(pSMB);
5404 
5405 	if (rc == -EAGAIN)
5406 		goto SETFSUnixRetry;
5407 
5408 	return rc;
5409 }
5410 
5411 
5412 
5413 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5414 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5415 		   struct kstatfs *FSData)
5416 {
5417 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5418 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5419 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5420 	FILE_SYSTEM_POSIX_INFO *response_data;
5421 	int rc = 0;
5422 	int bytes_returned = 0;
5423 	__u16 params, byte_count;
5424 
5425 	cifs_dbg(FYI, "In QFSPosixInfo\n");
5426 QFSPosixRetry:
5427 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5428 		      (void **) &pSMBr);
5429 	if (rc)
5430 		return rc;
5431 
5432 	params = 2;	/* level */
5433 	pSMB->TotalDataCount = 0;
5434 	pSMB->DataCount = 0;
5435 	pSMB->DataOffset = 0;
5436 	pSMB->MaxParameterCount = cpu_to_le16(2);
5437 	/* BB find exact max SMB PDU from sess structure BB */
5438 	pSMB->MaxDataCount = cpu_to_le16(100);
5439 	pSMB->MaxSetupCount = 0;
5440 	pSMB->Reserved = 0;
5441 	pSMB->Flags = 0;
5442 	pSMB->Timeout = 0;
5443 	pSMB->Reserved2 = 0;
5444 	byte_count = params + 1 /* pad */ ;
5445 	pSMB->ParameterCount = cpu_to_le16(params);
5446 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5447 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5448 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5449 	pSMB->SetupCount = 1;
5450 	pSMB->Reserved3 = 0;
5451 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5452 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5453 	inc_rfc1001_len(pSMB, byte_count);
5454 	pSMB->ByteCount = cpu_to_le16(byte_count);
5455 
5456 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5457 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5458 	if (rc) {
5459 		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5460 	} else {		/* decode response */
5461 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5462 
5463 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5464 			rc = -EIO;	/* bad smb */
5465 		} else {
5466 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5467 			response_data =
5468 			    (FILE_SYSTEM_POSIX_INFO
5469 			     *) (((char *) &pSMBr->hdr.Protocol) +
5470 				 data_offset);
5471 			FSData->f_bsize =
5472 					le32_to_cpu(response_data->BlockSize);
5473 			FSData->f_blocks =
5474 					le64_to_cpu(response_data->TotalBlocks);
5475 			FSData->f_bfree =
5476 			    le64_to_cpu(response_data->BlocksAvail);
5477 			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5478 				FSData->f_bavail = FSData->f_bfree;
5479 			} else {
5480 				FSData->f_bavail =
5481 				    le64_to_cpu(response_data->UserBlocksAvail);
5482 			}
5483 			if (response_data->TotalFileNodes != cpu_to_le64(-1))
5484 				FSData->f_files =
5485 				     le64_to_cpu(response_data->TotalFileNodes);
5486 			if (response_data->FreeFileNodes != cpu_to_le64(-1))
5487 				FSData->f_ffree =
5488 				      le64_to_cpu(response_data->FreeFileNodes);
5489 		}
5490 	}
5491 	cifs_buf_release(pSMB);
5492 
5493 	if (rc == -EAGAIN)
5494 		goto QFSPosixRetry;
5495 
5496 	return rc;
5497 }
5498 
5499 
5500 /*
5501  * We can not use write of zero bytes trick to set file size due to need for
5502  * large file support. Also note that this SetPathInfo is preferred to
5503  * SetFileInfo based method in next routine which is only needed to work around
5504  * a sharing violation bugin Samba which this routine can run into.
5505  */
5506 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)5507 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5508 	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5509 	      bool set_allocation)
5510 {
5511 	struct smb_com_transaction2_spi_req *pSMB = NULL;
5512 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5513 	struct file_end_of_file_info *parm_data;
5514 	int name_len;
5515 	int rc = 0;
5516 	int bytes_returned = 0;
5517 	int remap = cifs_remap(cifs_sb);
5518 
5519 	__u16 params, byte_count, data_count, param_offset, offset;
5520 
5521 	cifs_dbg(FYI, "In SetEOF\n");
5522 SetEOFRetry:
5523 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5524 		      (void **) &pSMBr);
5525 	if (rc)
5526 		return rc;
5527 
5528 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5529 		name_len =
5530 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5531 				       PATH_MAX, cifs_sb->local_nls, remap);
5532 		name_len++;	/* trailing null */
5533 		name_len *= 2;
5534 	} else {	/* BB improve the check for buffer overruns BB */
5535 		name_len = strnlen(file_name, PATH_MAX);
5536 		name_len++;	/* trailing null */
5537 		strncpy(pSMB->FileName, file_name, name_len);
5538 	}
5539 	params = 6 + name_len;
5540 	data_count = sizeof(struct file_end_of_file_info);
5541 	pSMB->MaxParameterCount = cpu_to_le16(2);
5542 	pSMB->MaxDataCount = cpu_to_le16(4100);
5543 	pSMB->MaxSetupCount = 0;
5544 	pSMB->Reserved = 0;
5545 	pSMB->Flags = 0;
5546 	pSMB->Timeout = 0;
5547 	pSMB->Reserved2 = 0;
5548 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5549 				InformationLevel) - 4;
5550 	offset = param_offset + params;
5551 	if (set_allocation) {
5552 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5553 			pSMB->InformationLevel =
5554 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5555 		else
5556 			pSMB->InformationLevel =
5557 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5558 	} else /* Set File Size */  {
5559 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5560 		    pSMB->InformationLevel =
5561 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5562 	    else
5563 		    pSMB->InformationLevel =
5564 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5565 	}
5566 
5567 	parm_data =
5568 	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5569 				       offset);
5570 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5571 	pSMB->DataOffset = cpu_to_le16(offset);
5572 	pSMB->SetupCount = 1;
5573 	pSMB->Reserved3 = 0;
5574 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5575 	byte_count = 3 /* pad */  + params + data_count;
5576 	pSMB->DataCount = cpu_to_le16(data_count);
5577 	pSMB->TotalDataCount = pSMB->DataCount;
5578 	pSMB->ParameterCount = cpu_to_le16(params);
5579 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5580 	pSMB->Reserved4 = 0;
5581 	inc_rfc1001_len(pSMB, byte_count);
5582 	parm_data->FileSize = cpu_to_le64(size);
5583 	pSMB->ByteCount = cpu_to_le16(byte_count);
5584 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5585 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5586 	if (rc)
5587 		cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5588 
5589 	cifs_buf_release(pSMB);
5590 
5591 	if (rc == -EAGAIN)
5592 		goto SetEOFRetry;
5593 
5594 	return rc;
5595 }
5596 
5597 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5598 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5599 		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5600 {
5601 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5602 	struct file_end_of_file_info *parm_data;
5603 	int rc = 0;
5604 	__u16 params, param_offset, offset, byte_count, count;
5605 
5606 	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5607 		 (long long)size);
5608 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5609 
5610 	if (rc)
5611 		return rc;
5612 
5613 	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5614 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5615 
5616 	params = 6;
5617 	pSMB->MaxSetupCount = 0;
5618 	pSMB->Reserved = 0;
5619 	pSMB->Flags = 0;
5620 	pSMB->Timeout = 0;
5621 	pSMB->Reserved2 = 0;
5622 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5623 	offset = param_offset + params;
5624 
5625 	count = sizeof(struct file_end_of_file_info);
5626 	pSMB->MaxParameterCount = cpu_to_le16(2);
5627 	/* BB find exact max SMB PDU from sess structure BB */
5628 	pSMB->MaxDataCount = cpu_to_le16(1000);
5629 	pSMB->SetupCount = 1;
5630 	pSMB->Reserved3 = 0;
5631 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5632 	byte_count = 3 /* pad */  + params + count;
5633 	pSMB->DataCount = cpu_to_le16(count);
5634 	pSMB->ParameterCount = cpu_to_le16(params);
5635 	pSMB->TotalDataCount = pSMB->DataCount;
5636 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5637 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5638 	parm_data =
5639 		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5640 				+ offset);
5641 	pSMB->DataOffset = cpu_to_le16(offset);
5642 	parm_data->FileSize = cpu_to_le64(size);
5643 	pSMB->Fid = cfile->fid.netfid;
5644 	if (set_allocation) {
5645 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5646 			pSMB->InformationLevel =
5647 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5648 		else
5649 			pSMB->InformationLevel =
5650 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5651 	} else /* Set File Size */  {
5652 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5653 		    pSMB->InformationLevel =
5654 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5655 	    else
5656 		    pSMB->InformationLevel =
5657 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5658 	}
5659 	pSMB->Reserved4 = 0;
5660 	inc_rfc1001_len(pSMB, byte_count);
5661 	pSMB->ByteCount = cpu_to_le16(byte_count);
5662 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5663 	cifs_small_buf_release(pSMB);
5664 	if (rc) {
5665 		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5666 			 rc);
5667 	}
5668 
5669 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5670 		since file handle passed in no longer valid */
5671 
5672 	return rc;
5673 }
5674 
5675 /* Some legacy servers such as NT4 require that the file times be set on
5676    an open handle, rather than by pathname - this is awkward due to
5677    potential access conflicts on the open, but it is unavoidable for these
5678    old servers since the only other choice is to go from 100 nanosecond DCE
5679    time and resort to the original setpathinfo level which takes the ancient
5680    DOS time format with 2 second granularity */
5681 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5682 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5683 		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5684 {
5685 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5686 	char *data_offset;
5687 	int rc = 0;
5688 	__u16 params, param_offset, offset, byte_count, count;
5689 
5690 	cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5691 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5692 
5693 	if (rc)
5694 		return rc;
5695 
5696 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5697 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5698 
5699 	params = 6;
5700 	pSMB->MaxSetupCount = 0;
5701 	pSMB->Reserved = 0;
5702 	pSMB->Flags = 0;
5703 	pSMB->Timeout = 0;
5704 	pSMB->Reserved2 = 0;
5705 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5706 	offset = param_offset + params;
5707 
5708 	data_offset = (char *)pSMB +
5709 			offsetof(struct smb_hdr, Protocol) + offset;
5710 
5711 	count = sizeof(FILE_BASIC_INFO);
5712 	pSMB->MaxParameterCount = cpu_to_le16(2);
5713 	/* BB find max SMB PDU from sess */
5714 	pSMB->MaxDataCount = cpu_to_le16(1000);
5715 	pSMB->SetupCount = 1;
5716 	pSMB->Reserved3 = 0;
5717 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5718 	byte_count = 3 /* pad */  + params + count;
5719 	pSMB->DataCount = cpu_to_le16(count);
5720 	pSMB->ParameterCount = cpu_to_le16(params);
5721 	pSMB->TotalDataCount = pSMB->DataCount;
5722 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5723 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5724 	pSMB->DataOffset = cpu_to_le16(offset);
5725 	pSMB->Fid = fid;
5726 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5727 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5728 	else
5729 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5730 	pSMB->Reserved4 = 0;
5731 	inc_rfc1001_len(pSMB, byte_count);
5732 	pSMB->ByteCount = cpu_to_le16(byte_count);
5733 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5734 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5735 	cifs_small_buf_release(pSMB);
5736 	if (rc)
5737 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5738 			 rc);
5739 
5740 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5741 		since file handle passed in no longer valid */
5742 
5743 	return rc;
5744 }
5745 
5746 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5747 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5748 			  bool delete_file, __u16 fid, __u32 pid_of_opener)
5749 {
5750 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5751 	char *data_offset;
5752 	int rc = 0;
5753 	__u16 params, param_offset, offset, byte_count, count;
5754 
5755 	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5756 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5757 
5758 	if (rc)
5759 		return rc;
5760 
5761 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5762 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5763 
5764 	params = 6;
5765 	pSMB->MaxSetupCount = 0;
5766 	pSMB->Reserved = 0;
5767 	pSMB->Flags = 0;
5768 	pSMB->Timeout = 0;
5769 	pSMB->Reserved2 = 0;
5770 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5771 	offset = param_offset + params;
5772 
5773 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5774 
5775 	count = 1;
5776 	pSMB->MaxParameterCount = cpu_to_le16(2);
5777 	/* BB find max SMB PDU from sess */
5778 	pSMB->MaxDataCount = cpu_to_le16(1000);
5779 	pSMB->SetupCount = 1;
5780 	pSMB->Reserved3 = 0;
5781 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5782 	byte_count = 3 /* pad */  + params + count;
5783 	pSMB->DataCount = cpu_to_le16(count);
5784 	pSMB->ParameterCount = cpu_to_le16(params);
5785 	pSMB->TotalDataCount = pSMB->DataCount;
5786 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5787 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5788 	pSMB->DataOffset = cpu_to_le16(offset);
5789 	pSMB->Fid = fid;
5790 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5791 	pSMB->Reserved4 = 0;
5792 	inc_rfc1001_len(pSMB, byte_count);
5793 	pSMB->ByteCount = cpu_to_le16(byte_count);
5794 	*data_offset = delete_file ? 1 : 0;
5795 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5796 	cifs_small_buf_release(pSMB);
5797 	if (rc)
5798 		cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5799 
5800 	return rc;
5801 }
5802 
5803 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)5804 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5805 		   const char *fileName, const FILE_BASIC_INFO *data,
5806 		   const struct nls_table *nls_codepage, int remap)
5807 {
5808 	TRANSACTION2_SPI_REQ *pSMB = NULL;
5809 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5810 	int name_len;
5811 	int rc = 0;
5812 	int bytes_returned = 0;
5813 	char *data_offset;
5814 	__u16 params, param_offset, offset, byte_count, count;
5815 
5816 	cifs_dbg(FYI, "In SetTimes\n");
5817 
5818 SetTimesRetry:
5819 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5820 		      (void **) &pSMBr);
5821 	if (rc)
5822 		return rc;
5823 
5824 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5825 		name_len =
5826 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5827 				       PATH_MAX, nls_codepage, remap);
5828 		name_len++;	/* trailing null */
5829 		name_len *= 2;
5830 	} else {	/* BB improve the check for buffer overruns BB */
5831 		name_len = strnlen(fileName, PATH_MAX);
5832 		name_len++;	/* trailing null */
5833 		strncpy(pSMB->FileName, fileName, name_len);
5834 	}
5835 
5836 	params = 6 + name_len;
5837 	count = sizeof(FILE_BASIC_INFO);
5838 	pSMB->MaxParameterCount = cpu_to_le16(2);
5839 	/* BB find max SMB PDU from sess structure BB */
5840 	pSMB->MaxDataCount = cpu_to_le16(1000);
5841 	pSMB->MaxSetupCount = 0;
5842 	pSMB->Reserved = 0;
5843 	pSMB->Flags = 0;
5844 	pSMB->Timeout = 0;
5845 	pSMB->Reserved2 = 0;
5846 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5847 				InformationLevel) - 4;
5848 	offset = param_offset + params;
5849 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5850 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5851 	pSMB->DataOffset = cpu_to_le16(offset);
5852 	pSMB->SetupCount = 1;
5853 	pSMB->Reserved3 = 0;
5854 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5855 	byte_count = 3 /* pad */  + params + count;
5856 
5857 	pSMB->DataCount = cpu_to_le16(count);
5858 	pSMB->ParameterCount = cpu_to_le16(params);
5859 	pSMB->TotalDataCount = pSMB->DataCount;
5860 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5861 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5862 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5863 	else
5864 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5865 	pSMB->Reserved4 = 0;
5866 	inc_rfc1001_len(pSMB, byte_count);
5867 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5868 	pSMB->ByteCount = cpu_to_le16(byte_count);
5869 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5870 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5871 	if (rc)
5872 		cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5873 
5874 	cifs_buf_release(pSMB);
5875 
5876 	if (rc == -EAGAIN)
5877 		goto SetTimesRetry;
5878 
5879 	return rc;
5880 }
5881 
5882 /* Can not be used to set time stamps yet (due to old DOS time format) */
5883 /* Can be used to set attributes */
5884 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5885 	  handling it anyway and NT4 was what we thought it would be needed for
5886 	  Do not delete it until we prove whether needed for Win9x though */
5887 int
5888 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5889 		__u16 dos_attrs, const struct nls_table *nls_codepage)
5890 {
5891 	SETATTR_REQ *pSMB = NULL;
5892 	SETATTR_RSP *pSMBr = NULL;
5893 	int rc = 0;
5894 	int bytes_returned;
5895 	int name_len;
5896 
5897 	cifs_dbg(FYI, "In SetAttrLegacy\n");
5898 
5899 SetAttrLgcyRetry:
5900 	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5901 		      (void **) &pSMBr);
5902 	if (rc)
5903 		return rc;
5904 
5905 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5906 		name_len =
5907 			ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5908 				       PATH_MAX, nls_codepage);
5909 		name_len++;     /* trailing null */
5910 		name_len *= 2;
5911 	} else {	/* BB improve the check for buffer overruns BB */
5912 		name_len = strnlen(fileName, PATH_MAX);
5913 		name_len++;     /* trailing null */
5914 		strncpy(pSMB->fileName, fileName, name_len);
5915 	}
5916 	pSMB->attr = cpu_to_le16(dos_attrs);
5917 	pSMB->BufferFormat = 0x04;
5918 	inc_rfc1001_len(pSMB, name_len + 1);
5919 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
5920 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5921 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5922 	if (rc)
5923 		cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5924 
5925 	cifs_buf_release(pSMB);
5926 
5927 	if (rc == -EAGAIN)
5928 		goto SetAttrLgcyRetry;
5929 
5930 	return rc;
5931 }
5932 #endif /* temporarily unneeded SetAttr legacy function */
5933 
5934 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5935 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5936 			const struct cifs_unix_set_info_args *args)
5937 {
5938 	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5939 	u64 mode = args->mode;
5940 
5941 	if (uid_valid(args->uid))
5942 		uid = from_kuid(&init_user_ns, args->uid);
5943 	if (gid_valid(args->gid))
5944 		gid = from_kgid(&init_user_ns, args->gid);
5945 
5946 	/*
5947 	 * Samba server ignores set of file size to zero due to bugs in some
5948 	 * older clients, but we should be precise - we use SetFileSize to
5949 	 * set file size and do not want to truncate file size to zero
5950 	 * accidentally as happened on one Samba server beta by putting
5951 	 * zero instead of -1 here
5952 	 */
5953 	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5954 	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5955 	data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5956 	data_offset->LastAccessTime = cpu_to_le64(args->atime);
5957 	data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5958 	data_offset->Uid = cpu_to_le64(uid);
5959 	data_offset->Gid = cpu_to_le64(gid);
5960 	/* better to leave device as zero when it is  */
5961 	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5962 	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5963 	data_offset->Permissions = cpu_to_le64(mode);
5964 
5965 	if (S_ISREG(mode))
5966 		data_offset->Type = cpu_to_le32(UNIX_FILE);
5967 	else if (S_ISDIR(mode))
5968 		data_offset->Type = cpu_to_le32(UNIX_DIR);
5969 	else if (S_ISLNK(mode))
5970 		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5971 	else if (S_ISCHR(mode))
5972 		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5973 	else if (S_ISBLK(mode))
5974 		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5975 	else if (S_ISFIFO(mode))
5976 		data_offset->Type = cpu_to_le32(UNIX_FIFO);
5977 	else if (S_ISSOCK(mode))
5978 		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5979 }
5980 
5981 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)5982 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5983 		       const struct cifs_unix_set_info_args *args,
5984 		       u16 fid, u32 pid_of_opener)
5985 {
5986 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5987 	char *data_offset;
5988 	int rc = 0;
5989 	u16 params, param_offset, offset, byte_count, count;
5990 
5991 	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5992 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5993 
5994 	if (rc)
5995 		return rc;
5996 
5997 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5998 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5999 
6000 	params = 6;
6001 	pSMB->MaxSetupCount = 0;
6002 	pSMB->Reserved = 0;
6003 	pSMB->Flags = 0;
6004 	pSMB->Timeout = 0;
6005 	pSMB->Reserved2 = 0;
6006 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6007 	offset = param_offset + params;
6008 
6009 	data_offset = (char *)pSMB +
6010 			offsetof(struct smb_hdr, Protocol) + offset;
6011 
6012 	count = sizeof(FILE_UNIX_BASIC_INFO);
6013 
6014 	pSMB->MaxParameterCount = cpu_to_le16(2);
6015 	/* BB find max SMB PDU from sess */
6016 	pSMB->MaxDataCount = cpu_to_le16(1000);
6017 	pSMB->SetupCount = 1;
6018 	pSMB->Reserved3 = 0;
6019 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6020 	byte_count = 3 /* pad */  + params + count;
6021 	pSMB->DataCount = cpu_to_le16(count);
6022 	pSMB->ParameterCount = cpu_to_le16(params);
6023 	pSMB->TotalDataCount = pSMB->DataCount;
6024 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6025 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6026 	pSMB->DataOffset = cpu_to_le16(offset);
6027 	pSMB->Fid = fid;
6028 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6029 	pSMB->Reserved4 = 0;
6030 	inc_rfc1001_len(pSMB, byte_count);
6031 	pSMB->ByteCount = cpu_to_le16(byte_count);
6032 
6033 	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6034 
6035 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6036 	cifs_small_buf_release(pSMB);
6037 	if (rc)
6038 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6039 			 rc);
6040 
6041 	/* Note: On -EAGAIN error only caller can retry on handle based calls
6042 		since file handle passed in no longer valid */
6043 
6044 	return rc;
6045 }
6046 
6047 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)6048 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6049 		       const char *file_name,
6050 		       const struct cifs_unix_set_info_args *args,
6051 		       const struct nls_table *nls_codepage, int remap)
6052 {
6053 	TRANSACTION2_SPI_REQ *pSMB = NULL;
6054 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
6055 	int name_len;
6056 	int rc = 0;
6057 	int bytes_returned = 0;
6058 	FILE_UNIX_BASIC_INFO *data_offset;
6059 	__u16 params, param_offset, offset, count, byte_count;
6060 
6061 	cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6062 setPermsRetry:
6063 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6064 		      (void **) &pSMBr);
6065 	if (rc)
6066 		return rc;
6067 
6068 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6069 		name_len =
6070 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6071 				       PATH_MAX, nls_codepage, remap);
6072 		name_len++;	/* trailing null */
6073 		name_len *= 2;
6074 	} else {	/* BB improve the check for buffer overruns BB */
6075 		name_len = strnlen(file_name, PATH_MAX);
6076 		name_len++;	/* trailing null */
6077 		strncpy(pSMB->FileName, file_name, name_len);
6078 	}
6079 
6080 	params = 6 + name_len;
6081 	count = sizeof(FILE_UNIX_BASIC_INFO);
6082 	pSMB->MaxParameterCount = cpu_to_le16(2);
6083 	/* BB find max SMB PDU from sess structure BB */
6084 	pSMB->MaxDataCount = cpu_to_le16(1000);
6085 	pSMB->MaxSetupCount = 0;
6086 	pSMB->Reserved = 0;
6087 	pSMB->Flags = 0;
6088 	pSMB->Timeout = 0;
6089 	pSMB->Reserved2 = 0;
6090 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6091 				InformationLevel) - 4;
6092 	offset = param_offset + params;
6093 	data_offset =
6094 	    (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6095 				      offset);
6096 	memset(data_offset, 0, count);
6097 	pSMB->DataOffset = cpu_to_le16(offset);
6098 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6099 	pSMB->SetupCount = 1;
6100 	pSMB->Reserved3 = 0;
6101 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6102 	byte_count = 3 /* pad */  + params + count;
6103 	pSMB->ParameterCount = cpu_to_le16(params);
6104 	pSMB->DataCount = cpu_to_le16(count);
6105 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6106 	pSMB->TotalDataCount = pSMB->DataCount;
6107 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6108 	pSMB->Reserved4 = 0;
6109 	inc_rfc1001_len(pSMB, byte_count);
6110 
6111 	cifs_fill_unix_set_info(data_offset, args);
6112 
6113 	pSMB->ByteCount = cpu_to_le16(byte_count);
6114 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6115 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6116 	if (rc)
6117 		cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6118 
6119 	cifs_buf_release(pSMB);
6120 	if (rc == -EAGAIN)
6121 		goto setPermsRetry;
6122 	return rc;
6123 }
6124 
6125 #ifdef CONFIG_CIFS_XATTR
6126 /*
6127  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6128  * function used by listxattr and getxattr type calls. When ea_name is set,
6129  * it looks for that attribute name and stuffs that value into the EAData
6130  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6131  * buffer. In both cases, the return value is either the length of the
6132  * resulting data or a negative error code. If EAData is a NULL pointer then
6133  * the data isn't copied to it, but the length is returned.
6134  */
6135 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)6136 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6137 		const unsigned char *searchName, const unsigned char *ea_name,
6138 		char *EAData, size_t buf_size,
6139 		struct cifs_sb_info *cifs_sb)
6140 {
6141 		/* BB assumes one setup word */
6142 	TRANSACTION2_QPI_REQ *pSMB = NULL;
6143 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
6144 	int remap = cifs_remap(cifs_sb);
6145 	struct nls_table *nls_codepage = cifs_sb->local_nls;
6146 	int rc = 0;
6147 	int bytes_returned;
6148 	int list_len;
6149 	struct fealist *ea_response_data;
6150 	struct fea *temp_fea;
6151 	char *temp_ptr;
6152 	char *end_of_smb;
6153 	__u16 params, byte_count, data_offset;
6154 	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6155 
6156 	cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6157 QAllEAsRetry:
6158 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6159 		      (void **) &pSMBr);
6160 	if (rc)
6161 		return rc;
6162 
6163 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6164 		list_len =
6165 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6166 				       PATH_MAX, nls_codepage, remap);
6167 		list_len++;	/* trailing null */
6168 		list_len *= 2;
6169 	} else {	/* BB improve the check for buffer overruns BB */
6170 		list_len = strnlen(searchName, PATH_MAX);
6171 		list_len++;	/* trailing null */
6172 		strncpy(pSMB->FileName, searchName, list_len);
6173 	}
6174 
6175 	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6176 	pSMB->TotalDataCount = 0;
6177 	pSMB->MaxParameterCount = cpu_to_le16(2);
6178 	/* BB find exact max SMB PDU from sess structure BB */
6179 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6180 	pSMB->MaxSetupCount = 0;
6181 	pSMB->Reserved = 0;
6182 	pSMB->Flags = 0;
6183 	pSMB->Timeout = 0;
6184 	pSMB->Reserved2 = 0;
6185 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
6186 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6187 	pSMB->DataCount = 0;
6188 	pSMB->DataOffset = 0;
6189 	pSMB->SetupCount = 1;
6190 	pSMB->Reserved3 = 0;
6191 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6192 	byte_count = params + 1 /* pad */ ;
6193 	pSMB->TotalParameterCount = cpu_to_le16(params);
6194 	pSMB->ParameterCount = pSMB->TotalParameterCount;
6195 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6196 	pSMB->Reserved4 = 0;
6197 	inc_rfc1001_len(pSMB, byte_count);
6198 	pSMB->ByteCount = cpu_to_le16(byte_count);
6199 
6200 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6201 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6202 	if (rc) {
6203 		cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6204 		goto QAllEAsOut;
6205 	}
6206 
6207 
6208 	/* BB also check enough total bytes returned */
6209 	/* BB we need to improve the validity checking
6210 	of these trans2 responses */
6211 
6212 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6213 	if (rc || get_bcc(&pSMBr->hdr) < 4) {
6214 		rc = -EIO;	/* bad smb */
6215 		goto QAllEAsOut;
6216 	}
6217 
6218 	/* check that length of list is not more than bcc */
6219 	/* check that each entry does not go beyond length
6220 	   of list */
6221 	/* check that each element of each entry does not
6222 	   go beyond end of list */
6223 	/* validate_trans2_offsets() */
6224 	/* BB check if start of smb + data_offset > &bcc+ bcc */
6225 
6226 	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6227 	ea_response_data = (struct fealist *)
6228 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
6229 
6230 	list_len = le32_to_cpu(ea_response_data->list_len);
6231 	cifs_dbg(FYI, "ea length %d\n", list_len);
6232 	if (list_len <= 8) {
6233 		cifs_dbg(FYI, "empty EA list returned from server\n");
6234 		/* didn't find the named attribute */
6235 		if (ea_name)
6236 			rc = -ENODATA;
6237 		goto QAllEAsOut;
6238 	}
6239 
6240 	/* make sure list_len doesn't go past end of SMB */
6241 	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6242 	if ((char *)ea_response_data + list_len > end_of_smb) {
6243 		cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6244 		rc = -EIO;
6245 		goto QAllEAsOut;
6246 	}
6247 
6248 	/* account for ea list len */
6249 	list_len -= 4;
6250 	temp_fea = ea_response_data->list;
6251 	temp_ptr = (char *)temp_fea;
6252 	while (list_len > 0) {
6253 		unsigned int name_len;
6254 		__u16 value_len;
6255 
6256 		list_len -= 4;
6257 		temp_ptr += 4;
6258 		/* make sure we can read name_len and value_len */
6259 		if (list_len < 0) {
6260 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6261 			rc = -EIO;
6262 			goto QAllEAsOut;
6263 		}
6264 
6265 		name_len = temp_fea->name_len;
6266 		value_len = le16_to_cpu(temp_fea->value_len);
6267 		list_len -= name_len + 1 + value_len;
6268 		if (list_len < 0) {
6269 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6270 			rc = -EIO;
6271 			goto QAllEAsOut;
6272 		}
6273 
6274 		if (ea_name) {
6275 			if (ea_name_len == name_len &&
6276 			    memcmp(ea_name, temp_ptr, name_len) == 0) {
6277 				temp_ptr += name_len + 1;
6278 				rc = value_len;
6279 				if (buf_size == 0)
6280 					goto QAllEAsOut;
6281 				if ((size_t)value_len > buf_size) {
6282 					rc = -ERANGE;
6283 					goto QAllEAsOut;
6284 				}
6285 				memcpy(EAData, temp_ptr, value_len);
6286 				goto QAllEAsOut;
6287 			}
6288 		} else {
6289 			/* account for prefix user. and trailing null */
6290 			rc += (5 + 1 + name_len);
6291 			if (rc < (int) buf_size) {
6292 				memcpy(EAData, "user.", 5);
6293 				EAData += 5;
6294 				memcpy(EAData, temp_ptr, name_len);
6295 				EAData += name_len;
6296 				/* null terminate name */
6297 				*EAData = 0;
6298 				++EAData;
6299 			} else if (buf_size == 0) {
6300 				/* skip copy - calc size only */
6301 			} else {
6302 				/* stop before overrun buffer */
6303 				rc = -ERANGE;
6304 				break;
6305 			}
6306 		}
6307 		temp_ptr += name_len + 1 + value_len;
6308 		temp_fea = (struct fea *)temp_ptr;
6309 	}
6310 
6311 	/* didn't find the named attribute */
6312 	if (ea_name)
6313 		rc = -ENODATA;
6314 
6315 QAllEAsOut:
6316 	cifs_buf_release(pSMB);
6317 	if (rc == -EAGAIN)
6318 		goto QAllEAsRetry;
6319 
6320 	return (ssize_t)rc;
6321 }
6322 
6323 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)6324 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6325 	     const char *fileName, const char *ea_name, const void *ea_value,
6326 	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
6327 	     struct cifs_sb_info *cifs_sb)
6328 {
6329 	struct smb_com_transaction2_spi_req *pSMB = NULL;
6330 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6331 	struct fealist *parm_data;
6332 	int name_len;
6333 	int rc = 0;
6334 	int bytes_returned = 0;
6335 	__u16 params, param_offset, byte_count, offset, count;
6336 	int remap = cifs_remap(cifs_sb);
6337 
6338 	cifs_dbg(FYI, "In SetEA\n");
6339 SetEARetry:
6340 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6341 		      (void **) &pSMBr);
6342 	if (rc)
6343 		return rc;
6344 
6345 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6346 		name_len =
6347 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6348 				       PATH_MAX, nls_codepage, remap);
6349 		name_len++;	/* trailing null */
6350 		name_len *= 2;
6351 	} else {	/* BB improve the check for buffer overruns BB */
6352 		name_len = strnlen(fileName, PATH_MAX);
6353 		name_len++;	/* trailing null */
6354 		strncpy(pSMB->FileName, fileName, name_len);
6355 	}
6356 
6357 	params = 6 + name_len;
6358 
6359 	/* done calculating parms using name_len of file name,
6360 	now use name_len to calculate length of ea name
6361 	we are going to create in the inode xattrs */
6362 	if (ea_name == NULL)
6363 		name_len = 0;
6364 	else
6365 		name_len = strnlen(ea_name, 255);
6366 
6367 	count = sizeof(*parm_data) + ea_value_len + name_len;
6368 	pSMB->MaxParameterCount = cpu_to_le16(2);
6369 	/* BB find max SMB PDU from sess */
6370 	pSMB->MaxDataCount = cpu_to_le16(1000);
6371 	pSMB->MaxSetupCount = 0;
6372 	pSMB->Reserved = 0;
6373 	pSMB->Flags = 0;
6374 	pSMB->Timeout = 0;
6375 	pSMB->Reserved2 = 0;
6376 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6377 				InformationLevel) - 4;
6378 	offset = param_offset + params;
6379 	pSMB->InformationLevel =
6380 		cpu_to_le16(SMB_SET_FILE_EA);
6381 
6382 	parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6383 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6384 	pSMB->DataOffset = cpu_to_le16(offset);
6385 	pSMB->SetupCount = 1;
6386 	pSMB->Reserved3 = 0;
6387 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6388 	byte_count = 3 /* pad */  + params + count;
6389 	pSMB->DataCount = cpu_to_le16(count);
6390 	parm_data->list_len = cpu_to_le32(count);
6391 	parm_data->list[0].EA_flags = 0;
6392 	/* we checked above that name len is less than 255 */
6393 	parm_data->list[0].name_len = (__u8)name_len;
6394 	/* EA names are always ASCII */
6395 	if (ea_name)
6396 		strncpy(parm_data->list[0].name, ea_name, name_len);
6397 	parm_data->list[0].name[name_len] = 0;
6398 	parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6399 	/* caller ensures that ea_value_len is less than 64K but
6400 	we need to ensure that it fits within the smb */
6401 
6402 	/*BB add length check to see if it would fit in
6403 	     negotiated SMB buffer size BB */
6404 	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
6405 	if (ea_value_len)
6406 		memcpy(parm_data->list[0].name+name_len+1,
6407 		       ea_value, ea_value_len);
6408 
6409 	pSMB->TotalDataCount = pSMB->DataCount;
6410 	pSMB->ParameterCount = cpu_to_le16(params);
6411 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6412 	pSMB->Reserved4 = 0;
6413 	inc_rfc1001_len(pSMB, byte_count);
6414 	pSMB->ByteCount = cpu_to_le16(byte_count);
6415 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6416 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6417 	if (rc)
6418 		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6419 
6420 	cifs_buf_release(pSMB);
6421 
6422 	if (rc == -EAGAIN)
6423 		goto SetEARetry;
6424 
6425 	return rc;
6426 }
6427 #endif
6428 
6429 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6430 /*
6431  *	Years ago the kernel added a "dnotify" function for Samba server,
6432  *	to allow network clients (such as Windows) to display updated
6433  *	lists of files in directory listings automatically when
6434  *	files are added by one user when another user has the
6435  *	same directory open on their desktop.  The Linux cifs kernel
6436  *	client hooked into the kernel side of this interface for
6437  *	the same reason, but ironically when the VFS moved from
6438  *	"dnotify" to "inotify" it became harder to plug in Linux
6439  *	network file system clients (the most obvious use case
6440  *	for notify interfaces is when multiple users can update
6441  *	the contents of the same directory - exactly what network
6442  *	file systems can do) although the server (Samba) could
6443  *	still use it.  For the short term we leave the worker
6444  *	function ifdeffed out (below) until inotify is fixed
6445  *	in the VFS to make it easier to plug in network file
6446  *	system clients.  If inotify turns out to be permanently
6447  *	incompatible for network fs clients, we could instead simply
6448  *	expose this config flag by adding a future cifs (and smb2) notify ioctl.
6449  */
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)6450 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6451 		  const int notify_subdirs, const __u16 netfid,
6452 		  __u32 filter, struct file *pfile, int multishot,
6453 		  const struct nls_table *nls_codepage)
6454 {
6455 	int rc = 0;
6456 	struct smb_com_transaction_change_notify_req *pSMB = NULL;
6457 	struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6458 	struct dir_notify_req *dnotify_req;
6459 	int bytes_returned;
6460 
6461 	cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid);
6462 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6463 		      (void **) &pSMBr);
6464 	if (rc)
6465 		return rc;
6466 
6467 	pSMB->TotalParameterCount = 0 ;
6468 	pSMB->TotalDataCount = 0;
6469 	pSMB->MaxParameterCount = cpu_to_le32(2);
6470 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6471 	pSMB->MaxSetupCount = 4;
6472 	pSMB->Reserved = 0;
6473 	pSMB->ParameterOffset = 0;
6474 	pSMB->DataCount = 0;
6475 	pSMB->DataOffset = 0;
6476 	pSMB->SetupCount = 4; /* single byte does not need le conversion */
6477 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6478 	pSMB->ParameterCount = pSMB->TotalParameterCount;
6479 	if (notify_subdirs)
6480 		pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6481 	pSMB->Reserved2 = 0;
6482 	pSMB->CompletionFilter = cpu_to_le32(filter);
6483 	pSMB->Fid = netfid; /* file handle always le */
6484 	pSMB->ByteCount = 0;
6485 
6486 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6487 			 (struct smb_hdr *)pSMBr, &bytes_returned,
6488 			 CIFS_ASYNC_OP);
6489 	if (rc) {
6490 		cifs_dbg(FYI, "Error in Notify = %d\n", rc);
6491 	} else {
6492 		/* Add file to outstanding requests */
6493 		/* BB change to kmem cache alloc */
6494 		dnotify_req = kmalloc(
6495 						sizeof(struct dir_notify_req),
6496 						 GFP_KERNEL);
6497 		if (dnotify_req) {
6498 			dnotify_req->Pid = pSMB->hdr.Pid;
6499 			dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6500 			dnotify_req->Mid = pSMB->hdr.Mid;
6501 			dnotify_req->Tid = pSMB->hdr.Tid;
6502 			dnotify_req->Uid = pSMB->hdr.Uid;
6503 			dnotify_req->netfid = netfid;
6504 			dnotify_req->pfile = pfile;
6505 			dnotify_req->filter = filter;
6506 			dnotify_req->multishot = multishot;
6507 			spin_lock(&GlobalMid_Lock);
6508 			list_add_tail(&dnotify_req->lhead,
6509 					&GlobalDnotifyReqList);
6510 			spin_unlock(&GlobalMid_Lock);
6511 		} else
6512 			rc = -ENOMEM;
6513 	}
6514 	cifs_buf_release(pSMB);
6515 	return rc;
6516 }
6517 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
6518