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