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