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