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