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