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