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