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