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