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