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