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