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 <asm/uaccess.h>
39 #include "cifsproto.h"
40 #include "cifs_unicode.h"
41 #include "cifs_debug.h"
43 #ifdef CONFIG_CIFS_POSIX
48 #ifdef CONFIG_CIFS_WEAK_PW_HASH
49 {LANMAN_PROT, "\2LM1.2X002"},
50 {LANMAN2_PROT, "\2LANMAN2.1"},
51 #endif /* weak password hashing for legacy clients */
52 {CIFS_PROT, "\2NT LM 0.12"},
53 {POSIX_PROT, "\2POSIX 2"},
61 #ifdef CONFIG_CIFS_WEAK_PW_HASH
62 {LANMAN_PROT, "\2LM1.2X002"},
63 {LANMAN2_PROT, "\2LANMAN2.1"},
64 #endif /* weak password hashing for legacy clients */
65 {CIFS_PROT, "\2NT LM 0.12"},
70 /* define the number of elements in the cifs dialect array */
71 #ifdef CONFIG_CIFS_POSIX
72 #ifdef CONFIG_CIFS_WEAK_PW_HASH
73 #define CIFS_NUM_PROT 4
75 #define CIFS_NUM_PROT 2
76 #endif /* CIFS_WEAK_PW_HASH */
78 #ifdef CONFIG_CIFS_WEAK_PW_HASH
79 #define CIFS_NUM_PROT 3
81 #define CIFS_NUM_PROT 1
82 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
83 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head *tmp;
91 struct list_head *tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 spin_lock(&cifs_file_list_lock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
97 open_file->invalidHandle = true;
98 open_file->oplock_break_cancelled = true;
100 spin_unlock(&cifs_file_list_lock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* reconnect the socket, tcon, and smb session if needed */
107 cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
110 struct cifsSesInfo *ses;
111 struct TCP_Server_Info *server;
112 struct nls_table *nls_codepage;
115 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
116 * tcp and smb session status done differently for those three - in the
123 server = ses->server;
126 * only tree disconnect, open, and write, (and ulogoff which does not
127 * have tcon) are allowed as we start force umount
129 if (tcon->tidStatus == CifsExiting) {
130 if (smb_command != SMB_COM_WRITE_ANDX &&
131 smb_command != SMB_COM_OPEN_ANDX &&
132 smb_command != SMB_COM_TREE_DISCONNECT) {
133 cFYI(1, "can not send cmd %d while umounting",
139 if (ses->status == CifsExiting)
143 * Give demultiplex thread up to 10 seconds to reconnect, should be
144 * greater than cifs socket timeout which is 7 seconds
146 while (server->tcpStatus == CifsNeedReconnect) {
147 wait_event_interruptible_timeout(server->response_q,
148 (server->tcpStatus == CifsGood), 10 * HZ);
150 /* is TCP session is reestablished now ?*/
151 if (server->tcpStatus != CifsNeedReconnect)
155 * on "soft" mounts we wait once. Hard mounts keep
156 * retrying until process is killed or server comes
159 if (!tcon->retry || ses->status == CifsExiting) {
160 cFYI(1, "gave up waiting on reconnect in smb_init");
165 if (!ses->need_reconnect && !tcon->need_reconnect)
168 nls_codepage = load_nls_default();
171 * need to prevent multiple threads trying to simultaneously
172 * reconnect the same SMB session
174 mutex_lock(&ses->session_mutex);
175 rc = cifs_negotiate_protocol(0, ses);
176 if (rc == 0 && ses->need_reconnect)
177 rc = cifs_setup_session(0, ses, nls_codepage);
179 /* do we need to reconnect tcon? */
180 if (rc || !tcon->need_reconnect) {
181 mutex_unlock(&ses->session_mutex);
185 mark_open_files_invalid(tcon);
186 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
187 mutex_unlock(&ses->session_mutex);
188 cFYI(1, "reconnect tcon rc = %d", rc);
194 * FIXME: check if wsize needs updated due to negotiated smb buffer
197 atomic_inc(&tconInfoReconnectCount);
199 /* tell server Unix caps we support */
200 if (ses->capabilities & CAP_UNIX)
201 reset_cifs_unix_caps(0, tcon, NULL, NULL);
204 * Removed call to reopen open files here. It is safer (and faster) to
205 * reopen files one at a time as needed in read and write.
207 * FIXME: what about file locks? don't we need to reclaim them ASAP?
212 * Check if handle based operation so we know whether we can continue
213 * or not without returning to caller to reset file handle
215 switch (smb_command) {
216 case SMB_COM_READ_ANDX:
217 case SMB_COM_WRITE_ANDX:
219 case SMB_COM_FIND_CLOSE2:
220 case SMB_COM_LOCKING_ANDX:
224 unload_nls(nls_codepage);
228 /* Allocate and return pointer to an SMB request buffer, and set basic
229 SMB information in the SMB header. If the return code is zero, this
230 function must have filled in request_buf pointer */
232 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
237 rc = cifs_reconnect_tcon(tcon, smb_command);
241 *request_buf = cifs_small_buf_get();
242 if (*request_buf == NULL) {
243 /* BB should we add a retry in here if not a writepage? */
247 header_assemble((struct smb_hdr *) *request_buf, smb_command,
251 cifs_stats_inc(&tcon->num_smbs_sent);
257 small_smb_init_no_tc(const int smb_command, const int wct,
258 struct cifsSesInfo *ses, void **request_buf)
261 struct smb_hdr *buffer;
263 rc = small_smb_init(smb_command, wct, NULL, request_buf);
267 buffer = (struct smb_hdr *)*request_buf;
268 buffer->Mid = GetNextMid(ses->server);
269 if (ses->capabilities & CAP_UNICODE)
270 buffer->Flags2 |= SMBFLG2_UNICODE;
271 if (ses->capabilities & CAP_STATUS32)
272 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
274 /* uid, tid can stay at zero as set in header assemble */
276 /* BB add support for turning on the signing when
277 this function is used after 1st of session setup requests */
282 /* If the return code is zero, this function must fill in request_buf pointer */
284 __smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
285 void **request_buf, void **response_buf)
287 *request_buf = cifs_buf_get();
288 if (*request_buf == NULL) {
289 /* BB should we add a retry in here if not a writepage? */
292 /* Although the original thought was we needed the response buf for */
293 /* potential retries of smb operations it turns out we can determine */
294 /* from the mid flags when the request buffer can be resent without */
295 /* having to use a second distinct buffer for the response */
297 *response_buf = *request_buf;
299 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
303 cifs_stats_inc(&tcon->num_smbs_sent);
308 /* If the return code is zero, this function must fill in request_buf pointer */
310 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
311 void **request_buf, void **response_buf)
315 rc = cifs_reconnect_tcon(tcon, smb_command);
319 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
323 smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
324 void **request_buf, void **response_buf)
326 if (tcon->ses->need_reconnect || tcon->need_reconnect)
329 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
332 static int validate_t2(struct smb_t2_rsp *pSMB)
338 /* check for plausible wct, bcc and t2 data and parm sizes */
339 /* check for parm and data offset going beyond end of smb */
340 if (pSMB->hdr.WordCount >= 10) {
341 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
342 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
343 /* check that bcc is at least as big as parms + data */
344 /* check that bcc is less than negotiated smb buffer */
345 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
346 if (total_size < 512) {
348 le16_to_cpu(pSMB->t2_rsp.DataCount);
349 /* BCC le converted in SendReceive */
350 pBCC = (pSMB->hdr.WordCount * 2) +
351 sizeof(struct smb_hdr) +
353 if ((total_size <= (*(u16 *)pBCC)) &&
355 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
361 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
362 sizeof(struct smb_t2_rsp) + 16);
366 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
369 NEGOTIATE_RSP *pSMBr;
373 struct TCP_Server_Info *server;
375 unsigned int secFlags;
378 server = ses->server;
383 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
384 (void **) &pSMB, (void **) &pSMBr);
388 /* if any of auth flags (ie not sign or seal) are overriden use them */
389 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
390 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
391 else /* if override flags set only sign/seal OR them with global auth */
392 secFlags = global_secflags | ses->overrideSecFlg;
394 cFYI(1, "secFlags 0x%x", secFlags);
396 pSMB->hdr.Mid = GetNextMid(server);
397 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
399 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
400 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
401 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
402 cFYI(1, "Kerberos only mechanism, enable extended security");
403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
404 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
405 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
406 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
407 cFYI(1, "NTLMSSP only mechanism, enable extended security");
408 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
412 for (i = 0; i < CIFS_NUM_PROT; i++) {
413 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
414 count += strlen(protocols[i].name) + 1;
415 /* null at end of source and target buffers anyway */
417 pSMB->hdr.smb_buf_length += count;
418 pSMB->ByteCount = cpu_to_le16(count);
420 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
421 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
425 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
426 cFYI(1, "Dialect: %d", server->dialect);
427 /* Check wct = 1 error case */
428 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
429 /* core returns wct = 1, but we do not ask for core - otherwise
430 small wct just comes when dialect index is -1 indicating we
431 could not negotiate a common dialect */
434 #ifdef CONFIG_CIFS_WEAK_PW_HASH
435 } else if ((pSMBr->hdr.WordCount == 13)
436 && ((server->dialect == LANMAN_PROT)
437 || (server->dialect == LANMAN2_PROT))) {
439 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
441 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
442 (secFlags & CIFSSEC_MAY_PLNTXT))
443 server->secType = LANMAN;
445 cERROR(1, "mount failed weak security disabled"
446 " in /proc/fs/cifs/SecurityFlags");
450 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
451 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
452 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
453 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
454 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
455 /* even though we do not use raw we might as well set this
456 accurately, in case we ever find a need for it */
457 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
458 server->max_rw = 0xFF00;
459 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
461 server->max_rw = 0;/* do not need to use raw anyway */
462 server->capabilities = CAP_MPX_MODE;
464 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
466 /* OS/2 often does not set timezone therefore
467 * we must use server time to calc time zone.
468 * Could deviate slightly from the right zone.
469 * Smallest defined timezone difference is 15 minutes
470 * (i.e. Nepal). Rounding up/down is done to match
473 int val, seconds, remain, result;
474 struct timespec ts, utc;
476 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
477 rsp->SrvTime.Time, 0);
478 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
479 (int)ts.tv_sec, (int)utc.tv_sec,
480 (int)(utc.tv_sec - ts.tv_sec));
481 val = (int)(utc.tv_sec - ts.tv_sec);
483 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
484 remain = seconds % MIN_TZ_ADJ;
485 if (remain >= (MIN_TZ_ADJ / 2))
486 result += MIN_TZ_ADJ;
489 server->timeAdj = result;
491 server->timeAdj = (int)tmp;
492 server->timeAdj *= 60; /* also in seconds */
494 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
497 /* BB get server time for time conversions and add
498 code to use it and timezone since this is not UTC */
500 if (rsp->EncryptionKeyLength ==
501 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
502 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
503 CIFS_CRYPTO_KEY_SIZE);
504 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
505 rc = -EIO; /* need cryptkey unless plain text */
509 cFYI(1, "LANMAN negotiated");
510 /* we will not end up setting signing flags - as no signing
511 was in LANMAN and server did not return the flags on */
513 #else /* weak security disabled */
514 } else if (pSMBr->hdr.WordCount == 13) {
515 cERROR(1, "mount failed, cifs module not built "
516 "with CIFS_WEAK_PW_HASH support");
518 #endif /* WEAK_PW_HASH */
520 } else if (pSMBr->hdr.WordCount != 17) {
525 /* else wct == 17 NTLM */
526 server->secMode = pSMBr->SecurityMode;
527 if ((server->secMode & SECMODE_USER) == 0)
528 cFYI(1, "share mode security");
530 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
531 #ifdef CONFIG_CIFS_WEAK_PW_HASH
532 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
533 #endif /* CIFS_WEAK_PW_HASH */
534 cERROR(1, "Server requests plain text password"
535 " but client support disabled");
537 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
538 server->secType = NTLMv2;
539 else if (secFlags & CIFSSEC_MAY_NTLM)
540 server->secType = NTLM;
541 else if (secFlags & CIFSSEC_MAY_NTLMV2)
542 server->secType = NTLMv2;
543 else if (secFlags & CIFSSEC_MAY_KRB5)
544 server->secType = Kerberos;
545 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
546 server->secType = RawNTLMSSP;
547 else if (secFlags & CIFSSEC_MAY_LANMAN)
548 server->secType = LANMAN;
549 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
550 else if (secFlags & CIFSSEC_MAY_PLNTXT)
555 cERROR(1, "Invalid security type");
558 /* else ... any others ...? */
560 /* one byte, so no need to convert this or EncryptionKeyLen from
562 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
563 /* probably no need to store and check maxvcs */
564 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
565 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
566 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
567 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
568 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
569 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
570 server->timeAdj *= 60;
571 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
572 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
573 CIFS_CRYPTO_KEY_SIZE);
574 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
575 && (pSMBr->EncryptionKeyLength == 0)) {
576 /* decode security blob */
577 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
578 rc = -EIO; /* no crypt key only if plain text pwd */
582 /* BB might be helpful to save off the domain of server here */
584 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
585 (server->capabilities & CAP_EXTENDED_SECURITY)) {
586 count = pSMBr->ByteCount;
591 spin_lock(&cifs_tcp_ses_lock);
592 if (server->srv_count > 1) {
593 spin_unlock(&cifs_tcp_ses_lock);
594 if (memcmp(server->server_GUID,
595 pSMBr->u.extended_response.
597 cFYI(1, "server UID changed");
598 memcpy(server->server_GUID,
599 pSMBr->u.extended_response.GUID,
603 spin_unlock(&cifs_tcp_ses_lock);
604 memcpy(server->server_GUID,
605 pSMBr->u.extended_response.GUID, 16);
609 server->secType = RawNTLMSSP;
611 rc = decode_negTokenInit(pSMBr->u.extended_response.
612 SecurityBlob, count - 16,
618 if (server->secType == Kerberos) {
619 if (!server->sec_kerberos &&
620 !server->sec_mskerberos)
622 } else if (server->secType == RawNTLMSSP) {
623 if (!server->sec_ntlmssp)
629 server->capabilities &= ~CAP_EXTENDED_SECURITY;
631 #ifdef CONFIG_CIFS_WEAK_PW_HASH
634 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
635 /* MUST_SIGN already includes the MAY_SIGN FLAG
636 so if this is zero it means that signing is disabled */
637 cFYI(1, "Signing disabled");
638 if (server->secMode & SECMODE_SIGN_REQUIRED) {
639 cERROR(1, "Server requires "
640 "packet signing to be enabled in "
641 "/proc/fs/cifs/SecurityFlags.");
645 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
646 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
647 /* signing required */
648 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
649 if ((server->secMode &
650 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
651 cERROR(1, "signing required but server lacks support");
654 server->secMode |= SECMODE_SIGN_REQUIRED;
656 /* signing optional ie CIFSSEC_MAY_SIGN */
657 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
659 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
663 cifs_buf_release(pSMB);
665 cFYI(1, "negprot rc %d", rc);
670 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
672 struct smb_hdr *smb_buffer;
675 cFYI(1, "In tree disconnect");
677 /* BB: do we need to check this? These should never be NULL. */
678 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
682 * No need to return error on this operation if tid invalidated and
683 * closed on server already e.g. due to tcp session crashing. Also,
684 * the tcon is no longer on the list, so no need to take lock before
687 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
690 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
691 (void **)&smb_buffer);
695 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
697 cFYI(1, "Tree disconnect failed %d", rc);
699 /* No need to return error on this operation if tid invalidated and
700 closed on server already e.g. due to tcp session crashing */
708 * This is a no-op for now. We're not really interested in the reply, but
709 * rather in the fact that the server sent one and that server->lstrp
712 * FIXME: maybe we should consider checking that the reply matches request?
715 cifs_echo_callback(struct mid_q_entry *mid)
717 struct TCP_Server_Info *server = mid->callback_data;
719 DeleteMidQEntry(mid);
720 atomic_dec(&server->inFlight);
721 wake_up(&server->request_q);
725 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 = cpu_to_le16(0xffff);
738 smb->hdr.WordCount = cpu_to_le16(1);
739 smb->EchoCount = cpu_to_le16(1);
740 smb->ByteCount = cpu_to_le16(1);
742 smb->hdr.smb_buf_length += 3;
744 rc = cifs_call_async(server, (struct smb_hdr *)smb,
745 cifs_echo_callback, server);
747 cFYI(1, "Echo request failed: %d", rc);
749 cifs_small_buf_release(smb);
755 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
757 LOGOFF_ANDX_REQ *pSMB;
760 cFYI(1, "In SMBLogoff for session disconnect");
763 * BB: do we need to check validity of ses and server? They should
764 * always be valid since we have an active reference. If not, that
765 * should probably be a BUG()
767 if (!ses || !ses->server)
770 mutex_lock(&ses->session_mutex);
771 if (ses->need_reconnect)
772 goto session_already_dead; /* no need to send SMBlogoff if uid
773 already closed due to reconnect */
774 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
776 mutex_unlock(&ses->session_mutex);
780 pSMB->hdr.Mid = GetNextMid(ses->server);
782 if (ses->server->secMode &
783 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
784 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
786 pSMB->hdr.Uid = ses->Suid;
788 pSMB->AndXCommand = 0xFF;
789 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
790 session_already_dead:
791 mutex_unlock(&ses->session_mutex);
793 /* if session dead then we do not need to do ulogoff,
794 since server closed smb session, no sense reporting
802 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
803 __u16 type, const struct nls_table *nls_codepage, int remap)
805 TRANSACTION2_SPI_REQ *pSMB = NULL;
806 TRANSACTION2_SPI_RSP *pSMBr = NULL;
807 struct unlink_psx_rq *pRqD;
810 int bytes_returned = 0;
811 __u16 params, param_offset, offset, byte_count;
813 cFYI(1, "In POSIX delete");
815 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
820 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
822 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
823 PATH_MAX, nls_codepage, remap);
824 name_len++; /* trailing null */
826 } else { /* BB add path length overrun check */
827 name_len = strnlen(fileName, PATH_MAX);
828 name_len++; /* trailing null */
829 strncpy(pSMB->FileName, fileName, name_len);
832 params = 6 + name_len;
833 pSMB->MaxParameterCount = cpu_to_le16(2);
834 pSMB->MaxDataCount = 0; /* BB double check this with jra */
835 pSMB->MaxSetupCount = 0;
840 param_offset = offsetof(struct smb_com_transaction2_spi_req,
841 InformationLevel) - 4;
842 offset = param_offset + params;
844 /* Setup pointer to Request Data (inode type) */
845 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
846 pRqD->type = cpu_to_le16(type);
847 pSMB->ParameterOffset = cpu_to_le16(param_offset);
848 pSMB->DataOffset = cpu_to_le16(offset);
849 pSMB->SetupCount = 1;
851 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
852 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
854 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
855 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
856 pSMB->ParameterCount = cpu_to_le16(params);
857 pSMB->TotalParameterCount = pSMB->ParameterCount;
858 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
860 pSMB->hdr.smb_buf_length += byte_count;
861 pSMB->ByteCount = cpu_to_le16(byte_count);
862 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
863 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
865 cFYI(1, "Posix delete returned %d", rc);
866 cifs_buf_release(pSMB);
868 cifs_stats_inc(&tcon->num_deletes);
877 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
878 const struct nls_table *nls_codepage, int remap)
880 DELETE_FILE_REQ *pSMB = NULL;
881 DELETE_FILE_RSP *pSMBr = NULL;
887 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
892 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
894 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
895 PATH_MAX, nls_codepage, remap);
896 name_len++; /* trailing null */
898 } else { /* BB improve check for buffer overruns BB */
899 name_len = strnlen(fileName, PATH_MAX);
900 name_len++; /* trailing null */
901 strncpy(pSMB->fileName, fileName, name_len);
903 pSMB->SearchAttributes =
904 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
905 pSMB->BufferFormat = 0x04;
906 pSMB->hdr.smb_buf_length += name_len + 1;
907 pSMB->ByteCount = cpu_to_le16(name_len + 1);
908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
909 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
910 cifs_stats_inc(&tcon->num_deletes);
912 cFYI(1, "Error in RMFile = %d", rc);
914 cifs_buf_release(pSMB);
922 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
923 const struct nls_table *nls_codepage, int remap)
925 DELETE_DIRECTORY_REQ *pSMB = NULL;
926 DELETE_DIRECTORY_RSP *pSMBr = NULL;
931 cFYI(1, "In CIFSSMBRmDir");
933 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
938 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
939 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
940 PATH_MAX, nls_codepage, remap);
941 name_len++; /* trailing null */
943 } else { /* BB improve check for buffer overruns BB */
944 name_len = strnlen(dirName, PATH_MAX);
945 name_len++; /* trailing null */
946 strncpy(pSMB->DirName, dirName, name_len);
949 pSMB->BufferFormat = 0x04;
950 pSMB->hdr.smb_buf_length += name_len + 1;
951 pSMB->ByteCount = cpu_to_le16(name_len + 1);
952 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
953 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
954 cifs_stats_inc(&tcon->num_rmdirs);
956 cFYI(1, "Error in RMDir = %d", rc);
958 cifs_buf_release(pSMB);
965 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
966 const char *name, const struct nls_table *nls_codepage, int remap)
969 CREATE_DIRECTORY_REQ *pSMB = NULL;
970 CREATE_DIRECTORY_RSP *pSMBr = NULL;
974 cFYI(1, "In CIFSSMBMkDir");
976 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
981 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
982 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
983 PATH_MAX, nls_codepage, remap);
984 name_len++; /* trailing null */
986 } else { /* BB improve check for buffer overruns BB */
987 name_len = strnlen(name, PATH_MAX);
988 name_len++; /* trailing null */
989 strncpy(pSMB->DirName, name, name_len);
992 pSMB->BufferFormat = 0x04;
993 pSMB->hdr.smb_buf_length += name_len + 1;
994 pSMB->ByteCount = cpu_to_le16(name_len + 1);
995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
996 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
997 cifs_stats_inc(&tcon->num_mkdirs);
999 cFYI(1, "Error in Mkdir = %d", rc);
1001 cifs_buf_release(pSMB);
1008 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1009 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1010 __u32 *pOplock, const char *name,
1011 const struct nls_table *nls_codepage, int remap)
1013 TRANSACTION2_SPI_REQ *pSMB = NULL;
1014 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1017 int bytes_returned = 0;
1018 __u16 params, param_offset, offset, byte_count, count;
1019 OPEN_PSX_REQ *pdata;
1020 OPEN_PSX_RSP *psx_rsp;
1022 cFYI(1, "In POSIX Create");
1024 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1029 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1031 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1032 PATH_MAX, nls_codepage, remap);
1033 name_len++; /* trailing null */
1035 } else { /* BB improve the check for buffer overruns BB */
1036 name_len = strnlen(name, PATH_MAX);
1037 name_len++; /* trailing null */
1038 strncpy(pSMB->FileName, name, name_len);
1041 params = 6 + name_len;
1042 count = sizeof(OPEN_PSX_REQ);
1043 pSMB->MaxParameterCount = cpu_to_le16(2);
1044 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1045 pSMB->MaxSetupCount = 0;
1049 pSMB->Reserved2 = 0;
1050 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1051 InformationLevel) - 4;
1052 offset = param_offset + params;
1053 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1054 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1055 pdata->Permissions = cpu_to_le64(mode);
1056 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1057 pdata->OpenFlags = cpu_to_le32(*pOplock);
1058 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1059 pSMB->DataOffset = cpu_to_le16(offset);
1060 pSMB->SetupCount = 1;
1061 pSMB->Reserved3 = 0;
1062 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1063 byte_count = 3 /* pad */ + params + count;
1065 pSMB->DataCount = cpu_to_le16(count);
1066 pSMB->ParameterCount = cpu_to_le16(params);
1067 pSMB->TotalDataCount = pSMB->DataCount;
1068 pSMB->TotalParameterCount = pSMB->ParameterCount;
1069 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1070 pSMB->Reserved4 = 0;
1071 pSMB->hdr.smb_buf_length += byte_count;
1072 pSMB->ByteCount = cpu_to_le16(byte_count);
1073 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1074 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1076 cFYI(1, "Posix create returned %d", rc);
1077 goto psx_create_err;
1080 cFYI(1, "copying inode info");
1081 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1083 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1084 rc = -EIO; /* bad smb */
1085 goto psx_create_err;
1088 /* copy return information to pRetData */
1089 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1090 + le16_to_cpu(pSMBr->t2.DataOffset));
1092 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1094 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1095 /* Let caller know file was created so we can set the mode. */
1096 /* Do we care about the CreateAction in any other cases? */
1097 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1098 *pOplock |= CIFS_CREATE_ACTION;
1099 /* check to make sure response data is there */
1100 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1101 pRetData->Type = cpu_to_le32(-1); /* unknown */
1102 cFYI(DBG2, "unknown type");
1104 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1105 + sizeof(FILE_UNIX_BASIC_INFO)) {
1106 cERROR(1, "Open response data too small");
1107 pRetData->Type = cpu_to_le32(-1);
1108 goto psx_create_err;
1110 memcpy((char *) pRetData,
1111 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1112 sizeof(FILE_UNIX_BASIC_INFO));
1116 cifs_buf_release(pSMB);
1118 if (posix_flags & SMB_O_DIRECTORY)
1119 cifs_stats_inc(&tcon->num_posixmkdirs);
1121 cifs_stats_inc(&tcon->num_posixopens);
1129 static __u16 convert_disposition(int disposition)
1133 switch (disposition) {
1134 case FILE_SUPERSEDE:
1135 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1138 ofun = SMBOPEN_OAPPEND;
1141 ofun = SMBOPEN_OCREATE;
1144 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1146 case FILE_OVERWRITE:
1147 ofun = SMBOPEN_OTRUNC;
1149 case FILE_OVERWRITE_IF:
1150 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1153 cFYI(1, "unknown disposition %d", disposition);
1154 ofun = SMBOPEN_OAPPEND; /* regular open */
1160 access_flags_to_smbopen_mode(const int access_flags)
1162 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1164 if (masked_flags == GENERIC_READ)
1165 return SMBOPEN_READ;
1166 else if (masked_flags == GENERIC_WRITE)
1167 return SMBOPEN_WRITE;
1169 /* just go for read/write */
1170 return SMBOPEN_READWRITE;
1174 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1175 const char *fileName, const int openDisposition,
1176 const int access_flags, const int create_options, __u16 *netfid,
1177 int *pOplock, FILE_ALL_INFO *pfile_info,
1178 const struct nls_table *nls_codepage, int remap)
1181 OPENX_REQ *pSMB = NULL;
1182 OPENX_RSP *pSMBr = NULL;
1188 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1193 pSMB->AndXCommand = 0xFF; /* none */
1195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1196 count = 1; /* account for one byte pad to word boundary */
1198 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1199 fileName, PATH_MAX, nls_codepage, remap);
1200 name_len++; /* trailing null */
1202 } else { /* BB improve check for buffer overruns BB */
1203 count = 0; /* no pad */
1204 name_len = strnlen(fileName, PATH_MAX);
1205 name_len++; /* trailing null */
1206 strncpy(pSMB->fileName, fileName, name_len);
1208 if (*pOplock & REQ_OPLOCK)
1209 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1210 else if (*pOplock & REQ_BATCHOPLOCK)
1211 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1213 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1214 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1215 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1216 /* set file as system file if special file such
1217 as fifo and server expecting SFU style and
1218 no Unix extensions */
1220 if (create_options & CREATE_OPTION_SPECIAL)
1221 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1222 else /* BB FIXME BB */
1223 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1225 if (create_options & CREATE_OPTION_READONLY)
1226 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1229 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1230 CREATE_OPTIONS_MASK); */
1231 /* BB FIXME END BB */
1233 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1234 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1236 pSMB->hdr.smb_buf_length += count;
1238 pSMB->ByteCount = cpu_to_le16(count);
1239 /* long_op set to 1 to allow for oplock break timeouts */
1240 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1241 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1242 cifs_stats_inc(&tcon->num_opens);
1244 cFYI(1, "Error in Open = %d", rc);
1246 /* BB verify if wct == 15 */
1248 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1250 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1251 /* Let caller know file was created so we can set the mode. */
1252 /* Do we care about the CreateAction in any other cases? */
1254 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1255 *pOplock |= CIFS_CREATE_ACTION; */
1259 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1260 pfile_info->LastAccessTime = 0; /* BB fixme */
1261 pfile_info->LastWriteTime = 0; /* BB fixme */
1262 pfile_info->ChangeTime = 0; /* BB fixme */
1263 pfile_info->Attributes =
1264 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1265 /* the file_info buf is endian converted by caller */
1266 pfile_info->AllocationSize =
1267 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1268 pfile_info->EndOfFile = pfile_info->AllocationSize;
1269 pfile_info->NumberOfLinks = cpu_to_le32(1);
1270 pfile_info->DeletePending = 0;
1274 cifs_buf_release(pSMB);
1281 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1282 const char *fileName, const int openDisposition,
1283 const int access_flags, const int create_options, __u16 *netfid,
1284 int *pOplock, FILE_ALL_INFO *pfile_info,
1285 const struct nls_table *nls_codepage, int remap)
1288 OPEN_REQ *pSMB = NULL;
1289 OPEN_RSP *pSMBr = NULL;
1295 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1300 pSMB->AndXCommand = 0xFF; /* none */
1302 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1303 count = 1; /* account for one byte pad to word boundary */
1305 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1306 fileName, PATH_MAX, nls_codepage, remap);
1307 name_len++; /* trailing null */
1309 pSMB->NameLength = cpu_to_le16(name_len);
1310 } else { /* BB improve check for buffer overruns BB */
1311 count = 0; /* no pad */
1312 name_len = strnlen(fileName, PATH_MAX);
1313 name_len++; /* trailing null */
1314 pSMB->NameLength = cpu_to_le16(name_len);
1315 strncpy(pSMB->fileName, fileName, name_len);
1317 if (*pOplock & REQ_OPLOCK)
1318 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1319 else if (*pOplock & REQ_BATCHOPLOCK)
1320 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1321 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1322 pSMB->AllocationSize = 0;
1323 /* set file as system file if special file such
1324 as fifo and server expecting SFU style and
1325 no Unix extensions */
1326 if (create_options & CREATE_OPTION_SPECIAL)
1327 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1329 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1331 /* XP does not handle ATTR_POSIX_SEMANTICS */
1332 /* but it helps speed up case sensitive checks for other
1333 servers such as Samba */
1334 if (tcon->ses->capabilities & CAP_UNIX)
1335 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1337 if (create_options & CREATE_OPTION_READONLY)
1338 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1340 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1341 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1342 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1343 /* BB Expirement with various impersonation levels and verify */
1344 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1345 pSMB->SecurityFlags =
1346 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1349 pSMB->hdr.smb_buf_length += count;
1351 pSMB->ByteCount = cpu_to_le16(count);
1352 /* long_op set to 1 to allow for oplock break timeouts */
1353 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1354 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1355 cifs_stats_inc(&tcon->num_opens);
1357 cFYI(1, "Error in Open = %d", rc);
1359 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1360 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1361 /* Let caller know file was created so we can set the mode. */
1362 /* Do we care about the CreateAction in any other cases? */
1363 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1364 *pOplock |= CIFS_CREATE_ACTION;
1366 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1367 36 /* CreationTime to Attributes */);
1368 /* the file_info buf is endian converted by caller */
1369 pfile_info->AllocationSize = pSMBr->AllocationSize;
1370 pfile_info->EndOfFile = pSMBr->EndOfFile;
1371 pfile_info->NumberOfLinks = cpu_to_le32(1);
1372 pfile_info->DeletePending = 0;
1376 cifs_buf_release(pSMB);
1383 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1384 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1385 char **buf, int *pbuf_type)
1388 READ_REQ *pSMB = NULL;
1389 READ_RSP *pSMBr = NULL;
1390 char *pReadData = NULL;
1392 int resp_buf_type = 0;
1395 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1396 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1399 wct = 10; /* old style read */
1400 if ((lseek >> 32) > 0) {
1401 /* can not handle this big offset for old */
1407 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1411 /* tcon and ses pointer are checked in smb_init */
1412 if (tcon->ses->server == NULL)
1413 return -ECONNABORTED;
1415 pSMB->AndXCommand = 0xFF; /* none */
1417 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1419 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1421 pSMB->Remaining = 0;
1422 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1423 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1425 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1427 /* old style read */
1428 struct smb_com_readx_req *pSMBW =
1429 (struct smb_com_readx_req *)pSMB;
1430 pSMBW->ByteCount = 0;
1433 iov[0].iov_base = (char *)pSMB;
1434 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1435 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1436 &resp_buf_type, CIFS_LOG_ERROR);
1437 cifs_stats_inc(&tcon->num_reads);
1438 pSMBr = (READ_RSP *)iov[0].iov_base;
1440 cERROR(1, "Send error in read = %d", rc);
1442 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1443 data_length = data_length << 16;
1444 data_length += le16_to_cpu(pSMBr->DataLength);
1445 *nbytes = data_length;
1447 /*check that DataLength would not go beyond end of SMB */
1448 if ((data_length > CIFSMaxBufSize)
1449 || (data_length > count)) {
1450 cFYI(1, "bad length %d for count %d",
1451 data_length, count);
1455 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1456 le16_to_cpu(pSMBr->DataOffset);
1457 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1458 cERROR(1, "Faulting on read rc = %d",rc);
1460 }*/ /* can not use copy_to_user when using page cache*/
1462 memcpy(*buf, pReadData, data_length);
1466 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1468 if (resp_buf_type == CIFS_SMALL_BUFFER)
1469 cifs_small_buf_release(iov[0].iov_base);
1470 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1471 cifs_buf_release(iov[0].iov_base);
1472 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1473 /* return buffer to caller to free */
1474 *buf = iov[0].iov_base;
1475 if (resp_buf_type == CIFS_SMALL_BUFFER)
1476 *pbuf_type = CIFS_SMALL_BUFFER;
1477 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1478 *pbuf_type = CIFS_LARGE_BUFFER;
1479 } /* else no valid buffer on return - leave as null */
1481 /* Note: On -EAGAIN error only caller can retry on handle based calls
1482 since file handle passed in no longer valid */
1488 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1489 const int netfid, const unsigned int count,
1490 const __u64 offset, unsigned int *nbytes, const char *buf,
1491 const char __user *ubuf, const int long_op)
1494 WRITE_REQ *pSMB = NULL;
1495 WRITE_RSP *pSMBr = NULL;
1496 int bytes_returned, wct;
1502 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1503 if (tcon->ses == NULL)
1504 return -ECONNABORTED;
1506 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1510 if ((offset >> 32) > 0) {
1511 /* can not handle big offset for old srv */
1516 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1520 /* tcon and ses pointer are checked in smb_init */
1521 if (tcon->ses->server == NULL)
1522 return -ECONNABORTED;
1524 pSMB->AndXCommand = 0xFF; /* none */
1526 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1528 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1530 pSMB->Reserved = 0xFFFFFFFF;
1531 pSMB->WriteMode = 0;
1532 pSMB->Remaining = 0;
1534 /* Can increase buffer size if buffer is big enough in some cases ie we
1535 can send more if LARGE_WRITE_X capability returned by the server and if
1536 our buffer is big enough or if we convert to iovecs on socket writes
1537 and eliminate the copy to the CIFS buffer */
1538 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1539 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1541 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1545 if (bytes_sent > count)
1548 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1550 memcpy(pSMB->Data, buf, bytes_sent);
1552 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1553 cifs_buf_release(pSMB);
1556 } else if (count != 0) {
1558 cifs_buf_release(pSMB);
1560 } /* else setting file size with write of zero bytes */
1562 byte_count = bytes_sent + 1; /* pad */
1563 else /* wct == 12 */
1564 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1566 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1567 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1568 pSMB->hdr.smb_buf_length += byte_count;
1571 pSMB->ByteCount = cpu_to_le16(byte_count);
1572 else { /* old style write has byte count 4 bytes earlier
1574 struct smb_com_writex_req *pSMBW =
1575 (struct smb_com_writex_req *)pSMB;
1576 pSMBW->ByteCount = cpu_to_le16(byte_count);
1579 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1580 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1581 cifs_stats_inc(&tcon->num_writes);
1583 cFYI(1, "Send error in write = %d", rc);
1585 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1586 *nbytes = (*nbytes) << 16;
1587 *nbytes += le16_to_cpu(pSMBr->Count);
1590 * Mask off high 16 bits when bytes written as returned by the
1591 * server is greater than bytes requested by the client. Some
1592 * OS/2 servers are known to set incorrect CountHigh values.
1594 if (*nbytes > count)
1598 cifs_buf_release(pSMB);
1600 /* Note: On -EAGAIN error only caller can retry on handle based calls
1601 since file handle passed in no longer valid */
1607 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1608 const int netfid, const unsigned int count,
1609 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1610 int n_vec, const int long_op)
1613 WRITE_REQ *pSMB = NULL;
1616 int resp_buf_type = 0;
1620 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1622 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1626 if ((offset >> 32) > 0) {
1627 /* can not handle big offset for old srv */
1631 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1634 /* tcon and ses pointer are checked in smb_init */
1635 if (tcon->ses->server == NULL)
1636 return -ECONNABORTED;
1638 pSMB->AndXCommand = 0xFF; /* none */
1640 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1642 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1643 pSMB->Reserved = 0xFFFFFFFF;
1644 pSMB->WriteMode = 0;
1645 pSMB->Remaining = 0;
1648 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1650 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1651 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1652 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1654 pSMB->hdr.smb_buf_length += count+1;
1655 else /* wct == 12 */
1656 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1658 pSMB->ByteCount = cpu_to_le16(count + 1);
1659 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1660 struct smb_com_writex_req *pSMBW =
1661 (struct smb_com_writex_req *)pSMB;
1662 pSMBW->ByteCount = cpu_to_le16(count + 5);
1664 iov[0].iov_base = pSMB;
1666 iov[0].iov_len = smb_hdr_len + 4;
1667 else /* wct == 12 pad bigger by four bytes */
1668 iov[0].iov_len = smb_hdr_len + 8;
1671 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1673 cifs_stats_inc(&tcon->num_writes);
1675 cFYI(1, "Send error Write2 = %d", rc);
1676 } else if (resp_buf_type == 0) {
1677 /* presumably this can not happen, but best to be safe */
1680 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1681 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1682 *nbytes = (*nbytes) << 16;
1683 *nbytes += le16_to_cpu(pSMBr->Count);
1686 * Mask off high 16 bits when bytes written as returned by the
1687 * server is greater than bytes requested by the client. OS/2
1688 * servers are known to set incorrect CountHigh values.
1690 if (*nbytes > count)
1694 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1695 if (resp_buf_type == CIFS_SMALL_BUFFER)
1696 cifs_small_buf_release(iov[0].iov_base);
1697 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1698 cifs_buf_release(iov[0].iov_base);
1700 /* Note: On -EAGAIN error only caller can retry on handle based calls
1701 since file handle passed in no longer valid */
1708 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1709 const __u16 smb_file_id, const __u64 len,
1710 const __u64 offset, const __u32 numUnlock,
1711 const __u32 numLock, const __u8 lockType,
1712 const bool waitFlag, const __u8 oplock_level)
1715 LOCK_REQ *pSMB = NULL;
1716 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1721 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1722 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1727 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1728 timeout = CIFS_ASYNC_OP; /* no response expected */
1730 } else if (waitFlag) {
1731 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1732 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1737 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1738 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1739 pSMB->LockType = lockType;
1740 pSMB->OplockLevel = oplock_level;
1741 pSMB->AndXCommand = 0xFF; /* none */
1742 pSMB->Fid = smb_file_id; /* netfid stays le */
1744 if ((numLock != 0) || (numUnlock != 0)) {
1745 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1746 /* BB where to store pid high? */
1747 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1748 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1749 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1750 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1751 count = sizeof(LOCKING_ANDX_RANGE);
1756 pSMB->hdr.smb_buf_length += count;
1757 pSMB->ByteCount = cpu_to_le16(count);
1760 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1761 (struct smb_hdr *) pSMB, &bytes_returned);
1762 cifs_small_buf_release(pSMB);
1764 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1766 /* SMB buffer freed by function above */
1768 cifs_stats_inc(&tcon->num_locks);
1770 cFYI(1, "Send error in Lock = %d", rc);
1772 /* Note: On -EAGAIN error only caller can retry on handle based calls
1773 since file handle passed in no longer valid */
1778 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1779 const __u16 smb_file_id, const int get_flag, const __u64 len,
1780 struct file_lock *pLockData, const __u16 lock_type,
1781 const bool waitFlag)
1783 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1784 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1785 struct cifs_posix_lock *parm_data;
1788 int bytes_returned = 0;
1789 int resp_buf_type = 0;
1790 __u16 params, param_offset, offset, byte_count, count;
1793 cFYI(1, "Posix Lock");
1795 if (pLockData == NULL)
1798 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1803 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1806 pSMB->MaxSetupCount = 0;
1809 pSMB->Reserved2 = 0;
1810 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1811 offset = param_offset + params;
1813 count = sizeof(struct cifs_posix_lock);
1814 pSMB->MaxParameterCount = cpu_to_le16(2);
1815 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1816 pSMB->SetupCount = 1;
1817 pSMB->Reserved3 = 0;
1819 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1821 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1822 byte_count = 3 /* pad */ + params + count;
1823 pSMB->DataCount = cpu_to_le16(count);
1824 pSMB->ParameterCount = cpu_to_le16(params);
1825 pSMB->TotalDataCount = pSMB->DataCount;
1826 pSMB->TotalParameterCount = pSMB->ParameterCount;
1827 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1828 parm_data = (struct cifs_posix_lock *)
1829 (((char *) &pSMB->hdr.Protocol) + offset);
1831 parm_data->lock_type = cpu_to_le16(lock_type);
1833 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1834 parm_data->lock_flags = cpu_to_le16(1);
1835 pSMB->Timeout = cpu_to_le32(-1);
1839 parm_data->pid = cpu_to_le32(current->tgid);
1840 parm_data->start = cpu_to_le64(pLockData->fl_start);
1841 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1843 pSMB->DataOffset = cpu_to_le16(offset);
1844 pSMB->Fid = smb_file_id;
1845 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1846 pSMB->Reserved4 = 0;
1847 pSMB->hdr.smb_buf_length += byte_count;
1848 pSMB->ByteCount = cpu_to_le16(byte_count);
1850 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1851 (struct smb_hdr *) pSMBr, &bytes_returned);
1853 iov[0].iov_base = (char *)pSMB;
1854 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1855 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1856 &resp_buf_type, timeout);
1857 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1858 not try to free it twice below on exit */
1859 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1863 cFYI(1, "Send error in Posix Lock = %d", rc);
1864 } else if (get_flag) {
1865 /* lock structure can be returned on get */
1868 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1870 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1871 rc = -EIO; /* bad smb */
1874 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1875 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1876 if (data_count < sizeof(struct cifs_posix_lock)) {
1880 parm_data = (struct cifs_posix_lock *)
1881 ((char *)&pSMBr->hdr.Protocol + data_offset);
1882 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1883 pLockData->fl_type = F_UNLCK;
1885 if (parm_data->lock_type ==
1886 __constant_cpu_to_le16(CIFS_RDLCK))
1887 pLockData->fl_type = F_RDLCK;
1888 else if (parm_data->lock_type ==
1889 __constant_cpu_to_le16(CIFS_WRLCK))
1890 pLockData->fl_type = F_WRLCK;
1892 pLockData->fl_start = parm_data->start;
1893 pLockData->fl_end = parm_data->start +
1894 parm_data->length - 1;
1895 pLockData->fl_pid = parm_data->pid;
1901 cifs_small_buf_release(pSMB);
1903 if (resp_buf_type == CIFS_SMALL_BUFFER)
1904 cifs_small_buf_release(iov[0].iov_base);
1905 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1906 cifs_buf_release(iov[0].iov_base);
1908 /* Note: On -EAGAIN error only caller can retry on handle based calls
1909 since file handle passed in no longer valid */
1916 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1919 CLOSE_REQ *pSMB = NULL;
1920 cFYI(1, "In CIFSSMBClose");
1922 /* do not retry on dead session on close */
1923 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1929 pSMB->FileID = (__u16) smb_file_id;
1930 pSMB->LastWriteTime = 0xFFFFFFFF;
1931 pSMB->ByteCount = 0;
1932 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1933 cifs_stats_inc(&tcon->num_closes);
1936 /* EINTR is expected when user ctl-c to kill app */
1937 cERROR(1, "Send error in Close = %d", rc);
1941 /* Since session is dead, file will be closed on server already */
1949 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1952 FLUSH_REQ *pSMB = NULL;
1953 cFYI(1, "In CIFSSMBFlush");
1955 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1959 pSMB->FileID = (__u16) smb_file_id;
1960 pSMB->ByteCount = 0;
1961 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1962 cifs_stats_inc(&tcon->num_flushes);
1964 cERROR(1, "Send error in Flush = %d", rc);
1970 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1971 const char *fromName, const char *toName,
1972 const struct nls_table *nls_codepage, int remap)
1975 RENAME_REQ *pSMB = NULL;
1976 RENAME_RSP *pSMBr = NULL;
1978 int name_len, name_len2;
1981 cFYI(1, "In CIFSSMBRename");
1983 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1988 pSMB->BufferFormat = 0x04;
1989 pSMB->SearchAttributes =
1990 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1993 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1995 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1996 PATH_MAX, nls_codepage, remap);
1997 name_len++; /* trailing null */
1999 pSMB->OldFileName[name_len] = 0x04; /* pad */
2000 /* protocol requires ASCII signature byte on Unicode string */
2001 pSMB->OldFileName[name_len + 1] = 0x00;
2003 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2004 toName, PATH_MAX, nls_codepage, remap);
2005 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2006 name_len2 *= 2; /* convert to bytes */
2007 } else { /* BB improve the check for buffer overruns BB */
2008 name_len = strnlen(fromName, PATH_MAX);
2009 name_len++; /* trailing null */
2010 strncpy(pSMB->OldFileName, fromName, name_len);
2011 name_len2 = strnlen(toName, PATH_MAX);
2012 name_len2++; /* trailing null */
2013 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2014 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2015 name_len2++; /* trailing null */
2016 name_len2++; /* signature byte */
2019 count = 1 /* 1st signature byte */ + name_len + name_len2;
2020 pSMB->hdr.smb_buf_length += count;
2021 pSMB->ByteCount = cpu_to_le16(count);
2023 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2024 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2025 cifs_stats_inc(&tcon->num_renames);
2027 cFYI(1, "Send error in rename = %d", rc);
2029 cifs_buf_release(pSMB);
2037 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2038 int netfid, const char *target_name,
2039 const struct nls_table *nls_codepage, int remap)
2041 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2042 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2043 struct set_file_rename *rename_info;
2045 char dummy_string[30];
2047 int bytes_returned = 0;
2049 __u16 params, param_offset, offset, count, byte_count;
2051 cFYI(1, "Rename to File by handle");
2052 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2058 pSMB->MaxSetupCount = 0;
2062 pSMB->Reserved2 = 0;
2063 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2064 offset = param_offset + params;
2066 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2067 rename_info = (struct set_file_rename *) data_offset;
2068 pSMB->MaxParameterCount = cpu_to_le16(2);
2069 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2070 pSMB->SetupCount = 1;
2071 pSMB->Reserved3 = 0;
2072 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2073 byte_count = 3 /* pad */ + params;
2074 pSMB->ParameterCount = cpu_to_le16(params);
2075 pSMB->TotalParameterCount = pSMB->ParameterCount;
2076 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2077 pSMB->DataOffset = cpu_to_le16(offset);
2078 /* construct random name ".cifs_tmp<inodenum><mid>" */
2079 rename_info->overwrite = cpu_to_le32(1);
2080 rename_info->root_fid = 0;
2081 /* unicode only call */
2082 if (target_name == NULL) {
2083 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2084 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2085 dummy_string, 24, nls_codepage, remap);
2087 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2088 target_name, PATH_MAX, nls_codepage,
2091 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2092 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2093 byte_count += count;
2094 pSMB->DataCount = cpu_to_le16(count);
2095 pSMB->TotalDataCount = pSMB->DataCount;
2097 pSMB->InformationLevel =
2098 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2099 pSMB->Reserved4 = 0;
2100 pSMB->hdr.smb_buf_length += byte_count;
2101 pSMB->ByteCount = cpu_to_le16(byte_count);
2102 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2103 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2104 cifs_stats_inc(&pTcon->num_t2renames);
2106 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2108 cifs_buf_release(pSMB);
2110 /* Note: On -EAGAIN error only caller can retry on handle based calls
2111 since file handle passed in no longer valid */
2117 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2118 const __u16 target_tid, const char *toName, const int flags,
2119 const struct nls_table *nls_codepage, int remap)
2122 COPY_REQ *pSMB = NULL;
2123 COPY_RSP *pSMBr = NULL;
2125 int name_len, name_len2;
2128 cFYI(1, "In CIFSSMBCopy");
2130 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2135 pSMB->BufferFormat = 0x04;
2136 pSMB->Tid2 = target_tid;
2138 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2140 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2141 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2142 fromName, PATH_MAX, nls_codepage,
2144 name_len++; /* trailing null */
2146 pSMB->OldFileName[name_len] = 0x04; /* pad */
2147 /* protocol requires ASCII signature byte on Unicode string */
2148 pSMB->OldFileName[name_len + 1] = 0x00;
2150 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2151 toName, PATH_MAX, nls_codepage, remap);
2152 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2153 name_len2 *= 2; /* convert to bytes */
2154 } else { /* BB improve the check for buffer overruns BB */
2155 name_len = strnlen(fromName, PATH_MAX);
2156 name_len++; /* trailing null */
2157 strncpy(pSMB->OldFileName, fromName, name_len);
2158 name_len2 = strnlen(toName, PATH_MAX);
2159 name_len2++; /* trailing null */
2160 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2161 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2162 name_len2++; /* trailing null */
2163 name_len2++; /* signature byte */
2166 count = 1 /* 1st signature byte */ + name_len + name_len2;
2167 pSMB->hdr.smb_buf_length += count;
2168 pSMB->ByteCount = cpu_to_le16(count);
2170 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2171 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2173 cFYI(1, "Send error in copy = %d with %d files copied",
2174 rc, le16_to_cpu(pSMBr->CopyCount));
2176 cifs_buf_release(pSMB);
2185 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2186 const char *fromName, const char *toName,
2187 const struct nls_table *nls_codepage)
2189 TRANSACTION2_SPI_REQ *pSMB = NULL;
2190 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2193 int name_len_target;
2195 int bytes_returned = 0;
2196 __u16 params, param_offset, offset, byte_count;
2198 cFYI(1, "In Symlink Unix style");
2200 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2205 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2207 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2208 /* find define for this maxpathcomponent */
2210 name_len++; /* trailing null */
2213 } else { /* BB improve the check for buffer overruns BB */
2214 name_len = strnlen(fromName, PATH_MAX);
2215 name_len++; /* trailing null */
2216 strncpy(pSMB->FileName, fromName, name_len);
2218 params = 6 + name_len;
2219 pSMB->MaxSetupCount = 0;
2223 pSMB->Reserved2 = 0;
2224 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2225 InformationLevel) - 4;
2226 offset = param_offset + params;
2228 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2229 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2231 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2232 /* find define for this maxpathcomponent */
2234 name_len_target++; /* trailing null */
2235 name_len_target *= 2;
2236 } else { /* BB improve the check for buffer overruns BB */
2237 name_len_target = strnlen(toName, PATH_MAX);
2238 name_len_target++; /* trailing null */
2239 strncpy(data_offset, toName, name_len_target);
2242 pSMB->MaxParameterCount = cpu_to_le16(2);
2243 /* BB find exact max on data count below from sess */
2244 pSMB->MaxDataCount = cpu_to_le16(1000);
2245 pSMB->SetupCount = 1;
2246 pSMB->Reserved3 = 0;
2247 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2248 byte_count = 3 /* pad */ + params + name_len_target;
2249 pSMB->DataCount = cpu_to_le16(name_len_target);
2250 pSMB->ParameterCount = cpu_to_le16(params);
2251 pSMB->TotalDataCount = pSMB->DataCount;
2252 pSMB->TotalParameterCount = pSMB->ParameterCount;
2253 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2254 pSMB->DataOffset = cpu_to_le16(offset);
2255 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2256 pSMB->Reserved4 = 0;
2257 pSMB->hdr.smb_buf_length += byte_count;
2258 pSMB->ByteCount = cpu_to_le16(byte_count);
2259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2260 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2261 cifs_stats_inc(&tcon->num_symlinks);
2263 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2265 cifs_buf_release(pSMB);
2268 goto createSymLinkRetry;
2274 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2275 const char *fromName, const char *toName,
2276 const struct nls_table *nls_codepage, int remap)
2278 TRANSACTION2_SPI_REQ *pSMB = NULL;
2279 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2282 int name_len_target;
2284 int bytes_returned = 0;
2285 __u16 params, param_offset, offset, byte_count;
2287 cFYI(1, "In Create Hard link Unix style");
2288 createHardLinkRetry:
2289 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2294 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2295 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2296 PATH_MAX, nls_codepage, remap);
2297 name_len++; /* trailing null */
2300 } else { /* BB improve the check for buffer overruns BB */
2301 name_len = strnlen(toName, PATH_MAX);
2302 name_len++; /* trailing null */
2303 strncpy(pSMB->FileName, toName, name_len);
2305 params = 6 + name_len;
2306 pSMB->MaxSetupCount = 0;
2310 pSMB->Reserved2 = 0;
2311 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2312 InformationLevel) - 4;
2313 offset = param_offset + params;
2315 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2316 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2318 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2319 nls_codepage, remap);
2320 name_len_target++; /* trailing null */
2321 name_len_target *= 2;
2322 } else { /* BB improve the check for buffer overruns BB */
2323 name_len_target = strnlen(fromName, PATH_MAX);
2324 name_len_target++; /* trailing null */
2325 strncpy(data_offset, fromName, name_len_target);
2328 pSMB->MaxParameterCount = cpu_to_le16(2);
2329 /* BB find exact max on data count below from sess*/
2330 pSMB->MaxDataCount = cpu_to_le16(1000);
2331 pSMB->SetupCount = 1;
2332 pSMB->Reserved3 = 0;
2333 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2334 byte_count = 3 /* pad */ + params + name_len_target;
2335 pSMB->ParameterCount = cpu_to_le16(params);
2336 pSMB->TotalParameterCount = pSMB->ParameterCount;
2337 pSMB->DataCount = cpu_to_le16(name_len_target);
2338 pSMB->TotalDataCount = pSMB->DataCount;
2339 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2340 pSMB->DataOffset = cpu_to_le16(offset);
2341 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2342 pSMB->Reserved4 = 0;
2343 pSMB->hdr.smb_buf_length += byte_count;
2344 pSMB->ByteCount = cpu_to_le16(byte_count);
2345 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2347 cifs_stats_inc(&tcon->num_hardlinks);
2349 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2351 cifs_buf_release(pSMB);
2353 goto createHardLinkRetry;
2359 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2360 const char *fromName, const char *toName,
2361 const struct nls_table *nls_codepage, int remap)
2364 NT_RENAME_REQ *pSMB = NULL;
2365 RENAME_RSP *pSMBr = NULL;
2367 int name_len, name_len2;
2370 cFYI(1, "In CIFSCreateHardLink");
2371 winCreateHardLinkRetry:
2373 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2378 pSMB->SearchAttributes =
2379 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2381 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2382 pSMB->ClusterCount = 0;
2384 pSMB->BufferFormat = 0x04;
2386 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2388 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2389 PATH_MAX, nls_codepage, remap);
2390 name_len++; /* trailing null */
2393 /* protocol specifies ASCII buffer format (0x04) for unicode */
2394 pSMB->OldFileName[name_len] = 0x04;
2395 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2397 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2398 toName, PATH_MAX, nls_codepage, remap);
2399 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2400 name_len2 *= 2; /* convert to bytes */
2401 } else { /* BB improve the check for buffer overruns BB */
2402 name_len = strnlen(fromName, PATH_MAX);
2403 name_len++; /* trailing null */
2404 strncpy(pSMB->OldFileName, fromName, name_len);
2405 name_len2 = strnlen(toName, PATH_MAX);
2406 name_len2++; /* trailing null */
2407 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2408 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2409 name_len2++; /* trailing null */
2410 name_len2++; /* signature byte */
2413 count = 1 /* string type byte */ + name_len + name_len2;
2414 pSMB->hdr.smb_buf_length += count;
2415 pSMB->ByteCount = cpu_to_le16(count);
2417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2418 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2419 cifs_stats_inc(&tcon->num_hardlinks);
2421 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2423 cifs_buf_release(pSMB);
2425 goto winCreateHardLinkRetry;
2431 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2432 const unsigned char *searchName, char **symlinkinfo,
2433 const struct nls_table *nls_codepage)
2435 /* SMB_QUERY_FILE_UNIX_LINK */
2436 TRANSACTION2_QPI_REQ *pSMB = NULL;
2437 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2441 __u16 params, byte_count;
2444 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2447 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2452 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2454 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2455 PATH_MAX, nls_codepage);
2456 name_len++; /* trailing null */
2458 } else { /* BB improve the check for buffer overruns BB */
2459 name_len = strnlen(searchName, PATH_MAX);
2460 name_len++; /* trailing null */
2461 strncpy(pSMB->FileName, searchName, name_len);
2464 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2465 pSMB->TotalDataCount = 0;
2466 pSMB->MaxParameterCount = cpu_to_le16(2);
2467 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2468 pSMB->MaxSetupCount = 0;
2472 pSMB->Reserved2 = 0;
2473 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2474 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2475 pSMB->DataCount = 0;
2476 pSMB->DataOffset = 0;
2477 pSMB->SetupCount = 1;
2478 pSMB->Reserved3 = 0;
2479 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2480 byte_count = params + 1 /* pad */ ;
2481 pSMB->TotalParameterCount = cpu_to_le16(params);
2482 pSMB->ParameterCount = pSMB->TotalParameterCount;
2483 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2484 pSMB->Reserved4 = 0;
2485 pSMB->hdr.smb_buf_length += byte_count;
2486 pSMB->ByteCount = cpu_to_le16(byte_count);
2488 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2489 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2491 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2493 /* decode response */
2495 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2496 /* BB also check enough total bytes returned */
2497 if (rc || (pSMBr->ByteCount < 2))
2501 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2503 data_start = ((char *) &pSMBr->hdr.Protocol) +
2504 le16_to_cpu(pSMBr->t2.DataOffset);
2506 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2511 /* BB FIXME investigate remapping reserved chars here */
2512 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2513 is_unicode, nls_codepage);
2518 cifs_buf_release(pSMB);
2520 goto querySymLinkRetry;
2524 #ifdef CONFIG_CIFS_EXPERIMENTAL
2526 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2527 const unsigned char *searchName,
2528 char *symlinkinfo, const int buflen, __u16 fid,
2529 const struct nls_table *nls_codepage)
2533 struct smb_com_transaction_ioctl_req *pSMB;
2534 struct smb_com_transaction_ioctl_rsp *pSMBr;
2536 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2537 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2542 pSMB->TotalParameterCount = 0 ;
2543 pSMB->TotalDataCount = 0;
2544 pSMB->MaxParameterCount = cpu_to_le32(2);
2545 /* BB find exact data count max from sess structure BB */
2546 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2547 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2548 pSMB->MaxSetupCount = 4;
2550 pSMB->ParameterOffset = 0;
2551 pSMB->DataCount = 0;
2552 pSMB->DataOffset = 0;
2553 pSMB->SetupCount = 4;
2554 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2555 pSMB->ParameterCount = pSMB->TotalParameterCount;
2556 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2557 pSMB->IsFsctl = 1; /* FSCTL */
2558 pSMB->IsRootFlag = 0;
2559 pSMB->Fid = fid; /* file handle always le */
2560 pSMB->ByteCount = 0;
2562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2563 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2565 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2566 } else { /* decode response */
2567 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2568 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2569 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2570 /* BB also check enough total bytes returned */
2571 rc = -EIO; /* bad smb */
2574 if (data_count && (data_count < 2048)) {
2575 char *end_of_smb = 2 /* sizeof byte count */ +
2576 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2578 struct reparse_data *reparse_buf =
2579 (struct reparse_data *)
2580 ((char *)&pSMBr->hdr.Protocol
2582 if ((char *)reparse_buf >= end_of_smb) {
2586 if ((reparse_buf->LinkNamesBuf +
2587 reparse_buf->TargetNameOffset +
2588 reparse_buf->TargetNameLen) > end_of_smb) {
2589 cFYI(1, "reparse buf beyond SMB");
2594 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2595 cifs_from_ucs2(symlinkinfo, (__le16 *)
2596 (reparse_buf->LinkNamesBuf +
2597 reparse_buf->TargetNameOffset),
2599 reparse_buf->TargetNameLen,
2601 } else { /* ASCII names */
2602 strncpy(symlinkinfo,
2603 reparse_buf->LinkNamesBuf +
2604 reparse_buf->TargetNameOffset,
2605 min_t(const int, buflen,
2606 reparse_buf->TargetNameLen));
2610 cFYI(1, "Invalid return data count on "
2611 "get reparse info ioctl");
2613 symlinkinfo[buflen] = 0; /* just in case so the caller
2614 does not go off the end of the buffer */
2615 cFYI(1, "readlink result - %s", symlinkinfo);
2619 cifs_buf_release(pSMB);
2621 /* Note: On -EAGAIN error only caller can retry on handle based calls
2622 since file handle passed in no longer valid */
2626 #endif /* CIFS_EXPERIMENTAL */
2628 #ifdef CONFIG_CIFS_POSIX
2630 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2631 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2632 struct cifs_posix_ace *cifs_ace)
2634 /* u8 cifs fields do not need le conversion */
2635 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2636 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2637 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2638 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2643 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2644 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2645 const int acl_type, const int size_of_data_area)
2650 struct cifs_posix_ace *pACE;
2651 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2652 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2654 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2657 if (acl_type & ACL_TYPE_ACCESS) {
2658 count = le16_to_cpu(cifs_acl->access_entry_count);
2659 pACE = &cifs_acl->ace_array[0];
2660 size = sizeof(struct cifs_posix_acl);
2661 size += sizeof(struct cifs_posix_ace) * count;
2662 /* check if we would go beyond end of SMB */
2663 if (size_of_data_area < size) {
2664 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2665 size_of_data_area, size);
2668 } else if (acl_type & ACL_TYPE_DEFAULT) {
2669 count = le16_to_cpu(cifs_acl->access_entry_count);
2670 size = sizeof(struct cifs_posix_acl);
2671 size += sizeof(struct cifs_posix_ace) * count;
2672 /* skip past access ACEs to get to default ACEs */
2673 pACE = &cifs_acl->ace_array[count];
2674 count = le16_to_cpu(cifs_acl->default_entry_count);
2675 size += sizeof(struct cifs_posix_ace) * count;
2676 /* check if we would go beyond end of SMB */
2677 if (size_of_data_area < size)
2684 size = posix_acl_xattr_size(count);
2685 if ((buflen == 0) || (local_acl == NULL)) {
2686 /* used to query ACL EA size */
2687 } else if (size > buflen) {
2689 } else /* buffer big enough */ {
2690 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2691 for (i = 0; i < count ; i++) {
2692 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2699 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2700 const posix_acl_xattr_entry *local_ace)
2702 __u16 rc = 0; /* 0 = ACL converted ok */
2704 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2705 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2706 /* BB is there a better way to handle the large uid? */
2707 if (local_ace->e_id == cpu_to_le32(-1)) {
2708 /* Probably no need to le convert -1 on any arch but can not hurt */
2709 cifs_ace->cifs_uid = cpu_to_le64(-1);
2711 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2712 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2716 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2717 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2718 const int buflen, const int acl_type)
2721 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2722 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2726 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2729 count = posix_acl_xattr_count((size_t)buflen);
2730 cFYI(1, "setting acl with %d entries from buf of length %d and "
2732 count, buflen, le32_to_cpu(local_acl->a_version));
2733 if (le32_to_cpu(local_acl->a_version) != 2) {
2734 cFYI(1, "unknown POSIX ACL version %d",
2735 le32_to_cpu(local_acl->a_version));
2738 cifs_acl->version = cpu_to_le16(1);
2739 if (acl_type == ACL_TYPE_ACCESS)
2740 cifs_acl->access_entry_count = cpu_to_le16(count);
2741 else if (acl_type == ACL_TYPE_DEFAULT)
2742 cifs_acl->default_entry_count = cpu_to_le16(count);
2744 cFYI(1, "unknown ACL type %d", acl_type);
2747 for (i = 0; i < count; i++) {
2748 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2749 &local_acl->a_entries[i]);
2751 /* ACE not converted */
2756 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2757 rc += sizeof(struct cifs_posix_acl);
2758 /* BB add check to make sure ACL does not overflow SMB */
2764 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2765 const unsigned char *searchName,
2766 char *acl_inf, const int buflen, const int acl_type,
2767 const struct nls_table *nls_codepage, int remap)
2769 /* SMB_QUERY_POSIX_ACL */
2770 TRANSACTION2_QPI_REQ *pSMB = NULL;
2771 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2775 __u16 params, byte_count;
2777 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2780 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2785 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2787 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2788 PATH_MAX, nls_codepage, remap);
2789 name_len++; /* trailing null */
2791 pSMB->FileName[name_len] = 0;
2792 pSMB->FileName[name_len+1] = 0;
2793 } else { /* BB improve the check for buffer overruns BB */
2794 name_len = strnlen(searchName, PATH_MAX);
2795 name_len++; /* trailing null */
2796 strncpy(pSMB->FileName, searchName, name_len);
2799 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2800 pSMB->TotalDataCount = 0;
2801 pSMB->MaxParameterCount = cpu_to_le16(2);
2802 /* BB find exact max data count below from sess structure BB */
2803 pSMB->MaxDataCount = cpu_to_le16(4000);
2804 pSMB->MaxSetupCount = 0;
2808 pSMB->Reserved2 = 0;
2809 pSMB->ParameterOffset = cpu_to_le16(
2810 offsetof(struct smb_com_transaction2_qpi_req,
2811 InformationLevel) - 4);
2812 pSMB->DataCount = 0;
2813 pSMB->DataOffset = 0;
2814 pSMB->SetupCount = 1;
2815 pSMB->Reserved3 = 0;
2816 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2817 byte_count = params + 1 /* pad */ ;
2818 pSMB->TotalParameterCount = cpu_to_le16(params);
2819 pSMB->ParameterCount = pSMB->TotalParameterCount;
2820 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2821 pSMB->Reserved4 = 0;
2822 pSMB->hdr.smb_buf_length += byte_count;
2823 pSMB->ByteCount = cpu_to_le16(byte_count);
2825 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2826 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2827 cifs_stats_inc(&tcon->num_acl_get);
2829 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2831 /* decode response */
2833 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2834 if (rc || (pSMBr->ByteCount < 2))
2835 /* BB also check enough total bytes returned */
2836 rc = -EIO; /* bad smb */
2838 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2839 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2840 rc = cifs_copy_posix_acl(acl_inf,
2841 (char *)&pSMBr->hdr.Protocol+data_offset,
2842 buflen, acl_type, count);
2845 cifs_buf_release(pSMB);
2852 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2853 const unsigned char *fileName,
2854 const char *local_acl, const int buflen,
2856 const struct nls_table *nls_codepage, int remap)
2858 struct smb_com_transaction2_spi_req *pSMB = NULL;
2859 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2863 int bytes_returned = 0;
2864 __u16 params, byte_count, data_count, param_offset, offset;
2866 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2868 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2872 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2874 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2875 PATH_MAX, nls_codepage, remap);
2876 name_len++; /* trailing null */
2878 } else { /* BB improve the check for buffer overruns BB */
2879 name_len = strnlen(fileName, PATH_MAX);
2880 name_len++; /* trailing null */
2881 strncpy(pSMB->FileName, fileName, name_len);
2883 params = 6 + name_len;
2884 pSMB->MaxParameterCount = cpu_to_le16(2);
2885 /* BB find max SMB size from sess */
2886 pSMB->MaxDataCount = cpu_to_le16(1000);
2887 pSMB->MaxSetupCount = 0;
2891 pSMB->Reserved2 = 0;
2892 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2893 InformationLevel) - 4;
2894 offset = param_offset + params;
2895 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2896 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2898 /* convert to on the wire format for POSIX ACL */
2899 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2901 if (data_count == 0) {
2903 goto setACLerrorExit;
2905 pSMB->DataOffset = cpu_to_le16(offset);
2906 pSMB->SetupCount = 1;
2907 pSMB->Reserved3 = 0;
2908 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2909 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2910 byte_count = 3 /* pad */ + params + data_count;
2911 pSMB->DataCount = cpu_to_le16(data_count);
2912 pSMB->TotalDataCount = pSMB->DataCount;
2913 pSMB->ParameterCount = cpu_to_le16(params);
2914 pSMB->TotalParameterCount = pSMB->ParameterCount;
2915 pSMB->Reserved4 = 0;
2916 pSMB->hdr.smb_buf_length += byte_count;
2917 pSMB->ByteCount = cpu_to_le16(byte_count);
2918 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2919 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2921 cFYI(1, "Set POSIX ACL returned %d", rc);
2924 cifs_buf_release(pSMB);
2930 /* BB fix tabs in this function FIXME BB */
2932 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2933 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2936 struct smb_t2_qfi_req *pSMB = NULL;
2937 struct smb_t2_qfi_rsp *pSMBr = NULL;
2939 __u16 params, byte_count;
2941 cFYI(1, "In GetExtAttr");
2946 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2951 params = 2 /* level */ + 2 /* fid */;
2952 pSMB->t2.TotalDataCount = 0;
2953 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2954 /* BB find exact max data count below from sess structure BB */
2955 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2956 pSMB->t2.MaxSetupCount = 0;
2957 pSMB->t2.Reserved = 0;
2959 pSMB->t2.Timeout = 0;
2960 pSMB->t2.Reserved2 = 0;
2961 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2963 pSMB->t2.DataCount = 0;
2964 pSMB->t2.DataOffset = 0;
2965 pSMB->t2.SetupCount = 1;
2966 pSMB->t2.Reserved3 = 0;
2967 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2968 byte_count = params + 1 /* pad */ ;
2969 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2970 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2971 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2974 pSMB->hdr.smb_buf_length += byte_count;
2975 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2977 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2978 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2980 cFYI(1, "error %d in GetExtAttr", rc);
2982 /* decode response */
2983 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2984 if (rc || (pSMBr->ByteCount < 2))
2985 /* BB also check enough total bytes returned */
2986 /* If rc should we check for EOPNOSUPP and
2987 disable the srvino flag? or in caller? */
2988 rc = -EIO; /* bad smb */
2990 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2991 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2992 struct file_chattr_info *pfinfo;
2993 /* BB Do we need a cast or hash here ? */
2995 cFYI(1, "Illegal size ret in GetExtAttr");
2999 pfinfo = (struct file_chattr_info *)
3000 (data_offset + (char *) &pSMBr->hdr.Protocol);
3001 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3002 *pMask = le64_to_cpu(pfinfo->mask);
3006 cifs_buf_release(pSMB);
3008 goto GetExtAttrRetry;
3012 #endif /* CONFIG_POSIX */
3014 #ifdef CONFIG_CIFS_ACL
3016 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3017 * all NT TRANSACTS that we init here have total parm and data under about 400
3018 * bytes (to fit in small cifs buffer size), which is the case so far, it
3019 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3020 * returned setup area) and MaxParameterCount (returned parms size) must be set
3024 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3025 const int parm_len, struct cifsTconInfo *tcon,
3030 struct smb_com_ntransact_req *pSMB;
3032 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3036 *ret_buf = (void *)pSMB;
3038 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3039 pSMB->TotalDataCount = 0;
3040 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
3041 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3042 pSMB->ParameterCount = pSMB->TotalParameterCount;
3043 pSMB->DataCount = pSMB->TotalDataCount;
3044 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3045 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3046 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3047 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3048 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3049 pSMB->SubCommand = cpu_to_le16(sub_command);
3054 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3055 __u32 *pparmlen, __u32 *pdatalen)
3058 __u32 data_count, data_offset, parm_count, parm_offset;
3059 struct smb_com_ntransact_rsp *pSMBr;
3067 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3069 /* ByteCount was converted from little endian in SendReceive */
3070 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
3071 (char *)&pSMBr->ByteCount;
3073 data_offset = le32_to_cpu(pSMBr->DataOffset);
3074 data_count = le32_to_cpu(pSMBr->DataCount);
3075 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3076 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3078 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3079 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3081 /* should we also check that parm and data areas do not overlap? */
3082 if (*ppparm > end_of_smb) {
3083 cFYI(1, "parms start after end of smb");
3085 } else if (parm_count + *ppparm > end_of_smb) {
3086 cFYI(1, "parm end after end of smb");
3088 } else if (*ppdata > end_of_smb) {
3089 cFYI(1, "data starts after end of smb");
3091 } else if (data_count + *ppdata > end_of_smb) {
3092 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3093 *ppdata, data_count, (data_count + *ppdata),
3096 } else if (parm_count + data_count > pSMBr->ByteCount) {
3097 cFYI(1, "parm count and data count larger than SMB");
3100 *pdatalen = data_count;
3101 *pparmlen = parm_count;
3105 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3107 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3108 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3112 QUERY_SEC_DESC_REQ *pSMB;
3115 cFYI(1, "GetCifsACL");
3120 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3121 8 /* parm len */, tcon, (void **) &pSMB);
3125 pSMB->MaxParameterCount = cpu_to_le32(4);
3126 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3127 pSMB->MaxSetupCount = 0;
3128 pSMB->Fid = fid; /* file handle always le */
3129 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3131 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3132 pSMB->hdr.smb_buf_length += 11;
3133 iov[0].iov_base = (char *)pSMB;
3134 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3136 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3138 cifs_stats_inc(&tcon->num_acl_get);
3140 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3141 } else { /* decode response */
3145 struct smb_com_ntransact_rsp *pSMBr;
3148 /* validate_nttransact */
3149 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3150 &pdata, &parm_len, pbuflen);
3153 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3155 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3157 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3158 rc = -EIO; /* bad smb */
3163 /* BB check that data area is minimum length and as big as acl_len */
3165 acl_len = le32_to_cpu(*parm);
3166 if (acl_len != *pbuflen) {
3167 cERROR(1, "acl length %d does not match %d",
3169 if (*pbuflen > acl_len)
3173 /* check if buffer is big enough for the acl
3174 header followed by the smallest SID */
3175 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3176 (*pbuflen >= 64 * 1024)) {
3177 cERROR(1, "bad acl length %d", *pbuflen);
3181 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3182 if (*acl_inf == NULL) {
3186 memcpy(*acl_inf, pdata, *pbuflen);
3190 if (buf_type == CIFS_SMALL_BUFFER)
3191 cifs_small_buf_release(iov[0].iov_base);
3192 else if (buf_type == CIFS_LARGE_BUFFER)
3193 cifs_buf_release(iov[0].iov_base);
3194 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3199 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3200 struct cifs_ntsd *pntsd, __u32 acllen)
3202 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3204 int bytes_returned = 0;
3205 SET_SEC_DESC_REQ *pSMB = NULL;
3206 NTRANSACT_RSP *pSMBr = NULL;
3209 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3214 pSMB->MaxSetupCount = 0;
3218 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3219 data_count = acllen;
3220 data_offset = param_offset + param_count;
3221 byte_count = 3 /* pad */ + param_count;
3223 pSMB->DataCount = cpu_to_le32(data_count);
3224 pSMB->TotalDataCount = pSMB->DataCount;
3225 pSMB->MaxParameterCount = cpu_to_le32(4);
3226 pSMB->MaxDataCount = cpu_to_le32(16384);
3227 pSMB->ParameterCount = cpu_to_le32(param_count);
3228 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3229 pSMB->TotalParameterCount = pSMB->ParameterCount;
3230 pSMB->DataOffset = cpu_to_le32(data_offset);
3231 pSMB->SetupCount = 0;
3232 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3233 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3235 pSMB->Fid = fid; /* file handle always le */
3236 pSMB->Reserved2 = 0;
3237 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3239 if (pntsd && acllen) {
3240 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3243 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3246 pSMB->hdr.smb_buf_length += byte_count;
3248 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3249 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3251 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3253 cFYI(1, "Set CIFS ACL returned %d", rc);
3254 cifs_buf_release(pSMB);
3257 goto setCifsAclRetry;
3262 #endif /* CONFIG_CIFS_ACL */
3264 /* Legacy Query Path Information call for lookup to old servers such
3266 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3267 const unsigned char *searchName,
3268 FILE_ALL_INFO *pFinfo,
3269 const struct nls_table *nls_codepage, int remap)
3271 QUERY_INFORMATION_REQ *pSMB;
3272 QUERY_INFORMATION_RSP *pSMBr;
3277 cFYI(1, "In SMBQPath path %s", searchName);
3279 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3284 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3286 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3287 PATH_MAX, nls_codepage, remap);
3288 name_len++; /* trailing null */
3291 name_len = strnlen(searchName, PATH_MAX);
3292 name_len++; /* trailing null */
3293 strncpy(pSMB->FileName, searchName, name_len);
3295 pSMB->BufferFormat = 0x04;
3296 name_len++; /* account for buffer type byte */
3297 pSMB->hdr.smb_buf_length += (__u16) name_len;
3298 pSMB->ByteCount = cpu_to_le16(name_len);
3300 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3301 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3303 cFYI(1, "Send error in QueryInfo = %d", rc);
3304 } else if (pFinfo) {
3306 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3308 /* decode response */
3309 /* BB FIXME - add time zone adjustment BB */
3310 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3313 /* decode time fields */
3314 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3315 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3316 pFinfo->LastAccessTime = 0;
3317 pFinfo->AllocationSize =
3318 cpu_to_le64(le32_to_cpu(pSMBr->size));
3319 pFinfo->EndOfFile = pFinfo->AllocationSize;
3320 pFinfo->Attributes =
3321 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3323 rc = -EIO; /* bad buffer passed in */
3325 cifs_buf_release(pSMB);
3334 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3335 u16 netfid, FILE_ALL_INFO *pFindData)
3337 struct smb_t2_qfi_req *pSMB = NULL;
3338 struct smb_t2_qfi_rsp *pSMBr = NULL;
3341 __u16 params, byte_count;
3344 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3349 params = 2 /* level */ + 2 /* fid */;
3350 pSMB->t2.TotalDataCount = 0;
3351 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3352 /* BB find exact max data count below from sess structure BB */
3353 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3354 pSMB->t2.MaxSetupCount = 0;
3355 pSMB->t2.Reserved = 0;
3357 pSMB->t2.Timeout = 0;
3358 pSMB->t2.Reserved2 = 0;
3359 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3361 pSMB->t2.DataCount = 0;
3362 pSMB->t2.DataOffset = 0;
3363 pSMB->t2.SetupCount = 1;
3364 pSMB->t2.Reserved3 = 0;
3365 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3366 byte_count = params + 1 /* pad */ ;
3367 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3368 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3369 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3372 pSMB->hdr.smb_buf_length += byte_count;
3374 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3375 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3377 cFYI(1, "Send error in QPathInfo = %d", rc);
3378 } else { /* decode response */
3379 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3381 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3383 else if (pSMBr->ByteCount < 40)
3384 rc = -EIO; /* bad smb */
3385 else if (pFindData) {
3386 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3387 memcpy((char *) pFindData,
3388 (char *) &pSMBr->hdr.Protocol +
3389 data_offset, sizeof(FILE_ALL_INFO));
3393 cifs_buf_release(pSMB);
3395 goto QFileInfoRetry;
3401 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3402 const unsigned char *searchName,
3403 FILE_ALL_INFO *pFindData,
3404 int legacy /* old style infolevel */,
3405 const struct nls_table *nls_codepage, int remap)
3407 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3408 TRANSACTION2_QPI_REQ *pSMB = NULL;
3409 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3413 __u16 params, byte_count;
3415 /* cFYI(1, "In QPathInfo path %s", searchName); */
3417 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3422 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3424 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3425 PATH_MAX, nls_codepage, remap);
3426 name_len++; /* trailing null */
3428 } else { /* BB improve the check for buffer overruns BB */
3429 name_len = strnlen(searchName, PATH_MAX);
3430 name_len++; /* trailing null */
3431 strncpy(pSMB->FileName, searchName, name_len);
3434 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3435 pSMB->TotalDataCount = 0;
3436 pSMB->MaxParameterCount = cpu_to_le16(2);
3437 /* BB find exact max SMB PDU from sess structure BB */
3438 pSMB->MaxDataCount = cpu_to_le16(4000);
3439 pSMB->MaxSetupCount = 0;
3443 pSMB->Reserved2 = 0;
3444 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3445 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3446 pSMB->DataCount = 0;
3447 pSMB->DataOffset = 0;
3448 pSMB->SetupCount = 1;
3449 pSMB->Reserved3 = 0;
3450 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3451 byte_count = params + 1 /* pad */ ;
3452 pSMB->TotalParameterCount = cpu_to_le16(params);
3453 pSMB->ParameterCount = pSMB->TotalParameterCount;
3455 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3457 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3458 pSMB->Reserved4 = 0;
3459 pSMB->hdr.smb_buf_length += byte_count;
3460 pSMB->ByteCount = cpu_to_le16(byte_count);
3462 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3463 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3465 cFYI(1, "Send error in QPathInfo = %d", rc);
3466 } else { /* decode response */
3467 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3469 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3471 else if (!legacy && (pSMBr->ByteCount < 40))
3472 rc = -EIO; /* bad smb */
3473 else if (legacy && (pSMBr->ByteCount < 24))
3474 rc = -EIO; /* 24 or 26 expected but we do not read
3476 else if (pFindData) {
3478 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3480 /* On legacy responses we do not read the last field,
3481 EAsize, fortunately since it varies by subdialect and
3482 also note it differs on Set vs. Get, ie two bytes or 4
3483 bytes depending but we don't care here */
3485 size = sizeof(FILE_INFO_STANDARD);
3487 size = sizeof(FILE_ALL_INFO);
3488 memcpy((char *) pFindData,
3489 (char *) &pSMBr->hdr.Protocol +
3494 cifs_buf_release(pSMB);
3496 goto QPathInfoRetry;
3502 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3503 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3505 struct smb_t2_qfi_req *pSMB = NULL;
3506 struct smb_t2_qfi_rsp *pSMBr = NULL;
3509 __u16 params, byte_count;
3512 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3517 params = 2 /* level */ + 2 /* fid */;
3518 pSMB->t2.TotalDataCount = 0;
3519 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3520 /* BB find exact max data count below from sess structure BB */
3521 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3522 pSMB->t2.MaxSetupCount = 0;
3523 pSMB->t2.Reserved = 0;
3525 pSMB->t2.Timeout = 0;
3526 pSMB->t2.Reserved2 = 0;
3527 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3529 pSMB->t2.DataCount = 0;
3530 pSMB->t2.DataOffset = 0;
3531 pSMB->t2.SetupCount = 1;
3532 pSMB->t2.Reserved3 = 0;
3533 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3534 byte_count = params + 1 /* pad */ ;
3535 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3536 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3537 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3540 pSMB->hdr.smb_buf_length += byte_count;
3542 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3543 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3545 cFYI(1, "Send error in QPathInfo = %d", rc);
3546 } else { /* decode response */
3547 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3549 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3550 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3551 "Unix Extensions can be disabled on mount "
3552 "by specifying the nosfu mount option.");
3553 rc = -EIO; /* bad smb */
3555 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3556 memcpy((char *) pFindData,
3557 (char *) &pSMBr->hdr.Protocol +
3559 sizeof(FILE_UNIX_BASIC_INFO));
3563 cifs_buf_release(pSMB);
3565 goto UnixQFileInfoRetry;
3571 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3572 const unsigned char *searchName,
3573 FILE_UNIX_BASIC_INFO *pFindData,
3574 const struct nls_table *nls_codepage, int remap)
3576 /* SMB_QUERY_FILE_UNIX_BASIC */
3577 TRANSACTION2_QPI_REQ *pSMB = NULL;
3578 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3580 int bytes_returned = 0;
3582 __u16 params, byte_count;
3584 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3586 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3591 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3593 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3594 PATH_MAX, nls_codepage, remap);
3595 name_len++; /* trailing null */
3597 } else { /* BB improve the check for buffer overruns BB */
3598 name_len = strnlen(searchName, PATH_MAX);
3599 name_len++; /* trailing null */
3600 strncpy(pSMB->FileName, searchName, name_len);
3603 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3604 pSMB->TotalDataCount = 0;
3605 pSMB->MaxParameterCount = cpu_to_le16(2);
3606 /* BB find exact max SMB PDU from sess structure BB */
3607 pSMB->MaxDataCount = cpu_to_le16(4000);
3608 pSMB->MaxSetupCount = 0;
3612 pSMB->Reserved2 = 0;
3613 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3614 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3615 pSMB->DataCount = 0;
3616 pSMB->DataOffset = 0;
3617 pSMB->SetupCount = 1;
3618 pSMB->Reserved3 = 0;
3619 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3620 byte_count = params + 1 /* pad */ ;
3621 pSMB->TotalParameterCount = cpu_to_le16(params);
3622 pSMB->ParameterCount = pSMB->TotalParameterCount;
3623 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3624 pSMB->Reserved4 = 0;
3625 pSMB->hdr.smb_buf_length += byte_count;
3626 pSMB->ByteCount = cpu_to_le16(byte_count);
3628 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3629 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3631 cFYI(1, "Send error in QPathInfo = %d", rc);
3632 } else { /* decode response */
3633 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3635 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3636 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3637 "Unix Extensions can be disabled on mount "
3638 "by specifying the nosfu mount option.");
3639 rc = -EIO; /* bad smb */
3641 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3642 memcpy((char *) pFindData,
3643 (char *) &pSMBr->hdr.Protocol +
3645 sizeof(FILE_UNIX_BASIC_INFO));
3648 cifs_buf_release(pSMB);
3650 goto UnixQPathInfoRetry;
3655 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3657 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3658 const char *searchName,
3659 const struct nls_table *nls_codepage,
3661 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3663 /* level 257 SMB_ */
3664 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3665 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3666 T2_FFIRST_RSP_PARMS *parms;
3668 int bytes_returned = 0;
3670 __u16 params, byte_count;
3672 cFYI(1, "In FindFirst for %s", searchName);
3675 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3680 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3682 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3683 PATH_MAX, nls_codepage, remap);
3684 /* We can not add the asterik earlier in case
3685 it got remapped to 0xF03A as if it were part of the
3686 directory name instead of a wildcard */
3688 pSMB->FileName[name_len] = dirsep;
3689 pSMB->FileName[name_len+1] = 0;
3690 pSMB->FileName[name_len+2] = '*';
3691 pSMB->FileName[name_len+3] = 0;
3692 name_len += 4; /* now the trailing null */
3693 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3694 pSMB->FileName[name_len+1] = 0;
3696 } else { /* BB add check for overrun of SMB buf BB */
3697 name_len = strnlen(searchName, PATH_MAX);
3698 /* BB fix here and in unicode clause above ie
3699 if (name_len > buffersize-header)
3700 free buffer exit; BB */
3701 strncpy(pSMB->FileName, searchName, name_len);
3702 pSMB->FileName[name_len] = dirsep;
3703 pSMB->FileName[name_len+1] = '*';
3704 pSMB->FileName[name_len+2] = 0;
3708 params = 12 + name_len /* includes null */ ;
3709 pSMB->TotalDataCount = 0; /* no EAs */
3710 pSMB->MaxParameterCount = cpu_to_le16(10);
3711 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3712 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3713 pSMB->MaxSetupCount = 0;
3717 pSMB->Reserved2 = 0;
3718 byte_count = params + 1 /* pad */ ;
3719 pSMB->TotalParameterCount = cpu_to_le16(params);
3720 pSMB->ParameterCount = pSMB->TotalParameterCount;
3721 pSMB->ParameterOffset = cpu_to_le16(
3722 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3724 pSMB->DataCount = 0;
3725 pSMB->DataOffset = 0;
3726 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3727 pSMB->Reserved3 = 0;
3728 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3729 pSMB->SearchAttributes =
3730 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3732 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3733 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3734 CIFS_SEARCH_RETURN_RESUME);
3735 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3737 /* BB what should we set StorageType to? Does it matter? BB */
3738 pSMB->SearchStorageType = 0;
3739 pSMB->hdr.smb_buf_length += byte_count;
3740 pSMB->ByteCount = cpu_to_le16(byte_count);
3742 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3743 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3744 cifs_stats_inc(&tcon->num_ffirst);
3746 if (rc) {/* BB add logic to retry regular search if Unix search
3747 rejected unexpectedly by server */
3748 /* BB Add code to handle unsupported level rc */
3749 cFYI(1, "Error in FindFirst = %d", rc);
3751 cifs_buf_release(pSMB);
3753 /* BB eventually could optimize out free and realloc of buf */
3756 goto findFirstRetry;
3757 } else { /* decode response */
3758 /* BB remember to free buffer if error BB */
3759 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3763 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3764 psrch_inf->unicode = true;
3766 psrch_inf->unicode = false;
3768 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3769 psrch_inf->smallBuf = 0;
3770 psrch_inf->srch_entries_start =
3771 (char *) &pSMBr->hdr.Protocol +
3772 le16_to_cpu(pSMBr->t2.DataOffset);
3773 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3774 le16_to_cpu(pSMBr->t2.ParameterOffset));
3776 if (parms->EndofSearch)
3777 psrch_inf->endOfSearch = true;
3779 psrch_inf->endOfSearch = false;
3781 psrch_inf->entries_in_buffer =
3782 le16_to_cpu(parms->SearchCount);
3783 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3784 psrch_inf->entries_in_buffer;
3785 lnoff = le16_to_cpu(parms->LastNameOffset);
3786 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3788 cERROR(1, "ignoring corrupt resume name");
3789 psrch_inf->last_entry = NULL;
3793 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3796 *pnetfid = parms->SearchHandle;
3798 cifs_buf_release(pSMB);
3805 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3806 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3808 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3809 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3810 T2_FNEXT_RSP_PARMS *parms;
3811 char *response_data;
3813 int bytes_returned, name_len;
3814 __u16 params, byte_count;
3816 cFYI(1, "In FindNext");
3818 if (psrch_inf->endOfSearch)
3821 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3826 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3828 pSMB->TotalDataCount = 0; /* no EAs */
3829 pSMB->MaxParameterCount = cpu_to_le16(8);
3830 pSMB->MaxDataCount =
3831 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3833 pSMB->MaxSetupCount = 0;
3837 pSMB->Reserved2 = 0;
3838 pSMB->ParameterOffset = cpu_to_le16(
3839 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3840 pSMB->DataCount = 0;
3841 pSMB->DataOffset = 0;
3842 pSMB->SetupCount = 1;
3843 pSMB->Reserved3 = 0;
3844 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3845 pSMB->SearchHandle = searchHandle; /* always kept as le */
3847 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3848 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3849 pSMB->ResumeKey = psrch_inf->resume_key;
3851 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3853 name_len = psrch_inf->resume_name_len;
3855 if (name_len < PATH_MAX) {
3856 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3857 byte_count += name_len;
3858 /* 14 byte parm len above enough for 2 byte null terminator */
3859 pSMB->ResumeFileName[name_len] = 0;
3860 pSMB->ResumeFileName[name_len+1] = 0;
3863 goto FNext2_err_exit;
3865 byte_count = params + 1 /* pad */ ;
3866 pSMB->TotalParameterCount = cpu_to_le16(params);
3867 pSMB->ParameterCount = pSMB->TotalParameterCount;
3868 pSMB->hdr.smb_buf_length += byte_count;
3869 pSMB->ByteCount = cpu_to_le16(byte_count);
3871 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3872 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3873 cifs_stats_inc(&tcon->num_fnext);
3876 psrch_inf->endOfSearch = true;
3877 cifs_buf_release(pSMB);
3878 rc = 0; /* search probably was closed at end of search*/
3880 cFYI(1, "FindNext returned = %d", rc);
3881 } else { /* decode response */
3882 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3887 /* BB fixme add lock for file (srch_info) struct here */
3888 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3889 psrch_inf->unicode = true;
3891 psrch_inf->unicode = false;
3892 response_data = (char *) &pSMBr->hdr.Protocol +
3893 le16_to_cpu(pSMBr->t2.ParameterOffset);
3894 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3895 response_data = (char *)&pSMBr->hdr.Protocol +
3896 le16_to_cpu(pSMBr->t2.DataOffset);
3897 if (psrch_inf->smallBuf)
3898 cifs_small_buf_release(
3899 psrch_inf->ntwrk_buf_start);
3901 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3902 psrch_inf->srch_entries_start = response_data;
3903 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3904 psrch_inf->smallBuf = 0;
3905 if (parms->EndofSearch)
3906 psrch_inf->endOfSearch = true;
3908 psrch_inf->endOfSearch = false;
3909 psrch_inf->entries_in_buffer =
3910 le16_to_cpu(parms->SearchCount);
3911 psrch_inf->index_of_last_entry +=
3912 psrch_inf->entries_in_buffer;
3913 lnoff = le16_to_cpu(parms->LastNameOffset);
3914 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3916 cERROR(1, "ignoring corrupt resume name");
3917 psrch_inf->last_entry = NULL;
3920 psrch_inf->last_entry =
3921 psrch_inf->srch_entries_start + lnoff;
3923 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3924 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3926 /* BB fixme add unlock here */
3931 /* BB On error, should we leave previous search buf (and count and
3932 last entry fields) intact or free the previous one? */
3934 /* Note: On -EAGAIN error only caller can retry on handle based calls
3935 since file handle passed in no longer valid */
3938 cifs_buf_release(pSMB);
3943 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3944 const __u16 searchHandle)
3947 FINDCLOSE_REQ *pSMB = NULL;
3949 cFYI(1, "In CIFSSMBFindClose");
3950 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3952 /* no sense returning error if session restarted
3953 as file handle has been closed */
3959 pSMB->FileID = searchHandle;
3960 pSMB->ByteCount = 0;
3961 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3963 cERROR(1, "Send error in FindClose = %d", rc);
3965 cifs_stats_inc(&tcon->num_fclose);
3967 /* Since session is dead, search handle closed on server already */
3975 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3976 const unsigned char *searchName,
3977 __u64 *inode_number,
3978 const struct nls_table *nls_codepage, int remap)
3981 TRANSACTION2_QPI_REQ *pSMB = NULL;
3982 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3983 int name_len, bytes_returned;
3984 __u16 params, byte_count;
3986 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3990 GetInodeNumberRetry:
3991 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3996 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3998 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3999 PATH_MAX, nls_codepage, remap);
4000 name_len++; /* trailing null */
4002 } else { /* BB improve the check for buffer overruns BB */
4003 name_len = strnlen(searchName, PATH_MAX);
4004 name_len++; /* trailing null */
4005 strncpy(pSMB->FileName, searchName, name_len);
4008 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4009 pSMB->TotalDataCount = 0;
4010 pSMB->MaxParameterCount = cpu_to_le16(2);
4011 /* BB find exact max data count below from sess structure BB */
4012 pSMB->MaxDataCount = cpu_to_le16(4000);
4013 pSMB->MaxSetupCount = 0;
4017 pSMB->Reserved2 = 0;
4018 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4019 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4020 pSMB->DataCount = 0;
4021 pSMB->DataOffset = 0;
4022 pSMB->SetupCount = 1;
4023 pSMB->Reserved3 = 0;
4024 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4025 byte_count = params + 1 /* pad */ ;
4026 pSMB->TotalParameterCount = cpu_to_le16(params);
4027 pSMB->ParameterCount = pSMB->TotalParameterCount;
4028 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4029 pSMB->Reserved4 = 0;
4030 pSMB->hdr.smb_buf_length += byte_count;
4031 pSMB->ByteCount = cpu_to_le16(byte_count);
4033 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4034 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4036 cFYI(1, "error %d in QueryInternalInfo", rc);
4038 /* decode response */
4039 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4040 if (rc || (pSMBr->ByteCount < 2))
4041 /* BB also check enough total bytes returned */
4042 /* If rc should we check for EOPNOSUPP and
4043 disable the srvino flag? or in caller? */
4044 rc = -EIO; /* bad smb */
4046 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4047 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4048 struct file_internal_info *pfinfo;
4049 /* BB Do we need a cast or hash here ? */
4051 cFYI(1, "Illegal size ret in QryIntrnlInf");
4053 goto GetInodeNumOut;
4055 pfinfo = (struct file_internal_info *)
4056 (data_offset + (char *) &pSMBr->hdr.Protocol);
4057 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4061 cifs_buf_release(pSMB);
4063 goto GetInodeNumberRetry;
4067 /* parses DFS refferal V3 structure
4068 * caller is responsible for freeing target_nodes
4071 * on failure - errno
4074 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4075 unsigned int *num_of_nodes,
4076 struct dfs_info3_param **target_nodes,
4077 const struct nls_table *nls_codepage, int remap,
4078 const char *searchName)
4083 struct dfs_referral_level_3 *ref;
4085 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4089 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4091 if (*num_of_nodes < 1) {
4092 cERROR(1, "num_referrals: must be at least > 0,"
4093 "but we get num_referrals = %d\n", *num_of_nodes);
4095 goto parse_DFS_referrals_exit;
4098 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4099 if (ref->VersionNumber != cpu_to_le16(3)) {
4100 cERROR(1, "Referrals of V%d version are not supported,"
4101 "should be V3", le16_to_cpu(ref->VersionNumber));
4103 goto parse_DFS_referrals_exit;
4106 /* get the upper boundary of the resp buffer */
4107 data_end = (char *)(&(pSMBr->PathConsumed)) +
4108 le16_to_cpu(pSMBr->t2.DataCount);
4110 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4112 le32_to_cpu(pSMBr->DFSFlags));
4114 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4115 *num_of_nodes, GFP_KERNEL);
4116 if (*target_nodes == NULL) {
4117 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4119 goto parse_DFS_referrals_exit;
4122 /* collect necessary data from referrals */
4123 for (i = 0; i < *num_of_nodes; i++) {
4126 struct dfs_info3_param *node = (*target_nodes)+i;
4128 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4130 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4134 goto parse_DFS_referrals_exit;
4136 cifsConvertToUCS((__le16 *) tmp, searchName,
4137 PATH_MAX, nls_codepage, remap);
4138 node->path_consumed = cifs_ucs2_bytes(tmp,
4139 le16_to_cpu(pSMBr->PathConsumed),
4143 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4145 node->server_type = le16_to_cpu(ref->ServerType);
4146 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4149 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4150 max_len = data_end - temp;
4151 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4152 is_unicode, nls_codepage);
4153 if (!node->path_name) {
4155 goto parse_DFS_referrals_exit;
4158 /* copy link target UNC */
4159 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4160 max_len = data_end - temp;
4161 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4162 is_unicode, nls_codepage);
4163 if (!node->node_name)
4167 parse_DFS_referrals_exit:
4169 free_dfs_info_array(*target_nodes, *num_of_nodes);
4170 *target_nodes = NULL;
4177 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4178 const unsigned char *searchName,
4179 struct dfs_info3_param **target_nodes,
4180 unsigned int *num_of_nodes,
4181 const struct nls_table *nls_codepage, int remap)
4183 /* TRANS2_GET_DFS_REFERRAL */
4184 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4185 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4189 __u16 params, byte_count;
4191 *target_nodes = NULL;
4193 cFYI(1, "In GetDFSRefer the path %s", searchName);
4197 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4202 /* server pointer checked in called function,
4203 but should never be null here anyway */
4204 pSMB->hdr.Mid = GetNextMid(ses->server);
4205 pSMB->hdr.Tid = ses->ipc_tid;
4206 pSMB->hdr.Uid = ses->Suid;
4207 if (ses->capabilities & CAP_STATUS32)
4208 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4209 if (ses->capabilities & CAP_DFS)
4210 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4212 if (ses->capabilities & CAP_UNICODE) {
4213 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4215 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4216 searchName, PATH_MAX, nls_codepage, remap);
4217 name_len++; /* trailing null */
4219 } else { /* BB improve the check for buffer overruns BB */
4220 name_len = strnlen(searchName, PATH_MAX);
4221 name_len++; /* trailing null */
4222 strncpy(pSMB->RequestFileName, searchName, name_len);
4226 if (ses->server->secMode &
4227 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4228 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4231 pSMB->hdr.Uid = ses->Suid;
4233 params = 2 /* level */ + name_len /*includes null */ ;
4234 pSMB->TotalDataCount = 0;
4235 pSMB->DataCount = 0;
4236 pSMB->DataOffset = 0;
4237 pSMB->MaxParameterCount = 0;
4238 /* BB find exact max SMB PDU from sess structure BB */
4239 pSMB->MaxDataCount = cpu_to_le16(4000);
4240 pSMB->MaxSetupCount = 0;
4244 pSMB->Reserved2 = 0;
4245 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4246 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4247 pSMB->SetupCount = 1;
4248 pSMB->Reserved3 = 0;
4249 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4250 byte_count = params + 3 /* pad */ ;
4251 pSMB->ParameterCount = cpu_to_le16(params);
4252 pSMB->TotalParameterCount = pSMB->ParameterCount;
4253 pSMB->MaxReferralLevel = cpu_to_le16(3);
4254 pSMB->hdr.smb_buf_length += byte_count;
4255 pSMB->ByteCount = cpu_to_le16(byte_count);
4257 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4258 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4260 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4263 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4265 /* BB Also check if enough total bytes returned? */
4266 if (rc || (pSMBr->ByteCount < 17)) {
4267 rc = -EIO; /* bad smb */
4271 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4273 le16_to_cpu(pSMBr->t2.DataOffset));
4275 /* parse returned result into more usable form */
4276 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4277 target_nodes, nls_codepage, remap,
4281 cifs_buf_release(pSMB);
4289 /* Query File System Info such as free space to old servers such as Win 9x */
4291 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4293 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4294 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4295 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4296 FILE_SYSTEM_ALLOC_INFO *response_data;
4298 int bytes_returned = 0;
4299 __u16 params, byte_count;
4301 cFYI(1, "OldQFSInfo");
4303 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4308 params = 2; /* level */
4309 pSMB->TotalDataCount = 0;
4310 pSMB->MaxParameterCount = cpu_to_le16(2);
4311 pSMB->MaxDataCount = cpu_to_le16(1000);
4312 pSMB->MaxSetupCount = 0;
4316 pSMB->Reserved2 = 0;
4317 byte_count = params + 1 /* pad */ ;
4318 pSMB->TotalParameterCount = cpu_to_le16(params);
4319 pSMB->ParameterCount = pSMB->TotalParameterCount;
4320 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4321 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4322 pSMB->DataCount = 0;
4323 pSMB->DataOffset = 0;
4324 pSMB->SetupCount = 1;
4325 pSMB->Reserved3 = 0;
4326 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4327 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4328 pSMB->hdr.smb_buf_length += byte_count;
4329 pSMB->ByteCount = cpu_to_le16(byte_count);
4331 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4332 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4334 cFYI(1, "Send error in QFSInfo = %d", rc);
4335 } else { /* decode response */
4336 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4338 if (rc || (pSMBr->ByteCount < 18))
4339 rc = -EIO; /* bad smb */
4341 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4342 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4343 pSMBr->ByteCount, data_offset);
4345 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4346 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4348 le16_to_cpu(response_data->BytesPerSector) *
4349 le32_to_cpu(response_data->
4350 SectorsPerAllocationUnit);
4352 le32_to_cpu(response_data->TotalAllocationUnits);
4353 FSData->f_bfree = FSData->f_bavail =
4354 le32_to_cpu(response_data->FreeAllocationUnits);
4355 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4356 (unsigned long long)FSData->f_blocks,
4357 (unsigned long long)FSData->f_bfree,
4361 cifs_buf_release(pSMB);
4364 goto oldQFSInfoRetry;
4370 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4372 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4373 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4374 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4375 FILE_SYSTEM_INFO *response_data;
4377 int bytes_returned = 0;
4378 __u16 params, byte_count;
4380 cFYI(1, "In QFSInfo");
4382 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4387 params = 2; /* level */
4388 pSMB->TotalDataCount = 0;
4389 pSMB->MaxParameterCount = cpu_to_le16(2);
4390 pSMB->MaxDataCount = cpu_to_le16(1000);
4391 pSMB->MaxSetupCount = 0;
4395 pSMB->Reserved2 = 0;
4396 byte_count = params + 1 /* pad */ ;
4397 pSMB->TotalParameterCount = cpu_to_le16(params);
4398 pSMB->ParameterCount = pSMB->TotalParameterCount;
4399 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4400 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4401 pSMB->DataCount = 0;
4402 pSMB->DataOffset = 0;
4403 pSMB->SetupCount = 1;
4404 pSMB->Reserved3 = 0;
4405 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4406 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4407 pSMB->hdr.smb_buf_length += byte_count;
4408 pSMB->ByteCount = cpu_to_le16(byte_count);
4410 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4411 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4413 cFYI(1, "Send error in QFSInfo = %d", rc);
4414 } else { /* decode response */
4415 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4417 if (rc || (pSMBr->ByteCount < 24))
4418 rc = -EIO; /* bad smb */
4420 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4424 *) (((char *) &pSMBr->hdr.Protocol) +
4427 le32_to_cpu(response_data->BytesPerSector) *
4428 le32_to_cpu(response_data->
4429 SectorsPerAllocationUnit);
4431 le64_to_cpu(response_data->TotalAllocationUnits);
4432 FSData->f_bfree = FSData->f_bavail =
4433 le64_to_cpu(response_data->FreeAllocationUnits);
4434 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4435 (unsigned long long)FSData->f_blocks,
4436 (unsigned long long)FSData->f_bfree,
4440 cifs_buf_release(pSMB);
4449 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4451 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4452 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4453 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4454 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4456 int bytes_returned = 0;
4457 __u16 params, byte_count;
4459 cFYI(1, "In QFSAttributeInfo");
4461 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4466 params = 2; /* level */
4467 pSMB->TotalDataCount = 0;
4468 pSMB->MaxParameterCount = cpu_to_le16(2);
4469 /* BB find exact max SMB PDU from sess structure BB */
4470 pSMB->MaxDataCount = cpu_to_le16(1000);
4471 pSMB->MaxSetupCount = 0;
4475 pSMB->Reserved2 = 0;
4476 byte_count = params + 1 /* pad */ ;
4477 pSMB->TotalParameterCount = cpu_to_le16(params);
4478 pSMB->ParameterCount = pSMB->TotalParameterCount;
4479 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4480 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4481 pSMB->DataCount = 0;
4482 pSMB->DataOffset = 0;
4483 pSMB->SetupCount = 1;
4484 pSMB->Reserved3 = 0;
4485 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4486 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4487 pSMB->hdr.smb_buf_length += byte_count;
4488 pSMB->ByteCount = cpu_to_le16(byte_count);
4490 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4491 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4493 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4494 } else { /* decode response */
4495 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4497 if (rc || (pSMBr->ByteCount < 13)) {
4498 /* BB also check if enough bytes returned */
4499 rc = -EIO; /* bad smb */
4501 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4503 (FILE_SYSTEM_ATTRIBUTE_INFO
4504 *) (((char *) &pSMBr->hdr.Protocol) +
4506 memcpy(&tcon->fsAttrInfo, response_data,
4507 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4510 cifs_buf_release(pSMB);
4513 goto QFSAttributeRetry;
4519 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4521 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4522 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4523 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4524 FILE_SYSTEM_DEVICE_INFO *response_data;
4526 int bytes_returned = 0;
4527 __u16 params, byte_count;
4529 cFYI(1, "In QFSDeviceInfo");
4531 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4536 params = 2; /* level */
4537 pSMB->TotalDataCount = 0;
4538 pSMB->MaxParameterCount = cpu_to_le16(2);
4539 /* BB find exact max SMB PDU from sess structure BB */
4540 pSMB->MaxDataCount = cpu_to_le16(1000);
4541 pSMB->MaxSetupCount = 0;
4545 pSMB->Reserved2 = 0;
4546 byte_count = params + 1 /* pad */ ;
4547 pSMB->TotalParameterCount = cpu_to_le16(params);
4548 pSMB->ParameterCount = pSMB->TotalParameterCount;
4549 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4550 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4552 pSMB->DataCount = 0;
4553 pSMB->DataOffset = 0;
4554 pSMB->SetupCount = 1;
4555 pSMB->Reserved3 = 0;
4556 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4557 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4558 pSMB->hdr.smb_buf_length += byte_count;
4559 pSMB->ByteCount = cpu_to_le16(byte_count);
4561 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4562 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4564 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4565 } else { /* decode response */
4566 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4568 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4569 rc = -EIO; /* bad smb */
4571 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4573 (FILE_SYSTEM_DEVICE_INFO *)
4574 (((char *) &pSMBr->hdr.Protocol) +
4576 memcpy(&tcon->fsDevInfo, response_data,
4577 sizeof(FILE_SYSTEM_DEVICE_INFO));
4580 cifs_buf_release(pSMB);
4583 goto QFSDeviceRetry;
4589 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4591 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4592 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4593 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4594 FILE_SYSTEM_UNIX_INFO *response_data;
4596 int bytes_returned = 0;
4597 __u16 params, byte_count;
4599 cFYI(1, "In QFSUnixInfo");
4601 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4602 (void **) &pSMB, (void **) &pSMBr);
4606 params = 2; /* level */
4607 pSMB->TotalDataCount = 0;
4608 pSMB->DataCount = 0;
4609 pSMB->DataOffset = 0;
4610 pSMB->MaxParameterCount = cpu_to_le16(2);
4611 /* BB find exact max SMB PDU from sess structure BB */
4612 pSMB->MaxDataCount = cpu_to_le16(100);
4613 pSMB->MaxSetupCount = 0;
4617 pSMB->Reserved2 = 0;
4618 byte_count = params + 1 /* pad */ ;
4619 pSMB->ParameterCount = cpu_to_le16(params);
4620 pSMB->TotalParameterCount = pSMB->ParameterCount;
4621 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4622 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4623 pSMB->SetupCount = 1;
4624 pSMB->Reserved3 = 0;
4625 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4626 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4627 pSMB->hdr.smb_buf_length += byte_count;
4628 pSMB->ByteCount = cpu_to_le16(byte_count);
4630 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4631 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4633 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4634 } else { /* decode response */
4635 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4637 if (rc || (pSMBr->ByteCount < 13)) {
4638 rc = -EIO; /* bad smb */
4640 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4642 (FILE_SYSTEM_UNIX_INFO
4643 *) (((char *) &pSMBr->hdr.Protocol) +
4645 memcpy(&tcon->fsUnixInfo, response_data,
4646 sizeof(FILE_SYSTEM_UNIX_INFO));
4649 cifs_buf_release(pSMB);
4659 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4661 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4662 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4663 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4665 int bytes_returned = 0;
4666 __u16 params, param_offset, offset, byte_count;
4668 cFYI(1, "In SETFSUnixInfo");
4670 /* BB switch to small buf init to save memory */
4671 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4672 (void **) &pSMB, (void **) &pSMBr);
4676 params = 4; /* 2 bytes zero followed by info level. */
4677 pSMB->MaxSetupCount = 0;
4681 pSMB->Reserved2 = 0;
4682 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4684 offset = param_offset + params;
4686 pSMB->MaxParameterCount = cpu_to_le16(4);
4687 /* BB find exact max SMB PDU from sess structure BB */
4688 pSMB->MaxDataCount = cpu_to_le16(100);
4689 pSMB->SetupCount = 1;
4690 pSMB->Reserved3 = 0;
4691 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4692 byte_count = 1 /* pad */ + params + 12;
4694 pSMB->DataCount = cpu_to_le16(12);
4695 pSMB->ParameterCount = cpu_to_le16(params);
4696 pSMB->TotalDataCount = pSMB->DataCount;
4697 pSMB->TotalParameterCount = pSMB->ParameterCount;
4698 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4699 pSMB->DataOffset = cpu_to_le16(offset);
4703 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4706 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4707 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4708 pSMB->ClientUnixCap = cpu_to_le64(cap);
4710 pSMB->hdr.smb_buf_length += byte_count;
4711 pSMB->ByteCount = cpu_to_le16(byte_count);
4713 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4714 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4716 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4717 } else { /* decode response */
4718 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4720 rc = -EIO; /* bad smb */
4722 cifs_buf_release(pSMB);
4725 goto SETFSUnixRetry;
4733 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4734 struct kstatfs *FSData)
4736 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4737 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4738 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4739 FILE_SYSTEM_POSIX_INFO *response_data;
4741 int bytes_returned = 0;
4742 __u16 params, byte_count;
4744 cFYI(1, "In QFSPosixInfo");
4746 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4751 params = 2; /* level */
4752 pSMB->TotalDataCount = 0;
4753 pSMB->DataCount = 0;
4754 pSMB->DataOffset = 0;
4755 pSMB->MaxParameterCount = cpu_to_le16(2);
4756 /* BB find exact max SMB PDU from sess structure BB */
4757 pSMB->MaxDataCount = cpu_to_le16(100);
4758 pSMB->MaxSetupCount = 0;
4762 pSMB->Reserved2 = 0;
4763 byte_count = params + 1 /* pad */ ;
4764 pSMB->ParameterCount = cpu_to_le16(params);
4765 pSMB->TotalParameterCount = pSMB->ParameterCount;
4766 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4767 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4768 pSMB->SetupCount = 1;
4769 pSMB->Reserved3 = 0;
4770 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4771 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4772 pSMB->hdr.smb_buf_length += byte_count;
4773 pSMB->ByteCount = cpu_to_le16(byte_count);
4775 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4776 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4778 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4779 } else { /* decode response */
4780 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4782 if (rc || (pSMBr->ByteCount < 13)) {
4783 rc = -EIO; /* bad smb */
4785 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4787 (FILE_SYSTEM_POSIX_INFO
4788 *) (((char *) &pSMBr->hdr.Protocol) +
4791 le32_to_cpu(response_data->BlockSize);
4793 le64_to_cpu(response_data->TotalBlocks);
4795 le64_to_cpu(response_data->BlocksAvail);
4796 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4797 FSData->f_bavail = FSData->f_bfree;
4800 le64_to_cpu(response_data->UserBlocksAvail);
4802 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4804 le64_to_cpu(response_data->TotalFileNodes);
4805 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4807 le64_to_cpu(response_data->FreeFileNodes);
4810 cifs_buf_release(pSMB);
4819 /* We can not use write of zero bytes trick to
4820 set file size due to need for large file support. Also note that
4821 this SetPathInfo is preferred to SetFileInfo based method in next
4822 routine which is only needed to work around a sharing violation bug
4823 in Samba which this routine can run into */
4826 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4827 __u64 size, bool SetAllocation,
4828 const struct nls_table *nls_codepage, int remap)
4830 struct smb_com_transaction2_spi_req *pSMB = NULL;
4831 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4832 struct file_end_of_file_info *parm_data;
4835 int bytes_returned = 0;
4836 __u16 params, byte_count, data_count, param_offset, offset;
4838 cFYI(1, "In SetEOF");
4840 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4845 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4847 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4848 PATH_MAX, nls_codepage, remap);
4849 name_len++; /* trailing null */
4851 } else { /* BB improve the check for buffer overruns BB */
4852 name_len = strnlen(fileName, PATH_MAX);
4853 name_len++; /* trailing null */
4854 strncpy(pSMB->FileName, fileName, name_len);
4856 params = 6 + name_len;
4857 data_count = sizeof(struct file_end_of_file_info);
4858 pSMB->MaxParameterCount = cpu_to_le16(2);
4859 pSMB->MaxDataCount = cpu_to_le16(4100);
4860 pSMB->MaxSetupCount = 0;
4864 pSMB->Reserved2 = 0;
4865 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4866 InformationLevel) - 4;
4867 offset = param_offset + params;
4868 if (SetAllocation) {
4869 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4870 pSMB->InformationLevel =
4871 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4873 pSMB->InformationLevel =
4874 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4875 } else /* Set File Size */ {
4876 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4877 pSMB->InformationLevel =
4878 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4880 pSMB->InformationLevel =
4881 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4885 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4887 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4888 pSMB->DataOffset = cpu_to_le16(offset);
4889 pSMB->SetupCount = 1;
4890 pSMB->Reserved3 = 0;
4891 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4892 byte_count = 3 /* pad */ + params + data_count;
4893 pSMB->DataCount = cpu_to_le16(data_count);
4894 pSMB->TotalDataCount = pSMB->DataCount;
4895 pSMB->ParameterCount = cpu_to_le16(params);
4896 pSMB->TotalParameterCount = pSMB->ParameterCount;
4897 pSMB->Reserved4 = 0;
4898 pSMB->hdr.smb_buf_length += byte_count;
4899 parm_data->FileSize = cpu_to_le64(size);
4900 pSMB->ByteCount = cpu_to_le16(byte_count);
4901 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4902 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4904 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4906 cifs_buf_release(pSMB);
4915 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4916 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4918 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4920 struct file_end_of_file_info *parm_data;
4922 __u16 params, param_offset, offset, byte_count, count;
4924 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4926 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4931 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4932 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4935 pSMB->MaxSetupCount = 0;
4939 pSMB->Reserved2 = 0;
4940 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4941 offset = param_offset + params;
4943 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4945 count = sizeof(struct file_end_of_file_info);
4946 pSMB->MaxParameterCount = cpu_to_le16(2);
4947 /* BB find exact max SMB PDU from sess structure BB */
4948 pSMB->MaxDataCount = cpu_to_le16(1000);
4949 pSMB->SetupCount = 1;
4950 pSMB->Reserved3 = 0;
4951 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4952 byte_count = 3 /* pad */ + params + count;
4953 pSMB->DataCount = cpu_to_le16(count);
4954 pSMB->ParameterCount = cpu_to_le16(params);
4955 pSMB->TotalDataCount = pSMB->DataCount;
4956 pSMB->TotalParameterCount = pSMB->ParameterCount;
4957 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4959 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4961 pSMB->DataOffset = cpu_to_le16(offset);
4962 parm_data->FileSize = cpu_to_le64(size);
4964 if (SetAllocation) {
4965 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4966 pSMB->InformationLevel =
4967 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4969 pSMB->InformationLevel =
4970 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4971 } else /* Set File Size */ {
4972 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4973 pSMB->InformationLevel =
4974 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4976 pSMB->InformationLevel =
4977 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4979 pSMB->Reserved4 = 0;
4980 pSMB->hdr.smb_buf_length += byte_count;
4981 pSMB->ByteCount = cpu_to_le16(byte_count);
4982 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4984 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4987 /* Note: On -EAGAIN error only caller can retry on handle based calls
4988 since file handle passed in no longer valid */
4993 /* Some legacy servers such as NT4 require that the file times be set on
4994 an open handle, rather than by pathname - this is awkward due to
4995 potential access conflicts on the open, but it is unavoidable for these
4996 old servers since the only other choice is to go from 100 nanosecond DCE
4997 time and resort to the original setpathinfo level which takes the ancient
4998 DOS time format with 2 second granularity */
5000 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5001 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5003 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5006 __u16 params, param_offset, offset, byte_count, count;
5008 cFYI(1, "Set Times (via SetFileInfo)");
5009 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5014 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5015 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5018 pSMB->MaxSetupCount = 0;
5022 pSMB->Reserved2 = 0;
5023 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5024 offset = param_offset + params;
5026 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5028 count = sizeof(FILE_BASIC_INFO);
5029 pSMB->MaxParameterCount = cpu_to_le16(2);
5030 /* BB find max SMB PDU from sess */
5031 pSMB->MaxDataCount = cpu_to_le16(1000);
5032 pSMB->SetupCount = 1;
5033 pSMB->Reserved3 = 0;
5034 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5035 byte_count = 3 /* pad */ + params + count;
5036 pSMB->DataCount = cpu_to_le16(count);
5037 pSMB->ParameterCount = cpu_to_le16(params);
5038 pSMB->TotalDataCount = pSMB->DataCount;
5039 pSMB->TotalParameterCount = pSMB->ParameterCount;
5040 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5041 pSMB->DataOffset = cpu_to_le16(offset);
5043 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5044 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5046 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5047 pSMB->Reserved4 = 0;
5048 pSMB->hdr.smb_buf_length += byte_count;
5049 pSMB->ByteCount = cpu_to_le16(byte_count);
5050 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5051 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5053 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5055 /* Note: On -EAGAIN error only caller can retry on handle based calls
5056 since file handle passed in no longer valid */
5062 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5063 bool delete_file, __u16 fid, __u32 pid_of_opener)
5065 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5068 __u16 params, param_offset, offset, byte_count, count;
5070 cFYI(1, "Set File Disposition (via SetFileInfo)");
5071 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5076 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5077 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5080 pSMB->MaxSetupCount = 0;
5084 pSMB->Reserved2 = 0;
5085 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5086 offset = param_offset + params;
5088 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5091 pSMB->MaxParameterCount = cpu_to_le16(2);
5092 /* BB find max SMB PDU from sess */
5093 pSMB->MaxDataCount = cpu_to_le16(1000);
5094 pSMB->SetupCount = 1;
5095 pSMB->Reserved3 = 0;
5096 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5097 byte_count = 3 /* pad */ + params + count;
5098 pSMB->DataCount = cpu_to_le16(count);
5099 pSMB->ParameterCount = cpu_to_le16(params);
5100 pSMB->TotalDataCount = pSMB->DataCount;
5101 pSMB->TotalParameterCount = pSMB->ParameterCount;
5102 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5103 pSMB->DataOffset = cpu_to_le16(offset);
5105 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5106 pSMB->Reserved4 = 0;
5107 pSMB->hdr.smb_buf_length += byte_count;
5108 pSMB->ByteCount = cpu_to_le16(byte_count);
5109 *data_offset = delete_file ? 1 : 0;
5110 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5112 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5118 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5119 const char *fileName, const FILE_BASIC_INFO *data,
5120 const struct nls_table *nls_codepage, int remap)
5122 TRANSACTION2_SPI_REQ *pSMB = NULL;
5123 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5126 int bytes_returned = 0;
5128 __u16 params, param_offset, offset, byte_count, count;
5130 cFYI(1, "In SetTimes");
5133 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5138 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5140 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5141 PATH_MAX, nls_codepage, remap);
5142 name_len++; /* trailing null */
5144 } else { /* BB improve the check for buffer overruns BB */
5145 name_len = strnlen(fileName, PATH_MAX);
5146 name_len++; /* trailing null */
5147 strncpy(pSMB->FileName, fileName, name_len);
5150 params = 6 + name_len;
5151 count = sizeof(FILE_BASIC_INFO);
5152 pSMB->MaxParameterCount = cpu_to_le16(2);
5153 /* BB find max SMB PDU from sess structure BB */
5154 pSMB->MaxDataCount = cpu_to_le16(1000);
5155 pSMB->MaxSetupCount = 0;
5159 pSMB->Reserved2 = 0;
5160 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5161 InformationLevel) - 4;
5162 offset = param_offset + params;
5163 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5164 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5165 pSMB->DataOffset = cpu_to_le16(offset);
5166 pSMB->SetupCount = 1;
5167 pSMB->Reserved3 = 0;
5168 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5169 byte_count = 3 /* pad */ + params + count;
5171 pSMB->DataCount = cpu_to_le16(count);
5172 pSMB->ParameterCount = cpu_to_le16(params);
5173 pSMB->TotalDataCount = pSMB->DataCount;
5174 pSMB->TotalParameterCount = pSMB->ParameterCount;
5175 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5176 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5178 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5179 pSMB->Reserved4 = 0;
5180 pSMB->hdr.smb_buf_length += byte_count;
5181 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5182 pSMB->ByteCount = cpu_to_le16(byte_count);
5183 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5184 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5186 cFYI(1, "SetPathInfo (times) returned %d", rc);
5188 cifs_buf_release(pSMB);
5196 /* Can not be used to set time stamps yet (due to old DOS time format) */
5197 /* Can be used to set attributes */
5198 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5199 handling it anyway and NT4 was what we thought it would be needed for
5200 Do not delete it until we prove whether needed for Win9x though */
5202 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5203 __u16 dos_attrs, const struct nls_table *nls_codepage)
5205 SETATTR_REQ *pSMB = NULL;
5206 SETATTR_RSP *pSMBr = NULL;
5211 cFYI(1, "In SetAttrLegacy");
5214 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5219 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5221 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5222 PATH_MAX, nls_codepage);
5223 name_len++; /* trailing null */
5225 } else { /* BB improve the check for buffer overruns BB */
5226 name_len = strnlen(fileName, PATH_MAX);
5227 name_len++; /* trailing null */
5228 strncpy(pSMB->fileName, fileName, name_len);
5230 pSMB->attr = cpu_to_le16(dos_attrs);
5231 pSMB->BufferFormat = 0x04;
5232 pSMB->hdr.smb_buf_length += name_len + 1;
5233 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5234 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5235 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5237 cFYI(1, "Error in LegacySetAttr = %d", rc);
5239 cifs_buf_release(pSMB);
5242 goto SetAttrLgcyRetry;
5246 #endif /* temporarily unneeded SetAttr legacy function */
5249 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5250 const struct cifs_unix_set_info_args *args)
5252 u64 mode = args->mode;
5255 * Samba server ignores set of file size to zero due to bugs in some
5256 * older clients, but we should be precise - we use SetFileSize to
5257 * set file size and do not want to truncate file size to zero
5258 * accidently as happened on one Samba server beta by putting
5259 * zero instead of -1 here
5261 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5262 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5263 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5264 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5265 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5266 data_offset->Uid = cpu_to_le64(args->uid);
5267 data_offset->Gid = cpu_to_le64(args->gid);
5268 /* better to leave device as zero when it is */
5269 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5270 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5271 data_offset->Permissions = cpu_to_le64(mode);
5274 data_offset->Type = cpu_to_le32(UNIX_FILE);
5275 else if (S_ISDIR(mode))
5276 data_offset->Type = cpu_to_le32(UNIX_DIR);
5277 else if (S_ISLNK(mode))
5278 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5279 else if (S_ISCHR(mode))
5280 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5281 else if (S_ISBLK(mode))
5282 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5283 else if (S_ISFIFO(mode))
5284 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5285 else if (S_ISSOCK(mode))
5286 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5290 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5291 const struct cifs_unix_set_info_args *args,
5292 u16 fid, u32 pid_of_opener)
5294 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5295 FILE_UNIX_BASIC_INFO *data_offset;
5297 u16 params, param_offset, offset, byte_count, count;
5299 cFYI(1, "Set Unix Info (via SetFileInfo)");
5300 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5305 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5306 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5309 pSMB->MaxSetupCount = 0;
5313 pSMB->Reserved2 = 0;
5314 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5315 offset = param_offset + params;
5317 data_offset = (FILE_UNIX_BASIC_INFO *)
5318 ((char *)(&pSMB->hdr.Protocol) + offset);
5319 count = sizeof(FILE_UNIX_BASIC_INFO);
5321 pSMB->MaxParameterCount = cpu_to_le16(2);
5322 /* BB find max SMB PDU from sess */
5323 pSMB->MaxDataCount = cpu_to_le16(1000);
5324 pSMB->SetupCount = 1;
5325 pSMB->Reserved3 = 0;
5326 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5327 byte_count = 3 /* pad */ + params + count;
5328 pSMB->DataCount = cpu_to_le16(count);
5329 pSMB->ParameterCount = cpu_to_le16(params);
5330 pSMB->TotalDataCount = pSMB->DataCount;
5331 pSMB->TotalParameterCount = pSMB->ParameterCount;
5332 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5333 pSMB->DataOffset = cpu_to_le16(offset);
5335 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5336 pSMB->Reserved4 = 0;
5337 pSMB->hdr.smb_buf_length += byte_count;
5338 pSMB->ByteCount = cpu_to_le16(byte_count);
5340 cifs_fill_unix_set_info(data_offset, args);
5342 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5344 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5346 /* Note: On -EAGAIN error only caller can retry on handle based calls
5347 since file handle passed in no longer valid */
5353 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5354 const struct cifs_unix_set_info_args *args,
5355 const struct nls_table *nls_codepage, int remap)
5357 TRANSACTION2_SPI_REQ *pSMB = NULL;
5358 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5361 int bytes_returned = 0;
5362 FILE_UNIX_BASIC_INFO *data_offset;
5363 __u16 params, param_offset, offset, count, byte_count;
5365 cFYI(1, "In SetUID/GID/Mode");
5367 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5372 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5374 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5375 PATH_MAX, nls_codepage, remap);
5376 name_len++; /* trailing null */
5378 } else { /* BB improve the check for buffer overruns BB */
5379 name_len = strnlen(fileName, PATH_MAX);
5380 name_len++; /* trailing null */
5381 strncpy(pSMB->FileName, fileName, name_len);
5384 params = 6 + name_len;
5385 count = sizeof(FILE_UNIX_BASIC_INFO);
5386 pSMB->MaxParameterCount = cpu_to_le16(2);
5387 /* BB find max SMB PDU from sess structure BB */
5388 pSMB->MaxDataCount = cpu_to_le16(1000);
5389 pSMB->MaxSetupCount = 0;
5393 pSMB->Reserved2 = 0;
5394 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5395 InformationLevel) - 4;
5396 offset = param_offset + params;
5398 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5400 memset(data_offset, 0, count);
5401 pSMB->DataOffset = cpu_to_le16(offset);
5402 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5403 pSMB->SetupCount = 1;
5404 pSMB->Reserved3 = 0;
5405 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5406 byte_count = 3 /* pad */ + params + count;
5407 pSMB->ParameterCount = cpu_to_le16(params);
5408 pSMB->DataCount = cpu_to_le16(count);
5409 pSMB->TotalParameterCount = pSMB->ParameterCount;
5410 pSMB->TotalDataCount = pSMB->DataCount;
5411 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5412 pSMB->Reserved4 = 0;
5413 pSMB->hdr.smb_buf_length += byte_count;
5415 cifs_fill_unix_set_info(data_offset, args);
5417 pSMB->ByteCount = cpu_to_le16(byte_count);
5418 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5419 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5421 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5423 cifs_buf_release(pSMB);
5429 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5430 const int notify_subdirs, const __u16 netfid,
5431 __u32 filter, struct file *pfile, int multishot,
5432 const struct nls_table *nls_codepage)
5435 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5436 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5437 struct dir_notify_req *dnotify_req;
5440 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5441 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5446 pSMB->TotalParameterCount = 0 ;
5447 pSMB->TotalDataCount = 0;
5448 pSMB->MaxParameterCount = cpu_to_le32(2);
5449 /* BB find exact data count max from sess structure BB */
5450 pSMB->MaxDataCount = 0; /* same in little endian or be */
5451 /* BB VERIFY verify which is correct for above BB */
5452 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5453 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5455 pSMB->MaxSetupCount = 4;
5457 pSMB->ParameterOffset = 0;
5458 pSMB->DataCount = 0;
5459 pSMB->DataOffset = 0;
5460 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5461 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5462 pSMB->ParameterCount = pSMB->TotalParameterCount;
5464 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5465 pSMB->Reserved2 = 0;
5466 pSMB->CompletionFilter = cpu_to_le32(filter);
5467 pSMB->Fid = netfid; /* file handle always le */
5468 pSMB->ByteCount = 0;
5470 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5471 (struct smb_hdr *)pSMBr, &bytes_returned,
5474 cFYI(1, "Error in Notify = %d", rc);
5476 /* Add file to outstanding requests */
5477 /* BB change to kmem cache alloc */
5478 dnotify_req = kmalloc(
5479 sizeof(struct dir_notify_req),
5482 dnotify_req->Pid = pSMB->hdr.Pid;
5483 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5484 dnotify_req->Mid = pSMB->hdr.Mid;
5485 dnotify_req->Tid = pSMB->hdr.Tid;
5486 dnotify_req->Uid = pSMB->hdr.Uid;
5487 dnotify_req->netfid = netfid;
5488 dnotify_req->pfile = pfile;
5489 dnotify_req->filter = filter;
5490 dnotify_req->multishot = multishot;
5491 spin_lock(&GlobalMid_Lock);
5492 list_add_tail(&dnotify_req->lhead,
5493 &GlobalDnotifyReqList);
5494 spin_unlock(&GlobalMid_Lock);
5498 cifs_buf_release(pSMB);
5502 #ifdef CONFIG_CIFS_XATTR
5504 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5505 * function used by listxattr and getxattr type calls. When ea_name is set,
5506 * it looks for that attribute name and stuffs that value into the EAData
5507 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5508 * buffer. In both cases, the return value is either the length of the
5509 * resulting data or a negative error code. If EAData is a NULL pointer then
5510 * the data isn't copied to it, but the length is returned.
5513 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5514 const unsigned char *searchName, const unsigned char *ea_name,
5515 char *EAData, size_t buf_size,
5516 const struct nls_table *nls_codepage, int remap)
5518 /* BB assumes one setup word */
5519 TRANSACTION2_QPI_REQ *pSMB = NULL;
5520 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5524 struct fealist *ea_response_data;
5525 struct fea *temp_fea;
5528 __u16 params, byte_count, data_offset;
5530 cFYI(1, "In Query All EAs path %s", searchName);
5532 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5537 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5539 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5540 PATH_MAX, nls_codepage, remap);
5541 list_len++; /* trailing null */
5543 } else { /* BB improve the check for buffer overruns BB */
5544 list_len = strnlen(searchName, PATH_MAX);
5545 list_len++; /* trailing null */
5546 strncpy(pSMB->FileName, searchName, list_len);
5549 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5550 pSMB->TotalDataCount = 0;
5551 pSMB->MaxParameterCount = cpu_to_le16(2);
5552 /* BB find exact max SMB PDU from sess structure BB */
5553 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5554 pSMB->MaxSetupCount = 0;
5558 pSMB->Reserved2 = 0;
5559 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5560 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5561 pSMB->DataCount = 0;
5562 pSMB->DataOffset = 0;
5563 pSMB->SetupCount = 1;
5564 pSMB->Reserved3 = 0;
5565 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5566 byte_count = params + 1 /* pad */ ;
5567 pSMB->TotalParameterCount = cpu_to_le16(params);
5568 pSMB->ParameterCount = pSMB->TotalParameterCount;
5569 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5570 pSMB->Reserved4 = 0;
5571 pSMB->hdr.smb_buf_length += byte_count;
5572 pSMB->ByteCount = cpu_to_le16(byte_count);
5574 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5575 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5577 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5582 /* BB also check enough total bytes returned */
5583 /* BB we need to improve the validity checking
5584 of these trans2 responses */
5586 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5587 if (rc || (pSMBr->ByteCount < 4)) {
5588 rc = -EIO; /* bad smb */
5592 /* check that length of list is not more than bcc */
5593 /* check that each entry does not go beyond length
5595 /* check that each element of each entry does not
5596 go beyond end of list */
5597 /* validate_trans2_offsets() */
5598 /* BB check if start of smb + data_offset > &bcc+ bcc */
5600 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5601 ea_response_data = (struct fealist *)
5602 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5604 list_len = le32_to_cpu(ea_response_data->list_len);
5605 cFYI(1, "ea length %d", list_len);
5606 if (list_len <= 8) {
5607 cFYI(1, "empty EA list returned from server");
5611 /* make sure list_len doesn't go past end of SMB */
5612 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5613 if ((char *)ea_response_data + list_len > end_of_smb) {
5614 cFYI(1, "EA list appears to go beyond SMB");
5619 /* account for ea list len */
5621 temp_fea = ea_response_data->list;
5622 temp_ptr = (char *)temp_fea;
5623 while (list_len > 0) {
5624 unsigned int name_len;
5629 /* make sure we can read name_len and value_len */
5631 cFYI(1, "EA entry goes beyond length of list");
5636 name_len = temp_fea->name_len;
5637 value_len = le16_to_cpu(temp_fea->value_len);
5638 list_len -= name_len + 1 + value_len;
5640 cFYI(1, "EA entry goes beyond length of list");
5646 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5647 temp_ptr += name_len + 1;
5651 if ((size_t)value_len > buf_size) {
5655 memcpy(EAData, temp_ptr, value_len);
5659 /* account for prefix user. and trailing null */
5660 rc += (5 + 1 + name_len);
5661 if (rc < (int) buf_size) {
5662 memcpy(EAData, "user.", 5);
5664 memcpy(EAData, temp_ptr, name_len);
5666 /* null terminate name */
5669 } else if (buf_size == 0) {
5670 /* skip copy - calc size only */
5672 /* stop before overrun buffer */
5677 temp_ptr += name_len + 1 + value_len;
5678 temp_fea = (struct fea *)temp_ptr;
5681 /* didn't find the named attribute */
5686 cifs_buf_release(pSMB);
5694 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5695 const char *ea_name, const void *ea_value,
5696 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5699 struct smb_com_transaction2_spi_req *pSMB = NULL;
5700 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5701 struct fealist *parm_data;
5704 int bytes_returned = 0;
5705 __u16 params, param_offset, byte_count, offset, count;
5707 cFYI(1, "In SetEA");
5709 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5714 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5716 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5717 PATH_MAX, nls_codepage, remap);
5718 name_len++; /* trailing null */
5720 } else { /* BB improve the check for buffer overruns BB */
5721 name_len = strnlen(fileName, PATH_MAX);
5722 name_len++; /* trailing null */
5723 strncpy(pSMB->FileName, fileName, name_len);
5726 params = 6 + name_len;
5728 /* done calculating parms using name_len of file name,
5729 now use name_len to calculate length of ea name
5730 we are going to create in the inode xattrs */
5731 if (ea_name == NULL)
5734 name_len = strnlen(ea_name, 255);
5736 count = sizeof(*parm_data) + ea_value_len + name_len;
5737 pSMB->MaxParameterCount = cpu_to_le16(2);
5738 /* BB find max SMB PDU from sess */
5739 pSMB->MaxDataCount = cpu_to_le16(1000);
5740 pSMB->MaxSetupCount = 0;
5744 pSMB->Reserved2 = 0;
5745 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5746 InformationLevel) - 4;
5747 offset = param_offset + params;
5748 pSMB->InformationLevel =
5749 cpu_to_le16(SMB_SET_FILE_EA);
5752 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5754 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5755 pSMB->DataOffset = cpu_to_le16(offset);
5756 pSMB->SetupCount = 1;
5757 pSMB->Reserved3 = 0;
5758 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5759 byte_count = 3 /* pad */ + params + count;
5760 pSMB->DataCount = cpu_to_le16(count);
5761 parm_data->list_len = cpu_to_le32(count);
5762 parm_data->list[0].EA_flags = 0;
5763 /* we checked above that name len is less than 255 */
5764 parm_data->list[0].name_len = (__u8)name_len;
5765 /* EA names are always ASCII */
5767 strncpy(parm_data->list[0].name, ea_name, name_len);
5768 parm_data->list[0].name[name_len] = 0;
5769 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5770 /* caller ensures that ea_value_len is less than 64K but
5771 we need to ensure that it fits within the smb */
5773 /*BB add length check to see if it would fit in
5774 negotiated SMB buffer size BB */
5775 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5777 memcpy(parm_data->list[0].name+name_len+1,
5778 ea_value, ea_value_len);
5780 pSMB->TotalDataCount = pSMB->DataCount;
5781 pSMB->ParameterCount = cpu_to_le16(params);
5782 pSMB->TotalParameterCount = pSMB->ParameterCount;
5783 pSMB->Reserved4 = 0;
5784 pSMB->hdr.smb_buf_length += byte_count;
5785 pSMB->ByteCount = cpu_to_le16(byte_count);
5786 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5787 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5789 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5791 cifs_buf_release(pSMB);