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