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