4 * Copyright (C) International Business Machines Corp., 2002,2008
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/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* Allocates buffer into dst and copies smb string from src to it.
85 * caller is responsible for freeing dst if function returned 0.
91 cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
92 const bool is_unicode, const struct nls_table *nls_codepage)
97 plen = UniStrnlen((wchar_t *)src, maxlen);
98 *dst = kmalloc(plen + 2, GFP_KERNEL);
100 goto cifs_strncpy_to_host_ErrExit;
101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
103 plen = strnlen(src, maxlen);
104 *dst = kmalloc(plen + 2, GFP_KERNEL);
106 goto cifs_strncpy_to_host_ErrExit;
107 strncpy(*dst, src, plen);
110 (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
113 cifs_strncpy_to_host_ErrExit:
114 cERROR(1, ("Failed to allocate buffer for string\n"));
119 /* Mark as invalid, all open files on tree connections since they
120 were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
123 struct cifsFileInfo *open_file = NULL;
124 struct list_head *tmp;
125 struct list_head *tmp1;
127 /* list all files open on tree connection and mark them invalid */
128 write_lock(&GlobalSMBSeslock);
129 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
130 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
132 open_file->invalidHandle = true;
134 write_unlock(&GlobalSMBSeslock);
135 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
139 /* Allocate and return pointer to an SMB request buffer, and set basic
140 SMB information in the SMB header. If the return code is zero, this
141 function must have filled in request_buf pointer */
143 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
148 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
149 check for tcp and smb session status done differently
150 for those three - in the calling routine */
152 if (tcon->tidStatus == CifsExiting) {
153 /* only tree disconnect, open, and write,
154 (and ulogoff which does not have tcon)
155 are allowed as we start force umount */
156 if ((smb_command != SMB_COM_WRITE_ANDX) &&
157 (smb_command != SMB_COM_OPEN_ANDX) &&
158 (smb_command != SMB_COM_TREE_DISCONNECT)) {
159 cFYI(1, ("can not send cmd %d while umounting",
164 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
165 (tcon->ses->server)) {
166 struct nls_table *nls_codepage;
167 /* Give Demultiplex thread up to 10 seconds to
168 reconnect, should be greater than cifs socket
169 timeout which is 7 seconds */
170 while (tcon->ses->server->tcpStatus ==
172 wait_event_interruptible_timeout(tcon->ses->server->response_q,
173 (tcon->ses->server->tcpStatus ==
175 if (tcon->ses->server->tcpStatus ==
177 /* on "soft" mounts we wait once */
179 (tcon->ses->status == CifsExiting)) {
180 cFYI(1, ("gave up waiting on "
181 "reconnect in smb_init"));
183 } /* else "hard" mount - keep retrying
184 until process is killed or server
185 comes back on-line */
186 } else /* TCP session is reestablished now */
190 nls_codepage = load_nls_default();
191 /* need to prevent multiple threads trying to
192 simultaneously reconnect the same SMB session */
193 down(&tcon->ses->sesSem);
194 if (tcon->ses->status == CifsNeedReconnect)
195 rc = cifs_setup_session(0, tcon->ses,
197 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
198 mark_open_files_invalid(tcon);
199 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
201 up(&tcon->ses->sesSem);
202 /* BB FIXME add code to check if wsize needs
203 update due to negotiated smb buffer size
206 atomic_inc(&tconInfoReconnectCount);
207 /* tell server Unix caps we support */
208 if (tcon->ses->capabilities & CAP_UNIX)
209 reset_cifs_unix_caps(
212 NULL /* we do not know sb */,
213 NULL /* no vol info */);
216 cFYI(1, ("reconnect tcon rc = %d", rc));
217 /* Removed call to reopen open files here.
218 It is safer (and faster) to reopen files
219 one at a time as needed in read and write */
221 /* Check if handle based operation so we
222 know whether we can continue or not without
223 returning to caller to reset file handle */
224 switch (smb_command) {
225 case SMB_COM_READ_ANDX:
226 case SMB_COM_WRITE_ANDX:
228 case SMB_COM_FIND_CLOSE2:
229 case SMB_COM_LOCKING_ANDX: {
230 unload_nls(nls_codepage);
235 up(&tcon->ses->sesSem);
237 unload_nls(nls_codepage);
246 *request_buf = cifs_small_buf_get();
247 if (*request_buf == NULL) {
248 /* BB should we add a retry in here if not a writepage? */
252 header_assemble((struct smb_hdr *) *request_buf, smb_command,
256 cifs_stats_inc(&tcon->num_smbs_sent);
262 small_smb_init_no_tc(const int smb_command, const int wct,
263 struct cifsSesInfo *ses, void **request_buf)
266 struct smb_hdr *buffer;
268 rc = small_smb_init(smb_command, wct, NULL, request_buf);
272 buffer = (struct smb_hdr *)*request_buf;
273 buffer->Mid = GetNextMid(ses->server);
274 if (ses->capabilities & CAP_UNICODE)
275 buffer->Flags2 |= SMBFLG2_UNICODE;
276 if (ses->capabilities & CAP_STATUS32)
277 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
279 /* uid, tid can stay at zero as set in header assemble */
281 /* BB add support for turning on the signing when
282 this function is used after 1st of session setup requests */
287 /* If the return code is zero, this function must fill in request_buf pointer */
289 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
290 void **request_buf /* returned */ ,
291 void **response_buf /* returned */ )
295 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
296 check for tcp and smb session status done differently
297 for those three - in the calling routine */
299 if (tcon->tidStatus == CifsExiting) {
300 /* only tree disconnect, open, and write,
301 (and ulogoff which does not have tcon)
302 are allowed as we start force umount */
303 if ((smb_command != SMB_COM_WRITE_ANDX) &&
304 (smb_command != SMB_COM_OPEN_ANDX) &&
305 (smb_command != SMB_COM_TREE_DISCONNECT)) {
306 cFYI(1, ("can not send cmd %d while umounting",
312 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
313 (tcon->ses->server)) {
314 struct nls_table *nls_codepage;
315 /* Give Demultiplex thread up to 10 seconds to
316 reconnect, should be greater than cifs socket
317 timeout which is 7 seconds */
318 while (tcon->ses->server->tcpStatus ==
320 wait_event_interruptible_timeout(tcon->ses->server->response_q,
321 (tcon->ses->server->tcpStatus ==
323 if (tcon->ses->server->tcpStatus ==
325 /* on "soft" mounts we wait once */
327 (tcon->ses->status == CifsExiting)) {
328 cFYI(1, ("gave up waiting on "
329 "reconnect in smb_init"));
331 } /* else "hard" mount - keep retrying
332 until process is killed or server
334 } else /* TCP session is reestablished now */
337 nls_codepage = load_nls_default();
338 /* need to prevent multiple threads trying to
339 simultaneously reconnect the same SMB session */
340 down(&tcon->ses->sesSem);
341 if (tcon->ses->status == CifsNeedReconnect)
342 rc = cifs_setup_session(0, tcon->ses,
344 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
345 mark_open_files_invalid(tcon);
346 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
348 up(&tcon->ses->sesSem);
349 /* BB FIXME add code to check if wsize needs
350 update due to negotiated smb buffer size
353 atomic_inc(&tconInfoReconnectCount);
354 /* tell server Unix caps we support */
355 if (tcon->ses->capabilities & CAP_UNIX)
356 reset_cifs_unix_caps(
359 NULL /* do not know sb */,
360 NULL /* no vol info */);
363 cFYI(1, ("reconnect tcon rc = %d", rc));
364 /* Removed call to reopen open files here.
365 It is safer (and faster) to reopen files
366 one at a time as needed in read and write */
368 /* Check if handle based operation so we
369 know whether we can continue or not without
370 returning to caller to reset file handle */
371 switch (smb_command) {
372 case SMB_COM_READ_ANDX:
373 case SMB_COM_WRITE_ANDX:
375 case SMB_COM_FIND_CLOSE2:
376 case SMB_COM_LOCKING_ANDX: {
377 unload_nls(nls_codepage);
382 up(&tcon->ses->sesSem);
384 unload_nls(nls_codepage);
393 *request_buf = cifs_buf_get();
394 if (*request_buf == NULL) {
395 /* BB should we add a retry in here if not a writepage? */
398 /* Although the original thought was we needed the response buf for */
399 /* potential retries of smb operations it turns out we can determine */
400 /* from the mid flags when the request buffer can be resent without */
401 /* having to use a second distinct buffer for the response */
403 *response_buf = *request_buf;
405 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
409 cifs_stats_inc(&tcon->num_smbs_sent);
414 static int validate_t2(struct smb_t2_rsp *pSMB)
420 /* check for plausible wct, bcc and t2 data and parm sizes */
421 /* check for parm and data offset going beyond end of smb */
422 if (pSMB->hdr.WordCount >= 10) {
423 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
424 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
425 /* check that bcc is at least as big as parms + data */
426 /* check that bcc is less than negotiated smb buffer */
427 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
428 if (total_size < 512) {
430 le16_to_cpu(pSMB->t2_rsp.DataCount);
431 /* BCC le converted in SendReceive */
432 pBCC = (pSMB->hdr.WordCount * 2) +
433 sizeof(struct smb_hdr) +
435 if ((total_size <= (*(u16 *)pBCC)) &&
437 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
443 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
444 sizeof(struct smb_t2_rsp) + 16);
448 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
451 NEGOTIATE_RSP *pSMBr;
455 struct TCP_Server_Info *server;
457 unsigned int secFlags;
461 server = ses->server;
466 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
467 (void **) &pSMB, (void **) &pSMBr);
471 /* if any of auth flags (ie not sign or seal) are overriden use them */
472 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
473 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
474 else /* if override flags set only sign/seal OR them with global auth */
475 secFlags = extended_security | ses->overrideSecFlg;
477 cFYI(1, ("secFlags 0x%x", secFlags));
479 pSMB->hdr.Mid = GetNextMid(server);
480 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
482 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
483 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
484 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
485 cFYI(1, ("Kerberos only mechanism, enable extended security"));
486 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
490 for (i = 0; i < CIFS_NUM_PROT; i++) {
491 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
492 count += strlen(protocols[i].name) + 1;
493 /* null at end of source and target buffers anyway */
495 pSMB->hdr.smb_buf_length += count;
496 pSMB->ByteCount = cpu_to_le16(count);
498 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
499 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
503 dialect = le16_to_cpu(pSMBr->DialectIndex);
504 cFYI(1, ("Dialect: %d", dialect));
505 /* Check wct = 1 error case */
506 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
507 /* core returns wct = 1, but we do not ask for core - otherwise
508 small wct just comes when dialect index is -1 indicating we
509 could not negotiate a common dialect */
512 #ifdef CONFIG_CIFS_WEAK_PW_HASH
513 } else if ((pSMBr->hdr.WordCount == 13)
514 && ((dialect == LANMAN_PROT)
515 || (dialect == LANMAN2_PROT))) {
517 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
519 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
520 (secFlags & CIFSSEC_MAY_PLNTXT))
521 server->secType = LANMAN;
523 cERROR(1, ("mount failed weak security disabled"
524 " in /proc/fs/cifs/SecurityFlags"));
528 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
529 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
530 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
531 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
532 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
533 /* even though we do not use raw we might as well set this
534 accurately, in case we ever find a need for it */
535 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
536 server->maxRw = 0xFF00;
537 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
539 server->maxRw = 0;/* we do not need to use raw anyway */
540 server->capabilities = CAP_MPX_MODE;
542 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
544 /* OS/2 often does not set timezone therefore
545 * we must use server time to calc time zone.
546 * Could deviate slightly from the right zone.
547 * Smallest defined timezone difference is 15 minutes
548 * (i.e. Nepal). Rounding up/down is done to match
551 int val, seconds, remain, result;
552 struct timespec ts, utc;
554 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
555 le16_to_cpu(rsp->SrvTime.Time));
556 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
557 (int)ts.tv_sec, (int)utc.tv_sec,
558 (int)(utc.tv_sec - ts.tv_sec)));
559 val = (int)(utc.tv_sec - ts.tv_sec);
561 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
562 remain = seconds % MIN_TZ_ADJ;
563 if (remain >= (MIN_TZ_ADJ / 2))
564 result += MIN_TZ_ADJ;
567 server->timeAdj = result;
569 server->timeAdj = (int)tmp;
570 server->timeAdj *= 60; /* also in seconds */
572 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
575 /* BB get server time for time conversions and add
576 code to use it and timezone since this is not UTC */
578 if (rsp->EncryptionKeyLength ==
579 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
580 memcpy(server->cryptKey, rsp->EncryptionKey,
581 CIFS_CRYPTO_KEY_SIZE);
582 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
583 rc = -EIO; /* need cryptkey unless plain text */
587 cFYI(1, ("LANMAN negotiated"));
588 /* we will not end up setting signing flags - as no signing
589 was in LANMAN and server did not return the flags on */
591 #else /* weak security disabled */
592 } else if (pSMBr->hdr.WordCount == 13) {
593 cERROR(1, ("mount failed, cifs module not built "
594 "with CIFS_WEAK_PW_HASH support"));
596 #endif /* WEAK_PW_HASH */
598 } else if (pSMBr->hdr.WordCount != 17) {
603 /* else wct == 17 NTLM */
604 server->secMode = pSMBr->SecurityMode;
605 if ((server->secMode & SECMODE_USER) == 0)
606 cFYI(1, ("share mode security"));
608 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
609 #ifdef CONFIG_CIFS_WEAK_PW_HASH
610 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
611 #endif /* CIFS_WEAK_PW_HASH */
612 cERROR(1, ("Server requests plain text password"
613 " but client support disabled"));
615 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
616 server->secType = NTLMv2;
617 else if (secFlags & CIFSSEC_MAY_NTLM)
618 server->secType = NTLM;
619 else if (secFlags & CIFSSEC_MAY_NTLMV2)
620 server->secType = NTLMv2;
621 else if (secFlags & CIFSSEC_MAY_KRB5)
622 server->secType = Kerberos;
623 else if (secFlags & CIFSSEC_MAY_LANMAN)
624 server->secType = LANMAN;
625 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
626 else if (secFlags & CIFSSEC_MAY_PLNTXT)
631 cERROR(1, ("Invalid security type"));
634 /* else ... any others ...? */
636 /* one byte, so no need to convert this or EncryptionKeyLen from
638 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
639 /* probably no need to store and check maxvcs */
640 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
641 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
642 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
643 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
644 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
645 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
646 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
647 server->timeAdj *= 60;
648 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
649 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
650 CIFS_CRYPTO_KEY_SIZE);
651 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
652 && (pSMBr->EncryptionKeyLength == 0)) {
653 /* decode security blob */
654 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
655 rc = -EIO; /* no crypt key only if plain text pwd */
659 /* BB might be helpful to save off the domain of server here */
661 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
662 (server->capabilities & CAP_EXTENDED_SECURITY)) {
663 count = pSMBr->ByteCount;
669 if (server->socketUseCount.counter > 1) {
670 if (memcmp(server->server_GUID,
671 pSMBr->u.extended_response.
673 cFYI(1, ("server UID changed"));
674 memcpy(server->server_GUID,
675 pSMBr->u.extended_response.GUID,
679 memcpy(server->server_GUID,
680 pSMBr->u.extended_response.GUID, 16);
683 server->secType = RawNTLMSSP;
685 rc = decode_negTokenInit(pSMBr->u.extended_response.
696 server->capabilities &= ~CAP_EXTENDED_SECURITY;
698 #ifdef CONFIG_CIFS_WEAK_PW_HASH
701 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
702 /* MUST_SIGN already includes the MAY_SIGN FLAG
703 so if this is zero it means that signing is disabled */
704 cFYI(1, ("Signing disabled"));
705 if (server->secMode & SECMODE_SIGN_REQUIRED) {
706 cERROR(1, ("Server requires "
707 "packet signing to be enabled in "
708 "/proc/fs/cifs/SecurityFlags."));
712 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
713 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
714 /* signing required */
715 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
716 if ((server->secMode &
717 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
719 ("signing required but server lacks support"));
722 server->secMode |= SECMODE_SIGN_REQUIRED;
724 /* signing optional ie CIFSSEC_MAY_SIGN */
725 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
727 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
731 cifs_buf_release(pSMB);
733 cFYI(1, ("negprot rc %d", rc));
738 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
740 struct smb_hdr *smb_buffer;
743 cFYI(1, ("In tree disconnect"));
745 * If last user of the connection and
746 * connection alive - disconnect it
747 * If this is the last connection on the server session disconnect it
748 * (and inside session disconnect we should check if tcp socket needs
749 * to be freed and kernel thread woken up).
752 down(&tcon->tconSem);
756 atomic_dec(&tcon->useCount);
757 if (atomic_read(&tcon->useCount) > 0) {
762 /* No need to return error on this operation if tid invalidated and
763 closed on server already e.g. due to tcp session crashing */
764 if (tcon->tidStatus == CifsNeedReconnect) {
769 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
773 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
774 (void **)&smb_buffer);
780 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
782 cFYI(1, ("Tree disconnect failed %d", rc));
786 /* No need to return error on this operation if tid invalidated and
787 closed on server already e.g. due to tcp session crashing */
795 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
797 LOGOFF_ANDX_REQ *pSMB;
800 cFYI(1, ("In SMBLogoff for session disconnect"));
806 atomic_dec(&ses->inUse);
807 if (atomic_read(&ses->inUse) > 0) {
811 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
818 pSMB->hdr.Mid = GetNextMid(ses->server);
820 if (ses->server->secMode &
821 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
822 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
825 pSMB->hdr.Uid = ses->Suid;
827 pSMB->AndXCommand = 0xFF;
828 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
830 atomic_dec(&ses->server->socketUseCount);
831 if (atomic_read(&ses->server->socketUseCount) == 0) {
832 spin_lock(&GlobalMid_Lock);
833 ses->server->tcpStatus = CifsExiting;
834 spin_unlock(&GlobalMid_Lock);
840 /* if session dead then we do not need to do ulogoff,
841 since server closed smb session, no sense reporting
849 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
850 __u16 type, const struct nls_table *nls_codepage, int remap)
852 TRANSACTION2_SPI_REQ *pSMB = NULL;
853 TRANSACTION2_SPI_RSP *pSMBr = NULL;
854 struct unlink_psx_rq *pRqD;
857 int bytes_returned = 0;
858 __u16 params, param_offset, offset, byte_count;
860 cFYI(1, ("In POSIX delete"));
862 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
867 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
869 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
870 PATH_MAX, nls_codepage, remap);
871 name_len++; /* trailing null */
873 } else { /* BB add path length overrun check */
874 name_len = strnlen(fileName, PATH_MAX);
875 name_len++; /* trailing null */
876 strncpy(pSMB->FileName, fileName, name_len);
879 params = 6 + name_len;
880 pSMB->MaxParameterCount = cpu_to_le16(2);
881 pSMB->MaxDataCount = 0; /* BB double check this with jra */
882 pSMB->MaxSetupCount = 0;
887 param_offset = offsetof(struct smb_com_transaction2_spi_req,
888 InformationLevel) - 4;
889 offset = param_offset + params;
891 /* Setup pointer to Request Data (inode type) */
892 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
893 pRqD->type = cpu_to_le16(type);
894 pSMB->ParameterOffset = cpu_to_le16(param_offset);
895 pSMB->DataOffset = cpu_to_le16(offset);
896 pSMB->SetupCount = 1;
898 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
899 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
901 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
902 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
903 pSMB->ParameterCount = cpu_to_le16(params);
904 pSMB->TotalParameterCount = pSMB->ParameterCount;
905 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
907 pSMB->hdr.smb_buf_length += byte_count;
908 pSMB->ByteCount = cpu_to_le16(byte_count);
909 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
910 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
912 cFYI(1, ("Posix delete returned %d", rc));
913 cifs_buf_release(pSMB);
915 cifs_stats_inc(&tcon->num_deletes);
924 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
925 const struct nls_table *nls_codepage, int remap)
927 DELETE_FILE_REQ *pSMB = NULL;
928 DELETE_FILE_RSP *pSMBr = NULL;
934 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
939 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
941 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
942 PATH_MAX, nls_codepage, remap);
943 name_len++; /* trailing null */
945 } else { /* BB improve check for buffer overruns BB */
946 name_len = strnlen(fileName, PATH_MAX);
947 name_len++; /* trailing null */
948 strncpy(pSMB->fileName, fileName, name_len);
950 pSMB->SearchAttributes =
951 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
952 pSMB->BufferFormat = 0x04;
953 pSMB->hdr.smb_buf_length += name_len + 1;
954 pSMB->ByteCount = cpu_to_le16(name_len + 1);
955 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
956 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
957 cifs_stats_inc(&tcon->num_deletes);
959 cFYI(1, ("Error in RMFile = %d", rc));
961 cifs_buf_release(pSMB);
969 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
970 const struct nls_table *nls_codepage, int remap)
972 DELETE_DIRECTORY_REQ *pSMB = NULL;
973 DELETE_DIRECTORY_RSP *pSMBr = NULL;
978 cFYI(1, ("In CIFSSMBRmDir"));
980 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
985 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
986 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
987 PATH_MAX, nls_codepage, remap);
988 name_len++; /* trailing null */
990 } else { /* BB improve check for buffer overruns BB */
991 name_len = strnlen(dirName, PATH_MAX);
992 name_len++; /* trailing null */
993 strncpy(pSMB->DirName, dirName, name_len);
996 pSMB->BufferFormat = 0x04;
997 pSMB->hdr.smb_buf_length += name_len + 1;
998 pSMB->ByteCount = cpu_to_le16(name_len + 1);
999 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1000 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1001 cifs_stats_inc(&tcon->num_rmdirs);
1003 cFYI(1, ("Error in RMDir = %d", rc));
1005 cifs_buf_release(pSMB);
1012 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
1013 const char *name, const struct nls_table *nls_codepage, int remap)
1016 CREATE_DIRECTORY_REQ *pSMB = NULL;
1017 CREATE_DIRECTORY_RSP *pSMBr = NULL;
1021 cFYI(1, ("In CIFSSMBMkDir"));
1023 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1028 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1029 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1030 PATH_MAX, nls_codepage, remap);
1031 name_len++; /* trailing null */
1033 } else { /* BB improve check for buffer overruns BB */
1034 name_len = strnlen(name, PATH_MAX);
1035 name_len++; /* trailing null */
1036 strncpy(pSMB->DirName, name, name_len);
1039 pSMB->BufferFormat = 0x04;
1040 pSMB->hdr.smb_buf_length += name_len + 1;
1041 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1042 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1043 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1044 cifs_stats_inc(&tcon->num_mkdirs);
1046 cFYI(1, ("Error in Mkdir = %d", rc));
1048 cifs_buf_release(pSMB);
1055 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1056 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1057 __u32 *pOplock, const char *name,
1058 const struct nls_table *nls_codepage, int remap)
1060 TRANSACTION2_SPI_REQ *pSMB = NULL;
1061 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1064 int bytes_returned = 0;
1065 __u16 params, param_offset, offset, byte_count, count;
1066 OPEN_PSX_REQ *pdata;
1067 OPEN_PSX_RSP *psx_rsp;
1069 cFYI(1, ("In POSIX Create"));
1071 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1076 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1078 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1079 PATH_MAX, nls_codepage, remap);
1080 name_len++; /* trailing null */
1082 } else { /* BB improve the check for buffer overruns BB */
1083 name_len = strnlen(name, PATH_MAX);
1084 name_len++; /* trailing null */
1085 strncpy(pSMB->FileName, name, name_len);
1088 params = 6 + name_len;
1089 count = sizeof(OPEN_PSX_REQ);
1090 pSMB->MaxParameterCount = cpu_to_le16(2);
1091 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1092 pSMB->MaxSetupCount = 0;
1096 pSMB->Reserved2 = 0;
1097 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1098 InformationLevel) - 4;
1099 offset = param_offset + params;
1100 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1101 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1102 pdata->Permissions = cpu_to_le64(mode);
1103 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1104 pdata->OpenFlags = cpu_to_le32(*pOplock);
1105 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1106 pSMB->DataOffset = cpu_to_le16(offset);
1107 pSMB->SetupCount = 1;
1108 pSMB->Reserved3 = 0;
1109 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1110 byte_count = 3 /* pad */ + params + count;
1112 pSMB->DataCount = cpu_to_le16(count);
1113 pSMB->ParameterCount = cpu_to_le16(params);
1114 pSMB->TotalDataCount = pSMB->DataCount;
1115 pSMB->TotalParameterCount = pSMB->ParameterCount;
1116 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1117 pSMB->Reserved4 = 0;
1118 pSMB->hdr.smb_buf_length += byte_count;
1119 pSMB->ByteCount = cpu_to_le16(byte_count);
1120 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1121 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1123 cFYI(1, ("Posix create returned %d", rc));
1124 goto psx_create_err;
1127 cFYI(1, ("copying inode info"));
1128 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1130 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1131 rc = -EIO; /* bad smb */
1132 goto psx_create_err;
1135 /* copy return information to pRetData */
1136 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1137 + le16_to_cpu(pSMBr->t2.DataOffset));
1139 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1141 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1142 /* Let caller know file was created so we can set the mode. */
1143 /* Do we care about the CreateAction in any other cases? */
1144 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1145 *pOplock |= CIFS_CREATE_ACTION;
1146 /* check to make sure response data is there */
1147 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1148 pRetData->Type = cpu_to_le32(-1); /* unknown */
1149 cFYI(DBG2, ("unknown type"));
1151 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1152 + sizeof(FILE_UNIX_BASIC_INFO)) {
1153 cERROR(1, ("Open response data too small"));
1154 pRetData->Type = cpu_to_le32(-1);
1155 goto psx_create_err;
1157 memcpy((char *) pRetData,
1158 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1159 sizeof(FILE_UNIX_BASIC_INFO));
1163 cifs_buf_release(pSMB);
1165 cifs_stats_inc(&tcon->num_mkdirs);
1173 static __u16 convert_disposition(int disposition)
1177 switch (disposition) {
1178 case FILE_SUPERSEDE:
1179 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1182 ofun = SMBOPEN_OAPPEND;
1185 ofun = SMBOPEN_OCREATE;
1188 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1190 case FILE_OVERWRITE:
1191 ofun = SMBOPEN_OTRUNC;
1193 case FILE_OVERWRITE_IF:
1194 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1197 cFYI(1, ("unknown disposition %d", disposition));
1198 ofun = SMBOPEN_OAPPEND; /* regular open */
1204 access_flags_to_smbopen_mode(const int access_flags)
1206 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1208 if (masked_flags == GENERIC_READ)
1209 return SMBOPEN_READ;
1210 else if (masked_flags == GENERIC_WRITE)
1211 return SMBOPEN_WRITE;
1213 /* just go for read/write */
1214 return SMBOPEN_READWRITE;
1218 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1219 const char *fileName, const int openDisposition,
1220 const int access_flags, const int create_options, __u16 *netfid,
1221 int *pOplock, FILE_ALL_INFO *pfile_info,
1222 const struct nls_table *nls_codepage, int remap)
1225 OPENX_REQ *pSMB = NULL;
1226 OPENX_RSP *pSMBr = NULL;
1232 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1237 pSMB->AndXCommand = 0xFF; /* none */
1239 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1240 count = 1; /* account for one byte pad to word boundary */
1242 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1243 fileName, PATH_MAX, nls_codepage, remap);
1244 name_len++; /* trailing null */
1246 } else { /* BB improve check for buffer overruns BB */
1247 count = 0; /* no pad */
1248 name_len = strnlen(fileName, PATH_MAX);
1249 name_len++; /* trailing null */
1250 strncpy(pSMB->fileName, fileName, name_len);
1252 if (*pOplock & REQ_OPLOCK)
1253 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1254 else if (*pOplock & REQ_BATCHOPLOCK)
1255 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1257 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1258 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1259 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1260 /* set file as system file if special file such
1261 as fifo and server expecting SFU style and
1262 no Unix extensions */
1264 if (create_options & CREATE_OPTION_SPECIAL)
1265 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1266 else /* BB FIXME BB */
1267 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1269 if (create_options & CREATE_OPTION_READONLY)
1270 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1273 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1274 CREATE_OPTIONS_MASK); */
1275 /* BB FIXME END BB */
1277 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1278 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1280 pSMB->hdr.smb_buf_length += count;
1282 pSMB->ByteCount = cpu_to_le16(count);
1283 /* long_op set to 1 to allow for oplock break timeouts */
1284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1285 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1286 cifs_stats_inc(&tcon->num_opens);
1288 cFYI(1, ("Error in Open = %d", rc));
1290 /* BB verify if wct == 15 */
1292 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1294 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1295 /* Let caller know file was created so we can set the mode. */
1296 /* Do we care about the CreateAction in any other cases? */
1298 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1299 *pOplock |= CIFS_CREATE_ACTION; */
1303 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1304 pfile_info->LastAccessTime = 0; /* BB fixme */
1305 pfile_info->LastWriteTime = 0; /* BB fixme */
1306 pfile_info->ChangeTime = 0; /* BB fixme */
1307 pfile_info->Attributes =
1308 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1309 /* the file_info buf is endian converted by caller */
1310 pfile_info->AllocationSize =
1311 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1312 pfile_info->EndOfFile = pfile_info->AllocationSize;
1313 pfile_info->NumberOfLinks = cpu_to_le32(1);
1317 cifs_buf_release(pSMB);
1324 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1325 const char *fileName, const int openDisposition,
1326 const int access_flags, const int create_options, __u16 *netfid,
1327 int *pOplock, FILE_ALL_INFO *pfile_info,
1328 const struct nls_table *nls_codepage, int remap)
1331 OPEN_REQ *pSMB = NULL;
1332 OPEN_RSP *pSMBr = NULL;
1338 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1343 pSMB->AndXCommand = 0xFF; /* none */
1345 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1346 count = 1; /* account for one byte pad to word boundary */
1348 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1349 fileName, PATH_MAX, nls_codepage, remap);
1350 name_len++; /* trailing null */
1352 pSMB->NameLength = cpu_to_le16(name_len);
1353 } else { /* BB improve check for buffer overruns BB */
1354 count = 0; /* no pad */
1355 name_len = strnlen(fileName, PATH_MAX);
1356 name_len++; /* trailing null */
1357 pSMB->NameLength = cpu_to_le16(name_len);
1358 strncpy(pSMB->fileName, fileName, name_len);
1360 if (*pOplock & REQ_OPLOCK)
1361 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1362 else if (*pOplock & REQ_BATCHOPLOCK)
1363 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1364 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1365 pSMB->AllocationSize = 0;
1366 /* set file as system file if special file such
1367 as fifo and server expecting SFU style and
1368 no Unix extensions */
1369 if (create_options & CREATE_OPTION_SPECIAL)
1370 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1372 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1374 /* XP does not handle ATTR_POSIX_SEMANTICS */
1375 /* but it helps speed up case sensitive checks for other
1376 servers such as Samba */
1377 if (tcon->ses->capabilities & CAP_UNIX)
1378 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1380 if (create_options & CREATE_OPTION_READONLY)
1381 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1383 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1384 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1385 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1386 /* BB Expirement with various impersonation levels and verify */
1387 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1388 pSMB->SecurityFlags =
1389 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1392 pSMB->hdr.smb_buf_length += count;
1394 pSMB->ByteCount = cpu_to_le16(count);
1395 /* long_op set to 1 to allow for oplock break timeouts */
1396 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1397 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1398 cifs_stats_inc(&tcon->num_opens);
1400 cFYI(1, ("Error in Open = %d", rc));
1402 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1403 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1404 /* Let caller know file was created so we can set the mode. */
1405 /* Do we care about the CreateAction in any other cases? */
1406 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1407 *pOplock |= CIFS_CREATE_ACTION;
1409 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1410 36 /* CreationTime to Attributes */);
1411 /* the file_info buf is endian converted by caller */
1412 pfile_info->AllocationSize = pSMBr->AllocationSize;
1413 pfile_info->EndOfFile = pSMBr->EndOfFile;
1414 pfile_info->NumberOfLinks = cpu_to_le32(1);
1418 cifs_buf_release(pSMB);
1425 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1426 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1427 char **buf, int *pbuf_type)
1430 READ_REQ *pSMB = NULL;
1431 READ_RSP *pSMBr = NULL;
1432 char *pReadData = NULL;
1434 int resp_buf_type = 0;
1437 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1438 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1441 wct = 10; /* old style read */
1444 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1448 /* tcon and ses pointer are checked in smb_init */
1449 if (tcon->ses->server == NULL)
1450 return -ECONNABORTED;
1452 pSMB->AndXCommand = 0xFF; /* none */
1454 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1456 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1457 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1460 pSMB->Remaining = 0;
1461 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1462 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1464 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1466 /* old style read */
1467 struct smb_com_readx_req *pSMBW =
1468 (struct smb_com_readx_req *)pSMB;
1469 pSMBW->ByteCount = 0;
1472 iov[0].iov_base = (char *)pSMB;
1473 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1474 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1475 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1476 cifs_stats_inc(&tcon->num_reads);
1477 pSMBr = (READ_RSP *)iov[0].iov_base;
1479 cERROR(1, ("Send error in read = %d", rc));
1481 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1482 data_length = data_length << 16;
1483 data_length += le16_to_cpu(pSMBr->DataLength);
1484 *nbytes = data_length;
1486 /*check that DataLength would not go beyond end of SMB */
1487 if ((data_length > CIFSMaxBufSize)
1488 || (data_length > count)) {
1489 cFYI(1, ("bad length %d for count %d",
1490 data_length, count));
1494 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1495 le16_to_cpu(pSMBr->DataOffset);
1496 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1497 cERROR(1,("Faulting on read rc = %d",rc));
1499 }*/ /* can not use copy_to_user when using page cache*/
1501 memcpy(*buf, pReadData, data_length);
1505 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1507 if (resp_buf_type == CIFS_SMALL_BUFFER)
1508 cifs_small_buf_release(iov[0].iov_base);
1509 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1510 cifs_buf_release(iov[0].iov_base);
1511 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1512 /* return buffer to caller to free */
1513 *buf = iov[0].iov_base;
1514 if (resp_buf_type == CIFS_SMALL_BUFFER)
1515 *pbuf_type = CIFS_SMALL_BUFFER;
1516 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1517 *pbuf_type = CIFS_LARGE_BUFFER;
1518 } /* else no valid buffer on return - leave as null */
1520 /* Note: On -EAGAIN error only caller can retry on handle based calls
1521 since file handle passed in no longer valid */
1527 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1528 const int netfid, const unsigned int count,
1529 const __u64 offset, unsigned int *nbytes, const char *buf,
1530 const char __user *ubuf, const int long_op)
1533 WRITE_REQ *pSMB = NULL;
1534 WRITE_RSP *pSMBr = NULL;
1535 int bytes_returned, wct;
1539 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1540 if (tcon->ses == NULL)
1541 return -ECONNABORTED;
1543 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1548 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1552 /* tcon and ses pointer are checked in smb_init */
1553 if (tcon->ses->server == NULL)
1554 return -ECONNABORTED;
1556 pSMB->AndXCommand = 0xFF; /* none */
1558 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1560 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1561 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1564 pSMB->Reserved = 0xFFFFFFFF;
1565 pSMB->WriteMode = 0;
1566 pSMB->Remaining = 0;
1568 /* Can increase buffer size if buffer is big enough in some cases ie we
1569 can send more if LARGE_WRITE_X capability returned by the server and if
1570 our buffer is big enough or if we convert to iovecs on socket writes
1571 and eliminate the copy to the CIFS buffer */
1572 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1573 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1575 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1579 if (bytes_sent > count)
1582 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1584 memcpy(pSMB->Data, buf, bytes_sent);
1586 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1587 cifs_buf_release(pSMB);
1590 } else if (count != 0) {
1592 cifs_buf_release(pSMB);
1594 } /* else setting file size with write of zero bytes */
1596 byte_count = bytes_sent + 1; /* pad */
1597 else /* wct == 12 */
1598 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1600 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1601 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1602 pSMB->hdr.smb_buf_length += byte_count;
1605 pSMB->ByteCount = cpu_to_le16(byte_count);
1606 else { /* old style write has byte count 4 bytes earlier
1608 struct smb_com_writex_req *pSMBW =
1609 (struct smb_com_writex_req *)pSMB;
1610 pSMBW->ByteCount = cpu_to_le16(byte_count);
1613 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1614 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1615 cifs_stats_inc(&tcon->num_writes);
1617 cFYI(1, ("Send error in write = %d", rc));
1620 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1621 *nbytes = (*nbytes) << 16;
1622 *nbytes += le16_to_cpu(pSMBr->Count);
1625 cifs_buf_release(pSMB);
1627 /* Note: On -EAGAIN error only caller can retry on handle based calls
1628 since file handle passed in no longer valid */
1634 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1635 const int netfid, const unsigned int count,
1636 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1637 int n_vec, const int long_op)
1640 WRITE_REQ *pSMB = NULL;
1643 int resp_buf_type = 0;
1645 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1647 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1651 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1654 /* tcon and ses pointer are checked in smb_init */
1655 if (tcon->ses->server == NULL)
1656 return -ECONNABORTED;
1658 pSMB->AndXCommand = 0xFF; /* none */
1660 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1662 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1663 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1665 pSMB->Reserved = 0xFFFFFFFF;
1666 pSMB->WriteMode = 0;
1667 pSMB->Remaining = 0;
1670 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1672 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1673 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1674 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1676 pSMB->hdr.smb_buf_length += count+1;
1677 else /* wct == 12 */
1678 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1680 pSMB->ByteCount = cpu_to_le16(count + 1);
1681 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1682 struct smb_com_writex_req *pSMBW =
1683 (struct smb_com_writex_req *)pSMB;
1684 pSMBW->ByteCount = cpu_to_le16(count + 5);
1686 iov[0].iov_base = pSMB;
1688 iov[0].iov_len = smb_hdr_len + 4;
1689 else /* wct == 12 pad bigger by four bytes */
1690 iov[0].iov_len = smb_hdr_len + 8;
1693 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1695 cifs_stats_inc(&tcon->num_writes);
1697 cFYI(1, ("Send error Write2 = %d", rc));
1699 } else if (resp_buf_type == 0) {
1700 /* presumably this can not happen, but best to be safe */
1704 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1705 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1706 *nbytes = (*nbytes) << 16;
1707 *nbytes += le16_to_cpu(pSMBr->Count);
1710 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1711 if (resp_buf_type == CIFS_SMALL_BUFFER)
1712 cifs_small_buf_release(iov[0].iov_base);
1713 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1714 cifs_buf_release(iov[0].iov_base);
1716 /* Note: On -EAGAIN error only caller can retry on handle based calls
1717 since file handle passed in no longer valid */
1724 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1725 const __u16 smb_file_id, const __u64 len,
1726 const __u64 offset, const __u32 numUnlock,
1727 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1730 LOCK_REQ *pSMB = NULL;
1731 LOCK_RSP *pSMBr = NULL;
1736 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1737 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1742 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1744 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1745 timeout = CIFS_ASYNC_OP; /* no response expected */
1747 } else if (waitFlag) {
1748 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1749 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1754 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1755 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1756 pSMB->LockType = lockType;
1757 pSMB->AndXCommand = 0xFF; /* none */
1758 pSMB->Fid = smb_file_id; /* netfid stays le */
1760 if ((numLock != 0) || (numUnlock != 0)) {
1761 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1762 /* BB where to store pid high? */
1763 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1764 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1765 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1766 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1767 count = sizeof(LOCKING_ANDX_RANGE);
1772 pSMB->hdr.smb_buf_length += count;
1773 pSMB->ByteCount = cpu_to_le16(count);
1776 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1777 (struct smb_hdr *) pSMBr, &bytes_returned);
1778 cifs_small_buf_release(pSMB);
1780 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1782 /* SMB buffer freed by function above */
1784 cifs_stats_inc(&tcon->num_locks);
1786 cFYI(1, ("Send error in Lock = %d", rc));
1788 /* Note: On -EAGAIN error only caller can retry on handle based calls
1789 since file handle passed in no longer valid */
1794 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1795 const __u16 smb_file_id, const int get_flag, const __u64 len,
1796 struct file_lock *pLockData, const __u16 lock_type,
1797 const bool waitFlag)
1799 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1800 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1801 struct cifs_posix_lock *parm_data;
1804 int bytes_returned = 0;
1805 int resp_buf_type = 0;
1806 __u16 params, param_offset, offset, byte_count, count;
1809 cFYI(1, ("Posix Lock"));
1811 if (pLockData == NULL)
1814 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1819 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1822 pSMB->MaxSetupCount = 0;
1825 pSMB->Reserved2 = 0;
1826 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1827 offset = param_offset + params;
1829 count = sizeof(struct cifs_posix_lock);
1830 pSMB->MaxParameterCount = cpu_to_le16(2);
1831 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1832 pSMB->SetupCount = 1;
1833 pSMB->Reserved3 = 0;
1835 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1837 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1838 byte_count = 3 /* pad */ + params + count;
1839 pSMB->DataCount = cpu_to_le16(count);
1840 pSMB->ParameterCount = cpu_to_le16(params);
1841 pSMB->TotalDataCount = pSMB->DataCount;
1842 pSMB->TotalParameterCount = pSMB->ParameterCount;
1843 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1844 parm_data = (struct cifs_posix_lock *)
1845 (((char *) &pSMB->hdr.Protocol) + offset);
1847 parm_data->lock_type = cpu_to_le16(lock_type);
1849 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1850 parm_data->lock_flags = cpu_to_le16(1);
1851 pSMB->Timeout = cpu_to_le32(-1);
1855 parm_data->pid = cpu_to_le32(current->tgid);
1856 parm_data->start = cpu_to_le64(pLockData->fl_start);
1857 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1859 pSMB->DataOffset = cpu_to_le16(offset);
1860 pSMB->Fid = smb_file_id;
1861 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1862 pSMB->Reserved4 = 0;
1863 pSMB->hdr.smb_buf_length += byte_count;
1864 pSMB->ByteCount = cpu_to_le16(byte_count);
1866 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1867 (struct smb_hdr *) pSMBr, &bytes_returned);
1869 iov[0].iov_base = (char *)pSMB;
1870 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1871 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1872 &resp_buf_type, timeout);
1873 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1874 not try to free it twice below on exit */
1875 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1879 cFYI(1, ("Send error in Posix Lock = %d", rc));
1880 } else if (get_flag) {
1881 /* lock structure can be returned on get */
1884 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1886 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1887 rc = -EIO; /* bad smb */
1890 if (pLockData == NULL) {
1894 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1895 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1896 if (data_count < sizeof(struct cifs_posix_lock)) {
1900 parm_data = (struct cifs_posix_lock *)
1901 ((char *)&pSMBr->hdr.Protocol + data_offset);
1902 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1903 pLockData->fl_type = F_UNLCK;
1908 cifs_small_buf_release(pSMB);
1910 if (resp_buf_type == CIFS_SMALL_BUFFER)
1911 cifs_small_buf_release(iov[0].iov_base);
1912 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1913 cifs_buf_release(iov[0].iov_base);
1915 /* Note: On -EAGAIN error only caller can retry on handle based calls
1916 since file handle passed in no longer valid */
1923 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1926 CLOSE_REQ *pSMB = NULL;
1927 cFYI(1, ("In CIFSSMBClose"));
1929 /* do not retry on dead session on close */
1930 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1936 pSMB->FileID = (__u16) smb_file_id;
1937 pSMB->LastWriteTime = 0xFFFFFFFF;
1938 pSMB->ByteCount = 0;
1939 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1940 cifs_stats_inc(&tcon->num_closes);
1943 /* EINTR is expected when user ctl-c to kill app */
1944 cERROR(1, ("Send error in Close = %d", rc));
1948 /* Since session is dead, file will be closed on server already */
1956 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1957 const char *fromName, const char *toName,
1958 const struct nls_table *nls_codepage, int remap)
1961 RENAME_REQ *pSMB = NULL;
1962 RENAME_RSP *pSMBr = NULL;
1964 int name_len, name_len2;
1967 cFYI(1, ("In CIFSSMBRename"));
1969 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1974 pSMB->BufferFormat = 0x04;
1975 pSMB->SearchAttributes =
1976 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1979 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1981 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1982 PATH_MAX, nls_codepage, remap);
1983 name_len++; /* trailing null */
1985 pSMB->OldFileName[name_len] = 0x04; /* pad */
1986 /* protocol requires ASCII signature byte on Unicode string */
1987 pSMB->OldFileName[name_len + 1] = 0x00;
1989 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1990 toName, PATH_MAX, nls_codepage, remap);
1991 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1992 name_len2 *= 2; /* convert to bytes */
1993 } else { /* BB improve the check for buffer overruns BB */
1994 name_len = strnlen(fromName, PATH_MAX);
1995 name_len++; /* trailing null */
1996 strncpy(pSMB->OldFileName, fromName, name_len);
1997 name_len2 = strnlen(toName, PATH_MAX);
1998 name_len2++; /* trailing null */
1999 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2000 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2001 name_len2++; /* trailing null */
2002 name_len2++; /* signature byte */
2005 count = 1 /* 1st signature byte */ + name_len + name_len2;
2006 pSMB->hdr.smb_buf_length += count;
2007 pSMB->ByteCount = cpu_to_le16(count);
2009 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2010 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2011 cifs_stats_inc(&tcon->num_renames);
2013 cFYI(1, ("Send error in rename = %d", rc));
2015 cifs_buf_release(pSMB);
2023 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2024 int netfid, char *target_name,
2025 const struct nls_table *nls_codepage, int remap)
2027 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2028 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2029 struct set_file_rename *rename_info;
2031 char dummy_string[30];
2033 int bytes_returned = 0;
2035 __u16 params, param_offset, offset, count, byte_count;
2037 cFYI(1, ("Rename to File by handle"));
2038 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2044 pSMB->MaxSetupCount = 0;
2048 pSMB->Reserved2 = 0;
2049 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2050 offset = param_offset + params;
2052 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2053 rename_info = (struct set_file_rename *) data_offset;
2054 pSMB->MaxParameterCount = cpu_to_le16(2);
2055 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2056 pSMB->SetupCount = 1;
2057 pSMB->Reserved3 = 0;
2058 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2059 byte_count = 3 /* pad */ + params;
2060 pSMB->ParameterCount = cpu_to_le16(params);
2061 pSMB->TotalParameterCount = pSMB->ParameterCount;
2062 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2063 pSMB->DataOffset = cpu_to_le16(offset);
2064 /* construct random name ".cifs_tmp<inodenum><mid>" */
2065 rename_info->overwrite = cpu_to_le32(1);
2066 rename_info->root_fid = 0;
2067 /* unicode only call */
2068 if (target_name == NULL) {
2069 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2070 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2071 dummy_string, 24, nls_codepage, remap);
2073 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2074 target_name, PATH_MAX, nls_codepage,
2077 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2078 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2079 byte_count += count;
2080 pSMB->DataCount = cpu_to_le16(count);
2081 pSMB->TotalDataCount = pSMB->DataCount;
2083 pSMB->InformationLevel =
2084 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2085 pSMB->Reserved4 = 0;
2086 pSMB->hdr.smb_buf_length += byte_count;
2087 pSMB->ByteCount = cpu_to_le16(byte_count);
2088 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2089 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2090 cifs_stats_inc(&pTcon->num_t2renames);
2092 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2094 cifs_buf_release(pSMB);
2096 /* Note: On -EAGAIN error only caller can retry on handle based calls
2097 since file handle passed in no longer valid */
2103 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2104 const __u16 target_tid, const char *toName, const int flags,
2105 const struct nls_table *nls_codepage, int remap)
2108 COPY_REQ *pSMB = NULL;
2109 COPY_RSP *pSMBr = NULL;
2111 int name_len, name_len2;
2114 cFYI(1, ("In CIFSSMBCopy"));
2116 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2121 pSMB->BufferFormat = 0x04;
2122 pSMB->Tid2 = target_tid;
2124 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2126 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2127 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2128 fromName, PATH_MAX, nls_codepage,
2130 name_len++; /* trailing null */
2132 pSMB->OldFileName[name_len] = 0x04; /* pad */
2133 /* protocol requires ASCII signature byte on Unicode string */
2134 pSMB->OldFileName[name_len + 1] = 0x00;
2136 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2137 toName, PATH_MAX, nls_codepage, remap);
2138 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2139 name_len2 *= 2; /* convert to bytes */
2140 } else { /* BB improve the check for buffer overruns BB */
2141 name_len = strnlen(fromName, PATH_MAX);
2142 name_len++; /* trailing null */
2143 strncpy(pSMB->OldFileName, fromName, name_len);
2144 name_len2 = strnlen(toName, PATH_MAX);
2145 name_len2++; /* trailing null */
2146 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2147 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2148 name_len2++; /* trailing null */
2149 name_len2++; /* signature byte */
2152 count = 1 /* 1st signature byte */ + name_len + name_len2;
2153 pSMB->hdr.smb_buf_length += count;
2154 pSMB->ByteCount = cpu_to_le16(count);
2156 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2157 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2159 cFYI(1, ("Send error in copy = %d with %d files copied",
2160 rc, le16_to_cpu(pSMBr->CopyCount)));
2163 cifs_buf_release(pSMB);
2172 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2173 const char *fromName, const char *toName,
2174 const struct nls_table *nls_codepage)
2176 TRANSACTION2_SPI_REQ *pSMB = NULL;
2177 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2180 int name_len_target;
2182 int bytes_returned = 0;
2183 __u16 params, param_offset, offset, byte_count;
2185 cFYI(1, ("In Symlink Unix style"));
2187 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2192 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2194 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2195 /* find define for this maxpathcomponent */
2197 name_len++; /* trailing null */
2200 } else { /* BB improve the check for buffer overruns BB */
2201 name_len = strnlen(fromName, PATH_MAX);
2202 name_len++; /* trailing null */
2203 strncpy(pSMB->FileName, fromName, name_len);
2205 params = 6 + name_len;
2206 pSMB->MaxSetupCount = 0;
2210 pSMB->Reserved2 = 0;
2211 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2212 InformationLevel) - 4;
2213 offset = param_offset + params;
2215 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2216 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2218 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2219 /* find define for this maxpathcomponent */
2221 name_len_target++; /* trailing null */
2222 name_len_target *= 2;
2223 } else { /* BB improve the check for buffer overruns BB */
2224 name_len_target = strnlen(toName, PATH_MAX);
2225 name_len_target++; /* trailing null */
2226 strncpy(data_offset, toName, name_len_target);
2229 pSMB->MaxParameterCount = cpu_to_le16(2);
2230 /* BB find exact max on data count below from sess */
2231 pSMB->MaxDataCount = cpu_to_le16(1000);
2232 pSMB->SetupCount = 1;
2233 pSMB->Reserved3 = 0;
2234 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2235 byte_count = 3 /* pad */ + params + name_len_target;
2236 pSMB->DataCount = cpu_to_le16(name_len_target);
2237 pSMB->ParameterCount = cpu_to_le16(params);
2238 pSMB->TotalDataCount = pSMB->DataCount;
2239 pSMB->TotalParameterCount = pSMB->ParameterCount;
2240 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2241 pSMB->DataOffset = cpu_to_le16(offset);
2242 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2243 pSMB->Reserved4 = 0;
2244 pSMB->hdr.smb_buf_length += byte_count;
2245 pSMB->ByteCount = cpu_to_le16(byte_count);
2246 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2247 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2248 cifs_stats_inc(&tcon->num_symlinks);
2250 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2253 cifs_buf_release(pSMB);
2256 goto createSymLinkRetry;
2262 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2263 const char *fromName, const char *toName,
2264 const struct nls_table *nls_codepage, int remap)
2266 TRANSACTION2_SPI_REQ *pSMB = NULL;
2267 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2270 int name_len_target;
2272 int bytes_returned = 0;
2273 __u16 params, param_offset, offset, byte_count;
2275 cFYI(1, ("In Create Hard link Unix style"));
2276 createHardLinkRetry:
2277 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2282 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2283 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2284 PATH_MAX, nls_codepage, remap);
2285 name_len++; /* trailing null */
2288 } else { /* BB improve the check for buffer overruns BB */
2289 name_len = strnlen(toName, PATH_MAX);
2290 name_len++; /* trailing null */
2291 strncpy(pSMB->FileName, toName, name_len);
2293 params = 6 + name_len;
2294 pSMB->MaxSetupCount = 0;
2298 pSMB->Reserved2 = 0;
2299 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2300 InformationLevel) - 4;
2301 offset = param_offset + params;
2303 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2306 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2307 nls_codepage, remap);
2308 name_len_target++; /* trailing null */
2309 name_len_target *= 2;
2310 } else { /* BB improve the check for buffer overruns BB */
2311 name_len_target = strnlen(fromName, PATH_MAX);
2312 name_len_target++; /* trailing null */
2313 strncpy(data_offset, fromName, name_len_target);
2316 pSMB->MaxParameterCount = cpu_to_le16(2);
2317 /* BB find exact max on data count below from sess*/
2318 pSMB->MaxDataCount = cpu_to_le16(1000);
2319 pSMB->SetupCount = 1;
2320 pSMB->Reserved3 = 0;
2321 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2322 byte_count = 3 /* pad */ + params + name_len_target;
2323 pSMB->ParameterCount = cpu_to_le16(params);
2324 pSMB->TotalParameterCount = pSMB->ParameterCount;
2325 pSMB->DataCount = cpu_to_le16(name_len_target);
2326 pSMB->TotalDataCount = pSMB->DataCount;
2327 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2328 pSMB->DataOffset = cpu_to_le16(offset);
2329 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2330 pSMB->Reserved4 = 0;
2331 pSMB->hdr.smb_buf_length += byte_count;
2332 pSMB->ByteCount = cpu_to_le16(byte_count);
2333 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2334 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2335 cifs_stats_inc(&tcon->num_hardlinks);
2337 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2339 cifs_buf_release(pSMB);
2341 goto createHardLinkRetry;
2347 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2348 const char *fromName, const char *toName,
2349 const struct nls_table *nls_codepage, int remap)
2352 NT_RENAME_REQ *pSMB = NULL;
2353 RENAME_RSP *pSMBr = NULL;
2355 int name_len, name_len2;
2358 cFYI(1, ("In CIFSCreateHardLink"));
2359 winCreateHardLinkRetry:
2361 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2366 pSMB->SearchAttributes =
2367 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2369 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2370 pSMB->ClusterCount = 0;
2372 pSMB->BufferFormat = 0x04;
2374 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2376 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2377 PATH_MAX, nls_codepage, remap);
2378 name_len++; /* trailing null */
2380 pSMB->OldFileName[name_len] = 0; /* pad */
2381 pSMB->OldFileName[name_len + 1] = 0x04;
2383 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2384 toName, PATH_MAX, nls_codepage, remap);
2385 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2386 name_len2 *= 2; /* convert to bytes */
2387 } else { /* BB improve the check for buffer overruns BB */
2388 name_len = strnlen(fromName, PATH_MAX);
2389 name_len++; /* trailing null */
2390 strncpy(pSMB->OldFileName, fromName, name_len);
2391 name_len2 = strnlen(toName, PATH_MAX);
2392 name_len2++; /* trailing null */
2393 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2394 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2395 name_len2++; /* trailing null */
2396 name_len2++; /* signature byte */
2399 count = 1 /* string type byte */ + name_len + name_len2;
2400 pSMB->hdr.smb_buf_length += count;
2401 pSMB->ByteCount = cpu_to_le16(count);
2403 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2404 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2405 cifs_stats_inc(&tcon->num_hardlinks);
2407 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2409 cifs_buf_release(pSMB);
2411 goto winCreateHardLinkRetry;
2417 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2418 const unsigned char *searchName,
2419 char *symlinkinfo, const int buflen,
2420 const struct nls_table *nls_codepage)
2422 /* SMB_QUERY_FILE_UNIX_LINK */
2423 TRANSACTION2_QPI_REQ *pSMB = NULL;
2424 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2428 __u16 params, byte_count;
2430 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2433 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2438 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2440 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2441 PATH_MAX, nls_codepage);
2442 name_len++; /* trailing null */
2444 } else { /* BB improve the check for buffer overruns BB */
2445 name_len = strnlen(searchName, PATH_MAX);
2446 name_len++; /* trailing null */
2447 strncpy(pSMB->FileName, searchName, name_len);
2450 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2451 pSMB->TotalDataCount = 0;
2452 pSMB->MaxParameterCount = cpu_to_le16(2);
2453 /* BB find exact max data count below from sess structure BB */
2454 pSMB->MaxDataCount = cpu_to_le16(4000);
2455 pSMB->MaxSetupCount = 0;
2459 pSMB->Reserved2 = 0;
2460 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2461 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2462 pSMB->DataCount = 0;
2463 pSMB->DataOffset = 0;
2464 pSMB->SetupCount = 1;
2465 pSMB->Reserved3 = 0;
2466 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2467 byte_count = params + 1 /* pad */ ;
2468 pSMB->TotalParameterCount = cpu_to_le16(params);
2469 pSMB->ParameterCount = pSMB->TotalParameterCount;
2470 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2471 pSMB->Reserved4 = 0;
2472 pSMB->hdr.smb_buf_length += byte_count;
2473 pSMB->ByteCount = cpu_to_le16(byte_count);
2475 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2478 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2480 /* decode response */
2482 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2483 if (rc || (pSMBr->ByteCount < 2))
2484 /* BB also check enough total bytes returned */
2485 rc = -EIO; /* bad smb */
2487 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2488 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2490 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2491 name_len = UniStrnlen((wchar_t *) ((char *)
2492 &pSMBr->hdr.Protocol + data_offset),
2493 min_t(const int, buflen, count) / 2);
2494 /* BB FIXME investigate remapping reserved chars here */
2495 cifs_strfromUCS_le(symlinkinfo,
2496 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2498 name_len, nls_codepage);
2500 strncpy(symlinkinfo,
2501 (char *) &pSMBr->hdr.Protocol +
2503 min_t(const int, buflen, count));
2505 symlinkinfo[buflen] = 0;
2506 /* just in case so calling code does not go off the end of buffer */
2509 cifs_buf_release(pSMB);
2511 goto querySymLinkRetry;
2515 #ifdef CONFIG_CIFS_EXPERIMENTAL
2516 /* Initialize NT TRANSACT SMB into small smb request buffer.
2517 This assumes that all NT TRANSACTS that we init here have
2518 total parm and data under about 400 bytes (to fit in small cifs
2519 buffer size), which is the case so far, it easily fits. NB:
2520 Setup words themselves and ByteCount
2521 MaxSetupCount (size of returned setup area) and
2522 MaxParameterCount (returned parms size) must be set by caller */
2524 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2525 const int parm_len, struct cifsTconInfo *tcon,
2530 struct smb_com_ntransact_req *pSMB;
2532 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2536 *ret_buf = (void *)pSMB;
2538 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2539 pSMB->TotalDataCount = 0;
2540 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2541 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2542 pSMB->ParameterCount = pSMB->TotalParameterCount;
2543 pSMB->DataCount = pSMB->TotalDataCount;
2544 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2545 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2546 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2547 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2548 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2549 pSMB->SubCommand = cpu_to_le16(sub_command);
2554 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2555 __u32 *pparmlen, __u32 *pdatalen)
2558 __u32 data_count, data_offset, parm_count, parm_offset;
2559 struct smb_com_ntransact_rsp *pSMBr;
2567 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2569 /* ByteCount was converted from little endian in SendReceive */
2570 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2571 (char *)&pSMBr->ByteCount;
2573 data_offset = le32_to_cpu(pSMBr->DataOffset);
2574 data_count = le32_to_cpu(pSMBr->DataCount);
2575 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2576 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2578 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2579 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2581 /* should we also check that parm and data areas do not overlap? */
2582 if (*ppparm > end_of_smb) {
2583 cFYI(1, ("parms start after end of smb"));
2585 } else if (parm_count + *ppparm > end_of_smb) {
2586 cFYI(1, ("parm end after end of smb"));
2588 } else if (*ppdata > end_of_smb) {
2589 cFYI(1, ("data starts after end of smb"));
2591 } else if (data_count + *ppdata > end_of_smb) {
2592 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2593 *ppdata, data_count, (data_count + *ppdata),
2594 end_of_smb, pSMBr));
2596 } else if (parm_count + data_count > pSMBr->ByteCount) {
2597 cFYI(1, ("parm count and data count larger than SMB"));
2600 *pdatalen = data_count;
2601 *pparmlen = parm_count;
2604 #endif /* CIFS_EXPERIMENTAL */
2607 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2608 const unsigned char *searchName,
2609 char *symlinkinfo, const int buflen, __u16 fid,
2610 const struct nls_table *nls_codepage)
2615 struct smb_com_transaction_ioctl_req *pSMB;
2616 struct smb_com_transaction_ioctl_rsp *pSMBr;
2618 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2619 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2624 pSMB->TotalParameterCount = 0 ;
2625 pSMB->TotalDataCount = 0;
2626 pSMB->MaxParameterCount = cpu_to_le32(2);
2627 /* BB find exact data count max from sess structure BB */
2628 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2629 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2630 pSMB->MaxSetupCount = 4;
2632 pSMB->ParameterOffset = 0;
2633 pSMB->DataCount = 0;
2634 pSMB->DataOffset = 0;
2635 pSMB->SetupCount = 4;
2636 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2637 pSMB->ParameterCount = pSMB->TotalParameterCount;
2638 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2639 pSMB->IsFsctl = 1; /* FSCTL */
2640 pSMB->IsRootFlag = 0;
2641 pSMB->Fid = fid; /* file handle always le */
2642 pSMB->ByteCount = 0;
2644 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2645 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2647 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2648 } else { /* decode response */
2649 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2650 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2651 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2652 /* BB also check enough total bytes returned */
2653 rc = -EIO; /* bad smb */
2655 if (data_count && (data_count < 2048)) {
2656 char *end_of_smb = 2 /* sizeof byte count */ +
2658 (char *)&pSMBr->ByteCount;
2660 struct reparse_data *reparse_buf =
2661 (struct reparse_data *)
2662 ((char *)&pSMBr->hdr.Protocol
2664 if ((char *)reparse_buf >= end_of_smb) {
2668 if ((reparse_buf->LinkNamesBuf +
2669 reparse_buf->TargetNameOffset +
2670 reparse_buf->TargetNameLen) >
2672 cFYI(1, ("reparse buf beyond SMB"));
2677 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2678 name_len = UniStrnlen((wchar_t *)
2679 (reparse_buf->LinkNamesBuf +
2680 reparse_buf->TargetNameOffset),
2682 reparse_buf->TargetNameLen / 2));
2683 cifs_strfromUCS_le(symlinkinfo,
2684 (__le16 *) (reparse_buf->LinkNamesBuf +
2685 reparse_buf->TargetNameOffset),
2686 name_len, nls_codepage);
2687 } else { /* ASCII names */
2688 strncpy(symlinkinfo,
2689 reparse_buf->LinkNamesBuf +
2690 reparse_buf->TargetNameOffset,
2691 min_t(const int, buflen,
2692 reparse_buf->TargetNameLen));
2696 cFYI(1, ("Invalid return data count on "
2697 "get reparse info ioctl"));
2699 symlinkinfo[buflen] = 0; /* just in case so the caller
2700 does not go off the end of the buffer */
2701 cFYI(1, ("readlink result - %s", symlinkinfo));
2705 cifs_buf_release(pSMB);
2707 /* Note: On -EAGAIN error only caller can retry on handle based calls
2708 since file handle passed in no longer valid */
2713 #ifdef CONFIG_CIFS_POSIX
2715 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2716 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2717 struct cifs_posix_ace *cifs_ace)
2719 /* u8 cifs fields do not need le conversion */
2720 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2721 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2722 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2723 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2728 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2729 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2730 const int acl_type, const int size_of_data_area)
2735 struct cifs_posix_ace *pACE;
2736 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2737 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2739 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2742 if (acl_type & ACL_TYPE_ACCESS) {
2743 count = le16_to_cpu(cifs_acl->access_entry_count);
2744 pACE = &cifs_acl->ace_array[0];
2745 size = sizeof(struct cifs_posix_acl);
2746 size += sizeof(struct cifs_posix_ace) * count;
2747 /* check if we would go beyond end of SMB */
2748 if (size_of_data_area < size) {
2749 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2750 size_of_data_area, size));
2753 } else if (acl_type & ACL_TYPE_DEFAULT) {
2754 count = le16_to_cpu(cifs_acl->access_entry_count);
2755 size = sizeof(struct cifs_posix_acl);
2756 size += sizeof(struct cifs_posix_ace) * count;
2757 /* skip past access ACEs to get to default ACEs */
2758 pACE = &cifs_acl->ace_array[count];
2759 count = le16_to_cpu(cifs_acl->default_entry_count);
2760 size += sizeof(struct cifs_posix_ace) * count;
2761 /* check if we would go beyond end of SMB */
2762 if (size_of_data_area < size)
2769 size = posix_acl_xattr_size(count);
2770 if ((buflen == 0) || (local_acl == NULL)) {
2771 /* used to query ACL EA size */
2772 } else if (size > buflen) {
2774 } else /* buffer big enough */ {
2775 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2776 for (i = 0; i < count ; i++) {
2777 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2784 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2785 const posix_acl_xattr_entry *local_ace)
2787 __u16 rc = 0; /* 0 = ACL converted ok */
2789 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2790 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2791 /* BB is there a better way to handle the large uid? */
2792 if (local_ace->e_id == cpu_to_le32(-1)) {
2793 /* Probably no need to le convert -1 on any arch but can not hurt */
2794 cifs_ace->cifs_uid = cpu_to_le64(-1);
2796 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2797 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2801 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2802 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2803 const int buflen, const int acl_type)
2806 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2807 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2811 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2814 count = posix_acl_xattr_count((size_t)buflen);
2815 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2817 count, buflen, le32_to_cpu(local_acl->a_version)));
2818 if (le32_to_cpu(local_acl->a_version) != 2) {
2819 cFYI(1, ("unknown POSIX ACL version %d",
2820 le32_to_cpu(local_acl->a_version)));
2823 cifs_acl->version = cpu_to_le16(1);
2824 if (acl_type == ACL_TYPE_ACCESS)
2825 cifs_acl->access_entry_count = cpu_to_le16(count);
2826 else if (acl_type == ACL_TYPE_DEFAULT)
2827 cifs_acl->default_entry_count = cpu_to_le16(count);
2829 cFYI(1, ("unknown ACL type %d", acl_type));
2832 for (i = 0; i < count; i++) {
2833 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2834 &local_acl->a_entries[i]);
2836 /* ACE not converted */
2841 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2842 rc += sizeof(struct cifs_posix_acl);
2843 /* BB add check to make sure ACL does not overflow SMB */
2849 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2850 const unsigned char *searchName,
2851 char *acl_inf, const int buflen, const int acl_type,
2852 const struct nls_table *nls_codepage, int remap)
2854 /* SMB_QUERY_POSIX_ACL */
2855 TRANSACTION2_QPI_REQ *pSMB = NULL;
2856 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2860 __u16 params, byte_count;
2862 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2865 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2870 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2872 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2873 PATH_MAX, nls_codepage, remap);
2874 name_len++; /* trailing null */
2876 pSMB->FileName[name_len] = 0;
2877 pSMB->FileName[name_len+1] = 0;
2878 } else { /* BB improve the check for buffer overruns BB */
2879 name_len = strnlen(searchName, PATH_MAX);
2880 name_len++; /* trailing null */
2881 strncpy(pSMB->FileName, searchName, name_len);
2884 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2885 pSMB->TotalDataCount = 0;
2886 pSMB->MaxParameterCount = cpu_to_le16(2);
2887 /* BB find exact max data count below from sess structure BB */
2888 pSMB->MaxDataCount = cpu_to_le16(4000);
2889 pSMB->MaxSetupCount = 0;
2893 pSMB->Reserved2 = 0;
2894 pSMB->ParameterOffset = cpu_to_le16(
2895 offsetof(struct smb_com_transaction2_qpi_req,
2896 InformationLevel) - 4);
2897 pSMB->DataCount = 0;
2898 pSMB->DataOffset = 0;
2899 pSMB->SetupCount = 1;
2900 pSMB->Reserved3 = 0;
2901 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2902 byte_count = params + 1 /* pad */ ;
2903 pSMB->TotalParameterCount = cpu_to_le16(params);
2904 pSMB->ParameterCount = pSMB->TotalParameterCount;
2905 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2906 pSMB->Reserved4 = 0;
2907 pSMB->hdr.smb_buf_length += byte_count;
2908 pSMB->ByteCount = cpu_to_le16(byte_count);
2910 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2911 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2912 cifs_stats_inc(&tcon->num_acl_get);
2914 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2916 /* decode response */
2918 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2919 if (rc || (pSMBr->ByteCount < 2))
2920 /* BB also check enough total bytes returned */
2921 rc = -EIO; /* bad smb */
2923 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2924 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2925 rc = cifs_copy_posix_acl(acl_inf,
2926 (char *)&pSMBr->hdr.Protocol+data_offset,
2927 buflen, acl_type, count);
2930 cifs_buf_release(pSMB);
2937 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2938 const unsigned char *fileName,
2939 const char *local_acl, const int buflen,
2941 const struct nls_table *nls_codepage, int remap)
2943 struct smb_com_transaction2_spi_req *pSMB = NULL;
2944 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2948 int bytes_returned = 0;
2949 __u16 params, byte_count, data_count, param_offset, offset;
2951 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2953 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2957 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2959 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2960 PATH_MAX, nls_codepage, remap);
2961 name_len++; /* trailing null */
2963 } else { /* BB improve the check for buffer overruns BB */
2964 name_len = strnlen(fileName, PATH_MAX);
2965 name_len++; /* trailing null */
2966 strncpy(pSMB->FileName, fileName, name_len);
2968 params = 6 + name_len;
2969 pSMB->MaxParameterCount = cpu_to_le16(2);
2970 /* BB find max SMB size from sess */
2971 pSMB->MaxDataCount = cpu_to_le16(1000);
2972 pSMB->MaxSetupCount = 0;
2976 pSMB->Reserved2 = 0;
2977 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2978 InformationLevel) - 4;
2979 offset = param_offset + params;
2980 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2981 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2983 /* convert to on the wire format for POSIX ACL */
2984 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2986 if (data_count == 0) {
2988 goto setACLerrorExit;
2990 pSMB->DataOffset = cpu_to_le16(offset);
2991 pSMB->SetupCount = 1;
2992 pSMB->Reserved3 = 0;
2993 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2994 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2995 byte_count = 3 /* pad */ + params + data_count;
2996 pSMB->DataCount = cpu_to_le16(data_count);
2997 pSMB->TotalDataCount = pSMB->DataCount;
2998 pSMB->ParameterCount = cpu_to_le16(params);
2999 pSMB->TotalParameterCount = pSMB->ParameterCount;
3000 pSMB->Reserved4 = 0;
3001 pSMB->hdr.smb_buf_length += byte_count;
3002 pSMB->ByteCount = cpu_to_le16(byte_count);
3003 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3004 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3006 cFYI(1, ("Set POSIX ACL returned %d", rc));
3009 cifs_buf_release(pSMB);
3015 /* BB fix tabs in this function FIXME BB */
3017 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3018 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3021 struct smb_t2_qfi_req *pSMB = NULL;
3022 struct smb_t2_qfi_rsp *pSMBr = NULL;
3024 __u16 params, byte_count;
3026 cFYI(1, ("In GetExtAttr"));
3031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3036 params = 2 /* level */ + 2 /* fid */;
3037 pSMB->t2.TotalDataCount = 0;
3038 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3039 /* BB find exact max data count below from sess structure BB */
3040 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3041 pSMB->t2.MaxSetupCount = 0;
3042 pSMB->t2.Reserved = 0;
3044 pSMB->t2.Timeout = 0;
3045 pSMB->t2.Reserved2 = 0;
3046 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3048 pSMB->t2.DataCount = 0;
3049 pSMB->t2.DataOffset = 0;
3050 pSMB->t2.SetupCount = 1;
3051 pSMB->t2.Reserved3 = 0;
3052 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3053 byte_count = params + 1 /* pad */ ;
3054 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3055 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3056 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3059 pSMB->hdr.smb_buf_length += byte_count;
3060 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3062 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3063 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3065 cFYI(1, ("error %d in GetExtAttr", rc));
3067 /* decode response */
3068 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3069 if (rc || (pSMBr->ByteCount < 2))
3070 /* BB also check enough total bytes returned */
3071 /* If rc should we check for EOPNOSUPP and
3072 disable the srvino flag? or in caller? */
3073 rc = -EIO; /* bad smb */
3075 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3076 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3077 struct file_chattr_info *pfinfo;
3078 /* BB Do we need a cast or hash here ? */
3080 cFYI(1, ("Illegal size ret in GetExtAttr"));
3084 pfinfo = (struct file_chattr_info *)
3085 (data_offset + (char *) &pSMBr->hdr.Protocol);
3086 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3087 *pMask = le64_to_cpu(pfinfo->mask);
3091 cifs_buf_release(pSMB);
3093 goto GetExtAttrRetry;
3097 #endif /* CONFIG_POSIX */
3099 #ifdef CONFIG_CIFS_EXPERIMENTAL
3100 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3102 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3103 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3107 QUERY_SEC_DESC_REQ *pSMB;
3110 cFYI(1, ("GetCifsACL"));
3115 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3116 8 /* parm len */, tcon, (void **) &pSMB);
3120 pSMB->MaxParameterCount = cpu_to_le32(4);
3121 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3122 pSMB->MaxSetupCount = 0;
3123 pSMB->Fid = fid; /* file handle always le */
3124 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3126 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3127 pSMB->hdr.smb_buf_length += 11;
3128 iov[0].iov_base = (char *)pSMB;
3129 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3131 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3133 cifs_stats_inc(&tcon->num_acl_get);
3135 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3136 } else { /* decode response */
3140 struct smb_com_ntransact_rsp *pSMBr;
3143 /* validate_nttransact */
3144 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3145 &pdata, &parm_len, pbuflen);
3148 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3150 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3152 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3153 rc = -EIO; /* bad smb */
3158 /* BB check that data area is minimum length and as big as acl_len */
3160 acl_len = le32_to_cpu(*parm);
3161 if (acl_len != *pbuflen) {
3162 cERROR(1, ("acl length %d does not match %d",
3163 acl_len, *pbuflen));
3164 if (*pbuflen > acl_len)
3168 /* check if buffer is big enough for the acl
3169 header followed by the smallest SID */
3170 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3171 (*pbuflen >= 64 * 1024)) {
3172 cERROR(1, ("bad acl length %d", *pbuflen));
3176 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3177 if (*acl_inf == NULL) {
3181 memcpy(*acl_inf, pdata, *pbuflen);
3185 if (buf_type == CIFS_SMALL_BUFFER)
3186 cifs_small_buf_release(iov[0].iov_base);
3187 else if (buf_type == CIFS_LARGE_BUFFER)
3188 cifs_buf_release(iov[0].iov_base);
3189 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3194 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3195 struct cifs_ntsd *pntsd, __u32 acllen)
3197 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3199 int bytes_returned = 0;
3200 SET_SEC_DESC_REQ *pSMB = NULL;
3201 NTRANSACT_RSP *pSMBr = NULL;
3204 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3209 pSMB->MaxSetupCount = 0;
3213 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3214 data_count = acllen;
3215 data_offset = param_offset + param_count;
3216 byte_count = 3 /* pad */ + param_count;
3218 pSMB->DataCount = cpu_to_le32(data_count);
3219 pSMB->TotalDataCount = pSMB->DataCount;
3220 pSMB->MaxParameterCount = cpu_to_le32(4);
3221 pSMB->MaxDataCount = cpu_to_le32(16384);
3222 pSMB->ParameterCount = cpu_to_le32(param_count);
3223 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3224 pSMB->TotalParameterCount = pSMB->ParameterCount;
3225 pSMB->DataOffset = cpu_to_le32(data_offset);
3226 pSMB->SetupCount = 0;
3227 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3228 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3230 pSMB->Fid = fid; /* file handle always le */
3231 pSMB->Reserved2 = 0;
3232 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3234 if (pntsd && acllen) {
3235 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3238 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3241 pSMB->hdr.smb_buf_length += byte_count;
3243 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3244 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3246 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3248 cFYI(1, ("Set CIFS ACL returned %d", rc));
3249 cifs_buf_release(pSMB);
3252 goto setCifsAclRetry;
3257 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3259 /* Legacy Query Path Information call for lookup to old servers such
3261 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3262 const unsigned char *searchName,
3263 FILE_ALL_INFO *pFinfo,
3264 const struct nls_table *nls_codepage, int remap)
3266 QUERY_INFORMATION_REQ *pSMB;
3267 QUERY_INFORMATION_RSP *pSMBr;
3272 cFYI(1, ("In SMBQPath path %s", searchName));
3274 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3279 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3281 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3282 PATH_MAX, nls_codepage, remap);
3283 name_len++; /* trailing null */
3286 name_len = strnlen(searchName, PATH_MAX);
3287 name_len++; /* trailing null */
3288 strncpy(pSMB->FileName, searchName, name_len);
3290 pSMB->BufferFormat = 0x04;
3291 name_len++; /* account for buffer type byte */
3292 pSMB->hdr.smb_buf_length += (__u16) name_len;
3293 pSMB->ByteCount = cpu_to_le16(name_len);
3295 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3296 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3298 cFYI(1, ("Send error in QueryInfo = %d", rc));
3299 } else if (pFinfo) {
3301 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3303 /* decode response */
3304 /* BB FIXME - add time zone adjustment BB */
3305 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3308 /* decode time fields */
3309 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3310 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3311 pFinfo->LastAccessTime = 0;
3312 pFinfo->AllocationSize =
3313 cpu_to_le64(le32_to_cpu(pSMBr->size));
3314 pFinfo->EndOfFile = pFinfo->AllocationSize;
3315 pFinfo->Attributes =
3316 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3318 rc = -EIO; /* bad buffer passed in */
3320 cifs_buf_release(pSMB);
3332 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3333 const unsigned char *searchName,
3334 FILE_ALL_INFO *pFindData,
3335 int legacy /* old style infolevel */,
3336 const struct nls_table *nls_codepage, int remap)
3338 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3339 TRANSACTION2_QPI_REQ *pSMB = NULL;
3340 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3344 __u16 params, byte_count;
3346 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3348 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3353 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3355 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3356 PATH_MAX, nls_codepage, remap);
3357 name_len++; /* trailing null */
3359 } else { /* BB improve the check for buffer overruns BB */
3360 name_len = strnlen(searchName, PATH_MAX);
3361 name_len++; /* trailing null */
3362 strncpy(pSMB->FileName, searchName, name_len);
3365 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3366 pSMB->TotalDataCount = 0;
3367 pSMB->MaxParameterCount = cpu_to_le16(2);
3368 /* BB find exact max SMB PDU from sess structure BB */
3369 pSMB->MaxDataCount = cpu_to_le16(4000);
3370 pSMB->MaxSetupCount = 0;
3374 pSMB->Reserved2 = 0;
3375 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3376 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3377 pSMB->DataCount = 0;
3378 pSMB->DataOffset = 0;
3379 pSMB->SetupCount = 1;
3380 pSMB->Reserved3 = 0;
3381 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3382 byte_count = params + 1 /* pad */ ;
3383 pSMB->TotalParameterCount = cpu_to_le16(params);
3384 pSMB->ParameterCount = pSMB->TotalParameterCount;
3386 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3388 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3389 pSMB->Reserved4 = 0;
3390 pSMB->hdr.smb_buf_length += byte_count;
3391 pSMB->ByteCount = cpu_to_le16(byte_count);
3393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3396 cFYI(1, ("Send error in QPathInfo = %d", rc));
3397 } else { /* decode response */
3398 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3400 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3402 else if (!legacy && (pSMBr->ByteCount < 40))
3403 rc = -EIO; /* bad smb */
3404 else if (legacy && (pSMBr->ByteCount < 24))
3405 rc = -EIO; /* 24 or 26 expected but we do not read
3407 else if (pFindData) {
3409 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3411 /* On legacy responses we do not read the last field,
3412 EAsize, fortunately since it varies by subdialect and
3413 also note it differs on Set vs. Get, ie two bytes or 4
3414 bytes depending but we don't care here */
3416 size = sizeof(FILE_INFO_STANDARD);
3418 size = sizeof(FILE_ALL_INFO);
3419 memcpy((char *) pFindData,
3420 (char *) &pSMBr->hdr.Protocol +
3425 cifs_buf_release(pSMB);
3427 goto QPathInfoRetry;
3433 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3434 const unsigned char *searchName,
3435 FILE_UNIX_BASIC_INFO *pFindData,
3436 const struct nls_table *nls_codepage, int remap)
3438 /* SMB_QUERY_FILE_UNIX_BASIC */
3439 TRANSACTION2_QPI_REQ *pSMB = NULL;
3440 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3442 int bytes_returned = 0;
3444 __u16 params, byte_count;
3446 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3448 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3453 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3455 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3456 PATH_MAX, nls_codepage, remap);
3457 name_len++; /* trailing null */
3459 } else { /* BB improve the check for buffer overruns BB */
3460 name_len = strnlen(searchName, PATH_MAX);
3461 name_len++; /* trailing null */
3462 strncpy(pSMB->FileName, searchName, name_len);
3465 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3466 pSMB->TotalDataCount = 0;
3467 pSMB->MaxParameterCount = cpu_to_le16(2);
3468 /* BB find exact max SMB PDU from sess structure BB */
3469 pSMB->MaxDataCount = cpu_to_le16(4000);
3470 pSMB->MaxSetupCount = 0;
3474 pSMB->Reserved2 = 0;
3475 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3476 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3477 pSMB->DataCount = 0;
3478 pSMB->DataOffset = 0;
3479 pSMB->SetupCount = 1;
3480 pSMB->Reserved3 = 0;
3481 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3482 byte_count = params + 1 /* pad */ ;
3483 pSMB->TotalParameterCount = cpu_to_le16(params);
3484 pSMB->ParameterCount = pSMB->TotalParameterCount;
3485 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3486 pSMB->Reserved4 = 0;
3487 pSMB->hdr.smb_buf_length += byte_count;
3488 pSMB->ByteCount = cpu_to_le16(byte_count);
3490 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3491 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3493 cFYI(1, ("Send error in QPathInfo = %d", rc));
3494 } else { /* decode response */
3495 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3497 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3498 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3499 "Unix Extensions can be disabled on mount "
3500 "by specifying the nosfu mount option."));
3501 rc = -EIO; /* bad smb */
3503 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3504 memcpy((char *) pFindData,
3505 (char *) &pSMBr->hdr.Protocol +
3507 sizeof(FILE_UNIX_BASIC_INFO));
3510 cifs_buf_release(pSMB);
3512 goto UnixQPathInfoRetry;
3517 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3519 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3520 const char *searchName,
3521 const struct nls_table *nls_codepage,
3523 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3525 /* level 257 SMB_ */
3526 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3527 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3528 T2_FFIRST_RSP_PARMS *parms;
3530 int bytes_returned = 0;
3532 __u16 params, byte_count;
3534 cFYI(1, ("In FindFirst for %s", searchName));
3537 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3542 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3544 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3545 PATH_MAX, nls_codepage, remap);
3546 /* We can not add the asterik earlier in case
3547 it got remapped to 0xF03A as if it were part of the
3548 directory name instead of a wildcard */
3550 pSMB->FileName[name_len] = dirsep;
3551 pSMB->FileName[name_len+1] = 0;
3552 pSMB->FileName[name_len+2] = '*';
3553 pSMB->FileName[name_len+3] = 0;
3554 name_len += 4; /* now the trailing null */
3555 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3556 pSMB->FileName[name_len+1] = 0;
3558 } else { /* BB add check for overrun of SMB buf BB */
3559 name_len = strnlen(searchName, PATH_MAX);
3560 /* BB fix here and in unicode clause above ie
3561 if (name_len > buffersize-header)
3562 free buffer exit; BB */
3563 strncpy(pSMB->FileName, searchName, name_len);
3564 pSMB->FileName[name_len] = dirsep;
3565 pSMB->FileName[name_len+1] = '*';
3566 pSMB->FileName[name_len+2] = 0;
3570 params = 12 + name_len /* includes null */ ;
3571 pSMB->TotalDataCount = 0; /* no EAs */
3572 pSMB->MaxParameterCount = cpu_to_le16(10);
3573 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3574 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3575 pSMB->MaxSetupCount = 0;
3579 pSMB->Reserved2 = 0;
3580 byte_count = params + 1 /* pad */ ;
3581 pSMB->TotalParameterCount = cpu_to_le16(params);
3582 pSMB->ParameterCount = pSMB->TotalParameterCount;
3583 pSMB->ParameterOffset = cpu_to_le16(
3584 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3586 pSMB->DataCount = 0;
3587 pSMB->DataOffset = 0;
3588 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3589 pSMB->Reserved3 = 0;
3590 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3591 pSMB->SearchAttributes =
3592 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3594 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3595 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3596 CIFS_SEARCH_RETURN_RESUME);
3597 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3599 /* BB what should we set StorageType to? Does it matter? BB */
3600 pSMB->SearchStorageType = 0;
3601 pSMB->hdr.smb_buf_length += byte_count;
3602 pSMB->ByteCount = cpu_to_le16(byte_count);
3604 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3605 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3606 cifs_stats_inc(&tcon->num_ffirst);
3608 if (rc) {/* BB add logic to retry regular search if Unix search
3609 rejected unexpectedly by server */
3610 /* BB Add code to handle unsupported level rc */
3611 cFYI(1, ("Error in FindFirst = %d", rc));
3613 cifs_buf_release(pSMB);
3615 /* BB eventually could optimize out free and realloc of buf */
3618 goto findFirstRetry;
3619 } else { /* decode response */
3620 /* BB remember to free buffer if error BB */
3621 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3623 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3624 psrch_inf->unicode = true;
3626 psrch_inf->unicode = false;
3628 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3629 psrch_inf->smallBuf = 0;
3630 psrch_inf->srch_entries_start =
3631 (char *) &pSMBr->hdr.Protocol +
3632 le16_to_cpu(pSMBr->t2.DataOffset);
3633 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3634 le16_to_cpu(pSMBr->t2.ParameterOffset));
3636 if (parms->EndofSearch)
3637 psrch_inf->endOfSearch = true;
3639 psrch_inf->endOfSearch = false;
3641 psrch_inf->entries_in_buffer =
3642 le16_to_cpu(parms->SearchCount);
3643 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3644 psrch_inf->entries_in_buffer;
3645 *pnetfid = parms->SearchHandle;
3647 cifs_buf_release(pSMB);
3654 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3655 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3657 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3658 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3659 T2_FNEXT_RSP_PARMS *parms;
3660 char *response_data;
3662 int bytes_returned, name_len;
3663 __u16 params, byte_count;
3665 cFYI(1, ("In FindNext"));
3667 if (psrch_inf->endOfSearch)
3670 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3675 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3677 pSMB->TotalDataCount = 0; /* no EAs */
3678 pSMB->MaxParameterCount = cpu_to_le16(8);
3679 pSMB->MaxDataCount =
3680 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3682 pSMB->MaxSetupCount = 0;
3686 pSMB->Reserved2 = 0;
3687 pSMB->ParameterOffset = cpu_to_le16(
3688 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3689 pSMB->DataCount = 0;
3690 pSMB->DataOffset = 0;
3691 pSMB->SetupCount = 1;
3692 pSMB->Reserved3 = 0;
3693 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3694 pSMB->SearchHandle = searchHandle; /* always kept as le */
3696 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3697 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3698 pSMB->ResumeKey = psrch_inf->resume_key;
3700 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3702 name_len = psrch_inf->resume_name_len;
3704 if (name_len < PATH_MAX) {
3705 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3706 byte_count += name_len;
3707 /* 14 byte parm len above enough for 2 byte null terminator */
3708 pSMB->ResumeFileName[name_len] = 0;
3709 pSMB->ResumeFileName[name_len+1] = 0;
3712 goto FNext2_err_exit;
3714 byte_count = params + 1 /* pad */ ;
3715 pSMB->TotalParameterCount = cpu_to_le16(params);
3716 pSMB->ParameterCount = pSMB->TotalParameterCount;
3717 pSMB->hdr.smb_buf_length += byte_count;
3718 pSMB->ByteCount = cpu_to_le16(byte_count);
3720 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3721 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3722 cifs_stats_inc(&tcon->num_fnext);
3725 psrch_inf->endOfSearch = true;
3726 cifs_buf_release(pSMB);
3727 rc = 0; /* search probably was closed at end of search*/
3729 cFYI(1, ("FindNext returned = %d", rc));
3730 } else { /* decode response */
3731 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3734 /* BB fixme add lock for file (srch_info) struct here */
3735 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3736 psrch_inf->unicode = true;
3738 psrch_inf->unicode = false;
3739 response_data = (char *) &pSMBr->hdr.Protocol +
3740 le16_to_cpu(pSMBr->t2.ParameterOffset);
3741 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3742 response_data = (char *)&pSMBr->hdr.Protocol +
3743 le16_to_cpu(pSMBr->t2.DataOffset);
3744 if (psrch_inf->smallBuf)
3745 cifs_small_buf_release(
3746 psrch_inf->ntwrk_buf_start);
3748 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3749 psrch_inf->srch_entries_start = response_data;
3750 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3751 psrch_inf->smallBuf = 0;
3752 if (parms->EndofSearch)
3753 psrch_inf->endOfSearch = true;
3755 psrch_inf->endOfSearch = false;
3756 psrch_inf->entries_in_buffer =
3757 le16_to_cpu(parms->SearchCount);
3758 psrch_inf->index_of_last_entry +=
3759 psrch_inf->entries_in_buffer;
3760 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3761 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3763 /* BB fixme add unlock here */
3768 /* BB On error, should we leave previous search buf (and count and
3769 last entry fields) intact or free the previous one? */
3771 /* Note: On -EAGAIN error only caller can retry on handle based calls
3772 since file handle passed in no longer valid */
3775 cifs_buf_release(pSMB);
3780 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3781 const __u16 searchHandle)
3784 FINDCLOSE_REQ *pSMB = NULL;
3786 cFYI(1, ("In CIFSSMBFindClose"));
3787 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3789 /* no sense returning error if session restarted
3790 as file handle has been closed */
3796 pSMB->FileID = searchHandle;
3797 pSMB->ByteCount = 0;
3798 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3800 cERROR(1, ("Send error in FindClose = %d", rc));
3802 cifs_stats_inc(&tcon->num_fclose);
3804 /* Since session is dead, search handle closed on server already */
3812 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3813 const unsigned char *searchName,
3814 __u64 *inode_number,
3815 const struct nls_table *nls_codepage, int remap)
3818 TRANSACTION2_QPI_REQ *pSMB = NULL;
3819 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3820 int name_len, bytes_returned;
3821 __u16 params, byte_count;
3823 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3827 GetInodeNumberRetry:
3828 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3833 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3835 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3836 PATH_MAX, nls_codepage, remap);
3837 name_len++; /* trailing null */
3839 } else { /* BB improve the check for buffer overruns BB */
3840 name_len = strnlen(searchName, PATH_MAX);
3841 name_len++; /* trailing null */
3842 strncpy(pSMB->FileName, searchName, name_len);
3845 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3846 pSMB->TotalDataCount = 0;
3847 pSMB->MaxParameterCount = cpu_to_le16(2);
3848 /* BB find exact max data count below from sess structure BB */
3849 pSMB->MaxDataCount = cpu_to_le16(4000);
3850 pSMB->MaxSetupCount = 0;
3854 pSMB->Reserved2 = 0;
3855 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3856 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3857 pSMB->DataCount = 0;
3858 pSMB->DataOffset = 0;
3859 pSMB->SetupCount = 1;
3860 pSMB->Reserved3 = 0;
3861 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3862 byte_count = params + 1 /* pad */ ;
3863 pSMB->TotalParameterCount = cpu_to_le16(params);
3864 pSMB->ParameterCount = pSMB->TotalParameterCount;
3865 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3866 pSMB->Reserved4 = 0;
3867 pSMB->hdr.smb_buf_length += byte_count;
3868 pSMB->ByteCount = cpu_to_le16(byte_count);
3870 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3871 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3873 cFYI(1, ("error %d in QueryInternalInfo", rc));
3875 /* decode response */
3876 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3877 if (rc || (pSMBr->ByteCount < 2))
3878 /* BB also check enough total bytes returned */
3879 /* If rc should we check for EOPNOSUPP and
3880 disable the srvino flag? or in caller? */
3881 rc = -EIO; /* bad smb */
3883 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3884 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3885 struct file_internal_info *pfinfo;
3886 /* BB Do we need a cast or hash here ? */
3888 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3890 goto GetInodeNumOut;
3892 pfinfo = (struct file_internal_info *)
3893 (data_offset + (char *) &pSMBr->hdr.Protocol);
3894 *inode_number = pfinfo->UniqueId;
3898 cifs_buf_release(pSMB);
3900 goto GetInodeNumberRetry;
3904 /* parses DFS refferal V3 structure
3905 * caller is responsible for freeing target_nodes
3908 * on failure - errno
3911 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3912 unsigned int *num_of_nodes,
3913 struct dfs_info3_param **target_nodes,
3914 const struct nls_table *nls_codepage)
3919 struct dfs_referral_level_3 *ref;
3921 is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE;
3922 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3924 if (*num_of_nodes < 1) {
3925 cERROR(1, ("num_referrals: must be at least > 0,"
3926 "but we get num_referrals = %d\n", *num_of_nodes));
3928 goto parse_DFS_referrals_exit;
3931 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3932 if (ref->VersionNumber != 3) {
3933 cERROR(1, ("Referrals of V%d version are not supported,"
3934 "should be V3", ref->VersionNumber));
3936 goto parse_DFS_referrals_exit;
3939 /* get the upper boundary of the resp buffer */
3940 data_end = (char *)(&(pSMBr->PathConsumed)) +
3941 le16_to_cpu(pSMBr->t2.DataCount);
3943 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3945 le16_to_cpu(pSMBr->DFSFlags)));
3947 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3948 *num_of_nodes, GFP_KERNEL);
3949 if (*target_nodes == NULL) {
3950 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3952 goto parse_DFS_referrals_exit;
3955 /* collect neccessary data from referrals */
3956 for (i = 0; i < *num_of_nodes; i++) {
3959 struct dfs_info3_param *node = (*target_nodes)+i;
3961 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3962 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3963 node->server_type = le16_to_cpu(ref->ServerType);
3964 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3967 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3968 max_len = data_end - temp;
3969 rc = cifs_strncpy_to_host(&(node->path_name), temp,
3970 max_len, is_unicode, nls_codepage);
3972 goto parse_DFS_referrals_exit;
3974 /* copy link target UNC */
3975 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3976 max_len = data_end - temp;
3977 rc = cifs_strncpy_to_host(&(node->node_name), temp,
3978 max_len, is_unicode, nls_codepage);
3980 goto parse_DFS_referrals_exit;
3985 parse_DFS_referrals_exit:
3987 free_dfs_info_array(*target_nodes, *num_of_nodes);
3988 *target_nodes = NULL;
3995 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3996 const unsigned char *searchName,
3997 struct dfs_info3_param **target_nodes,
3998 unsigned int *num_of_nodes,
3999 const struct nls_table *nls_codepage, int remap)
4001 /* TRANS2_GET_DFS_REFERRAL */
4002 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4003 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4007 __u16 params, byte_count;
4009 *target_nodes = NULL;
4011 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4015 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4020 /* server pointer checked in called function,
4021 but should never be null here anyway */
4022 pSMB->hdr.Mid = GetNextMid(ses->server);
4023 pSMB->hdr.Tid = ses->ipc_tid;
4024 pSMB->hdr.Uid = ses->Suid;
4025 if (ses->capabilities & CAP_STATUS32)
4026 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4027 if (ses->capabilities & CAP_DFS)
4028 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4030 if (ses->capabilities & CAP_UNICODE) {
4031 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4033 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4034 searchName, PATH_MAX, nls_codepage, remap);
4035 name_len++; /* trailing null */
4037 } else { /* BB improve the check for buffer overruns BB */
4038 name_len = strnlen(searchName, PATH_MAX);
4039 name_len++; /* trailing null */
4040 strncpy(pSMB->RequestFileName, searchName, name_len);
4044 if (ses->server->secMode &
4045 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4046 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4049 pSMB->hdr.Uid = ses->Suid;
4051 params = 2 /* level */ + name_len /*includes null */ ;
4052 pSMB->TotalDataCount = 0;
4053 pSMB->DataCount = 0;
4054 pSMB->DataOffset = 0;
4055 pSMB->MaxParameterCount = 0;
4056 /* BB find exact max SMB PDU from sess structure BB */
4057 pSMB->MaxDataCount = cpu_to_le16(4000);
4058 pSMB->MaxSetupCount = 0;
4062 pSMB->Reserved2 = 0;
4063 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4064 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4065 pSMB->SetupCount = 1;
4066 pSMB->Reserved3 = 0;
4067 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4068 byte_count = params + 3 /* pad */ ;
4069 pSMB->ParameterCount = cpu_to_le16(params);
4070 pSMB->TotalParameterCount = pSMB->ParameterCount;
4071 pSMB->MaxReferralLevel = cpu_to_le16(3);
4072 pSMB->hdr.smb_buf_length += byte_count;
4073 pSMB->ByteCount = cpu_to_le16(byte_count);
4075 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4076 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4078 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4081 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4083 /* BB Also check if enough total bytes returned? */
4084 if (rc || (pSMBr->ByteCount < 17)) {
4085 rc = -EIO; /* bad smb */
4089 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4091 le16_to_cpu(pSMBr->t2.DataOffset)));
4093 /* parse returned result into more usable form */
4094 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4095 target_nodes, nls_codepage);
4099 cifs_buf_release(pSMB);
4107 /* Query File System Info such as free space to old servers such as Win 9x */
4109 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4111 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4112 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4113 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4114 FILE_SYSTEM_ALLOC_INFO *response_data;
4116 int bytes_returned = 0;
4117 __u16 params, byte_count;
4119 cFYI(1, ("OldQFSInfo"));
4121 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4126 params = 2; /* level */
4127 pSMB->TotalDataCount = 0;
4128 pSMB->MaxParameterCount = cpu_to_le16(2);
4129 pSMB->MaxDataCount = cpu_to_le16(1000);
4130 pSMB->MaxSetupCount = 0;
4134 pSMB->Reserved2 = 0;
4135 byte_count = params + 1 /* pad */ ;
4136 pSMB->TotalParameterCount = cpu_to_le16(params);
4137 pSMB->ParameterCount = pSMB->TotalParameterCount;
4138 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4139 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4140 pSMB->DataCount = 0;
4141 pSMB->DataOffset = 0;
4142 pSMB->SetupCount = 1;
4143 pSMB->Reserved3 = 0;
4144 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4145 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4146 pSMB->hdr.smb_buf_length += byte_count;
4147 pSMB->ByteCount = cpu_to_le16(byte_count);
4149 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4150 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4152 cFYI(1, ("Send error in QFSInfo = %d", rc));
4153 } else { /* decode response */
4154 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4156 if (rc || (pSMBr->ByteCount < 18))
4157 rc = -EIO; /* bad smb */
4159 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4160 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4161 pSMBr->ByteCount, data_offset));
4163 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4164 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4166 le16_to_cpu(response_data->BytesPerSector) *
4167 le32_to_cpu(response_data->
4168 SectorsPerAllocationUnit);
4170 le32_to_cpu(response_data->TotalAllocationUnits);
4171 FSData->f_bfree = FSData->f_bavail =
4172 le32_to_cpu(response_data->FreeAllocationUnits);
4174 ("Blocks: %lld Free: %lld Block size %ld",
4175 (unsigned long long)FSData->f_blocks,
4176 (unsigned long long)FSData->f_bfree,
4180 cifs_buf_release(pSMB);
4183 goto oldQFSInfoRetry;
4189 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4191 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4192 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4193 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4194 FILE_SYSTEM_INFO *response_data;
4196 int bytes_returned = 0;
4197 __u16 params, byte_count;
4199 cFYI(1, ("In QFSInfo"));
4201 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4206 params = 2; /* level */
4207 pSMB->TotalDataCount = 0;
4208 pSMB->MaxParameterCount = cpu_to_le16(2);
4209 pSMB->MaxDataCount = cpu_to_le16(1000);
4210 pSMB->MaxSetupCount = 0;
4214 pSMB->Reserved2 = 0;
4215 byte_count = params + 1 /* pad */ ;
4216 pSMB->TotalParameterCount = cpu_to_le16(params);
4217 pSMB->ParameterCount = pSMB->TotalParameterCount;
4218 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4219 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4220 pSMB->DataCount = 0;
4221 pSMB->DataOffset = 0;
4222 pSMB->SetupCount = 1;
4223 pSMB->Reserved3 = 0;
4224 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4225 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4226 pSMB->hdr.smb_buf_length += byte_count;
4227 pSMB->ByteCount = cpu_to_le16(byte_count);
4229 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4230 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4232 cFYI(1, ("Send error in QFSInfo = %d", rc));
4233 } else { /* decode response */
4234 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4236 if (rc || (pSMBr->ByteCount < 24))
4237 rc = -EIO; /* bad smb */
4239 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4243 *) (((char *) &pSMBr->hdr.Protocol) +
4246 le32_to_cpu(response_data->BytesPerSector) *
4247 le32_to_cpu(response_data->
4248 SectorsPerAllocationUnit);
4250 le64_to_cpu(response_data->TotalAllocationUnits);
4251 FSData->f_bfree = FSData->f_bavail =
4252 le64_to_cpu(response_data->FreeAllocationUnits);
4254 ("Blocks: %lld Free: %lld Block size %ld",
4255 (unsigned long long)FSData->f_blocks,
4256 (unsigned long long)FSData->f_bfree,
4260 cifs_buf_release(pSMB);
4269 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4271 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4272 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4273 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4274 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4276 int bytes_returned = 0;
4277 __u16 params, byte_count;
4279 cFYI(1, ("In QFSAttributeInfo"));
4281 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4286 params = 2; /* level */
4287 pSMB->TotalDataCount = 0;
4288 pSMB->MaxParameterCount = cpu_to_le16(2);
4289 /* BB find exact max SMB PDU from sess structure BB */
4290 pSMB->MaxDataCount = cpu_to_le16(1000);
4291 pSMB->MaxSetupCount = 0;
4295 pSMB->Reserved2 = 0;
4296 byte_count = params + 1 /* pad */ ;
4297 pSMB->TotalParameterCount = cpu_to_le16(params);
4298 pSMB->ParameterCount = pSMB->TotalParameterCount;
4299 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4300 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4301 pSMB->DataCount = 0;
4302 pSMB->DataOffset = 0;
4303 pSMB->SetupCount = 1;
4304 pSMB->Reserved3 = 0;
4305 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4306 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4307 pSMB->hdr.smb_buf_length += byte_count;
4308 pSMB->ByteCount = cpu_to_le16(byte_count);
4310 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4311 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4313 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4314 } else { /* decode response */
4315 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4317 if (rc || (pSMBr->ByteCount < 13)) {
4318 /* BB also check if enough bytes returned */
4319 rc = -EIO; /* bad smb */
4321 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4323 (FILE_SYSTEM_ATTRIBUTE_INFO
4324 *) (((char *) &pSMBr->hdr.Protocol) +
4326 memcpy(&tcon->fsAttrInfo, response_data,
4327 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4330 cifs_buf_release(pSMB);
4333 goto QFSAttributeRetry;
4339 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4341 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4342 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4343 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4344 FILE_SYSTEM_DEVICE_INFO *response_data;
4346 int bytes_returned = 0;
4347 __u16 params, byte_count;
4349 cFYI(1, ("In QFSDeviceInfo"));
4351 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4356 params = 2; /* level */
4357 pSMB->TotalDataCount = 0;
4358 pSMB->MaxParameterCount = cpu_to_le16(2);
4359 /* BB find exact max SMB PDU from sess structure BB */
4360 pSMB->MaxDataCount = cpu_to_le16(1000);
4361 pSMB->MaxSetupCount = 0;
4365 pSMB->Reserved2 = 0;
4366 byte_count = params + 1 /* pad */ ;
4367 pSMB->TotalParameterCount = cpu_to_le16(params);
4368 pSMB->ParameterCount = pSMB->TotalParameterCount;
4369 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4370 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4372 pSMB->DataCount = 0;
4373 pSMB->DataOffset = 0;
4374 pSMB->SetupCount = 1;
4375 pSMB->Reserved3 = 0;
4376 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4377 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4378 pSMB->hdr.smb_buf_length += byte_count;
4379 pSMB->ByteCount = cpu_to_le16(byte_count);
4381 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4382 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4384 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4385 } else { /* decode response */
4386 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4388 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4389 rc = -EIO; /* bad smb */
4391 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4393 (FILE_SYSTEM_DEVICE_INFO *)
4394 (((char *) &pSMBr->hdr.Protocol) +
4396 memcpy(&tcon->fsDevInfo, response_data,
4397 sizeof(FILE_SYSTEM_DEVICE_INFO));
4400 cifs_buf_release(pSMB);
4403 goto QFSDeviceRetry;
4409 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4411 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4412 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4413 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4414 FILE_SYSTEM_UNIX_INFO *response_data;
4416 int bytes_returned = 0;
4417 __u16 params, byte_count;
4419 cFYI(1, ("In QFSUnixInfo"));
4421 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4426 params = 2; /* level */
4427 pSMB->TotalDataCount = 0;
4428 pSMB->DataCount = 0;
4429 pSMB->DataOffset = 0;
4430 pSMB->MaxParameterCount = cpu_to_le16(2);
4431 /* BB find exact max SMB PDU from sess structure BB */
4432 pSMB->MaxDataCount = cpu_to_le16(100);
4433 pSMB->MaxSetupCount = 0;
4437 pSMB->Reserved2 = 0;
4438 byte_count = params + 1 /* pad */ ;
4439 pSMB->ParameterCount = cpu_to_le16(params);
4440 pSMB->TotalParameterCount = pSMB->ParameterCount;
4441 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4442 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4443 pSMB->SetupCount = 1;
4444 pSMB->Reserved3 = 0;
4445 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4446 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4447 pSMB->hdr.smb_buf_length += byte_count;
4448 pSMB->ByteCount = cpu_to_le16(byte_count);
4450 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4451 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4453 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4454 } else { /* decode response */
4455 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4457 if (rc || (pSMBr->ByteCount < 13)) {
4458 rc = -EIO; /* bad smb */
4460 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4462 (FILE_SYSTEM_UNIX_INFO
4463 *) (((char *) &pSMBr->hdr.Protocol) +
4465 memcpy(&tcon->fsUnixInfo, response_data,
4466 sizeof(FILE_SYSTEM_UNIX_INFO));
4469 cifs_buf_release(pSMB);
4479 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4481 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4482 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4483 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4485 int bytes_returned = 0;
4486 __u16 params, param_offset, offset, byte_count;
4488 cFYI(1, ("In SETFSUnixInfo"));
4490 /* BB switch to small buf init to save memory */
4491 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4496 params = 4; /* 2 bytes zero followed by info level. */
4497 pSMB->MaxSetupCount = 0;
4501 pSMB->Reserved2 = 0;
4502 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4504 offset = param_offset + params;
4506 pSMB->MaxParameterCount = cpu_to_le16(4);
4507 /* BB find exact max SMB PDU from sess structure BB */
4508 pSMB->MaxDataCount = cpu_to_le16(100);
4509 pSMB->SetupCount = 1;
4510 pSMB->Reserved3 = 0;
4511 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4512 byte_count = 1 /* pad */ + params + 12;
4514 pSMB->DataCount = cpu_to_le16(12);
4515 pSMB->ParameterCount = cpu_to_le16(params);
4516 pSMB->TotalDataCount = pSMB->DataCount;
4517 pSMB->TotalParameterCount = pSMB->ParameterCount;
4518 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4519 pSMB->DataOffset = cpu_to_le16(offset);
4523 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4526 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4527 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4528 pSMB->ClientUnixCap = cpu_to_le64(cap);
4530 pSMB->hdr.smb_buf_length += byte_count;
4531 pSMB->ByteCount = cpu_to_le16(byte_count);
4533 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4534 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4536 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4537 } else { /* decode response */
4538 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4540 rc = -EIO; /* bad smb */
4542 cifs_buf_release(pSMB);
4545 goto SETFSUnixRetry;
4553 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4554 struct kstatfs *FSData)
4556 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4557 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4558 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4559 FILE_SYSTEM_POSIX_INFO *response_data;
4561 int bytes_returned = 0;
4562 __u16 params, byte_count;
4564 cFYI(1, ("In QFSPosixInfo"));
4566 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4571 params = 2; /* level */
4572 pSMB->TotalDataCount = 0;
4573 pSMB->DataCount = 0;
4574 pSMB->DataOffset = 0;
4575 pSMB->MaxParameterCount = cpu_to_le16(2);
4576 /* BB find exact max SMB PDU from sess structure BB */
4577 pSMB->MaxDataCount = cpu_to_le16(100);
4578 pSMB->MaxSetupCount = 0;
4582 pSMB->Reserved2 = 0;
4583 byte_count = params + 1 /* pad */ ;
4584 pSMB->ParameterCount = cpu_to_le16(params);
4585 pSMB->TotalParameterCount = pSMB->ParameterCount;
4586 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4587 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4588 pSMB->SetupCount = 1;
4589 pSMB->Reserved3 = 0;
4590 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4591 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4592 pSMB->hdr.smb_buf_length += byte_count;
4593 pSMB->ByteCount = cpu_to_le16(byte_count);
4595 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4596 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4598 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4599 } else { /* decode response */
4600 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4602 if (rc || (pSMBr->ByteCount < 13)) {
4603 rc = -EIO; /* bad smb */
4605 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4607 (FILE_SYSTEM_POSIX_INFO
4608 *) (((char *) &pSMBr->hdr.Protocol) +
4611 le32_to_cpu(response_data->BlockSize);
4613 le64_to_cpu(response_data->TotalBlocks);
4615 le64_to_cpu(response_data->BlocksAvail);
4616 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4617 FSData->f_bavail = FSData->f_bfree;
4620 le64_to_cpu(response_data->UserBlocksAvail);
4622 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4624 le64_to_cpu(response_data->TotalFileNodes);
4625 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4627 le64_to_cpu(response_data->FreeFileNodes);
4630 cifs_buf_release(pSMB);
4639 /* We can not use write of zero bytes trick to
4640 set file size due to need for large file support. Also note that
4641 this SetPathInfo is preferred to SetFileInfo based method in next
4642 routine which is only needed to work around a sharing violation bug
4643 in Samba which this routine can run into */
4646 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4647 __u64 size, bool SetAllocation,
4648 const struct nls_table *nls_codepage, int remap)
4650 struct smb_com_transaction2_spi_req *pSMB = NULL;
4651 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4652 struct file_end_of_file_info *parm_data;
4655 int bytes_returned = 0;
4656 __u16 params, byte_count, data_count, param_offset, offset;
4658 cFYI(1, ("In SetEOF"));
4660 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4665 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4667 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4668 PATH_MAX, nls_codepage, remap);
4669 name_len++; /* trailing null */
4671 } else { /* BB improve the check for buffer overruns BB */
4672 name_len = strnlen(fileName, PATH_MAX);
4673 name_len++; /* trailing null */
4674 strncpy(pSMB->FileName, fileName, name_len);
4676 params = 6 + name_len;
4677 data_count = sizeof(struct file_end_of_file_info);
4678 pSMB->MaxParameterCount = cpu_to_le16(2);
4679 pSMB->MaxDataCount = cpu_to_le16(4100);
4680 pSMB->MaxSetupCount = 0;
4684 pSMB->Reserved2 = 0;
4685 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4686 InformationLevel) - 4;
4687 offset = param_offset + params;
4688 if (SetAllocation) {
4689 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4690 pSMB->InformationLevel =
4691 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4693 pSMB->InformationLevel =
4694 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4695 } else /* Set File Size */ {
4696 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4697 pSMB->InformationLevel =
4698 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4700 pSMB->InformationLevel =
4701 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4705 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4707 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4708 pSMB->DataOffset = cpu_to_le16(offset);
4709 pSMB->SetupCount = 1;
4710 pSMB->Reserved3 = 0;
4711 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4712 byte_count = 3 /* pad */ + params + data_count;
4713 pSMB->DataCount = cpu_to_le16(data_count);
4714 pSMB->TotalDataCount = pSMB->DataCount;
4715 pSMB->ParameterCount = cpu_to_le16(params);
4716 pSMB->TotalParameterCount = pSMB->ParameterCount;
4717 pSMB->Reserved4 = 0;
4718 pSMB->hdr.smb_buf_length += byte_count;
4719 parm_data->FileSize = cpu_to_le64(size);
4720 pSMB->ByteCount = cpu_to_le16(byte_count);
4721 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4722 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4724 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4726 cifs_buf_release(pSMB);
4735 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4736 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4738 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4740 struct file_end_of_file_info *parm_data;
4742 __u16 params, param_offset, offset, byte_count, count;
4744 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4746 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4751 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4752 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4755 pSMB->MaxSetupCount = 0;
4759 pSMB->Reserved2 = 0;
4760 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4761 offset = param_offset + params;
4763 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4765 count = sizeof(struct file_end_of_file_info);
4766 pSMB->MaxParameterCount = cpu_to_le16(2);
4767 /* BB find exact max SMB PDU from sess structure BB */
4768 pSMB->MaxDataCount = cpu_to_le16(1000);
4769 pSMB->SetupCount = 1;
4770 pSMB->Reserved3 = 0;
4771 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4772 byte_count = 3 /* pad */ + params + count;
4773 pSMB->DataCount = cpu_to_le16(count);
4774 pSMB->ParameterCount = cpu_to_le16(params);
4775 pSMB->TotalDataCount = pSMB->DataCount;
4776 pSMB->TotalParameterCount = pSMB->ParameterCount;
4777 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4779 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4781 pSMB->DataOffset = cpu_to_le16(offset);
4782 parm_data->FileSize = cpu_to_le64(size);
4784 if (SetAllocation) {
4785 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4786 pSMB->InformationLevel =
4787 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4789 pSMB->InformationLevel =
4790 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4791 } else /* Set File Size */ {
4792 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4793 pSMB->InformationLevel =
4794 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4796 pSMB->InformationLevel =
4797 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4799 pSMB->Reserved4 = 0;
4800 pSMB->hdr.smb_buf_length += byte_count;
4801 pSMB->ByteCount = cpu_to_le16(byte_count);
4802 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4805 ("Send error in SetFileInfo (SetFileSize) = %d",
4809 /* Note: On -EAGAIN error only caller can retry on handle based calls
4810 since file handle passed in no longer valid */
4815 /* Some legacy servers such as NT4 require that the file times be set on
4816 an open handle, rather than by pathname - this is awkward due to
4817 potential access conflicts on the open, but it is unavoidable for these
4818 old servers since the only other choice is to go from 100 nanosecond DCE
4819 time and resort to the original setpathinfo level which takes the ancient
4820 DOS time format with 2 second granularity */
4822 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4823 const FILE_BASIC_INFO *data, __u16 fid)
4825 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4828 __u16 params, param_offset, offset, byte_count, count;
4830 cFYI(1, ("Set Times (via SetFileInfo)"));
4831 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4836 /* At this point there is no need to override the current pid
4837 with the pid of the opener, but that could change if we someday
4838 use an existing handle (rather than opening one on the fly) */
4839 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4840 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4843 pSMB->MaxSetupCount = 0;
4847 pSMB->Reserved2 = 0;
4848 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4849 offset = param_offset + params;
4851 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4853 count = sizeof(FILE_BASIC_INFO);
4854 pSMB->MaxParameterCount = cpu_to_le16(2);
4855 /* BB find max SMB PDU from sess */
4856 pSMB->MaxDataCount = cpu_to_le16(1000);
4857 pSMB->SetupCount = 1;
4858 pSMB->Reserved3 = 0;
4859 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4860 byte_count = 3 /* pad */ + params + count;
4861 pSMB->DataCount = cpu_to_le16(count);
4862 pSMB->ParameterCount = cpu_to_le16(params);
4863 pSMB->TotalDataCount = pSMB->DataCount;
4864 pSMB->TotalParameterCount = pSMB->ParameterCount;
4865 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4866 pSMB->DataOffset = cpu_to_le16(offset);
4868 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4869 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4871 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4872 pSMB->Reserved4 = 0;
4873 pSMB->hdr.smb_buf_length += byte_count;
4874 pSMB->ByteCount = cpu_to_le16(byte_count);
4875 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4876 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4878 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4880 /* Note: On -EAGAIN error only caller can retry on handle based calls
4881 since file handle passed in no longer valid */
4888 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4889 const FILE_BASIC_INFO *data,
4890 const struct nls_table *nls_codepage, int remap)
4892 TRANSACTION2_SPI_REQ *pSMB = NULL;
4893 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4896 int bytes_returned = 0;
4898 __u16 params, param_offset, offset, byte_count, count;
4900 cFYI(1, ("In SetTimes"));
4903 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4908 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4910 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4911 PATH_MAX, nls_codepage, remap);
4912 name_len++; /* trailing null */
4914 } else { /* BB improve the check for buffer overruns BB */
4915 name_len = strnlen(fileName, PATH_MAX);
4916 name_len++; /* trailing null */
4917 strncpy(pSMB->FileName, fileName, name_len);
4920 params = 6 + name_len;
4921 count = sizeof(FILE_BASIC_INFO);
4922 pSMB->MaxParameterCount = cpu_to_le16(2);
4923 /* BB find max SMB PDU from sess structure BB */
4924 pSMB->MaxDataCount = cpu_to_le16(1000);
4925 pSMB->MaxSetupCount = 0;
4929 pSMB->Reserved2 = 0;
4930 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4931 InformationLevel) - 4;
4932 offset = param_offset + params;
4933 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4934 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4935 pSMB->DataOffset = cpu_to_le16(offset);
4936 pSMB->SetupCount = 1;
4937 pSMB->Reserved3 = 0;
4938 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4939 byte_count = 3 /* pad */ + params + count;
4941 pSMB->DataCount = cpu_to_le16(count);
4942 pSMB->ParameterCount = cpu_to_le16(params);
4943 pSMB->TotalDataCount = pSMB->DataCount;
4944 pSMB->TotalParameterCount = pSMB->ParameterCount;
4945 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4946 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4948 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4949 pSMB->Reserved4 = 0;
4950 pSMB->hdr.smb_buf_length += byte_count;
4951 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4952 pSMB->ByteCount = cpu_to_le16(byte_count);
4953 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4954 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4956 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4958 cifs_buf_release(pSMB);
4966 /* Can not be used to set time stamps yet (due to old DOS time format) */
4967 /* Can be used to set attributes */
4968 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4969 handling it anyway and NT4 was what we thought it would be needed for
4970 Do not delete it until we prove whether needed for Win9x though */
4972 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4973 __u16 dos_attrs, const struct nls_table *nls_codepage)
4975 SETATTR_REQ *pSMB = NULL;
4976 SETATTR_RSP *pSMBr = NULL;
4981 cFYI(1, ("In SetAttrLegacy"));
4984 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4989 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4991 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4992 PATH_MAX, nls_codepage);
4993 name_len++; /* trailing null */
4995 } else { /* BB improve the check for buffer overruns BB */
4996 name_len = strnlen(fileName, PATH_MAX);
4997 name_len++; /* trailing null */
4998 strncpy(pSMB->fileName, fileName, name_len);
5000 pSMB->attr = cpu_to_le16(dos_attrs);
5001 pSMB->BufferFormat = 0x04;
5002 pSMB->hdr.smb_buf_length += name_len + 1;
5003 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5004 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5005 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5007 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5009 cifs_buf_release(pSMB);
5012 goto SetAttrLgcyRetry;
5016 #endif /* temporarily unneeded SetAttr legacy function */
5019 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
5020 char *fileName, __u64 mode, __u64 uid, __u64 gid,
5021 dev_t device, const struct nls_table *nls_codepage,
5024 TRANSACTION2_SPI_REQ *pSMB = NULL;
5025 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5028 int bytes_returned = 0;
5029 FILE_UNIX_BASIC_INFO *data_offset;
5030 __u16 params, param_offset, offset, count, byte_count;
5032 cFYI(1, ("In SetUID/GID/Mode"));
5034 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5039 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5041 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5042 PATH_MAX, nls_codepage, remap);
5043 name_len++; /* trailing null */
5045 } else { /* BB improve the check for buffer overruns BB */
5046 name_len = strnlen(fileName, PATH_MAX);
5047 name_len++; /* trailing null */
5048 strncpy(pSMB->FileName, fileName, name_len);
5051 params = 6 + name_len;
5052 count = sizeof(FILE_UNIX_BASIC_INFO);
5053 pSMB->MaxParameterCount = cpu_to_le16(2);
5054 /* BB find max SMB PDU from sess structure BB */
5055 pSMB->MaxDataCount = cpu_to_le16(1000);
5056 pSMB->MaxSetupCount = 0;
5060 pSMB->Reserved2 = 0;
5061 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5062 InformationLevel) - 4;
5063 offset = param_offset + params;
5065 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5067 memset(data_offset, 0, count);
5068 pSMB->DataOffset = cpu_to_le16(offset);
5069 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5070 pSMB->SetupCount = 1;
5071 pSMB->Reserved3 = 0;
5072 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5073 byte_count = 3 /* pad */ + params + count;
5074 pSMB->ParameterCount = cpu_to_le16(params);
5075 pSMB->DataCount = cpu_to_le16(count);
5076 pSMB->TotalParameterCount = pSMB->ParameterCount;
5077 pSMB->TotalDataCount = pSMB->DataCount;
5078 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5079 pSMB->Reserved4 = 0;
5080 pSMB->hdr.smb_buf_length += byte_count;
5081 /* Samba server ignores set of file size to zero due to bugs in some
5082 older clients, but we should be precise - we use SetFileSize to
5083 set file size and do not want to truncate file size to zero
5084 accidently as happened on one Samba server beta by putting
5085 zero instead of -1 here */
5086 data_offset->EndOfFile = NO_CHANGE_64;
5087 data_offset->NumOfBytes = NO_CHANGE_64;
5088 data_offset->LastStatusChange = NO_CHANGE_64;
5089 data_offset->LastAccessTime = NO_CHANGE_64;
5090 data_offset->LastModificationTime = NO_CHANGE_64;
5091 data_offset->Uid = cpu_to_le64(uid);
5092 data_offset->Gid = cpu_to_le64(gid);
5093 /* better to leave device as zero when it is */
5094 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5095 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5096 data_offset->Permissions = cpu_to_le64(mode);
5099 data_offset->Type = cpu_to_le32(UNIX_FILE);
5100 else if (S_ISDIR(mode))
5101 data_offset->Type = cpu_to_le32(UNIX_DIR);
5102 else if (S_ISLNK(mode))
5103 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5104 else if (S_ISCHR(mode))
5105 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5106 else if (S_ISBLK(mode))
5107 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5108 else if (S_ISFIFO(mode))
5109 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5110 else if (S_ISSOCK(mode))
5111 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5114 pSMB->ByteCount = cpu_to_le16(byte_count);
5115 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5116 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5118 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5121 cifs_buf_release(pSMB);
5127 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5128 const int notify_subdirs, const __u16 netfid,
5129 __u32 filter, struct file *pfile, int multishot,
5130 const struct nls_table *nls_codepage)
5133 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5134 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5135 struct dir_notify_req *dnotify_req;
5138 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5139 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5144 pSMB->TotalParameterCount = 0 ;
5145 pSMB->TotalDataCount = 0;
5146 pSMB->MaxParameterCount = cpu_to_le32(2);
5147 /* BB find exact data count max from sess structure BB */
5148 pSMB->MaxDataCount = 0; /* same in little endian or be */
5149 /* BB VERIFY verify which is correct for above BB */
5150 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5151 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5153 pSMB->MaxSetupCount = 4;
5155 pSMB->ParameterOffset = 0;
5156 pSMB->DataCount = 0;
5157 pSMB->DataOffset = 0;
5158 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5159 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5160 pSMB->ParameterCount = pSMB->TotalParameterCount;
5162 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5163 pSMB->Reserved2 = 0;
5164 pSMB->CompletionFilter = cpu_to_le32(filter);
5165 pSMB->Fid = netfid; /* file handle always le */
5166 pSMB->ByteCount = 0;
5168 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5169 (struct smb_hdr *)pSMBr, &bytes_returned,
5172 cFYI(1, ("Error in Notify = %d", rc));
5174 /* Add file to outstanding requests */
5175 /* BB change to kmem cache alloc */
5176 dnotify_req = kmalloc(
5177 sizeof(struct dir_notify_req),
5180 dnotify_req->Pid = pSMB->hdr.Pid;
5181 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5182 dnotify_req->Mid = pSMB->hdr.Mid;
5183 dnotify_req->Tid = pSMB->hdr.Tid;
5184 dnotify_req->Uid = pSMB->hdr.Uid;
5185 dnotify_req->netfid = netfid;
5186 dnotify_req->pfile = pfile;
5187 dnotify_req->filter = filter;
5188 dnotify_req->multishot = multishot;
5189 spin_lock(&GlobalMid_Lock);
5190 list_add_tail(&dnotify_req->lhead,
5191 &GlobalDnotifyReqList);
5192 spin_unlock(&GlobalMid_Lock);
5196 cifs_buf_release(pSMB);
5199 #ifdef CONFIG_CIFS_XATTR
5201 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5202 const unsigned char *searchName,
5203 char *EAData, size_t buf_size,
5204 const struct nls_table *nls_codepage, int remap)
5206 /* BB assumes one setup word */
5207 TRANSACTION2_QPI_REQ *pSMB = NULL;
5208 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5212 struct fea *temp_fea;
5214 __u16 params, byte_count;
5216 cFYI(1, ("In Query All EAs path %s", searchName));
5218 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5223 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5225 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5226 PATH_MAX, nls_codepage, remap);
5227 name_len++; /* trailing null */
5229 } else { /* BB improve the check for buffer overruns BB */
5230 name_len = strnlen(searchName, PATH_MAX);
5231 name_len++; /* trailing null */
5232 strncpy(pSMB->FileName, searchName, name_len);
5235 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5236 pSMB->TotalDataCount = 0;
5237 pSMB->MaxParameterCount = cpu_to_le16(2);
5238 /* BB find exact max SMB PDU from sess structure BB */
5239 pSMB->MaxDataCount = cpu_to_le16(4000);
5240 pSMB->MaxSetupCount = 0;
5244 pSMB->Reserved2 = 0;
5245 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5246 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5247 pSMB->DataCount = 0;
5248 pSMB->DataOffset = 0;
5249 pSMB->SetupCount = 1;
5250 pSMB->Reserved3 = 0;
5251 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5252 byte_count = params + 1 /* pad */ ;
5253 pSMB->TotalParameterCount = cpu_to_le16(params);
5254 pSMB->ParameterCount = pSMB->TotalParameterCount;
5255 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5256 pSMB->Reserved4 = 0;
5257 pSMB->hdr.smb_buf_length += byte_count;
5258 pSMB->ByteCount = cpu_to_le16(byte_count);
5260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5261 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5263 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5264 } else { /* decode response */
5265 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5267 /* BB also check enough total bytes returned */
5268 /* BB we need to improve the validity checking
5269 of these trans2 responses */
5270 if (rc || (pSMBr->ByteCount < 4))
5271 rc = -EIO; /* bad smb */
5272 /* else if (pFindData){
5273 memcpy((char *) pFindData,
5274 (char *) &pSMBr->hdr.Protocol +
5277 /* check that length of list is not more than bcc */
5278 /* check that each entry does not go beyond length
5280 /* check that each element of each entry does not
5281 go beyond end of list */
5282 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5283 struct fealist *ea_response_data;
5285 /* validate_trans2_offsets() */
5286 /* BB check if start of smb + data_offset > &bcc+ bcc */
5287 ea_response_data = (struct fealist *)
5288 (((char *) &pSMBr->hdr.Protocol) +
5290 name_len = le32_to_cpu(ea_response_data->list_len);
5291 cFYI(1, ("ea length %d", name_len));
5292 if (name_len <= 8) {
5293 /* returned EA size zeroed at top of function */
5294 cFYI(1, ("empty EA list returned from server"));
5296 /* account for ea list len */
5298 temp_fea = ea_response_data->list;
5299 temp_ptr = (char *)temp_fea;
5300 while (name_len > 0) {
5304 rc += temp_fea->name_len;
5305 /* account for prefix user. and trailing null */
5307 if (rc < (int)buf_size) {
5308 memcpy(EAData, "user.", 5);
5310 memcpy(EAData, temp_ptr,
5311 temp_fea->name_len);
5312 EAData += temp_fea->name_len;
5313 /* null terminate name */
5315 EAData = EAData + 1;
5316 } else if (buf_size == 0) {
5317 /* skip copy - calc size only */
5319 /* stop before overrun buffer */
5323 name_len -= temp_fea->name_len;
5324 temp_ptr += temp_fea->name_len;
5325 /* account for trailing null */
5329 le16_to_cpu(temp_fea->value_len);
5330 name_len -= value_len;
5331 temp_ptr += value_len;
5332 /* BB check that temp_ptr is still
5335 /* no trailing null to account for
5337 /* go on to next EA */
5338 temp_fea = (struct fea *)temp_ptr;
5344 cifs_buf_release(pSMB);
5351 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5352 const unsigned char *searchName, const unsigned char *ea_name,
5353 unsigned char *ea_value, size_t buf_size,
5354 const struct nls_table *nls_codepage, int remap)
5356 TRANSACTION2_QPI_REQ *pSMB = NULL;
5357 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5361 struct fea *temp_fea;
5363 __u16 params, byte_count;
5365 cFYI(1, ("In Query EA path %s", searchName));
5367 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5372 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5374 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
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(searchName, PATH_MAX);
5380 name_len++; /* trailing null */
5381 strncpy(pSMB->FileName, searchName, name_len);
5384 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5385 pSMB->TotalDataCount = 0;
5386 pSMB->MaxParameterCount = cpu_to_le16(2);
5387 /* BB find exact max SMB PDU from sess structure BB */
5388 pSMB->MaxDataCount = cpu_to_le16(4000);
5389 pSMB->MaxSetupCount = 0;
5393 pSMB->Reserved2 = 0;
5394 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5395 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5396 pSMB->DataCount = 0;
5397 pSMB->DataOffset = 0;
5398 pSMB->SetupCount = 1;
5399 pSMB->Reserved3 = 0;
5400 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5401 byte_count = params + 1 /* pad */ ;
5402 pSMB->TotalParameterCount = cpu_to_le16(params);
5403 pSMB->ParameterCount = pSMB->TotalParameterCount;
5404 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5405 pSMB->Reserved4 = 0;
5406 pSMB->hdr.smb_buf_length += byte_count;
5407 pSMB->ByteCount = cpu_to_le16(byte_count);
5409 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5410 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5412 cFYI(1, ("Send error in Query EA = %d", rc));
5413 } else { /* decode response */
5414 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5416 /* BB also check enough total bytes returned */
5417 /* BB we need to improve the validity checking
5418 of these trans2 responses */
5419 if (rc || (pSMBr->ByteCount < 4))
5420 rc = -EIO; /* bad smb */
5421 /* else if (pFindData){
5422 memcpy((char *) pFindData,
5423 (char *) &pSMBr->hdr.Protocol +
5426 /* check that length of list is not more than bcc */
5427 /* check that each entry does not go beyond length
5429 /* check that each element of each entry does not
5430 go beyond end of list */
5431 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5432 struct fealist *ea_response_data;
5434 /* validate_trans2_offsets() */
5435 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5436 ea_response_data = (struct fealist *)
5437 (((char *) &pSMBr->hdr.Protocol) +
5439 name_len = le32_to_cpu(ea_response_data->list_len);
5440 cFYI(1, ("ea length %d", name_len));
5441 if (name_len <= 8) {
5442 /* returned EA size zeroed at top of function */
5443 cFYI(1, ("empty EA list returned from server"));
5445 /* account for ea list len */
5447 temp_fea = ea_response_data->list;
5448 temp_ptr = (char *)temp_fea;
5449 /* loop through checking if we have a matching
5450 name and then return the associated value */
5451 while (name_len > 0) {
5456 le16_to_cpu(temp_fea->value_len);
5457 /* BB validate that value_len falls within SMB,
5458 even though maximum for name_len is 255 */
5459 if (memcmp(temp_fea->name, ea_name,
5460 temp_fea->name_len) == 0) {
5463 /* account for prefix user. and trailing null */
5464 if (rc <= (int)buf_size) {
5466 temp_fea->name+temp_fea->name_len+1,
5468 /* ea values, unlike ea
5471 } else if (buf_size == 0) {
5472 /* skip copy - calc size only */
5474 /* stop before overrun buffer */
5479 name_len -= temp_fea->name_len;
5480 temp_ptr += temp_fea->name_len;
5481 /* account for trailing null */
5484 name_len -= value_len;
5485 temp_ptr += value_len;
5486 /* No trailing null to account for in
5487 value_len. Go on to next EA */
5488 temp_fea = (struct fea *)temp_ptr;
5494 cifs_buf_release(pSMB);
5502 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5503 const char *ea_name, const void *ea_value,
5504 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5507 struct smb_com_transaction2_spi_req *pSMB = NULL;
5508 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5509 struct fealist *parm_data;
5512 int bytes_returned = 0;
5513 __u16 params, param_offset, byte_count, offset, count;
5515 cFYI(1, ("In SetEA"));
5517 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5522 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5524 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5525 PATH_MAX, nls_codepage, remap);
5526 name_len++; /* trailing null */
5528 } else { /* BB improve the check for buffer overruns BB */
5529 name_len = strnlen(fileName, PATH_MAX);
5530 name_len++; /* trailing null */
5531 strncpy(pSMB->FileName, fileName, name_len);
5534 params = 6 + name_len;
5536 /* done calculating parms using name_len of file name,
5537 now use name_len to calculate length of ea name
5538 we are going to create in the inode xattrs */
5539 if (ea_name == NULL)
5542 name_len = strnlen(ea_name, 255);
5544 count = sizeof(*parm_data) + ea_value_len + name_len;
5545 pSMB->MaxParameterCount = cpu_to_le16(2);
5546 /* BB find max SMB PDU from sess */
5547 pSMB->MaxDataCount = cpu_to_le16(1000);
5548 pSMB->MaxSetupCount = 0;
5552 pSMB->Reserved2 = 0;
5553 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5554 InformationLevel) - 4;
5555 offset = param_offset + params;
5556 pSMB->InformationLevel =
5557 cpu_to_le16(SMB_SET_FILE_EA);
5560 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5562 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5563 pSMB->DataOffset = cpu_to_le16(offset);
5564 pSMB->SetupCount = 1;
5565 pSMB->Reserved3 = 0;
5566 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5567 byte_count = 3 /* pad */ + params + count;
5568 pSMB->DataCount = cpu_to_le16(count);
5569 parm_data->list_len = cpu_to_le32(count);
5570 parm_data->list[0].EA_flags = 0;
5571 /* we checked above that name len is less than 255 */
5572 parm_data->list[0].name_len = (__u8)name_len;
5573 /* EA names are always ASCII */
5575 strncpy(parm_data->list[0].name, ea_name, name_len);
5576 parm_data->list[0].name[name_len] = 0;
5577 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5578 /* caller ensures that ea_value_len is less than 64K but
5579 we need to ensure that it fits within the smb */
5581 /*BB add length check to see if it would fit in
5582 negotiated SMB buffer size BB */
5583 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5585 memcpy(parm_data->list[0].name+name_len+1,
5586 ea_value, ea_value_len);
5588 pSMB->TotalDataCount = pSMB->DataCount;
5589 pSMB->ParameterCount = cpu_to_le16(params);
5590 pSMB->TotalParameterCount = pSMB->ParameterCount;
5591 pSMB->Reserved4 = 0;
5592 pSMB->hdr.smb_buf_length += byte_count;
5593 pSMB->ByteCount = cpu_to_le16(byte_count);
5594 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5595 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5597 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5599 cifs_buf_release(pSMB);