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 rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4755 (void **) &pSMBr);
4756 if (rc)
4757 return rc;
4758
4759 /* server pointer checked in called function,
4760 but should never be null here anyway */
4761 pSMB->hdr.Mid = get_next_mid(ses->server);
4762 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4763 pSMB->hdr.Uid = ses->Suid;
4764 if (ses->capabilities & CAP_STATUS32)
4765 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4766 if (ses->capabilities & CAP_DFS)
4767 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4768
4769 if (ses->capabilities & CAP_UNICODE) {
4770 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4771 name_len =
4772 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4773 search_name, PATH_MAX, nls_codepage,
4774 remap);
4775 name_len++; /* trailing null */
4776 name_len *= 2;
4777 } else { /* BB improve the check for buffer overruns BB */
4778 name_len = copy_path_name(pSMB->RequestFileName, search_name);
4779 }
4780
4781 if (ses->server->sign)
4782 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4783
4784 pSMB->hdr.Uid = ses->Suid;
4785
4786 params = 2 /* level */ + name_len /*includes null */ ;
4787 pSMB->TotalDataCount = 0;
4788 pSMB->DataCount = 0;
4789 pSMB->DataOffset = 0;
4790 pSMB->MaxParameterCount = 0;
4791 /* BB find exact max SMB PDU from sess structure BB */
4792 pSMB->MaxDataCount = cpu_to_le16(4000);
4793 pSMB->MaxSetupCount = 0;
4794 pSMB->Reserved = 0;
4795 pSMB->Flags = 0;
4796 pSMB->Timeout = 0;
4797 pSMB->Reserved2 = 0;
4798 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4799 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4800 pSMB->SetupCount = 1;
4801 pSMB->Reserved3 = 0;
4802 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4803 byte_count = params + 3 /* pad */ ;
4804 pSMB->ParameterCount = cpu_to_le16(params);
4805 pSMB->TotalParameterCount = pSMB->ParameterCount;
4806 pSMB->MaxReferralLevel = cpu_to_le16(3);
4807 inc_rfc1001_len(pSMB, byte_count);
4808 pSMB->ByteCount = cpu_to_le16(byte_count);
4809
4810 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4811 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4812 if (rc) {
4813 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4814 goto GetDFSRefExit;
4815 }
4816 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4817
4818 /* BB Also check if enough total bytes returned? */
4819 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4820 rc = -EIO; /* bad smb */
4821 goto GetDFSRefExit;
4822 }
4823
4824 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4825 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4826
4827 /* parse returned result into more usable form */
4828 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4829 le16_to_cpu(pSMBr->t2.DataCount),
4830 num_of_nodes, target_nodes, nls_codepage,
4831 remap, search_name,
4832 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4833
4834 GetDFSRefExit:
4835 cifs_buf_release(pSMB);
4836
4837 if (rc == -EAGAIN)
4838 goto getDFSRetry;
4839
4840 return rc;
4841 }
4842
4843 /* Query File System Info such as free space to old servers such as Win 9x */
4844 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4845 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4846 struct kstatfs *FSData)
4847 {
4848 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4849 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4850 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4851 FILE_SYSTEM_ALLOC_INFO *response_data;
4852 int rc = 0;
4853 int bytes_returned = 0;
4854 __u16 params, byte_count;
4855
4856 cifs_dbg(FYI, "OldQFSInfo\n");
4857 oldQFSInfoRetry:
4858 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4859 (void **) &pSMBr);
4860 if (rc)
4861 return rc;
4862
4863 params = 2; /* level */
4864 pSMB->TotalDataCount = 0;
4865 pSMB->MaxParameterCount = cpu_to_le16(2);
4866 pSMB->MaxDataCount = cpu_to_le16(1000);
4867 pSMB->MaxSetupCount = 0;
4868 pSMB->Reserved = 0;
4869 pSMB->Flags = 0;
4870 pSMB->Timeout = 0;
4871 pSMB->Reserved2 = 0;
4872 byte_count = params + 1 /* pad */ ;
4873 pSMB->TotalParameterCount = cpu_to_le16(params);
4874 pSMB->ParameterCount = pSMB->TotalParameterCount;
4875 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4876 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4877 pSMB->DataCount = 0;
4878 pSMB->DataOffset = 0;
4879 pSMB->SetupCount = 1;
4880 pSMB->Reserved3 = 0;
4881 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4882 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4883 inc_rfc1001_len(pSMB, byte_count);
4884 pSMB->ByteCount = cpu_to_le16(byte_count);
4885
4886 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4887 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4888 if (rc) {
4889 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4890 } else { /* decode response */
4891 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4892
4893 if (rc || get_bcc(&pSMBr->hdr) < 18)
4894 rc = -EIO; /* bad smb */
4895 else {
4896 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4897 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
4898 get_bcc(&pSMBr->hdr), data_offset);
4899
4900 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4901 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4902 FSData->f_bsize =
4903 le16_to_cpu(response_data->BytesPerSector) *
4904 le32_to_cpu(response_data->
4905 SectorsPerAllocationUnit);
4906 /*
4907 * much prefer larger but if server doesn't report
4908 * a valid size than 4K is a reasonable minimum
4909 */
4910 if (FSData->f_bsize < 512)
4911 FSData->f_bsize = 4096;
4912
4913 FSData->f_blocks =
4914 le32_to_cpu(response_data->TotalAllocationUnits);
4915 FSData->f_bfree = FSData->f_bavail =
4916 le32_to_cpu(response_data->FreeAllocationUnits);
4917 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4918 (unsigned long long)FSData->f_blocks,
4919 (unsigned long long)FSData->f_bfree,
4920 FSData->f_bsize);
4921 }
4922 }
4923 cifs_buf_release(pSMB);
4924
4925 if (rc == -EAGAIN)
4926 goto oldQFSInfoRetry;
4927
4928 return rc;
4929 }
4930
4931 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4932 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4933 struct kstatfs *FSData)
4934 {
4935 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4936 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4937 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4938 FILE_SYSTEM_INFO *response_data;
4939 int rc = 0;
4940 int bytes_returned = 0;
4941 __u16 params, byte_count;
4942
4943 cifs_dbg(FYI, "In QFSInfo\n");
4944 QFSInfoRetry:
4945 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4946 (void **) &pSMBr);
4947 if (rc)
4948 return rc;
4949
4950 params = 2; /* level */
4951 pSMB->TotalDataCount = 0;
4952 pSMB->MaxParameterCount = cpu_to_le16(2);
4953 pSMB->MaxDataCount = cpu_to_le16(1000);
4954 pSMB->MaxSetupCount = 0;
4955 pSMB->Reserved = 0;
4956 pSMB->Flags = 0;
4957 pSMB->Timeout = 0;
4958 pSMB->Reserved2 = 0;
4959 byte_count = params + 1 /* pad */ ;
4960 pSMB->TotalParameterCount = cpu_to_le16(params);
4961 pSMB->ParameterCount = pSMB->TotalParameterCount;
4962 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4963 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4964 pSMB->DataCount = 0;
4965 pSMB->DataOffset = 0;
4966 pSMB->SetupCount = 1;
4967 pSMB->Reserved3 = 0;
4968 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4969 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4970 inc_rfc1001_len(pSMB, byte_count);
4971 pSMB->ByteCount = cpu_to_le16(byte_count);
4972
4973 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4975 if (rc) {
4976 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4977 } else { /* decode response */
4978 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4979
4980 if (rc || get_bcc(&pSMBr->hdr) < 24)
4981 rc = -EIO; /* bad smb */
4982 else {
4983 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4984
4985 response_data =
4986 (FILE_SYSTEM_INFO
4987 *) (((char *) &pSMBr->hdr.Protocol) +
4988 data_offset);
4989 FSData->f_bsize =
4990 le32_to_cpu(response_data->BytesPerSector) *
4991 le32_to_cpu(response_data->
4992 SectorsPerAllocationUnit);
4993 /*
4994 * much prefer larger but if server doesn't report
4995 * a valid size than 4K is a reasonable minimum
4996 */
4997 if (FSData->f_bsize < 512)
4998 FSData->f_bsize = 4096;
4999
5000 FSData->f_blocks =
5001 le64_to_cpu(response_data->TotalAllocationUnits);
5002 FSData->f_bfree = FSData->f_bavail =
5003 le64_to_cpu(response_data->FreeAllocationUnits);
5004 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5005 (unsigned long long)FSData->f_blocks,
5006 (unsigned long long)FSData->f_bfree,
5007 FSData->f_bsize);
5008 }
5009 }
5010 cifs_buf_release(pSMB);
5011
5012 if (rc == -EAGAIN)
5013 goto QFSInfoRetry;
5014
5015 return rc;
5016 }
5017
5018 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)5019 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5020 {
5021 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5022 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5023 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5024 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5025 int rc = 0;
5026 int bytes_returned = 0;
5027 __u16 params, byte_count;
5028
5029 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5030 QFSAttributeRetry:
5031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5032 (void **) &pSMBr);
5033 if (rc)
5034 return rc;
5035
5036 params = 2; /* level */
5037 pSMB->TotalDataCount = 0;
5038 pSMB->MaxParameterCount = cpu_to_le16(2);
5039 /* BB find exact max SMB PDU from sess structure BB */
5040 pSMB->MaxDataCount = cpu_to_le16(1000);
5041 pSMB->MaxSetupCount = 0;
5042 pSMB->Reserved = 0;
5043 pSMB->Flags = 0;
5044 pSMB->Timeout = 0;
5045 pSMB->Reserved2 = 0;
5046 byte_count = params + 1 /* pad */ ;
5047 pSMB->TotalParameterCount = cpu_to_le16(params);
5048 pSMB->ParameterCount = pSMB->TotalParameterCount;
5049 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5050 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5051 pSMB->DataCount = 0;
5052 pSMB->DataOffset = 0;
5053 pSMB->SetupCount = 1;
5054 pSMB->Reserved3 = 0;
5055 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5056 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5057 inc_rfc1001_len(pSMB, byte_count);
5058 pSMB->ByteCount = cpu_to_le16(byte_count);
5059
5060 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5061 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5062 if (rc) {
5063 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5064 } else { /* decode response */
5065 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5066
5067 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5068 /* BB also check if enough bytes returned */
5069 rc = -EIO; /* bad smb */
5070 } else {
5071 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5072 response_data =
5073 (FILE_SYSTEM_ATTRIBUTE_INFO
5074 *) (((char *) &pSMBr->hdr.Protocol) +
5075 data_offset);
5076 memcpy(&tcon->fsAttrInfo, response_data,
5077 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5078 }
5079 }
5080 cifs_buf_release(pSMB);
5081
5082 if (rc == -EAGAIN)
5083 goto QFSAttributeRetry;
5084
5085 return rc;
5086 }
5087
5088 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)5089 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5090 {
5091 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5092 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5093 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5094 FILE_SYSTEM_DEVICE_INFO *response_data;
5095 int rc = 0;
5096 int bytes_returned = 0;
5097 __u16 params, byte_count;
5098
5099 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5100 QFSDeviceRetry:
5101 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5102 (void **) &pSMBr);
5103 if (rc)
5104 return rc;
5105
5106 params = 2; /* level */
5107 pSMB->TotalDataCount = 0;
5108 pSMB->MaxParameterCount = cpu_to_le16(2);
5109 /* BB find exact max SMB PDU from sess structure BB */
5110 pSMB->MaxDataCount = cpu_to_le16(1000);
5111 pSMB->MaxSetupCount = 0;
5112 pSMB->Reserved = 0;
5113 pSMB->Flags = 0;
5114 pSMB->Timeout = 0;
5115 pSMB->Reserved2 = 0;
5116 byte_count = params + 1 /* pad */ ;
5117 pSMB->TotalParameterCount = cpu_to_le16(params);
5118 pSMB->ParameterCount = pSMB->TotalParameterCount;
5119 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5120 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5121
5122 pSMB->DataCount = 0;
5123 pSMB->DataOffset = 0;
5124 pSMB->SetupCount = 1;
5125 pSMB->Reserved3 = 0;
5126 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5127 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5128 inc_rfc1001_len(pSMB, byte_count);
5129 pSMB->ByteCount = cpu_to_le16(byte_count);
5130
5131 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5132 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5133 if (rc) {
5134 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5135 } else { /* decode response */
5136 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5137
5138 if (rc || get_bcc(&pSMBr->hdr) <
5139 sizeof(FILE_SYSTEM_DEVICE_INFO))
5140 rc = -EIO; /* bad smb */
5141 else {
5142 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5143 response_data =
5144 (FILE_SYSTEM_DEVICE_INFO *)
5145 (((char *) &pSMBr->hdr.Protocol) +
5146 data_offset);
5147 memcpy(&tcon->fsDevInfo, response_data,
5148 sizeof(FILE_SYSTEM_DEVICE_INFO));
5149 }
5150 }
5151 cifs_buf_release(pSMB);
5152
5153 if (rc == -EAGAIN)
5154 goto QFSDeviceRetry;
5155
5156 return rc;
5157 }
5158
5159 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)5160 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5161 {
5162 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5163 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5164 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5165 FILE_SYSTEM_UNIX_INFO *response_data;
5166 int rc = 0;
5167 int bytes_returned = 0;
5168 __u16 params, byte_count;
5169
5170 cifs_dbg(FYI, "In QFSUnixInfo\n");
5171 QFSUnixRetry:
5172 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5173 (void **) &pSMB, (void **) &pSMBr);
5174 if (rc)
5175 return rc;
5176
5177 params = 2; /* level */
5178 pSMB->TotalDataCount = 0;
5179 pSMB->DataCount = 0;
5180 pSMB->DataOffset = 0;
5181 pSMB->MaxParameterCount = cpu_to_le16(2);
5182 /* BB find exact max SMB PDU from sess structure BB */
5183 pSMB->MaxDataCount = cpu_to_le16(100);
5184 pSMB->MaxSetupCount = 0;
5185 pSMB->Reserved = 0;
5186 pSMB->Flags = 0;
5187 pSMB->Timeout = 0;
5188 pSMB->Reserved2 = 0;
5189 byte_count = params + 1 /* pad */ ;
5190 pSMB->ParameterCount = cpu_to_le16(params);
5191 pSMB->TotalParameterCount = pSMB->ParameterCount;
5192 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5193 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5194 pSMB->SetupCount = 1;
5195 pSMB->Reserved3 = 0;
5196 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5197 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5198 inc_rfc1001_len(pSMB, byte_count);
5199 pSMB->ByteCount = cpu_to_le16(byte_count);
5200
5201 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5202 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5203 if (rc) {
5204 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5205 } else { /* decode response */
5206 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5207
5208 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5209 rc = -EIO; /* bad smb */
5210 } else {
5211 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5212 response_data =
5213 (FILE_SYSTEM_UNIX_INFO
5214 *) (((char *) &pSMBr->hdr.Protocol) +
5215 data_offset);
5216 memcpy(&tcon->fsUnixInfo, response_data,
5217 sizeof(FILE_SYSTEM_UNIX_INFO));
5218 }
5219 }
5220 cifs_buf_release(pSMB);
5221
5222 if (rc == -EAGAIN)
5223 goto QFSUnixRetry;
5224
5225
5226 return rc;
5227 }
5228
5229 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)5230 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5231 {
5232 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5233 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5234 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5235 int rc = 0;
5236 int bytes_returned = 0;
5237 __u16 params, param_offset, offset, byte_count;
5238
5239 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5240 SETFSUnixRetry:
5241 /* BB switch to small buf init to save memory */
5242 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5243 (void **) &pSMB, (void **) &pSMBr);
5244 if (rc)
5245 return rc;
5246
5247 params = 4; /* 2 bytes zero followed by info level. */
5248 pSMB->MaxSetupCount = 0;
5249 pSMB->Reserved = 0;
5250 pSMB->Flags = 0;
5251 pSMB->Timeout = 0;
5252 pSMB->Reserved2 = 0;
5253 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5254 - 4;
5255 offset = param_offset + params;
5256
5257 pSMB->MaxParameterCount = cpu_to_le16(4);
5258 /* BB find exact max SMB PDU from sess structure BB */
5259 pSMB->MaxDataCount = cpu_to_le16(100);
5260 pSMB->SetupCount = 1;
5261 pSMB->Reserved3 = 0;
5262 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5263 byte_count = 1 /* pad */ + params + 12;
5264
5265 pSMB->DataCount = cpu_to_le16(12);
5266 pSMB->ParameterCount = cpu_to_le16(params);
5267 pSMB->TotalDataCount = pSMB->DataCount;
5268 pSMB->TotalParameterCount = pSMB->ParameterCount;
5269 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5270 pSMB->DataOffset = cpu_to_le16(offset);
5271
5272 /* Params. */
5273 pSMB->FileNum = 0;
5274 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5275
5276 /* Data. */
5277 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5278 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5279 pSMB->ClientUnixCap = cpu_to_le64(cap);
5280
5281 inc_rfc1001_len(pSMB, byte_count);
5282 pSMB->ByteCount = cpu_to_le16(byte_count);
5283
5284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5286 if (rc) {
5287 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5288 } else { /* decode response */
5289 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5290 if (rc)
5291 rc = -EIO; /* bad smb */
5292 }
5293 cifs_buf_release(pSMB);
5294
5295 if (rc == -EAGAIN)
5296 goto SETFSUnixRetry;
5297
5298 return rc;
5299 }
5300
5301
5302
5303 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5304 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5305 struct kstatfs *FSData)
5306 {
5307 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5308 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5309 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5310 FILE_SYSTEM_POSIX_INFO *response_data;
5311 int rc = 0;
5312 int bytes_returned = 0;
5313 __u16 params, byte_count;
5314
5315 cifs_dbg(FYI, "In QFSPosixInfo\n");
5316 QFSPosixRetry:
5317 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5318 (void **) &pSMBr);
5319 if (rc)
5320 return rc;
5321
5322 params = 2; /* level */
5323 pSMB->TotalDataCount = 0;
5324 pSMB->DataCount = 0;
5325 pSMB->DataOffset = 0;
5326 pSMB->MaxParameterCount = cpu_to_le16(2);
5327 /* BB find exact max SMB PDU from sess structure BB */
5328 pSMB->MaxDataCount = cpu_to_le16(100);
5329 pSMB->MaxSetupCount = 0;
5330 pSMB->Reserved = 0;
5331 pSMB->Flags = 0;
5332 pSMB->Timeout = 0;
5333 pSMB->Reserved2 = 0;
5334 byte_count = params + 1 /* pad */ ;
5335 pSMB->ParameterCount = cpu_to_le16(params);
5336 pSMB->TotalParameterCount = pSMB->ParameterCount;
5337 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5338 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5339 pSMB->SetupCount = 1;
5340 pSMB->Reserved3 = 0;
5341 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5342 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5343 inc_rfc1001_len(pSMB, byte_count);
5344 pSMB->ByteCount = cpu_to_le16(byte_count);
5345
5346 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5347 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5348 if (rc) {
5349 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5350 } else { /* decode response */
5351 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5352
5353 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5354 rc = -EIO; /* bad smb */
5355 } else {
5356 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5357 response_data =
5358 (FILE_SYSTEM_POSIX_INFO
5359 *) (((char *) &pSMBr->hdr.Protocol) +
5360 data_offset);
5361 FSData->f_bsize =
5362 le32_to_cpu(response_data->BlockSize);
5363 /*
5364 * much prefer larger but if server doesn't report
5365 * a valid size than 4K is a reasonable minimum
5366 */
5367 if (FSData->f_bsize < 512)
5368 FSData->f_bsize = 4096;
5369
5370 FSData->f_blocks =
5371 le64_to_cpu(response_data->TotalBlocks);
5372 FSData->f_bfree =
5373 le64_to_cpu(response_data->BlocksAvail);
5374 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5375 FSData->f_bavail = FSData->f_bfree;
5376 } else {
5377 FSData->f_bavail =
5378 le64_to_cpu(response_data->UserBlocksAvail);
5379 }
5380 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5381 FSData->f_files =
5382 le64_to_cpu(response_data->TotalFileNodes);
5383 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5384 FSData->f_ffree =
5385 le64_to_cpu(response_data->FreeFileNodes);
5386 }
5387 }
5388 cifs_buf_release(pSMB);
5389
5390 if (rc == -EAGAIN)
5391 goto QFSPosixRetry;
5392
5393 return rc;
5394 }
5395
5396
5397 /*
5398 * We can not use write of zero bytes trick to set file size due to need for
5399 * large file support. Also note that this SetPathInfo is preferred to
5400 * SetFileInfo based method in next routine which is only needed to work around
5401 * a sharing violation bugin Samba which this routine can run into.
5402 */
5403 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)5404 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5405 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5406 bool set_allocation)
5407 {
5408 struct smb_com_transaction2_spi_req *pSMB = NULL;
5409 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5410 struct file_end_of_file_info *parm_data;
5411 int name_len;
5412 int rc = 0;
5413 int bytes_returned = 0;
5414 int remap = cifs_remap(cifs_sb);
5415
5416 __u16 params, byte_count, data_count, param_offset, offset;
5417
5418 cifs_dbg(FYI, "In SetEOF\n");
5419 SetEOFRetry:
5420 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5421 (void **) &pSMBr);
5422 if (rc)
5423 return rc;
5424
5425 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5426 name_len =
5427 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5428 PATH_MAX, cifs_sb->local_nls, remap);
5429 name_len++; /* trailing null */
5430 name_len *= 2;
5431 } else {
5432 name_len = copy_path_name(pSMB->FileName, file_name);
5433 }
5434 params = 6 + name_len;
5435 data_count = sizeof(struct file_end_of_file_info);
5436 pSMB->MaxParameterCount = cpu_to_le16(2);
5437 pSMB->MaxDataCount = cpu_to_le16(4100);
5438 pSMB->MaxSetupCount = 0;
5439 pSMB->Reserved = 0;
5440 pSMB->Flags = 0;
5441 pSMB->Timeout = 0;
5442 pSMB->Reserved2 = 0;
5443 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5444 InformationLevel) - 4;
5445 offset = param_offset + params;
5446 if (set_allocation) {
5447 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5448 pSMB->InformationLevel =
5449 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5450 else
5451 pSMB->InformationLevel =
5452 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5453 } else /* Set File Size */ {
5454 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5455 pSMB->InformationLevel =
5456 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5457 else
5458 pSMB->InformationLevel =
5459 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5460 }
5461
5462 parm_data =
5463 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5464 offset);
5465 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5466 pSMB->DataOffset = cpu_to_le16(offset);
5467 pSMB->SetupCount = 1;
5468 pSMB->Reserved3 = 0;
5469 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5470 byte_count = 3 /* pad */ + params + data_count;
5471 pSMB->DataCount = cpu_to_le16(data_count);
5472 pSMB->TotalDataCount = pSMB->DataCount;
5473 pSMB->ParameterCount = cpu_to_le16(params);
5474 pSMB->TotalParameterCount = pSMB->ParameterCount;
5475 pSMB->Reserved4 = 0;
5476 inc_rfc1001_len(pSMB, byte_count);
5477 parm_data->FileSize = cpu_to_le64(size);
5478 pSMB->ByteCount = cpu_to_le16(byte_count);
5479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5481 if (rc)
5482 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5483
5484 cifs_buf_release(pSMB);
5485
5486 if (rc == -EAGAIN)
5487 goto SetEOFRetry;
5488
5489 return rc;
5490 }
5491
5492 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5493 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5494 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5495 {
5496 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5497 struct file_end_of_file_info *parm_data;
5498 int rc = 0;
5499 __u16 params, param_offset, offset, byte_count, count;
5500
5501 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5502 (long long)size);
5503 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5504
5505 if (rc)
5506 return rc;
5507
5508 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5509 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5510
5511 params = 6;
5512 pSMB->MaxSetupCount = 0;
5513 pSMB->Reserved = 0;
5514 pSMB->Flags = 0;
5515 pSMB->Timeout = 0;
5516 pSMB->Reserved2 = 0;
5517 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5518 offset = param_offset + params;
5519
5520 count = sizeof(struct file_end_of_file_info);
5521 pSMB->MaxParameterCount = cpu_to_le16(2);
5522 /* BB find exact max SMB PDU from sess structure BB */
5523 pSMB->MaxDataCount = cpu_to_le16(1000);
5524 pSMB->SetupCount = 1;
5525 pSMB->Reserved3 = 0;
5526 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5527 byte_count = 3 /* pad */ + params + count;
5528 pSMB->DataCount = cpu_to_le16(count);
5529 pSMB->ParameterCount = cpu_to_le16(params);
5530 pSMB->TotalDataCount = pSMB->DataCount;
5531 pSMB->TotalParameterCount = pSMB->ParameterCount;
5532 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5533 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5534 parm_data =
5535 (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
5536 pSMB->DataOffset = cpu_to_le16(offset);
5537 parm_data->FileSize = cpu_to_le64(size);
5538 pSMB->Fid = cfile->fid.netfid;
5539 if (set_allocation) {
5540 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5541 pSMB->InformationLevel =
5542 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5543 else
5544 pSMB->InformationLevel =
5545 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5546 } else /* Set File Size */ {
5547 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5548 pSMB->InformationLevel =
5549 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5550 else
5551 pSMB->InformationLevel =
5552 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5553 }
5554 pSMB->Reserved4 = 0;
5555 inc_rfc1001_len(pSMB, byte_count);
5556 pSMB->ByteCount = cpu_to_le16(byte_count);
5557 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5558 cifs_small_buf_release(pSMB);
5559 if (rc) {
5560 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5561 rc);
5562 }
5563
5564 /* Note: On -EAGAIN error only caller can retry on handle based calls
5565 since file handle passed in no longer valid */
5566
5567 return rc;
5568 }
5569
5570 /* Some legacy servers such as NT4 require that the file times be set on
5571 an open handle, rather than by pathname - this is awkward due to
5572 potential access conflicts on the open, but it is unavoidable for these
5573 old servers since the only other choice is to go from 100 nanosecond DCE
5574 time and resort to the original setpathinfo level which takes the ancient
5575 DOS time format with 2 second granularity */
5576 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5577 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5578 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5579 {
5580 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5581 char *data_offset;
5582 int rc = 0;
5583 __u16 params, param_offset, offset, byte_count, count;
5584
5585 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5586 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5587
5588 if (rc)
5589 return rc;
5590
5591 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5592 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5593
5594 params = 6;
5595 pSMB->MaxSetupCount = 0;
5596 pSMB->Reserved = 0;
5597 pSMB->Flags = 0;
5598 pSMB->Timeout = 0;
5599 pSMB->Reserved2 = 0;
5600 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5601 offset = param_offset + params;
5602
5603 data_offset = (char *)pSMB +
5604 offsetof(struct smb_hdr, Protocol) + offset;
5605
5606 count = sizeof(FILE_BASIC_INFO);
5607 pSMB->MaxParameterCount = cpu_to_le16(2);
5608 /* BB find max SMB PDU from sess */
5609 pSMB->MaxDataCount = cpu_to_le16(1000);
5610 pSMB->SetupCount = 1;
5611 pSMB->Reserved3 = 0;
5612 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5613 byte_count = 3 /* pad */ + params + count;
5614 pSMB->DataCount = cpu_to_le16(count);
5615 pSMB->ParameterCount = cpu_to_le16(params);
5616 pSMB->TotalDataCount = pSMB->DataCount;
5617 pSMB->TotalParameterCount = pSMB->ParameterCount;
5618 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5619 pSMB->DataOffset = cpu_to_le16(offset);
5620 pSMB->Fid = fid;
5621 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5622 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5623 else
5624 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5625 pSMB->Reserved4 = 0;
5626 inc_rfc1001_len(pSMB, byte_count);
5627 pSMB->ByteCount = cpu_to_le16(byte_count);
5628 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5629 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5630 cifs_small_buf_release(pSMB);
5631 if (rc)
5632 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5633 rc);
5634
5635 /* Note: On -EAGAIN error only caller can retry on handle based calls
5636 since file handle passed in no longer valid */
5637
5638 return rc;
5639 }
5640
5641 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5642 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5643 bool delete_file, __u16 fid, __u32 pid_of_opener)
5644 {
5645 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5646 char *data_offset;
5647 int rc = 0;
5648 __u16 params, param_offset, offset, byte_count, count;
5649
5650 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5651 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5652
5653 if (rc)
5654 return rc;
5655
5656 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5657 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5658
5659 params = 6;
5660 pSMB->MaxSetupCount = 0;
5661 pSMB->Reserved = 0;
5662 pSMB->Flags = 0;
5663 pSMB->Timeout = 0;
5664 pSMB->Reserved2 = 0;
5665 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5666 offset = param_offset + params;
5667
5668 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5669 data_offset = (char *)(pSMB) + offset + 4;
5670
5671 count = 1;
5672 pSMB->MaxParameterCount = cpu_to_le16(2);
5673 /* BB find max SMB PDU from sess */
5674 pSMB->MaxDataCount = cpu_to_le16(1000);
5675 pSMB->SetupCount = 1;
5676 pSMB->Reserved3 = 0;
5677 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5678 byte_count = 3 /* pad */ + params + count;
5679 pSMB->DataCount = cpu_to_le16(count);
5680 pSMB->ParameterCount = cpu_to_le16(params);
5681 pSMB->TotalDataCount = pSMB->DataCount;
5682 pSMB->TotalParameterCount = pSMB->ParameterCount;
5683 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5684 pSMB->DataOffset = cpu_to_le16(offset);
5685 pSMB->Fid = fid;
5686 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5687 pSMB->Reserved4 = 0;
5688 inc_rfc1001_len(pSMB, byte_count);
5689 pSMB->ByteCount = cpu_to_le16(byte_count);
5690 *data_offset = delete_file ? 1 : 0;
5691 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5692 cifs_small_buf_release(pSMB);
5693 if (rc)
5694 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5695
5696 return rc;
5697 }
5698
5699 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)5700 CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5701 const char *fileName, const FILE_BASIC_INFO *data,
5702 const struct nls_table *nls_codepage,
5703 struct cifs_sb_info *cifs_sb)
5704 {
5705 int oplock = 0;
5706 struct cifs_open_parms oparms;
5707 struct cifs_fid fid;
5708 int rc;
5709
5710 oparms.tcon = tcon;
5711 oparms.cifs_sb = cifs_sb;
5712 oparms.desired_access = GENERIC_WRITE;
5713 oparms.create_options = cifs_create_options(cifs_sb, 0);
5714 oparms.disposition = FILE_OPEN;
5715 oparms.path = fileName;
5716 oparms.fid = &fid;
5717 oparms.reconnect = false;
5718
5719 rc = CIFS_open(xid, &oparms, &oplock, NULL);
5720 if (rc)
5721 goto out;
5722
5723 rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5724 CIFSSMBClose(xid, tcon, fid.netfid);
5725 out:
5726
5727 return rc;
5728 }
5729
5730 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)5731 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5732 const char *fileName, const FILE_BASIC_INFO *data,
5733 const struct nls_table *nls_codepage,
5734 struct cifs_sb_info *cifs_sb)
5735 {
5736 TRANSACTION2_SPI_REQ *pSMB = NULL;
5737 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5738 int name_len;
5739 int rc = 0;
5740 int bytes_returned = 0;
5741 char *data_offset;
5742 __u16 params, param_offset, offset, byte_count, count;
5743 int remap = cifs_remap(cifs_sb);
5744
5745 cifs_dbg(FYI, "In SetTimes\n");
5746
5747 SetTimesRetry:
5748 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5749 (void **) &pSMBr);
5750 if (rc)
5751 return rc;
5752
5753 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5754 name_len =
5755 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5756 PATH_MAX, nls_codepage, remap);
5757 name_len++; /* trailing null */
5758 name_len *= 2;
5759 } else {
5760 name_len = copy_path_name(pSMB->FileName, fileName);
5761 }
5762
5763 params = 6 + name_len;
5764 count = sizeof(FILE_BASIC_INFO);
5765 pSMB->MaxParameterCount = cpu_to_le16(2);
5766 /* BB find max SMB PDU from sess structure BB */
5767 pSMB->MaxDataCount = cpu_to_le16(1000);
5768 pSMB->MaxSetupCount = 0;
5769 pSMB->Reserved = 0;
5770 pSMB->Flags = 0;
5771 pSMB->Timeout = 0;
5772 pSMB->Reserved2 = 0;
5773 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5774 InformationLevel) - 4;
5775 offset = param_offset + params;
5776 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5777 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5778 pSMB->DataOffset = cpu_to_le16(offset);
5779 pSMB->SetupCount = 1;
5780 pSMB->Reserved3 = 0;
5781 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5782 byte_count = 3 /* pad */ + params + count;
5783
5784 pSMB->DataCount = cpu_to_le16(count);
5785 pSMB->ParameterCount = cpu_to_le16(params);
5786 pSMB->TotalDataCount = pSMB->DataCount;
5787 pSMB->TotalParameterCount = pSMB->ParameterCount;
5788 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5789 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5790 else
5791 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5792 pSMB->Reserved4 = 0;
5793 inc_rfc1001_len(pSMB, byte_count);
5794 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5795 pSMB->ByteCount = cpu_to_le16(byte_count);
5796 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5797 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5798 if (rc)
5799 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5800
5801 cifs_buf_release(pSMB);
5802
5803 if (rc == -EAGAIN)
5804 goto SetTimesRetry;
5805
5806 if (rc == -EOPNOTSUPP)
5807 return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5808 nls_codepage, cifs_sb);
5809
5810 return rc;
5811 }
5812
5813 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5814 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5815 const struct cifs_unix_set_info_args *args)
5816 {
5817 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5818 u64 mode = args->mode;
5819
5820 if (uid_valid(args->uid))
5821 uid = from_kuid(&init_user_ns, args->uid);
5822 if (gid_valid(args->gid))
5823 gid = from_kgid(&init_user_ns, args->gid);
5824
5825 /*
5826 * Samba server ignores set of file size to zero due to bugs in some
5827 * older clients, but we should be precise - we use SetFileSize to
5828 * set file size and do not want to truncate file size to zero
5829 * accidentally as happened on one Samba server beta by putting
5830 * zero instead of -1 here
5831 */
5832 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5833 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5834 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5835 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5836 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5837 data_offset->Uid = cpu_to_le64(uid);
5838 data_offset->Gid = cpu_to_le64(gid);
5839 /* better to leave device as zero when it is */
5840 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5841 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5842 data_offset->Permissions = cpu_to_le64(mode);
5843
5844 if (S_ISREG(mode))
5845 data_offset->Type = cpu_to_le32(UNIX_FILE);
5846 else if (S_ISDIR(mode))
5847 data_offset->Type = cpu_to_le32(UNIX_DIR);
5848 else if (S_ISLNK(mode))
5849 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5850 else if (S_ISCHR(mode))
5851 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5852 else if (S_ISBLK(mode))
5853 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5854 else if (S_ISFIFO(mode))
5855 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5856 else if (S_ISSOCK(mode))
5857 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5858 }
5859
5860 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)5861 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5862 const struct cifs_unix_set_info_args *args,
5863 u16 fid, u32 pid_of_opener)
5864 {
5865 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5866 char *data_offset;
5867 int rc = 0;
5868 u16 params, param_offset, offset, byte_count, count;
5869
5870 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5871 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5872
5873 if (rc)
5874 return rc;
5875
5876 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5877 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5878
5879 params = 6;
5880 pSMB->MaxSetupCount = 0;
5881 pSMB->Reserved = 0;
5882 pSMB->Flags = 0;
5883 pSMB->Timeout = 0;
5884 pSMB->Reserved2 = 0;
5885 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5886 offset = param_offset + params;
5887
5888 data_offset = (char *)pSMB +
5889 offsetof(struct smb_hdr, Protocol) + offset;
5890
5891 count = sizeof(FILE_UNIX_BASIC_INFO);
5892
5893 pSMB->MaxParameterCount = cpu_to_le16(2);
5894 /* BB find max SMB PDU from sess */
5895 pSMB->MaxDataCount = cpu_to_le16(1000);
5896 pSMB->SetupCount = 1;
5897 pSMB->Reserved3 = 0;
5898 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5899 byte_count = 3 /* pad */ + params + count;
5900 pSMB->DataCount = cpu_to_le16(count);
5901 pSMB->ParameterCount = cpu_to_le16(params);
5902 pSMB->TotalDataCount = pSMB->DataCount;
5903 pSMB->TotalParameterCount = pSMB->ParameterCount;
5904 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5905 pSMB->DataOffset = cpu_to_le16(offset);
5906 pSMB->Fid = fid;
5907 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5908 pSMB->Reserved4 = 0;
5909 inc_rfc1001_len(pSMB, byte_count);
5910 pSMB->ByteCount = cpu_to_le16(byte_count);
5911
5912 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5913
5914 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5915 cifs_small_buf_release(pSMB);
5916 if (rc)
5917 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5918 rc);
5919
5920 /* Note: On -EAGAIN error only caller can retry on handle based calls
5921 since file handle passed in no longer valid */
5922
5923 return rc;
5924 }
5925
5926 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)5927 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5928 const char *file_name,
5929 const struct cifs_unix_set_info_args *args,
5930 const struct nls_table *nls_codepage, int remap)
5931 {
5932 TRANSACTION2_SPI_REQ *pSMB = NULL;
5933 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5934 int name_len;
5935 int rc = 0;
5936 int bytes_returned = 0;
5937 FILE_UNIX_BASIC_INFO *data_offset;
5938 __u16 params, param_offset, offset, count, byte_count;
5939
5940 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
5941 setPermsRetry:
5942 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5943 (void **) &pSMBr);
5944 if (rc)
5945 return rc;
5946
5947 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5948 name_len =
5949 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5950 PATH_MAX, nls_codepage, remap);
5951 name_len++; /* trailing null */
5952 name_len *= 2;
5953 } else {
5954 name_len = copy_path_name(pSMB->FileName, file_name);
5955 }
5956
5957 params = 6 + name_len;
5958 count = sizeof(FILE_UNIX_BASIC_INFO);
5959 pSMB->MaxParameterCount = cpu_to_le16(2);
5960 /* BB find max SMB PDU from sess structure BB */
5961 pSMB->MaxDataCount = cpu_to_le16(1000);
5962 pSMB->MaxSetupCount = 0;
5963 pSMB->Reserved = 0;
5964 pSMB->Flags = 0;
5965 pSMB->Timeout = 0;
5966 pSMB->Reserved2 = 0;
5967 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5968 InformationLevel) - 4;
5969 offset = param_offset + params;
5970 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5971 data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
5972 memset(data_offset, 0, count);
5973 pSMB->DataOffset = cpu_to_le16(offset);
5974 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5975 pSMB->SetupCount = 1;
5976 pSMB->Reserved3 = 0;
5977 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5978 byte_count = 3 /* pad */ + params + count;
5979 pSMB->ParameterCount = cpu_to_le16(params);
5980 pSMB->DataCount = cpu_to_le16(count);
5981 pSMB->TotalParameterCount = pSMB->ParameterCount;
5982 pSMB->TotalDataCount = pSMB->DataCount;
5983 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5984 pSMB->Reserved4 = 0;
5985 inc_rfc1001_len(pSMB, byte_count);
5986
5987 cifs_fill_unix_set_info(data_offset, args);
5988
5989 pSMB->ByteCount = cpu_to_le16(byte_count);
5990 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5991 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5992 if (rc)
5993 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
5994
5995 cifs_buf_release(pSMB);
5996 if (rc == -EAGAIN)
5997 goto setPermsRetry;
5998 return rc;
5999 }
6000
6001 #ifdef CONFIG_CIFS_XATTR
6002 /*
6003 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6004 * function used by listxattr and getxattr type calls. When ea_name is set,
6005 * it looks for that attribute name and stuffs that value into the EAData
6006 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6007 * buffer. In both cases, the return value is either the length of the
6008 * resulting data or a negative error code. If EAData is a NULL pointer then
6009 * the data isn't copied to it, but the length is returned.
6010 */
6011 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)6012 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6013 const unsigned char *searchName, const unsigned char *ea_name,
6014 char *EAData, size_t buf_size,
6015 struct cifs_sb_info *cifs_sb)
6016 {
6017 /* BB assumes one setup word */
6018 TRANSACTION2_QPI_REQ *pSMB = NULL;
6019 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6020 int remap = cifs_remap(cifs_sb);
6021 struct nls_table *nls_codepage = cifs_sb->local_nls;
6022 int rc = 0;
6023 int bytes_returned;
6024 int list_len;
6025 struct fealist *ea_response_data;
6026 struct fea *temp_fea;
6027 char *temp_ptr;
6028 char *end_of_smb;
6029 __u16 params, byte_count, data_offset;
6030 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6031
6032 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6033 QAllEAsRetry:
6034 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6035 (void **) &pSMBr);
6036 if (rc)
6037 return rc;
6038
6039 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6040 list_len =
6041 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6042 PATH_MAX, nls_codepage, remap);
6043 list_len++; /* trailing null */
6044 list_len *= 2;
6045 } else {
6046 list_len = copy_path_name(pSMB->FileName, searchName);
6047 }
6048
6049 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6050 pSMB->TotalDataCount = 0;
6051 pSMB->MaxParameterCount = cpu_to_le16(2);
6052 /* BB find exact max SMB PDU from sess structure BB */
6053 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6054 pSMB->MaxSetupCount = 0;
6055 pSMB->Reserved = 0;
6056 pSMB->Flags = 0;
6057 pSMB->Timeout = 0;
6058 pSMB->Reserved2 = 0;
6059 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6060 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6061 pSMB->DataCount = 0;
6062 pSMB->DataOffset = 0;
6063 pSMB->SetupCount = 1;
6064 pSMB->Reserved3 = 0;
6065 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6066 byte_count = params + 1 /* pad */ ;
6067 pSMB->TotalParameterCount = cpu_to_le16(params);
6068 pSMB->ParameterCount = pSMB->TotalParameterCount;
6069 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6070 pSMB->Reserved4 = 0;
6071 inc_rfc1001_len(pSMB, byte_count);
6072 pSMB->ByteCount = cpu_to_le16(byte_count);
6073
6074 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6075 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6076 if (rc) {
6077 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6078 goto QAllEAsOut;
6079 }
6080
6081
6082 /* BB also check enough total bytes returned */
6083 /* BB we need to improve the validity checking
6084 of these trans2 responses */
6085
6086 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6087 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6088 rc = -EIO; /* bad smb */
6089 goto QAllEAsOut;
6090 }
6091
6092 /* check that length of list is not more than bcc */
6093 /* check that each entry does not go beyond length
6094 of list */
6095 /* check that each element of each entry does not
6096 go beyond end of list */
6097 /* validate_trans2_offsets() */
6098 /* BB check if start of smb + data_offset > &bcc+ bcc */
6099
6100 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6101 ea_response_data = (struct fealist *)
6102 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6103
6104 list_len = le32_to_cpu(ea_response_data->list_len);
6105 cifs_dbg(FYI, "ea length %d\n", list_len);
6106 if (list_len <= 8) {
6107 cifs_dbg(FYI, "empty EA list returned from server\n");
6108 /* didn't find the named attribute */
6109 if (ea_name)
6110 rc = -ENODATA;
6111 goto QAllEAsOut;
6112 }
6113
6114 /* make sure list_len doesn't go past end of SMB */
6115 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6116 if ((char *)ea_response_data + list_len > end_of_smb) {
6117 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6118 rc = -EIO;
6119 goto QAllEAsOut;
6120 }
6121
6122 /* account for ea list len */
6123 list_len -= 4;
6124 temp_fea = ea_response_data->list;
6125 temp_ptr = (char *)temp_fea;
6126 while (list_len > 0) {
6127 unsigned int name_len;
6128 __u16 value_len;
6129
6130 list_len -= 4;
6131 temp_ptr += 4;
6132 /* make sure we can read name_len and value_len */
6133 if (list_len < 0) {
6134 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6135 rc = -EIO;
6136 goto QAllEAsOut;
6137 }
6138
6139 name_len = temp_fea->name_len;
6140 value_len = le16_to_cpu(temp_fea->value_len);
6141 list_len -= name_len + 1 + value_len;
6142 if (list_len < 0) {
6143 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6144 rc = -EIO;
6145 goto QAllEAsOut;
6146 }
6147
6148 if (ea_name) {
6149 if (ea_name_len == name_len &&
6150 memcmp(ea_name, temp_ptr, name_len) == 0) {
6151 temp_ptr += name_len + 1;
6152 rc = value_len;
6153 if (buf_size == 0)
6154 goto QAllEAsOut;
6155 if ((size_t)value_len > buf_size) {
6156 rc = -ERANGE;
6157 goto QAllEAsOut;
6158 }
6159 memcpy(EAData, temp_ptr, value_len);
6160 goto QAllEAsOut;
6161 }
6162 } else {
6163 /* account for prefix user. and trailing null */
6164 rc += (5 + 1 + name_len);
6165 if (rc < (int) buf_size) {
6166 memcpy(EAData, "user.", 5);
6167 EAData += 5;
6168 memcpy(EAData, temp_ptr, name_len);
6169 EAData += name_len;
6170 /* null terminate name */
6171 *EAData = 0;
6172 ++EAData;
6173 } else if (buf_size == 0) {
6174 /* skip copy - calc size only */
6175 } else {
6176 /* stop before overrun buffer */
6177 rc = -ERANGE;
6178 break;
6179 }
6180 }
6181 temp_ptr += name_len + 1 + value_len;
6182 temp_fea = (struct fea *)temp_ptr;
6183 }
6184
6185 /* didn't find the named attribute */
6186 if (ea_name)
6187 rc = -ENODATA;
6188
6189 QAllEAsOut:
6190 cifs_buf_release(pSMB);
6191 if (rc == -EAGAIN)
6192 goto QAllEAsRetry;
6193
6194 return (ssize_t)rc;
6195 }
6196
6197 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)6198 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6199 const char *fileName, const char *ea_name, const void *ea_value,
6200 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6201 struct cifs_sb_info *cifs_sb)
6202 {
6203 struct smb_com_transaction2_spi_req *pSMB = NULL;
6204 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6205 struct fealist *parm_data;
6206 int name_len;
6207 int rc = 0;
6208 int bytes_returned = 0;
6209 __u16 params, param_offset, byte_count, offset, count;
6210 int remap = cifs_remap(cifs_sb);
6211
6212 cifs_dbg(FYI, "In SetEA\n");
6213 SetEARetry:
6214 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6215 (void **) &pSMBr);
6216 if (rc)
6217 return rc;
6218
6219 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6220 name_len =
6221 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6222 PATH_MAX, nls_codepage, remap);
6223 name_len++; /* trailing null */
6224 name_len *= 2;
6225 } else {
6226 name_len = copy_path_name(pSMB->FileName, fileName);
6227 }
6228
6229 params = 6 + name_len;
6230
6231 /* done calculating parms using name_len of file name,
6232 now use name_len to calculate length of ea name
6233 we are going to create in the inode xattrs */
6234 if (ea_name == NULL)
6235 name_len = 0;
6236 else
6237 name_len = strnlen(ea_name, 255);
6238
6239 count = sizeof(*parm_data) + ea_value_len + name_len;
6240 pSMB->MaxParameterCount = cpu_to_le16(2);
6241 /* BB find max SMB PDU from sess */
6242 pSMB->MaxDataCount = cpu_to_le16(1000);
6243 pSMB->MaxSetupCount = 0;
6244 pSMB->Reserved = 0;
6245 pSMB->Flags = 0;
6246 pSMB->Timeout = 0;
6247 pSMB->Reserved2 = 0;
6248 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6249 InformationLevel) - 4;
6250 offset = param_offset + params;
6251 pSMB->InformationLevel =
6252 cpu_to_le16(SMB_SET_FILE_EA);
6253
6254 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6255 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6256 pSMB->DataOffset = cpu_to_le16(offset);
6257 pSMB->SetupCount = 1;
6258 pSMB->Reserved3 = 0;
6259 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6260 byte_count = 3 /* pad */ + params + count;
6261 pSMB->DataCount = cpu_to_le16(count);
6262 parm_data->list_len = cpu_to_le32(count);
6263 parm_data->list[0].EA_flags = 0;
6264 /* we checked above that name len is less than 255 */
6265 parm_data->list[0].name_len = (__u8)name_len;
6266 /* EA names are always ASCII */
6267 if (ea_name)
6268 strncpy(parm_data->list[0].name, ea_name, name_len);
6269 parm_data->list[0].name[name_len] = 0;
6270 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6271 /* caller ensures that ea_value_len is less than 64K but
6272 we need to ensure that it fits within the smb */
6273
6274 /*BB add length check to see if it would fit in
6275 negotiated SMB buffer size BB */
6276 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6277 if (ea_value_len)
6278 memcpy(parm_data->list[0].name+name_len+1,
6279 ea_value, ea_value_len);
6280
6281 pSMB->TotalDataCount = pSMB->DataCount;
6282 pSMB->ParameterCount = cpu_to_le16(params);
6283 pSMB->TotalParameterCount = pSMB->ParameterCount;
6284 pSMB->Reserved4 = 0;
6285 inc_rfc1001_len(pSMB, byte_count);
6286 pSMB->ByteCount = cpu_to_le16(byte_count);
6287 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6288 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6289 if (rc)
6290 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6291
6292 cifs_buf_release(pSMB);
6293
6294 if (rc == -EAGAIN)
6295 goto SetEARetry;
6296
6297 return rc;
6298 }
6299 #endif
6300