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