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