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 */
89 /* Forward declarations */
90 static void cifs_readv_complete(struct work_struct *work);
92 /* Mark as invalid, all open files on tree connections since they
93 were closed when session to server was lost */
94 static void mark_open_files_invalid(struct cifs_tcon *pTcon)
96 struct cifsFileInfo *open_file = NULL;
97 struct list_head *tmp;
98 struct list_head *tmp1;
100 /* list all files open on tree connection and mark them invalid */
101 spin_lock(&cifs_file_list_lock);
102 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
103 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
104 open_file->invalidHandle = true;
105 open_file->oplock_break_cancelled = true;
107 spin_unlock(&cifs_file_list_lock);
108 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
112 /* reconnect the socket, tcon, and smb session if needed */
114 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
117 struct cifs_ses *ses;
118 struct TCP_Server_Info *server;
119 struct nls_table *nls_codepage;
122 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
123 * tcp and smb session status done differently for those three - in the
130 server = ses->server;
133 * only tree disconnect, open, and write, (and ulogoff which does not
134 * have tcon) are allowed as we start force umount
136 if (tcon->tidStatus == CifsExiting) {
137 if (smb_command != SMB_COM_WRITE_ANDX &&
138 smb_command != SMB_COM_OPEN_ANDX &&
139 smb_command != SMB_COM_TREE_DISCONNECT) {
140 cFYI(1, "can not send cmd %d while umounting",
147 * Give demultiplex thread up to 10 seconds to reconnect, should be
148 * greater than cifs socket timeout which is 7 seconds
150 while (server->tcpStatus == CifsNeedReconnect) {
151 wait_event_interruptible_timeout(server->response_q,
152 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
154 /* are we still trying to reconnect? */
155 if (server->tcpStatus != CifsNeedReconnect)
159 * on "soft" mounts we wait once. Hard mounts keep
160 * retrying until process is killed or server comes
164 cFYI(1, "gave up waiting on reconnect in smb_init");
169 if (!ses->need_reconnect && !tcon->need_reconnect)
172 nls_codepage = load_nls_default();
175 * need to prevent multiple threads trying to simultaneously
176 * reconnect the same SMB session
178 mutex_lock(&ses->session_mutex);
179 rc = cifs_negotiate_protocol(0, ses);
180 if (rc == 0 && ses->need_reconnect)
181 rc = cifs_setup_session(0, ses, nls_codepage);
183 /* do we need to reconnect tcon? */
184 if (rc || !tcon->need_reconnect) {
185 mutex_unlock(&ses->session_mutex);
189 mark_open_files_invalid(tcon);
190 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
191 mutex_unlock(&ses->session_mutex);
192 cFYI(1, "reconnect tcon rc = %d", rc);
198 * FIXME: check if wsize needs updated due to negotiated smb buffer
201 atomic_inc(&tconInfoReconnectCount);
203 /* tell server Unix caps we support */
204 if (ses->capabilities & CAP_UNIX)
205 reset_cifs_unix_caps(0, tcon, NULL, NULL);
208 * Removed call to reopen open files here. It is safer (and faster) to
209 * reopen files one at a time as needed in read and write.
211 * FIXME: what about file locks? don't we need to reclaim them ASAP?
216 * Check if handle based operation so we know whether we can continue
217 * or not without returning to caller to reset file handle
219 switch (smb_command) {
220 case SMB_COM_READ_ANDX:
221 case SMB_COM_WRITE_ANDX:
223 case SMB_COM_FIND_CLOSE2:
224 case SMB_COM_LOCKING_ANDX:
228 unload_nls(nls_codepage);
232 /* Allocate and return pointer to an SMB request buffer, and set basic
233 SMB information in the SMB header. If the return code is zero, this
234 function must have filled in request_buf pointer */
236 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
241 rc = cifs_reconnect_tcon(tcon, smb_command);
245 *request_buf = cifs_small_buf_get();
246 if (*request_buf == NULL) {
247 /* BB should we add a retry in here if not a writepage? */
251 header_assemble((struct smb_hdr *) *request_buf, smb_command,
255 cifs_stats_inc(&tcon->num_smbs_sent);
261 small_smb_init_no_tc(const int smb_command, const int wct,
262 struct cifs_ses *ses, void **request_buf)
265 struct smb_hdr *buffer;
267 rc = small_smb_init(smb_command, wct, NULL, request_buf);
271 buffer = (struct smb_hdr *)*request_buf;
272 buffer->Mid = GetNextMid(ses->server);
273 if (ses->capabilities & CAP_UNICODE)
274 buffer->Flags2 |= SMBFLG2_UNICODE;
275 if (ses->capabilities & CAP_STATUS32)
276 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
278 /* uid, tid can stay at zero as set in header assemble */
280 /* BB add support for turning on the signing when
281 this function is used after 1st of session setup requests */
286 /* If the return code is zero, this function must fill in request_buf pointer */
288 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
289 void **request_buf, void **response_buf)
291 *request_buf = cifs_buf_get();
292 if (*request_buf == NULL) {
293 /* BB should we add a retry in here if not a writepage? */
296 /* Although the original thought was we needed the response buf for */
297 /* potential retries of smb operations it turns out we can determine */
298 /* from the mid flags when the request buffer can be resent without */
299 /* having to use a second distinct buffer for the response */
301 *response_buf = *request_buf;
303 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
307 cifs_stats_inc(&tcon->num_smbs_sent);
312 /* If the return code is zero, this function must fill in request_buf pointer */
314 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
315 void **request_buf, void **response_buf)
319 rc = cifs_reconnect_tcon(tcon, smb_command);
323 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
327 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
328 void **request_buf, void **response_buf)
330 if (tcon->ses->need_reconnect || tcon->need_reconnect)
333 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
336 static int validate_t2(struct smb_t2_rsp *pSMB)
338 unsigned int total_size;
340 /* check for plausible wct */
341 if (pSMB->hdr.WordCount < 10)
344 /* check for parm and data offset going beyond end of smb */
345 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
346 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
349 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
350 if (total_size >= 512)
353 /* check that bcc is at least as big as parms + data, and that it is
354 * less than negotiated smb buffer
356 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
357 if (total_size > get_bcc(&pSMB->hdr) ||
358 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
363 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
364 sizeof(struct smb_t2_rsp) + 16);
368 static inline void inc_rfc1001_len(void *pSMB, int count)
370 struct smb_hdr *hdr = (struct smb_hdr *)pSMB;
372 be32_add_cpu(&hdr->smb_buf_length, count);
376 CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
379 NEGOTIATE_RSP *pSMBr;
383 struct TCP_Server_Info *server;
385 unsigned int secFlags;
388 server = ses->server;
393 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
394 (void **) &pSMB, (void **) &pSMBr);
398 /* if any of auth flags (ie not sign or seal) are overriden use them */
399 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
400 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
401 else /* if override flags set only sign/seal OR them with global auth */
402 secFlags = global_secflags | ses->overrideSecFlg;
404 cFYI(1, "secFlags 0x%x", secFlags);
406 pSMB->hdr.Mid = GetNextMid(server);
407 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
409 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
410 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
411 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
412 cFYI(1, "Kerberos only mechanism, enable extended security");
413 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
414 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
415 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
416 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
417 cFYI(1, "NTLMSSP only mechanism, enable extended security");
418 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
422 for (i = 0; i < CIFS_NUM_PROT; i++) {
423 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
424 count += strlen(protocols[i].name) + 1;
425 /* null at end of source and target buffers anyway */
427 inc_rfc1001_len(pSMB, count);
428 pSMB->ByteCount = cpu_to_le16(count);
430 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
431 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
435 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
436 cFYI(1, "Dialect: %d", server->dialect);
437 /* Check wct = 1 error case */
438 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
439 /* core returns wct = 1, but we do not ask for core - otherwise
440 small wct just comes when dialect index is -1 indicating we
441 could not negotiate a common dialect */
444 #ifdef CONFIG_CIFS_WEAK_PW_HASH
445 } else if ((pSMBr->hdr.WordCount == 13)
446 && ((server->dialect == LANMAN_PROT)
447 || (server->dialect == LANMAN2_PROT))) {
449 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
451 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
452 (secFlags & CIFSSEC_MAY_PLNTXT))
453 server->secType = LANMAN;
455 cERROR(1, "mount failed weak security disabled"
456 " in /proc/fs/cifs/SecurityFlags");
460 server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
461 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
462 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
463 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
464 /* even though we do not use raw we might as well set this
465 accurately, in case we ever find a need for it */
466 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
467 server->max_rw = 0xFF00;
468 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
470 server->max_rw = 0;/* do not need to use raw anyway */
471 server->capabilities = CAP_MPX_MODE;
473 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
475 /* OS/2 often does not set timezone therefore
476 * we must use server time to calc time zone.
477 * Could deviate slightly from the right zone.
478 * Smallest defined timezone difference is 15 minutes
479 * (i.e. Nepal). Rounding up/down is done to match
482 int val, seconds, remain, result;
483 struct timespec ts, utc;
485 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
486 rsp->SrvTime.Time, 0);
487 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
488 (int)ts.tv_sec, (int)utc.tv_sec,
489 (int)(utc.tv_sec - ts.tv_sec));
490 val = (int)(utc.tv_sec - ts.tv_sec);
492 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
493 remain = seconds % MIN_TZ_ADJ;
494 if (remain >= (MIN_TZ_ADJ / 2))
495 result += MIN_TZ_ADJ;
498 server->timeAdj = result;
500 server->timeAdj = (int)tmp;
501 server->timeAdj *= 60; /* also in seconds */
503 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
506 /* BB get server time for time conversions and add
507 code to use it and timezone since this is not UTC */
509 if (rsp->EncryptionKeyLength ==
510 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
511 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
512 CIFS_CRYPTO_KEY_SIZE);
513 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
514 rc = -EIO; /* need cryptkey unless plain text */
518 cFYI(1, "LANMAN negotiated");
519 /* we will not end up setting signing flags - as no signing
520 was in LANMAN and server did not return the flags on */
522 #else /* weak security disabled */
523 } else if (pSMBr->hdr.WordCount == 13) {
524 cERROR(1, "mount failed, cifs module not built "
525 "with CIFS_WEAK_PW_HASH support");
527 #endif /* WEAK_PW_HASH */
529 } else if (pSMBr->hdr.WordCount != 17) {
534 /* else wct == 17 NTLM */
535 server->sec_mode = pSMBr->SecurityMode;
536 if ((server->sec_mode & SECMODE_USER) == 0)
537 cFYI(1, "share mode security");
539 if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
540 #ifdef CONFIG_CIFS_WEAK_PW_HASH
541 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
542 #endif /* CIFS_WEAK_PW_HASH */
543 cERROR(1, "Server requests plain text password"
544 " but client support disabled");
546 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
547 server->secType = NTLMv2;
548 else if (secFlags & CIFSSEC_MAY_NTLM)
549 server->secType = NTLM;
550 else if (secFlags & CIFSSEC_MAY_NTLMV2)
551 server->secType = NTLMv2;
552 else if (secFlags & CIFSSEC_MAY_KRB5)
553 server->secType = Kerberos;
554 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
555 server->secType = RawNTLMSSP;
556 else if (secFlags & CIFSSEC_MAY_LANMAN)
557 server->secType = LANMAN;
560 cERROR(1, "Invalid security type");
563 /* else ... any others ...? */
565 /* one byte, so no need to convert this or EncryptionKeyLen from
567 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
568 /* probably no need to store and check maxvcs */
569 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
570 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
571 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
572 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
573 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
574 server->timeAdj *= 60;
575 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
576 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
577 CIFS_CRYPTO_KEY_SIZE);
578 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
579 server->capabilities & CAP_EXTENDED_SECURITY) &&
580 (pSMBr->EncryptionKeyLength == 0)) {
581 /* decode security blob */
582 count = get_bcc(&pSMBr->hdr);
587 spin_lock(&cifs_tcp_ses_lock);
588 if (server->srv_count > 1) {
589 spin_unlock(&cifs_tcp_ses_lock);
590 if (memcmp(server->server_GUID,
591 pSMBr->u.extended_response.
593 cFYI(1, "server UID changed");
594 memcpy(server->server_GUID,
595 pSMBr->u.extended_response.GUID,
599 spin_unlock(&cifs_tcp_ses_lock);
600 memcpy(server->server_GUID,
601 pSMBr->u.extended_response.GUID, 16);
605 server->secType = RawNTLMSSP;
607 rc = decode_negTokenInit(pSMBr->u.extended_response.
608 SecurityBlob, count - 16,
614 if (server->secType == Kerberos) {
615 if (!server->sec_kerberos &&
616 !server->sec_mskerberos)
618 } else if (server->secType == RawNTLMSSP) {
619 if (!server->sec_ntlmssp)
624 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
625 rc = -EIO; /* no crypt key only if plain text pwd */
628 server->capabilities &= ~CAP_EXTENDED_SECURITY;
630 #ifdef CONFIG_CIFS_WEAK_PW_HASH
633 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
634 /* MUST_SIGN already includes the MAY_SIGN FLAG
635 so if this is zero it means that signing is disabled */
636 cFYI(1, "Signing disabled");
637 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
638 cERROR(1, "Server requires "
639 "packet signing to be enabled in "
640 "/proc/fs/cifs/SecurityFlags.");
644 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
645 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
646 /* signing required */
647 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
648 if ((server->sec_mode &
649 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
650 cERROR(1, "signing required but server lacks support");
653 server->sec_mode |= SECMODE_SIGN_REQUIRED;
655 /* signing optional ie CIFSSEC_MAY_SIGN */
656 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
658 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
662 cifs_buf_release(pSMB);
664 cFYI(1, "negprot rc %d", rc);
669 CIFSSMBTDis(const int xid, struct cifs_tcon *tcon)
671 struct smb_hdr *smb_buffer;
674 cFYI(1, "In tree disconnect");
676 /* BB: do we need to check this? These should never be NULL. */
677 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
681 * No need to return error on this operation if tid invalidated and
682 * closed on server already e.g. due to tcp session crashing. Also,
683 * the tcon is no longer on the list, so no need to take lock before
686 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
689 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
690 (void **)&smb_buffer);
694 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
696 cFYI(1, "Tree disconnect failed %d", rc);
698 /* No need to return error on this operation if tid invalidated and
699 closed on server already e.g. due to tcp session crashing */
707 * This is a no-op for now. We're not really interested in the reply, but
708 * rather in the fact that the server sent one and that server->lstrp
711 * FIXME: maybe we should consider checking that the reply matches request?
714 cifs_echo_callback(struct mid_q_entry *mid)
716 struct TCP_Server_Info *server = mid->callback_data;
718 DeleteMidQEntry(mid);
719 atomic_dec(&server->inFlight);
720 wake_up(&server->request_q);
724 CIFSSMBEcho(struct TCP_Server_Info *server)
730 cFYI(1, "In echo request");
732 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
736 /* set up echo request */
737 smb->hdr.Tid = 0xffff;
738 smb->hdr.WordCount = 1;
739 put_unaligned_le16(1, &smb->EchoCount);
740 put_bcc(1, &smb->hdr);
742 inc_rfc1001_len(smb, 3);
744 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
746 rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
749 cFYI(1, "Echo request failed: %d", rc);
751 cifs_small_buf_release(smb);
757 CIFSSMBLogoff(const int xid, struct cifs_ses *ses)
759 LOGOFF_ANDX_REQ *pSMB;
762 cFYI(1, "In SMBLogoff for session disconnect");
765 * BB: do we need to check validity of ses and server? They should
766 * always be valid since we have an active reference. If not, that
767 * should probably be a BUG()
769 if (!ses || !ses->server)
772 mutex_lock(&ses->session_mutex);
773 if (ses->need_reconnect)
774 goto session_already_dead; /* no need to send SMBlogoff if uid
775 already closed due to reconnect */
776 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
778 mutex_unlock(&ses->session_mutex);
782 pSMB->hdr.Mid = GetNextMid(ses->server);
784 if (ses->server->sec_mode &
785 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
786 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
788 pSMB->hdr.Uid = ses->Suid;
790 pSMB->AndXCommand = 0xFF;
791 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
792 session_already_dead:
793 mutex_unlock(&ses->session_mutex);
795 /* if session dead then we do not need to do ulogoff,
796 since server closed smb session, no sense reporting
804 CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
805 __u16 type, const struct nls_table *nls_codepage, int remap)
807 TRANSACTION2_SPI_REQ *pSMB = NULL;
808 TRANSACTION2_SPI_RSP *pSMBr = NULL;
809 struct unlink_psx_rq *pRqD;
812 int bytes_returned = 0;
813 __u16 params, param_offset, offset, byte_count;
815 cFYI(1, "In POSIX delete");
817 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
822 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
824 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
825 PATH_MAX, nls_codepage, remap);
826 name_len++; /* trailing null */
828 } else { /* BB add path length overrun check */
829 name_len = strnlen(fileName, PATH_MAX);
830 name_len++; /* trailing null */
831 strncpy(pSMB->FileName, fileName, name_len);
834 params = 6 + name_len;
835 pSMB->MaxParameterCount = cpu_to_le16(2);
836 pSMB->MaxDataCount = 0; /* BB double check this with jra */
837 pSMB->MaxSetupCount = 0;
842 param_offset = offsetof(struct smb_com_transaction2_spi_req,
843 InformationLevel) - 4;
844 offset = param_offset + params;
846 /* Setup pointer to Request Data (inode type) */
847 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
848 pRqD->type = cpu_to_le16(type);
849 pSMB->ParameterOffset = cpu_to_le16(param_offset);
850 pSMB->DataOffset = cpu_to_le16(offset);
851 pSMB->SetupCount = 1;
853 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
854 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
856 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
857 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
858 pSMB->ParameterCount = cpu_to_le16(params);
859 pSMB->TotalParameterCount = pSMB->ParameterCount;
860 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
862 inc_rfc1001_len(pSMB, byte_count);
863 pSMB->ByteCount = cpu_to_le16(byte_count);
864 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
865 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
867 cFYI(1, "Posix delete returned %d", rc);
868 cifs_buf_release(pSMB);
870 cifs_stats_inc(&tcon->num_deletes);
879 CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
880 const struct nls_table *nls_codepage, int remap)
882 DELETE_FILE_REQ *pSMB = NULL;
883 DELETE_FILE_RSP *pSMBr = NULL;
889 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
894 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
896 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
897 PATH_MAX, nls_codepage, remap);
898 name_len++; /* trailing null */
900 } else { /* BB improve check for buffer overruns BB */
901 name_len = strnlen(fileName, PATH_MAX);
902 name_len++; /* trailing null */
903 strncpy(pSMB->fileName, fileName, name_len);
905 pSMB->SearchAttributes =
906 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
907 pSMB->BufferFormat = 0x04;
908 inc_rfc1001_len(pSMB, name_len + 1);
909 pSMB->ByteCount = cpu_to_le16(name_len + 1);
910 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
911 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
912 cifs_stats_inc(&tcon->num_deletes);
914 cFYI(1, "Error in RMFile = %d", rc);
916 cifs_buf_release(pSMB);
924 CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName,
925 const struct nls_table *nls_codepage, int remap)
927 DELETE_DIRECTORY_REQ *pSMB = NULL;
928 DELETE_DIRECTORY_RSP *pSMBr = NULL;
933 cFYI(1, "In CIFSSMBRmDir");
935 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
941 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
942 PATH_MAX, nls_codepage, remap);
943 name_len++; /* trailing null */
945 } else { /* BB improve check for buffer overruns BB */
946 name_len = strnlen(dirName, PATH_MAX);
947 name_len++; /* trailing null */
948 strncpy(pSMB->DirName, dirName, name_len);
951 pSMB->BufferFormat = 0x04;
952 inc_rfc1001_len(pSMB, name_len + 1);
953 pSMB->ByteCount = cpu_to_le16(name_len + 1);
954 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
955 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
956 cifs_stats_inc(&tcon->num_rmdirs);
958 cFYI(1, "Error in RMDir = %d", rc);
960 cifs_buf_release(pSMB);
967 CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
968 const char *name, const struct nls_table *nls_codepage, int remap)
971 CREATE_DIRECTORY_REQ *pSMB = NULL;
972 CREATE_DIRECTORY_RSP *pSMBr = NULL;
976 cFYI(1, "In CIFSSMBMkDir");
978 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
983 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
984 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
985 PATH_MAX, nls_codepage, remap);
986 name_len++; /* trailing null */
988 } else { /* BB improve check for buffer overruns BB */
989 name_len = strnlen(name, PATH_MAX);
990 name_len++; /* trailing null */
991 strncpy(pSMB->DirName, name, name_len);
994 pSMB->BufferFormat = 0x04;
995 inc_rfc1001_len(pSMB, name_len + 1);
996 pSMB->ByteCount = cpu_to_le16(name_len + 1);
997 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
998 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
999 cifs_stats_inc(&tcon->num_mkdirs);
1001 cFYI(1, "Error in Mkdir = %d", rc);
1003 cifs_buf_release(pSMB);
1010 CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags,
1011 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1012 __u32 *pOplock, const char *name,
1013 const struct nls_table *nls_codepage, int remap)
1015 TRANSACTION2_SPI_REQ *pSMB = NULL;
1016 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1019 int bytes_returned = 0;
1020 __u16 params, param_offset, offset, byte_count, count;
1021 OPEN_PSX_REQ *pdata;
1022 OPEN_PSX_RSP *psx_rsp;
1024 cFYI(1, "In POSIX Create");
1026 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1031 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1033 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1034 PATH_MAX, nls_codepage, remap);
1035 name_len++; /* trailing null */
1037 } else { /* BB improve the check for buffer overruns BB */
1038 name_len = strnlen(name, PATH_MAX);
1039 name_len++; /* trailing null */
1040 strncpy(pSMB->FileName, name, name_len);
1043 params = 6 + name_len;
1044 count = sizeof(OPEN_PSX_REQ);
1045 pSMB->MaxParameterCount = cpu_to_le16(2);
1046 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1047 pSMB->MaxSetupCount = 0;
1051 pSMB->Reserved2 = 0;
1052 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1053 InformationLevel) - 4;
1054 offset = param_offset + params;
1055 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1056 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1057 pdata->Permissions = cpu_to_le64(mode);
1058 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1059 pdata->OpenFlags = cpu_to_le32(*pOplock);
1060 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1061 pSMB->DataOffset = cpu_to_le16(offset);
1062 pSMB->SetupCount = 1;
1063 pSMB->Reserved3 = 0;
1064 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1065 byte_count = 3 /* pad */ + params + count;
1067 pSMB->DataCount = cpu_to_le16(count);
1068 pSMB->ParameterCount = cpu_to_le16(params);
1069 pSMB->TotalDataCount = pSMB->DataCount;
1070 pSMB->TotalParameterCount = pSMB->ParameterCount;
1071 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1072 pSMB->Reserved4 = 0;
1073 inc_rfc1001_len(pSMB, byte_count);
1074 pSMB->ByteCount = cpu_to_le16(byte_count);
1075 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1076 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1078 cFYI(1, "Posix create returned %d", rc);
1079 goto psx_create_err;
1082 cFYI(1, "copying inode info");
1083 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1085 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1086 rc = -EIO; /* bad smb */
1087 goto psx_create_err;
1090 /* copy return information to pRetData */
1091 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1092 + le16_to_cpu(pSMBr->t2.DataOffset));
1094 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1096 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1097 /* Let caller know file was created so we can set the mode. */
1098 /* Do we care about the CreateAction in any other cases? */
1099 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1100 *pOplock |= CIFS_CREATE_ACTION;
1101 /* check to make sure response data is there */
1102 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1103 pRetData->Type = cpu_to_le32(-1); /* unknown */
1104 cFYI(DBG2, "unknown type");
1106 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1107 + sizeof(FILE_UNIX_BASIC_INFO)) {
1108 cERROR(1, "Open response data too small");
1109 pRetData->Type = cpu_to_le32(-1);
1110 goto psx_create_err;
1112 memcpy((char *) pRetData,
1113 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1114 sizeof(FILE_UNIX_BASIC_INFO));
1118 cifs_buf_release(pSMB);
1120 if (posix_flags & SMB_O_DIRECTORY)
1121 cifs_stats_inc(&tcon->num_posixmkdirs);
1123 cifs_stats_inc(&tcon->num_posixopens);
1131 static __u16 convert_disposition(int disposition)
1135 switch (disposition) {
1136 case FILE_SUPERSEDE:
1137 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1140 ofun = SMBOPEN_OAPPEND;
1143 ofun = SMBOPEN_OCREATE;
1146 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1148 case FILE_OVERWRITE:
1149 ofun = SMBOPEN_OTRUNC;
1151 case FILE_OVERWRITE_IF:
1152 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1155 cFYI(1, "unknown disposition %d", disposition);
1156 ofun = SMBOPEN_OAPPEND; /* regular open */
1162 access_flags_to_smbopen_mode(const int access_flags)
1164 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1166 if (masked_flags == GENERIC_READ)
1167 return SMBOPEN_READ;
1168 else if (masked_flags == GENERIC_WRITE)
1169 return SMBOPEN_WRITE;
1171 /* just go for read/write */
1172 return SMBOPEN_READWRITE;
1176 SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
1177 const char *fileName, const int openDisposition,
1178 const int access_flags, const int create_options, __u16 *netfid,
1179 int *pOplock, FILE_ALL_INFO *pfile_info,
1180 const struct nls_table *nls_codepage, int remap)
1183 OPENX_REQ *pSMB = NULL;
1184 OPENX_RSP *pSMBr = NULL;
1190 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1195 pSMB->AndXCommand = 0xFF; /* none */
1197 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1198 count = 1; /* account for one byte pad to word boundary */
1200 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1201 fileName, PATH_MAX, nls_codepage, remap);
1202 name_len++; /* trailing null */
1204 } else { /* BB improve check for buffer overruns BB */
1205 count = 0; /* no pad */
1206 name_len = strnlen(fileName, PATH_MAX);
1207 name_len++; /* trailing null */
1208 strncpy(pSMB->fileName, fileName, name_len);
1210 if (*pOplock & REQ_OPLOCK)
1211 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1212 else if (*pOplock & REQ_BATCHOPLOCK)
1213 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1215 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1216 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1217 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1218 /* set file as system file if special file such
1219 as fifo and server expecting SFU style and
1220 no Unix extensions */
1222 if (create_options & CREATE_OPTION_SPECIAL)
1223 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1224 else /* BB FIXME BB */
1225 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1227 if (create_options & CREATE_OPTION_READONLY)
1228 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1231 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1232 CREATE_OPTIONS_MASK); */
1233 /* BB FIXME END BB */
1235 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1236 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1238 inc_rfc1001_len(pSMB, count);
1240 pSMB->ByteCount = cpu_to_le16(count);
1241 /* long_op set to 1 to allow for oplock break timeouts */
1242 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1243 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1244 cifs_stats_inc(&tcon->num_opens);
1246 cFYI(1, "Error in Open = %d", rc);
1248 /* BB verify if wct == 15 */
1250 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1252 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1253 /* Let caller know file was created so we can set the mode. */
1254 /* Do we care about the CreateAction in any other cases? */
1256 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1257 *pOplock |= CIFS_CREATE_ACTION; */
1261 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1262 pfile_info->LastAccessTime = 0; /* BB fixme */
1263 pfile_info->LastWriteTime = 0; /* BB fixme */
1264 pfile_info->ChangeTime = 0; /* BB fixme */
1265 pfile_info->Attributes =
1266 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1267 /* the file_info buf is endian converted by caller */
1268 pfile_info->AllocationSize =
1269 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1270 pfile_info->EndOfFile = pfile_info->AllocationSize;
1271 pfile_info->NumberOfLinks = cpu_to_le32(1);
1272 pfile_info->DeletePending = 0;
1276 cifs_buf_release(pSMB);
1283 CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
1284 const char *fileName, const int openDisposition,
1285 const int access_flags, const int create_options, __u16 *netfid,
1286 int *pOplock, FILE_ALL_INFO *pfile_info,
1287 const struct nls_table *nls_codepage, int remap)
1290 OPEN_REQ *pSMB = NULL;
1291 OPEN_RSP *pSMBr = NULL;
1297 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1302 pSMB->AndXCommand = 0xFF; /* none */
1304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1305 count = 1; /* account for one byte pad to word boundary */
1307 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1308 fileName, PATH_MAX, nls_codepage, remap);
1309 name_len++; /* trailing null */
1311 pSMB->NameLength = cpu_to_le16(name_len);
1312 } else { /* BB improve check for buffer overruns BB */
1313 count = 0; /* no pad */
1314 name_len = strnlen(fileName, PATH_MAX);
1315 name_len++; /* trailing null */
1316 pSMB->NameLength = cpu_to_le16(name_len);
1317 strncpy(pSMB->fileName, fileName, name_len);
1319 if (*pOplock & REQ_OPLOCK)
1320 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1321 else if (*pOplock & REQ_BATCHOPLOCK)
1322 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1323 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1324 pSMB->AllocationSize = 0;
1325 /* set file as system file if special file such
1326 as fifo and server expecting SFU style and
1327 no Unix extensions */
1328 if (create_options & CREATE_OPTION_SPECIAL)
1329 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1331 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1333 /* XP does not handle ATTR_POSIX_SEMANTICS */
1334 /* but it helps speed up case sensitive checks for other
1335 servers such as Samba */
1336 if (tcon->ses->capabilities & CAP_UNIX)
1337 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1339 if (create_options & CREATE_OPTION_READONLY)
1340 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1342 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1343 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1344 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1345 /* BB Expirement with various impersonation levels and verify */
1346 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1347 pSMB->SecurityFlags =
1348 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1351 inc_rfc1001_len(pSMB, count);
1353 pSMB->ByteCount = cpu_to_le16(count);
1354 /* long_op set to 1 to allow for oplock break timeouts */
1355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1356 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1357 cifs_stats_inc(&tcon->num_opens);
1359 cFYI(1, "Error in Open = %d", rc);
1361 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1362 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1363 /* Let caller know file was created so we can set the mode. */
1364 /* Do we care about the CreateAction in any other cases? */
1365 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1366 *pOplock |= CIFS_CREATE_ACTION;
1368 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1369 36 /* CreationTime to Attributes */);
1370 /* the file_info buf is endian converted by caller */
1371 pfile_info->AllocationSize = pSMBr->AllocationSize;
1372 pfile_info->EndOfFile = pSMBr->EndOfFile;
1373 pfile_info->NumberOfLinks = cpu_to_le32(1);
1374 pfile_info->DeletePending = 0;
1378 cifs_buf_release(pSMB);
1384 struct cifs_readdata *
1385 cifs_readdata_alloc(unsigned int nr_pages)
1387 struct cifs_readdata *rdata;
1389 /* readdata + 1 kvec for each page */
1390 rdata = kzalloc(sizeof(*rdata) +
1391 sizeof(struct kvec) * nr_pages, GFP_KERNEL);
1392 if (rdata != NULL) {
1393 INIT_WORK(&rdata->work, cifs_readv_complete);
1394 INIT_LIST_HEAD(&rdata->pages);
1400 cifs_readdata_free(struct cifs_readdata *rdata)
1402 cifsFileInfo_put(rdata->cfile);
1407 * Discard any remaining data in the current SMB. To do this, we borrow the
1411 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1413 READ_RSP *rsp = (READ_RSP *)server->smallbuf;
1414 unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length);
1415 int remaining = rfclen + 4 - server->total_read;
1416 struct cifs_readdata *rdata = mid->callback_data;
1418 while (remaining > 0) {
1421 length = cifs_read_from_socket(server, server->bigbuf,
1422 min_t(unsigned int, remaining,
1423 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE));
1426 server->total_read += length;
1427 remaining -= length;
1430 dequeue_mid(mid, rdata->result);
1435 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1438 unsigned int data_offset, remaining, data_len;
1439 struct cifs_readdata *rdata = mid->callback_data;
1440 READ_RSP *rsp = (READ_RSP *)server->smallbuf;
1441 unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length) + 4;
1444 struct page *page, *tpage;
1446 cFYI(1, "%s: mid=%u offset=%llu bytes=%u", __func__,
1447 mid->mid, rdata->offset, rdata->bytes);
1450 * read the rest of READ_RSP header (sans Data array), or whatever we
1451 * can if there's not enough data. At this point, we've read down to
1454 len = min_t(unsigned int, rfclen, sizeof(*rsp)) -
1455 sizeof(struct smb_hdr) + 1;
1457 rdata->iov[0].iov_base = server->smallbuf + sizeof(struct smb_hdr) - 1;
1458 rdata->iov[0].iov_len = len;
1460 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1463 server->total_read += length;
1465 /* Was the SMB read successful? */
1466 rdata->result = map_smb_to_linux_error(&rsp->hdr, false);
1467 if (rdata->result != 0) {
1468 cFYI(1, "%s: server returned error %d", __func__,
1470 return cifs_readv_discard(server, mid);
1473 /* Is there enough to get to the rest of the READ_RSP header? */
1474 if (server->total_read < sizeof(READ_RSP)) {
1475 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1476 __func__, server->total_read, sizeof(READ_RSP));
1477 rdata->result = -EIO;
1478 return cifs_readv_discard(server, mid);
1481 data_offset = le16_to_cpu(rsp->DataOffset) + 4;
1482 if (data_offset < server->total_read) {
1484 * win2k8 sometimes sends an offset of 0 when the read
1485 * is beyond the EOF. Treat it as if the data starts just after
1488 cFYI(1, "%s: data offset (%u) inside read response header",
1489 __func__, data_offset);
1490 data_offset = server->total_read;
1491 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1492 /* data_offset is beyond the end of smallbuf */
1493 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1494 __func__, data_offset);
1495 rdata->result = -EIO;
1496 return cifs_readv_discard(server, mid);
1499 cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1500 server->total_read, data_offset);
1502 len = data_offset - server->total_read;
1504 /* read any junk before data into the rest of smallbuf */
1505 rdata->iov[0].iov_base = server->smallbuf + server->total_read;
1506 rdata->iov[0].iov_len = len;
1507 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1510 server->total_read += length;
1513 /* set up first iov for signature check */
1514 rdata->iov[0].iov_base = server->smallbuf;
1515 rdata->iov[0].iov_len = server->total_read;
1516 cFYI(1, "0: iov_base=%p iov_len=%zu",
1517 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1519 /* how much data is in the response? */
1520 data_len = le16_to_cpu(rsp->DataLengthHigh) << 16;
1521 data_len += le16_to_cpu(rsp->DataLength);
1522 if (data_offset + data_len > rfclen) {
1523 /* data_len is corrupt -- discard frame */
1524 rdata->result = -EIO;
1525 return cifs_readv_discard(server, mid);
1528 /* marshal up the page array */
1530 remaining = data_len;
1533 /* determine the eof that the server (probably) has */
1534 eof = CIFS_I(rdata->mapping->host)->server_eof;
1535 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
1536 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
1538 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1539 if (remaining >= PAGE_CACHE_SIZE) {
1540 /* enough data to fill the page */
1541 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1542 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
1543 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1544 rdata->nr_iov, page->index,
1545 rdata->iov[rdata->nr_iov].iov_base,
1546 rdata->iov[rdata->nr_iov].iov_len);
1548 len += PAGE_CACHE_SIZE;
1549 remaining -= PAGE_CACHE_SIZE;
1550 } else if (remaining > 0) {
1551 /* enough for partial page, fill and zero the rest */
1552 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1553 rdata->iov[rdata->nr_iov].iov_len = remaining;
1554 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1555 rdata->nr_iov, page->index,
1556 rdata->iov[rdata->nr_iov].iov_base,
1557 rdata->iov[rdata->nr_iov].iov_len);
1558 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
1559 '\0', PAGE_CACHE_SIZE - remaining);
1563 } else if (page->index > eof_index) {
1565 * The VFS will not try to do readahead past the
1566 * i_size, but it's possible that we have outstanding
1567 * writes with gaps in the middle and the i_size hasn't
1568 * caught up yet. Populate those with zeroed out pages
1569 * to prevent the VFS from repeatedly attempting to
1570 * fill them until the writes are flushed.
1572 zero_user(page, 0, PAGE_CACHE_SIZE);
1573 list_del(&page->lru);
1574 lru_cache_add_file(page);
1575 flush_dcache_page(page);
1576 SetPageUptodate(page);
1578 page_cache_release(page);
1580 /* no need to hold page hostage */
1581 list_del(&page->lru);
1582 lru_cache_add_file(page);
1584 page_cache_release(page);
1588 /* issue the read if we have any iovecs left to fill */
1589 if (rdata->nr_iov > 1) {
1590 length = cifs_readv_from_socket(server, &rdata->iov[1],
1591 rdata->nr_iov - 1, len);
1594 server->total_read += length;
1599 rdata->bytes = length;
1601 cFYI(1, "total_read=%u rfclen=%u remaining=%u", server->total_read,
1604 /* discard anything left over */
1605 if (server->total_read < rfclen)
1606 return cifs_readv_discard(server, mid);
1608 dequeue_mid(mid, false);
1613 cifs_readv_complete(struct work_struct *work)
1615 struct cifs_readdata *rdata = container_of(work,
1616 struct cifs_readdata, work);
1617 struct page *page, *tpage;
1619 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1620 list_del(&page->lru);
1621 lru_cache_add_file(page);
1623 if (rdata->result == 0) {
1625 flush_dcache_page(page);
1626 SetPageUptodate(page);
1631 if (rdata->result == 0)
1632 cifs_readpage_to_fscache(rdata->mapping->host, page);
1634 page_cache_release(page);
1636 cifs_readdata_free(rdata);
1640 cifs_readv_callback(struct mid_q_entry *mid)
1642 struct cifs_readdata *rdata = mid->callback_data;
1643 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1644 struct TCP_Server_Info *server = tcon->ses->server;
1646 cFYI(1, "%s: mid=%u state=%d result=%d bytes=%u", __func__,
1647 mid->mid, mid->midState, rdata->result, rdata->bytes);
1649 switch (mid->midState) {
1650 case MID_RESPONSE_RECEIVED:
1651 /* result already set, check signature */
1652 if (server->sec_mode &
1653 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1654 if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1655 server, mid->sequence_number + 1))
1656 cERROR(1, "Unexpected SMB signature");
1658 /* FIXME: should this be counted toward the initiating task? */
1659 task_io_account_read(rdata->bytes);
1660 cifs_stats_bytes_read(tcon, rdata->bytes);
1662 case MID_REQUEST_SUBMITTED:
1663 case MID_RETRY_NEEDED:
1664 rdata->result = -EAGAIN;
1667 rdata->result = -EIO;
1670 queue_work(system_nrt_wq, &rdata->work);
1671 DeleteMidQEntry(mid);
1672 atomic_dec(&server->inFlight);
1673 wake_up(&server->request_q);
1676 /* cifs_async_readv - send an async write, and set up mid to handle result */
1678 cifs_async_readv(struct cifs_readdata *rdata)
1681 READ_REQ *smb = NULL;
1683 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1685 cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1686 rdata->offset, rdata->bytes);
1688 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1691 wct = 10; /* old style read */
1692 if ((rdata->offset >> 32) > 0) {
1693 /* can not handle this big offset for old */
1698 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1702 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1703 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1705 smb->AndXCommand = 0xFF; /* none */
1706 smb->Fid = rdata->cfile->netfid;
1707 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1709 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1711 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1712 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1716 /* old style read */
1717 struct smb_com_readx_req *smbr =
1718 (struct smb_com_readx_req *)smb;
1719 smbr->ByteCount = 0;
1722 /* 4 for RFC1001 length + 1 for BCC */
1723 rdata->iov[0].iov_base = smb;
1724 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1726 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1727 cifs_readv_receive, cifs_readv_callback,
1731 cifs_stats_inc(&tcon->num_reads);
1733 cifs_small_buf_release(smb);
1738 CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1739 char **buf, int *pbuf_type)
1742 READ_REQ *pSMB = NULL;
1743 READ_RSP *pSMBr = NULL;
1744 char *pReadData = NULL;
1746 int resp_buf_type = 0;
1748 __u32 pid = io_parms->pid;
1749 __u16 netfid = io_parms->netfid;
1750 __u64 offset = io_parms->offset;
1751 struct cifs_tcon *tcon = io_parms->tcon;
1752 unsigned int count = io_parms->length;
1754 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1755 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1758 wct = 10; /* old style read */
1759 if ((offset >> 32) > 0) {
1760 /* can not handle this big offset for old */
1766 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1770 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1771 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1773 /* tcon and ses pointer are checked in smb_init */
1774 if (tcon->ses->server == NULL)
1775 return -ECONNABORTED;
1777 pSMB->AndXCommand = 0xFF; /* none */
1779 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1781 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1783 pSMB->Remaining = 0;
1784 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1785 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1787 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1789 /* old style read */
1790 struct smb_com_readx_req *pSMBW =
1791 (struct smb_com_readx_req *)pSMB;
1792 pSMBW->ByteCount = 0;
1795 iov[0].iov_base = (char *)pSMB;
1796 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1797 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1798 &resp_buf_type, CIFS_LOG_ERROR);
1799 cifs_stats_inc(&tcon->num_reads);
1800 pSMBr = (READ_RSP *)iov[0].iov_base;
1802 cERROR(1, "Send error in read = %d", rc);
1804 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1805 data_length = data_length << 16;
1806 data_length += le16_to_cpu(pSMBr->DataLength);
1807 *nbytes = data_length;
1809 /*check that DataLength would not go beyond end of SMB */
1810 if ((data_length > CIFSMaxBufSize)
1811 || (data_length > count)) {
1812 cFYI(1, "bad length %d for count %d",
1813 data_length, count);
1817 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1818 le16_to_cpu(pSMBr->DataOffset);
1819 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1820 cERROR(1, "Faulting on read rc = %d",rc);
1822 }*/ /* can not use copy_to_user when using page cache*/
1824 memcpy(*buf, pReadData, data_length);
1828 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1830 if (resp_buf_type == CIFS_SMALL_BUFFER)
1831 cifs_small_buf_release(iov[0].iov_base);
1832 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1833 cifs_buf_release(iov[0].iov_base);
1834 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1835 /* return buffer to caller to free */
1836 *buf = iov[0].iov_base;
1837 if (resp_buf_type == CIFS_SMALL_BUFFER)
1838 *pbuf_type = CIFS_SMALL_BUFFER;
1839 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1840 *pbuf_type = CIFS_LARGE_BUFFER;
1841 } /* else no valid buffer on return - leave as null */
1843 /* Note: On -EAGAIN error only caller can retry on handle based calls
1844 since file handle passed in no longer valid */
1850 CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1851 unsigned int *nbytes, const char *buf,
1852 const char __user *ubuf, const int long_op)
1855 WRITE_REQ *pSMB = NULL;
1856 WRITE_RSP *pSMBr = NULL;
1857 int bytes_returned, wct;
1860 __u32 pid = io_parms->pid;
1861 __u16 netfid = io_parms->netfid;
1862 __u64 offset = io_parms->offset;
1863 struct cifs_tcon *tcon = io_parms->tcon;
1864 unsigned int count = io_parms->length;
1868 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1869 if (tcon->ses == NULL)
1870 return -ECONNABORTED;
1872 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1876 if ((offset >> 32) > 0) {
1877 /* can not handle big offset for old srv */
1882 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1887 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1888 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1890 /* tcon and ses pointer are checked in smb_init */
1891 if (tcon->ses->server == NULL)
1892 return -ECONNABORTED;
1894 pSMB->AndXCommand = 0xFF; /* none */
1896 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1898 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1900 pSMB->Reserved = 0xFFFFFFFF;
1901 pSMB->WriteMode = 0;
1902 pSMB->Remaining = 0;
1904 /* Can increase buffer size if buffer is big enough in some cases ie we
1905 can send more if LARGE_WRITE_X capability returned by the server and if
1906 our buffer is big enough or if we convert to iovecs on socket writes
1907 and eliminate the copy to the CIFS buffer */
1908 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1909 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1911 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1915 if (bytes_sent > count)
1918 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1920 memcpy(pSMB->Data, buf, bytes_sent);
1922 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1923 cifs_buf_release(pSMB);
1926 } else if (count != 0) {
1928 cifs_buf_release(pSMB);
1930 } /* else setting file size with write of zero bytes */
1932 byte_count = bytes_sent + 1; /* pad */
1933 else /* wct == 12 */
1934 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1936 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1937 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1938 inc_rfc1001_len(pSMB, byte_count);
1941 pSMB->ByteCount = cpu_to_le16(byte_count);
1942 else { /* old style write has byte count 4 bytes earlier
1944 struct smb_com_writex_req *pSMBW =
1945 (struct smb_com_writex_req *)pSMB;
1946 pSMBW->ByteCount = cpu_to_le16(byte_count);
1949 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1950 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1951 cifs_stats_inc(&tcon->num_writes);
1953 cFYI(1, "Send error in write = %d", rc);
1955 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1956 *nbytes = (*nbytes) << 16;
1957 *nbytes += le16_to_cpu(pSMBr->Count);
1960 * Mask off high 16 bits when bytes written as returned by the
1961 * server is greater than bytes requested by the client. Some
1962 * OS/2 servers are known to set incorrect CountHigh values.
1964 if (*nbytes > count)
1968 cifs_buf_release(pSMB);
1970 /* Note: On -EAGAIN error only caller can retry on handle based calls
1971 since file handle passed in no longer valid */
1977 cifs_writedata_release(struct kref *refcount)
1979 struct cifs_writedata *wdata = container_of(refcount,
1980 struct cifs_writedata, refcount);
1983 cifsFileInfo_put(wdata->cfile);
1989 * Write failed with a retryable error. Resend the write request. It's also
1990 * possible that the page was redirtied so re-clean the page.
1993 cifs_writev_requeue(struct cifs_writedata *wdata)
1996 struct inode *inode = wdata->cfile->dentry->d_inode;
1998 for (i = 0; i < wdata->nr_pages; i++) {
1999 lock_page(wdata->pages[i]);
2000 clear_page_dirty_for_io(wdata->pages[i]);
2004 rc = cifs_async_writev(wdata);
2005 } while (rc == -EAGAIN);
2007 for (i = 0; i < wdata->nr_pages; i++) {
2009 SetPageError(wdata->pages[i]);
2010 unlock_page(wdata->pages[i]);
2013 mapping_set_error(inode->i_mapping, rc);
2014 kref_put(&wdata->refcount, cifs_writedata_release);
2018 cifs_writev_complete(struct work_struct *work)
2020 struct cifs_writedata *wdata = container_of(work,
2021 struct cifs_writedata, work);
2022 struct inode *inode = wdata->cfile->dentry->d_inode;
2025 if (wdata->result == 0) {
2026 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2027 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2029 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2030 return cifs_writev_requeue(wdata);
2032 for (i = 0; i < wdata->nr_pages; i++) {
2033 struct page *page = wdata->pages[i];
2034 if (wdata->result == -EAGAIN)
2035 __set_page_dirty_nobuffers(page);
2036 else if (wdata->result < 0)
2038 end_page_writeback(page);
2039 page_cache_release(page);
2041 if (wdata->result != -EAGAIN)
2042 mapping_set_error(inode->i_mapping, wdata->result);
2043 kref_put(&wdata->refcount, cifs_writedata_release);
2046 struct cifs_writedata *
2047 cifs_writedata_alloc(unsigned int nr_pages)
2049 struct cifs_writedata *wdata;
2051 /* this would overflow */
2052 if (nr_pages == 0) {
2053 cERROR(1, "%s: called with nr_pages == 0!", __func__);
2057 /* writedata + number of page pointers */
2058 wdata = kzalloc(sizeof(*wdata) +
2059 sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
2060 if (wdata != NULL) {
2061 INIT_WORK(&wdata->work, cifs_writev_complete);
2062 kref_init(&wdata->refcount);
2068 * Check the midState and signature on received buffer (if any), and queue the
2069 * workqueue completion task.
2072 cifs_writev_callback(struct mid_q_entry *mid)
2074 struct cifs_writedata *wdata = mid->callback_data;
2075 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2076 unsigned int written;
2077 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2079 switch (mid->midState) {
2080 case MID_RESPONSE_RECEIVED:
2081 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2082 if (wdata->result != 0)
2085 written = le16_to_cpu(smb->CountHigh);
2087 written += le16_to_cpu(smb->Count);
2089 * Mask off high 16 bits when bytes written as returned
2090 * by the server is greater than bytes requested by the
2091 * client. OS/2 servers are known to set incorrect
2094 if (written > wdata->bytes)
2097 if (written < wdata->bytes)
2098 wdata->result = -ENOSPC;
2100 wdata->bytes = written;
2102 case MID_REQUEST_SUBMITTED:
2103 case MID_RETRY_NEEDED:
2104 wdata->result = -EAGAIN;
2107 wdata->result = -EIO;
2111 queue_work(system_nrt_wq, &wdata->work);
2112 DeleteMidQEntry(mid);
2113 atomic_dec(&tcon->ses->server->inFlight);
2114 wake_up(&tcon->ses->server->request_q);
2117 /* cifs_async_writev - send an async write, and set up mid to handle result */
2119 cifs_async_writev(struct cifs_writedata *wdata)
2121 int i, rc = -EACCES;
2122 WRITE_REQ *smb = NULL;
2124 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2125 struct inode *inode = wdata->cfile->dentry->d_inode;
2126 struct kvec *iov = NULL;
2128 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2132 if (wdata->offset >> 32 > 0) {
2133 /* can not handle big offset for old srv */
2138 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2140 goto async_writev_out;
2142 /* 1 iov per page + 1 for header */
2143 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2146 goto async_writev_out;
2149 smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid);
2150 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16));
2152 smb->AndXCommand = 0xFF; /* none */
2153 smb->Fid = wdata->cfile->netfid;
2154 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2156 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2157 smb->Reserved = 0xFFFFFFFF;
2162 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2164 /* 4 for RFC1001 length + 1 for BCC */
2165 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2166 iov[0].iov_base = smb;
2168 /* marshal up the pages into iov array */
2170 for (i = 0; i < wdata->nr_pages; i++) {
2171 iov[i + 1].iov_len = min(inode->i_size -
2172 page_offset(wdata->pages[i]),
2173 (loff_t)PAGE_CACHE_SIZE);
2174 iov[i + 1].iov_base = kmap(wdata->pages[i]);
2175 wdata->bytes += iov[i + 1].iov_len;
2178 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2180 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2181 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2184 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2185 put_bcc(wdata->bytes + 1, &smb->hdr);
2188 struct smb_com_writex_req *smbw =
2189 (struct smb_com_writex_req *)smb;
2190 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2191 put_bcc(wdata->bytes + 5, &smbw->hdr);
2192 iov[0].iov_len += 4; /* pad bigger by four bytes */
2195 kref_get(&wdata->refcount);
2196 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2197 NULL, cifs_writev_callback, wdata, false);
2200 cifs_stats_inc(&tcon->num_writes);
2202 kref_put(&wdata->refcount, cifs_writedata_release);
2204 /* send is done, unmap pages */
2205 for (i = 0; i < wdata->nr_pages; i++)
2206 kunmap(wdata->pages[i]);
2209 cifs_small_buf_release(smb);
2215 CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
2216 unsigned int *nbytes, struct kvec *iov, int n_vec,
2220 WRITE_REQ *pSMB = NULL;
2223 int resp_buf_type = 0;
2224 __u32 pid = io_parms->pid;
2225 __u16 netfid = io_parms->netfid;
2226 __u64 offset = io_parms->offset;
2227 struct cifs_tcon *tcon = io_parms->tcon;
2228 unsigned int count = io_parms->length;
2232 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2234 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2238 if ((offset >> 32) > 0) {
2239 /* can not handle big offset for old srv */
2243 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2247 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2248 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2250 /* tcon and ses pointer are checked in smb_init */
2251 if (tcon->ses->server == NULL)
2252 return -ECONNABORTED;
2254 pSMB->AndXCommand = 0xFF; /* none */
2256 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2258 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2259 pSMB->Reserved = 0xFFFFFFFF;
2260 pSMB->WriteMode = 0;
2261 pSMB->Remaining = 0;
2264 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2266 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2267 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2268 /* header + 1 byte pad */
2269 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2271 inc_rfc1001_len(pSMB, count + 1);
2272 else /* wct == 12 */
2273 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2275 pSMB->ByteCount = cpu_to_le16(count + 1);
2276 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2277 struct smb_com_writex_req *pSMBW =
2278 (struct smb_com_writex_req *)pSMB;
2279 pSMBW->ByteCount = cpu_to_le16(count + 5);
2281 iov[0].iov_base = pSMB;
2283 iov[0].iov_len = smb_hdr_len + 4;
2284 else /* wct == 12 pad bigger by four bytes */
2285 iov[0].iov_len = smb_hdr_len + 8;
2288 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2290 cifs_stats_inc(&tcon->num_writes);
2292 cFYI(1, "Send error Write2 = %d", rc);
2293 } else if (resp_buf_type == 0) {
2294 /* presumably this can not happen, but best to be safe */
2297 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2298 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2299 *nbytes = (*nbytes) << 16;
2300 *nbytes += le16_to_cpu(pSMBr->Count);
2303 * Mask off high 16 bits when bytes written as returned by the
2304 * server is greater than bytes requested by the client. OS/2
2305 * servers are known to set incorrect CountHigh values.
2307 if (*nbytes > count)
2311 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2312 if (resp_buf_type == CIFS_SMALL_BUFFER)
2313 cifs_small_buf_release(iov[0].iov_base);
2314 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2315 cifs_buf_release(iov[0].iov_base);
2317 /* Note: On -EAGAIN error only caller can retry on handle based calls
2318 since file handle passed in no longer valid */
2323 int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
2324 const __u8 lock_type, const __u32 num_unlock,
2325 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2328 LOCK_REQ *pSMB = NULL;
2333 cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2335 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2340 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2341 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2342 pSMB->LockType = lock_type;
2343 pSMB->AndXCommand = 0xFF; /* none */
2344 pSMB->Fid = netfid; /* netfid stays le */
2346 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2347 inc_rfc1001_len(pSMB, count);
2348 pSMB->ByteCount = cpu_to_le16(count);
2350 iov[0].iov_base = (char *)pSMB;
2351 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2352 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2353 iov[1].iov_base = (char *)buf;
2354 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2356 cifs_stats_inc(&tcon->num_locks);
2357 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2359 cFYI(1, "Send error in cifs_lockv = %d", rc);
2365 CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
2366 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2367 const __u64 offset, const __u32 numUnlock,
2368 const __u32 numLock, const __u8 lockType,
2369 const bool waitFlag, const __u8 oplock_level)
2372 LOCK_REQ *pSMB = NULL;
2373 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2378 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2379 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2384 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2385 timeout = CIFS_ASYNC_OP; /* no response expected */
2387 } else if (waitFlag) {
2388 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2389 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2394 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2395 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2396 pSMB->LockType = lockType;
2397 pSMB->OplockLevel = oplock_level;
2398 pSMB->AndXCommand = 0xFF; /* none */
2399 pSMB->Fid = smb_file_id; /* netfid stays le */
2401 if ((numLock != 0) || (numUnlock != 0)) {
2402 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2403 /* BB where to store pid high? */
2404 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2405 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2406 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2407 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2408 count = sizeof(LOCKING_ANDX_RANGE);
2413 inc_rfc1001_len(pSMB, count);
2414 pSMB->ByteCount = cpu_to_le16(count);
2417 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2418 (struct smb_hdr *) pSMB, &bytes_returned);
2419 cifs_small_buf_release(pSMB);
2421 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
2423 /* SMB buffer freed by function above */
2425 cifs_stats_inc(&tcon->num_locks);
2427 cFYI(1, "Send error in Lock = %d", rc);
2429 /* Note: On -EAGAIN error only caller can retry on handle based calls
2430 since file handle passed in no longer valid */
2435 CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
2436 const __u16 smb_file_id, const __u32 netpid, const int get_flag,
2437 const __u64 len, struct file_lock *pLockData,
2438 const __u16 lock_type, const bool waitFlag)
2440 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2441 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2442 struct cifs_posix_lock *parm_data;
2445 int bytes_returned = 0;
2446 int resp_buf_type = 0;
2447 __u16 params, param_offset, offset, byte_count, count;
2450 cFYI(1, "Posix Lock");
2452 if (pLockData == NULL)
2455 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2460 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2463 pSMB->MaxSetupCount = 0;
2466 pSMB->Reserved2 = 0;
2467 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2468 offset = param_offset + params;
2470 count = sizeof(struct cifs_posix_lock);
2471 pSMB->MaxParameterCount = cpu_to_le16(2);
2472 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2473 pSMB->SetupCount = 1;
2474 pSMB->Reserved3 = 0;
2476 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2478 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2479 byte_count = 3 /* pad */ + params + count;
2480 pSMB->DataCount = cpu_to_le16(count);
2481 pSMB->ParameterCount = cpu_to_le16(params);
2482 pSMB->TotalDataCount = pSMB->DataCount;
2483 pSMB->TotalParameterCount = pSMB->ParameterCount;
2484 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2485 parm_data = (struct cifs_posix_lock *)
2486 (((char *) &pSMB->hdr.Protocol) + offset);
2488 parm_data->lock_type = cpu_to_le16(lock_type);
2490 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2491 parm_data->lock_flags = cpu_to_le16(1);
2492 pSMB->Timeout = cpu_to_le32(-1);
2496 parm_data->pid = cpu_to_le32(netpid);
2497 parm_data->start = cpu_to_le64(pLockData->fl_start);
2498 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2500 pSMB->DataOffset = cpu_to_le16(offset);
2501 pSMB->Fid = smb_file_id;
2502 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2503 pSMB->Reserved4 = 0;
2504 inc_rfc1001_len(pSMB, byte_count);
2505 pSMB->ByteCount = cpu_to_le16(byte_count);
2507 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2508 (struct smb_hdr *) pSMBr, &bytes_returned);
2510 iov[0].iov_base = (char *)pSMB;
2511 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2512 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2513 &resp_buf_type, timeout);
2514 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2515 not try to free it twice below on exit */
2516 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2520 cFYI(1, "Send error in Posix Lock = %d", rc);
2521 } else if (get_flag) {
2522 /* lock structure can be returned on get */
2525 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2527 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2528 rc = -EIO; /* bad smb */
2531 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2532 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2533 if (data_count < sizeof(struct cifs_posix_lock)) {
2537 parm_data = (struct cifs_posix_lock *)
2538 ((char *)&pSMBr->hdr.Protocol + data_offset);
2539 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2540 pLockData->fl_type = F_UNLCK;
2542 if (parm_data->lock_type ==
2543 __constant_cpu_to_le16(CIFS_RDLCK))
2544 pLockData->fl_type = F_RDLCK;
2545 else if (parm_data->lock_type ==
2546 __constant_cpu_to_le16(CIFS_WRLCK))
2547 pLockData->fl_type = F_WRLCK;
2549 pLockData->fl_start = le64_to_cpu(parm_data->start);
2550 pLockData->fl_end = pLockData->fl_start +
2551 le64_to_cpu(parm_data->length) - 1;
2552 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2558 cifs_small_buf_release(pSMB);
2560 if (resp_buf_type == CIFS_SMALL_BUFFER)
2561 cifs_small_buf_release(iov[0].iov_base);
2562 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2563 cifs_buf_release(iov[0].iov_base);
2565 /* Note: On -EAGAIN error only caller can retry on handle based calls
2566 since file handle passed in no longer valid */
2573 CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2576 CLOSE_REQ *pSMB = NULL;
2577 cFYI(1, "In CIFSSMBClose");
2579 /* do not retry on dead session on close */
2580 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2586 pSMB->FileID = (__u16) smb_file_id;
2587 pSMB->LastWriteTime = 0xFFFFFFFF;
2588 pSMB->ByteCount = 0;
2589 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2590 cifs_stats_inc(&tcon->num_closes);
2593 /* EINTR is expected when user ctl-c to kill app */
2594 cERROR(1, "Send error in Close = %d", rc);
2598 /* Since session is dead, file will be closed on server already */
2606 CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2609 FLUSH_REQ *pSMB = NULL;
2610 cFYI(1, "In CIFSSMBFlush");
2612 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2616 pSMB->FileID = (__u16) smb_file_id;
2617 pSMB->ByteCount = 0;
2618 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2619 cifs_stats_inc(&tcon->num_flushes);
2621 cERROR(1, "Send error in Flush = %d", rc);
2627 CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
2628 const char *fromName, const char *toName,
2629 const struct nls_table *nls_codepage, int remap)
2632 RENAME_REQ *pSMB = NULL;
2633 RENAME_RSP *pSMBr = NULL;
2635 int name_len, name_len2;
2638 cFYI(1, "In CIFSSMBRename");
2640 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2645 pSMB->BufferFormat = 0x04;
2646 pSMB->SearchAttributes =
2647 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2650 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2652 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2653 PATH_MAX, nls_codepage, remap);
2654 name_len++; /* trailing null */
2656 pSMB->OldFileName[name_len] = 0x04; /* pad */
2657 /* protocol requires ASCII signature byte on Unicode string */
2658 pSMB->OldFileName[name_len + 1] = 0x00;
2660 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2661 toName, PATH_MAX, nls_codepage, remap);
2662 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2663 name_len2 *= 2; /* convert to bytes */
2664 } else { /* BB improve the check for buffer overruns BB */
2665 name_len = strnlen(fromName, PATH_MAX);
2666 name_len++; /* trailing null */
2667 strncpy(pSMB->OldFileName, fromName, name_len);
2668 name_len2 = strnlen(toName, PATH_MAX);
2669 name_len2++; /* trailing null */
2670 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2671 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2672 name_len2++; /* trailing null */
2673 name_len2++; /* signature byte */
2676 count = 1 /* 1st signature byte */ + name_len + name_len2;
2677 inc_rfc1001_len(pSMB, count);
2678 pSMB->ByteCount = cpu_to_le16(count);
2680 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2681 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2682 cifs_stats_inc(&tcon->num_renames);
2684 cFYI(1, "Send error in rename = %d", rc);
2686 cifs_buf_release(pSMB);
2694 int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
2695 int netfid, const char *target_name,
2696 const struct nls_table *nls_codepage, int remap)
2698 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2699 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2700 struct set_file_rename *rename_info;
2702 char dummy_string[30];
2704 int bytes_returned = 0;
2706 __u16 params, param_offset, offset, count, byte_count;
2708 cFYI(1, "Rename to File by handle");
2709 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2715 pSMB->MaxSetupCount = 0;
2719 pSMB->Reserved2 = 0;
2720 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2721 offset = param_offset + params;
2723 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2724 rename_info = (struct set_file_rename *) data_offset;
2725 pSMB->MaxParameterCount = cpu_to_le16(2);
2726 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2727 pSMB->SetupCount = 1;
2728 pSMB->Reserved3 = 0;
2729 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2730 byte_count = 3 /* pad */ + params;
2731 pSMB->ParameterCount = cpu_to_le16(params);
2732 pSMB->TotalParameterCount = pSMB->ParameterCount;
2733 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2734 pSMB->DataOffset = cpu_to_le16(offset);
2735 /* construct random name ".cifs_tmp<inodenum><mid>" */
2736 rename_info->overwrite = cpu_to_le32(1);
2737 rename_info->root_fid = 0;
2738 /* unicode only call */
2739 if (target_name == NULL) {
2740 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2741 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2742 dummy_string, 24, nls_codepage, remap);
2744 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2745 target_name, PATH_MAX, nls_codepage,
2748 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2749 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2750 byte_count += count;
2751 pSMB->DataCount = cpu_to_le16(count);
2752 pSMB->TotalDataCount = pSMB->DataCount;
2754 pSMB->InformationLevel =
2755 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2756 pSMB->Reserved4 = 0;
2757 inc_rfc1001_len(pSMB, byte_count);
2758 pSMB->ByteCount = cpu_to_le16(byte_count);
2759 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2760 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2761 cifs_stats_inc(&pTcon->num_t2renames);
2763 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2765 cifs_buf_release(pSMB);
2767 /* Note: On -EAGAIN error only caller can retry on handle based calls
2768 since file handle passed in no longer valid */
2774 CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
2775 const __u16 target_tid, const char *toName, const int flags,
2776 const struct nls_table *nls_codepage, int remap)
2779 COPY_REQ *pSMB = NULL;
2780 COPY_RSP *pSMBr = NULL;
2782 int name_len, name_len2;
2785 cFYI(1, "In CIFSSMBCopy");
2787 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2792 pSMB->BufferFormat = 0x04;
2793 pSMB->Tid2 = target_tid;
2795 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2797 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2798 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2799 fromName, PATH_MAX, nls_codepage,
2801 name_len++; /* trailing null */
2803 pSMB->OldFileName[name_len] = 0x04; /* pad */
2804 /* protocol requires ASCII signature byte on Unicode string */
2805 pSMB->OldFileName[name_len + 1] = 0x00;
2807 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2808 toName, PATH_MAX, nls_codepage, remap);
2809 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2810 name_len2 *= 2; /* convert to bytes */
2811 } else { /* BB improve the check for buffer overruns BB */
2812 name_len = strnlen(fromName, PATH_MAX);
2813 name_len++; /* trailing null */
2814 strncpy(pSMB->OldFileName, fromName, name_len);
2815 name_len2 = strnlen(toName, PATH_MAX);
2816 name_len2++; /* trailing null */
2817 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2818 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2819 name_len2++; /* trailing null */
2820 name_len2++; /* signature byte */
2823 count = 1 /* 1st signature byte */ + name_len + name_len2;
2824 inc_rfc1001_len(pSMB, count);
2825 pSMB->ByteCount = cpu_to_le16(count);
2827 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2828 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2830 cFYI(1, "Send error in copy = %d with %d files copied",
2831 rc, le16_to_cpu(pSMBr->CopyCount));
2833 cifs_buf_release(pSMB);
2842 CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
2843 const char *fromName, const char *toName,
2844 const struct nls_table *nls_codepage)
2846 TRANSACTION2_SPI_REQ *pSMB = NULL;
2847 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2850 int name_len_target;
2852 int bytes_returned = 0;
2853 __u16 params, param_offset, offset, byte_count;
2855 cFYI(1, "In Symlink Unix style");
2857 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2862 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2864 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2865 /* find define for this maxpathcomponent */
2867 name_len++; /* trailing null */
2870 } else { /* BB improve the check for buffer overruns BB */
2871 name_len = strnlen(fromName, PATH_MAX);
2872 name_len++; /* trailing null */
2873 strncpy(pSMB->FileName, fromName, name_len);
2875 params = 6 + name_len;
2876 pSMB->MaxSetupCount = 0;
2880 pSMB->Reserved2 = 0;
2881 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2882 InformationLevel) - 4;
2883 offset = param_offset + params;
2885 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2886 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2888 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2889 /* find define for this maxpathcomponent */
2891 name_len_target++; /* trailing null */
2892 name_len_target *= 2;
2893 } else { /* BB improve the check for buffer overruns BB */
2894 name_len_target = strnlen(toName, PATH_MAX);
2895 name_len_target++; /* trailing null */
2896 strncpy(data_offset, toName, name_len_target);
2899 pSMB->MaxParameterCount = cpu_to_le16(2);
2900 /* BB find exact max on data count below from sess */
2901 pSMB->MaxDataCount = cpu_to_le16(1000);
2902 pSMB->SetupCount = 1;
2903 pSMB->Reserved3 = 0;
2904 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2905 byte_count = 3 /* pad */ + params + name_len_target;
2906 pSMB->DataCount = cpu_to_le16(name_len_target);
2907 pSMB->ParameterCount = cpu_to_le16(params);
2908 pSMB->TotalDataCount = pSMB->DataCount;
2909 pSMB->TotalParameterCount = pSMB->ParameterCount;
2910 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2911 pSMB->DataOffset = cpu_to_le16(offset);
2912 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2913 pSMB->Reserved4 = 0;
2914 inc_rfc1001_len(pSMB, byte_count);
2915 pSMB->ByteCount = cpu_to_le16(byte_count);
2916 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2917 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2918 cifs_stats_inc(&tcon->num_symlinks);
2920 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2922 cifs_buf_release(pSMB);
2925 goto createSymLinkRetry;
2931 CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
2932 const char *fromName, const char *toName,
2933 const struct nls_table *nls_codepage, int remap)
2935 TRANSACTION2_SPI_REQ *pSMB = NULL;
2936 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2939 int name_len_target;
2941 int bytes_returned = 0;
2942 __u16 params, param_offset, offset, byte_count;
2944 cFYI(1, "In Create Hard link Unix style");
2945 createHardLinkRetry:
2946 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2951 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2952 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2953 PATH_MAX, nls_codepage, remap);
2954 name_len++; /* trailing null */
2957 } else { /* BB improve the check for buffer overruns BB */
2958 name_len = strnlen(toName, PATH_MAX);
2959 name_len++; /* trailing null */
2960 strncpy(pSMB->FileName, toName, name_len);
2962 params = 6 + name_len;
2963 pSMB->MaxSetupCount = 0;
2967 pSMB->Reserved2 = 0;
2968 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2969 InformationLevel) - 4;
2970 offset = param_offset + params;
2972 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2973 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2975 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2976 nls_codepage, remap);
2977 name_len_target++; /* trailing null */
2978 name_len_target *= 2;
2979 } else { /* BB improve the check for buffer overruns BB */
2980 name_len_target = strnlen(fromName, PATH_MAX);
2981 name_len_target++; /* trailing null */
2982 strncpy(data_offset, fromName, name_len_target);
2985 pSMB->MaxParameterCount = cpu_to_le16(2);
2986 /* BB find exact max on data count below from sess*/
2987 pSMB->MaxDataCount = cpu_to_le16(1000);
2988 pSMB->SetupCount = 1;
2989 pSMB->Reserved3 = 0;
2990 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2991 byte_count = 3 /* pad */ + params + name_len_target;
2992 pSMB->ParameterCount = cpu_to_le16(params);
2993 pSMB->TotalParameterCount = pSMB->ParameterCount;
2994 pSMB->DataCount = cpu_to_le16(name_len_target);
2995 pSMB->TotalDataCount = pSMB->DataCount;
2996 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2997 pSMB->DataOffset = cpu_to_le16(offset);
2998 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2999 pSMB->Reserved4 = 0;
3000 inc_rfc1001_len(pSMB, byte_count);
3001 pSMB->ByteCount = cpu_to_le16(byte_count);
3002 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3003 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3004 cifs_stats_inc(&tcon->num_hardlinks);
3006 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
3008 cifs_buf_release(pSMB);
3010 goto createHardLinkRetry;
3016 CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
3017 const char *fromName, const char *toName,
3018 const struct nls_table *nls_codepage, int remap)
3021 NT_RENAME_REQ *pSMB = NULL;
3022 RENAME_RSP *pSMBr = NULL;
3024 int name_len, name_len2;
3027 cFYI(1, "In CIFSCreateHardLink");
3028 winCreateHardLinkRetry:
3030 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3035 pSMB->SearchAttributes =
3036 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3038 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3039 pSMB->ClusterCount = 0;
3041 pSMB->BufferFormat = 0x04;
3043 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3045 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
3046 PATH_MAX, nls_codepage, remap);
3047 name_len++; /* trailing null */
3050 /* protocol specifies ASCII buffer format (0x04) for unicode */
3051 pSMB->OldFileName[name_len] = 0x04;
3052 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3054 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
3055 toName, PATH_MAX, nls_codepage, remap);
3056 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3057 name_len2 *= 2; /* convert to bytes */
3058 } else { /* BB improve the check for buffer overruns BB */
3059 name_len = strnlen(fromName, PATH_MAX);
3060 name_len++; /* trailing null */
3061 strncpy(pSMB->OldFileName, fromName, name_len);
3062 name_len2 = strnlen(toName, PATH_MAX);
3063 name_len2++; /* trailing null */
3064 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3065 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
3066 name_len2++; /* trailing null */
3067 name_len2++; /* signature byte */
3070 count = 1 /* string type byte */ + name_len + name_len2;
3071 inc_rfc1001_len(pSMB, count);
3072 pSMB->ByteCount = cpu_to_le16(count);
3074 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3075 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3076 cifs_stats_inc(&tcon->num_hardlinks);
3078 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3080 cifs_buf_release(pSMB);
3082 goto winCreateHardLinkRetry;
3088 CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
3089 const unsigned char *searchName, char **symlinkinfo,
3090 const struct nls_table *nls_codepage)
3092 /* SMB_QUERY_FILE_UNIX_LINK */
3093 TRANSACTION2_QPI_REQ *pSMB = NULL;
3094 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3098 __u16 params, byte_count;
3101 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3104 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3109 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3111 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
3112 PATH_MAX, nls_codepage);
3113 name_len++; /* trailing null */
3115 } else { /* BB improve the check for buffer overruns BB */
3116 name_len = strnlen(searchName, PATH_MAX);
3117 name_len++; /* trailing null */
3118 strncpy(pSMB->FileName, searchName, name_len);
3121 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3122 pSMB->TotalDataCount = 0;
3123 pSMB->MaxParameterCount = cpu_to_le16(2);
3124 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3125 pSMB->MaxSetupCount = 0;
3129 pSMB->Reserved2 = 0;
3130 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3131 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3132 pSMB->DataCount = 0;
3133 pSMB->DataOffset = 0;
3134 pSMB->SetupCount = 1;
3135 pSMB->Reserved3 = 0;
3136 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3137 byte_count = params + 1 /* pad */ ;
3138 pSMB->TotalParameterCount = cpu_to_le16(params);
3139 pSMB->ParameterCount = pSMB->TotalParameterCount;
3140 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3141 pSMB->Reserved4 = 0;
3142 inc_rfc1001_len(pSMB, byte_count);
3143 pSMB->ByteCount = cpu_to_le16(byte_count);
3145 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3146 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3148 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3150 /* decode response */
3152 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3153 /* BB also check enough total bytes returned */
3154 if (rc || get_bcc(&pSMBr->hdr) < 2)
3158 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3160 data_start = ((char *) &pSMBr->hdr.Protocol) +
3161 le16_to_cpu(pSMBr->t2.DataOffset);
3163 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3168 /* BB FIXME investigate remapping reserved chars here */
3169 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
3170 is_unicode, nls_codepage);
3175 cifs_buf_release(pSMB);
3177 goto querySymLinkRetry;
3181 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3183 * Recent Windows versions now create symlinks more frequently
3184 * and they use the "reparse point" mechanism below. We can of course
3185 * do symlinks nicely to Samba and other servers which support the
3186 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3187 * "MF" symlinks optionally, but for recent Windows we really need to
3188 * reenable the code below and fix the cifs_symlink callers to handle this.
3189 * In the interim this code has been moved to its own config option so
3190 * it is not compiled in by default until callers fixed up and more tested.
3193 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
3194 const unsigned char *searchName,
3195 char *symlinkinfo, const int buflen, __u16 fid,
3196 const struct nls_table *nls_codepage)
3200 struct smb_com_transaction_ioctl_req *pSMB;
3201 struct smb_com_transaction_ioctl_rsp *pSMBr;
3203 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3204 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3209 pSMB->TotalParameterCount = 0 ;
3210 pSMB->TotalDataCount = 0;
3211 pSMB->MaxParameterCount = cpu_to_le32(2);
3212 /* BB find exact data count max from sess structure BB */
3213 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3214 pSMB->MaxSetupCount = 4;
3216 pSMB->ParameterOffset = 0;
3217 pSMB->DataCount = 0;
3218 pSMB->DataOffset = 0;
3219 pSMB->SetupCount = 4;
3220 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3221 pSMB->ParameterCount = pSMB->TotalParameterCount;
3222 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3223 pSMB->IsFsctl = 1; /* FSCTL */
3224 pSMB->IsRootFlag = 0;
3225 pSMB->Fid = fid; /* file handle always le */
3226 pSMB->ByteCount = 0;
3228 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3229 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3231 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3232 } else { /* decode response */
3233 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3234 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3235 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3236 /* BB also check enough total bytes returned */
3237 rc = -EIO; /* bad smb */
3240 if (data_count && (data_count < 2048)) {
3241 char *end_of_smb = 2 /* sizeof byte count */ +
3242 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3244 struct reparse_data *reparse_buf =
3245 (struct reparse_data *)
3246 ((char *)&pSMBr->hdr.Protocol
3248 if ((char *)reparse_buf >= end_of_smb) {
3252 if ((reparse_buf->LinkNamesBuf +
3253 reparse_buf->TargetNameOffset +
3254 reparse_buf->TargetNameLen) > end_of_smb) {
3255 cFYI(1, "reparse buf beyond SMB");
3260 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3261 cifs_from_ucs2(symlinkinfo, (__le16 *)
3262 (reparse_buf->LinkNamesBuf +
3263 reparse_buf->TargetNameOffset),
3265 reparse_buf->TargetNameLen,
3267 } else { /* ASCII names */
3268 strncpy(symlinkinfo,
3269 reparse_buf->LinkNamesBuf +
3270 reparse_buf->TargetNameOffset,
3271 min_t(const int, buflen,
3272 reparse_buf->TargetNameLen));
3276 cFYI(1, "Invalid return data count on "
3277 "get reparse info ioctl");
3279 symlinkinfo[buflen] = 0; /* just in case so the caller
3280 does not go off the end of the buffer */
3281 cFYI(1, "readlink result - %s", symlinkinfo);
3285 cifs_buf_release(pSMB);
3287 /* Note: On -EAGAIN error only caller can retry on handle based calls
3288 since file handle passed in no longer valid */
3292 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3294 #ifdef CONFIG_CIFS_POSIX
3296 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3297 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3298 struct cifs_posix_ace *cifs_ace)
3300 /* u8 cifs fields do not need le conversion */
3301 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3302 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3303 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3304 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3309 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3310 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3311 const int acl_type, const int size_of_data_area)
3316 struct cifs_posix_ace *pACE;
3317 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3318 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3320 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3323 if (acl_type & ACL_TYPE_ACCESS) {
3324 count = le16_to_cpu(cifs_acl->access_entry_count);
3325 pACE = &cifs_acl->ace_array[0];
3326 size = sizeof(struct cifs_posix_acl);
3327 size += sizeof(struct cifs_posix_ace) * count;
3328 /* check if we would go beyond end of SMB */
3329 if (size_of_data_area < size) {
3330 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3331 size_of_data_area, size);
3334 } else if (acl_type & ACL_TYPE_DEFAULT) {
3335 count = le16_to_cpu(cifs_acl->access_entry_count);
3336 size = sizeof(struct cifs_posix_acl);
3337 size += sizeof(struct cifs_posix_ace) * count;
3338 /* skip past access ACEs to get to default ACEs */
3339 pACE = &cifs_acl->ace_array[count];
3340 count = le16_to_cpu(cifs_acl->default_entry_count);
3341 size += sizeof(struct cifs_posix_ace) * count;
3342 /* check if we would go beyond end of SMB */
3343 if (size_of_data_area < size)
3350 size = posix_acl_xattr_size(count);
3351 if ((buflen == 0) || (local_acl == NULL)) {
3352 /* used to query ACL EA size */
3353 } else if (size > buflen) {
3355 } else /* buffer big enough */ {
3356 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3357 for (i = 0; i < count ; i++) {
3358 cifs_convert_ace(&local_acl->a_entries[i], pACE);
3365 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3366 const posix_acl_xattr_entry *local_ace)
3368 __u16 rc = 0; /* 0 = ACL converted ok */
3370 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3371 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3372 /* BB is there a better way to handle the large uid? */
3373 if (local_ace->e_id == cpu_to_le32(-1)) {
3374 /* Probably no need to le convert -1 on any arch but can not hurt */
3375 cifs_ace->cifs_uid = cpu_to_le64(-1);
3377 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3378 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3382 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3383 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3384 const int buflen, const int acl_type)
3387 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3388 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3392 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3395 count = posix_acl_xattr_count((size_t)buflen);
3396 cFYI(1, "setting acl with %d entries from buf of length %d and "
3398 count, buflen, le32_to_cpu(local_acl->a_version));
3399 if (le32_to_cpu(local_acl->a_version) != 2) {
3400 cFYI(1, "unknown POSIX ACL version %d",
3401 le32_to_cpu(local_acl->a_version));
3404 cifs_acl->version = cpu_to_le16(1);
3405 if (acl_type == ACL_TYPE_ACCESS)
3406 cifs_acl->access_entry_count = cpu_to_le16(count);
3407 else if (acl_type == ACL_TYPE_DEFAULT)
3408 cifs_acl->default_entry_count = cpu_to_le16(count);
3410 cFYI(1, "unknown ACL type %d", acl_type);
3413 for (i = 0; i < count; i++) {
3414 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3415 &local_acl->a_entries[i]);
3417 /* ACE not converted */
3422 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3423 rc += sizeof(struct cifs_posix_acl);
3424 /* BB add check to make sure ACL does not overflow SMB */
3430 CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3431 const unsigned char *searchName,
3432 char *acl_inf, const int buflen, const int acl_type,
3433 const struct nls_table *nls_codepage, int remap)
3435 /* SMB_QUERY_POSIX_ACL */
3436 TRANSACTION2_QPI_REQ *pSMB = NULL;
3437 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3441 __u16 params, byte_count;
3443 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3446 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3451 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3453 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3454 PATH_MAX, nls_codepage, remap);
3455 name_len++; /* trailing null */
3457 pSMB->FileName[name_len] = 0;
3458 pSMB->FileName[name_len+1] = 0;
3459 } else { /* BB improve the check for buffer overruns BB */
3460 name_len = strnlen(searchName, PATH_MAX);
3461 name_len++; /* trailing null */
3462 strncpy(pSMB->FileName, searchName, name_len);
3465 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3466 pSMB->TotalDataCount = 0;
3467 pSMB->MaxParameterCount = cpu_to_le16(2);
3468 /* BB find exact max data count below from sess structure BB */
3469 pSMB->MaxDataCount = cpu_to_le16(4000);
3470 pSMB->MaxSetupCount = 0;
3474 pSMB->Reserved2 = 0;
3475 pSMB->ParameterOffset = cpu_to_le16(
3476 offsetof(struct smb_com_transaction2_qpi_req,
3477 InformationLevel) - 4);
3478 pSMB->DataCount = 0;
3479 pSMB->DataOffset = 0;
3480 pSMB->SetupCount = 1;
3481 pSMB->Reserved3 = 0;
3482 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3483 byte_count = params + 1 /* pad */ ;
3484 pSMB->TotalParameterCount = cpu_to_le16(params);
3485 pSMB->ParameterCount = pSMB->TotalParameterCount;
3486 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3487 pSMB->Reserved4 = 0;
3488 inc_rfc1001_len(pSMB, byte_count);
3489 pSMB->ByteCount = cpu_to_le16(byte_count);
3491 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3492 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3493 cifs_stats_inc(&tcon->num_acl_get);
3495 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3497 /* decode response */
3499 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3500 /* BB also check enough total bytes returned */
3501 if (rc || get_bcc(&pSMBr->hdr) < 2)
3502 rc = -EIO; /* bad smb */
3504 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3505 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3506 rc = cifs_copy_posix_acl(acl_inf,
3507 (char *)&pSMBr->hdr.Protocol+data_offset,
3508 buflen, acl_type, count);
3511 cifs_buf_release(pSMB);
3518 CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3519 const unsigned char *fileName,
3520 const char *local_acl, const int buflen,
3522 const struct nls_table *nls_codepage, int remap)
3524 struct smb_com_transaction2_spi_req *pSMB = NULL;
3525 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3529 int bytes_returned = 0;
3530 __u16 params, byte_count, data_count, param_offset, offset;
3532 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3534 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3538 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3540 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3541 PATH_MAX, nls_codepage, remap);
3542 name_len++; /* trailing null */
3544 } else { /* BB improve the check for buffer overruns BB */
3545 name_len = strnlen(fileName, PATH_MAX);
3546 name_len++; /* trailing null */
3547 strncpy(pSMB->FileName, fileName, name_len);
3549 params = 6 + name_len;
3550 pSMB->MaxParameterCount = cpu_to_le16(2);
3551 /* BB find max SMB size from sess */
3552 pSMB->MaxDataCount = cpu_to_le16(1000);
3553 pSMB->MaxSetupCount = 0;
3557 pSMB->Reserved2 = 0;
3558 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3559 InformationLevel) - 4;
3560 offset = param_offset + params;
3561 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3562 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3564 /* convert to on the wire format for POSIX ACL */
3565 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3567 if (data_count == 0) {
3569 goto setACLerrorExit;
3571 pSMB->DataOffset = cpu_to_le16(offset);
3572 pSMB->SetupCount = 1;
3573 pSMB->Reserved3 = 0;
3574 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3575 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3576 byte_count = 3 /* pad */ + params + data_count;
3577 pSMB->DataCount = cpu_to_le16(data_count);
3578 pSMB->TotalDataCount = pSMB->DataCount;
3579 pSMB->ParameterCount = cpu_to_le16(params);
3580 pSMB->TotalParameterCount = pSMB->ParameterCount;
3581 pSMB->Reserved4 = 0;
3582 inc_rfc1001_len(pSMB, byte_count);
3583 pSMB->ByteCount = cpu_to_le16(byte_count);
3584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3587 cFYI(1, "Set POSIX ACL returned %d", rc);
3590 cifs_buf_release(pSMB);
3596 /* BB fix tabs in this function FIXME BB */
3598 CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3599 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3602 struct smb_t2_qfi_req *pSMB = NULL;
3603 struct smb_t2_qfi_rsp *pSMBr = NULL;
3605 __u16 params, byte_count;
3607 cFYI(1, "In GetExtAttr");
3612 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3617 params = 2 /* level */ + 2 /* fid */;
3618 pSMB->t2.TotalDataCount = 0;
3619 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3620 /* BB find exact max data count below from sess structure BB */
3621 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3622 pSMB->t2.MaxSetupCount = 0;
3623 pSMB->t2.Reserved = 0;
3625 pSMB->t2.Timeout = 0;
3626 pSMB->t2.Reserved2 = 0;
3627 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3629 pSMB->t2.DataCount = 0;
3630 pSMB->t2.DataOffset = 0;
3631 pSMB->t2.SetupCount = 1;
3632 pSMB->t2.Reserved3 = 0;
3633 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3634 byte_count = params + 1 /* pad */ ;
3635 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3636 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3637 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3640 inc_rfc1001_len(pSMB, byte_count);
3641 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3643 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3644 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3646 cFYI(1, "error %d in GetExtAttr", rc);
3648 /* decode response */
3649 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3650 /* BB also check enough total bytes returned */
3651 if (rc || get_bcc(&pSMBr->hdr) < 2)
3652 /* If rc should we check for EOPNOSUPP and
3653 disable the srvino flag? or in caller? */
3654 rc = -EIO; /* bad smb */
3656 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3657 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3658 struct file_chattr_info *pfinfo;
3659 /* BB Do we need a cast or hash here ? */
3661 cFYI(1, "Illegal size ret in GetExtAttr");
3665 pfinfo = (struct file_chattr_info *)
3666 (data_offset + (char *) &pSMBr->hdr.Protocol);
3667 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3668 *pMask = le64_to_cpu(pfinfo->mask);
3672 cifs_buf_release(pSMB);
3674 goto GetExtAttrRetry;
3678 #endif /* CONFIG_POSIX */
3680 #ifdef CONFIG_CIFS_ACL
3682 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3683 * all NT TRANSACTS that we init here have total parm and data under about 400
3684 * bytes (to fit in small cifs buffer size), which is the case so far, it
3685 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3686 * returned setup area) and MaxParameterCount (returned parms size) must be set
3690 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3691 const int parm_len, struct cifs_tcon *tcon,
3696 struct smb_com_ntransact_req *pSMB;
3698 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3702 *ret_buf = (void *)pSMB;
3704 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3705 pSMB->TotalDataCount = 0;
3706 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3707 pSMB->ParameterCount = pSMB->TotalParameterCount;
3708 pSMB->DataCount = pSMB->TotalDataCount;
3709 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3710 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3711 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3712 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3713 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3714 pSMB->SubCommand = cpu_to_le16(sub_command);
3719 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3720 __u32 *pparmlen, __u32 *pdatalen)
3723 __u32 data_count, data_offset, parm_count, parm_offset;
3724 struct smb_com_ntransact_rsp *pSMBr;
3733 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3735 bcc = get_bcc(&pSMBr->hdr);
3736 end_of_smb = 2 /* sizeof byte count */ + bcc +
3737 (char *)&pSMBr->ByteCount;
3739 data_offset = le32_to_cpu(pSMBr->DataOffset);
3740 data_count = le32_to_cpu(pSMBr->DataCount);
3741 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3742 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3744 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3745 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3747 /* should we also check that parm and data areas do not overlap? */
3748 if (*ppparm > end_of_smb) {
3749 cFYI(1, "parms start after end of smb");
3751 } else if (parm_count + *ppparm > end_of_smb) {
3752 cFYI(1, "parm end after end of smb");
3754 } else if (*ppdata > end_of_smb) {
3755 cFYI(1, "data starts after end of smb");
3757 } else if (data_count + *ppdata > end_of_smb) {
3758 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3759 *ppdata, data_count, (data_count + *ppdata),
3762 } else if (parm_count + data_count > bcc) {
3763 cFYI(1, "parm count and data count larger than SMB");
3766 *pdatalen = data_count;
3767 *pparmlen = parm_count;
3771 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3773 CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3774 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3778 QUERY_SEC_DESC_REQ *pSMB;
3781 cFYI(1, "GetCifsACL");
3786 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3787 8 /* parm len */, tcon, (void **) &pSMB);
3791 pSMB->MaxParameterCount = cpu_to_le32(4);
3792 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3793 pSMB->MaxSetupCount = 0;
3794 pSMB->Fid = fid; /* file handle always le */
3795 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3797 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3798 inc_rfc1001_len(pSMB, 11);
3799 iov[0].iov_base = (char *)pSMB;
3800 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3802 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3804 cifs_stats_inc(&tcon->num_acl_get);
3806 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3807 } else { /* decode response */
3811 struct smb_com_ntransact_rsp *pSMBr;
3814 /* validate_nttransact */
3815 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3816 &pdata, &parm_len, pbuflen);
3819 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3821 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3823 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3824 rc = -EIO; /* bad smb */
3829 /* BB check that data area is minimum length and as big as acl_len */
3831 acl_len = le32_to_cpu(*parm);
3832 if (acl_len != *pbuflen) {
3833 cERROR(1, "acl length %d does not match %d",
3835 if (*pbuflen > acl_len)
3839 /* check if buffer is big enough for the acl
3840 header followed by the smallest SID */
3841 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3842 (*pbuflen >= 64 * 1024)) {
3843 cERROR(1, "bad acl length %d", *pbuflen);
3847 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3848 if (*acl_inf == NULL) {
3852 memcpy(*acl_inf, pdata, *pbuflen);
3856 if (buf_type == CIFS_SMALL_BUFFER)
3857 cifs_small_buf_release(iov[0].iov_base);
3858 else if (buf_type == CIFS_LARGE_BUFFER)
3859 cifs_buf_release(iov[0].iov_base);
3860 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3865 CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3866 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3868 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3870 int bytes_returned = 0;
3871 SET_SEC_DESC_REQ *pSMB = NULL;
3872 NTRANSACT_RSP *pSMBr = NULL;
3875 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3880 pSMB->MaxSetupCount = 0;
3884 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3885 data_count = acllen;
3886 data_offset = param_offset + param_count;
3887 byte_count = 3 /* pad */ + param_count;
3889 pSMB->DataCount = cpu_to_le32(data_count);
3890 pSMB->TotalDataCount = pSMB->DataCount;
3891 pSMB->MaxParameterCount = cpu_to_le32(4);
3892 pSMB->MaxDataCount = cpu_to_le32(16384);
3893 pSMB->ParameterCount = cpu_to_le32(param_count);
3894 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3895 pSMB->TotalParameterCount = pSMB->ParameterCount;
3896 pSMB->DataOffset = cpu_to_le32(data_offset);
3897 pSMB->SetupCount = 0;
3898 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3899 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3901 pSMB->Fid = fid; /* file handle always le */
3902 pSMB->Reserved2 = 0;
3903 pSMB->AclFlags = cpu_to_le32(aclflag);
3905 if (pntsd && acllen) {
3906 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3909 inc_rfc1001_len(pSMB, byte_count + data_count);
3911 inc_rfc1001_len(pSMB, byte_count);
3913 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3914 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3916 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3918 cFYI(1, "Set CIFS ACL returned %d", rc);
3919 cifs_buf_release(pSMB);
3922 goto setCifsAclRetry;
3927 #endif /* CONFIG_CIFS_ACL */
3929 /* Legacy Query Path Information call for lookup to old servers such
3931 int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3932 const unsigned char *searchName,
3933 FILE_ALL_INFO *pFinfo,
3934 const struct nls_table *nls_codepage, int remap)
3936 QUERY_INFORMATION_REQ *pSMB;
3937 QUERY_INFORMATION_RSP *pSMBr;
3942 cFYI(1, "In SMBQPath path %s", searchName);
3944 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3949 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3951 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3952 PATH_MAX, nls_codepage, remap);
3953 name_len++; /* trailing null */
3956 name_len = strnlen(searchName, PATH_MAX);
3957 name_len++; /* trailing null */
3958 strncpy(pSMB->FileName, searchName, name_len);
3960 pSMB->BufferFormat = 0x04;
3961 name_len++; /* account for buffer type byte */
3962 inc_rfc1001_len(pSMB, (__u16)name_len);
3963 pSMB->ByteCount = cpu_to_le16(name_len);
3965 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3966 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3968 cFYI(1, "Send error in QueryInfo = %d", rc);
3969 } else if (pFinfo) {
3971 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3973 /* decode response */
3974 /* BB FIXME - add time zone adjustment BB */
3975 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3978 /* decode time fields */
3979 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3980 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3981 pFinfo->LastAccessTime = 0;
3982 pFinfo->AllocationSize =
3983 cpu_to_le64(le32_to_cpu(pSMBr->size));
3984 pFinfo->EndOfFile = pFinfo->AllocationSize;
3985 pFinfo->Attributes =
3986 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3988 rc = -EIO; /* bad buffer passed in */
3990 cifs_buf_release(pSMB);
3999 CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
4000 u16 netfid, FILE_ALL_INFO *pFindData)
4002 struct smb_t2_qfi_req *pSMB = NULL;
4003 struct smb_t2_qfi_rsp *pSMBr = NULL;
4006 __u16 params, byte_count;
4009 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4014 params = 2 /* level */ + 2 /* fid */;
4015 pSMB->t2.TotalDataCount = 0;
4016 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4017 /* BB find exact max data count below from sess structure BB */
4018 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4019 pSMB->t2.MaxSetupCount = 0;
4020 pSMB->t2.Reserved = 0;
4022 pSMB->t2.Timeout = 0;
4023 pSMB->t2.Reserved2 = 0;
4024 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4026 pSMB->t2.DataCount = 0;
4027 pSMB->t2.DataOffset = 0;
4028 pSMB->t2.SetupCount = 1;
4029 pSMB->t2.Reserved3 = 0;
4030 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4031 byte_count = params + 1 /* pad */ ;
4032 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4033 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4034 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4037 inc_rfc1001_len(pSMB, byte_count);
4039 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4040 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4042 cFYI(1, "Send error in QPathInfo = %d", rc);
4043 } else { /* decode response */
4044 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4046 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4048 else if (get_bcc(&pSMBr->hdr) < 40)
4049 rc = -EIO; /* bad smb */
4050 else if (pFindData) {
4051 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4052 memcpy((char *) pFindData,
4053 (char *) &pSMBr->hdr.Protocol +
4054 data_offset, sizeof(FILE_ALL_INFO));
4058 cifs_buf_release(pSMB);
4060 goto QFileInfoRetry;
4066 CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
4067 const unsigned char *searchName,
4068 FILE_ALL_INFO *pFindData,
4069 int legacy /* old style infolevel */,
4070 const struct nls_table *nls_codepage, int remap)
4072 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4073 TRANSACTION2_QPI_REQ *pSMB = NULL;
4074 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4078 __u16 params, byte_count;
4080 /* cFYI(1, "In QPathInfo path %s", searchName); */
4082 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4087 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4089 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4090 PATH_MAX, nls_codepage, remap);
4091 name_len++; /* trailing null */
4093 } else { /* BB improve the check for buffer overruns BB */
4094 name_len = strnlen(searchName, PATH_MAX);
4095 name_len++; /* trailing null */
4096 strncpy(pSMB->FileName, searchName, name_len);
4099 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4100 pSMB->TotalDataCount = 0;
4101 pSMB->MaxParameterCount = cpu_to_le16(2);
4102 /* BB find exact max SMB PDU from sess structure BB */
4103 pSMB->MaxDataCount = cpu_to_le16(4000);
4104 pSMB->MaxSetupCount = 0;
4108 pSMB->Reserved2 = 0;
4109 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4110 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4111 pSMB->DataCount = 0;
4112 pSMB->DataOffset = 0;
4113 pSMB->SetupCount = 1;
4114 pSMB->Reserved3 = 0;
4115 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4116 byte_count = params + 1 /* pad */ ;
4117 pSMB->TotalParameterCount = cpu_to_le16(params);
4118 pSMB->ParameterCount = pSMB->TotalParameterCount;
4120 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4122 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4123 pSMB->Reserved4 = 0;
4124 inc_rfc1001_len(pSMB, byte_count);
4125 pSMB->ByteCount = cpu_to_le16(byte_count);
4127 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4128 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4130 cFYI(1, "Send error in QPathInfo = %d", rc);
4131 } else { /* decode response */
4132 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4134 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4136 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4137 rc = -EIO; /* bad smb */
4138 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4139 rc = -EIO; /* 24 or 26 expected but we do not read
4141 else if (pFindData) {
4143 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4145 /* On legacy responses we do not read the last field,
4146 EAsize, fortunately since it varies by subdialect and
4147 also note it differs on Set vs. Get, ie two bytes or 4
4148 bytes depending but we don't care here */
4150 size = sizeof(FILE_INFO_STANDARD);
4152 size = sizeof(FILE_ALL_INFO);
4153 memcpy((char *) pFindData,
4154 (char *) &pSMBr->hdr.Protocol +
4159 cifs_buf_release(pSMB);
4161 goto QPathInfoRetry;
4167 CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
4168 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4170 struct smb_t2_qfi_req *pSMB = NULL;
4171 struct smb_t2_qfi_rsp *pSMBr = NULL;
4174 __u16 params, byte_count;
4177 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4182 params = 2 /* level */ + 2 /* fid */;
4183 pSMB->t2.TotalDataCount = 0;
4184 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4185 /* BB find exact max data count below from sess structure BB */
4186 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4187 pSMB->t2.MaxSetupCount = 0;
4188 pSMB->t2.Reserved = 0;
4190 pSMB->t2.Timeout = 0;
4191 pSMB->t2.Reserved2 = 0;
4192 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4194 pSMB->t2.DataCount = 0;
4195 pSMB->t2.DataOffset = 0;
4196 pSMB->t2.SetupCount = 1;
4197 pSMB->t2.Reserved3 = 0;
4198 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4199 byte_count = params + 1 /* pad */ ;
4200 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4201 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4202 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4205 inc_rfc1001_len(pSMB, byte_count);
4207 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4208 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4210 cFYI(1, "Send error in QPathInfo = %d", rc);
4211 } else { /* decode response */
4212 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4214 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4215 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4216 "Unix Extensions can be disabled on mount "
4217 "by specifying the nosfu mount option.");
4218 rc = -EIO; /* bad smb */
4220 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4221 memcpy((char *) pFindData,
4222 (char *) &pSMBr->hdr.Protocol +
4224 sizeof(FILE_UNIX_BASIC_INFO));
4228 cifs_buf_release(pSMB);
4230 goto UnixQFileInfoRetry;
4236 CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
4237 const unsigned char *searchName,
4238 FILE_UNIX_BASIC_INFO *pFindData,
4239 const struct nls_table *nls_codepage, int remap)
4241 /* SMB_QUERY_FILE_UNIX_BASIC */
4242 TRANSACTION2_QPI_REQ *pSMB = NULL;
4243 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4245 int bytes_returned = 0;
4247 __u16 params, byte_count;
4249 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4251 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4256 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4258 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4259 PATH_MAX, nls_codepage, remap);
4260 name_len++; /* trailing null */
4262 } else { /* BB improve the check for buffer overruns BB */
4263 name_len = strnlen(searchName, PATH_MAX);
4264 name_len++; /* trailing null */
4265 strncpy(pSMB->FileName, searchName, name_len);
4268 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4269 pSMB->TotalDataCount = 0;
4270 pSMB->MaxParameterCount = cpu_to_le16(2);
4271 /* BB find exact max SMB PDU from sess structure BB */
4272 pSMB->MaxDataCount = cpu_to_le16(4000);
4273 pSMB->MaxSetupCount = 0;
4277 pSMB->Reserved2 = 0;
4278 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4279 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4280 pSMB->DataCount = 0;
4281 pSMB->DataOffset = 0;
4282 pSMB->SetupCount = 1;
4283 pSMB->Reserved3 = 0;
4284 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4285 byte_count = params + 1 /* pad */ ;
4286 pSMB->TotalParameterCount = cpu_to_le16(params);
4287 pSMB->ParameterCount = pSMB->TotalParameterCount;
4288 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4289 pSMB->Reserved4 = 0;
4290 inc_rfc1001_len(pSMB, byte_count);
4291 pSMB->ByteCount = cpu_to_le16(byte_count);
4293 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4294 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4296 cFYI(1, "Send error in QPathInfo = %d", rc);
4297 } else { /* decode response */
4298 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4300 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4301 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4302 "Unix Extensions can be disabled on mount "
4303 "by specifying the nosfu mount option.");
4304 rc = -EIO; /* bad smb */
4306 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4307 memcpy((char *) pFindData,
4308 (char *) &pSMBr->hdr.Protocol +
4310 sizeof(FILE_UNIX_BASIC_INFO));
4313 cifs_buf_release(pSMB);
4315 goto UnixQPathInfoRetry;
4320 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4322 CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4323 const char *searchName,
4324 const struct nls_table *nls_codepage,
4326 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4328 /* level 257 SMB_ */
4329 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4330 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4331 T2_FFIRST_RSP_PARMS *parms;
4333 int bytes_returned = 0;
4335 __u16 params, byte_count;
4337 cFYI(1, "In FindFirst for %s", searchName);
4340 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4345 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4347 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4348 PATH_MAX, nls_codepage, remap);
4349 /* We can not add the asterik earlier in case
4350 it got remapped to 0xF03A as if it were part of the
4351 directory name instead of a wildcard */
4353 pSMB->FileName[name_len] = dirsep;
4354 pSMB->FileName[name_len+1] = 0;
4355 pSMB->FileName[name_len+2] = '*';
4356 pSMB->FileName[name_len+3] = 0;
4357 name_len += 4; /* now the trailing null */
4358 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4359 pSMB->FileName[name_len+1] = 0;
4361 } else { /* BB add check for overrun of SMB buf BB */
4362 name_len = strnlen(searchName, PATH_MAX);
4363 /* BB fix here and in unicode clause above ie
4364 if (name_len > buffersize-header)
4365 free buffer exit; BB */
4366 strncpy(pSMB->FileName, searchName, name_len);
4367 pSMB->FileName[name_len] = dirsep;
4368 pSMB->FileName[name_len+1] = '*';
4369 pSMB->FileName[name_len+2] = 0;
4373 params = 12 + name_len /* includes null */ ;
4374 pSMB->TotalDataCount = 0; /* no EAs */
4375 pSMB->MaxParameterCount = cpu_to_le16(10);
4376 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4377 pSMB->MaxSetupCount = 0;
4381 pSMB->Reserved2 = 0;
4382 byte_count = params + 1 /* pad */ ;
4383 pSMB->TotalParameterCount = cpu_to_le16(params);
4384 pSMB->ParameterCount = pSMB->TotalParameterCount;
4385 pSMB->ParameterOffset = cpu_to_le16(
4386 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4388 pSMB->DataCount = 0;
4389 pSMB->DataOffset = 0;
4390 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4391 pSMB->Reserved3 = 0;
4392 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4393 pSMB->SearchAttributes =
4394 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4396 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4397 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
4398 CIFS_SEARCH_RETURN_RESUME);
4399 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4401 /* BB what should we set StorageType to? Does it matter? BB */
4402 pSMB->SearchStorageType = 0;
4403 inc_rfc1001_len(pSMB, byte_count);
4404 pSMB->ByteCount = cpu_to_le16(byte_count);
4406 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4407 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4408 cifs_stats_inc(&tcon->num_ffirst);
4410 if (rc) {/* BB add logic to retry regular search if Unix search
4411 rejected unexpectedly by server */
4412 /* BB Add code to handle unsupported level rc */
4413 cFYI(1, "Error in FindFirst = %d", rc);
4415 cifs_buf_release(pSMB);
4417 /* BB eventually could optimize out free and realloc of buf */
4420 goto findFirstRetry;
4421 } else { /* decode response */
4422 /* BB remember to free buffer if error BB */
4423 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4427 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4428 psrch_inf->unicode = true;
4430 psrch_inf->unicode = false;
4432 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4433 psrch_inf->smallBuf = 0;
4434 psrch_inf->srch_entries_start =
4435 (char *) &pSMBr->hdr.Protocol +
4436 le16_to_cpu(pSMBr->t2.DataOffset);
4437 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4438 le16_to_cpu(pSMBr->t2.ParameterOffset));
4440 if (parms->EndofSearch)
4441 psrch_inf->endOfSearch = true;
4443 psrch_inf->endOfSearch = false;
4445 psrch_inf->entries_in_buffer =
4446 le16_to_cpu(parms->SearchCount);
4447 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4448 psrch_inf->entries_in_buffer;
4449 lnoff = le16_to_cpu(parms->LastNameOffset);
4450 if (CIFSMaxBufSize < lnoff) {
4451 cERROR(1, "ignoring corrupt resume name");
4452 psrch_inf->last_entry = NULL;
4456 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4459 *pnetfid = parms->SearchHandle;
4461 cifs_buf_release(pSMB);
4468 int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
4469 __u16 searchHandle, struct cifs_search_info *psrch_inf)
4471 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4472 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4473 T2_FNEXT_RSP_PARMS *parms;
4474 char *response_data;
4477 unsigned int name_len;
4478 __u16 params, byte_count;
4480 cFYI(1, "In FindNext");
4482 if (psrch_inf->endOfSearch)
4485 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4490 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4492 pSMB->TotalDataCount = 0; /* no EAs */
4493 pSMB->MaxParameterCount = cpu_to_le16(8);
4494 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4495 pSMB->MaxSetupCount = 0;
4499 pSMB->Reserved2 = 0;
4500 pSMB->ParameterOffset = cpu_to_le16(
4501 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4502 pSMB->DataCount = 0;
4503 pSMB->DataOffset = 0;
4504 pSMB->SetupCount = 1;
4505 pSMB->Reserved3 = 0;
4506 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4507 pSMB->SearchHandle = searchHandle; /* always kept as le */
4509 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4510 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4511 pSMB->ResumeKey = psrch_inf->resume_key;
4513 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
4515 name_len = psrch_inf->resume_name_len;
4517 if (name_len < PATH_MAX) {
4518 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4519 byte_count += name_len;
4520 /* 14 byte parm len above enough for 2 byte null terminator */
4521 pSMB->ResumeFileName[name_len] = 0;
4522 pSMB->ResumeFileName[name_len+1] = 0;
4525 goto FNext2_err_exit;
4527 byte_count = params + 1 /* pad */ ;
4528 pSMB->TotalParameterCount = cpu_to_le16(params);
4529 pSMB->ParameterCount = pSMB->TotalParameterCount;
4530 inc_rfc1001_len(pSMB, byte_count);
4531 pSMB->ByteCount = cpu_to_le16(byte_count);
4533 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4534 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4535 cifs_stats_inc(&tcon->num_fnext);
4538 psrch_inf->endOfSearch = true;
4539 cifs_buf_release(pSMB);
4540 rc = 0; /* search probably was closed at end of search*/
4542 cFYI(1, "FindNext returned = %d", rc);
4543 } else { /* decode response */
4544 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4549 /* BB fixme add lock for file (srch_info) struct here */
4550 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4551 psrch_inf->unicode = true;
4553 psrch_inf->unicode = false;
4554 response_data = (char *) &pSMBr->hdr.Protocol +
4555 le16_to_cpu(pSMBr->t2.ParameterOffset);
4556 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4557 response_data = (char *)&pSMBr->hdr.Protocol +
4558 le16_to_cpu(pSMBr->t2.DataOffset);
4559 if (psrch_inf->smallBuf)
4560 cifs_small_buf_release(
4561 psrch_inf->ntwrk_buf_start);
4563 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4564 psrch_inf->srch_entries_start = response_data;
4565 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4566 psrch_inf->smallBuf = 0;
4567 if (parms->EndofSearch)
4568 psrch_inf->endOfSearch = true;
4570 psrch_inf->endOfSearch = false;
4571 psrch_inf->entries_in_buffer =
4572 le16_to_cpu(parms->SearchCount);
4573 psrch_inf->index_of_last_entry +=
4574 psrch_inf->entries_in_buffer;
4575 lnoff = le16_to_cpu(parms->LastNameOffset);
4576 if (CIFSMaxBufSize < lnoff) {
4577 cERROR(1, "ignoring corrupt resume name");
4578 psrch_inf->last_entry = NULL;
4581 psrch_inf->last_entry =
4582 psrch_inf->srch_entries_start + lnoff;
4584 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4585 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4587 /* BB fixme add unlock here */
4592 /* BB On error, should we leave previous search buf (and count and
4593 last entry fields) intact or free the previous one? */
4595 /* Note: On -EAGAIN error only caller can retry on handle based calls
4596 since file handle passed in no longer valid */
4599 cifs_buf_release(pSMB);
4604 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4605 const __u16 searchHandle)
4608 FINDCLOSE_REQ *pSMB = NULL;
4610 cFYI(1, "In CIFSSMBFindClose");
4611 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4613 /* no sense returning error if session restarted
4614 as file handle has been closed */
4620 pSMB->FileID = searchHandle;
4621 pSMB->ByteCount = 0;
4622 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4624 cERROR(1, "Send error in FindClose = %d", rc);
4626 cifs_stats_inc(&tcon->num_fclose);
4628 /* Since session is dead, search handle closed on server already */
4636 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4637 const unsigned char *searchName,
4638 __u64 *inode_number,
4639 const struct nls_table *nls_codepage, int remap)
4642 TRANSACTION2_QPI_REQ *pSMB = NULL;
4643 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4644 int name_len, bytes_returned;
4645 __u16 params, byte_count;
4647 cFYI(1, "In GetSrvInodeNum for %s", searchName);
4651 GetInodeNumberRetry:
4652 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4657 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4659 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4660 PATH_MAX, nls_codepage, remap);
4661 name_len++; /* trailing null */
4663 } else { /* BB improve the check for buffer overruns BB */
4664 name_len = strnlen(searchName, PATH_MAX);
4665 name_len++; /* trailing null */
4666 strncpy(pSMB->FileName, searchName, name_len);
4669 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4670 pSMB->TotalDataCount = 0;
4671 pSMB->MaxParameterCount = cpu_to_le16(2);
4672 /* BB find exact max data count below from sess structure BB */
4673 pSMB->MaxDataCount = cpu_to_le16(4000);
4674 pSMB->MaxSetupCount = 0;
4678 pSMB->Reserved2 = 0;
4679 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4680 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4681 pSMB->DataCount = 0;
4682 pSMB->DataOffset = 0;
4683 pSMB->SetupCount = 1;
4684 pSMB->Reserved3 = 0;
4685 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4686 byte_count = params + 1 /* pad */ ;
4687 pSMB->TotalParameterCount = cpu_to_le16(params);
4688 pSMB->ParameterCount = pSMB->TotalParameterCount;
4689 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4690 pSMB->Reserved4 = 0;
4691 inc_rfc1001_len(pSMB, byte_count);
4692 pSMB->ByteCount = cpu_to_le16(byte_count);
4694 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4695 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4697 cFYI(1, "error %d in QueryInternalInfo", rc);
4699 /* decode response */
4700 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4701 /* BB also check enough total bytes returned */
4702 if (rc || get_bcc(&pSMBr->hdr) < 2)
4703 /* If rc should we check for EOPNOSUPP and
4704 disable the srvino flag? or in caller? */
4705 rc = -EIO; /* bad smb */
4707 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4708 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4709 struct file_internal_info *pfinfo;
4710 /* BB Do we need a cast or hash here ? */
4712 cFYI(1, "Illegal size ret in QryIntrnlInf");
4714 goto GetInodeNumOut;
4716 pfinfo = (struct file_internal_info *)
4717 (data_offset + (char *) &pSMBr->hdr.Protocol);
4718 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4722 cifs_buf_release(pSMB);
4724 goto GetInodeNumberRetry;
4728 /* parses DFS refferal V3 structure
4729 * caller is responsible for freeing target_nodes
4732 * on failure - errno
4735 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4736 unsigned int *num_of_nodes,
4737 struct dfs_info3_param **target_nodes,
4738 const struct nls_table *nls_codepage, int remap,
4739 const char *searchName)
4744 struct dfs_referral_level_3 *ref;
4746 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4750 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4752 if (*num_of_nodes < 1) {
4753 cERROR(1, "num_referrals: must be at least > 0,"
4754 "but we get num_referrals = %d\n", *num_of_nodes);
4756 goto parse_DFS_referrals_exit;
4759 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4760 if (ref->VersionNumber != cpu_to_le16(3)) {
4761 cERROR(1, "Referrals of V%d version are not supported,"
4762 "should be V3", le16_to_cpu(ref->VersionNumber));
4764 goto parse_DFS_referrals_exit;
4767 /* get the upper boundary of the resp buffer */
4768 data_end = (char *)(&(pSMBr->PathConsumed)) +
4769 le16_to_cpu(pSMBr->t2.DataCount);
4771 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4773 le32_to_cpu(pSMBr->DFSFlags));
4775 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4776 *num_of_nodes, GFP_KERNEL);
4777 if (*target_nodes == NULL) {
4778 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4780 goto parse_DFS_referrals_exit;
4783 /* collect necessary data from referrals */
4784 for (i = 0; i < *num_of_nodes; i++) {
4787 struct dfs_info3_param *node = (*target_nodes)+i;
4789 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4791 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4795 goto parse_DFS_referrals_exit;
4797 cifsConvertToUCS((__le16 *) tmp, searchName,
4798 PATH_MAX, nls_codepage, remap);
4799 node->path_consumed = cifs_ucs2_bytes(tmp,
4800 le16_to_cpu(pSMBr->PathConsumed),
4804 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4806 node->server_type = le16_to_cpu(ref->ServerType);
4807 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4810 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4811 max_len = data_end - temp;
4812 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4813 is_unicode, nls_codepage);
4814 if (!node->path_name) {
4816 goto parse_DFS_referrals_exit;
4819 /* copy link target UNC */
4820 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4821 max_len = data_end - temp;
4822 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4823 is_unicode, nls_codepage);
4824 if (!node->node_name)
4828 parse_DFS_referrals_exit:
4830 free_dfs_info_array(*target_nodes, *num_of_nodes);
4831 *target_nodes = NULL;
4838 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4839 const unsigned char *searchName,
4840 struct dfs_info3_param **target_nodes,
4841 unsigned int *num_of_nodes,
4842 const struct nls_table *nls_codepage, int remap)
4844 /* TRANS2_GET_DFS_REFERRAL */
4845 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4846 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4850 __u16 params, byte_count;
4852 *target_nodes = NULL;
4854 cFYI(1, "In GetDFSRefer the path %s", searchName);
4858 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4863 /* server pointer checked in called function,
4864 but should never be null here anyway */
4865 pSMB->hdr.Mid = GetNextMid(ses->server);
4866 pSMB->hdr.Tid = ses->ipc_tid;
4867 pSMB->hdr.Uid = ses->Suid;
4868 if (ses->capabilities & CAP_STATUS32)
4869 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4870 if (ses->capabilities & CAP_DFS)
4871 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4873 if (ses->capabilities & CAP_UNICODE) {
4874 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4876 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4877 searchName, PATH_MAX, nls_codepage, remap);
4878 name_len++; /* trailing null */
4880 } else { /* BB improve the check for buffer overruns BB */
4881 name_len = strnlen(searchName, PATH_MAX);
4882 name_len++; /* trailing null */
4883 strncpy(pSMB->RequestFileName, searchName, name_len);
4887 if (ses->server->sec_mode &
4888 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4889 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4892 pSMB->hdr.Uid = ses->Suid;
4894 params = 2 /* level */ + name_len /*includes null */ ;
4895 pSMB->TotalDataCount = 0;
4896 pSMB->DataCount = 0;
4897 pSMB->DataOffset = 0;
4898 pSMB->MaxParameterCount = 0;
4899 /* BB find exact max SMB PDU from sess structure BB */
4900 pSMB->MaxDataCount = cpu_to_le16(4000);
4901 pSMB->MaxSetupCount = 0;
4905 pSMB->Reserved2 = 0;
4906 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4907 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4908 pSMB->SetupCount = 1;
4909 pSMB->Reserved3 = 0;
4910 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4911 byte_count = params + 3 /* pad */ ;
4912 pSMB->ParameterCount = cpu_to_le16(params);
4913 pSMB->TotalParameterCount = pSMB->ParameterCount;
4914 pSMB->MaxReferralLevel = cpu_to_le16(3);
4915 inc_rfc1001_len(pSMB, byte_count);
4916 pSMB->ByteCount = cpu_to_le16(byte_count);
4918 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4919 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4921 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4924 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4926 /* BB Also check if enough total bytes returned? */
4927 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4928 rc = -EIO; /* bad smb */
4932 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4933 get_bcc(&pSMBr->hdr),
4934 le16_to_cpu(pSMBr->t2.DataOffset));
4936 /* parse returned result into more usable form */
4937 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4938 target_nodes, nls_codepage, remap,
4942 cifs_buf_release(pSMB);
4950 /* Query File System Info such as free space to old servers such as Win 9x */
4952 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4954 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4955 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4956 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4957 FILE_SYSTEM_ALLOC_INFO *response_data;
4959 int bytes_returned = 0;
4960 __u16 params, byte_count;
4962 cFYI(1, "OldQFSInfo");
4964 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4969 params = 2; /* level */
4970 pSMB->TotalDataCount = 0;
4971 pSMB->MaxParameterCount = cpu_to_le16(2);
4972 pSMB->MaxDataCount = cpu_to_le16(1000);
4973 pSMB->MaxSetupCount = 0;
4977 pSMB->Reserved2 = 0;
4978 byte_count = params + 1 /* pad */ ;
4979 pSMB->TotalParameterCount = cpu_to_le16(params);
4980 pSMB->ParameterCount = pSMB->TotalParameterCount;
4981 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4982 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4983 pSMB->DataCount = 0;
4984 pSMB->DataOffset = 0;
4985 pSMB->SetupCount = 1;
4986 pSMB->Reserved3 = 0;
4987 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4988 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4989 inc_rfc1001_len(pSMB, byte_count);
4990 pSMB->ByteCount = cpu_to_le16(byte_count);
4992 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4993 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4995 cFYI(1, "Send error in QFSInfo = %d", rc);
4996 } else { /* decode response */
4997 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4999 if (rc || get_bcc(&pSMBr->hdr) < 18)
5000 rc = -EIO; /* bad smb */
5002 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5003 cFYI(1, "qfsinf resp BCC: %d Offset %d",
5004 get_bcc(&pSMBr->hdr), data_offset);
5006 response_data = (FILE_SYSTEM_ALLOC_INFO *)
5007 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5009 le16_to_cpu(response_data->BytesPerSector) *
5010 le32_to_cpu(response_data->
5011 SectorsPerAllocationUnit);
5013 le32_to_cpu(response_data->TotalAllocationUnits);
5014 FSData->f_bfree = FSData->f_bavail =
5015 le32_to_cpu(response_data->FreeAllocationUnits);
5016 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5017 (unsigned long long)FSData->f_blocks,
5018 (unsigned long long)FSData->f_bfree,
5022 cifs_buf_release(pSMB);
5025 goto oldQFSInfoRetry;
5031 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
5033 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5034 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5035 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5036 FILE_SYSTEM_INFO *response_data;
5038 int bytes_returned = 0;
5039 __u16 params, byte_count;
5041 cFYI(1, "In QFSInfo");
5043 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5048 params = 2; /* level */
5049 pSMB->TotalDataCount = 0;
5050 pSMB->MaxParameterCount = cpu_to_le16(2);
5051 pSMB->MaxDataCount = cpu_to_le16(1000);
5052 pSMB->MaxSetupCount = 0;
5056 pSMB->Reserved2 = 0;
5057 byte_count = params + 1 /* pad */ ;
5058 pSMB->TotalParameterCount = cpu_to_le16(params);
5059 pSMB->ParameterCount = pSMB->TotalParameterCount;
5060 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5061 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5062 pSMB->DataCount = 0;
5063 pSMB->DataOffset = 0;
5064 pSMB->SetupCount = 1;
5065 pSMB->Reserved3 = 0;
5066 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5067 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5068 inc_rfc1001_len(pSMB, byte_count);
5069 pSMB->ByteCount = cpu_to_le16(byte_count);
5071 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5072 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5074 cFYI(1, "Send error in QFSInfo = %d", rc);
5075 } else { /* decode response */
5076 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5078 if (rc || get_bcc(&pSMBr->hdr) < 24)
5079 rc = -EIO; /* bad smb */
5081 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5085 *) (((char *) &pSMBr->hdr.Protocol) +
5088 le32_to_cpu(response_data->BytesPerSector) *
5089 le32_to_cpu(response_data->
5090 SectorsPerAllocationUnit);
5092 le64_to_cpu(response_data->TotalAllocationUnits);
5093 FSData->f_bfree = FSData->f_bavail =
5094 le64_to_cpu(response_data->FreeAllocationUnits);
5095 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5096 (unsigned long long)FSData->f_blocks,
5097 (unsigned long long)FSData->f_bfree,
5101 cifs_buf_release(pSMB);
5110 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
5112 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5113 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5114 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5115 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5117 int bytes_returned = 0;
5118 __u16 params, byte_count;
5120 cFYI(1, "In QFSAttributeInfo");
5122 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5127 params = 2; /* level */
5128 pSMB->TotalDataCount = 0;
5129 pSMB->MaxParameterCount = cpu_to_le16(2);
5130 /* BB find exact max SMB PDU from sess structure BB */
5131 pSMB->MaxDataCount = cpu_to_le16(1000);
5132 pSMB->MaxSetupCount = 0;
5136 pSMB->Reserved2 = 0;
5137 byte_count = params + 1 /* pad */ ;
5138 pSMB->TotalParameterCount = cpu_to_le16(params);
5139 pSMB->ParameterCount = pSMB->TotalParameterCount;
5140 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5141 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5142 pSMB->DataCount = 0;
5143 pSMB->DataOffset = 0;
5144 pSMB->SetupCount = 1;
5145 pSMB->Reserved3 = 0;
5146 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5147 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5148 inc_rfc1001_len(pSMB, byte_count);
5149 pSMB->ByteCount = cpu_to_le16(byte_count);
5151 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5152 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5154 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5155 } else { /* decode response */
5156 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5158 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5159 /* BB also check if enough bytes returned */
5160 rc = -EIO; /* bad smb */
5162 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5164 (FILE_SYSTEM_ATTRIBUTE_INFO
5165 *) (((char *) &pSMBr->hdr.Protocol) +
5167 memcpy(&tcon->fsAttrInfo, response_data,
5168 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5171 cifs_buf_release(pSMB);
5174 goto QFSAttributeRetry;
5180 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
5182 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5183 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5184 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5185 FILE_SYSTEM_DEVICE_INFO *response_data;
5187 int bytes_returned = 0;
5188 __u16 params, byte_count;
5190 cFYI(1, "In QFSDeviceInfo");
5192 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5197 params = 2; /* level */
5198 pSMB->TotalDataCount = 0;
5199 pSMB->MaxParameterCount = cpu_to_le16(2);
5200 /* BB find exact max SMB PDU from sess structure BB */
5201 pSMB->MaxDataCount = cpu_to_le16(1000);
5202 pSMB->MaxSetupCount = 0;
5206 pSMB->Reserved2 = 0;
5207 byte_count = params + 1 /* pad */ ;
5208 pSMB->TotalParameterCount = cpu_to_le16(params);
5209 pSMB->ParameterCount = pSMB->TotalParameterCount;
5210 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5211 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5213 pSMB->DataCount = 0;
5214 pSMB->DataOffset = 0;
5215 pSMB->SetupCount = 1;
5216 pSMB->Reserved3 = 0;
5217 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5218 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5219 inc_rfc1001_len(pSMB, byte_count);
5220 pSMB->ByteCount = cpu_to_le16(byte_count);
5222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5223 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5225 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5226 } else { /* decode response */
5227 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5229 if (rc || get_bcc(&pSMBr->hdr) <
5230 sizeof(FILE_SYSTEM_DEVICE_INFO))
5231 rc = -EIO; /* bad smb */
5233 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5235 (FILE_SYSTEM_DEVICE_INFO *)
5236 (((char *) &pSMBr->hdr.Protocol) +
5238 memcpy(&tcon->fsDevInfo, response_data,
5239 sizeof(FILE_SYSTEM_DEVICE_INFO));
5242 cifs_buf_release(pSMB);
5245 goto QFSDeviceRetry;
5251 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
5253 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5254 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5255 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5256 FILE_SYSTEM_UNIX_INFO *response_data;
5258 int bytes_returned = 0;
5259 __u16 params, byte_count;
5261 cFYI(1, "In QFSUnixInfo");
5263 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5264 (void **) &pSMB, (void **) &pSMBr);
5268 params = 2; /* level */
5269 pSMB->TotalDataCount = 0;
5270 pSMB->DataCount = 0;
5271 pSMB->DataOffset = 0;
5272 pSMB->MaxParameterCount = cpu_to_le16(2);
5273 /* BB find exact max SMB PDU from sess structure BB */
5274 pSMB->MaxDataCount = cpu_to_le16(100);
5275 pSMB->MaxSetupCount = 0;
5279 pSMB->Reserved2 = 0;
5280 byte_count = params + 1 /* pad */ ;
5281 pSMB->ParameterCount = cpu_to_le16(params);
5282 pSMB->TotalParameterCount = pSMB->ParameterCount;
5283 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5284 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5285 pSMB->SetupCount = 1;
5286 pSMB->Reserved3 = 0;
5287 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5288 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5289 inc_rfc1001_len(pSMB, byte_count);
5290 pSMB->ByteCount = cpu_to_le16(byte_count);
5292 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5293 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5295 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5296 } else { /* decode response */
5297 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5299 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5300 rc = -EIO; /* bad smb */
5302 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5304 (FILE_SYSTEM_UNIX_INFO
5305 *) (((char *) &pSMBr->hdr.Protocol) +
5307 memcpy(&tcon->fsUnixInfo, response_data,
5308 sizeof(FILE_SYSTEM_UNIX_INFO));
5311 cifs_buf_release(pSMB);
5321 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
5323 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5324 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5325 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5327 int bytes_returned = 0;
5328 __u16 params, param_offset, offset, byte_count;
5330 cFYI(1, "In SETFSUnixInfo");
5332 /* BB switch to small buf init to save memory */
5333 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5334 (void **) &pSMB, (void **) &pSMBr);
5338 params = 4; /* 2 bytes zero followed by info level. */
5339 pSMB->MaxSetupCount = 0;
5343 pSMB->Reserved2 = 0;
5344 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5346 offset = param_offset + params;
5348 pSMB->MaxParameterCount = cpu_to_le16(4);
5349 /* BB find exact max SMB PDU from sess structure BB */
5350 pSMB->MaxDataCount = cpu_to_le16(100);
5351 pSMB->SetupCount = 1;
5352 pSMB->Reserved3 = 0;
5353 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5354 byte_count = 1 /* pad */ + params + 12;
5356 pSMB->DataCount = cpu_to_le16(12);
5357 pSMB->ParameterCount = cpu_to_le16(params);
5358 pSMB->TotalDataCount = pSMB->DataCount;
5359 pSMB->TotalParameterCount = pSMB->ParameterCount;
5360 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5361 pSMB->DataOffset = cpu_to_le16(offset);
5365 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5368 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5369 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5370 pSMB->ClientUnixCap = cpu_to_le64(cap);
5372 inc_rfc1001_len(pSMB, byte_count);
5373 pSMB->ByteCount = cpu_to_le16(byte_count);
5375 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5376 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5378 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5379 } else { /* decode response */
5380 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5382 rc = -EIO; /* bad smb */
5384 cifs_buf_release(pSMB);
5387 goto SETFSUnixRetry;
5395 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5396 struct kstatfs *FSData)
5398 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5399 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5400 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5401 FILE_SYSTEM_POSIX_INFO *response_data;
5403 int bytes_returned = 0;
5404 __u16 params, byte_count;
5406 cFYI(1, "In QFSPosixInfo");
5408 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5413 params = 2; /* level */
5414 pSMB->TotalDataCount = 0;
5415 pSMB->DataCount = 0;
5416 pSMB->DataOffset = 0;
5417 pSMB->MaxParameterCount = cpu_to_le16(2);
5418 /* BB find exact max SMB PDU from sess structure BB */
5419 pSMB->MaxDataCount = cpu_to_le16(100);
5420 pSMB->MaxSetupCount = 0;
5424 pSMB->Reserved2 = 0;
5425 byte_count = params + 1 /* pad */ ;
5426 pSMB->ParameterCount = cpu_to_le16(params);
5427 pSMB->TotalParameterCount = pSMB->ParameterCount;
5428 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5429 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5430 pSMB->SetupCount = 1;
5431 pSMB->Reserved3 = 0;
5432 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5433 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5434 inc_rfc1001_len(pSMB, byte_count);
5435 pSMB->ByteCount = cpu_to_le16(byte_count);
5437 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5438 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5440 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5441 } else { /* decode response */
5442 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5444 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5445 rc = -EIO; /* bad smb */
5447 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5449 (FILE_SYSTEM_POSIX_INFO
5450 *) (((char *) &pSMBr->hdr.Protocol) +
5453 le32_to_cpu(response_data->BlockSize);
5455 le64_to_cpu(response_data->TotalBlocks);
5457 le64_to_cpu(response_data->BlocksAvail);
5458 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5459 FSData->f_bavail = FSData->f_bfree;
5462 le64_to_cpu(response_data->UserBlocksAvail);
5464 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5466 le64_to_cpu(response_data->TotalFileNodes);
5467 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5469 le64_to_cpu(response_data->FreeFileNodes);
5472 cifs_buf_release(pSMB);
5481 /* We can not use write of zero bytes trick to
5482 set file size due to need for large file support. Also note that
5483 this SetPathInfo is preferred to SetFileInfo based method in next
5484 routine which is only needed to work around a sharing violation bug
5485 in Samba which this routine can run into */
5488 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5489 __u64 size, bool SetAllocation,
5490 const struct nls_table *nls_codepage, int remap)
5492 struct smb_com_transaction2_spi_req *pSMB = NULL;
5493 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5494 struct file_end_of_file_info *parm_data;
5497 int bytes_returned = 0;
5498 __u16 params, byte_count, data_count, param_offset, offset;
5500 cFYI(1, "In SetEOF");
5502 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5507 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5509 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5510 PATH_MAX, nls_codepage, remap);
5511 name_len++; /* trailing null */
5513 } else { /* BB improve the check for buffer overruns BB */
5514 name_len = strnlen(fileName, PATH_MAX);
5515 name_len++; /* trailing null */
5516 strncpy(pSMB->FileName, fileName, name_len);
5518 params = 6 + name_len;
5519 data_count = sizeof(struct file_end_of_file_info);
5520 pSMB->MaxParameterCount = cpu_to_le16(2);
5521 pSMB->MaxDataCount = cpu_to_le16(4100);
5522 pSMB->MaxSetupCount = 0;
5526 pSMB->Reserved2 = 0;
5527 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5528 InformationLevel) - 4;
5529 offset = param_offset + params;
5530 if (SetAllocation) {
5531 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5532 pSMB->InformationLevel =
5533 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5535 pSMB->InformationLevel =
5536 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5537 } else /* Set File Size */ {
5538 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5539 pSMB->InformationLevel =
5540 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5542 pSMB->InformationLevel =
5543 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5547 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5549 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5550 pSMB->DataOffset = cpu_to_le16(offset);
5551 pSMB->SetupCount = 1;
5552 pSMB->Reserved3 = 0;
5553 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5554 byte_count = 3 /* pad */ + params + data_count;
5555 pSMB->DataCount = cpu_to_le16(data_count);
5556 pSMB->TotalDataCount = pSMB->DataCount;
5557 pSMB->ParameterCount = cpu_to_le16(params);
5558 pSMB->TotalParameterCount = pSMB->ParameterCount;
5559 pSMB->Reserved4 = 0;
5560 inc_rfc1001_len(pSMB, byte_count);
5561 parm_data->FileSize = cpu_to_le64(size);
5562 pSMB->ByteCount = cpu_to_le16(byte_count);
5563 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5564 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5566 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5568 cifs_buf_release(pSMB);
5577 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5578 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5580 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5581 struct file_end_of_file_info *parm_data;
5583 __u16 params, param_offset, offset, byte_count, count;
5585 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5587 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5592 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5593 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5596 pSMB->MaxSetupCount = 0;
5600 pSMB->Reserved2 = 0;
5601 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5602 offset = param_offset + params;
5604 count = sizeof(struct file_end_of_file_info);
5605 pSMB->MaxParameterCount = cpu_to_le16(2);
5606 /* BB find exact max SMB PDU from sess structure BB */
5607 pSMB->MaxDataCount = cpu_to_le16(1000);
5608 pSMB->SetupCount = 1;
5609 pSMB->Reserved3 = 0;
5610 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5611 byte_count = 3 /* pad */ + params + count;
5612 pSMB->DataCount = cpu_to_le16(count);
5613 pSMB->ParameterCount = cpu_to_le16(params);
5614 pSMB->TotalDataCount = pSMB->DataCount;
5615 pSMB->TotalParameterCount = pSMB->ParameterCount;
5616 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5618 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5620 pSMB->DataOffset = cpu_to_le16(offset);
5621 parm_data->FileSize = cpu_to_le64(size);
5623 if (SetAllocation) {
5624 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5625 pSMB->InformationLevel =
5626 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5628 pSMB->InformationLevel =
5629 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5630 } else /* Set File Size */ {
5631 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5632 pSMB->InformationLevel =
5633 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5635 pSMB->InformationLevel =
5636 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5638 pSMB->Reserved4 = 0;
5639 inc_rfc1001_len(pSMB, byte_count);
5640 pSMB->ByteCount = cpu_to_le16(byte_count);
5641 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5643 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5646 /* Note: On -EAGAIN error only caller can retry on handle based calls
5647 since file handle passed in no longer valid */
5652 /* Some legacy servers such as NT4 require that the file times be set on
5653 an open handle, rather than by pathname - this is awkward due to
5654 potential access conflicts on the open, but it is unavoidable for these
5655 old servers since the only other choice is to go from 100 nanosecond DCE
5656 time and resort to the original setpathinfo level which takes the ancient
5657 DOS time format with 2 second granularity */
5659 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5660 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5662 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5665 __u16 params, param_offset, offset, byte_count, count;
5667 cFYI(1, "Set Times (via SetFileInfo)");
5668 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5673 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5674 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5677 pSMB->MaxSetupCount = 0;
5681 pSMB->Reserved2 = 0;
5682 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5683 offset = param_offset + params;
5685 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5687 count = sizeof(FILE_BASIC_INFO);
5688 pSMB->MaxParameterCount = cpu_to_le16(2);
5689 /* BB find max SMB PDU from sess */
5690 pSMB->MaxDataCount = cpu_to_le16(1000);
5691 pSMB->SetupCount = 1;
5692 pSMB->Reserved3 = 0;
5693 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5694 byte_count = 3 /* pad */ + params + count;
5695 pSMB->DataCount = cpu_to_le16(count);
5696 pSMB->ParameterCount = cpu_to_le16(params);
5697 pSMB->TotalDataCount = pSMB->DataCount;
5698 pSMB->TotalParameterCount = pSMB->ParameterCount;
5699 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5700 pSMB->DataOffset = cpu_to_le16(offset);
5702 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5703 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5705 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5706 pSMB->Reserved4 = 0;
5707 inc_rfc1001_len(pSMB, byte_count);
5708 pSMB->ByteCount = cpu_to_le16(byte_count);
5709 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5710 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5712 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5714 /* Note: On -EAGAIN error only caller can retry on handle based calls
5715 since file handle passed in no longer valid */
5721 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5722 bool delete_file, __u16 fid, __u32 pid_of_opener)
5724 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5727 __u16 params, param_offset, offset, byte_count, count;
5729 cFYI(1, "Set File Disposition (via SetFileInfo)");
5730 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5735 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5736 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5739 pSMB->MaxSetupCount = 0;
5743 pSMB->Reserved2 = 0;
5744 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5745 offset = param_offset + params;
5747 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5750 pSMB->MaxParameterCount = cpu_to_le16(2);
5751 /* BB find max SMB PDU from sess */
5752 pSMB->MaxDataCount = cpu_to_le16(1000);
5753 pSMB->SetupCount = 1;
5754 pSMB->Reserved3 = 0;
5755 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5756 byte_count = 3 /* pad */ + params + count;
5757 pSMB->DataCount = cpu_to_le16(count);
5758 pSMB->ParameterCount = cpu_to_le16(params);
5759 pSMB->TotalDataCount = pSMB->DataCount;
5760 pSMB->TotalParameterCount = pSMB->ParameterCount;
5761 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5762 pSMB->DataOffset = cpu_to_le16(offset);
5764 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5765 pSMB->Reserved4 = 0;
5766 inc_rfc1001_len(pSMB, byte_count);
5767 pSMB->ByteCount = cpu_to_le16(byte_count);
5768 *data_offset = delete_file ? 1 : 0;
5769 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5771 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5777 CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
5778 const char *fileName, const FILE_BASIC_INFO *data,
5779 const struct nls_table *nls_codepage, int remap)
5781 TRANSACTION2_SPI_REQ *pSMB = NULL;
5782 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5785 int bytes_returned = 0;
5787 __u16 params, param_offset, offset, byte_count, count;
5789 cFYI(1, "In SetTimes");
5792 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5797 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5799 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5800 PATH_MAX, nls_codepage, remap);
5801 name_len++; /* trailing null */
5803 } else { /* BB improve the check for buffer overruns BB */
5804 name_len = strnlen(fileName, PATH_MAX);
5805 name_len++; /* trailing null */
5806 strncpy(pSMB->FileName, fileName, name_len);
5809 params = 6 + name_len;
5810 count = sizeof(FILE_BASIC_INFO);
5811 pSMB->MaxParameterCount = cpu_to_le16(2);
5812 /* BB find max SMB PDU from sess structure BB */
5813 pSMB->MaxDataCount = cpu_to_le16(1000);
5814 pSMB->MaxSetupCount = 0;
5818 pSMB->Reserved2 = 0;
5819 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5820 InformationLevel) - 4;
5821 offset = param_offset + params;
5822 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5823 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5824 pSMB->DataOffset = cpu_to_le16(offset);
5825 pSMB->SetupCount = 1;
5826 pSMB->Reserved3 = 0;
5827 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5828 byte_count = 3 /* pad */ + params + count;
5830 pSMB->DataCount = cpu_to_le16(count);
5831 pSMB->ParameterCount = cpu_to_le16(params);
5832 pSMB->TotalDataCount = pSMB->DataCount;
5833 pSMB->TotalParameterCount = pSMB->ParameterCount;
5834 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5835 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5837 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5838 pSMB->Reserved4 = 0;
5839 inc_rfc1001_len(pSMB, byte_count);
5840 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5841 pSMB->ByteCount = cpu_to_le16(byte_count);
5842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5843 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5845 cFYI(1, "SetPathInfo (times) returned %d", rc);
5847 cifs_buf_release(pSMB);
5855 /* Can not be used to set time stamps yet (due to old DOS time format) */
5856 /* Can be used to set attributes */
5857 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5858 handling it anyway and NT4 was what we thought it would be needed for
5859 Do not delete it until we prove whether needed for Win9x though */
5861 CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
5862 __u16 dos_attrs, const struct nls_table *nls_codepage)
5864 SETATTR_REQ *pSMB = NULL;
5865 SETATTR_RSP *pSMBr = NULL;
5870 cFYI(1, "In SetAttrLegacy");
5873 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5878 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5880 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5881 PATH_MAX, nls_codepage);
5882 name_len++; /* trailing null */
5884 } else { /* BB improve the check for buffer overruns BB */
5885 name_len = strnlen(fileName, PATH_MAX);
5886 name_len++; /* trailing null */
5887 strncpy(pSMB->fileName, fileName, name_len);
5889 pSMB->attr = cpu_to_le16(dos_attrs);
5890 pSMB->BufferFormat = 0x04;
5891 inc_rfc1001_len(pSMB, name_len + 1);
5892 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5893 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5894 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5896 cFYI(1, "Error in LegacySetAttr = %d", rc);
5898 cifs_buf_release(pSMB);
5901 goto SetAttrLgcyRetry;
5905 #endif /* temporarily unneeded SetAttr legacy function */
5908 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5909 const struct cifs_unix_set_info_args *args)
5911 u64 mode = args->mode;
5914 * Samba server ignores set of file size to zero due to bugs in some
5915 * older clients, but we should be precise - we use SetFileSize to
5916 * set file size and do not want to truncate file size to zero
5917 * accidentally as happened on one Samba server beta by putting
5918 * zero instead of -1 here
5920 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5921 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5922 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5923 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5924 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5925 data_offset->Uid = cpu_to_le64(args->uid);
5926 data_offset->Gid = cpu_to_le64(args->gid);
5927 /* better to leave device as zero when it is */
5928 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5929 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5930 data_offset->Permissions = cpu_to_le64(mode);
5933 data_offset->Type = cpu_to_le32(UNIX_FILE);
5934 else if (S_ISDIR(mode))
5935 data_offset->Type = cpu_to_le32(UNIX_DIR);
5936 else if (S_ISLNK(mode))
5937 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5938 else if (S_ISCHR(mode))
5939 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5940 else if (S_ISBLK(mode))
5941 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5942 else if (S_ISFIFO(mode))
5943 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5944 else if (S_ISSOCK(mode))
5945 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5949 CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
5950 const struct cifs_unix_set_info_args *args,
5951 u16 fid, u32 pid_of_opener)
5953 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5954 FILE_UNIX_BASIC_INFO *data_offset;
5956 u16 params, param_offset, offset, byte_count, count;
5958 cFYI(1, "Set Unix Info (via SetFileInfo)");
5959 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5964 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5965 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5968 pSMB->MaxSetupCount = 0;
5972 pSMB->Reserved2 = 0;
5973 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5974 offset = param_offset + params;
5976 data_offset = (FILE_UNIX_BASIC_INFO *)
5977 ((char *)(&pSMB->hdr.Protocol) + offset);
5978 count = sizeof(FILE_UNIX_BASIC_INFO);
5980 pSMB->MaxParameterCount = cpu_to_le16(2);
5981 /* BB find max SMB PDU from sess */
5982 pSMB->MaxDataCount = cpu_to_le16(1000);
5983 pSMB->SetupCount = 1;
5984 pSMB->Reserved3 = 0;
5985 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5986 byte_count = 3 /* pad */ + params + count;
5987 pSMB->DataCount = cpu_to_le16(count);
5988 pSMB->ParameterCount = cpu_to_le16(params);
5989 pSMB->TotalDataCount = pSMB->DataCount;
5990 pSMB->TotalParameterCount = pSMB->ParameterCount;
5991 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5992 pSMB->DataOffset = cpu_to_le16(offset);
5994 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5995 pSMB->Reserved4 = 0;
5996 inc_rfc1001_len(pSMB, byte_count);
5997 pSMB->ByteCount = cpu_to_le16(byte_count);
5999 cifs_fill_unix_set_info(data_offset, args);
6001 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
6003 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
6005 /* Note: On -EAGAIN error only caller can retry on handle based calls
6006 since file handle passed in no longer valid */
6012 CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
6013 const struct cifs_unix_set_info_args *args,
6014 const struct nls_table *nls_codepage, int remap)
6016 TRANSACTION2_SPI_REQ *pSMB = NULL;
6017 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6020 int bytes_returned = 0;
6021 FILE_UNIX_BASIC_INFO *data_offset;
6022 __u16 params, param_offset, offset, count, byte_count;
6024 cFYI(1, "In SetUID/GID/Mode");
6026 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6031 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6033 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
6034 PATH_MAX, nls_codepage, remap);
6035 name_len++; /* trailing null */
6037 } else { /* BB improve the check for buffer overruns BB */
6038 name_len = strnlen(fileName, PATH_MAX);
6039 name_len++; /* trailing null */
6040 strncpy(pSMB->FileName, fileName, name_len);
6043 params = 6 + name_len;
6044 count = sizeof(FILE_UNIX_BASIC_INFO);
6045 pSMB->MaxParameterCount = cpu_to_le16(2);
6046 /* BB find max SMB PDU from sess structure BB */
6047 pSMB->MaxDataCount = cpu_to_le16(1000);
6048 pSMB->MaxSetupCount = 0;
6052 pSMB->Reserved2 = 0;
6053 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6054 InformationLevel) - 4;
6055 offset = param_offset + params;
6057 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6059 memset(data_offset, 0, count);
6060 pSMB->DataOffset = cpu_to_le16(offset);
6061 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6062 pSMB->SetupCount = 1;
6063 pSMB->Reserved3 = 0;
6064 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6065 byte_count = 3 /* pad */ + params + count;
6066 pSMB->ParameterCount = cpu_to_le16(params);
6067 pSMB->DataCount = cpu_to_le16(count);
6068 pSMB->TotalParameterCount = pSMB->ParameterCount;
6069 pSMB->TotalDataCount = pSMB->DataCount;
6070 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6071 pSMB->Reserved4 = 0;
6072 inc_rfc1001_len(pSMB, byte_count);
6074 cifs_fill_unix_set_info(data_offset, args);
6076 pSMB->ByteCount = cpu_to_le16(byte_count);
6077 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6078 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6080 cFYI(1, "SetPathInfo (perms) returned %d", rc);
6082 cifs_buf_release(pSMB);
6088 #ifdef CONFIG_CIFS_XATTR
6090 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6091 * function used by listxattr and getxattr type calls. When ea_name is set,
6092 * it looks for that attribute name and stuffs that value into the EAData
6093 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6094 * buffer. In both cases, the return value is either the length of the
6095 * resulting data or a negative error code. If EAData is a NULL pointer then
6096 * the data isn't copied to it, but the length is returned.
6099 CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
6100 const unsigned char *searchName, const unsigned char *ea_name,
6101 char *EAData, size_t buf_size,
6102 const struct nls_table *nls_codepage, int remap)
6104 /* BB assumes one setup word */
6105 TRANSACTION2_QPI_REQ *pSMB = NULL;
6106 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6110 struct fealist *ea_response_data;
6111 struct fea *temp_fea;
6114 __u16 params, byte_count, data_offset;
6115 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6117 cFYI(1, "In Query All EAs path %s", searchName);
6119 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6124 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6126 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
6127 PATH_MAX, nls_codepage, remap);
6128 list_len++; /* trailing null */
6130 } else { /* BB improve the check for buffer overruns BB */
6131 list_len = strnlen(searchName, PATH_MAX);
6132 list_len++; /* trailing null */
6133 strncpy(pSMB->FileName, searchName, list_len);
6136 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6137 pSMB->TotalDataCount = 0;
6138 pSMB->MaxParameterCount = cpu_to_le16(2);
6139 /* BB find exact max SMB PDU from sess structure BB */
6140 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6141 pSMB->MaxSetupCount = 0;
6145 pSMB->Reserved2 = 0;
6146 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6147 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6148 pSMB->DataCount = 0;
6149 pSMB->DataOffset = 0;
6150 pSMB->SetupCount = 1;
6151 pSMB->Reserved3 = 0;
6152 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6153 byte_count = params + 1 /* pad */ ;
6154 pSMB->TotalParameterCount = cpu_to_le16(params);
6155 pSMB->ParameterCount = pSMB->TotalParameterCount;
6156 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6157 pSMB->Reserved4 = 0;
6158 inc_rfc1001_len(pSMB, byte_count);
6159 pSMB->ByteCount = cpu_to_le16(byte_count);
6161 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6162 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6164 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6169 /* BB also check enough total bytes returned */
6170 /* BB we need to improve the validity checking
6171 of these trans2 responses */
6173 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6174 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6175 rc = -EIO; /* bad smb */
6179 /* check that length of list is not more than bcc */
6180 /* check that each entry does not go beyond length
6182 /* check that each element of each entry does not
6183 go beyond end of list */
6184 /* validate_trans2_offsets() */
6185 /* BB check if start of smb + data_offset > &bcc+ bcc */
6187 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6188 ea_response_data = (struct fealist *)
6189 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6191 list_len = le32_to_cpu(ea_response_data->list_len);
6192 cFYI(1, "ea length %d", list_len);
6193 if (list_len <= 8) {
6194 cFYI(1, "empty EA list returned from server");
6198 /* make sure list_len doesn't go past end of SMB */
6199 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6200 if ((char *)ea_response_data + list_len > end_of_smb) {
6201 cFYI(1, "EA list appears to go beyond SMB");
6206 /* account for ea list len */
6208 temp_fea = ea_response_data->list;
6209 temp_ptr = (char *)temp_fea;
6210 while (list_len > 0) {
6211 unsigned int name_len;
6216 /* make sure we can read name_len and value_len */
6218 cFYI(1, "EA entry goes beyond length of list");
6223 name_len = temp_fea->name_len;
6224 value_len = le16_to_cpu(temp_fea->value_len);
6225 list_len -= name_len + 1 + value_len;
6227 cFYI(1, "EA entry goes beyond length of list");
6233 if (ea_name_len == name_len &&
6234 memcmp(ea_name, temp_ptr, name_len) == 0) {
6235 temp_ptr += name_len + 1;
6239 if ((size_t)value_len > buf_size) {
6243 memcpy(EAData, temp_ptr, value_len);
6247 /* account for prefix user. and trailing null */
6248 rc += (5 + 1 + name_len);
6249 if (rc < (int) buf_size) {
6250 memcpy(EAData, "user.", 5);
6252 memcpy(EAData, temp_ptr, name_len);
6254 /* null terminate name */
6257 } else if (buf_size == 0) {
6258 /* skip copy - calc size only */
6260 /* stop before overrun buffer */
6265 temp_ptr += name_len + 1 + value_len;
6266 temp_fea = (struct fea *)temp_ptr;
6269 /* didn't find the named attribute */
6274 cifs_buf_release(pSMB);
6282 CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
6283 const char *ea_name, const void *ea_value,
6284 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6287 struct smb_com_transaction2_spi_req *pSMB = NULL;
6288 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6289 struct fealist *parm_data;
6292 int bytes_returned = 0;
6293 __u16 params, param_offset, byte_count, offset, count;
6295 cFYI(1, "In SetEA");
6297 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6302 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6304 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
6305 PATH_MAX, nls_codepage, remap);
6306 name_len++; /* trailing null */
6308 } else { /* BB improve the check for buffer overruns BB */
6309 name_len = strnlen(fileName, PATH_MAX);
6310 name_len++; /* trailing null */
6311 strncpy(pSMB->FileName, fileName, name_len);
6314 params = 6 + name_len;
6316 /* done calculating parms using name_len of file name,
6317 now use name_len to calculate length of ea name
6318 we are going to create in the inode xattrs */
6319 if (ea_name == NULL)
6322 name_len = strnlen(ea_name, 255);
6324 count = sizeof(*parm_data) + ea_value_len + name_len;
6325 pSMB->MaxParameterCount = cpu_to_le16(2);
6326 /* BB find max SMB PDU from sess */
6327 pSMB->MaxDataCount = cpu_to_le16(1000);
6328 pSMB->MaxSetupCount = 0;
6332 pSMB->Reserved2 = 0;
6333 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6334 InformationLevel) - 4;
6335 offset = param_offset + params;
6336 pSMB->InformationLevel =
6337 cpu_to_le16(SMB_SET_FILE_EA);
6340 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6342 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6343 pSMB->DataOffset = cpu_to_le16(offset);
6344 pSMB->SetupCount = 1;
6345 pSMB->Reserved3 = 0;
6346 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6347 byte_count = 3 /* pad */ + params + count;
6348 pSMB->DataCount = cpu_to_le16(count);
6349 parm_data->list_len = cpu_to_le32(count);
6350 parm_data->list[0].EA_flags = 0;
6351 /* we checked above that name len is less than 255 */
6352 parm_data->list[0].name_len = (__u8)name_len;
6353 /* EA names are always ASCII */
6355 strncpy(parm_data->list[0].name, ea_name, name_len);
6356 parm_data->list[0].name[name_len] = 0;
6357 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6358 /* caller ensures that ea_value_len is less than 64K but
6359 we need to ensure that it fits within the smb */
6361 /*BB add length check to see if it would fit in
6362 negotiated SMB buffer size BB */
6363 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6365 memcpy(parm_data->list[0].name+name_len+1,
6366 ea_value, ea_value_len);
6368 pSMB->TotalDataCount = pSMB->DataCount;
6369 pSMB->ParameterCount = cpu_to_le16(params);
6370 pSMB->TotalParameterCount = pSMB->ParameterCount;
6371 pSMB->Reserved4 = 0;
6372 inc_rfc1001_len(pSMB, byte_count);
6373 pSMB->ByteCount = cpu_to_le16(byte_count);
6374 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6375 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6377 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6379 cifs_buf_release(pSMB);
6388 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6390 * Years ago the kernel added a "dnotify" function for Samba server,
6391 * to allow network clients (such as Windows) to display updated
6392 * lists of files in directory listings automatically when
6393 * files are added by one user when another user has the
6394 * same directory open on their desktop. The Linux cifs kernel
6395 * client hooked into the kernel side of this interface for
6396 * the same reason, but ironically when the VFS moved from
6397 * "dnotify" to "inotify" it became harder to plug in Linux
6398 * network file system clients (the most obvious use case
6399 * for notify interfaces is when multiple users can update
6400 * the contents of the same directory - exactly what network
6401 * file systems can do) although the server (Samba) could
6402 * still use it. For the short term we leave the worker
6403 * function ifdeffed out (below) until inotify is fixed
6404 * in the VFS to make it easier to plug in network file
6405 * system clients. If inotify turns out to be permanently
6406 * incompatible for network fs clients, we could instead simply
6407 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6409 int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
6410 const int notify_subdirs, const __u16 netfid,
6411 __u32 filter, struct file *pfile, int multishot,
6412 const struct nls_table *nls_codepage)
6415 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6416 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6417 struct dir_notify_req *dnotify_req;
6420 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6421 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6426 pSMB->TotalParameterCount = 0 ;
6427 pSMB->TotalDataCount = 0;
6428 pSMB->MaxParameterCount = cpu_to_le32(2);
6429 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6430 pSMB->MaxSetupCount = 4;
6432 pSMB->ParameterOffset = 0;
6433 pSMB->DataCount = 0;
6434 pSMB->DataOffset = 0;
6435 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6436 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6437 pSMB->ParameterCount = pSMB->TotalParameterCount;
6439 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6440 pSMB->Reserved2 = 0;
6441 pSMB->CompletionFilter = cpu_to_le32(filter);
6442 pSMB->Fid = netfid; /* file handle always le */
6443 pSMB->ByteCount = 0;
6445 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6446 (struct smb_hdr *)pSMBr, &bytes_returned,
6449 cFYI(1, "Error in Notify = %d", rc);
6451 /* Add file to outstanding requests */
6452 /* BB change to kmem cache alloc */
6453 dnotify_req = kmalloc(
6454 sizeof(struct dir_notify_req),
6457 dnotify_req->Pid = pSMB->hdr.Pid;
6458 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6459 dnotify_req->Mid = pSMB->hdr.Mid;
6460 dnotify_req->Tid = pSMB->hdr.Tid;
6461 dnotify_req->Uid = pSMB->hdr.Uid;
6462 dnotify_req->netfid = netfid;
6463 dnotify_req->pfile = pfile;
6464 dnotify_req->filter = filter;
6465 dnotify_req->multishot = multishot;
6466 spin_lock(&GlobalMid_Lock);
6467 list_add_tail(&dnotify_req->lhead,
6468 &GlobalDnotifyReqList);
6469 spin_unlock(&GlobalMid_Lock);
6473 cifs_buf_release(pSMB);
6476 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */