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