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