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