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