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