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