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