4 * Copyright (C) International Business Machines Corp., 2002,2010
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
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.
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.
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
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 */
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 <asm/uaccess.h>
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
47 #ifdef CONFIG_CIFS_POSIX
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"},
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"},
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
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
91 * On arches that have high memory, kmap address space is limited. By
92 * serializing the kmap operations on those arches, we ensure that we don't
93 * end up with a bunch of threads in writeback with partially mapped page
94 * arrays, stuck waiting for kmap to come back. That situation prevents
95 * progress and can deadlock.
97 static DEFINE_MUTEX(cifs_kmap_mutex);
102 mutex_lock(&cifs_kmap_mutex);
106 cifs_kmap_unlock(void)
108 mutex_unlock(&cifs_kmap_mutex);
110 #else /* !CONFIG_HIGHMEM */
111 #define cifs_kmap_lock() do { ; } while(0)
112 #define cifs_kmap_unlock() do { ; } while(0)
113 #endif /* CONFIG_HIGHMEM */
116 * Mark as invalid, all open files on tree connections since they
117 * were closed when session to server was lost.
120 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
122 struct cifsFileInfo *open_file = NULL;
123 struct list_head *tmp;
124 struct list_head *tmp1;
126 /* list all files open on tree connection and mark them invalid */
127 spin_lock(&cifs_file_list_lock);
128 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
129 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
130 open_file->invalidHandle = true;
131 open_file->oplock_break_cancelled = true;
133 spin_unlock(&cifs_file_list_lock);
135 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
140 /* reconnect the socket, tcon, and smb session if needed */
142 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
145 struct cifs_ses *ses;
146 struct TCP_Server_Info *server;
147 struct nls_table *nls_codepage;
150 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
151 * tcp and smb session status done differently for those three - in the
158 server = ses->server;
161 * only tree disconnect, open, and write, (and ulogoff which does not
162 * have tcon) are allowed as we start force umount
164 if (tcon->tidStatus == CifsExiting) {
165 if (smb_command != SMB_COM_WRITE_ANDX &&
166 smb_command != SMB_COM_OPEN_ANDX &&
167 smb_command != SMB_COM_TREE_DISCONNECT) {
168 cFYI(1, "can not send cmd %d while umounting",
175 * Give demultiplex thread up to 10 seconds to reconnect, should be
176 * greater than cifs socket timeout which is 7 seconds
178 while (server->tcpStatus == CifsNeedReconnect) {
179 wait_event_interruptible_timeout(server->response_q,
180 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
182 /* are we still trying to reconnect? */
183 if (server->tcpStatus != CifsNeedReconnect)
187 * on "soft" mounts we wait once. Hard mounts keep
188 * retrying until process is killed or server comes
192 cFYI(1, "gave up waiting on reconnect in smb_init");
197 if (!ses->need_reconnect && !tcon->need_reconnect)
200 nls_codepage = load_nls_default();
203 * need to prevent multiple threads trying to simultaneously
204 * reconnect the same SMB session
206 mutex_lock(&ses->session_mutex);
207 rc = cifs_negotiate_protocol(0, ses);
208 if (rc == 0 && ses->need_reconnect)
209 rc = cifs_setup_session(0, ses, nls_codepage);
211 /* do we need to reconnect tcon? */
212 if (rc || !tcon->need_reconnect) {
213 mutex_unlock(&ses->session_mutex);
217 cifs_mark_open_files_invalid(tcon);
218 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
219 mutex_unlock(&ses->session_mutex);
220 cFYI(1, "reconnect tcon rc = %d", rc);
226 * FIXME: check if wsize needs updated due to negotiated smb buffer
229 atomic_inc(&tconInfoReconnectCount);
231 /* tell server Unix caps we support */
232 if (ses->capabilities & CAP_UNIX)
233 reset_cifs_unix_caps(0, tcon, NULL, NULL);
236 * Removed call to reopen open files here. It is safer (and faster) to
237 * reopen files one at a time as needed in read and write.
239 * FIXME: what about file locks? don't we need to reclaim them ASAP?
244 * Check if handle based operation so we know whether we can continue
245 * or not without returning to caller to reset file handle
247 switch (smb_command) {
248 case SMB_COM_READ_ANDX:
249 case SMB_COM_WRITE_ANDX:
251 case SMB_COM_FIND_CLOSE2:
252 case SMB_COM_LOCKING_ANDX:
256 unload_nls(nls_codepage);
260 /* Allocate and return pointer to an SMB request buffer, and set basic
261 SMB information in the SMB header. If the return code is zero, this
262 function must have filled in request_buf pointer */
264 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
269 rc = cifs_reconnect_tcon(tcon, smb_command);
273 *request_buf = cifs_small_buf_get();
274 if (*request_buf == NULL) {
275 /* BB should we add a retry in here if not a writepage? */
279 header_assemble((struct smb_hdr *) *request_buf, smb_command,
283 cifs_stats_inc(&tcon->num_smbs_sent);
289 small_smb_init_no_tc(const int smb_command, const int wct,
290 struct cifs_ses *ses, void **request_buf)
293 struct smb_hdr *buffer;
295 rc = small_smb_init(smb_command, wct, NULL, request_buf);
299 buffer = (struct smb_hdr *)*request_buf;
300 buffer->Mid = get_next_mid(ses->server);
301 if (ses->capabilities & CAP_UNICODE)
302 buffer->Flags2 |= SMBFLG2_UNICODE;
303 if (ses->capabilities & CAP_STATUS32)
304 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
306 /* uid, tid can stay at zero as set in header assemble */
308 /* BB add support for turning on the signing when
309 this function is used after 1st of session setup requests */
314 /* If the return code is zero, this function must fill in request_buf pointer */
316 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
317 void **request_buf, void **response_buf)
319 *request_buf = cifs_buf_get();
320 if (*request_buf == NULL) {
321 /* BB should we add a retry in here if not a writepage? */
324 /* Although the original thought was we needed the response buf for */
325 /* potential retries of smb operations it turns out we can determine */
326 /* from the mid flags when the request buffer can be resent without */
327 /* having to use a second distinct buffer for the response */
329 *response_buf = *request_buf;
331 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
335 cifs_stats_inc(&tcon->num_smbs_sent);
340 /* If the return code is zero, this function must fill in request_buf pointer */
342 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
343 void **request_buf, void **response_buf)
347 rc = cifs_reconnect_tcon(tcon, smb_command);
351 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
355 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
356 void **request_buf, void **response_buf)
358 if (tcon->ses->need_reconnect || tcon->need_reconnect)
361 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
364 static int validate_t2(struct smb_t2_rsp *pSMB)
366 unsigned int total_size;
368 /* check for plausible wct */
369 if (pSMB->hdr.WordCount < 10)
372 /* check for parm and data offset going beyond end of smb */
373 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
374 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
377 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
378 if (total_size >= 512)
381 /* check that bcc is at least as big as parms + data, and that it is
382 * less than negotiated smb buffer
384 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
385 if (total_size > get_bcc(&pSMB->hdr) ||
386 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
391 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
392 sizeof(struct smb_t2_rsp) + 16);
397 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
400 NEGOTIATE_RSP *pSMBr;
404 struct TCP_Server_Info *server;
406 unsigned int secFlags;
409 server = ses->server;
414 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
415 (void **) &pSMB, (void **) &pSMBr);
419 /* if any of auth flags (ie not sign or seal) are overriden use them */
420 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
421 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
422 else /* if override flags set only sign/seal OR them with global auth */
423 secFlags = global_secflags | ses->overrideSecFlg;
425 cFYI(1, "secFlags 0x%x", secFlags);
427 pSMB->hdr.Mid = get_next_mid(server);
428 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
430 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
431 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
432 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
433 cFYI(1, "Kerberos only mechanism, enable extended security");
434 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
435 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
436 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
437 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
438 cFYI(1, "NTLMSSP only mechanism, enable extended security");
439 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
443 for (i = 0; i < CIFS_NUM_PROT; i++) {
444 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
445 count += strlen(protocols[i].name) + 1;
446 /* null at end of source and target buffers anyway */
448 inc_rfc1001_len(pSMB, count);
449 pSMB->ByteCount = cpu_to_le16(count);
451 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
452 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
456 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
457 cFYI(1, "Dialect: %d", server->dialect);
458 /* Check wct = 1 error case */
459 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
460 /* core returns wct = 1, but we do not ask for core - otherwise
461 small wct just comes when dialect index is -1 indicating we
462 could not negotiate a common dialect */
465 #ifdef CONFIG_CIFS_WEAK_PW_HASH
466 } else if ((pSMBr->hdr.WordCount == 13)
467 && ((server->dialect == LANMAN_PROT)
468 || (server->dialect == LANMAN2_PROT))) {
470 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
472 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
473 (secFlags & CIFSSEC_MAY_PLNTXT))
474 server->secType = LANMAN;
476 cERROR(1, "mount failed weak security disabled"
477 " in /proc/fs/cifs/SecurityFlags");
481 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
482 server->maxReq = min_t(unsigned int,
483 le16_to_cpu(rsp->MaxMpxCount),
485 set_credits(server, server->maxReq);
486 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
487 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
488 /* even though we do not use raw we might as well set this
489 accurately, in case we ever find a need for it */
490 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
491 server->max_rw = 0xFF00;
492 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
494 server->max_rw = 0;/* do not need to use raw anyway */
495 server->capabilities = CAP_MPX_MODE;
497 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
499 /* OS/2 often does not set timezone therefore
500 * we must use server time to calc time zone.
501 * Could deviate slightly from the right zone.
502 * Smallest defined timezone difference is 15 minutes
503 * (i.e. Nepal). Rounding up/down is done to match
506 int val, seconds, remain, result;
507 struct timespec ts, utc;
509 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
510 rsp->SrvTime.Time, 0);
511 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
512 (int)ts.tv_sec, (int)utc.tv_sec,
513 (int)(utc.tv_sec - ts.tv_sec));
514 val = (int)(utc.tv_sec - ts.tv_sec);
516 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
517 remain = seconds % MIN_TZ_ADJ;
518 if (remain >= (MIN_TZ_ADJ / 2))
519 result += MIN_TZ_ADJ;
522 server->timeAdj = result;
524 server->timeAdj = (int)tmp;
525 server->timeAdj *= 60; /* also in seconds */
527 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
530 /* BB get server time for time conversions and add
531 code to use it and timezone since this is not UTC */
533 if (rsp->EncryptionKeyLength ==
534 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
535 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
536 CIFS_CRYPTO_KEY_SIZE);
537 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
538 rc = -EIO; /* need cryptkey unless plain text */
542 cFYI(1, "LANMAN negotiated");
543 /* we will not end up setting signing flags - as no signing
544 was in LANMAN and server did not return the flags on */
546 #else /* weak security disabled */
547 } else if (pSMBr->hdr.WordCount == 13) {
548 cERROR(1, "mount failed, cifs module not built "
549 "with CIFS_WEAK_PW_HASH support");
551 #endif /* WEAK_PW_HASH */
553 } else if (pSMBr->hdr.WordCount != 17) {
558 /* else wct == 17 NTLM */
559 server->sec_mode = pSMBr->SecurityMode;
560 if ((server->sec_mode & SECMODE_USER) == 0)
561 cFYI(1, "share mode security");
563 if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
564 #ifdef CONFIG_CIFS_WEAK_PW_HASH
565 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
566 #endif /* CIFS_WEAK_PW_HASH */
567 cERROR(1, "Server requests plain text password"
568 " but client support disabled");
570 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
571 server->secType = NTLMv2;
572 else if (secFlags & CIFSSEC_MAY_NTLM)
573 server->secType = NTLM;
574 else if (secFlags & CIFSSEC_MAY_NTLMV2)
575 server->secType = NTLMv2;
576 else if (secFlags & CIFSSEC_MAY_KRB5)
577 server->secType = Kerberos;
578 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
579 server->secType = RawNTLMSSP;
580 else if (secFlags & CIFSSEC_MAY_LANMAN)
581 server->secType = LANMAN;
584 cERROR(1, "Invalid security type");
587 /* else ... any others ...? */
589 /* one byte, so no need to convert this or EncryptionKeyLen from
591 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
593 set_credits(server, server->maxReq);
594 /* probably no need to store and check maxvcs */
595 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
596 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
597 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
598 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
599 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
600 server->timeAdj *= 60;
601 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
602 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
603 CIFS_CRYPTO_KEY_SIZE);
604 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
605 server->capabilities & CAP_EXTENDED_SECURITY) &&
606 (pSMBr->EncryptionKeyLength == 0)) {
607 /* decode security blob */
608 count = get_bcc(&pSMBr->hdr);
613 spin_lock(&cifs_tcp_ses_lock);
614 if (server->srv_count > 1) {
615 spin_unlock(&cifs_tcp_ses_lock);
616 if (memcmp(server->server_GUID,
617 pSMBr->u.extended_response.
619 cFYI(1, "server UID changed");
620 memcpy(server->server_GUID,
621 pSMBr->u.extended_response.GUID,
625 spin_unlock(&cifs_tcp_ses_lock);
626 memcpy(server->server_GUID,
627 pSMBr->u.extended_response.GUID, 16);
631 server->secType = RawNTLMSSP;
633 rc = decode_negTokenInit(pSMBr->u.extended_response.
634 SecurityBlob, count - 16,
640 if (server->secType == Kerberos) {
641 if (!server->sec_kerberos &&
642 !server->sec_mskerberos)
644 } else if (server->secType == RawNTLMSSP) {
645 if (!server->sec_ntlmssp)
650 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
651 rc = -EIO; /* no crypt key only if plain text pwd */
654 server->capabilities &= ~CAP_EXTENDED_SECURITY;
656 #ifdef CONFIG_CIFS_WEAK_PW_HASH
659 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
660 /* MUST_SIGN already includes the MAY_SIGN FLAG
661 so if this is zero it means that signing is disabled */
662 cFYI(1, "Signing disabled");
663 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
664 cERROR(1, "Server requires "
665 "packet signing to be enabled in "
666 "/proc/fs/cifs/SecurityFlags.");
670 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
671 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
672 /* signing required */
673 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
674 if ((server->sec_mode &
675 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
676 cERROR(1, "signing required but server lacks support");
679 server->sec_mode |= SECMODE_SIGN_REQUIRED;
681 /* signing optional ie CIFSSEC_MAY_SIGN */
682 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
684 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
688 cifs_buf_release(pSMB);
690 cFYI(1, "negprot rc %d", rc);
695 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
697 struct smb_hdr *smb_buffer;
700 cFYI(1, "In tree disconnect");
702 /* BB: do we need to check this? These should never be NULL. */
703 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
707 * No need to return error on this operation if tid invalidated and
708 * closed on server already e.g. due to tcp session crashing. Also,
709 * the tcon is no longer on the list, so no need to take lock before
712 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
715 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
716 (void **)&smb_buffer);
720 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
722 cFYI(1, "Tree disconnect failed %d", rc);
724 /* No need to return error on this operation if tid invalidated and
725 closed on server already e.g. due to tcp session crashing */
733 * This is a no-op for now. We're not really interested in the reply, but
734 * rather in the fact that the server sent one and that server->lstrp
737 * FIXME: maybe we should consider checking that the reply matches request?
740 cifs_echo_callback(struct mid_q_entry *mid)
742 struct TCP_Server_Info *server = mid->callback_data;
744 DeleteMidQEntry(mid);
745 add_credits(server, 1, CIFS_ECHO_OP);
749 CIFSSMBEcho(struct TCP_Server_Info *server)
755 cFYI(1, "In echo request");
757 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
761 /* set up echo request */
762 smb->hdr.Tid = 0xffff;
763 smb->hdr.WordCount = 1;
764 put_unaligned_le16(1, &smb->EchoCount);
765 put_bcc(1, &smb->hdr);
767 inc_rfc1001_len(smb, 3);
769 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
771 rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
772 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
774 cFYI(1, "Echo request failed: %d", rc);
776 cifs_small_buf_release(smb);
782 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
784 LOGOFF_ANDX_REQ *pSMB;
787 cFYI(1, "In SMBLogoff for session disconnect");
790 * BB: do we need to check validity of ses and server? They should
791 * always be valid since we have an active reference. If not, that
792 * should probably be a BUG()
794 if (!ses || !ses->server)
797 mutex_lock(&ses->session_mutex);
798 if (ses->need_reconnect)
799 goto session_already_dead; /* no need to send SMBlogoff if uid
800 already closed due to reconnect */
801 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
803 mutex_unlock(&ses->session_mutex);
807 pSMB->hdr.Mid = get_next_mid(ses->server);
809 if (ses->server->sec_mode &
810 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
811 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
813 pSMB->hdr.Uid = ses->Suid;
815 pSMB->AndXCommand = 0xFF;
816 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
817 session_already_dead:
818 mutex_unlock(&ses->session_mutex);
820 /* if session dead then we do not need to do ulogoff,
821 since server closed smb session, no sense reporting
829 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
830 const char *fileName, __u16 type,
831 const struct nls_table *nls_codepage, int remap)
833 TRANSACTION2_SPI_REQ *pSMB = NULL;
834 TRANSACTION2_SPI_RSP *pSMBr = NULL;
835 struct unlink_psx_rq *pRqD;
838 int bytes_returned = 0;
839 __u16 params, param_offset, offset, byte_count;
841 cFYI(1, "In POSIX delete");
843 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
848 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
850 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
851 PATH_MAX, nls_codepage, remap);
852 name_len++; /* trailing null */
854 } else { /* BB add path length overrun check */
855 name_len = strnlen(fileName, PATH_MAX);
856 name_len++; /* trailing null */
857 strncpy(pSMB->FileName, fileName, name_len);
860 params = 6 + name_len;
861 pSMB->MaxParameterCount = cpu_to_le16(2);
862 pSMB->MaxDataCount = 0; /* BB double check this with jra */
863 pSMB->MaxSetupCount = 0;
868 param_offset = offsetof(struct smb_com_transaction2_spi_req,
869 InformationLevel) - 4;
870 offset = param_offset + params;
872 /* Setup pointer to Request Data (inode type) */
873 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
874 pRqD->type = cpu_to_le16(type);
875 pSMB->ParameterOffset = cpu_to_le16(param_offset);
876 pSMB->DataOffset = cpu_to_le16(offset);
877 pSMB->SetupCount = 1;
879 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
880 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
882 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
883 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
884 pSMB->ParameterCount = cpu_to_le16(params);
885 pSMB->TotalParameterCount = pSMB->ParameterCount;
886 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
888 inc_rfc1001_len(pSMB, byte_count);
889 pSMB->ByteCount = cpu_to_le16(byte_count);
890 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
891 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
893 cFYI(1, "Posix delete returned %d", rc);
894 cifs_buf_release(pSMB);
896 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
905 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
906 const char *fileName, const struct nls_table *nls_codepage,
909 DELETE_FILE_REQ *pSMB = NULL;
910 DELETE_FILE_RSP *pSMBr = NULL;
916 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
921 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
923 cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
924 PATH_MAX, nls_codepage, remap);
925 name_len++; /* trailing null */
927 } else { /* BB improve check for buffer overruns BB */
928 name_len = strnlen(fileName, PATH_MAX);
929 name_len++; /* trailing null */
930 strncpy(pSMB->fileName, fileName, name_len);
932 pSMB->SearchAttributes =
933 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
934 pSMB->BufferFormat = 0x04;
935 inc_rfc1001_len(pSMB, name_len + 1);
936 pSMB->ByteCount = cpu_to_le16(name_len + 1);
937 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
939 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
941 cFYI(1, "Error in RMFile = %d", rc);
943 cifs_buf_release(pSMB);
951 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
952 const char *dirName, const struct nls_table *nls_codepage,
955 DELETE_DIRECTORY_REQ *pSMB = NULL;
956 DELETE_DIRECTORY_RSP *pSMBr = NULL;
961 cFYI(1, "In CIFSSMBRmDir");
963 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
968 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
969 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
970 PATH_MAX, nls_codepage, remap);
971 name_len++; /* trailing null */
973 } else { /* BB improve check for buffer overruns BB */
974 name_len = strnlen(dirName, PATH_MAX);
975 name_len++; /* trailing null */
976 strncpy(pSMB->DirName, dirName, name_len);
979 pSMB->BufferFormat = 0x04;
980 inc_rfc1001_len(pSMB, name_len + 1);
981 pSMB->ByteCount = cpu_to_le16(name_len + 1);
982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
984 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
986 cFYI(1, "Error in RMDir = %d", rc);
988 cifs_buf_release(pSMB);
995 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
996 const char *name, const struct nls_table *nls_codepage, int remap)
999 CREATE_DIRECTORY_REQ *pSMB = NULL;
1000 CREATE_DIRECTORY_RSP *pSMBr = NULL;
1004 cFYI(1, "In CIFSSMBMkDir");
1006 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1011 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1012 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1013 PATH_MAX, nls_codepage, remap);
1014 name_len++; /* trailing null */
1016 } else { /* BB improve check for buffer overruns BB */
1017 name_len = strnlen(name, PATH_MAX);
1018 name_len++; /* trailing null */
1019 strncpy(pSMB->DirName, name, name_len);
1022 pSMB->BufferFormat = 0x04;
1023 inc_rfc1001_len(pSMB, name_len + 1);
1024 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1025 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1026 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1027 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1029 cFYI(1, "Error in Mkdir = %d", rc);
1031 cifs_buf_release(pSMB);
1038 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1039 __u32 posix_flags, __u64 mode, __u16 *netfid,
1040 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1041 const char *name, const struct nls_table *nls_codepage,
1044 TRANSACTION2_SPI_REQ *pSMB = NULL;
1045 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1048 int bytes_returned = 0;
1049 __u16 params, param_offset, offset, byte_count, count;
1050 OPEN_PSX_REQ *pdata;
1051 OPEN_PSX_RSP *psx_rsp;
1053 cFYI(1, "In POSIX Create");
1055 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1060 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1062 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1063 PATH_MAX, nls_codepage, remap);
1064 name_len++; /* trailing null */
1066 } else { /* BB improve the check for buffer overruns BB */
1067 name_len = strnlen(name, PATH_MAX);
1068 name_len++; /* trailing null */
1069 strncpy(pSMB->FileName, name, name_len);
1072 params = 6 + name_len;
1073 count = sizeof(OPEN_PSX_REQ);
1074 pSMB->MaxParameterCount = cpu_to_le16(2);
1075 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1076 pSMB->MaxSetupCount = 0;
1080 pSMB->Reserved2 = 0;
1081 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1082 InformationLevel) - 4;
1083 offset = param_offset + params;
1084 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1085 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1086 pdata->Permissions = cpu_to_le64(mode);
1087 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1088 pdata->OpenFlags = cpu_to_le32(*pOplock);
1089 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1090 pSMB->DataOffset = cpu_to_le16(offset);
1091 pSMB->SetupCount = 1;
1092 pSMB->Reserved3 = 0;
1093 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1094 byte_count = 3 /* pad */ + params + count;
1096 pSMB->DataCount = cpu_to_le16(count);
1097 pSMB->ParameterCount = cpu_to_le16(params);
1098 pSMB->TotalDataCount = pSMB->DataCount;
1099 pSMB->TotalParameterCount = pSMB->ParameterCount;
1100 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1101 pSMB->Reserved4 = 0;
1102 inc_rfc1001_len(pSMB, byte_count);
1103 pSMB->ByteCount = cpu_to_le16(byte_count);
1104 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1105 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1107 cFYI(1, "Posix create returned %d", rc);
1108 goto psx_create_err;
1111 cFYI(1, "copying inode info");
1112 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1114 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1115 rc = -EIO; /* bad smb */
1116 goto psx_create_err;
1119 /* copy return information to pRetData */
1120 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1121 + le16_to_cpu(pSMBr->t2.DataOffset));
1123 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1125 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1126 /* Let caller know file was created so we can set the mode. */
1127 /* Do we care about the CreateAction in any other cases? */
1128 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1129 *pOplock |= CIFS_CREATE_ACTION;
1130 /* check to make sure response data is there */
1131 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1132 pRetData->Type = cpu_to_le32(-1); /* unknown */
1133 cFYI(DBG2, "unknown type");
1135 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1136 + sizeof(FILE_UNIX_BASIC_INFO)) {
1137 cERROR(1, "Open response data too small");
1138 pRetData->Type = cpu_to_le32(-1);
1139 goto psx_create_err;
1141 memcpy((char *) pRetData,
1142 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1143 sizeof(FILE_UNIX_BASIC_INFO));
1147 cifs_buf_release(pSMB);
1149 if (posix_flags & SMB_O_DIRECTORY)
1150 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1152 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1160 static __u16 convert_disposition(int disposition)
1164 switch (disposition) {
1165 case FILE_SUPERSEDE:
1166 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1169 ofun = SMBOPEN_OAPPEND;
1172 ofun = SMBOPEN_OCREATE;
1175 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1177 case FILE_OVERWRITE:
1178 ofun = SMBOPEN_OTRUNC;
1180 case FILE_OVERWRITE_IF:
1181 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1184 cFYI(1, "unknown disposition %d", disposition);
1185 ofun = SMBOPEN_OAPPEND; /* regular open */
1191 access_flags_to_smbopen_mode(const int access_flags)
1193 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1195 if (masked_flags == GENERIC_READ)
1196 return SMBOPEN_READ;
1197 else if (masked_flags == GENERIC_WRITE)
1198 return SMBOPEN_WRITE;
1200 /* just go for read/write */
1201 return SMBOPEN_READWRITE;
1205 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1206 const char *fileName, const int openDisposition,
1207 const int access_flags, const int create_options, __u16 *netfid,
1208 int *pOplock, FILE_ALL_INFO *pfile_info,
1209 const struct nls_table *nls_codepage, int remap)
1212 OPENX_REQ *pSMB = NULL;
1213 OPENX_RSP *pSMBr = NULL;
1219 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1224 pSMB->AndXCommand = 0xFF; /* none */
1226 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1227 count = 1; /* account for one byte pad to word boundary */
1229 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1230 fileName, PATH_MAX, nls_codepage, remap);
1231 name_len++; /* trailing null */
1233 } else { /* BB improve check for buffer overruns BB */
1234 count = 0; /* no pad */
1235 name_len = strnlen(fileName, PATH_MAX);
1236 name_len++; /* trailing null */
1237 strncpy(pSMB->fileName, fileName, name_len);
1239 if (*pOplock & REQ_OPLOCK)
1240 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1241 else if (*pOplock & REQ_BATCHOPLOCK)
1242 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1244 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1245 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1246 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1247 /* set file as system file if special file such
1248 as fifo and server expecting SFU style and
1249 no Unix extensions */
1251 if (create_options & CREATE_OPTION_SPECIAL)
1252 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1253 else /* BB FIXME BB */
1254 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1256 if (create_options & CREATE_OPTION_READONLY)
1257 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1260 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1261 CREATE_OPTIONS_MASK); */
1262 /* BB FIXME END BB */
1264 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1265 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1267 inc_rfc1001_len(pSMB, count);
1269 pSMB->ByteCount = cpu_to_le16(count);
1270 /* long_op set to 1 to allow for oplock break timeouts */
1271 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1272 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1273 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1275 cFYI(1, "Error in Open = %d", rc);
1277 /* BB verify if wct == 15 */
1279 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1281 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1282 /* Let caller know file was created so we can set the mode. */
1283 /* Do we care about the CreateAction in any other cases? */
1285 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1286 *pOplock |= CIFS_CREATE_ACTION; */
1290 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1291 pfile_info->LastAccessTime = 0; /* BB fixme */
1292 pfile_info->LastWriteTime = 0; /* BB fixme */
1293 pfile_info->ChangeTime = 0; /* BB fixme */
1294 pfile_info->Attributes =
1295 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1296 /* the file_info buf is endian converted by caller */
1297 pfile_info->AllocationSize =
1298 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1299 pfile_info->EndOfFile = pfile_info->AllocationSize;
1300 pfile_info->NumberOfLinks = cpu_to_le32(1);
1301 pfile_info->DeletePending = 0;
1305 cifs_buf_release(pSMB);
1312 CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1313 const char *fileName, const int openDisposition,
1314 const int access_flags, const int create_options, __u16 *netfid,
1315 int *pOplock, FILE_ALL_INFO *pfile_info,
1316 const struct nls_table *nls_codepage, int remap)
1319 OPEN_REQ *pSMB = NULL;
1320 OPEN_RSP *pSMBr = NULL;
1326 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1331 pSMB->AndXCommand = 0xFF; /* none */
1333 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1334 count = 1; /* account for one byte pad to word boundary */
1336 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1337 fileName, PATH_MAX, nls_codepage, remap);
1338 name_len++; /* trailing null */
1340 pSMB->NameLength = cpu_to_le16(name_len);
1341 } else { /* BB improve check for buffer overruns BB */
1342 count = 0; /* no pad */
1343 name_len = strnlen(fileName, PATH_MAX);
1344 name_len++; /* trailing null */
1345 pSMB->NameLength = cpu_to_le16(name_len);
1346 strncpy(pSMB->fileName, fileName, name_len);
1348 if (*pOplock & REQ_OPLOCK)
1349 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1350 else if (*pOplock & REQ_BATCHOPLOCK)
1351 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1352 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1353 pSMB->AllocationSize = 0;
1354 /* set file as system file if special file such
1355 as fifo and server expecting SFU style and
1356 no Unix extensions */
1357 if (create_options & CREATE_OPTION_SPECIAL)
1358 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1360 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1362 /* XP does not handle ATTR_POSIX_SEMANTICS */
1363 /* but it helps speed up case sensitive checks for other
1364 servers such as Samba */
1365 if (tcon->ses->capabilities & CAP_UNIX)
1366 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1368 if (create_options & CREATE_OPTION_READONLY)
1369 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1371 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1372 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1373 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1374 /* BB Expirement with various impersonation levels and verify */
1375 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1376 pSMB->SecurityFlags =
1377 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1380 inc_rfc1001_len(pSMB, count);
1382 pSMB->ByteCount = cpu_to_le16(count);
1383 /* long_op set to 1 to allow for oplock break timeouts */
1384 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1385 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1386 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1388 cFYI(1, "Error in Open = %d", rc);
1390 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1391 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1392 /* Let caller know file was created so we can set the mode. */
1393 /* Do we care about the CreateAction in any other cases? */
1394 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1395 *pOplock |= CIFS_CREATE_ACTION;
1397 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1398 36 /* CreationTime to Attributes */);
1399 /* the file_info buf is endian converted by caller */
1400 pfile_info->AllocationSize = pSMBr->AllocationSize;
1401 pfile_info->EndOfFile = pSMBr->EndOfFile;
1402 pfile_info->NumberOfLinks = cpu_to_le32(1);
1403 pfile_info->DeletePending = 0;
1407 cifs_buf_release(pSMB);
1414 * Discard any remaining data in the current SMB. To do this, we borrow the
1418 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1420 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1421 int remaining = rfclen + 4 - server->total_read;
1422 struct cifs_readdata *rdata = mid->callback_data;
1424 while (remaining > 0) {
1427 length = cifs_read_from_socket(server, server->bigbuf,
1428 min_t(unsigned int, remaining,
1429 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1432 server->total_read += length;
1433 remaining -= length;
1436 dequeue_mid(mid, rdata->result);
1441 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1444 unsigned int data_offset, data_len;
1445 struct cifs_readdata *rdata = mid->callback_data;
1446 char *buf = server->smallbuf;
1447 unsigned int buflen = get_rfc1002_length(buf) + 4;
1449 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1450 mid->mid, rdata->offset, rdata->bytes);
1453 * read the rest of READ_RSP header (sans Data array), or whatever we
1454 * can if there's not enough data. At this point, we've read down to
1457 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1458 HEADER_SIZE(server) + 1;
1460 rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1461 rdata->iov[0].iov_len = len;
1463 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1466 server->total_read += length;
1468 /* Was the SMB read successful? */
1469 rdata->result = server->ops->map_error(buf, false);
1470 if (rdata->result != 0) {
1471 cFYI(1, "%s: server returned error %d", __func__,
1473 return cifs_readv_discard(server, mid);
1476 /* Is there enough to get to the rest of the READ_RSP header? */
1477 if (server->total_read < server->vals->read_rsp_size) {
1478 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1479 __func__, server->total_read,
1480 server->vals->read_rsp_size);
1481 rdata->result = -EIO;
1482 return cifs_readv_discard(server, mid);
1485 data_offset = server->ops->read_data_offset(buf) + 4;
1486 if (data_offset < server->total_read) {
1488 * win2k8 sometimes sends an offset of 0 when the read
1489 * is beyond the EOF. Treat it as if the data starts just after
1492 cFYI(1, "%s: data offset (%u) inside read response header",
1493 __func__, data_offset);
1494 data_offset = server->total_read;
1495 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1496 /* data_offset is beyond the end of smallbuf */
1497 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1498 __func__, data_offset);
1499 rdata->result = -EIO;
1500 return cifs_readv_discard(server, mid);
1503 cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1504 server->total_read, data_offset);
1506 len = data_offset - server->total_read;
1508 /* read any junk before data into the rest of smallbuf */
1509 rdata->iov[0].iov_base = buf + server->total_read;
1510 rdata->iov[0].iov_len = len;
1511 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1514 server->total_read += length;
1517 /* set up first iov for signature check */
1518 rdata->iov[0].iov_base = buf;
1519 rdata->iov[0].iov_len = server->total_read;
1520 cFYI(1, "0: iov_base=%p iov_len=%zu",
1521 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1523 /* how much data is in the response? */
1524 data_len = server->ops->read_data_length(buf);
1525 if (data_offset + data_len > buflen) {
1526 /* data_len is corrupt -- discard frame */
1527 rdata->result = -EIO;
1528 return cifs_readv_discard(server, mid);
1531 /* marshal up the page array */
1533 len = rdata->marshal_iov(rdata, data_len);
1537 /* issue the read if we have any iovecs left to fill */
1538 if (rdata->nr_iov > 1) {
1539 length = cifs_readv_from_socket(server, &rdata->iov[1],
1540 rdata->nr_iov - 1, len);
1543 server->total_read += length;
1548 rdata->bytes = length;
1550 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1553 /* discard anything left over */
1554 if (server->total_read < buflen)
1555 return cifs_readv_discard(server, mid);
1557 dequeue_mid(mid, false);
1562 cifs_readv_callback(struct mid_q_entry *mid)
1564 struct cifs_readdata *rdata = mid->callback_data;
1565 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1566 struct TCP_Server_Info *server = tcon->ses->server;
1568 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1569 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1571 switch (mid->mid_state) {
1572 case MID_RESPONSE_RECEIVED:
1573 /* result already set, check signature */
1574 if (server->sec_mode &
1575 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1576 if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1577 server, mid->sequence_number + 1))
1578 cERROR(1, "Unexpected SMB signature");
1580 /* FIXME: should this be counted toward the initiating task? */
1581 task_io_account_read(rdata->bytes);
1582 cifs_stats_bytes_read(tcon, rdata->bytes);
1584 case MID_REQUEST_SUBMITTED:
1585 case MID_RETRY_NEEDED:
1586 rdata->result = -EAGAIN;
1589 rdata->result = -EIO;
1592 queue_work(cifsiod_wq, &rdata->work);
1593 DeleteMidQEntry(mid);
1594 add_credits(server, 1, 0);
1597 /* cifs_async_readv - send an async write, and set up mid to handle result */
1599 cifs_async_readv(struct cifs_readdata *rdata)
1602 READ_REQ *smb = NULL;
1604 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1606 cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1607 rdata->offset, rdata->bytes);
1609 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1612 wct = 10; /* old style read */
1613 if ((rdata->offset >> 32) > 0) {
1614 /* can not handle this big offset for old */
1619 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1623 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1624 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1626 smb->AndXCommand = 0xFF; /* none */
1627 smb->Fid = rdata->cfile->netfid;
1628 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1630 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1632 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1633 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1637 /* old style read */
1638 struct smb_com_readx_req *smbr =
1639 (struct smb_com_readx_req *)smb;
1640 smbr->ByteCount = 0;
1643 /* 4 for RFC1001 length + 1 for BCC */
1644 rdata->iov[0].iov_base = smb;
1645 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1647 kref_get(&rdata->refcount);
1648 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1649 cifs_readv_receive, cifs_readv_callback,
1653 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1655 kref_put(&rdata->refcount, cifs_readdata_release);
1657 cifs_small_buf_release(smb);
1662 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1663 unsigned int *nbytes, char **buf, int *pbuf_type)
1666 READ_REQ *pSMB = NULL;
1667 READ_RSP *pSMBr = NULL;
1668 char *pReadData = NULL;
1670 int resp_buf_type = 0;
1672 __u32 pid = io_parms->pid;
1673 __u16 netfid = io_parms->netfid;
1674 __u64 offset = io_parms->offset;
1675 struct cifs_tcon *tcon = io_parms->tcon;
1676 unsigned int count = io_parms->length;
1678 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1679 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1682 wct = 10; /* old style read */
1683 if ((offset >> 32) > 0) {
1684 /* can not handle this big offset for old */
1690 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1694 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1695 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1697 /* tcon and ses pointer are checked in smb_init */
1698 if (tcon->ses->server == NULL)
1699 return -ECONNABORTED;
1701 pSMB->AndXCommand = 0xFF; /* none */
1703 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1705 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1707 pSMB->Remaining = 0;
1708 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1709 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1711 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1713 /* old style read */
1714 struct smb_com_readx_req *pSMBW =
1715 (struct smb_com_readx_req *)pSMB;
1716 pSMBW->ByteCount = 0;
1719 iov[0].iov_base = (char *)pSMB;
1720 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1721 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1722 &resp_buf_type, CIFS_LOG_ERROR);
1723 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1724 pSMBr = (READ_RSP *)iov[0].iov_base;
1726 cERROR(1, "Send error in read = %d", rc);
1728 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1729 data_length = data_length << 16;
1730 data_length += le16_to_cpu(pSMBr->DataLength);
1731 *nbytes = data_length;
1733 /*check that DataLength would not go beyond end of SMB */
1734 if ((data_length > CIFSMaxBufSize)
1735 || (data_length > count)) {
1736 cFYI(1, "bad length %d for count %d",
1737 data_length, count);
1741 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1742 le16_to_cpu(pSMBr->DataOffset);
1743 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1744 cERROR(1, "Faulting on read rc = %d",rc);
1746 }*/ /* can not use copy_to_user when using page cache*/
1748 memcpy(*buf, pReadData, data_length);
1752 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1754 if (resp_buf_type == CIFS_SMALL_BUFFER)
1755 cifs_small_buf_release(iov[0].iov_base);
1756 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1757 cifs_buf_release(iov[0].iov_base);
1758 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1759 /* return buffer to caller to free */
1760 *buf = iov[0].iov_base;
1761 if (resp_buf_type == CIFS_SMALL_BUFFER)
1762 *pbuf_type = CIFS_SMALL_BUFFER;
1763 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1764 *pbuf_type = CIFS_LARGE_BUFFER;
1765 } /* else no valid buffer on return - leave as null */
1767 /* Note: On -EAGAIN error only caller can retry on handle based calls
1768 since file handle passed in no longer valid */
1774 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1775 unsigned int *nbytes, const char *buf,
1776 const char __user *ubuf, const int long_op)
1779 WRITE_REQ *pSMB = NULL;
1780 WRITE_RSP *pSMBr = NULL;
1781 int bytes_returned, wct;
1784 __u32 pid = io_parms->pid;
1785 __u16 netfid = io_parms->netfid;
1786 __u64 offset = io_parms->offset;
1787 struct cifs_tcon *tcon = io_parms->tcon;
1788 unsigned int count = io_parms->length;
1792 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1793 if (tcon->ses == NULL)
1794 return -ECONNABORTED;
1796 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1800 if ((offset >> 32) > 0) {
1801 /* can not handle big offset for old srv */
1806 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1811 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1812 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1814 /* tcon and ses pointer are checked in smb_init */
1815 if (tcon->ses->server == NULL)
1816 return -ECONNABORTED;
1818 pSMB->AndXCommand = 0xFF; /* none */
1820 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1822 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1824 pSMB->Reserved = 0xFFFFFFFF;
1825 pSMB->WriteMode = 0;
1826 pSMB->Remaining = 0;
1828 /* Can increase buffer size if buffer is big enough in some cases ie we
1829 can send more if LARGE_WRITE_X capability returned by the server and if
1830 our buffer is big enough or if we convert to iovecs on socket writes
1831 and eliminate the copy to the CIFS buffer */
1832 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1833 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1835 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1839 if (bytes_sent > count)
1842 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1844 memcpy(pSMB->Data, buf, bytes_sent);
1846 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1847 cifs_buf_release(pSMB);
1850 } else if (count != 0) {
1852 cifs_buf_release(pSMB);
1854 } /* else setting file size with write of zero bytes */
1856 byte_count = bytes_sent + 1; /* pad */
1857 else /* wct == 12 */
1858 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1860 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1861 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1862 inc_rfc1001_len(pSMB, byte_count);
1865 pSMB->ByteCount = cpu_to_le16(byte_count);
1866 else { /* old style write has byte count 4 bytes earlier
1868 struct smb_com_writex_req *pSMBW =
1869 (struct smb_com_writex_req *)pSMB;
1870 pSMBW->ByteCount = cpu_to_le16(byte_count);
1873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1874 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1875 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1877 cFYI(1, "Send error in write = %d", rc);
1879 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1880 *nbytes = (*nbytes) << 16;
1881 *nbytes += le16_to_cpu(pSMBr->Count);
1884 * Mask off high 16 bits when bytes written as returned by the
1885 * server is greater than bytes requested by the client. Some
1886 * OS/2 servers are known to set incorrect CountHigh values.
1888 if (*nbytes > count)
1892 cifs_buf_release(pSMB);
1894 /* Note: On -EAGAIN error only caller can retry on handle based calls
1895 since file handle passed in no longer valid */
1901 cifs_writedata_release(struct kref *refcount)
1903 struct cifs_writedata *wdata = container_of(refcount,
1904 struct cifs_writedata, refcount);
1907 cifsFileInfo_put(wdata->cfile);
1913 * Write failed with a retryable error. Resend the write request. It's also
1914 * possible that the page was redirtied so re-clean the page.
1917 cifs_writev_requeue(struct cifs_writedata *wdata)
1920 struct inode *inode = wdata->cfile->dentry->d_inode;
1922 for (i = 0; i < wdata->nr_pages; i++) {
1923 lock_page(wdata->pages[i]);
1924 clear_page_dirty_for_io(wdata->pages[i]);
1928 rc = cifs_async_writev(wdata);
1929 } while (rc == -EAGAIN);
1931 for (i = 0; i < wdata->nr_pages; i++) {
1933 SetPageError(wdata->pages[i]);
1934 unlock_page(wdata->pages[i]);
1937 mapping_set_error(inode->i_mapping, rc);
1938 kref_put(&wdata->refcount, cifs_writedata_release);
1942 cifs_writev_complete(struct work_struct *work)
1944 struct cifs_writedata *wdata = container_of(work,
1945 struct cifs_writedata, work);
1946 struct inode *inode = wdata->cfile->dentry->d_inode;
1949 if (wdata->result == 0) {
1950 spin_lock(&inode->i_lock);
1951 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1952 spin_unlock(&inode->i_lock);
1953 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1955 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1956 return cifs_writev_requeue(wdata);
1958 for (i = 0; i < wdata->nr_pages; i++) {
1959 struct page *page = wdata->pages[i];
1960 if (wdata->result == -EAGAIN)
1961 __set_page_dirty_nobuffers(page);
1962 else if (wdata->result < 0)
1964 end_page_writeback(page);
1965 page_cache_release(page);
1967 if (wdata->result != -EAGAIN)
1968 mapping_set_error(inode->i_mapping, wdata->result);
1969 kref_put(&wdata->refcount, cifs_writedata_release);
1972 struct cifs_writedata *
1973 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1975 struct cifs_writedata *wdata;
1977 /* this would overflow */
1978 if (nr_pages == 0) {
1979 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1983 /* writedata + number of page pointers */
1984 wdata = kzalloc(sizeof(*wdata) +
1985 sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1986 if (wdata != NULL) {
1987 kref_init(&wdata->refcount);
1988 INIT_LIST_HEAD(&wdata->list);
1989 init_completion(&wdata->done);
1990 INIT_WORK(&wdata->work, complete);
1996 * Check the mid_state and signature on received buffer (if any), and queue the
1997 * workqueue completion task.
2000 cifs_writev_callback(struct mid_q_entry *mid)
2002 struct cifs_writedata *wdata = mid->callback_data;
2003 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2004 unsigned int written;
2005 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2007 switch (mid->mid_state) {
2008 case MID_RESPONSE_RECEIVED:
2009 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2010 if (wdata->result != 0)
2013 written = le16_to_cpu(smb->CountHigh);
2015 written += le16_to_cpu(smb->Count);
2017 * Mask off high 16 bits when bytes written as returned
2018 * by the server is greater than bytes requested by the
2019 * client. OS/2 servers are known to set incorrect
2022 if (written > wdata->bytes)
2025 if (written < wdata->bytes)
2026 wdata->result = -ENOSPC;
2028 wdata->bytes = written;
2030 case MID_REQUEST_SUBMITTED:
2031 case MID_RETRY_NEEDED:
2032 wdata->result = -EAGAIN;
2035 wdata->result = -EIO;
2039 queue_work(cifsiod_wq, &wdata->work);
2040 DeleteMidQEntry(mid);
2041 add_credits(tcon->ses->server, 1, 0);
2044 /* cifs_async_writev - send an async write, and set up mid to handle result */
2046 cifs_async_writev(struct cifs_writedata *wdata)
2048 int i, rc = -EACCES;
2049 WRITE_REQ *smb = NULL;
2051 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2052 struct kvec *iov = NULL;
2054 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2058 if (wdata->offset >> 32 > 0) {
2059 /* can not handle big offset for old srv */
2064 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2066 goto async_writev_out;
2068 /* 1 iov per page + 1 for header */
2069 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2072 goto async_writev_out;
2075 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2076 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2078 smb->AndXCommand = 0xFF; /* none */
2079 smb->Fid = wdata->cfile->netfid;
2080 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2082 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2083 smb->Reserved = 0xFFFFFFFF;
2088 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2090 /* 4 for RFC1001 length + 1 for BCC */
2091 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2092 iov[0].iov_base = smb;
2095 * This function should marshal up the page array into the kvec
2096 * array, reserving [0] for the header. It should kmap the pages
2097 * and set the iov_len properly for each one. It may also set
2101 wdata->marshal_iov(iov, wdata);
2104 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2106 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2107 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2110 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2111 put_bcc(wdata->bytes + 1, &smb->hdr);
2114 struct smb_com_writex_req *smbw =
2115 (struct smb_com_writex_req *)smb;
2116 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2117 put_bcc(wdata->bytes + 5, &smbw->hdr);
2118 iov[0].iov_len += 4; /* pad bigger by four bytes */
2121 kref_get(&wdata->refcount);
2122 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2123 NULL, cifs_writev_callback, wdata, 0);
2126 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2128 kref_put(&wdata->refcount, cifs_writedata_release);
2130 /* send is done, unmap pages */
2131 for (i = 0; i < wdata->nr_pages; i++)
2132 kunmap(wdata->pages[i]);
2135 cifs_small_buf_release(smb);
2141 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2142 unsigned int *nbytes, struct kvec *iov, int n_vec,
2146 WRITE_REQ *pSMB = NULL;
2149 int resp_buf_type = 0;
2150 __u32 pid = io_parms->pid;
2151 __u16 netfid = io_parms->netfid;
2152 __u64 offset = io_parms->offset;
2153 struct cifs_tcon *tcon = io_parms->tcon;
2154 unsigned int count = io_parms->length;
2158 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2160 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2164 if ((offset >> 32) > 0) {
2165 /* can not handle big offset for old srv */
2169 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2173 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2174 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2176 /* tcon and ses pointer are checked in smb_init */
2177 if (tcon->ses->server == NULL)
2178 return -ECONNABORTED;
2180 pSMB->AndXCommand = 0xFF; /* none */
2182 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2184 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2185 pSMB->Reserved = 0xFFFFFFFF;
2186 pSMB->WriteMode = 0;
2187 pSMB->Remaining = 0;
2190 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2192 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2193 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2194 /* header + 1 byte pad */
2195 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2197 inc_rfc1001_len(pSMB, count + 1);
2198 else /* wct == 12 */
2199 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2201 pSMB->ByteCount = cpu_to_le16(count + 1);
2202 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2203 struct smb_com_writex_req *pSMBW =
2204 (struct smb_com_writex_req *)pSMB;
2205 pSMBW->ByteCount = cpu_to_le16(count + 5);
2207 iov[0].iov_base = pSMB;
2209 iov[0].iov_len = smb_hdr_len + 4;
2210 else /* wct == 12 pad bigger by four bytes */
2211 iov[0].iov_len = smb_hdr_len + 8;
2214 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2216 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2218 cFYI(1, "Send error Write2 = %d", rc);
2219 } else if (resp_buf_type == 0) {
2220 /* presumably this can not happen, but best to be safe */
2223 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2224 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2225 *nbytes = (*nbytes) << 16;
2226 *nbytes += le16_to_cpu(pSMBr->Count);
2229 * Mask off high 16 bits when bytes written as returned by the
2230 * server is greater than bytes requested by the client. OS/2
2231 * servers are known to set incorrect CountHigh values.
2233 if (*nbytes > count)
2237 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2238 if (resp_buf_type == CIFS_SMALL_BUFFER)
2239 cifs_small_buf_release(iov[0].iov_base);
2240 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2241 cifs_buf_release(iov[0].iov_base);
2243 /* Note: On -EAGAIN error only caller can retry on handle based calls
2244 since file handle passed in no longer valid */
2249 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2250 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2251 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2254 LOCK_REQ *pSMB = NULL;
2259 cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2261 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2266 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2267 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2268 pSMB->LockType = lock_type;
2269 pSMB->AndXCommand = 0xFF; /* none */
2270 pSMB->Fid = netfid; /* netfid stays le */
2272 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2273 inc_rfc1001_len(pSMB, count);
2274 pSMB->ByteCount = cpu_to_le16(count);
2276 iov[0].iov_base = (char *)pSMB;
2277 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2278 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2279 iov[1].iov_base = (char *)buf;
2280 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2282 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2283 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2285 cFYI(1, "Send error in cifs_lockv = %d", rc);
2291 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2292 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2293 const __u64 offset, const __u32 numUnlock,
2294 const __u32 numLock, const __u8 lockType,
2295 const bool waitFlag, const __u8 oplock_level)
2298 LOCK_REQ *pSMB = NULL;
2299 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2304 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2305 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2310 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2311 /* no response expected */
2312 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2314 } else if (waitFlag) {
2315 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2316 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2321 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2322 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2323 pSMB->LockType = lockType;
2324 pSMB->OplockLevel = oplock_level;
2325 pSMB->AndXCommand = 0xFF; /* none */
2326 pSMB->Fid = smb_file_id; /* netfid stays le */
2328 if ((numLock != 0) || (numUnlock != 0)) {
2329 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2330 /* BB where to store pid high? */
2331 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2332 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2333 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2334 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2335 count = sizeof(LOCKING_ANDX_RANGE);
2340 inc_rfc1001_len(pSMB, count);
2341 pSMB->ByteCount = cpu_to_le16(count);
2344 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2345 (struct smb_hdr *) pSMB, &bytes_returned);
2346 cifs_small_buf_release(pSMB);
2348 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2349 /* SMB buffer freed by function above */
2351 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2353 cFYI(1, "Send error in Lock = %d", rc);
2355 /* Note: On -EAGAIN error only caller can retry on handle based calls
2356 since file handle passed in no longer valid */
2361 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2362 const __u16 smb_file_id, const __u32 netpid,
2363 const loff_t start_offset, const __u64 len,
2364 struct file_lock *pLockData, const __u16 lock_type,
2365 const bool waitFlag)
2367 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2368 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2369 struct cifs_posix_lock *parm_data;
2372 int bytes_returned = 0;
2373 int resp_buf_type = 0;
2374 __u16 params, param_offset, offset, byte_count, count;
2377 cFYI(1, "Posix Lock");
2379 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2384 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2387 pSMB->MaxSetupCount = 0;
2390 pSMB->Reserved2 = 0;
2391 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2392 offset = param_offset + params;
2394 count = sizeof(struct cifs_posix_lock);
2395 pSMB->MaxParameterCount = cpu_to_le16(2);
2396 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2397 pSMB->SetupCount = 1;
2398 pSMB->Reserved3 = 0;
2400 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2402 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2403 byte_count = 3 /* pad */ + params + count;
2404 pSMB->DataCount = cpu_to_le16(count);
2405 pSMB->ParameterCount = cpu_to_le16(params);
2406 pSMB->TotalDataCount = pSMB->DataCount;
2407 pSMB->TotalParameterCount = pSMB->ParameterCount;
2408 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2409 parm_data = (struct cifs_posix_lock *)
2410 (((char *) &pSMB->hdr.Protocol) + offset);
2412 parm_data->lock_type = cpu_to_le16(lock_type);
2414 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2415 parm_data->lock_flags = cpu_to_le16(1);
2416 pSMB->Timeout = cpu_to_le32(-1);
2420 parm_data->pid = cpu_to_le32(netpid);
2421 parm_data->start = cpu_to_le64(start_offset);
2422 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2424 pSMB->DataOffset = cpu_to_le16(offset);
2425 pSMB->Fid = smb_file_id;
2426 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2427 pSMB->Reserved4 = 0;
2428 inc_rfc1001_len(pSMB, byte_count);
2429 pSMB->ByteCount = cpu_to_le16(byte_count);
2431 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2432 (struct smb_hdr *) pSMBr, &bytes_returned);
2434 iov[0].iov_base = (char *)pSMB;
2435 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2436 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2437 &resp_buf_type, timeout);
2438 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2439 not try to free it twice below on exit */
2440 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2444 cFYI(1, "Send error in Posix Lock = %d", rc);
2445 } else if (pLockData) {
2446 /* lock structure can be returned on get */
2449 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2451 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2452 rc = -EIO; /* bad smb */
2455 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2456 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2457 if (data_count < sizeof(struct cifs_posix_lock)) {
2461 parm_data = (struct cifs_posix_lock *)
2462 ((char *)&pSMBr->hdr.Protocol + data_offset);
2463 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2464 pLockData->fl_type = F_UNLCK;
2466 if (parm_data->lock_type ==
2467 __constant_cpu_to_le16(CIFS_RDLCK))
2468 pLockData->fl_type = F_RDLCK;
2469 else if (parm_data->lock_type ==
2470 __constant_cpu_to_le16(CIFS_WRLCK))
2471 pLockData->fl_type = F_WRLCK;
2473 pLockData->fl_start = le64_to_cpu(parm_data->start);
2474 pLockData->fl_end = pLockData->fl_start +
2475 le64_to_cpu(parm_data->length) - 1;
2476 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2482 cifs_small_buf_release(pSMB);
2484 if (resp_buf_type == CIFS_SMALL_BUFFER)
2485 cifs_small_buf_release(iov[0].iov_base);
2486 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2487 cifs_buf_release(iov[0].iov_base);
2489 /* Note: On -EAGAIN error only caller can retry on handle based calls
2490 since file handle passed in no longer valid */
2497 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2500 CLOSE_REQ *pSMB = NULL;
2501 cFYI(1, "In CIFSSMBClose");
2503 /* do not retry on dead session on close */
2504 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2510 pSMB->FileID = (__u16) smb_file_id;
2511 pSMB->LastWriteTime = 0xFFFFFFFF;
2512 pSMB->ByteCount = 0;
2513 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2514 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2517 /* EINTR is expected when user ctl-c to kill app */
2518 cERROR(1, "Send error in Close = %d", rc);
2522 /* Since session is dead, file will be closed on server already */
2530 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2533 FLUSH_REQ *pSMB = NULL;
2534 cFYI(1, "In CIFSSMBFlush");
2536 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2540 pSMB->FileID = (__u16) smb_file_id;
2541 pSMB->ByteCount = 0;
2542 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2543 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2545 cERROR(1, "Send error in Flush = %d", rc);
2551 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2552 const char *fromName, const char *toName,
2553 const struct nls_table *nls_codepage, int remap)
2556 RENAME_REQ *pSMB = NULL;
2557 RENAME_RSP *pSMBr = NULL;
2559 int name_len, name_len2;
2562 cFYI(1, "In CIFSSMBRename");
2564 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2569 pSMB->BufferFormat = 0x04;
2570 pSMB->SearchAttributes =
2571 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2574 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2576 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2577 PATH_MAX, nls_codepage, remap);
2578 name_len++; /* trailing null */
2580 pSMB->OldFileName[name_len] = 0x04; /* pad */
2581 /* protocol requires ASCII signature byte on Unicode string */
2582 pSMB->OldFileName[name_len + 1] = 0x00;
2584 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2585 toName, PATH_MAX, nls_codepage, remap);
2586 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2587 name_len2 *= 2; /* convert to bytes */
2588 } else { /* BB improve the check for buffer overruns BB */
2589 name_len = strnlen(fromName, PATH_MAX);
2590 name_len++; /* trailing null */
2591 strncpy(pSMB->OldFileName, fromName, name_len);
2592 name_len2 = strnlen(toName, PATH_MAX);
2593 name_len2++; /* trailing null */
2594 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2595 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2596 name_len2++; /* trailing null */
2597 name_len2++; /* signature byte */
2600 count = 1 /* 1st signature byte */ + name_len + name_len2;
2601 inc_rfc1001_len(pSMB, count);
2602 pSMB->ByteCount = cpu_to_le16(count);
2604 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2605 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2606 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2608 cFYI(1, "Send error in rename = %d", rc);
2610 cifs_buf_release(pSMB);
2618 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2619 int netfid, const char *target_name,
2620 const struct nls_table *nls_codepage, int remap)
2622 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2623 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2624 struct set_file_rename *rename_info;
2626 char dummy_string[30];
2628 int bytes_returned = 0;
2630 __u16 params, param_offset, offset, count, byte_count;
2632 cFYI(1, "Rename to File by handle");
2633 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2639 pSMB->MaxSetupCount = 0;
2643 pSMB->Reserved2 = 0;
2644 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2645 offset = param_offset + params;
2647 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2648 rename_info = (struct set_file_rename *) data_offset;
2649 pSMB->MaxParameterCount = cpu_to_le16(2);
2650 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2651 pSMB->SetupCount = 1;
2652 pSMB->Reserved3 = 0;
2653 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2654 byte_count = 3 /* pad */ + params;
2655 pSMB->ParameterCount = cpu_to_le16(params);
2656 pSMB->TotalParameterCount = pSMB->ParameterCount;
2657 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2658 pSMB->DataOffset = cpu_to_le16(offset);
2659 /* construct random name ".cifs_tmp<inodenum><mid>" */
2660 rename_info->overwrite = cpu_to_le32(1);
2661 rename_info->root_fid = 0;
2662 /* unicode only call */
2663 if (target_name == NULL) {
2664 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2666 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2667 dummy_string, 24, nls_codepage, remap);
2670 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2671 target_name, PATH_MAX, nls_codepage,
2674 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2675 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2676 byte_count += count;
2677 pSMB->DataCount = cpu_to_le16(count);
2678 pSMB->TotalDataCount = pSMB->DataCount;
2680 pSMB->InformationLevel =
2681 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2682 pSMB->Reserved4 = 0;
2683 inc_rfc1001_len(pSMB, byte_count);
2684 pSMB->ByteCount = cpu_to_le16(byte_count);
2685 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2686 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2687 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2689 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2691 cifs_buf_release(pSMB);
2693 /* Note: On -EAGAIN error only caller can retry on handle based calls
2694 since file handle passed in no longer valid */
2700 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2701 const char *fromName, const __u16 target_tid, const char *toName,
2702 const int flags, const struct nls_table *nls_codepage, int remap)
2705 COPY_REQ *pSMB = NULL;
2706 COPY_RSP *pSMBr = NULL;
2708 int name_len, name_len2;
2711 cFYI(1, "In CIFSSMBCopy");
2713 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2718 pSMB->BufferFormat = 0x04;
2719 pSMB->Tid2 = target_tid;
2721 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2723 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2724 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2725 fromName, PATH_MAX, nls_codepage,
2727 name_len++; /* trailing null */
2729 pSMB->OldFileName[name_len] = 0x04; /* pad */
2730 /* protocol requires ASCII signature byte on Unicode string */
2731 pSMB->OldFileName[name_len + 1] = 0x00;
2733 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2734 toName, PATH_MAX, nls_codepage, remap);
2735 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2736 name_len2 *= 2; /* convert to bytes */
2737 } else { /* BB improve the check for buffer overruns BB */
2738 name_len = strnlen(fromName, PATH_MAX);
2739 name_len++; /* trailing null */
2740 strncpy(pSMB->OldFileName, fromName, name_len);
2741 name_len2 = strnlen(toName, PATH_MAX);
2742 name_len2++; /* trailing null */
2743 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2744 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2745 name_len2++; /* trailing null */
2746 name_len2++; /* signature byte */
2749 count = 1 /* 1st signature byte */ + name_len + name_len2;
2750 inc_rfc1001_len(pSMB, count);
2751 pSMB->ByteCount = cpu_to_le16(count);
2753 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2754 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2756 cFYI(1, "Send error in copy = %d with %d files copied",
2757 rc, le16_to_cpu(pSMBr->CopyCount));
2759 cifs_buf_release(pSMB);
2768 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2769 const char *fromName, const char *toName,
2770 const struct nls_table *nls_codepage)
2772 TRANSACTION2_SPI_REQ *pSMB = NULL;
2773 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2776 int name_len_target;
2778 int bytes_returned = 0;
2779 __u16 params, param_offset, offset, byte_count;
2781 cFYI(1, "In Symlink Unix style");
2783 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2788 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2790 cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2791 /* find define for this maxpathcomponent */
2792 PATH_MAX, nls_codepage);
2793 name_len++; /* trailing null */
2796 } else { /* BB improve the check for buffer overruns BB */
2797 name_len = strnlen(fromName, PATH_MAX);
2798 name_len++; /* trailing null */
2799 strncpy(pSMB->FileName, fromName, name_len);
2801 params = 6 + name_len;
2802 pSMB->MaxSetupCount = 0;
2806 pSMB->Reserved2 = 0;
2807 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2808 InformationLevel) - 4;
2809 offset = param_offset + params;
2811 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2812 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2814 cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2815 /* find define for this maxpathcomponent */
2817 name_len_target++; /* trailing null */
2818 name_len_target *= 2;
2819 } else { /* BB improve the check for buffer overruns BB */
2820 name_len_target = strnlen(toName, PATH_MAX);
2821 name_len_target++; /* trailing null */
2822 strncpy(data_offset, toName, name_len_target);
2825 pSMB->MaxParameterCount = cpu_to_le16(2);
2826 /* BB find exact max on data count below from sess */
2827 pSMB->MaxDataCount = cpu_to_le16(1000);
2828 pSMB->SetupCount = 1;
2829 pSMB->Reserved3 = 0;
2830 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2831 byte_count = 3 /* pad */ + params + name_len_target;
2832 pSMB->DataCount = cpu_to_le16(name_len_target);
2833 pSMB->ParameterCount = cpu_to_le16(params);
2834 pSMB->TotalDataCount = pSMB->DataCount;
2835 pSMB->TotalParameterCount = pSMB->ParameterCount;
2836 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2837 pSMB->DataOffset = cpu_to_le16(offset);
2838 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2839 pSMB->Reserved4 = 0;
2840 inc_rfc1001_len(pSMB, byte_count);
2841 pSMB->ByteCount = cpu_to_le16(byte_count);
2842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2843 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2844 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2846 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2848 cifs_buf_release(pSMB);
2851 goto createSymLinkRetry;
2857 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2858 const char *fromName, const char *toName,
2859 const struct nls_table *nls_codepage, int remap)
2861 TRANSACTION2_SPI_REQ *pSMB = NULL;
2862 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2865 int name_len_target;
2867 int bytes_returned = 0;
2868 __u16 params, param_offset, offset, byte_count;
2870 cFYI(1, "In Create Hard link Unix style");
2871 createHardLinkRetry:
2872 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2877 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2878 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2879 PATH_MAX, nls_codepage, remap);
2880 name_len++; /* trailing null */
2883 } else { /* BB improve the check for buffer overruns BB */
2884 name_len = strnlen(toName, PATH_MAX);
2885 name_len++; /* trailing null */
2886 strncpy(pSMB->FileName, toName, name_len);
2888 params = 6 + name_len;
2889 pSMB->MaxSetupCount = 0;
2893 pSMB->Reserved2 = 0;
2894 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2895 InformationLevel) - 4;
2896 offset = param_offset + params;
2898 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2899 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2901 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2902 PATH_MAX, nls_codepage, remap);
2903 name_len_target++; /* trailing null */
2904 name_len_target *= 2;
2905 } else { /* BB improve the check for buffer overruns BB */
2906 name_len_target = strnlen(fromName, PATH_MAX);
2907 name_len_target++; /* trailing null */
2908 strncpy(data_offset, fromName, name_len_target);
2911 pSMB->MaxParameterCount = cpu_to_le16(2);
2912 /* BB find exact max on data count below from sess*/
2913 pSMB->MaxDataCount = cpu_to_le16(1000);
2914 pSMB->SetupCount = 1;
2915 pSMB->Reserved3 = 0;
2916 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2917 byte_count = 3 /* pad */ + params + name_len_target;
2918 pSMB->ParameterCount = cpu_to_le16(params);
2919 pSMB->TotalParameterCount = pSMB->ParameterCount;
2920 pSMB->DataCount = cpu_to_le16(name_len_target);
2921 pSMB->TotalDataCount = pSMB->DataCount;
2922 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2923 pSMB->DataOffset = cpu_to_le16(offset);
2924 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2925 pSMB->Reserved4 = 0;
2926 inc_rfc1001_len(pSMB, byte_count);
2927 pSMB->ByteCount = cpu_to_le16(byte_count);
2928 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2929 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2930 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2932 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2934 cifs_buf_release(pSMB);
2936 goto createHardLinkRetry;
2942 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2943 const char *fromName, const char *toName,
2944 const struct nls_table *nls_codepage, int remap)
2947 NT_RENAME_REQ *pSMB = NULL;
2948 RENAME_RSP *pSMBr = NULL;
2950 int name_len, name_len2;
2953 cFYI(1, "In CIFSCreateHardLink");
2954 winCreateHardLinkRetry:
2956 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2961 pSMB->SearchAttributes =
2962 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2964 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2965 pSMB->ClusterCount = 0;
2967 pSMB->BufferFormat = 0x04;
2969 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2971 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2972 PATH_MAX, nls_codepage, remap);
2973 name_len++; /* trailing null */
2976 /* protocol specifies ASCII buffer format (0x04) for unicode */
2977 pSMB->OldFileName[name_len] = 0x04;
2978 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2980 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2981 toName, PATH_MAX, nls_codepage, remap);
2982 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2983 name_len2 *= 2; /* convert to bytes */
2984 } else { /* BB improve the check for buffer overruns BB */
2985 name_len = strnlen(fromName, PATH_MAX);
2986 name_len++; /* trailing null */
2987 strncpy(pSMB->OldFileName, fromName, name_len);
2988 name_len2 = strnlen(toName, PATH_MAX);
2989 name_len2++; /* trailing null */
2990 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2991 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2992 name_len2++; /* trailing null */
2993 name_len2++; /* signature byte */
2996 count = 1 /* string type byte */ + name_len + name_len2;
2997 inc_rfc1001_len(pSMB, count);
2998 pSMB->ByteCount = cpu_to_le16(count);
3000 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3001 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3002 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3004 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3006 cifs_buf_release(pSMB);
3008 goto winCreateHardLinkRetry;
3014 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3015 const unsigned char *searchName, char **symlinkinfo,
3016 const struct nls_table *nls_codepage)
3018 /* SMB_QUERY_FILE_UNIX_LINK */
3019 TRANSACTION2_QPI_REQ *pSMB = NULL;
3020 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3024 __u16 params, byte_count;
3027 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3030 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3035 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3037 cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3038 PATH_MAX, nls_codepage);
3039 name_len++; /* trailing null */
3041 } else { /* BB improve the check for buffer overruns BB */
3042 name_len = strnlen(searchName, PATH_MAX);
3043 name_len++; /* trailing null */
3044 strncpy(pSMB->FileName, searchName, name_len);
3047 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3048 pSMB->TotalDataCount = 0;
3049 pSMB->MaxParameterCount = cpu_to_le16(2);
3050 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3051 pSMB->MaxSetupCount = 0;
3055 pSMB->Reserved2 = 0;
3056 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3057 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3058 pSMB->DataCount = 0;
3059 pSMB->DataOffset = 0;
3060 pSMB->SetupCount = 1;
3061 pSMB->Reserved3 = 0;
3062 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3063 byte_count = params + 1 /* pad */ ;
3064 pSMB->TotalParameterCount = cpu_to_le16(params);
3065 pSMB->ParameterCount = pSMB->TotalParameterCount;
3066 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3067 pSMB->Reserved4 = 0;
3068 inc_rfc1001_len(pSMB, byte_count);
3069 pSMB->ByteCount = cpu_to_le16(byte_count);
3071 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3072 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3074 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3076 /* decode response */
3078 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3079 /* BB also check enough total bytes returned */
3080 if (rc || get_bcc(&pSMBr->hdr) < 2)
3084 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3086 data_start = ((char *) &pSMBr->hdr.Protocol) +
3087 le16_to_cpu(pSMBr->t2.DataOffset);
3089 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3094 /* BB FIXME investigate remapping reserved chars here */
3095 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3096 count, is_unicode, nls_codepage);
3101 cifs_buf_release(pSMB);
3103 goto querySymLinkRetry;
3107 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3109 * Recent Windows versions now create symlinks more frequently
3110 * and they use the "reparse point" mechanism below. We can of course
3111 * do symlinks nicely to Samba and other servers which support the
3112 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3113 * "MF" symlinks optionally, but for recent Windows we really need to
3114 * reenable the code below and fix the cifs_symlink callers to handle this.
3115 * In the interim this code has been moved to its own config option so
3116 * it is not compiled in by default until callers fixed up and more tested.
3119 CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3120 const unsigned char *searchName,
3121 char *symlinkinfo, const int buflen, __u16 fid,
3122 const struct nls_table *nls_codepage)
3126 struct smb_com_transaction_ioctl_req *pSMB;
3127 struct smb_com_transaction_ioctl_rsp *pSMBr;
3129 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3130 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3135 pSMB->TotalParameterCount = 0 ;
3136 pSMB->TotalDataCount = 0;
3137 pSMB->MaxParameterCount = cpu_to_le32(2);
3138 /* BB find exact data count max from sess structure BB */
3139 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3140 pSMB->MaxSetupCount = 4;
3142 pSMB->ParameterOffset = 0;
3143 pSMB->DataCount = 0;
3144 pSMB->DataOffset = 0;
3145 pSMB->SetupCount = 4;
3146 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3147 pSMB->ParameterCount = pSMB->TotalParameterCount;
3148 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3149 pSMB->IsFsctl = 1; /* FSCTL */
3150 pSMB->IsRootFlag = 0;
3151 pSMB->Fid = fid; /* file handle always le */
3152 pSMB->ByteCount = 0;
3154 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3155 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3157 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3158 } else { /* decode response */
3159 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3160 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3161 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3162 /* BB also check enough total bytes returned */
3163 rc = -EIO; /* bad smb */
3166 if (data_count && (data_count < 2048)) {
3167 char *end_of_smb = 2 /* sizeof byte count */ +
3168 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3170 struct reparse_data *reparse_buf =
3171 (struct reparse_data *)
3172 ((char *)&pSMBr->hdr.Protocol
3174 if ((char *)reparse_buf >= end_of_smb) {
3178 if ((reparse_buf->LinkNamesBuf +
3179 reparse_buf->TargetNameOffset +
3180 reparse_buf->TargetNameLen) > end_of_smb) {
3181 cFYI(1, "reparse buf beyond SMB");
3186 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3187 cifs_from_ucs2(symlinkinfo, (__le16 *)
3188 (reparse_buf->LinkNamesBuf +
3189 reparse_buf->TargetNameOffset),
3191 reparse_buf->TargetNameLen,
3193 } else { /* ASCII names */
3194 strncpy(symlinkinfo,
3195 reparse_buf->LinkNamesBuf +
3196 reparse_buf->TargetNameOffset,
3197 min_t(const int, buflen,
3198 reparse_buf->TargetNameLen));
3202 cFYI(1, "Invalid return data count on "
3203 "get reparse info ioctl");
3205 symlinkinfo[buflen] = 0; /* just in case so the caller
3206 does not go off the end of the buffer */
3207 cFYI(1, "readlink result - %s", symlinkinfo);
3211 cifs_buf_release(pSMB);
3213 /* Note: On -EAGAIN error only caller can retry on handle based calls
3214 since file handle passed in no longer valid */
3218 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3220 #ifdef CONFIG_CIFS_POSIX
3222 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3223 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3224 struct cifs_posix_ace *cifs_ace)
3226 /* u8 cifs fields do not need le conversion */
3227 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3228 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3229 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3230 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3235 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3236 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3237 const int acl_type, const int size_of_data_area)
3242 struct cifs_posix_ace *pACE;
3243 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3244 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3246 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3249 if (acl_type & ACL_TYPE_ACCESS) {
3250 count = le16_to_cpu(cifs_acl->access_entry_count);
3251 pACE = &cifs_acl->ace_array[0];
3252 size = sizeof(struct cifs_posix_acl);
3253 size += sizeof(struct cifs_posix_ace) * count;
3254 /* check if we would go beyond end of SMB */
3255 if (size_of_data_area < size) {
3256 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3257 size_of_data_area, size);
3260 } else if (acl_type & ACL_TYPE_DEFAULT) {
3261 count = le16_to_cpu(cifs_acl->access_entry_count);
3262 size = sizeof(struct cifs_posix_acl);
3263 size += sizeof(struct cifs_posix_ace) * count;
3264 /* skip past access ACEs to get to default ACEs */
3265 pACE = &cifs_acl->ace_array[count];
3266 count = le16_to_cpu(cifs_acl->default_entry_count);
3267 size += sizeof(struct cifs_posix_ace) * count;
3268 /* check if we would go beyond end of SMB */
3269 if (size_of_data_area < size)
3276 size = posix_acl_xattr_size(count);
3277 if ((buflen == 0) || (local_acl == NULL)) {
3278 /* used to query ACL EA size */
3279 } else if (size > buflen) {
3281 } else /* buffer big enough */ {
3282 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3283 for (i = 0; i < count ; i++) {
3284 cifs_convert_ace(&local_acl->a_entries[i], pACE);
3291 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3292 const posix_acl_xattr_entry *local_ace)
3294 __u16 rc = 0; /* 0 = ACL converted ok */
3296 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3297 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3298 /* BB is there a better way to handle the large uid? */
3299 if (local_ace->e_id == cpu_to_le32(-1)) {
3300 /* Probably no need to le convert -1 on any arch but can not hurt */
3301 cifs_ace->cifs_uid = cpu_to_le64(-1);
3303 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3304 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3308 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3309 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3310 const int buflen, const int acl_type)
3313 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3314 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3318 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3321 count = posix_acl_xattr_count((size_t)buflen);
3322 cFYI(1, "setting acl with %d entries from buf of length %d and "
3324 count, buflen, le32_to_cpu(local_acl->a_version));
3325 if (le32_to_cpu(local_acl->a_version) != 2) {
3326 cFYI(1, "unknown POSIX ACL version %d",
3327 le32_to_cpu(local_acl->a_version));
3330 cifs_acl->version = cpu_to_le16(1);
3331 if (acl_type == ACL_TYPE_ACCESS)
3332 cifs_acl->access_entry_count = cpu_to_le16(count);
3333 else if (acl_type == ACL_TYPE_DEFAULT)
3334 cifs_acl->default_entry_count = cpu_to_le16(count);
3336 cFYI(1, "unknown ACL type %d", acl_type);
3339 for (i = 0; i < count; i++) {
3340 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3341 &local_acl->a_entries[i]);
3343 /* ACE not converted */
3348 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3349 rc += sizeof(struct cifs_posix_acl);
3350 /* BB add check to make sure ACL does not overflow SMB */
3356 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3357 const unsigned char *searchName,
3358 char *acl_inf, const int buflen, const int acl_type,
3359 const struct nls_table *nls_codepage, int remap)
3361 /* SMB_QUERY_POSIX_ACL */
3362 TRANSACTION2_QPI_REQ *pSMB = NULL;
3363 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3367 __u16 params, byte_count;
3369 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3372 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3377 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3379 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3380 searchName, PATH_MAX, nls_codepage,
3382 name_len++; /* trailing null */
3384 pSMB->FileName[name_len] = 0;
3385 pSMB->FileName[name_len+1] = 0;
3386 } else { /* BB improve the check for buffer overruns BB */
3387 name_len = strnlen(searchName, PATH_MAX);
3388 name_len++; /* trailing null */
3389 strncpy(pSMB->FileName, searchName, name_len);
3392 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3393 pSMB->TotalDataCount = 0;
3394 pSMB->MaxParameterCount = cpu_to_le16(2);
3395 /* BB find exact max data count below from sess structure BB */
3396 pSMB->MaxDataCount = cpu_to_le16(4000);
3397 pSMB->MaxSetupCount = 0;
3401 pSMB->Reserved2 = 0;
3402 pSMB->ParameterOffset = cpu_to_le16(
3403 offsetof(struct smb_com_transaction2_qpi_req,
3404 InformationLevel) - 4);
3405 pSMB->DataCount = 0;
3406 pSMB->DataOffset = 0;
3407 pSMB->SetupCount = 1;
3408 pSMB->Reserved3 = 0;
3409 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3410 byte_count = params + 1 /* pad */ ;
3411 pSMB->TotalParameterCount = cpu_to_le16(params);
3412 pSMB->ParameterCount = pSMB->TotalParameterCount;
3413 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3414 pSMB->Reserved4 = 0;
3415 inc_rfc1001_len(pSMB, byte_count);
3416 pSMB->ByteCount = cpu_to_le16(byte_count);
3418 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3419 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3420 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3422 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3424 /* decode response */
3426 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3427 /* BB also check enough total bytes returned */
3428 if (rc || get_bcc(&pSMBr->hdr) < 2)
3429 rc = -EIO; /* bad smb */
3431 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3432 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3433 rc = cifs_copy_posix_acl(acl_inf,
3434 (char *)&pSMBr->hdr.Protocol+data_offset,
3435 buflen, acl_type, count);
3438 cifs_buf_release(pSMB);
3445 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3446 const unsigned char *fileName,
3447 const char *local_acl, const int buflen,
3449 const struct nls_table *nls_codepage, int remap)
3451 struct smb_com_transaction2_spi_req *pSMB = NULL;
3452 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3456 int bytes_returned = 0;
3457 __u16 params, byte_count, data_count, param_offset, offset;
3459 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3461 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3465 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3467 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3468 PATH_MAX, nls_codepage, remap);
3469 name_len++; /* trailing null */
3471 } else { /* BB improve the check for buffer overruns BB */
3472 name_len = strnlen(fileName, PATH_MAX);
3473 name_len++; /* trailing null */
3474 strncpy(pSMB->FileName, fileName, name_len);
3476 params = 6 + name_len;
3477 pSMB->MaxParameterCount = cpu_to_le16(2);
3478 /* BB find max SMB size from sess */
3479 pSMB->MaxDataCount = cpu_to_le16(1000);
3480 pSMB->MaxSetupCount = 0;
3484 pSMB->Reserved2 = 0;
3485 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3486 InformationLevel) - 4;
3487 offset = param_offset + params;
3488 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3489 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3491 /* convert to on the wire format for POSIX ACL */
3492 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3494 if (data_count == 0) {
3496 goto setACLerrorExit;
3498 pSMB->DataOffset = cpu_to_le16(offset);
3499 pSMB->SetupCount = 1;
3500 pSMB->Reserved3 = 0;
3501 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3502 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3503 byte_count = 3 /* pad */ + params + data_count;
3504 pSMB->DataCount = cpu_to_le16(data_count);
3505 pSMB->TotalDataCount = pSMB->DataCount;
3506 pSMB->ParameterCount = cpu_to_le16(params);
3507 pSMB->TotalParameterCount = pSMB->ParameterCount;
3508 pSMB->Reserved4 = 0;
3509 inc_rfc1001_len(pSMB, byte_count);
3510 pSMB->ByteCount = cpu_to_le16(byte_count);
3511 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3512 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3514 cFYI(1, "Set POSIX ACL returned %d", rc);
3517 cifs_buf_release(pSMB);
3523 /* BB fix tabs in this function FIXME BB */
3525 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3526 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3529 struct smb_t2_qfi_req *pSMB = NULL;
3530 struct smb_t2_qfi_rsp *pSMBr = NULL;
3532 __u16 params, byte_count;
3534 cFYI(1, "In GetExtAttr");
3539 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3544 params = 2 /* level */ + 2 /* fid */;
3545 pSMB->t2.TotalDataCount = 0;
3546 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3547 /* BB find exact max data count below from sess structure BB */
3548 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3549 pSMB->t2.MaxSetupCount = 0;
3550 pSMB->t2.Reserved = 0;
3552 pSMB->t2.Timeout = 0;
3553 pSMB->t2.Reserved2 = 0;
3554 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3556 pSMB->t2.DataCount = 0;
3557 pSMB->t2.DataOffset = 0;
3558 pSMB->t2.SetupCount = 1;
3559 pSMB->t2.Reserved3 = 0;
3560 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3561 byte_count = params + 1 /* pad */ ;
3562 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3563 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3564 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3567 inc_rfc1001_len(pSMB, byte_count);
3568 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3570 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3571 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3573 cFYI(1, "error %d in GetExtAttr", rc);
3575 /* decode response */
3576 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3577 /* BB also check enough total bytes returned */
3578 if (rc || get_bcc(&pSMBr->hdr) < 2)
3579 /* If rc should we check for EOPNOSUPP and
3580 disable the srvino flag? or in caller? */
3581 rc = -EIO; /* bad smb */
3583 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3584 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3585 struct file_chattr_info *pfinfo;
3586 /* BB Do we need a cast or hash here ? */
3588 cFYI(1, "Illegal size ret in GetExtAttr");
3592 pfinfo = (struct file_chattr_info *)
3593 (data_offset + (char *) &pSMBr->hdr.Protocol);
3594 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3595 *pMask = le64_to_cpu(pfinfo->mask);
3599 cifs_buf_release(pSMB);
3601 goto GetExtAttrRetry;
3605 #endif /* CONFIG_POSIX */
3607 #ifdef CONFIG_CIFS_ACL
3609 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3610 * all NT TRANSACTS that we init here have total parm and data under about 400
3611 * bytes (to fit in small cifs buffer size), which is the case so far, it
3612 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3613 * returned setup area) and MaxParameterCount (returned parms size) must be set
3617 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3618 const int parm_len, struct cifs_tcon *tcon,
3623 struct smb_com_ntransact_req *pSMB;
3625 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3629 *ret_buf = (void *)pSMB;
3631 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3632 pSMB->TotalDataCount = 0;
3633 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3634 pSMB->ParameterCount = pSMB->TotalParameterCount;
3635 pSMB->DataCount = pSMB->TotalDataCount;
3636 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3637 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3638 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3639 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3640 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3641 pSMB->SubCommand = cpu_to_le16(sub_command);
3646 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3647 __u32 *pparmlen, __u32 *pdatalen)
3650 __u32 data_count, data_offset, parm_count, parm_offset;
3651 struct smb_com_ntransact_rsp *pSMBr;
3660 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3662 bcc = get_bcc(&pSMBr->hdr);
3663 end_of_smb = 2 /* sizeof byte count */ + bcc +
3664 (char *)&pSMBr->ByteCount;
3666 data_offset = le32_to_cpu(pSMBr->DataOffset);
3667 data_count = le32_to_cpu(pSMBr->DataCount);
3668 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3669 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3671 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3672 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3674 /* should we also check that parm and data areas do not overlap? */
3675 if (*ppparm > end_of_smb) {
3676 cFYI(1, "parms start after end of smb");
3678 } else if (parm_count + *ppparm > end_of_smb) {
3679 cFYI(1, "parm end after end of smb");
3681 } else if (*ppdata > end_of_smb) {
3682 cFYI(1, "data starts after end of smb");
3684 } else if (data_count + *ppdata > end_of_smb) {
3685 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3686 *ppdata, data_count, (data_count + *ppdata),
3689 } else if (parm_count + data_count > bcc) {
3690 cFYI(1, "parm count and data count larger than SMB");
3693 *pdatalen = data_count;
3694 *pparmlen = parm_count;
3698 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3700 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3701 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3705 QUERY_SEC_DESC_REQ *pSMB;
3708 cFYI(1, "GetCifsACL");
3713 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3714 8 /* parm len */, tcon, (void **) &pSMB);
3718 pSMB->MaxParameterCount = cpu_to_le32(4);
3719 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3720 pSMB->MaxSetupCount = 0;
3721 pSMB->Fid = fid; /* file handle always le */
3722 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3724 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3725 inc_rfc1001_len(pSMB, 11);
3726 iov[0].iov_base = (char *)pSMB;
3727 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3729 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3731 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3733 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3734 } else { /* decode response */
3738 struct smb_com_ntransact_rsp *pSMBr;
3741 /* validate_nttransact */
3742 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3743 &pdata, &parm_len, pbuflen);
3746 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3748 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3750 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3751 rc = -EIO; /* bad smb */
3756 /* BB check that data area is minimum length and as big as acl_len */
3758 acl_len = le32_to_cpu(*parm);
3759 if (acl_len != *pbuflen) {
3760 cERROR(1, "acl length %d does not match %d",
3762 if (*pbuflen > acl_len)
3766 /* check if buffer is big enough for the acl
3767 header followed by the smallest SID */
3768 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3769 (*pbuflen >= 64 * 1024)) {
3770 cERROR(1, "bad acl length %d", *pbuflen);
3774 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3775 if (*acl_inf == NULL) {
3779 memcpy(*acl_inf, pdata, *pbuflen);
3783 if (buf_type == CIFS_SMALL_BUFFER)
3784 cifs_small_buf_release(iov[0].iov_base);
3785 else if (buf_type == CIFS_LARGE_BUFFER)
3786 cifs_buf_release(iov[0].iov_base);
3787 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3792 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3793 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3795 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3797 int bytes_returned = 0;
3798 SET_SEC_DESC_REQ *pSMB = NULL;
3802 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3806 pSMB->MaxSetupCount = 0;
3810 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3811 data_count = acllen;
3812 data_offset = param_offset + param_count;
3813 byte_count = 3 /* pad */ + param_count;
3815 pSMB->DataCount = cpu_to_le32(data_count);
3816 pSMB->TotalDataCount = pSMB->DataCount;
3817 pSMB->MaxParameterCount = cpu_to_le32(4);
3818 pSMB->MaxDataCount = cpu_to_le32(16384);
3819 pSMB->ParameterCount = cpu_to_le32(param_count);
3820 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3821 pSMB->TotalParameterCount = pSMB->ParameterCount;
3822 pSMB->DataOffset = cpu_to_le32(data_offset);
3823 pSMB->SetupCount = 0;
3824 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3825 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3827 pSMB->Fid = fid; /* file handle always le */
3828 pSMB->Reserved2 = 0;
3829 pSMB->AclFlags = cpu_to_le32(aclflag);
3831 if (pntsd && acllen) {
3832 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3833 data_offset, pntsd, acllen);
3834 inc_rfc1001_len(pSMB, byte_count + data_count);
3836 inc_rfc1001_len(pSMB, byte_count);
3838 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3839 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3841 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3843 cFYI(1, "Set CIFS ACL returned %d", rc);
3844 cifs_buf_release(pSMB);
3847 goto setCifsAclRetry;
3852 #endif /* CONFIG_CIFS_ACL */
3854 /* Legacy Query Path Information call for lookup to old servers such
3857 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3858 const char *search_name, FILE_ALL_INFO *data,
3859 const struct nls_table *nls_codepage, int remap)
3861 QUERY_INFORMATION_REQ *pSMB;
3862 QUERY_INFORMATION_RSP *pSMBr;
3867 cFYI(1, "In SMBQPath path %s", search_name);
3869 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3874 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3876 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3877 search_name, PATH_MAX, nls_codepage,
3879 name_len++; /* trailing null */
3882 name_len = strnlen(search_name, PATH_MAX);
3883 name_len++; /* trailing null */
3884 strncpy(pSMB->FileName, search_name, name_len);
3886 pSMB->BufferFormat = 0x04;
3887 name_len++; /* account for buffer type byte */
3888 inc_rfc1001_len(pSMB, (__u16)name_len);
3889 pSMB->ByteCount = cpu_to_le16(name_len);
3891 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3892 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3894 cFYI(1, "Send error in QueryInfo = %d", rc);
3897 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3899 /* decode response */
3900 /* BB FIXME - add time zone adjustment BB */
3901 memset(data, 0, sizeof(FILE_ALL_INFO));
3904 /* decode time fields */
3905 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3906 data->LastWriteTime = data->ChangeTime;
3907 data->LastAccessTime = 0;
3908 data->AllocationSize =
3909 cpu_to_le64(le32_to_cpu(pSMBr->size));
3910 data->EndOfFile = data->AllocationSize;
3912 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3914 rc = -EIO; /* bad buffer passed in */
3916 cifs_buf_release(pSMB);
3925 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3926 u16 netfid, FILE_ALL_INFO *pFindData)
3928 struct smb_t2_qfi_req *pSMB = NULL;
3929 struct smb_t2_qfi_rsp *pSMBr = NULL;
3932 __u16 params, byte_count;
3935 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3940 params = 2 /* level */ + 2 /* fid */;
3941 pSMB->t2.TotalDataCount = 0;
3942 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3943 /* BB find exact max data count below from sess structure BB */
3944 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3945 pSMB->t2.MaxSetupCount = 0;
3946 pSMB->t2.Reserved = 0;
3948 pSMB->t2.Timeout = 0;
3949 pSMB->t2.Reserved2 = 0;
3950 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3952 pSMB->t2.DataCount = 0;
3953 pSMB->t2.DataOffset = 0;
3954 pSMB->t2.SetupCount = 1;
3955 pSMB->t2.Reserved3 = 0;
3956 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3957 byte_count = params + 1 /* pad */ ;
3958 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3959 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3960 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3963 inc_rfc1001_len(pSMB, byte_count);
3965 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3966 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3968 cFYI(1, "Send error in QPathInfo = %d", rc);
3969 } else { /* decode response */
3970 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3972 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3974 else if (get_bcc(&pSMBr->hdr) < 40)
3975 rc = -EIO; /* bad smb */
3976 else if (pFindData) {
3977 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3978 memcpy((char *) pFindData,
3979 (char *) &pSMBr->hdr.Protocol +
3980 data_offset, sizeof(FILE_ALL_INFO));
3984 cifs_buf_release(pSMB);
3986 goto QFileInfoRetry;
3992 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3993 const char *search_name, FILE_ALL_INFO *data,
3994 int legacy /* old style infolevel */,
3995 const struct nls_table *nls_codepage, int remap)
3997 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3998 TRANSACTION2_QPI_REQ *pSMB = NULL;
3999 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4003 __u16 params, byte_count;
4005 /* cFYI(1, "In QPathInfo path %s", search_name); */
4007 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4012 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4014 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4015 PATH_MAX, nls_codepage, remap);
4016 name_len++; /* trailing null */
4018 } else { /* BB improve the check for buffer overruns BB */
4019 name_len = strnlen(search_name, PATH_MAX);
4020 name_len++; /* trailing null */
4021 strncpy(pSMB->FileName, search_name, name_len);
4024 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4025 pSMB->TotalDataCount = 0;
4026 pSMB->MaxParameterCount = cpu_to_le16(2);
4027 /* BB find exact max SMB PDU from sess structure BB */
4028 pSMB->MaxDataCount = cpu_to_le16(4000);
4029 pSMB->MaxSetupCount = 0;
4033 pSMB->Reserved2 = 0;
4034 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4035 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4036 pSMB->DataCount = 0;
4037 pSMB->DataOffset = 0;
4038 pSMB->SetupCount = 1;
4039 pSMB->Reserved3 = 0;
4040 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4041 byte_count = params + 1 /* pad */ ;
4042 pSMB->TotalParameterCount = cpu_to_le16(params);
4043 pSMB->ParameterCount = pSMB->TotalParameterCount;
4045 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4047 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4048 pSMB->Reserved4 = 0;
4049 inc_rfc1001_len(pSMB, byte_count);
4050 pSMB->ByteCount = cpu_to_le16(byte_count);
4052 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4053 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4055 cFYI(1, "Send error in QPathInfo = %d", rc);
4056 } else { /* decode response */
4057 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4059 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4061 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4062 rc = -EIO; /* bad smb */
4063 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4064 rc = -EIO; /* 24 or 26 expected but we do not read
4068 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4071 * On legacy responses we do not read the last field,
4072 * EAsize, fortunately since it varies by subdialect and
4073 * also note it differs on Set vs Get, ie two bytes or 4
4074 * bytes depending but we don't care here.
4077 size = sizeof(FILE_INFO_STANDARD);
4079 size = sizeof(FILE_ALL_INFO);
4080 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4085 cifs_buf_release(pSMB);
4087 goto QPathInfoRetry;
4093 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4094 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4096 struct smb_t2_qfi_req *pSMB = NULL;
4097 struct smb_t2_qfi_rsp *pSMBr = NULL;
4100 __u16 params, byte_count;
4103 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4108 params = 2 /* level */ + 2 /* fid */;
4109 pSMB->t2.TotalDataCount = 0;
4110 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4111 /* BB find exact max data count below from sess structure BB */
4112 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4113 pSMB->t2.MaxSetupCount = 0;
4114 pSMB->t2.Reserved = 0;
4116 pSMB->t2.Timeout = 0;
4117 pSMB->t2.Reserved2 = 0;
4118 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4120 pSMB->t2.DataCount = 0;
4121 pSMB->t2.DataOffset = 0;
4122 pSMB->t2.SetupCount = 1;
4123 pSMB->t2.Reserved3 = 0;
4124 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4125 byte_count = params + 1 /* pad */ ;
4126 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4127 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4128 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4131 inc_rfc1001_len(pSMB, byte_count);
4133 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4134 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4136 cFYI(1, "Send error in QPathInfo = %d", rc);
4137 } else { /* decode response */
4138 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4140 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4141 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4142 "Unix Extensions can be disabled on mount "
4143 "by specifying the nosfu mount option.");
4144 rc = -EIO; /* bad smb */
4146 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4147 memcpy((char *) pFindData,
4148 (char *) &pSMBr->hdr.Protocol +
4150 sizeof(FILE_UNIX_BASIC_INFO));
4154 cifs_buf_release(pSMB);
4156 goto UnixQFileInfoRetry;
4162 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4163 const unsigned char *searchName,
4164 FILE_UNIX_BASIC_INFO *pFindData,
4165 const struct nls_table *nls_codepage, int remap)
4167 /* SMB_QUERY_FILE_UNIX_BASIC */
4168 TRANSACTION2_QPI_REQ *pSMB = NULL;
4169 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4171 int bytes_returned = 0;
4173 __u16 params, byte_count;
4175 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4177 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4182 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4184 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4185 PATH_MAX, nls_codepage, remap);
4186 name_len++; /* trailing null */
4188 } else { /* BB improve the check for buffer overruns BB */
4189 name_len = strnlen(searchName, PATH_MAX);
4190 name_len++; /* trailing null */
4191 strncpy(pSMB->FileName, searchName, name_len);
4194 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4195 pSMB->TotalDataCount = 0;
4196 pSMB->MaxParameterCount = cpu_to_le16(2);
4197 /* BB find exact max SMB PDU from sess structure BB */
4198 pSMB->MaxDataCount = cpu_to_le16(4000);
4199 pSMB->MaxSetupCount = 0;
4203 pSMB->Reserved2 = 0;
4204 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4205 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4206 pSMB->DataCount = 0;
4207 pSMB->DataOffset = 0;
4208 pSMB->SetupCount = 1;
4209 pSMB->Reserved3 = 0;
4210 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4211 byte_count = params + 1 /* pad */ ;
4212 pSMB->TotalParameterCount = cpu_to_le16(params);
4213 pSMB->ParameterCount = pSMB->TotalParameterCount;
4214 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4215 pSMB->Reserved4 = 0;
4216 inc_rfc1001_len(pSMB, byte_count);
4217 pSMB->ByteCount = cpu_to_le16(byte_count);
4219 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4220 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4222 cFYI(1, "Send error in QPathInfo = %d", rc);
4223 } else { /* decode response */
4224 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4226 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4227 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4228 "Unix Extensions can be disabled on mount "
4229 "by specifying the nosfu mount option.");
4230 rc = -EIO; /* bad smb */
4232 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4233 memcpy((char *) pFindData,
4234 (char *) &pSMBr->hdr.Protocol +
4236 sizeof(FILE_UNIX_BASIC_INFO));
4239 cifs_buf_release(pSMB);
4241 goto UnixQPathInfoRetry;
4246 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4248 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4249 const char *searchName,
4250 const struct nls_table *nls_codepage,
4251 __u16 *pnetfid, __u16 search_flags,
4252 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4254 /* level 257 SMB_ */
4255 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4256 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4257 T2_FFIRST_RSP_PARMS *parms;
4259 int bytes_returned = 0;
4261 __u16 params, byte_count;
4263 cFYI(1, "In FindFirst for %s", searchName);
4266 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4271 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4273 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4274 PATH_MAX, nls_codepage, remap);
4275 /* We can not add the asterik earlier in case
4276 it got remapped to 0xF03A as if it were part of the
4277 directory name instead of a wildcard */
4279 pSMB->FileName[name_len] = dirsep;
4280 pSMB->FileName[name_len+1] = 0;
4281 pSMB->FileName[name_len+2] = '*';
4282 pSMB->FileName[name_len+3] = 0;
4283 name_len += 4; /* now the trailing null */
4284 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4285 pSMB->FileName[name_len+1] = 0;
4287 } else { /* BB add check for overrun of SMB buf BB */
4288 name_len = strnlen(searchName, PATH_MAX);
4289 /* BB fix here and in unicode clause above ie
4290 if (name_len > buffersize-header)
4291 free buffer exit; BB */
4292 strncpy(pSMB->FileName, searchName, name_len);
4293 pSMB->FileName[name_len] = dirsep;
4294 pSMB->FileName[name_len+1] = '*';
4295 pSMB->FileName[name_len+2] = 0;
4299 params = 12 + name_len /* includes null */ ;
4300 pSMB->TotalDataCount = 0; /* no EAs */
4301 pSMB->MaxParameterCount = cpu_to_le16(10);
4302 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4303 pSMB->MaxSetupCount = 0;
4307 pSMB->Reserved2 = 0;
4308 byte_count = params + 1 /* pad */ ;
4309 pSMB->TotalParameterCount = cpu_to_le16(params);
4310 pSMB->ParameterCount = pSMB->TotalParameterCount;
4311 pSMB->ParameterOffset = cpu_to_le16(
4312 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4314 pSMB->DataCount = 0;
4315 pSMB->DataOffset = 0;
4316 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4317 pSMB->Reserved3 = 0;
4318 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4319 pSMB->SearchAttributes =
4320 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4322 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4323 pSMB->SearchFlags = cpu_to_le16(search_flags);
4324 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4326 /* BB what should we set StorageType to? Does it matter? BB */
4327 pSMB->SearchStorageType = 0;
4328 inc_rfc1001_len(pSMB, byte_count);
4329 pSMB->ByteCount = cpu_to_le16(byte_count);
4331 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4332 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4333 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4335 if (rc) {/* BB add logic to retry regular search if Unix search
4336 rejected unexpectedly by server */
4337 /* BB Add code to handle unsupported level rc */
4338 cFYI(1, "Error in FindFirst = %d", rc);
4340 cifs_buf_release(pSMB);
4342 /* BB eventually could optimize out free and realloc of buf */
4345 goto findFirstRetry;
4346 } else { /* decode response */
4347 /* BB remember to free buffer if error BB */
4348 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4352 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4353 psrch_inf->unicode = true;
4355 psrch_inf->unicode = false;
4357 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4358 psrch_inf->smallBuf = 0;
4359 psrch_inf->srch_entries_start =
4360 (char *) &pSMBr->hdr.Protocol +
4361 le16_to_cpu(pSMBr->t2.DataOffset);
4362 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4363 le16_to_cpu(pSMBr->t2.ParameterOffset));
4365 if (parms->EndofSearch)
4366 psrch_inf->endOfSearch = true;
4368 psrch_inf->endOfSearch = false;
4370 psrch_inf->entries_in_buffer =
4371 le16_to_cpu(parms->SearchCount);
4372 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4373 psrch_inf->entries_in_buffer;
4374 lnoff = le16_to_cpu(parms->LastNameOffset);
4375 if (CIFSMaxBufSize < lnoff) {
4376 cERROR(1, "ignoring corrupt resume name");
4377 psrch_inf->last_entry = NULL;
4381 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4384 *pnetfid = parms->SearchHandle;
4386 cifs_buf_release(pSMB);
4393 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4394 __u16 searchHandle, __u16 search_flags,
4395 struct cifs_search_info *psrch_inf)
4397 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4398 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4399 T2_FNEXT_RSP_PARMS *parms;
4400 char *response_data;
4403 unsigned int name_len;
4404 __u16 params, byte_count;
4406 cFYI(1, "In FindNext");
4408 if (psrch_inf->endOfSearch)
4411 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4416 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4418 pSMB->TotalDataCount = 0; /* no EAs */
4419 pSMB->MaxParameterCount = cpu_to_le16(8);
4420 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4421 pSMB->MaxSetupCount = 0;
4425 pSMB->Reserved2 = 0;
4426 pSMB->ParameterOffset = cpu_to_le16(
4427 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4428 pSMB->DataCount = 0;
4429 pSMB->DataOffset = 0;
4430 pSMB->SetupCount = 1;
4431 pSMB->Reserved3 = 0;
4432 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4433 pSMB->SearchHandle = searchHandle; /* always kept as le */
4435 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4436 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4437 pSMB->ResumeKey = psrch_inf->resume_key;
4438 pSMB->SearchFlags = cpu_to_le16(search_flags);
4440 name_len = psrch_inf->resume_name_len;
4442 if (name_len < PATH_MAX) {
4443 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4444 byte_count += name_len;
4445 /* 14 byte parm len above enough for 2 byte null terminator */
4446 pSMB->ResumeFileName[name_len] = 0;
4447 pSMB->ResumeFileName[name_len+1] = 0;
4450 goto FNext2_err_exit;
4452 byte_count = params + 1 /* pad */ ;
4453 pSMB->TotalParameterCount = cpu_to_le16(params);
4454 pSMB->ParameterCount = pSMB->TotalParameterCount;
4455 inc_rfc1001_len(pSMB, byte_count);
4456 pSMB->ByteCount = cpu_to_le16(byte_count);
4458 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4459 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4460 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4463 psrch_inf->endOfSearch = true;
4464 cifs_buf_release(pSMB);
4465 rc = 0; /* search probably was closed at end of search*/
4467 cFYI(1, "FindNext returned = %d", rc);
4468 } else { /* decode response */
4469 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4474 /* BB fixme add lock for file (srch_info) struct here */
4475 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4476 psrch_inf->unicode = true;
4478 psrch_inf->unicode = false;
4479 response_data = (char *) &pSMBr->hdr.Protocol +
4480 le16_to_cpu(pSMBr->t2.ParameterOffset);
4481 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4482 response_data = (char *)&pSMBr->hdr.Protocol +
4483 le16_to_cpu(pSMBr->t2.DataOffset);
4484 if (psrch_inf->smallBuf)
4485 cifs_small_buf_release(
4486 psrch_inf->ntwrk_buf_start);
4488 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4489 psrch_inf->srch_entries_start = response_data;
4490 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4491 psrch_inf->smallBuf = 0;
4492 if (parms->EndofSearch)
4493 psrch_inf->endOfSearch = true;
4495 psrch_inf->endOfSearch = false;
4496 psrch_inf->entries_in_buffer =
4497 le16_to_cpu(parms->SearchCount);
4498 psrch_inf->index_of_last_entry +=
4499 psrch_inf->entries_in_buffer;
4500 lnoff = le16_to_cpu(parms->LastNameOffset);
4501 if (CIFSMaxBufSize < lnoff) {
4502 cERROR(1, "ignoring corrupt resume name");
4503 psrch_inf->last_entry = NULL;
4506 psrch_inf->last_entry =
4507 psrch_inf->srch_entries_start + lnoff;
4509 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4510 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4512 /* BB fixme add unlock here */
4517 /* BB On error, should we leave previous search buf (and count and
4518 last entry fields) intact or free the previous one? */
4520 /* Note: On -EAGAIN error only caller can retry on handle based calls
4521 since file handle passed in no longer valid */
4524 cifs_buf_release(pSMB);
4529 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4530 const __u16 searchHandle)
4533 FINDCLOSE_REQ *pSMB = NULL;
4535 cFYI(1, "In CIFSSMBFindClose");
4536 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4538 /* no sense returning error if session restarted
4539 as file handle has been closed */
4545 pSMB->FileID = searchHandle;
4546 pSMB->ByteCount = 0;
4547 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4549 cERROR(1, "Send error in FindClose = %d", rc);
4551 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4553 /* Since session is dead, search handle closed on server already */
4561 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4562 const char *search_name, __u64 *inode_number,
4563 const struct nls_table *nls_codepage, int remap)
4566 TRANSACTION2_QPI_REQ *pSMB = NULL;
4567 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4568 int name_len, bytes_returned;
4569 __u16 params, byte_count;
4571 cFYI(1, "In GetSrvInodeNum for %s", search_name);
4575 GetInodeNumberRetry:
4576 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4581 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4583 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4584 search_name, PATH_MAX, nls_codepage,
4586 name_len++; /* trailing null */
4588 } else { /* BB improve the check for buffer overruns BB */
4589 name_len = strnlen(search_name, PATH_MAX);
4590 name_len++; /* trailing null */
4591 strncpy(pSMB->FileName, search_name, name_len);
4594 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4595 pSMB->TotalDataCount = 0;
4596 pSMB->MaxParameterCount = cpu_to_le16(2);
4597 /* BB find exact max data count below from sess structure BB */
4598 pSMB->MaxDataCount = cpu_to_le16(4000);
4599 pSMB->MaxSetupCount = 0;
4603 pSMB->Reserved2 = 0;
4604 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4605 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4606 pSMB->DataCount = 0;
4607 pSMB->DataOffset = 0;
4608 pSMB->SetupCount = 1;
4609 pSMB->Reserved3 = 0;
4610 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4611 byte_count = params + 1 /* pad */ ;
4612 pSMB->TotalParameterCount = cpu_to_le16(params);
4613 pSMB->ParameterCount = pSMB->TotalParameterCount;
4614 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4615 pSMB->Reserved4 = 0;
4616 inc_rfc1001_len(pSMB, byte_count);
4617 pSMB->ByteCount = cpu_to_le16(byte_count);
4619 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4620 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4622 cFYI(1, "error %d in QueryInternalInfo", rc);
4624 /* decode response */
4625 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4626 /* BB also check enough total bytes returned */
4627 if (rc || get_bcc(&pSMBr->hdr) < 2)
4628 /* If rc should we check for EOPNOSUPP and
4629 disable the srvino flag? or in caller? */
4630 rc = -EIO; /* bad smb */
4632 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4633 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4634 struct file_internal_info *pfinfo;
4635 /* BB Do we need a cast or hash here ? */
4637 cFYI(1, "Illegal size ret in QryIntrnlInf");
4639 goto GetInodeNumOut;
4641 pfinfo = (struct file_internal_info *)
4642 (data_offset + (char *) &pSMBr->hdr.Protocol);
4643 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4647 cifs_buf_release(pSMB);
4649 goto GetInodeNumberRetry;
4653 /* parses DFS refferal V3 structure
4654 * caller is responsible for freeing target_nodes
4657 * on failure - errno
4660 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4661 unsigned int *num_of_nodes,
4662 struct dfs_info3_param **target_nodes,
4663 const struct nls_table *nls_codepage, int remap,
4664 const char *searchName)
4669 struct dfs_referral_level_3 *ref;
4671 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4675 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4677 if (*num_of_nodes < 1) {
4678 cERROR(1, "num_referrals: must be at least > 0,"
4679 "but we get num_referrals = %d", *num_of_nodes);
4681 goto parse_DFS_referrals_exit;
4684 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4685 if (ref->VersionNumber != cpu_to_le16(3)) {
4686 cERROR(1, "Referrals of V%d version are not supported,"
4687 "should be V3", le16_to_cpu(ref->VersionNumber));
4689 goto parse_DFS_referrals_exit;
4692 /* get the upper boundary of the resp buffer */
4693 data_end = (char *)(&(pSMBr->PathConsumed)) +
4694 le16_to_cpu(pSMBr->t2.DataCount);
4696 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4698 le32_to_cpu(pSMBr->DFSFlags));
4700 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4701 *num_of_nodes, GFP_KERNEL);
4702 if (*target_nodes == NULL) {
4703 cERROR(1, "Failed to allocate buffer for target_nodes");
4705 goto parse_DFS_referrals_exit;
4708 /* collect necessary data from referrals */
4709 for (i = 0; i < *num_of_nodes; i++) {
4712 struct dfs_info3_param *node = (*target_nodes)+i;
4714 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4716 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4720 goto parse_DFS_referrals_exit;
4722 cifsConvertToUTF16((__le16 *) tmp, searchName,
4723 PATH_MAX, nls_codepage, remap);
4724 node->path_consumed = cifs_utf16_bytes(tmp,
4725 le16_to_cpu(pSMBr->PathConsumed),
4729 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4731 node->server_type = le16_to_cpu(ref->ServerType);
4732 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4735 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4736 max_len = data_end - temp;
4737 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4738 is_unicode, nls_codepage);
4739 if (!node->path_name) {
4741 goto parse_DFS_referrals_exit;
4744 /* copy link target UNC */
4745 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4746 max_len = data_end - temp;
4747 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4748 is_unicode, nls_codepage);
4749 if (!node->node_name) {
4751 goto parse_DFS_referrals_exit;
4757 parse_DFS_referrals_exit:
4759 free_dfs_info_array(*target_nodes, *num_of_nodes);
4760 *target_nodes = NULL;
4767 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4768 const char *search_name, struct dfs_info3_param **target_nodes,
4769 unsigned int *num_of_nodes,
4770 const struct nls_table *nls_codepage, int remap)
4772 /* TRANS2_GET_DFS_REFERRAL */
4773 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4774 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4778 __u16 params, byte_count;
4780 *target_nodes = NULL;
4782 cFYI(1, "In GetDFSRefer the path %s", search_name);
4786 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4791 /* server pointer checked in called function,
4792 but should never be null here anyway */
4793 pSMB->hdr.Mid = get_next_mid(ses->server);
4794 pSMB->hdr.Tid = ses->ipc_tid;
4795 pSMB->hdr.Uid = ses->Suid;
4796 if (ses->capabilities & CAP_STATUS32)
4797 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4798 if (ses->capabilities & CAP_DFS)
4799 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4801 if (ses->capabilities & CAP_UNICODE) {
4802 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4804 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4805 search_name, PATH_MAX, nls_codepage,
4807 name_len++; /* trailing null */
4809 } else { /* BB improve the check for buffer overruns BB */
4810 name_len = strnlen(search_name, PATH_MAX);
4811 name_len++; /* trailing null */
4812 strncpy(pSMB->RequestFileName, search_name, name_len);
4816 if (ses->server->sec_mode &
4817 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4818 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4821 pSMB->hdr.Uid = ses->Suid;
4823 params = 2 /* level */ + name_len /*includes null */ ;
4824 pSMB->TotalDataCount = 0;
4825 pSMB->DataCount = 0;
4826 pSMB->DataOffset = 0;
4827 pSMB->MaxParameterCount = 0;
4828 /* BB find exact max SMB PDU from sess structure BB */
4829 pSMB->MaxDataCount = cpu_to_le16(4000);
4830 pSMB->MaxSetupCount = 0;
4834 pSMB->Reserved2 = 0;
4835 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4836 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4837 pSMB->SetupCount = 1;
4838 pSMB->Reserved3 = 0;
4839 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4840 byte_count = params + 3 /* pad */ ;
4841 pSMB->ParameterCount = cpu_to_le16(params);
4842 pSMB->TotalParameterCount = pSMB->ParameterCount;
4843 pSMB->MaxReferralLevel = cpu_to_le16(3);
4844 inc_rfc1001_len(pSMB, byte_count);
4845 pSMB->ByteCount = cpu_to_le16(byte_count);
4847 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4848 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4850 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4853 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4855 /* BB Also check if enough total bytes returned? */
4856 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4857 rc = -EIO; /* bad smb */
4861 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4862 get_bcc(&pSMBr->hdr),
4863 le16_to_cpu(pSMBr->t2.DataOffset));
4865 /* parse returned result into more usable form */
4866 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4867 target_nodes, nls_codepage, remap,
4871 cifs_buf_release(pSMB);
4879 /* Query File System Info such as free space to old servers such as Win 9x */
4881 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4882 struct kstatfs *FSData)
4884 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4885 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4886 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4887 FILE_SYSTEM_ALLOC_INFO *response_data;
4889 int bytes_returned = 0;
4890 __u16 params, byte_count;
4892 cFYI(1, "OldQFSInfo");
4894 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4899 params = 2; /* level */
4900 pSMB->TotalDataCount = 0;
4901 pSMB->MaxParameterCount = cpu_to_le16(2);
4902 pSMB->MaxDataCount = cpu_to_le16(1000);
4903 pSMB->MaxSetupCount = 0;
4907 pSMB->Reserved2 = 0;
4908 byte_count = params + 1 /* pad */ ;
4909 pSMB->TotalParameterCount = cpu_to_le16(params);
4910 pSMB->ParameterCount = pSMB->TotalParameterCount;
4911 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4912 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4913 pSMB->DataCount = 0;
4914 pSMB->DataOffset = 0;
4915 pSMB->SetupCount = 1;
4916 pSMB->Reserved3 = 0;
4917 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4918 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4919 inc_rfc1001_len(pSMB, byte_count);
4920 pSMB->ByteCount = cpu_to_le16(byte_count);
4922 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4923 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4925 cFYI(1, "Send error in QFSInfo = %d", rc);
4926 } else { /* decode response */
4927 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4929 if (rc || get_bcc(&pSMBr->hdr) < 18)
4930 rc = -EIO; /* bad smb */
4932 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4933 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4934 get_bcc(&pSMBr->hdr), data_offset);
4936 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4937 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4939 le16_to_cpu(response_data->BytesPerSector) *
4940 le32_to_cpu(response_data->
4941 SectorsPerAllocationUnit);
4943 le32_to_cpu(response_data->TotalAllocationUnits);
4944 FSData->f_bfree = FSData->f_bavail =
4945 le32_to_cpu(response_data->FreeAllocationUnits);
4946 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4947 (unsigned long long)FSData->f_blocks,
4948 (unsigned long long)FSData->f_bfree,
4952 cifs_buf_release(pSMB);
4955 goto oldQFSInfoRetry;
4961 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4962 struct kstatfs *FSData)
4964 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4965 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4966 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4967 FILE_SYSTEM_INFO *response_data;
4969 int bytes_returned = 0;
4970 __u16 params, byte_count;
4972 cFYI(1, "In QFSInfo");
4974 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4979 params = 2; /* level */
4980 pSMB->TotalDataCount = 0;
4981 pSMB->MaxParameterCount = cpu_to_le16(2);
4982 pSMB->MaxDataCount = cpu_to_le16(1000);
4983 pSMB->MaxSetupCount = 0;
4987 pSMB->Reserved2 = 0;
4988 byte_count = params + 1 /* pad */ ;
4989 pSMB->TotalParameterCount = cpu_to_le16(params);
4990 pSMB->ParameterCount = pSMB->TotalParameterCount;
4991 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4992 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4993 pSMB->DataCount = 0;
4994 pSMB->DataOffset = 0;
4995 pSMB->SetupCount = 1;
4996 pSMB->Reserved3 = 0;
4997 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4998 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4999 inc_rfc1001_len(pSMB, byte_count);
5000 pSMB->ByteCount = cpu_to_le16(byte_count);
5002 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5003 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5005 cFYI(1, "Send error in QFSInfo = %d", rc);
5006 } else { /* decode response */
5007 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5009 if (rc || get_bcc(&pSMBr->hdr) < 24)
5010 rc = -EIO; /* bad smb */
5012 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5016 *) (((char *) &pSMBr->hdr.Protocol) +
5019 le32_to_cpu(response_data->BytesPerSector) *
5020 le32_to_cpu(response_data->
5021 SectorsPerAllocationUnit);
5023 le64_to_cpu(response_data->TotalAllocationUnits);
5024 FSData->f_bfree = FSData->f_bavail =
5025 le64_to_cpu(response_data->FreeAllocationUnits);
5026 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5027 (unsigned long long)FSData->f_blocks,
5028 (unsigned long long)FSData->f_bfree,
5032 cifs_buf_release(pSMB);
5041 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5043 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5044 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5045 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5046 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5048 int bytes_returned = 0;
5049 __u16 params, byte_count;
5051 cFYI(1, "In QFSAttributeInfo");
5053 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5058 params = 2; /* level */
5059 pSMB->TotalDataCount = 0;
5060 pSMB->MaxParameterCount = cpu_to_le16(2);
5061 /* BB find exact max SMB PDU from sess structure BB */
5062 pSMB->MaxDataCount = cpu_to_le16(1000);
5063 pSMB->MaxSetupCount = 0;
5067 pSMB->Reserved2 = 0;
5068 byte_count = params + 1 /* pad */ ;
5069 pSMB->TotalParameterCount = cpu_to_le16(params);
5070 pSMB->ParameterCount = pSMB->TotalParameterCount;
5071 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5072 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5073 pSMB->DataCount = 0;
5074 pSMB->DataOffset = 0;
5075 pSMB->SetupCount = 1;
5076 pSMB->Reserved3 = 0;
5077 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5078 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5079 inc_rfc1001_len(pSMB, byte_count);
5080 pSMB->ByteCount = cpu_to_le16(byte_count);
5082 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5083 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5085 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5086 } else { /* decode response */
5087 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5089 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5090 /* BB also check if enough bytes returned */
5091 rc = -EIO; /* bad smb */
5093 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5095 (FILE_SYSTEM_ATTRIBUTE_INFO
5096 *) (((char *) &pSMBr->hdr.Protocol) +
5098 memcpy(&tcon->fsAttrInfo, response_data,
5099 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5102 cifs_buf_release(pSMB);
5105 goto QFSAttributeRetry;
5111 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5113 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5114 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5115 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5116 FILE_SYSTEM_DEVICE_INFO *response_data;
5118 int bytes_returned = 0;
5119 __u16 params, byte_count;
5121 cFYI(1, "In QFSDeviceInfo");
5123 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5128 params = 2; /* level */
5129 pSMB->TotalDataCount = 0;
5130 pSMB->MaxParameterCount = cpu_to_le16(2);
5131 /* BB find exact max SMB PDU from sess structure BB */
5132 pSMB->MaxDataCount = cpu_to_le16(1000);
5133 pSMB->MaxSetupCount = 0;
5137 pSMB->Reserved2 = 0;
5138 byte_count = params + 1 /* pad */ ;
5139 pSMB->TotalParameterCount = cpu_to_le16(params);
5140 pSMB->ParameterCount = pSMB->TotalParameterCount;
5141 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5142 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5144 pSMB->DataCount = 0;
5145 pSMB->DataOffset = 0;
5146 pSMB->SetupCount = 1;
5147 pSMB->Reserved3 = 0;
5148 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5149 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5150 inc_rfc1001_len(pSMB, byte_count);
5151 pSMB->ByteCount = cpu_to_le16(byte_count);
5153 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5154 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5156 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5157 } else { /* decode response */
5158 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5160 if (rc || get_bcc(&pSMBr->hdr) <
5161 sizeof(FILE_SYSTEM_DEVICE_INFO))
5162 rc = -EIO; /* bad smb */
5164 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5166 (FILE_SYSTEM_DEVICE_INFO *)
5167 (((char *) &pSMBr->hdr.Protocol) +
5169 memcpy(&tcon->fsDevInfo, response_data,
5170 sizeof(FILE_SYSTEM_DEVICE_INFO));
5173 cifs_buf_release(pSMB);
5176 goto QFSDeviceRetry;
5182 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5184 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5185 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5186 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5187 FILE_SYSTEM_UNIX_INFO *response_data;
5189 int bytes_returned = 0;
5190 __u16 params, byte_count;
5192 cFYI(1, "In QFSUnixInfo");
5194 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5195 (void **) &pSMB, (void **) &pSMBr);
5199 params = 2; /* level */
5200 pSMB->TotalDataCount = 0;
5201 pSMB->DataCount = 0;
5202 pSMB->DataOffset = 0;
5203 pSMB->MaxParameterCount = cpu_to_le16(2);
5204 /* BB find exact max SMB PDU from sess structure BB */
5205 pSMB->MaxDataCount = cpu_to_le16(100);
5206 pSMB->MaxSetupCount = 0;
5210 pSMB->Reserved2 = 0;
5211 byte_count = params + 1 /* pad */ ;
5212 pSMB->ParameterCount = cpu_to_le16(params);
5213 pSMB->TotalParameterCount = pSMB->ParameterCount;
5214 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5215 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5216 pSMB->SetupCount = 1;
5217 pSMB->Reserved3 = 0;
5218 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5219 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5220 inc_rfc1001_len(pSMB, byte_count);
5221 pSMB->ByteCount = cpu_to_le16(byte_count);
5223 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5224 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5226 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5227 } else { /* decode response */
5228 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5230 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5231 rc = -EIO; /* bad smb */
5233 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5235 (FILE_SYSTEM_UNIX_INFO
5236 *) (((char *) &pSMBr->hdr.Protocol) +
5238 memcpy(&tcon->fsUnixInfo, response_data,
5239 sizeof(FILE_SYSTEM_UNIX_INFO));
5242 cifs_buf_release(pSMB);
5252 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5254 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5255 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5256 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5258 int bytes_returned = 0;
5259 __u16 params, param_offset, offset, byte_count;
5261 cFYI(1, "In SETFSUnixInfo");
5263 /* BB switch to small buf init to save memory */
5264 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5265 (void **) &pSMB, (void **) &pSMBr);
5269 params = 4; /* 2 bytes zero followed by info level. */
5270 pSMB->MaxSetupCount = 0;
5274 pSMB->Reserved2 = 0;
5275 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5277 offset = param_offset + params;
5279 pSMB->MaxParameterCount = cpu_to_le16(4);
5280 /* BB find exact max SMB PDU from sess structure BB */
5281 pSMB->MaxDataCount = cpu_to_le16(100);
5282 pSMB->SetupCount = 1;
5283 pSMB->Reserved3 = 0;
5284 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5285 byte_count = 1 /* pad */ + params + 12;
5287 pSMB->DataCount = cpu_to_le16(12);
5288 pSMB->ParameterCount = cpu_to_le16(params);
5289 pSMB->TotalDataCount = pSMB->DataCount;
5290 pSMB->TotalParameterCount = pSMB->ParameterCount;
5291 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5292 pSMB->DataOffset = cpu_to_le16(offset);
5296 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5299 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5300 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5301 pSMB->ClientUnixCap = cpu_to_le64(cap);
5303 inc_rfc1001_len(pSMB, byte_count);
5304 pSMB->ByteCount = cpu_to_le16(byte_count);
5306 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5307 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5309 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5310 } else { /* decode response */
5311 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5313 rc = -EIO; /* bad smb */
5315 cifs_buf_release(pSMB);
5318 goto SETFSUnixRetry;
5326 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5327 struct kstatfs *FSData)
5329 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5330 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5331 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5332 FILE_SYSTEM_POSIX_INFO *response_data;
5334 int bytes_returned = 0;
5335 __u16 params, byte_count;
5337 cFYI(1, "In QFSPosixInfo");
5339 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5344 params = 2; /* level */
5345 pSMB->TotalDataCount = 0;
5346 pSMB->DataCount = 0;
5347 pSMB->DataOffset = 0;
5348 pSMB->MaxParameterCount = cpu_to_le16(2);
5349 /* BB find exact max SMB PDU from sess structure BB */
5350 pSMB->MaxDataCount = cpu_to_le16(100);
5351 pSMB->MaxSetupCount = 0;
5355 pSMB->Reserved2 = 0;
5356 byte_count = params + 1 /* pad */ ;
5357 pSMB->ParameterCount = cpu_to_le16(params);
5358 pSMB->TotalParameterCount = pSMB->ParameterCount;
5359 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5360 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5361 pSMB->SetupCount = 1;
5362 pSMB->Reserved3 = 0;
5363 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5364 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5365 inc_rfc1001_len(pSMB, byte_count);
5366 pSMB->ByteCount = cpu_to_le16(byte_count);
5368 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5369 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5371 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5372 } else { /* decode response */
5373 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5375 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5376 rc = -EIO; /* bad smb */
5378 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5380 (FILE_SYSTEM_POSIX_INFO
5381 *) (((char *) &pSMBr->hdr.Protocol) +
5384 le32_to_cpu(response_data->BlockSize);
5386 le64_to_cpu(response_data->TotalBlocks);
5388 le64_to_cpu(response_data->BlocksAvail);
5389 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5390 FSData->f_bavail = FSData->f_bfree;
5393 le64_to_cpu(response_data->UserBlocksAvail);
5395 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5397 le64_to_cpu(response_data->TotalFileNodes);
5398 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5400 le64_to_cpu(response_data->FreeFileNodes);
5403 cifs_buf_release(pSMB);
5412 /* We can not use write of zero bytes trick to
5413 set file size due to need for large file support. Also note that
5414 this SetPathInfo is preferred to SetFileInfo based method in next
5415 routine which is only needed to work around a sharing violation bug
5416 in Samba which this routine can run into */
5419 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5420 const char *fileName, __u64 size, bool SetAllocation,
5421 const struct nls_table *nls_codepage, int remap)
5423 struct smb_com_transaction2_spi_req *pSMB = NULL;
5424 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5425 struct file_end_of_file_info *parm_data;
5428 int bytes_returned = 0;
5429 __u16 params, byte_count, data_count, param_offset, offset;
5431 cFYI(1, "In SetEOF");
5433 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5438 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5440 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5441 PATH_MAX, nls_codepage, remap);
5442 name_len++; /* trailing null */
5444 } else { /* BB improve the check for buffer overruns BB */
5445 name_len = strnlen(fileName, PATH_MAX);
5446 name_len++; /* trailing null */
5447 strncpy(pSMB->FileName, fileName, name_len);
5449 params = 6 + name_len;
5450 data_count = sizeof(struct file_end_of_file_info);
5451 pSMB->MaxParameterCount = cpu_to_le16(2);
5452 pSMB->MaxDataCount = cpu_to_le16(4100);
5453 pSMB->MaxSetupCount = 0;
5457 pSMB->Reserved2 = 0;
5458 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5459 InformationLevel) - 4;
5460 offset = param_offset + params;
5461 if (SetAllocation) {
5462 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5463 pSMB->InformationLevel =
5464 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5466 pSMB->InformationLevel =
5467 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5468 } else /* Set File Size */ {
5469 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5470 pSMB->InformationLevel =
5471 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5473 pSMB->InformationLevel =
5474 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5478 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5480 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5481 pSMB->DataOffset = cpu_to_le16(offset);
5482 pSMB->SetupCount = 1;
5483 pSMB->Reserved3 = 0;
5484 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5485 byte_count = 3 /* pad */ + params + data_count;
5486 pSMB->DataCount = cpu_to_le16(data_count);
5487 pSMB->TotalDataCount = pSMB->DataCount;
5488 pSMB->ParameterCount = cpu_to_le16(params);
5489 pSMB->TotalParameterCount = pSMB->ParameterCount;
5490 pSMB->Reserved4 = 0;
5491 inc_rfc1001_len(pSMB, byte_count);
5492 parm_data->FileSize = cpu_to_le64(size);
5493 pSMB->ByteCount = cpu_to_le16(byte_count);
5494 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5495 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5497 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5499 cifs_buf_release(pSMB);
5508 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5509 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5511 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5512 struct file_end_of_file_info *parm_data;
5514 __u16 params, param_offset, offset, byte_count, count;
5516 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5518 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5523 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5524 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5527 pSMB->MaxSetupCount = 0;
5531 pSMB->Reserved2 = 0;
5532 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5533 offset = param_offset + params;
5535 count = sizeof(struct file_end_of_file_info);
5536 pSMB->MaxParameterCount = cpu_to_le16(2);
5537 /* BB find exact max SMB PDU from sess structure BB */
5538 pSMB->MaxDataCount = cpu_to_le16(1000);
5539 pSMB->SetupCount = 1;
5540 pSMB->Reserved3 = 0;
5541 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5542 byte_count = 3 /* pad */ + params + count;
5543 pSMB->DataCount = cpu_to_le16(count);
5544 pSMB->ParameterCount = cpu_to_le16(params);
5545 pSMB->TotalDataCount = pSMB->DataCount;
5546 pSMB->TotalParameterCount = pSMB->ParameterCount;
5547 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5549 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5551 pSMB->DataOffset = cpu_to_le16(offset);
5552 parm_data->FileSize = cpu_to_le64(size);
5554 if (SetAllocation) {
5555 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5556 pSMB->InformationLevel =
5557 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5559 pSMB->InformationLevel =
5560 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5561 } else /* Set File Size */ {
5562 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5563 pSMB->InformationLevel =
5564 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5566 pSMB->InformationLevel =
5567 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5569 pSMB->Reserved4 = 0;
5570 inc_rfc1001_len(pSMB, byte_count);
5571 pSMB->ByteCount = cpu_to_le16(byte_count);
5572 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5574 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5577 /* Note: On -EAGAIN error only caller can retry on handle based calls
5578 since file handle passed in no longer valid */
5583 /* Some legacy servers such as NT4 require that the file times be set on
5584 an open handle, rather than by pathname - this is awkward due to
5585 potential access conflicts on the open, but it is unavoidable for these
5586 old servers since the only other choice is to go from 100 nanosecond DCE
5587 time and resort to the original setpathinfo level which takes the ancient
5588 DOS time format with 2 second granularity */
5590 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5591 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5593 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5596 __u16 params, param_offset, offset, byte_count, count;
5598 cFYI(1, "Set Times (via SetFileInfo)");
5599 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5604 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5605 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5608 pSMB->MaxSetupCount = 0;
5612 pSMB->Reserved2 = 0;
5613 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5614 offset = param_offset + params;
5616 data_offset = (char *)pSMB +
5617 offsetof(struct smb_hdr, Protocol) + offset;
5619 count = sizeof(FILE_BASIC_INFO);
5620 pSMB->MaxParameterCount = cpu_to_le16(2);
5621 /* BB find max SMB PDU from sess */
5622 pSMB->MaxDataCount = cpu_to_le16(1000);
5623 pSMB->SetupCount = 1;
5624 pSMB->Reserved3 = 0;
5625 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5626 byte_count = 3 /* pad */ + params + count;
5627 pSMB->DataCount = cpu_to_le16(count);
5628 pSMB->ParameterCount = cpu_to_le16(params);
5629 pSMB->TotalDataCount = pSMB->DataCount;
5630 pSMB->TotalParameterCount = pSMB->ParameterCount;
5631 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5632 pSMB->DataOffset = cpu_to_le16(offset);
5634 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5635 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5637 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5638 pSMB->Reserved4 = 0;
5639 inc_rfc1001_len(pSMB, byte_count);
5640 pSMB->ByteCount = cpu_to_le16(byte_count);
5641 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5642 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5644 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5646 /* Note: On -EAGAIN error only caller can retry on handle based calls
5647 since file handle passed in no longer valid */
5653 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5654 bool delete_file, __u16 fid, __u32 pid_of_opener)
5656 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5659 __u16 params, param_offset, offset, byte_count, count;
5661 cFYI(1, "Set File Disposition (via SetFileInfo)");
5662 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5667 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5668 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5671 pSMB->MaxSetupCount = 0;
5675 pSMB->Reserved2 = 0;
5676 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5677 offset = param_offset + params;
5679 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5682 pSMB->MaxParameterCount = cpu_to_le16(2);
5683 /* BB find max SMB PDU from sess */
5684 pSMB->MaxDataCount = cpu_to_le16(1000);
5685 pSMB->SetupCount = 1;
5686 pSMB->Reserved3 = 0;
5687 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5688 byte_count = 3 /* pad */ + params + count;
5689 pSMB->DataCount = cpu_to_le16(count);
5690 pSMB->ParameterCount = cpu_to_le16(params);
5691 pSMB->TotalDataCount = pSMB->DataCount;
5692 pSMB->TotalParameterCount = pSMB->ParameterCount;
5693 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5694 pSMB->DataOffset = cpu_to_le16(offset);
5696 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5697 pSMB->Reserved4 = 0;
5698 inc_rfc1001_len(pSMB, byte_count);
5699 pSMB->ByteCount = cpu_to_le16(byte_count);
5700 *data_offset = delete_file ? 1 : 0;
5701 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5703 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5709 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5710 const char *fileName, const FILE_BASIC_INFO *data,
5711 const struct nls_table *nls_codepage, int remap)
5713 TRANSACTION2_SPI_REQ *pSMB = NULL;
5714 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5717 int bytes_returned = 0;
5719 __u16 params, param_offset, offset, byte_count, count;
5721 cFYI(1, "In SetTimes");
5724 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5729 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5731 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5732 PATH_MAX, nls_codepage, remap);
5733 name_len++; /* trailing null */
5735 } else { /* BB improve the check for buffer overruns BB */
5736 name_len = strnlen(fileName, PATH_MAX);
5737 name_len++; /* trailing null */
5738 strncpy(pSMB->FileName, fileName, name_len);
5741 params = 6 + name_len;
5742 count = sizeof(FILE_BASIC_INFO);
5743 pSMB->MaxParameterCount = cpu_to_le16(2);
5744 /* BB find max SMB PDU from sess structure BB */
5745 pSMB->MaxDataCount = cpu_to_le16(1000);
5746 pSMB->MaxSetupCount = 0;
5750 pSMB->Reserved2 = 0;
5751 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5752 InformationLevel) - 4;
5753 offset = param_offset + params;
5754 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5755 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5756 pSMB->DataOffset = cpu_to_le16(offset);
5757 pSMB->SetupCount = 1;
5758 pSMB->Reserved3 = 0;
5759 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5760 byte_count = 3 /* pad */ + params + count;
5762 pSMB->DataCount = cpu_to_le16(count);
5763 pSMB->ParameterCount = cpu_to_le16(params);
5764 pSMB->TotalDataCount = pSMB->DataCount;
5765 pSMB->TotalParameterCount = pSMB->ParameterCount;
5766 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5767 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5769 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5770 pSMB->Reserved4 = 0;
5771 inc_rfc1001_len(pSMB, byte_count);
5772 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5773 pSMB->ByteCount = cpu_to_le16(byte_count);
5774 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5775 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5777 cFYI(1, "SetPathInfo (times) returned %d", rc);
5779 cifs_buf_release(pSMB);
5787 /* Can not be used to set time stamps yet (due to old DOS time format) */
5788 /* Can be used to set attributes */
5789 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5790 handling it anyway and NT4 was what we thought it would be needed for
5791 Do not delete it until we prove whether needed for Win9x though */
5793 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5794 __u16 dos_attrs, const struct nls_table *nls_codepage)
5796 SETATTR_REQ *pSMB = NULL;
5797 SETATTR_RSP *pSMBr = NULL;
5802 cFYI(1, "In SetAttrLegacy");
5805 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5810 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5812 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5813 PATH_MAX, nls_codepage);
5814 name_len++; /* trailing null */
5816 } else { /* BB improve the check for buffer overruns BB */
5817 name_len = strnlen(fileName, PATH_MAX);
5818 name_len++; /* trailing null */
5819 strncpy(pSMB->fileName, fileName, name_len);
5821 pSMB->attr = cpu_to_le16(dos_attrs);
5822 pSMB->BufferFormat = 0x04;
5823 inc_rfc1001_len(pSMB, name_len + 1);
5824 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5825 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5826 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5828 cFYI(1, "Error in LegacySetAttr = %d", rc);
5830 cifs_buf_release(pSMB);
5833 goto SetAttrLgcyRetry;
5837 #endif /* temporarily unneeded SetAttr legacy function */
5840 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5841 const struct cifs_unix_set_info_args *args)
5843 u64 mode = args->mode;
5846 * Samba server ignores set of file size to zero due to bugs in some
5847 * older clients, but we should be precise - we use SetFileSize to
5848 * set file size and do not want to truncate file size to zero
5849 * accidentally as happened on one Samba server beta by putting
5850 * zero instead of -1 here
5852 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5853 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5854 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5855 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5856 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5857 data_offset->Uid = cpu_to_le64(args->uid);
5858 data_offset->Gid = cpu_to_le64(args->gid);
5859 /* better to leave device as zero when it is */
5860 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5861 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5862 data_offset->Permissions = cpu_to_le64(mode);
5865 data_offset->Type = cpu_to_le32(UNIX_FILE);
5866 else if (S_ISDIR(mode))
5867 data_offset->Type = cpu_to_le32(UNIX_DIR);
5868 else if (S_ISLNK(mode))
5869 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5870 else if (S_ISCHR(mode))
5871 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5872 else if (S_ISBLK(mode))
5873 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5874 else if (S_ISFIFO(mode))
5875 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5876 else if (S_ISSOCK(mode))
5877 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5881 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5882 const struct cifs_unix_set_info_args *args,
5883 u16 fid, u32 pid_of_opener)
5885 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5888 u16 params, param_offset, offset, byte_count, count;
5890 cFYI(1, "Set Unix Info (via SetFileInfo)");
5891 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5896 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5897 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5900 pSMB->MaxSetupCount = 0;
5904 pSMB->Reserved2 = 0;
5905 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5906 offset = param_offset + params;
5908 data_offset = (char *)pSMB +
5909 offsetof(struct smb_hdr, Protocol) + offset;
5911 count = sizeof(FILE_UNIX_BASIC_INFO);
5913 pSMB->MaxParameterCount = cpu_to_le16(2);
5914 /* BB find max SMB PDU from sess */
5915 pSMB->MaxDataCount = cpu_to_le16(1000);
5916 pSMB->SetupCount = 1;
5917 pSMB->Reserved3 = 0;
5918 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5919 byte_count = 3 /* pad */ + params + count;
5920 pSMB->DataCount = cpu_to_le16(count);
5921 pSMB->ParameterCount = cpu_to_le16(params);
5922 pSMB->TotalDataCount = pSMB->DataCount;
5923 pSMB->TotalParameterCount = pSMB->ParameterCount;
5924 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5925 pSMB->DataOffset = cpu_to_le16(offset);
5927 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5928 pSMB->Reserved4 = 0;
5929 inc_rfc1001_len(pSMB, byte_count);
5930 pSMB->ByteCount = cpu_to_le16(byte_count);
5932 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5934 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5936 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5938 /* Note: On -EAGAIN error only caller can retry on handle based calls
5939 since file handle passed in no longer valid */
5945 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5947 const struct cifs_unix_set_info_args *args,
5948 const struct nls_table *nls_codepage, int remap)
5950 TRANSACTION2_SPI_REQ *pSMB = NULL;
5951 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5954 int bytes_returned = 0;
5955 FILE_UNIX_BASIC_INFO *data_offset;
5956 __u16 params, param_offset, offset, count, byte_count;
5958 cFYI(1, "In SetUID/GID/Mode");
5960 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5965 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5967 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5968 PATH_MAX, nls_codepage, remap);
5969 name_len++; /* trailing null */
5971 } else { /* BB improve the check for buffer overruns BB */
5972 name_len = strnlen(fileName, PATH_MAX);
5973 name_len++; /* trailing null */
5974 strncpy(pSMB->FileName, fileName, name_len);
5977 params = 6 + name_len;
5978 count = sizeof(FILE_UNIX_BASIC_INFO);
5979 pSMB->MaxParameterCount = cpu_to_le16(2);
5980 /* BB find max SMB PDU from sess structure BB */
5981 pSMB->MaxDataCount = cpu_to_le16(1000);
5982 pSMB->MaxSetupCount = 0;
5986 pSMB->Reserved2 = 0;
5987 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5988 InformationLevel) - 4;
5989 offset = param_offset + params;
5991 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5993 memset(data_offset, 0, count);
5994 pSMB->DataOffset = cpu_to_le16(offset);
5995 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5996 pSMB->SetupCount = 1;
5997 pSMB->Reserved3 = 0;
5998 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5999 byte_count = 3 /* pad */ + params + count;
6000 pSMB->ParameterCount = cpu_to_le16(params);
6001 pSMB->DataCount = cpu_to_le16(count);
6002 pSMB->TotalParameterCount = pSMB->ParameterCount;
6003 pSMB->TotalDataCount = pSMB->DataCount;
6004 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6005 pSMB->Reserved4 = 0;
6006 inc_rfc1001_len(pSMB, byte_count);
6008 cifs_fill_unix_set_info(data_offset, args);
6010 pSMB->ByteCount = cpu_to_le16(byte_count);
6011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6014 cFYI(1, "SetPathInfo (perms) returned %d", rc);
6016 cifs_buf_release(pSMB);
6022 #ifdef CONFIG_CIFS_XATTR
6024 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6025 * function used by listxattr and getxattr type calls. When ea_name is set,
6026 * it looks for that attribute name and stuffs that value into the EAData
6027 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6028 * buffer. In both cases, the return value is either the length of the
6029 * resulting data or a negative error code. If EAData is a NULL pointer then
6030 * the data isn't copied to it, but the length is returned.
6033 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6034 const unsigned char *searchName, const unsigned char *ea_name,
6035 char *EAData, size_t buf_size,
6036 const struct nls_table *nls_codepage, int remap)
6038 /* BB assumes one setup word */
6039 TRANSACTION2_QPI_REQ *pSMB = NULL;
6040 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6044 struct fealist *ea_response_data;
6045 struct fea *temp_fea;
6048 __u16 params, byte_count, data_offset;
6049 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6051 cFYI(1, "In Query All EAs path %s", searchName);
6053 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6058 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6060 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6061 PATH_MAX, nls_codepage, remap);
6062 list_len++; /* trailing null */
6064 } else { /* BB improve the check for buffer overruns BB */
6065 list_len = strnlen(searchName, PATH_MAX);
6066 list_len++; /* trailing null */
6067 strncpy(pSMB->FileName, searchName, list_len);
6070 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6071 pSMB->TotalDataCount = 0;
6072 pSMB->MaxParameterCount = cpu_to_le16(2);
6073 /* BB find exact max SMB PDU from sess structure BB */
6074 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6075 pSMB->MaxSetupCount = 0;
6079 pSMB->Reserved2 = 0;
6080 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6081 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6082 pSMB->DataCount = 0;
6083 pSMB->DataOffset = 0;
6084 pSMB->SetupCount = 1;
6085 pSMB->Reserved3 = 0;
6086 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6087 byte_count = params + 1 /* pad */ ;
6088 pSMB->TotalParameterCount = cpu_to_le16(params);
6089 pSMB->ParameterCount = pSMB->TotalParameterCount;
6090 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6091 pSMB->Reserved4 = 0;
6092 inc_rfc1001_len(pSMB, byte_count);
6093 pSMB->ByteCount = cpu_to_le16(byte_count);
6095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6098 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6103 /* BB also check enough total bytes returned */
6104 /* BB we need to improve the validity checking
6105 of these trans2 responses */
6107 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6108 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6109 rc = -EIO; /* bad smb */
6113 /* check that length of list is not more than bcc */
6114 /* check that each entry does not go beyond length
6116 /* check that each element of each entry does not
6117 go beyond end of list */
6118 /* validate_trans2_offsets() */
6119 /* BB check if start of smb + data_offset > &bcc+ bcc */
6121 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6122 ea_response_data = (struct fealist *)
6123 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6125 list_len = le32_to_cpu(ea_response_data->list_len);
6126 cFYI(1, "ea length %d", list_len);
6127 if (list_len <= 8) {
6128 cFYI(1, "empty EA list returned from server");
6132 /* make sure list_len doesn't go past end of SMB */
6133 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6134 if ((char *)ea_response_data + list_len > end_of_smb) {
6135 cFYI(1, "EA list appears to go beyond SMB");
6140 /* account for ea list len */
6142 temp_fea = ea_response_data->list;
6143 temp_ptr = (char *)temp_fea;
6144 while (list_len > 0) {
6145 unsigned int name_len;
6150 /* make sure we can read name_len and value_len */
6152 cFYI(1, "EA entry goes beyond length of list");
6157 name_len = temp_fea->name_len;
6158 value_len = le16_to_cpu(temp_fea->value_len);
6159 list_len -= name_len + 1 + value_len;
6161 cFYI(1, "EA entry goes beyond length of list");
6167 if (ea_name_len == name_len &&
6168 memcmp(ea_name, temp_ptr, name_len) == 0) {
6169 temp_ptr += name_len + 1;
6173 if ((size_t)value_len > buf_size) {
6177 memcpy(EAData, temp_ptr, value_len);
6181 /* account for prefix user. and trailing null */
6182 rc += (5 + 1 + name_len);
6183 if (rc < (int) buf_size) {
6184 memcpy(EAData, "user.", 5);
6186 memcpy(EAData, temp_ptr, name_len);
6188 /* null terminate name */
6191 } else if (buf_size == 0) {
6192 /* skip copy - calc size only */
6194 /* stop before overrun buffer */
6199 temp_ptr += name_len + 1 + value_len;
6200 temp_fea = (struct fea *)temp_ptr;
6203 /* didn't find the named attribute */
6208 cifs_buf_release(pSMB);
6216 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6217 const char *fileName, const char *ea_name, const void *ea_value,
6218 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6221 struct smb_com_transaction2_spi_req *pSMB = NULL;
6222 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6223 struct fealist *parm_data;
6226 int bytes_returned = 0;
6227 __u16 params, param_offset, byte_count, offset, count;
6229 cFYI(1, "In SetEA");
6231 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6236 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6238 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6239 PATH_MAX, nls_codepage, remap);
6240 name_len++; /* trailing null */
6242 } else { /* BB improve the check for buffer overruns BB */
6243 name_len = strnlen(fileName, PATH_MAX);
6244 name_len++; /* trailing null */
6245 strncpy(pSMB->FileName, fileName, name_len);
6248 params = 6 + name_len;
6250 /* done calculating parms using name_len of file name,
6251 now use name_len to calculate length of ea name
6252 we are going to create in the inode xattrs */
6253 if (ea_name == NULL)
6256 name_len = strnlen(ea_name, 255);
6258 count = sizeof(*parm_data) + ea_value_len + name_len;
6259 pSMB->MaxParameterCount = cpu_to_le16(2);
6260 /* BB find max SMB PDU from sess */
6261 pSMB->MaxDataCount = cpu_to_le16(1000);
6262 pSMB->MaxSetupCount = 0;
6266 pSMB->Reserved2 = 0;
6267 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6268 InformationLevel) - 4;
6269 offset = param_offset + params;
6270 pSMB->InformationLevel =
6271 cpu_to_le16(SMB_SET_FILE_EA);
6274 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6276 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6277 pSMB->DataOffset = cpu_to_le16(offset);
6278 pSMB->SetupCount = 1;
6279 pSMB->Reserved3 = 0;
6280 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6281 byte_count = 3 /* pad */ + params + count;
6282 pSMB->DataCount = cpu_to_le16(count);
6283 parm_data->list_len = cpu_to_le32(count);
6284 parm_data->list[0].EA_flags = 0;
6285 /* we checked above that name len is less than 255 */
6286 parm_data->list[0].name_len = (__u8)name_len;
6287 /* EA names are always ASCII */
6289 strncpy(parm_data->list[0].name, ea_name, name_len);
6290 parm_data->list[0].name[name_len] = 0;
6291 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6292 /* caller ensures that ea_value_len is less than 64K but
6293 we need to ensure that it fits within the smb */
6295 /*BB add length check to see if it would fit in
6296 negotiated SMB buffer size BB */
6297 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6299 memcpy(parm_data->list[0].name+name_len+1,
6300 ea_value, ea_value_len);
6302 pSMB->TotalDataCount = pSMB->DataCount;
6303 pSMB->ParameterCount = cpu_to_le16(params);
6304 pSMB->TotalParameterCount = pSMB->ParameterCount;
6305 pSMB->Reserved4 = 0;
6306 inc_rfc1001_len(pSMB, byte_count);
6307 pSMB->ByteCount = cpu_to_le16(byte_count);
6308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6309 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6311 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6313 cifs_buf_release(pSMB);
6322 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6324 * Years ago the kernel added a "dnotify" function for Samba server,
6325 * to allow network clients (such as Windows) to display updated
6326 * lists of files in directory listings automatically when
6327 * files are added by one user when another user has the
6328 * same directory open on their desktop. The Linux cifs kernel
6329 * client hooked into the kernel side of this interface for
6330 * the same reason, but ironically when the VFS moved from
6331 * "dnotify" to "inotify" it became harder to plug in Linux
6332 * network file system clients (the most obvious use case
6333 * for notify interfaces is when multiple users can update
6334 * the contents of the same directory - exactly what network
6335 * file systems can do) although the server (Samba) could
6336 * still use it. For the short term we leave the worker
6337 * function ifdeffed out (below) until inotify is fixed
6338 * in the VFS to make it easier to plug in network file
6339 * system clients. If inotify turns out to be permanently
6340 * incompatible for network fs clients, we could instead simply
6341 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6343 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6344 const int notify_subdirs, const __u16 netfid,
6345 __u32 filter, struct file *pfile, int multishot,
6346 const struct nls_table *nls_codepage)
6349 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6350 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6351 struct dir_notify_req *dnotify_req;
6354 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6355 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6360 pSMB->TotalParameterCount = 0 ;
6361 pSMB->TotalDataCount = 0;
6362 pSMB->MaxParameterCount = cpu_to_le32(2);
6363 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6364 pSMB->MaxSetupCount = 4;
6366 pSMB->ParameterOffset = 0;
6367 pSMB->DataCount = 0;
6368 pSMB->DataOffset = 0;
6369 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6370 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6371 pSMB->ParameterCount = pSMB->TotalParameterCount;
6373 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6374 pSMB->Reserved2 = 0;
6375 pSMB->CompletionFilter = cpu_to_le32(filter);
6376 pSMB->Fid = netfid; /* file handle always le */
6377 pSMB->ByteCount = 0;
6379 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6380 (struct smb_hdr *)pSMBr, &bytes_returned,
6383 cFYI(1, "Error in Notify = %d", rc);
6385 /* Add file to outstanding requests */
6386 /* BB change to kmem cache alloc */
6387 dnotify_req = kmalloc(
6388 sizeof(struct dir_notify_req),
6391 dnotify_req->Pid = pSMB->hdr.Pid;
6392 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6393 dnotify_req->Mid = pSMB->hdr.Mid;
6394 dnotify_req->Tid = pSMB->hdr.Tid;
6395 dnotify_req->Uid = pSMB->hdr.Uid;
6396 dnotify_req->netfid = netfid;
6397 dnotify_req->pfile = pfile;
6398 dnotify_req->filter = filter;
6399 dnotify_req->multishot = multishot;
6400 spin_lock(&GlobalMid_Lock);
6401 list_add_tail(&dnotify_req->lhead,
6402 &GlobalDnotifyReqList);
6403 spin_unlock(&GlobalMid_Lock);
6407 cifs_buf_release(pSMB);
6410 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */