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