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 */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head *tmp;
91 struct list_head *tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
98 open_file->invalidHandle = true;
100 write_unlock(&GlobalSMBSeslock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* Allocate and return pointer to an SMB request buffer, and set basic
106 SMB information in the SMB header. If the return code is zero, this
107 function must have filled in request_buf pointer */
109 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
114 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
115 check for tcp and smb session status done differently
116 for those three - in the calling routine */
118 if (tcon->tidStatus == CifsExiting) {
119 /* only tree disconnect, open, and write,
120 (and ulogoff which does not have tcon)
121 are allowed as we start force umount */
122 if ((smb_command != SMB_COM_WRITE_ANDX) &&
123 (smb_command != SMB_COM_OPEN_ANDX) &&
124 (smb_command != SMB_COM_TREE_DISCONNECT)) {
125 cFYI(1, ("can not send cmd %d while umounting",
130 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
131 (tcon->ses->server)) {
132 struct nls_table *nls_codepage;
133 /* Give Demultiplex thread up to 10 seconds to
134 reconnect, should be greater than cifs socket
135 timeout which is 7 seconds */
136 while (tcon->ses->server->tcpStatus ==
138 wait_event_interruptible_timeout(tcon->ses->server->response_q,
139 (tcon->ses->server->tcpStatus ==
141 if (tcon->ses->server->tcpStatus ==
143 /* on "soft" mounts we wait once */
145 (tcon->ses->status == CifsExiting)) {
146 cFYI(1, ("gave up waiting on "
147 "reconnect in smb_init"));
149 } /* else "hard" mount - keep retrying
150 until process is killed or server
151 comes back on-line */
152 } else /* TCP session is reestablished now */
156 nls_codepage = load_nls_default();
157 /* need to prevent multiple threads trying to
158 simultaneously reconnect the same SMB session */
159 down(&tcon->ses->sesSem);
160 if (tcon->ses->status == CifsNeedReconnect)
161 rc = cifs_setup_session(0, tcon->ses,
163 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
164 mark_open_files_invalid(tcon);
165 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
167 up(&tcon->ses->sesSem);
168 /* BB FIXME add code to check if wsize needs
169 update due to negotiated smb buffer size
172 atomic_inc(&tconInfoReconnectCount);
173 /* tell server Unix caps we support */
174 if (tcon->ses->capabilities & CAP_UNIX)
175 reset_cifs_unix_caps(
178 NULL /* we do not know sb */,
179 NULL /* no vol info */);
182 cFYI(1, ("reconnect tcon rc = %d", rc));
183 /* Removed call to reopen open files here.
184 It is safer (and faster) to reopen files
185 one at a time as needed in read and write */
187 /* Check if handle based operation so we
188 know whether we can continue or not without
189 returning to caller to reset file handle */
190 switch (smb_command) {
191 case SMB_COM_READ_ANDX:
192 case SMB_COM_WRITE_ANDX:
194 case SMB_COM_FIND_CLOSE2:
195 case SMB_COM_LOCKING_ANDX: {
196 unload_nls(nls_codepage);
201 up(&tcon->ses->sesSem);
203 unload_nls(nls_codepage);
212 *request_buf = cifs_small_buf_get();
213 if (*request_buf == NULL) {
214 /* BB should we add a retry in here if not a writepage? */
218 header_assemble((struct smb_hdr *) *request_buf, smb_command,
222 cifs_stats_inc(&tcon->num_smbs_sent);
228 small_smb_init_no_tc(const int smb_command, const int wct,
229 struct cifsSesInfo *ses, void **request_buf)
232 struct smb_hdr *buffer;
234 rc = small_smb_init(smb_command, wct, NULL, request_buf);
238 buffer = (struct smb_hdr *)*request_buf;
239 buffer->Mid = GetNextMid(ses->server);
240 if (ses->capabilities & CAP_UNICODE)
241 buffer->Flags2 |= SMBFLG2_UNICODE;
242 if (ses->capabilities & CAP_STATUS32)
243 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
245 /* uid, tid can stay at zero as set in header assemble */
247 /* BB add support for turning on the signing when
248 this function is used after 1st of session setup requests */
253 /* If the return code is zero, this function must fill in request_buf pointer */
255 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
256 void **request_buf /* returned */ ,
257 void **response_buf /* returned */ )
261 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
262 check for tcp and smb session status done differently
263 for those three - in the calling routine */
265 if (tcon->tidStatus == CifsExiting) {
266 /* only tree disconnect, open, and write,
267 (and ulogoff which does not have tcon)
268 are allowed as we start force umount */
269 if ((smb_command != SMB_COM_WRITE_ANDX) &&
270 (smb_command != SMB_COM_OPEN_ANDX) &&
271 (smb_command != SMB_COM_TREE_DISCONNECT)) {
272 cFYI(1, ("can not send cmd %d while umounting",
278 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
279 (tcon->ses->server)) {
280 struct nls_table *nls_codepage;
281 /* Give Demultiplex thread up to 10 seconds to
282 reconnect, should be greater than cifs socket
283 timeout which is 7 seconds */
284 while (tcon->ses->server->tcpStatus ==
286 wait_event_interruptible_timeout(tcon->ses->server->response_q,
287 (tcon->ses->server->tcpStatus ==
289 if (tcon->ses->server->tcpStatus ==
291 /* on "soft" mounts we wait once */
293 (tcon->ses->status == CifsExiting)) {
294 cFYI(1, ("gave up waiting on "
295 "reconnect in smb_init"));
297 } /* else "hard" mount - keep retrying
298 until process is killed or server
300 } else /* TCP session is reestablished now */
303 nls_codepage = load_nls_default();
304 /* need to prevent multiple threads trying to
305 simultaneously reconnect the same SMB session */
306 down(&tcon->ses->sesSem);
307 if (tcon->ses->status == CifsNeedReconnect)
308 rc = cifs_setup_session(0, tcon->ses,
310 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
311 mark_open_files_invalid(tcon);
312 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
314 up(&tcon->ses->sesSem);
315 /* BB FIXME add code to check if wsize needs
316 update due to negotiated smb buffer size
319 atomic_inc(&tconInfoReconnectCount);
320 /* tell server Unix caps we support */
321 if (tcon->ses->capabilities & CAP_UNIX)
322 reset_cifs_unix_caps(
325 NULL /* do not know sb */,
326 NULL /* no vol info */);
329 cFYI(1, ("reconnect tcon rc = %d", rc));
330 /* Removed call to reopen open files here.
331 It is safer (and faster) to reopen files
332 one at a time as needed in read and write */
334 /* Check if handle based operation so we
335 know whether we can continue or not without
336 returning to caller to reset file handle */
337 switch (smb_command) {
338 case SMB_COM_READ_ANDX:
339 case SMB_COM_WRITE_ANDX:
341 case SMB_COM_FIND_CLOSE2:
342 case SMB_COM_LOCKING_ANDX: {
343 unload_nls(nls_codepage);
348 up(&tcon->ses->sesSem);
350 unload_nls(nls_codepage);
359 *request_buf = cifs_buf_get();
360 if (*request_buf == NULL) {
361 /* BB should we add a retry in here if not a writepage? */
364 /* Although the original thought was we needed the response buf for */
365 /* potential retries of smb operations it turns out we can determine */
366 /* from the mid flags when the request buffer can be resent without */
367 /* having to use a second distinct buffer for the response */
369 *response_buf = *request_buf;
371 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
375 cifs_stats_inc(&tcon->num_smbs_sent);
380 static int validate_t2(struct smb_t2_rsp *pSMB)
386 /* check for plausible wct, bcc and t2 data and parm sizes */
387 /* check for parm and data offset going beyond end of smb */
388 if (pSMB->hdr.WordCount >= 10) {
389 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
390 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
391 /* check that bcc is at least as big as parms + data */
392 /* check that bcc is less than negotiated smb buffer */
393 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
394 if (total_size < 512) {
396 le16_to_cpu(pSMB->t2_rsp.DataCount);
397 /* BCC le converted in SendReceive */
398 pBCC = (pSMB->hdr.WordCount * 2) +
399 sizeof(struct smb_hdr) +
401 if ((total_size <= (*(u16 *)pBCC)) &&
403 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
409 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
410 sizeof(struct smb_t2_rsp) + 16);
414 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
417 NEGOTIATE_RSP *pSMBr;
421 struct TCP_Server_Info *server;
423 unsigned int secFlags;
427 server = ses->server;
432 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
433 (void **) &pSMB, (void **) &pSMBr);
437 /* if any of auth flags (ie not sign or seal) are overriden use them */
438 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
439 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
440 else /* if override flags set only sign/seal OR them with global auth */
441 secFlags = extended_security | ses->overrideSecFlg;
443 cFYI(1, ("secFlags 0x%x", secFlags));
445 pSMB->hdr.Mid = GetNextMid(server);
446 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
448 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
449 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
450 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
451 cFYI(1, ("Kerberos only mechanism, enable extended security"));
452 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
456 for (i = 0; i < CIFS_NUM_PROT; i++) {
457 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
458 count += strlen(protocols[i].name) + 1;
459 /* null at end of source and target buffers anyway */
461 pSMB->hdr.smb_buf_length += count;
462 pSMB->ByteCount = cpu_to_le16(count);
464 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
465 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
469 dialect = le16_to_cpu(pSMBr->DialectIndex);
470 cFYI(1, ("Dialect: %d", dialect));
471 /* Check wct = 1 error case */
472 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
473 /* core returns wct = 1, but we do not ask for core - otherwise
474 small wct just comes when dialect index is -1 indicating we
475 could not negotiate a common dialect */
478 #ifdef CONFIG_CIFS_WEAK_PW_HASH
479 } else if ((pSMBr->hdr.WordCount == 13)
480 && ((dialect == LANMAN_PROT)
481 || (dialect == LANMAN2_PROT))) {
483 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
485 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
486 (secFlags & CIFSSEC_MAY_PLNTXT))
487 server->secType = LANMAN;
489 cERROR(1, ("mount failed weak security disabled"
490 " in /proc/fs/cifs/SecurityFlags"));
494 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
495 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
496 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
497 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
498 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
499 /* even though we do not use raw we might as well set this
500 accurately, in case we ever find a need for it */
501 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
502 server->maxRw = 0xFF00;
503 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
505 server->maxRw = 0;/* we do not need to use raw anyway */
506 server->capabilities = CAP_MPX_MODE;
508 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
510 /* OS/2 often does not set timezone therefore
511 * we must use server time to calc time zone.
512 * Could deviate slightly from the right zone.
513 * Smallest defined timezone difference is 15 minutes
514 * (i.e. Nepal). Rounding up/down is done to match
517 int val, seconds, remain, result;
518 struct timespec ts, utc;
520 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
521 le16_to_cpu(rsp->SrvTime.Time));
522 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
523 (int)ts.tv_sec, (int)utc.tv_sec,
524 (int)(utc.tv_sec - ts.tv_sec)));
525 val = (int)(utc.tv_sec - ts.tv_sec);
527 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
528 remain = seconds % MIN_TZ_ADJ;
529 if (remain >= (MIN_TZ_ADJ / 2))
530 result += MIN_TZ_ADJ;
533 server->timeAdj = result;
535 server->timeAdj = (int)tmp;
536 server->timeAdj *= 60; /* also in seconds */
538 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
541 /* BB get server time for time conversions and add
542 code to use it and timezone since this is not UTC */
544 if (rsp->EncryptionKeyLength ==
545 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
546 memcpy(server->cryptKey, rsp->EncryptionKey,
547 CIFS_CRYPTO_KEY_SIZE);
548 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
549 rc = -EIO; /* need cryptkey unless plain text */
553 cFYI(1, ("LANMAN negotiated"));
554 /* we will not end up setting signing flags - as no signing
555 was in LANMAN and server did not return the flags on */
557 #else /* weak security disabled */
558 } else if (pSMBr->hdr.WordCount == 13) {
559 cERROR(1, ("mount failed, cifs module not built "
560 "with CIFS_WEAK_PW_HASH support"));
562 #endif /* WEAK_PW_HASH */
564 } else if (pSMBr->hdr.WordCount != 17) {
569 /* else wct == 17 NTLM */
570 server->secMode = pSMBr->SecurityMode;
571 if ((server->secMode & SECMODE_USER) == 0)
572 cFYI(1, ("share mode security"));
574 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
575 #ifdef CONFIG_CIFS_WEAK_PW_HASH
576 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
577 #endif /* CIFS_WEAK_PW_HASH */
578 cERROR(1, ("Server requests plain text password"
579 " but client support disabled"));
581 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
582 server->secType = NTLMv2;
583 else if (secFlags & CIFSSEC_MAY_NTLM)
584 server->secType = NTLM;
585 else if (secFlags & CIFSSEC_MAY_NTLMV2)
586 server->secType = NTLMv2;
587 else if (secFlags & CIFSSEC_MAY_KRB5)
588 server->secType = Kerberos;
589 else if (secFlags & CIFSSEC_MAY_LANMAN)
590 server->secType = LANMAN;
591 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
592 else if (secFlags & CIFSSEC_MAY_PLNTXT)
597 cERROR(1, ("Invalid security type"));
600 /* else ... any others ...? */
602 /* one byte, so no need to convert this or EncryptionKeyLen from
604 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
605 /* probably no need to store and check maxvcs */
606 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
607 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
608 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
609 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
610 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
611 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
612 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
613 server->timeAdj *= 60;
614 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
615 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
616 CIFS_CRYPTO_KEY_SIZE);
617 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
618 && (pSMBr->EncryptionKeyLength == 0)) {
619 /* decode security blob */
620 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
621 rc = -EIO; /* no crypt key only if plain text pwd */
625 /* BB might be helpful to save off the domain of server here */
627 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
628 (server->capabilities & CAP_EXTENDED_SECURITY)) {
629 count = pSMBr->ByteCount;
635 if (server->socketUseCount.counter > 1) {
636 if (memcmp(server->server_GUID,
637 pSMBr->u.extended_response.
639 cFYI(1, ("server UID changed"));
640 memcpy(server->server_GUID,
641 pSMBr->u.extended_response.GUID,
645 memcpy(server->server_GUID,
646 pSMBr->u.extended_response.GUID, 16);
649 server->secType = RawNTLMSSP;
651 rc = decode_negTokenInit(pSMBr->u.extended_response.
662 server->capabilities &= ~CAP_EXTENDED_SECURITY;
664 #ifdef CONFIG_CIFS_WEAK_PW_HASH
667 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
668 /* MUST_SIGN already includes the MAY_SIGN FLAG
669 so if this is zero it means that signing is disabled */
670 cFYI(1, ("Signing disabled"));
671 if (server->secMode & SECMODE_SIGN_REQUIRED) {
672 cERROR(1, ("Server requires "
673 "packet signing to be enabled in "
674 "/proc/fs/cifs/SecurityFlags."));
678 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
679 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
680 /* signing required */
681 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
682 if ((server->secMode &
683 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
685 ("signing required but server lacks support"));
688 server->secMode |= SECMODE_SIGN_REQUIRED;
690 /* signing optional ie CIFSSEC_MAY_SIGN */
691 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
693 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
697 cifs_buf_release(pSMB);
699 cFYI(1, ("negprot rc %d", rc));
704 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
706 struct smb_hdr *smb_buffer;
709 cFYI(1, ("In tree disconnect"));
711 * If last user of the connection and
712 * connection alive - disconnect it
713 * If this is the last connection on the server session disconnect it
714 * (and inside session disconnect we should check if tcp socket needs
715 * to be freed and kernel thread woken up).
718 down(&tcon->tconSem);
722 atomic_dec(&tcon->useCount);
723 if (atomic_read(&tcon->useCount) > 0) {
728 /* No need to return error on this operation if tid invalidated and
729 closed on server already e.g. due to tcp session crashing */
730 if (tcon->tidStatus == CifsNeedReconnect) {
735 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
739 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
740 (void **)&smb_buffer);
746 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
748 cFYI(1, ("Tree disconnect failed %d", rc));
752 /* No need to return error on this operation if tid invalidated and
753 closed on server already e.g. due to tcp session crashing */
761 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
763 LOGOFF_ANDX_REQ *pSMB;
766 cFYI(1, ("In SMBLogoff for session disconnect"));
772 atomic_dec(&ses->inUse);
773 if (atomic_read(&ses->inUse) > 0) {
777 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
784 pSMB->hdr.Mid = GetNextMid(ses->server);
786 if (ses->server->secMode &
787 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
788 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
791 pSMB->hdr.Uid = ses->Suid;
793 pSMB->AndXCommand = 0xFF;
794 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
796 atomic_dec(&ses->server->socketUseCount);
797 if (atomic_read(&ses->server->socketUseCount) == 0) {
798 spin_lock(&GlobalMid_Lock);
799 ses->server->tcpStatus = CifsExiting;
800 spin_unlock(&GlobalMid_Lock);
806 /* if session dead then we do not need to do ulogoff,
807 since server closed smb session, no sense reporting
815 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
816 __u16 type, const struct nls_table *nls_codepage, int remap)
818 TRANSACTION2_SPI_REQ *pSMB = NULL;
819 TRANSACTION2_SPI_RSP *pSMBr = NULL;
820 struct unlink_psx_rq *pRqD;
823 int bytes_returned = 0;
824 __u16 params, param_offset, offset, byte_count;
826 cFYI(1, ("In POSIX delete"));
828 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
833 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
835 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
836 PATH_MAX, nls_codepage, remap);
837 name_len++; /* trailing null */
839 } else { /* BB add path length overrun check */
840 name_len = strnlen(fileName, PATH_MAX);
841 name_len++; /* trailing null */
842 strncpy(pSMB->FileName, fileName, name_len);
845 params = 6 + name_len;
846 pSMB->MaxParameterCount = cpu_to_le16(2);
847 pSMB->MaxDataCount = 0; /* BB double check this with jra */
848 pSMB->MaxSetupCount = 0;
853 param_offset = offsetof(struct smb_com_transaction2_spi_req,
854 InformationLevel) - 4;
855 offset = param_offset + params;
857 /* Setup pointer to Request Data (inode type) */
858 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
859 pRqD->type = cpu_to_le16(type);
860 pSMB->ParameterOffset = cpu_to_le16(param_offset);
861 pSMB->DataOffset = cpu_to_le16(offset);
862 pSMB->SetupCount = 1;
864 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
865 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
867 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
868 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
869 pSMB->ParameterCount = cpu_to_le16(params);
870 pSMB->TotalParameterCount = pSMB->ParameterCount;
871 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
873 pSMB->hdr.smb_buf_length += byte_count;
874 pSMB->ByteCount = cpu_to_le16(byte_count);
875 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
876 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
878 cFYI(1, ("Posix delete returned %d", rc));
879 cifs_buf_release(pSMB);
881 cifs_stats_inc(&tcon->num_deletes);
890 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
891 const struct nls_table *nls_codepage, int remap)
893 DELETE_FILE_REQ *pSMB = NULL;
894 DELETE_FILE_RSP *pSMBr = NULL;
900 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
907 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
908 PATH_MAX, nls_codepage, remap);
909 name_len++; /* trailing null */
911 } else { /* BB improve check for buffer overruns BB */
912 name_len = strnlen(fileName, PATH_MAX);
913 name_len++; /* trailing null */
914 strncpy(pSMB->fileName, fileName, name_len);
916 pSMB->SearchAttributes =
917 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
918 pSMB->BufferFormat = 0x04;
919 pSMB->hdr.smb_buf_length += name_len + 1;
920 pSMB->ByteCount = cpu_to_le16(name_len + 1);
921 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
922 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
923 cifs_stats_inc(&tcon->num_deletes);
925 cFYI(1, ("Error in RMFile = %d", rc));
927 cifs_buf_release(pSMB);
935 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
936 const struct nls_table *nls_codepage, int remap)
938 DELETE_DIRECTORY_REQ *pSMB = NULL;
939 DELETE_DIRECTORY_RSP *pSMBr = NULL;
944 cFYI(1, ("In CIFSSMBRmDir"));
946 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
951 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
952 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
953 PATH_MAX, nls_codepage, remap);
954 name_len++; /* trailing null */
956 } else { /* BB improve check for buffer overruns BB */
957 name_len = strnlen(dirName, PATH_MAX);
958 name_len++; /* trailing null */
959 strncpy(pSMB->DirName, dirName, name_len);
962 pSMB->BufferFormat = 0x04;
963 pSMB->hdr.smb_buf_length += name_len + 1;
964 pSMB->ByteCount = cpu_to_le16(name_len + 1);
965 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
966 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
967 cifs_stats_inc(&tcon->num_rmdirs);
969 cFYI(1, ("Error in RMDir = %d", rc));
971 cifs_buf_release(pSMB);
978 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
979 const char *name, const struct nls_table *nls_codepage, int remap)
982 CREATE_DIRECTORY_REQ *pSMB = NULL;
983 CREATE_DIRECTORY_RSP *pSMBr = NULL;
987 cFYI(1, ("In CIFSSMBMkDir"));
989 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
994 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
995 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
996 PATH_MAX, nls_codepage, remap);
997 name_len++; /* trailing null */
999 } else { /* BB improve check for buffer overruns BB */
1000 name_len = strnlen(name, PATH_MAX);
1001 name_len++; /* trailing null */
1002 strncpy(pSMB->DirName, name, name_len);
1005 pSMB->BufferFormat = 0x04;
1006 pSMB->hdr.smb_buf_length += name_len + 1;
1007 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1008 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1009 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1010 cifs_stats_inc(&tcon->num_mkdirs);
1012 cFYI(1, ("Error in Mkdir = %d", rc));
1014 cifs_buf_release(pSMB);
1021 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1022 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1023 __u32 *pOplock, const char *name,
1024 const struct nls_table *nls_codepage, int remap)
1026 TRANSACTION2_SPI_REQ *pSMB = NULL;
1027 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1030 int bytes_returned = 0;
1031 __u16 params, param_offset, offset, byte_count, count;
1032 OPEN_PSX_REQ *pdata;
1033 OPEN_PSX_RSP *psx_rsp;
1035 cFYI(1, ("In POSIX Create"));
1037 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1042 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1044 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1045 PATH_MAX, nls_codepage, remap);
1046 name_len++; /* trailing null */
1048 } else { /* BB improve the check for buffer overruns BB */
1049 name_len = strnlen(name, PATH_MAX);
1050 name_len++; /* trailing null */
1051 strncpy(pSMB->FileName, name, name_len);
1054 params = 6 + name_len;
1055 count = sizeof(OPEN_PSX_REQ);
1056 pSMB->MaxParameterCount = cpu_to_le16(2);
1057 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1058 pSMB->MaxSetupCount = 0;
1062 pSMB->Reserved2 = 0;
1063 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1064 InformationLevel) - 4;
1065 offset = param_offset + params;
1066 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1067 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1068 pdata->Permissions = cpu_to_le64(mode);
1069 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1070 pdata->OpenFlags = cpu_to_le32(*pOplock);
1071 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1072 pSMB->DataOffset = cpu_to_le16(offset);
1073 pSMB->SetupCount = 1;
1074 pSMB->Reserved3 = 0;
1075 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1076 byte_count = 3 /* pad */ + params + count;
1078 pSMB->DataCount = cpu_to_le16(count);
1079 pSMB->ParameterCount = cpu_to_le16(params);
1080 pSMB->TotalDataCount = pSMB->DataCount;
1081 pSMB->TotalParameterCount = pSMB->ParameterCount;
1082 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1083 pSMB->Reserved4 = 0;
1084 pSMB->hdr.smb_buf_length += byte_count;
1085 pSMB->ByteCount = cpu_to_le16(byte_count);
1086 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1089 cFYI(1, ("Posix create returned %d", rc));
1090 goto psx_create_err;
1093 cFYI(1, ("copying inode info"));
1094 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1096 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1097 rc = -EIO; /* bad smb */
1098 goto psx_create_err;
1101 /* copy return information to pRetData */
1102 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1103 + le16_to_cpu(pSMBr->t2.DataOffset));
1105 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1107 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1108 /* Let caller know file was created so we can set the mode. */
1109 /* Do we care about the CreateAction in any other cases? */
1110 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1111 *pOplock |= CIFS_CREATE_ACTION;
1112 /* check to make sure response data is there */
1113 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1114 pRetData->Type = cpu_to_le32(-1); /* unknown */
1115 cFYI(DBG2, ("unknown type"));
1117 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1118 + sizeof(FILE_UNIX_BASIC_INFO)) {
1119 cERROR(1, ("Open response data too small"));
1120 pRetData->Type = cpu_to_le32(-1);
1121 goto psx_create_err;
1123 memcpy((char *) pRetData,
1124 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1125 sizeof(FILE_UNIX_BASIC_INFO));
1129 cifs_buf_release(pSMB);
1131 cifs_stats_inc(&tcon->num_mkdirs);
1139 static __u16 convert_disposition(int disposition)
1143 switch (disposition) {
1144 case FILE_SUPERSEDE:
1145 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1148 ofun = SMBOPEN_OAPPEND;
1151 ofun = SMBOPEN_OCREATE;
1154 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1156 case FILE_OVERWRITE:
1157 ofun = SMBOPEN_OTRUNC;
1159 case FILE_OVERWRITE_IF:
1160 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1163 cFYI(1, ("unknown disposition %d", disposition));
1164 ofun = SMBOPEN_OAPPEND; /* regular open */
1170 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1171 const char *fileName, const int openDisposition,
1172 const int access_flags, const int create_options, __u16 *netfid,
1173 int *pOplock, FILE_ALL_INFO *pfile_info,
1174 const struct nls_table *nls_codepage, int remap)
1177 OPENX_REQ *pSMB = NULL;
1178 OPENX_RSP *pSMBr = NULL;
1184 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1189 pSMB->AndXCommand = 0xFF; /* none */
1191 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1192 count = 1; /* account for one byte pad to word boundary */
1194 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1195 fileName, PATH_MAX, nls_codepage, remap);
1196 name_len++; /* trailing null */
1198 } else { /* BB improve check for buffer overruns BB */
1199 count = 0; /* no pad */
1200 name_len = strnlen(fileName, PATH_MAX);
1201 name_len++; /* trailing null */
1202 strncpy(pSMB->fileName, fileName, name_len);
1204 if (*pOplock & REQ_OPLOCK)
1205 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1206 else if (*pOplock & REQ_BATCHOPLOCK)
1207 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1209 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1210 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1216 pSMB->Mode = cpu_to_le16(2);
1217 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1218 /* set file as system file if special file such
1219 as fifo and server expecting SFU style and
1220 no Unix extensions */
1222 if (create_options & CREATE_OPTION_SPECIAL)
1223 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1224 else /* BB FIXME BB */
1225 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1227 if (create_options & CREATE_OPTION_READONLY)
1228 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1231 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1232 CREATE_OPTIONS_MASK); */
1233 /* BB FIXME END BB */
1235 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1236 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1238 pSMB->hdr.smb_buf_length += count;
1240 pSMB->ByteCount = cpu_to_le16(count);
1241 /* long_op set to 1 to allow for oplock break timeouts */
1242 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1243 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1244 cifs_stats_inc(&tcon->num_opens);
1246 cFYI(1, ("Error in Open = %d", rc));
1248 /* BB verify if wct == 15 */
1250 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1252 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1253 /* Let caller know file was created so we can set the mode. */
1254 /* Do we care about the CreateAction in any other cases? */
1256 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1257 *pOplock |= CIFS_CREATE_ACTION; */
1261 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1262 pfile_info->LastAccessTime = 0; /* BB fixme */
1263 pfile_info->LastWriteTime = 0; /* BB fixme */
1264 pfile_info->ChangeTime = 0; /* BB fixme */
1265 pfile_info->Attributes =
1266 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1267 /* the file_info buf is endian converted by caller */
1268 pfile_info->AllocationSize =
1269 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1270 pfile_info->EndOfFile = pfile_info->AllocationSize;
1271 pfile_info->NumberOfLinks = cpu_to_le32(1);
1275 cifs_buf_release(pSMB);
1282 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1283 const char *fileName, const int openDisposition,
1284 const int access_flags, const int create_options, __u16 *netfid,
1285 int *pOplock, FILE_ALL_INFO *pfile_info,
1286 const struct nls_table *nls_codepage, int remap)
1289 OPEN_REQ *pSMB = NULL;
1290 OPEN_RSP *pSMBr = NULL;
1296 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1301 pSMB->AndXCommand = 0xFF; /* none */
1303 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1304 count = 1; /* account for one byte pad to word boundary */
1306 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1307 fileName, PATH_MAX, nls_codepage, remap);
1308 name_len++; /* trailing null */
1310 pSMB->NameLength = cpu_to_le16(name_len);
1311 } else { /* BB improve check for buffer overruns BB */
1312 count = 0; /* no pad */
1313 name_len = strnlen(fileName, PATH_MAX);
1314 name_len++; /* trailing null */
1315 pSMB->NameLength = cpu_to_le16(name_len);
1316 strncpy(pSMB->fileName, fileName, name_len);
1318 if (*pOplock & REQ_OPLOCK)
1319 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1320 else if (*pOplock & REQ_BATCHOPLOCK)
1321 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1322 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1323 pSMB->AllocationSize = 0;
1324 /* set file as system file if special file such
1325 as fifo and server expecting SFU style and
1326 no Unix extensions */
1327 if (create_options & CREATE_OPTION_SPECIAL)
1328 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1330 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1332 /* XP does not handle ATTR_POSIX_SEMANTICS */
1333 /* but it helps speed up case sensitive checks for other
1334 servers such as Samba */
1335 if (tcon->ses->capabilities & CAP_UNIX)
1336 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1338 if (create_options & CREATE_OPTION_READONLY)
1339 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1341 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1342 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1343 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1344 /* BB Expirement with various impersonation levels and verify */
1345 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1346 pSMB->SecurityFlags =
1347 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1350 pSMB->hdr.smb_buf_length += count;
1352 pSMB->ByteCount = cpu_to_le16(count);
1353 /* long_op set to 1 to allow for oplock break timeouts */
1354 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1355 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1356 cifs_stats_inc(&tcon->num_opens);
1358 cFYI(1, ("Error in Open = %d", rc));
1360 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1361 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1362 /* Let caller know file was created so we can set the mode. */
1363 /* Do we care about the CreateAction in any other cases? */
1364 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1365 *pOplock |= CIFS_CREATE_ACTION;
1367 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1368 36 /* CreationTime to Attributes */);
1369 /* the file_info buf is endian converted by caller */
1370 pfile_info->AllocationSize = pSMBr->AllocationSize;
1371 pfile_info->EndOfFile = pSMBr->EndOfFile;
1372 pfile_info->NumberOfLinks = cpu_to_le32(1);
1376 cifs_buf_release(pSMB);
1383 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1384 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1385 char **buf, int *pbuf_type)
1388 READ_REQ *pSMB = NULL;
1389 READ_RSP *pSMBr = NULL;
1390 char *pReadData = NULL;
1392 int resp_buf_type = 0;
1395 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1396 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1399 wct = 10; /* old style read */
1402 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1406 /* tcon and ses pointer are checked in smb_init */
1407 if (tcon->ses->server == NULL)
1408 return -ECONNABORTED;
1410 pSMB->AndXCommand = 0xFF; /* none */
1412 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1414 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1415 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1418 pSMB->Remaining = 0;
1419 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1420 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1422 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1424 /* old style read */
1425 struct smb_com_readx_req *pSMBW =
1426 (struct smb_com_readx_req *)pSMB;
1427 pSMBW->ByteCount = 0;
1430 iov[0].iov_base = (char *)pSMB;
1431 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1432 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1433 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1434 cifs_stats_inc(&tcon->num_reads);
1435 pSMBr = (READ_RSP *)iov[0].iov_base;
1437 cERROR(1, ("Send error in read = %d", rc));
1439 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1440 data_length = data_length << 16;
1441 data_length += le16_to_cpu(pSMBr->DataLength);
1442 *nbytes = data_length;
1444 /*check that DataLength would not go beyond end of SMB */
1445 if ((data_length > CIFSMaxBufSize)
1446 || (data_length > count)) {
1447 cFYI(1, ("bad length %d for count %d",
1448 data_length, count));
1452 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1453 le16_to_cpu(pSMBr->DataOffset);
1454 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1455 cERROR(1,("Faulting on read rc = %d",rc));
1457 }*/ /* can not use copy_to_user when using page cache*/
1459 memcpy(*buf, pReadData, data_length);
1463 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1465 if (resp_buf_type == CIFS_SMALL_BUFFER)
1466 cifs_small_buf_release(iov[0].iov_base);
1467 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1468 cifs_buf_release(iov[0].iov_base);
1469 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1470 /* return buffer to caller to free */
1471 *buf = iov[0].iov_base;
1472 if (resp_buf_type == CIFS_SMALL_BUFFER)
1473 *pbuf_type = CIFS_SMALL_BUFFER;
1474 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1475 *pbuf_type = CIFS_LARGE_BUFFER;
1476 } /* else no valid buffer on return - leave as null */
1478 /* Note: On -EAGAIN error only caller can retry on handle based calls
1479 since file handle passed in no longer valid */
1485 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1486 const int netfid, const unsigned int count,
1487 const __u64 offset, unsigned int *nbytes, const char *buf,
1488 const char __user *ubuf, const int long_op)
1491 WRITE_REQ *pSMB = NULL;
1492 WRITE_RSP *pSMBr = NULL;
1493 int bytes_returned, wct;
1497 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1498 if (tcon->ses == NULL)
1499 return -ECONNABORTED;
1501 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1506 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1510 /* tcon and ses pointer are checked in smb_init */
1511 if (tcon->ses->server == NULL)
1512 return -ECONNABORTED;
1514 pSMB->AndXCommand = 0xFF; /* none */
1516 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1518 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1519 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1522 pSMB->Reserved = 0xFFFFFFFF;
1523 pSMB->WriteMode = 0;
1524 pSMB->Remaining = 0;
1526 /* Can increase buffer size if buffer is big enough in some cases ie we
1527 can send more if LARGE_WRITE_X capability returned by the server and if
1528 our buffer is big enough or if we convert to iovecs on socket writes
1529 and eliminate the copy to the CIFS buffer */
1530 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1531 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1533 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1537 if (bytes_sent > count)
1540 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1542 memcpy(pSMB->Data, buf, bytes_sent);
1544 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1545 cifs_buf_release(pSMB);
1548 } else if (count != 0) {
1550 cifs_buf_release(pSMB);
1552 } /* else setting file size with write of zero bytes */
1554 byte_count = bytes_sent + 1; /* pad */
1555 else /* wct == 12 */
1556 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1558 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1559 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1560 pSMB->hdr.smb_buf_length += byte_count;
1563 pSMB->ByteCount = cpu_to_le16(byte_count);
1564 else { /* old style write has byte count 4 bytes earlier
1566 struct smb_com_writex_req *pSMBW =
1567 (struct smb_com_writex_req *)pSMB;
1568 pSMBW->ByteCount = cpu_to_le16(byte_count);
1571 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1572 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1573 cifs_stats_inc(&tcon->num_writes);
1575 cFYI(1, ("Send error in write = %d", rc));
1578 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1579 *nbytes = (*nbytes) << 16;
1580 *nbytes += le16_to_cpu(pSMBr->Count);
1583 cifs_buf_release(pSMB);
1585 /* Note: On -EAGAIN error only caller can retry on handle based calls
1586 since file handle passed in no longer valid */
1592 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1593 const int netfid, const unsigned int count,
1594 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1595 int n_vec, const int long_op)
1598 WRITE_REQ *pSMB = NULL;
1601 int resp_buf_type = 0;
1603 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1605 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1609 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1612 /* tcon and ses pointer are checked in smb_init */
1613 if (tcon->ses->server == NULL)
1614 return -ECONNABORTED;
1616 pSMB->AndXCommand = 0xFF; /* none */
1618 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1620 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1621 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1623 pSMB->Reserved = 0xFFFFFFFF;
1624 pSMB->WriteMode = 0;
1625 pSMB->Remaining = 0;
1628 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1630 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1631 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1632 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1634 pSMB->hdr.smb_buf_length += count+1;
1635 else /* wct == 12 */
1636 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1638 pSMB->ByteCount = cpu_to_le16(count + 1);
1639 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1640 struct smb_com_writex_req *pSMBW =
1641 (struct smb_com_writex_req *)pSMB;
1642 pSMBW->ByteCount = cpu_to_le16(count + 5);
1644 iov[0].iov_base = pSMB;
1646 iov[0].iov_len = smb_hdr_len + 4;
1647 else /* wct == 12 pad bigger by four bytes */
1648 iov[0].iov_len = smb_hdr_len + 8;
1651 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1653 cifs_stats_inc(&tcon->num_writes);
1655 cFYI(1, ("Send error Write2 = %d", rc));
1657 } else if (resp_buf_type == 0) {
1658 /* presumably this can not happen, but best to be safe */
1662 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1663 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1664 *nbytes = (*nbytes) << 16;
1665 *nbytes += le16_to_cpu(pSMBr->Count);
1668 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1669 if (resp_buf_type == CIFS_SMALL_BUFFER)
1670 cifs_small_buf_release(iov[0].iov_base);
1671 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1672 cifs_buf_release(iov[0].iov_base);
1674 /* Note: On -EAGAIN error only caller can retry on handle based calls
1675 since file handle passed in no longer valid */
1682 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1683 const __u16 smb_file_id, const __u64 len,
1684 const __u64 offset, const __u32 numUnlock,
1685 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1688 LOCK_REQ *pSMB = NULL;
1689 LOCK_RSP *pSMBr = NULL;
1694 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1695 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1700 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1702 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1703 timeout = CIFS_ASYNC_OP; /* no response expected */
1705 } else if (waitFlag) {
1706 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1707 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1712 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1713 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1714 pSMB->LockType = lockType;
1715 pSMB->AndXCommand = 0xFF; /* none */
1716 pSMB->Fid = smb_file_id; /* netfid stays le */
1718 if ((numLock != 0) || (numUnlock != 0)) {
1719 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1720 /* BB where to store pid high? */
1721 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1722 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1723 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1724 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1725 count = sizeof(LOCKING_ANDX_RANGE);
1730 pSMB->hdr.smb_buf_length += count;
1731 pSMB->ByteCount = cpu_to_le16(count);
1734 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1735 (struct smb_hdr *) pSMBr, &bytes_returned);
1736 cifs_small_buf_release(pSMB);
1738 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1740 /* SMB buffer freed by function above */
1742 cifs_stats_inc(&tcon->num_locks);
1744 cFYI(1, ("Send error in Lock = %d", rc));
1746 /* Note: On -EAGAIN error only caller can retry on handle based calls
1747 since file handle passed in no longer valid */
1752 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1753 const __u16 smb_file_id, const int get_flag, const __u64 len,
1754 struct file_lock *pLockData, const __u16 lock_type,
1755 const bool waitFlag)
1757 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1758 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1759 struct cifs_posix_lock *parm_data;
1762 int bytes_returned = 0;
1763 int resp_buf_type = 0;
1764 __u16 params, param_offset, offset, byte_count, count;
1767 cFYI(1, ("Posix Lock"));
1769 if (pLockData == NULL)
1772 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1777 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1780 pSMB->MaxSetupCount = 0;
1783 pSMB->Reserved2 = 0;
1784 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1785 offset = param_offset + params;
1787 count = sizeof(struct cifs_posix_lock);
1788 pSMB->MaxParameterCount = cpu_to_le16(2);
1789 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1790 pSMB->SetupCount = 1;
1791 pSMB->Reserved3 = 0;
1793 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1795 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1796 byte_count = 3 /* pad */ + params + count;
1797 pSMB->DataCount = cpu_to_le16(count);
1798 pSMB->ParameterCount = cpu_to_le16(params);
1799 pSMB->TotalDataCount = pSMB->DataCount;
1800 pSMB->TotalParameterCount = pSMB->ParameterCount;
1801 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1802 parm_data = (struct cifs_posix_lock *)
1803 (((char *) &pSMB->hdr.Protocol) + offset);
1805 parm_data->lock_type = cpu_to_le16(lock_type);
1807 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1808 parm_data->lock_flags = cpu_to_le16(1);
1809 pSMB->Timeout = cpu_to_le32(-1);
1813 parm_data->pid = cpu_to_le32(current->tgid);
1814 parm_data->start = cpu_to_le64(pLockData->fl_start);
1815 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1817 pSMB->DataOffset = cpu_to_le16(offset);
1818 pSMB->Fid = smb_file_id;
1819 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1820 pSMB->Reserved4 = 0;
1821 pSMB->hdr.smb_buf_length += byte_count;
1822 pSMB->ByteCount = cpu_to_le16(byte_count);
1824 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1825 (struct smb_hdr *) pSMBr, &bytes_returned);
1827 iov[0].iov_base = (char *)pSMB;
1828 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1829 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1830 &resp_buf_type, timeout);
1831 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1832 not try to free it twice below on exit */
1833 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1837 cFYI(1, ("Send error in Posix Lock = %d", rc));
1838 } else if (get_flag) {
1839 /* lock structure can be returned on get */
1842 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1844 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1845 rc = -EIO; /* bad smb */
1848 if (pLockData == NULL) {
1852 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1853 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1854 if (data_count < sizeof(struct cifs_posix_lock)) {
1858 parm_data = (struct cifs_posix_lock *)
1859 ((char *)&pSMBr->hdr.Protocol + data_offset);
1860 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1861 pLockData->fl_type = F_UNLCK;
1866 cifs_small_buf_release(pSMB);
1868 if (resp_buf_type == CIFS_SMALL_BUFFER)
1869 cifs_small_buf_release(iov[0].iov_base);
1870 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1871 cifs_buf_release(iov[0].iov_base);
1873 /* Note: On -EAGAIN error only caller can retry on handle based calls
1874 since file handle passed in no longer valid */
1881 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1884 CLOSE_REQ *pSMB = NULL;
1885 cFYI(1, ("In CIFSSMBClose"));
1887 /* do not retry on dead session on close */
1888 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1894 pSMB->FileID = (__u16) smb_file_id;
1895 pSMB->LastWriteTime = 0xFFFFFFFF;
1896 pSMB->ByteCount = 0;
1897 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1898 cifs_stats_inc(&tcon->num_closes);
1901 /* EINTR is expected when user ctl-c to kill app */
1902 cERROR(1, ("Send error in Close = %d", rc));
1906 /* Since session is dead, file will be closed on server already */
1914 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1915 const char *fromName, const char *toName,
1916 const struct nls_table *nls_codepage, int remap)
1919 RENAME_REQ *pSMB = NULL;
1920 RENAME_RSP *pSMBr = NULL;
1922 int name_len, name_len2;
1925 cFYI(1, ("In CIFSSMBRename"));
1927 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1932 pSMB->BufferFormat = 0x04;
1933 pSMB->SearchAttributes =
1934 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1937 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1939 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1940 PATH_MAX, nls_codepage, remap);
1941 name_len++; /* trailing null */
1943 pSMB->OldFileName[name_len] = 0x04; /* pad */
1944 /* protocol requires ASCII signature byte on Unicode string */
1945 pSMB->OldFileName[name_len + 1] = 0x00;
1947 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1948 toName, PATH_MAX, nls_codepage, remap);
1949 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1950 name_len2 *= 2; /* convert to bytes */
1951 } else { /* BB improve the check for buffer overruns BB */
1952 name_len = strnlen(fromName, PATH_MAX);
1953 name_len++; /* trailing null */
1954 strncpy(pSMB->OldFileName, fromName, name_len);
1955 name_len2 = strnlen(toName, PATH_MAX);
1956 name_len2++; /* trailing null */
1957 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1958 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1959 name_len2++; /* trailing null */
1960 name_len2++; /* signature byte */
1963 count = 1 /* 1st signature byte */ + name_len + name_len2;
1964 pSMB->hdr.smb_buf_length += count;
1965 pSMB->ByteCount = cpu_to_le16(count);
1967 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1968 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1969 cifs_stats_inc(&tcon->num_renames);
1971 cFYI(1, ("Send error in rename = %d", rc));
1973 cifs_buf_release(pSMB);
1981 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1982 int netfid, char *target_name,
1983 const struct nls_table *nls_codepage, int remap)
1985 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1986 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1987 struct set_file_rename *rename_info;
1989 char dummy_string[30];
1991 int bytes_returned = 0;
1993 __u16 params, param_offset, offset, count, byte_count;
1995 cFYI(1, ("Rename to File by handle"));
1996 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2002 pSMB->MaxSetupCount = 0;
2006 pSMB->Reserved2 = 0;
2007 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2008 offset = param_offset + params;
2010 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2011 rename_info = (struct set_file_rename *) data_offset;
2012 pSMB->MaxParameterCount = cpu_to_le16(2);
2013 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2014 pSMB->SetupCount = 1;
2015 pSMB->Reserved3 = 0;
2016 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2017 byte_count = 3 /* pad */ + params;
2018 pSMB->ParameterCount = cpu_to_le16(params);
2019 pSMB->TotalParameterCount = pSMB->ParameterCount;
2020 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2021 pSMB->DataOffset = cpu_to_le16(offset);
2022 /* construct random name ".cifs_tmp<inodenum><mid>" */
2023 rename_info->overwrite = cpu_to_le32(1);
2024 rename_info->root_fid = 0;
2025 /* unicode only call */
2026 if (target_name == NULL) {
2027 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2028 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2029 dummy_string, 24, nls_codepage, remap);
2031 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2032 target_name, PATH_MAX, nls_codepage,
2035 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2036 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2037 byte_count += count;
2038 pSMB->DataCount = cpu_to_le16(count);
2039 pSMB->TotalDataCount = pSMB->DataCount;
2041 pSMB->InformationLevel =
2042 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2043 pSMB->Reserved4 = 0;
2044 pSMB->hdr.smb_buf_length += byte_count;
2045 pSMB->ByteCount = cpu_to_le16(byte_count);
2046 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2047 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2048 cifs_stats_inc(&pTcon->num_t2renames);
2050 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2052 cifs_buf_release(pSMB);
2054 /* Note: On -EAGAIN error only caller can retry on handle based calls
2055 since file handle passed in no longer valid */
2061 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2062 const __u16 target_tid, const char *toName, const int flags,
2063 const struct nls_table *nls_codepage, int remap)
2066 COPY_REQ *pSMB = NULL;
2067 COPY_RSP *pSMBr = NULL;
2069 int name_len, name_len2;
2072 cFYI(1, ("In CIFSSMBCopy"));
2074 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2079 pSMB->BufferFormat = 0x04;
2080 pSMB->Tid2 = target_tid;
2082 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2084 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2085 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2086 fromName, PATH_MAX, nls_codepage,
2088 name_len++; /* trailing null */
2090 pSMB->OldFileName[name_len] = 0x04; /* pad */
2091 /* protocol requires ASCII signature byte on Unicode string */
2092 pSMB->OldFileName[name_len + 1] = 0x00;
2094 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2095 toName, PATH_MAX, nls_codepage, remap);
2096 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2097 name_len2 *= 2; /* convert to bytes */
2098 } else { /* BB improve the check for buffer overruns BB */
2099 name_len = strnlen(fromName, PATH_MAX);
2100 name_len++; /* trailing null */
2101 strncpy(pSMB->OldFileName, fromName, name_len);
2102 name_len2 = strnlen(toName, PATH_MAX);
2103 name_len2++; /* trailing null */
2104 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2105 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2106 name_len2++; /* trailing null */
2107 name_len2++; /* signature byte */
2110 count = 1 /* 1st signature byte */ + name_len + name_len2;
2111 pSMB->hdr.smb_buf_length += count;
2112 pSMB->ByteCount = cpu_to_le16(count);
2114 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2115 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2117 cFYI(1, ("Send error in copy = %d with %d files copied",
2118 rc, le16_to_cpu(pSMBr->CopyCount)));
2121 cifs_buf_release(pSMB);
2130 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2131 const char *fromName, const char *toName,
2132 const struct nls_table *nls_codepage)
2134 TRANSACTION2_SPI_REQ *pSMB = NULL;
2135 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2138 int name_len_target;
2140 int bytes_returned = 0;
2141 __u16 params, param_offset, offset, byte_count;
2143 cFYI(1, ("In Symlink Unix style"));
2145 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2150 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2152 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2153 /* find define for this maxpathcomponent */
2155 name_len++; /* trailing null */
2158 } else { /* BB improve the check for buffer overruns BB */
2159 name_len = strnlen(fromName, PATH_MAX);
2160 name_len++; /* trailing null */
2161 strncpy(pSMB->FileName, fromName, name_len);
2163 params = 6 + name_len;
2164 pSMB->MaxSetupCount = 0;
2168 pSMB->Reserved2 = 0;
2169 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2170 InformationLevel) - 4;
2171 offset = param_offset + params;
2173 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2174 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2176 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2177 /* find define for this maxpathcomponent */
2179 name_len_target++; /* trailing null */
2180 name_len_target *= 2;
2181 } else { /* BB improve the check for buffer overruns BB */
2182 name_len_target = strnlen(toName, PATH_MAX);
2183 name_len_target++; /* trailing null */
2184 strncpy(data_offset, toName, name_len_target);
2187 pSMB->MaxParameterCount = cpu_to_le16(2);
2188 /* BB find exact max on data count below from sess */
2189 pSMB->MaxDataCount = cpu_to_le16(1000);
2190 pSMB->SetupCount = 1;
2191 pSMB->Reserved3 = 0;
2192 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2193 byte_count = 3 /* pad */ + params + name_len_target;
2194 pSMB->DataCount = cpu_to_le16(name_len_target);
2195 pSMB->ParameterCount = cpu_to_le16(params);
2196 pSMB->TotalDataCount = pSMB->DataCount;
2197 pSMB->TotalParameterCount = pSMB->ParameterCount;
2198 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2199 pSMB->DataOffset = cpu_to_le16(offset);
2200 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2201 pSMB->Reserved4 = 0;
2202 pSMB->hdr.smb_buf_length += byte_count;
2203 pSMB->ByteCount = cpu_to_le16(byte_count);
2204 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2205 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2206 cifs_stats_inc(&tcon->num_symlinks);
2208 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2211 cifs_buf_release(pSMB);
2214 goto createSymLinkRetry;
2220 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2221 const char *fromName, const char *toName,
2222 const struct nls_table *nls_codepage, int remap)
2224 TRANSACTION2_SPI_REQ *pSMB = NULL;
2225 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2228 int name_len_target;
2230 int bytes_returned = 0;
2231 __u16 params, param_offset, offset, byte_count;
2233 cFYI(1, ("In Create Hard link Unix style"));
2234 createHardLinkRetry:
2235 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2240 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2241 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2242 PATH_MAX, nls_codepage, remap);
2243 name_len++; /* trailing null */
2246 } else { /* BB improve the check for buffer overruns BB */
2247 name_len = strnlen(toName, PATH_MAX);
2248 name_len++; /* trailing null */
2249 strncpy(pSMB->FileName, toName, name_len);
2251 params = 6 + name_len;
2252 pSMB->MaxSetupCount = 0;
2256 pSMB->Reserved2 = 0;
2257 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2258 InformationLevel) - 4;
2259 offset = param_offset + params;
2261 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2262 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2264 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2265 nls_codepage, remap);
2266 name_len_target++; /* trailing null */
2267 name_len_target *= 2;
2268 } else { /* BB improve the check for buffer overruns BB */
2269 name_len_target = strnlen(fromName, PATH_MAX);
2270 name_len_target++; /* trailing null */
2271 strncpy(data_offset, fromName, name_len_target);
2274 pSMB->MaxParameterCount = cpu_to_le16(2);
2275 /* BB find exact max on data count below from sess*/
2276 pSMB->MaxDataCount = cpu_to_le16(1000);
2277 pSMB->SetupCount = 1;
2278 pSMB->Reserved3 = 0;
2279 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2280 byte_count = 3 /* pad */ + params + name_len_target;
2281 pSMB->ParameterCount = cpu_to_le16(params);
2282 pSMB->TotalParameterCount = pSMB->ParameterCount;
2283 pSMB->DataCount = cpu_to_le16(name_len_target);
2284 pSMB->TotalDataCount = pSMB->DataCount;
2285 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2286 pSMB->DataOffset = cpu_to_le16(offset);
2287 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2288 pSMB->Reserved4 = 0;
2289 pSMB->hdr.smb_buf_length += byte_count;
2290 pSMB->ByteCount = cpu_to_le16(byte_count);
2291 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2292 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2293 cifs_stats_inc(&tcon->num_hardlinks);
2295 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2297 cifs_buf_release(pSMB);
2299 goto createHardLinkRetry;
2305 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2306 const char *fromName, const char *toName,
2307 const struct nls_table *nls_codepage, int remap)
2310 NT_RENAME_REQ *pSMB = NULL;
2311 RENAME_RSP *pSMBr = NULL;
2313 int name_len, name_len2;
2316 cFYI(1, ("In CIFSCreateHardLink"));
2317 winCreateHardLinkRetry:
2319 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2324 pSMB->SearchAttributes =
2325 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2327 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2328 pSMB->ClusterCount = 0;
2330 pSMB->BufferFormat = 0x04;
2332 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2334 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2335 PATH_MAX, nls_codepage, remap);
2336 name_len++; /* trailing null */
2338 pSMB->OldFileName[name_len] = 0; /* pad */
2339 pSMB->OldFileName[name_len + 1] = 0x04;
2341 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2342 toName, PATH_MAX, nls_codepage, remap);
2343 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2344 name_len2 *= 2; /* convert to bytes */
2345 } else { /* BB improve the check for buffer overruns BB */
2346 name_len = strnlen(fromName, PATH_MAX);
2347 name_len++; /* trailing null */
2348 strncpy(pSMB->OldFileName, fromName, name_len);
2349 name_len2 = strnlen(toName, PATH_MAX);
2350 name_len2++; /* trailing null */
2351 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2352 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2353 name_len2++; /* trailing null */
2354 name_len2++; /* signature byte */
2357 count = 1 /* string type byte */ + name_len + name_len2;
2358 pSMB->hdr.smb_buf_length += count;
2359 pSMB->ByteCount = cpu_to_le16(count);
2361 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2362 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2363 cifs_stats_inc(&tcon->num_hardlinks);
2365 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2367 cifs_buf_release(pSMB);
2369 goto winCreateHardLinkRetry;
2375 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2376 const unsigned char *searchName,
2377 char *symlinkinfo, const int buflen,
2378 const struct nls_table *nls_codepage)
2380 /* SMB_QUERY_FILE_UNIX_LINK */
2381 TRANSACTION2_QPI_REQ *pSMB = NULL;
2382 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2386 __u16 params, byte_count;
2388 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2391 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2396 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2398 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2399 PATH_MAX, nls_codepage);
2400 name_len++; /* trailing null */
2402 } else { /* BB improve the check for buffer overruns BB */
2403 name_len = strnlen(searchName, PATH_MAX);
2404 name_len++; /* trailing null */
2405 strncpy(pSMB->FileName, searchName, name_len);
2408 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2409 pSMB->TotalDataCount = 0;
2410 pSMB->MaxParameterCount = cpu_to_le16(2);
2411 /* BB find exact max data count below from sess structure BB */
2412 pSMB->MaxDataCount = cpu_to_le16(4000);
2413 pSMB->MaxSetupCount = 0;
2417 pSMB->Reserved2 = 0;
2418 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2419 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2420 pSMB->DataCount = 0;
2421 pSMB->DataOffset = 0;
2422 pSMB->SetupCount = 1;
2423 pSMB->Reserved3 = 0;
2424 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2425 byte_count = params + 1 /* pad */ ;
2426 pSMB->TotalParameterCount = cpu_to_le16(params);
2427 pSMB->ParameterCount = pSMB->TotalParameterCount;
2428 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2429 pSMB->Reserved4 = 0;
2430 pSMB->hdr.smb_buf_length += byte_count;
2431 pSMB->ByteCount = cpu_to_le16(byte_count);
2433 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2434 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2436 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2438 /* decode response */
2440 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2441 if (rc || (pSMBr->ByteCount < 2))
2442 /* BB also check enough total bytes returned */
2443 rc = -EIO; /* bad smb */
2445 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2446 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2448 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2449 name_len = UniStrnlen((wchar_t *) ((char *)
2450 &pSMBr->hdr.Protocol + data_offset),
2451 min_t(const int, buflen, count) / 2);
2452 /* BB FIXME investigate remapping reserved chars here */
2453 cifs_strfromUCS_le(symlinkinfo,
2454 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2456 name_len, nls_codepage);
2458 strncpy(symlinkinfo,
2459 (char *) &pSMBr->hdr.Protocol +
2461 min_t(const int, buflen, count));
2463 symlinkinfo[buflen] = 0;
2464 /* just in case so calling code does not go off the end of buffer */
2467 cifs_buf_release(pSMB);
2469 goto querySymLinkRetry;
2473 #ifdef CONFIG_CIFS_EXPERIMENTAL
2474 /* Initialize NT TRANSACT SMB into small smb request buffer.
2475 This assumes that all NT TRANSACTS that we init here have
2476 total parm and data under about 400 bytes (to fit in small cifs
2477 buffer size), which is the case so far, it easily fits. NB:
2478 Setup words themselves and ByteCount
2479 MaxSetupCount (size of returned setup area) and
2480 MaxParameterCount (returned parms size) must be set by caller */
2482 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2483 const int parm_len, struct cifsTconInfo *tcon,
2488 struct smb_com_ntransact_req *pSMB;
2490 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2494 *ret_buf = (void *)pSMB;
2496 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2497 pSMB->TotalDataCount = 0;
2498 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2499 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2500 pSMB->ParameterCount = pSMB->TotalParameterCount;
2501 pSMB->DataCount = pSMB->TotalDataCount;
2502 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2503 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2504 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2505 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2506 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2507 pSMB->SubCommand = cpu_to_le16(sub_command);
2512 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2513 __u32 *pparmlen, __u32 *pdatalen)
2516 __u32 data_count, data_offset, parm_count, parm_offset;
2517 struct smb_com_ntransact_rsp *pSMBr;
2525 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2527 /* ByteCount was converted from little endian in SendReceive */
2528 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2529 (char *)&pSMBr->ByteCount;
2531 data_offset = le32_to_cpu(pSMBr->DataOffset);
2532 data_count = le32_to_cpu(pSMBr->DataCount);
2533 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2534 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2536 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2537 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2539 /* should we also check that parm and data areas do not overlap? */
2540 if (*ppparm > end_of_smb) {
2541 cFYI(1, ("parms start after end of smb"));
2543 } else if (parm_count + *ppparm > end_of_smb) {
2544 cFYI(1, ("parm end after end of smb"));
2546 } else if (*ppdata > end_of_smb) {
2547 cFYI(1, ("data starts after end of smb"));
2549 } else if (data_count + *ppdata > end_of_smb) {
2550 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2551 *ppdata, data_count, (data_count + *ppdata),
2552 end_of_smb, pSMBr));
2554 } else if (parm_count + data_count > pSMBr->ByteCount) {
2555 cFYI(1, ("parm count and data count larger than SMB"));
2558 *pdatalen = data_count;
2559 *pparmlen = parm_count;
2562 #endif /* CIFS_EXPERIMENTAL */
2565 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2566 const unsigned char *searchName,
2567 char *symlinkinfo, const int buflen, __u16 fid,
2568 const struct nls_table *nls_codepage)
2573 struct smb_com_transaction_ioctl_req *pSMB;
2574 struct smb_com_transaction_ioctl_rsp *pSMBr;
2576 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2577 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2582 pSMB->TotalParameterCount = 0 ;
2583 pSMB->TotalDataCount = 0;
2584 pSMB->MaxParameterCount = cpu_to_le32(2);
2585 /* BB find exact data count max from sess structure BB */
2586 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2587 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2588 pSMB->MaxSetupCount = 4;
2590 pSMB->ParameterOffset = 0;
2591 pSMB->DataCount = 0;
2592 pSMB->DataOffset = 0;
2593 pSMB->SetupCount = 4;
2594 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2595 pSMB->ParameterCount = pSMB->TotalParameterCount;
2596 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2597 pSMB->IsFsctl = 1; /* FSCTL */
2598 pSMB->IsRootFlag = 0;
2599 pSMB->Fid = fid; /* file handle always le */
2600 pSMB->ByteCount = 0;
2602 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2603 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2605 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2606 } else { /* decode response */
2607 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2608 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2609 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2610 /* BB also check enough total bytes returned */
2611 rc = -EIO; /* bad smb */
2613 if (data_count && (data_count < 2048)) {
2614 char *end_of_smb = 2 /* sizeof byte count */ +
2616 (char *)&pSMBr->ByteCount;
2618 struct reparse_data *reparse_buf =
2619 (struct reparse_data *)
2620 ((char *)&pSMBr->hdr.Protocol
2622 if ((char *)reparse_buf >= end_of_smb) {
2626 if ((reparse_buf->LinkNamesBuf +
2627 reparse_buf->TargetNameOffset +
2628 reparse_buf->TargetNameLen) >
2630 cFYI(1, ("reparse buf beyond SMB"));
2635 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2636 name_len = UniStrnlen((wchar_t *)
2637 (reparse_buf->LinkNamesBuf +
2638 reparse_buf->TargetNameOffset),
2640 reparse_buf->TargetNameLen / 2));
2641 cifs_strfromUCS_le(symlinkinfo,
2642 (__le16 *) (reparse_buf->LinkNamesBuf +
2643 reparse_buf->TargetNameOffset),
2644 name_len, nls_codepage);
2645 } else { /* ASCII names */
2646 strncpy(symlinkinfo,
2647 reparse_buf->LinkNamesBuf +
2648 reparse_buf->TargetNameOffset,
2649 min_t(const int, buflen,
2650 reparse_buf->TargetNameLen));
2654 cFYI(1, ("Invalid return data count on "
2655 "get reparse info ioctl"));
2657 symlinkinfo[buflen] = 0; /* just in case so the caller
2658 does not go off the end of the buffer */
2659 cFYI(1, ("readlink result - %s", symlinkinfo));
2663 cifs_buf_release(pSMB);
2665 /* Note: On -EAGAIN error only caller can retry on handle based calls
2666 since file handle passed in no longer valid */
2671 #ifdef CONFIG_CIFS_POSIX
2673 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2674 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2675 struct cifs_posix_ace *cifs_ace)
2677 /* u8 cifs fields do not need le conversion */
2678 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2679 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2680 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2681 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2686 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2687 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2688 const int acl_type, const int size_of_data_area)
2693 struct cifs_posix_ace *pACE;
2694 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2695 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2697 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2700 if (acl_type & ACL_TYPE_ACCESS) {
2701 count = le16_to_cpu(cifs_acl->access_entry_count);
2702 pACE = &cifs_acl->ace_array[0];
2703 size = sizeof(struct cifs_posix_acl);
2704 size += sizeof(struct cifs_posix_ace) * count;
2705 /* check if we would go beyond end of SMB */
2706 if (size_of_data_area < size) {
2707 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2708 size_of_data_area, size));
2711 } else if (acl_type & ACL_TYPE_DEFAULT) {
2712 count = le16_to_cpu(cifs_acl->access_entry_count);
2713 size = sizeof(struct cifs_posix_acl);
2714 size += sizeof(struct cifs_posix_ace) * count;
2715 /* skip past access ACEs to get to default ACEs */
2716 pACE = &cifs_acl->ace_array[count];
2717 count = le16_to_cpu(cifs_acl->default_entry_count);
2718 size += sizeof(struct cifs_posix_ace) * count;
2719 /* check if we would go beyond end of SMB */
2720 if (size_of_data_area < size)
2727 size = posix_acl_xattr_size(count);
2728 if ((buflen == 0) || (local_acl == NULL)) {
2729 /* used to query ACL EA size */
2730 } else if (size > buflen) {
2732 } else /* buffer big enough */ {
2733 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2734 for (i = 0; i < count ; i++) {
2735 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2742 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2743 const posix_acl_xattr_entry *local_ace)
2745 __u16 rc = 0; /* 0 = ACL converted ok */
2747 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2748 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2749 /* BB is there a better way to handle the large uid? */
2750 if (local_ace->e_id == cpu_to_le32(-1)) {
2751 /* Probably no need to le convert -1 on any arch but can not hurt */
2752 cifs_ace->cifs_uid = cpu_to_le64(-1);
2754 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2755 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2759 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2760 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2761 const int buflen, const int acl_type)
2764 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2765 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2769 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2772 count = posix_acl_xattr_count((size_t)buflen);
2773 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2775 count, buflen, le32_to_cpu(local_acl->a_version)));
2776 if (le32_to_cpu(local_acl->a_version) != 2) {
2777 cFYI(1, ("unknown POSIX ACL version %d",
2778 le32_to_cpu(local_acl->a_version)));
2781 cifs_acl->version = cpu_to_le16(1);
2782 if (acl_type == ACL_TYPE_ACCESS)
2783 cifs_acl->access_entry_count = cpu_to_le16(count);
2784 else if (acl_type == ACL_TYPE_DEFAULT)
2785 cifs_acl->default_entry_count = cpu_to_le16(count);
2787 cFYI(1, ("unknown ACL type %d", acl_type));
2790 for (i = 0; i < count; i++) {
2791 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2792 &local_acl->a_entries[i]);
2794 /* ACE not converted */
2799 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2800 rc += sizeof(struct cifs_posix_acl);
2801 /* BB add check to make sure ACL does not overflow SMB */
2807 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2808 const unsigned char *searchName,
2809 char *acl_inf, const int buflen, const int acl_type,
2810 const struct nls_table *nls_codepage, int remap)
2812 /* SMB_QUERY_POSIX_ACL */
2813 TRANSACTION2_QPI_REQ *pSMB = NULL;
2814 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2818 __u16 params, byte_count;
2820 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2830 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2831 PATH_MAX, nls_codepage, remap);
2832 name_len++; /* trailing null */
2834 pSMB->FileName[name_len] = 0;
2835 pSMB->FileName[name_len+1] = 0;
2836 } else { /* BB improve the check for buffer overruns BB */
2837 name_len = strnlen(searchName, PATH_MAX);
2838 name_len++; /* trailing null */
2839 strncpy(pSMB->FileName, searchName, name_len);
2842 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2843 pSMB->TotalDataCount = 0;
2844 pSMB->MaxParameterCount = cpu_to_le16(2);
2845 /* BB find exact max data count below from sess structure BB */
2846 pSMB->MaxDataCount = cpu_to_le16(4000);
2847 pSMB->MaxSetupCount = 0;
2851 pSMB->Reserved2 = 0;
2852 pSMB->ParameterOffset = cpu_to_le16(
2853 offsetof(struct smb_com_transaction2_qpi_req,
2854 InformationLevel) - 4);
2855 pSMB->DataCount = 0;
2856 pSMB->DataOffset = 0;
2857 pSMB->SetupCount = 1;
2858 pSMB->Reserved3 = 0;
2859 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2860 byte_count = params + 1 /* pad */ ;
2861 pSMB->TotalParameterCount = cpu_to_le16(params);
2862 pSMB->ParameterCount = pSMB->TotalParameterCount;
2863 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2864 pSMB->Reserved4 = 0;
2865 pSMB->hdr.smb_buf_length += byte_count;
2866 pSMB->ByteCount = cpu_to_le16(byte_count);
2868 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2869 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2870 cifs_stats_inc(&tcon->num_acl_get);
2872 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2874 /* decode response */
2876 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2877 if (rc || (pSMBr->ByteCount < 2))
2878 /* BB also check enough total bytes returned */
2879 rc = -EIO; /* bad smb */
2881 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2882 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2883 rc = cifs_copy_posix_acl(acl_inf,
2884 (char *)&pSMBr->hdr.Protocol+data_offset,
2885 buflen, acl_type, count);
2888 cifs_buf_release(pSMB);
2895 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2896 const unsigned char *fileName,
2897 const char *local_acl, const int buflen,
2899 const struct nls_table *nls_codepage, int remap)
2901 struct smb_com_transaction2_spi_req *pSMB = NULL;
2902 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2906 int bytes_returned = 0;
2907 __u16 params, byte_count, data_count, param_offset, offset;
2909 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2911 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2915 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2917 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2918 PATH_MAX, nls_codepage, remap);
2919 name_len++; /* trailing null */
2921 } else { /* BB improve the check for buffer overruns BB */
2922 name_len = strnlen(fileName, PATH_MAX);
2923 name_len++; /* trailing null */
2924 strncpy(pSMB->FileName, fileName, name_len);
2926 params = 6 + name_len;
2927 pSMB->MaxParameterCount = cpu_to_le16(2);
2928 /* BB find max SMB size from sess */
2929 pSMB->MaxDataCount = cpu_to_le16(1000);
2930 pSMB->MaxSetupCount = 0;
2934 pSMB->Reserved2 = 0;
2935 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2936 InformationLevel) - 4;
2937 offset = param_offset + params;
2938 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2939 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2941 /* convert to on the wire format for POSIX ACL */
2942 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2944 if (data_count == 0) {
2946 goto setACLerrorExit;
2948 pSMB->DataOffset = cpu_to_le16(offset);
2949 pSMB->SetupCount = 1;
2950 pSMB->Reserved3 = 0;
2951 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2952 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2953 byte_count = 3 /* pad */ + params + data_count;
2954 pSMB->DataCount = cpu_to_le16(data_count);
2955 pSMB->TotalDataCount = pSMB->DataCount;
2956 pSMB->ParameterCount = cpu_to_le16(params);
2957 pSMB->TotalParameterCount = pSMB->ParameterCount;
2958 pSMB->Reserved4 = 0;
2959 pSMB->hdr.smb_buf_length += byte_count;
2960 pSMB->ByteCount = cpu_to_le16(byte_count);
2961 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2962 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2964 cFYI(1, ("Set POSIX ACL returned %d", rc));
2967 cifs_buf_release(pSMB);
2973 /* BB fix tabs in this function FIXME BB */
2975 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2976 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2979 struct smb_t2_qfi_req *pSMB = NULL;
2980 struct smb_t2_qfi_rsp *pSMBr = NULL;
2982 __u16 params, byte_count;
2984 cFYI(1, ("In GetExtAttr"));
2989 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2994 params = 2 /* level */ + 2 /* fid */;
2995 pSMB->t2.TotalDataCount = 0;
2996 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2997 /* BB find exact max data count below from sess structure BB */
2998 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2999 pSMB->t2.MaxSetupCount = 0;
3000 pSMB->t2.Reserved = 0;
3002 pSMB->t2.Timeout = 0;
3003 pSMB->t2.Reserved2 = 0;
3004 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3006 pSMB->t2.DataCount = 0;
3007 pSMB->t2.DataOffset = 0;
3008 pSMB->t2.SetupCount = 1;
3009 pSMB->t2.Reserved3 = 0;
3010 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3011 byte_count = params + 1 /* pad */ ;
3012 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3013 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3014 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3017 pSMB->hdr.smb_buf_length += byte_count;
3018 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3020 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3021 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3023 cFYI(1, ("error %d in GetExtAttr", rc));
3025 /* decode response */
3026 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3027 if (rc || (pSMBr->ByteCount < 2))
3028 /* BB also check enough total bytes returned */
3029 /* If rc should we check for EOPNOSUPP and
3030 disable the srvino flag? or in caller? */
3031 rc = -EIO; /* bad smb */
3033 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3034 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3035 struct file_chattr_info *pfinfo;
3036 /* BB Do we need a cast or hash here ? */
3038 cFYI(1, ("Illegal size ret in GetExtAttr"));
3042 pfinfo = (struct file_chattr_info *)
3043 (data_offset + (char *) &pSMBr->hdr.Protocol);
3044 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3045 *pMask = le64_to_cpu(pfinfo->mask);
3049 cifs_buf_release(pSMB);
3051 goto GetExtAttrRetry;
3055 #endif /* CONFIG_POSIX */
3057 #ifdef CONFIG_CIFS_EXPERIMENTAL
3058 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3060 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3061 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3065 QUERY_SEC_DESC_REQ *pSMB;
3068 cFYI(1, ("GetCifsACL"));
3073 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3074 8 /* parm len */, tcon, (void **) &pSMB);
3078 pSMB->MaxParameterCount = cpu_to_le32(4);
3079 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3080 pSMB->MaxSetupCount = 0;
3081 pSMB->Fid = fid; /* file handle always le */
3082 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3084 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3085 pSMB->hdr.smb_buf_length += 11;
3086 iov[0].iov_base = (char *)pSMB;
3087 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3089 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3091 cifs_stats_inc(&tcon->num_acl_get);
3093 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3094 } else { /* decode response */
3098 struct smb_com_ntransact_rsp *pSMBr;
3101 /* validate_nttransact */
3102 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3103 &pdata, &parm_len, pbuflen);
3106 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3108 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3110 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3111 rc = -EIO; /* bad smb */
3116 /* BB check that data area is minimum length and as big as acl_len */
3118 acl_len = le32_to_cpu(*parm);
3119 if (acl_len != *pbuflen) {
3120 cERROR(1, ("acl length %d does not match %d",
3121 acl_len, *pbuflen));
3122 if (*pbuflen > acl_len)
3126 /* check if buffer is big enough for the acl
3127 header followed by the smallest SID */
3128 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3129 (*pbuflen >= 64 * 1024)) {
3130 cERROR(1, ("bad acl length %d", *pbuflen));
3134 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3135 if (*acl_inf == NULL) {
3139 memcpy(*acl_inf, pdata, *pbuflen);
3143 if (buf_type == CIFS_SMALL_BUFFER)
3144 cifs_small_buf_release(iov[0].iov_base);
3145 else if (buf_type == CIFS_LARGE_BUFFER)
3146 cifs_buf_release(iov[0].iov_base);
3147 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3152 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3153 struct cifs_ntsd *pntsd, __u32 acllen)
3155 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3157 int bytes_returned = 0;
3158 SET_SEC_DESC_REQ *pSMB = NULL;
3159 NTRANSACT_RSP *pSMBr = NULL;
3162 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3167 pSMB->MaxSetupCount = 0;
3171 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3172 data_count = acllen;
3173 data_offset = param_offset + param_count;
3174 byte_count = 3 /* pad */ + param_count;
3176 pSMB->DataCount = cpu_to_le32(data_count);
3177 pSMB->TotalDataCount = pSMB->DataCount;
3178 pSMB->MaxParameterCount = cpu_to_le32(4);
3179 pSMB->MaxDataCount = cpu_to_le32(16384);
3180 pSMB->ParameterCount = cpu_to_le32(param_count);
3181 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3182 pSMB->TotalParameterCount = pSMB->ParameterCount;
3183 pSMB->DataOffset = cpu_to_le32(data_offset);
3184 pSMB->SetupCount = 0;
3185 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3186 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3188 pSMB->Fid = fid; /* file handle always le */
3189 pSMB->Reserved2 = 0;
3190 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3192 if (pntsd && acllen) {
3193 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3196 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3199 pSMB->hdr.smb_buf_length += byte_count;
3201 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3202 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3204 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3206 cFYI(1, ("Set CIFS ACL returned %d", rc));
3207 cifs_buf_release(pSMB);
3210 goto setCifsAclRetry;
3215 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3217 /* Legacy Query Path Information call for lookup to old servers such
3219 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3220 const unsigned char *searchName,
3221 FILE_ALL_INFO *pFinfo,
3222 const struct nls_table *nls_codepage, int remap)
3224 QUERY_INFORMATION_REQ *pSMB;
3225 QUERY_INFORMATION_RSP *pSMBr;
3230 cFYI(1, ("In SMBQPath path %s", searchName));
3232 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3237 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3239 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3240 PATH_MAX, nls_codepage, remap);
3241 name_len++; /* trailing null */
3244 name_len = strnlen(searchName, PATH_MAX);
3245 name_len++; /* trailing null */
3246 strncpy(pSMB->FileName, searchName, name_len);
3248 pSMB->BufferFormat = 0x04;
3249 name_len++; /* account for buffer type byte */
3250 pSMB->hdr.smb_buf_length += (__u16) name_len;
3251 pSMB->ByteCount = cpu_to_le16(name_len);
3253 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3254 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3256 cFYI(1, ("Send error in QueryInfo = %d", rc));
3257 } else if (pFinfo) {
3259 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3261 /* decode response */
3262 /* BB FIXME - add time zone adjustment BB */
3263 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3266 /* decode time fields */
3267 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3268 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3269 pFinfo->LastAccessTime = 0;
3270 pFinfo->AllocationSize =
3271 cpu_to_le64(le32_to_cpu(pSMBr->size));
3272 pFinfo->EndOfFile = pFinfo->AllocationSize;
3273 pFinfo->Attributes =
3274 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3276 rc = -EIO; /* bad buffer passed in */
3278 cifs_buf_release(pSMB);
3290 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3291 const unsigned char *searchName,
3292 FILE_ALL_INFO *pFindData,
3293 int legacy /* old style infolevel */,
3294 const struct nls_table *nls_codepage, int remap)
3296 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3297 TRANSACTION2_QPI_REQ *pSMB = NULL;
3298 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3302 __u16 params, byte_count;
3304 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3306 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3311 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3313 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3314 PATH_MAX, nls_codepage, remap);
3315 name_len++; /* trailing null */
3317 } else { /* BB improve the check for buffer overruns BB */
3318 name_len = strnlen(searchName, PATH_MAX);
3319 name_len++; /* trailing null */
3320 strncpy(pSMB->FileName, searchName, name_len);
3323 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3324 pSMB->TotalDataCount = 0;
3325 pSMB->MaxParameterCount = cpu_to_le16(2);
3326 /* BB find exact max SMB PDU from sess structure BB */
3327 pSMB->MaxDataCount = cpu_to_le16(4000);
3328 pSMB->MaxSetupCount = 0;
3332 pSMB->Reserved2 = 0;
3333 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3334 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3335 pSMB->DataCount = 0;
3336 pSMB->DataOffset = 0;
3337 pSMB->SetupCount = 1;
3338 pSMB->Reserved3 = 0;
3339 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3340 byte_count = params + 1 /* pad */ ;
3341 pSMB->TotalParameterCount = cpu_to_le16(params);
3342 pSMB->ParameterCount = pSMB->TotalParameterCount;
3344 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3346 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3347 pSMB->Reserved4 = 0;
3348 pSMB->hdr.smb_buf_length += byte_count;
3349 pSMB->ByteCount = cpu_to_le16(byte_count);
3351 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3352 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3354 cFYI(1, ("Send error in QPathInfo = %d", rc));
3355 } else { /* decode response */
3356 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3358 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3360 else if (!legacy && (pSMBr->ByteCount < 40))
3361 rc = -EIO; /* bad smb */
3362 else if (legacy && (pSMBr->ByteCount < 24))
3363 rc = -EIO; /* 24 or 26 expected but we do not read
3365 else if (pFindData) {
3367 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3369 /* On legacy responses we do not read the last field,
3370 EAsize, fortunately since it varies by subdialect and
3371 also note it differs on Set vs. Get, ie two bytes or 4
3372 bytes depending but we don't care here */
3374 size = sizeof(FILE_INFO_STANDARD);
3376 size = sizeof(FILE_ALL_INFO);
3377 memcpy((char *) pFindData,
3378 (char *) &pSMBr->hdr.Protocol +
3383 cifs_buf_release(pSMB);
3385 goto QPathInfoRetry;
3391 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3392 const unsigned char *searchName,
3393 FILE_UNIX_BASIC_INFO *pFindData,
3394 const struct nls_table *nls_codepage, int remap)
3396 /* SMB_QUERY_FILE_UNIX_BASIC */
3397 TRANSACTION2_QPI_REQ *pSMB = NULL;
3398 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3400 int bytes_returned = 0;
3402 __u16 params, byte_count;
3404 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3406 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3411 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3413 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3414 PATH_MAX, nls_codepage, remap);
3415 name_len++; /* trailing null */
3417 } else { /* BB improve the check for buffer overruns BB */
3418 name_len = strnlen(searchName, PATH_MAX);
3419 name_len++; /* trailing null */
3420 strncpy(pSMB->FileName, searchName, name_len);
3423 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3424 pSMB->TotalDataCount = 0;
3425 pSMB->MaxParameterCount = cpu_to_le16(2);
3426 /* BB find exact max SMB PDU from sess structure BB */
3427 pSMB->MaxDataCount = cpu_to_le16(4000);
3428 pSMB->MaxSetupCount = 0;
3432 pSMB->Reserved2 = 0;
3433 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3434 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3435 pSMB->DataCount = 0;
3436 pSMB->DataOffset = 0;
3437 pSMB->SetupCount = 1;
3438 pSMB->Reserved3 = 0;
3439 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3440 byte_count = params + 1 /* pad */ ;
3441 pSMB->TotalParameterCount = cpu_to_le16(params);
3442 pSMB->ParameterCount = pSMB->TotalParameterCount;
3443 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3444 pSMB->Reserved4 = 0;
3445 pSMB->hdr.smb_buf_length += byte_count;
3446 pSMB->ByteCount = cpu_to_le16(byte_count);
3448 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3449 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3451 cFYI(1, ("Send error in QPathInfo = %d", rc));
3452 } else { /* decode response */
3453 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3455 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3456 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3457 "Unix Extensions can be disabled on mount "
3458 "by specifying the nosfu mount option."));
3459 rc = -EIO; /* bad smb */
3461 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3462 memcpy((char *) pFindData,
3463 (char *) &pSMBr->hdr.Protocol +
3465 sizeof(FILE_UNIX_BASIC_INFO));
3468 cifs_buf_release(pSMB);
3470 goto UnixQPathInfoRetry;
3475 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3477 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3478 const char *searchName,
3479 const struct nls_table *nls_codepage,
3481 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3483 /* level 257 SMB_ */
3484 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3485 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3486 T2_FFIRST_RSP_PARMS *parms;
3488 int bytes_returned = 0;
3490 __u16 params, byte_count;
3492 cFYI(1, ("In FindFirst for %s", searchName));
3495 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3500 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3502 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3503 PATH_MAX, nls_codepage, remap);
3504 /* We can not add the asterik earlier in case
3505 it got remapped to 0xF03A as if it were part of the
3506 directory name instead of a wildcard */
3508 pSMB->FileName[name_len] = dirsep;
3509 pSMB->FileName[name_len+1] = 0;
3510 pSMB->FileName[name_len+2] = '*';
3511 pSMB->FileName[name_len+3] = 0;
3512 name_len += 4; /* now the trailing null */
3513 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3514 pSMB->FileName[name_len+1] = 0;
3516 } else { /* BB add check for overrun of SMB buf BB */
3517 name_len = strnlen(searchName, PATH_MAX);
3518 /* BB fix here and in unicode clause above ie
3519 if (name_len > buffersize-header)
3520 free buffer exit; BB */
3521 strncpy(pSMB->FileName, searchName, name_len);
3522 pSMB->FileName[name_len] = dirsep;
3523 pSMB->FileName[name_len+1] = '*';
3524 pSMB->FileName[name_len+2] = 0;
3528 params = 12 + name_len /* includes null */ ;
3529 pSMB->TotalDataCount = 0; /* no EAs */
3530 pSMB->MaxParameterCount = cpu_to_le16(10);
3531 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3532 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3533 pSMB->MaxSetupCount = 0;
3537 pSMB->Reserved2 = 0;
3538 byte_count = params + 1 /* pad */ ;
3539 pSMB->TotalParameterCount = cpu_to_le16(params);
3540 pSMB->ParameterCount = pSMB->TotalParameterCount;
3541 pSMB->ParameterOffset = cpu_to_le16(
3542 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3544 pSMB->DataCount = 0;
3545 pSMB->DataOffset = 0;
3546 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3547 pSMB->Reserved3 = 0;
3548 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3549 pSMB->SearchAttributes =
3550 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3552 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3553 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3554 CIFS_SEARCH_RETURN_RESUME);
3555 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3557 /* BB what should we set StorageType to? Does it matter? BB */
3558 pSMB->SearchStorageType = 0;
3559 pSMB->hdr.smb_buf_length += byte_count;
3560 pSMB->ByteCount = cpu_to_le16(byte_count);
3562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3563 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3564 cifs_stats_inc(&tcon->num_ffirst);
3566 if (rc) {/* BB add logic to retry regular search if Unix search
3567 rejected unexpectedly by server */
3568 /* BB Add code to handle unsupported level rc */
3569 cFYI(1, ("Error in FindFirst = %d", rc));
3571 cifs_buf_release(pSMB);
3573 /* BB eventually could optimize out free and realloc of buf */
3576 goto findFirstRetry;
3577 } else { /* decode response */
3578 /* BB remember to free buffer if error BB */
3579 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3581 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3582 psrch_inf->unicode = true;
3584 psrch_inf->unicode = false;
3586 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3587 psrch_inf->smallBuf = 0;
3588 psrch_inf->srch_entries_start =
3589 (char *) &pSMBr->hdr.Protocol +
3590 le16_to_cpu(pSMBr->t2.DataOffset);
3591 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3592 le16_to_cpu(pSMBr->t2.ParameterOffset));
3594 if (parms->EndofSearch)
3595 psrch_inf->endOfSearch = true;
3597 psrch_inf->endOfSearch = false;
3599 psrch_inf->entries_in_buffer =
3600 le16_to_cpu(parms->SearchCount);
3601 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3602 psrch_inf->entries_in_buffer;
3603 *pnetfid = parms->SearchHandle;
3605 cifs_buf_release(pSMB);
3612 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3613 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3615 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3616 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3617 T2_FNEXT_RSP_PARMS *parms;
3618 char *response_data;
3620 int bytes_returned, name_len;
3621 __u16 params, byte_count;
3623 cFYI(1, ("In FindNext"));
3625 if (psrch_inf->endOfSearch)
3628 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3633 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3635 pSMB->TotalDataCount = 0; /* no EAs */
3636 pSMB->MaxParameterCount = cpu_to_le16(8);
3637 pSMB->MaxDataCount =
3638 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3640 pSMB->MaxSetupCount = 0;
3644 pSMB->Reserved2 = 0;
3645 pSMB->ParameterOffset = cpu_to_le16(
3646 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3647 pSMB->DataCount = 0;
3648 pSMB->DataOffset = 0;
3649 pSMB->SetupCount = 1;
3650 pSMB->Reserved3 = 0;
3651 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3652 pSMB->SearchHandle = searchHandle; /* always kept as le */
3654 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3655 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3656 pSMB->ResumeKey = psrch_inf->resume_key;
3658 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3660 name_len = psrch_inf->resume_name_len;
3662 if (name_len < PATH_MAX) {
3663 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3664 byte_count += name_len;
3665 /* 14 byte parm len above enough for 2 byte null terminator */
3666 pSMB->ResumeFileName[name_len] = 0;
3667 pSMB->ResumeFileName[name_len+1] = 0;
3670 goto FNext2_err_exit;
3672 byte_count = params + 1 /* pad */ ;
3673 pSMB->TotalParameterCount = cpu_to_le16(params);
3674 pSMB->ParameterCount = pSMB->TotalParameterCount;
3675 pSMB->hdr.smb_buf_length += byte_count;
3676 pSMB->ByteCount = cpu_to_le16(byte_count);
3678 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3679 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3680 cifs_stats_inc(&tcon->num_fnext);
3683 psrch_inf->endOfSearch = true;
3684 cifs_buf_release(pSMB);
3685 rc = 0; /* search probably was closed at end of search*/
3687 cFYI(1, ("FindNext returned = %d", rc));
3688 } else { /* decode response */
3689 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3692 /* BB fixme add lock for file (srch_info) struct here */
3693 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3694 psrch_inf->unicode = true;
3696 psrch_inf->unicode = false;
3697 response_data = (char *) &pSMBr->hdr.Protocol +
3698 le16_to_cpu(pSMBr->t2.ParameterOffset);
3699 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3700 response_data = (char *)&pSMBr->hdr.Protocol +
3701 le16_to_cpu(pSMBr->t2.DataOffset);
3702 if (psrch_inf->smallBuf)
3703 cifs_small_buf_release(
3704 psrch_inf->ntwrk_buf_start);
3706 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3707 psrch_inf->srch_entries_start = response_data;
3708 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3709 psrch_inf->smallBuf = 0;
3710 if (parms->EndofSearch)
3711 psrch_inf->endOfSearch = true;
3713 psrch_inf->endOfSearch = false;
3714 psrch_inf->entries_in_buffer =
3715 le16_to_cpu(parms->SearchCount);
3716 psrch_inf->index_of_last_entry +=
3717 psrch_inf->entries_in_buffer;
3718 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3719 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3721 /* BB fixme add unlock here */
3726 /* BB On error, should we leave previous search buf (and count and
3727 last entry fields) intact or free the previous one? */
3729 /* Note: On -EAGAIN error only caller can retry on handle based calls
3730 since file handle passed in no longer valid */
3733 cifs_buf_release(pSMB);
3738 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3739 const __u16 searchHandle)
3742 FINDCLOSE_REQ *pSMB = NULL;
3744 cFYI(1, ("In CIFSSMBFindClose"));
3745 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3747 /* no sense returning error if session restarted
3748 as file handle has been closed */
3754 pSMB->FileID = searchHandle;
3755 pSMB->ByteCount = 0;
3756 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3758 cERROR(1, ("Send error in FindClose = %d", rc));
3760 cifs_stats_inc(&tcon->num_fclose);
3762 /* Since session is dead, search handle closed on server already */
3770 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3771 const unsigned char *searchName,
3772 __u64 *inode_number,
3773 const struct nls_table *nls_codepage, int remap)
3776 TRANSACTION2_QPI_REQ *pSMB = NULL;
3777 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3778 int name_len, bytes_returned;
3779 __u16 params, byte_count;
3781 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3785 GetInodeNumberRetry:
3786 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3791 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3793 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3794 PATH_MAX, nls_codepage, remap);
3795 name_len++; /* trailing null */
3797 } else { /* BB improve the check for buffer overruns BB */
3798 name_len = strnlen(searchName, PATH_MAX);
3799 name_len++; /* trailing null */
3800 strncpy(pSMB->FileName, searchName, name_len);
3803 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3804 pSMB->TotalDataCount = 0;
3805 pSMB->MaxParameterCount = cpu_to_le16(2);
3806 /* BB find exact max data count below from sess structure BB */
3807 pSMB->MaxDataCount = cpu_to_le16(4000);
3808 pSMB->MaxSetupCount = 0;
3812 pSMB->Reserved2 = 0;
3813 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3814 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3815 pSMB->DataCount = 0;
3816 pSMB->DataOffset = 0;
3817 pSMB->SetupCount = 1;
3818 pSMB->Reserved3 = 0;
3819 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3820 byte_count = params + 1 /* pad */ ;
3821 pSMB->TotalParameterCount = cpu_to_le16(params);
3822 pSMB->ParameterCount = pSMB->TotalParameterCount;
3823 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3824 pSMB->Reserved4 = 0;
3825 pSMB->hdr.smb_buf_length += byte_count;
3826 pSMB->ByteCount = cpu_to_le16(byte_count);
3828 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3829 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3831 cFYI(1, ("error %d in QueryInternalInfo", rc));
3833 /* decode response */
3834 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3835 if (rc || (pSMBr->ByteCount < 2))
3836 /* BB also check enough total bytes returned */
3837 /* If rc should we check for EOPNOSUPP and
3838 disable the srvino flag? or in caller? */
3839 rc = -EIO; /* bad smb */
3841 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3842 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3843 struct file_internal_info *pfinfo;
3844 /* BB Do we need a cast or hash here ? */
3846 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3848 goto GetInodeNumOut;
3850 pfinfo = (struct file_internal_info *)
3851 (data_offset + (char *) &pSMBr->hdr.Protocol);
3852 *inode_number = pfinfo->UniqueId;
3856 cifs_buf_release(pSMB);
3858 goto GetInodeNumberRetry;
3863 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3864 const unsigned char *searchName,
3865 unsigned char **targetUNCs,
3866 unsigned int *number_of_UNC_in_array,
3867 const struct nls_table *nls_codepage, int remap)
3869 /* TRANS2_GET_DFS_REFERRAL */
3870 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3871 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3872 struct dfs_referral_level_3 *referrals = NULL;
3878 __u16 params, byte_count;
3879 *number_of_UNC_in_array = 0;
3882 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3886 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3891 /* server pointer checked in called function,
3892 but should never be null here anyway */
3893 pSMB->hdr.Mid = GetNextMid(ses->server);
3894 pSMB->hdr.Tid = ses->ipc_tid;
3895 pSMB->hdr.Uid = ses->Suid;
3896 if (ses->capabilities & CAP_STATUS32)
3897 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3898 if (ses->capabilities & CAP_DFS)
3899 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3901 if (ses->capabilities & CAP_UNICODE) {
3902 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3904 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3905 searchName, PATH_MAX, nls_codepage, remap);
3906 name_len++; /* trailing null */
3908 } else { /* BB improve the check for buffer overruns BB */
3909 name_len = strnlen(searchName, PATH_MAX);
3910 name_len++; /* trailing null */
3911 strncpy(pSMB->RequestFileName, searchName, name_len);
3915 if (ses->server->secMode &
3916 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3917 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3920 pSMB->hdr.Uid = ses->Suid;
3922 params = 2 /* level */ + name_len /*includes null */ ;
3923 pSMB->TotalDataCount = 0;
3924 pSMB->DataCount = 0;
3925 pSMB->DataOffset = 0;
3926 pSMB->MaxParameterCount = 0;
3927 /* BB find exact max SMB PDU from sess structure BB */
3928 pSMB->MaxDataCount = cpu_to_le16(4000);
3929 pSMB->MaxSetupCount = 0;
3933 pSMB->Reserved2 = 0;
3934 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3935 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3936 pSMB->SetupCount = 1;
3937 pSMB->Reserved3 = 0;
3938 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3939 byte_count = params + 3 /* pad */ ;
3940 pSMB->ParameterCount = cpu_to_le16(params);
3941 pSMB->TotalParameterCount = pSMB->ParameterCount;
3942 pSMB->MaxReferralLevel = cpu_to_le16(3);
3943 pSMB->hdr.smb_buf_length += byte_count;
3944 pSMB->ByteCount = cpu_to_le16(byte_count);
3946 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3947 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3949 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3950 } else { /* decode response */
3951 /* BB Add logic to parse referrals here */
3952 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3954 /* BB Also check if enough total bytes returned? */
3955 if (rc || (pSMBr->ByteCount < 17))
3956 rc = -EIO; /* bad smb */
3958 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3959 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3962 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3963 pSMBr->ByteCount, data_offset));
3965 (struct dfs_referral_level_3 *)
3966 (8 /* sizeof start of data block */ +
3968 (char *) &pSMBr->hdr.Protocol);
3969 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3970 "for referral one refer size: 0x%x srv "
3971 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3972 le16_to_cpu(pSMBr->NumberOfReferrals),
3973 le16_to_cpu(pSMBr->DFSFlags),
3974 le16_to_cpu(referrals->ReferralSize),
3975 le16_to_cpu(referrals->ServerType),
3976 le16_to_cpu(referrals->ReferralFlags),
3977 le16_to_cpu(referrals->TimeToLive)));
3978 /* BB This field is actually two bytes in from start of
3979 data block so we could do safety check that DataBlock
3980 begins at address of pSMBr->NumberOfReferrals */
3981 *number_of_UNC_in_array =
3982 le16_to_cpu(pSMBr->NumberOfReferrals);
3984 /* BB Fix below so can return more than one referral */
3985 if (*number_of_UNC_in_array > 1)
3986 *number_of_UNC_in_array = 1;
3988 /* get the length of the strings describing refs */
3990 for (i = 0; i < *number_of_UNC_in_array; i++) {
3991 /* make sure that DfsPathOffset not past end */
3993 le16_to_cpu(referrals->DfsPathOffset);
3994 if (offset > data_count) {
3995 /* if invalid referral, stop here and do
3996 not try to copy any more */
3997 *number_of_UNC_in_array = i;
4000 temp = ((char *)referrals) + offset;
4002 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4003 name_len += UniStrnlen((wchar_t *)temp,
4006 name_len += strnlen(temp, data_count);
4009 /* BB add check that referral pointer does
4010 not fall off end PDU */
4012 /* BB add check for name_len bigger than bcc */
4014 kmalloc(name_len+1+(*number_of_UNC_in_array),
4016 if (*targetUNCs == NULL) {
4020 /* copy the ref strings */
4021 referrals = (struct dfs_referral_level_3 *)
4022 (8 /* sizeof data hdr */ + data_offset +
4023 (char *) &pSMBr->hdr.Protocol);
4025 for (i = 0; i < *number_of_UNC_in_array; i++) {
4026 temp = ((char *)referrals) +
4027 le16_to_cpu(referrals->DfsPathOffset);
4028 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4029 cifs_strfromUCS_le(*targetUNCs,
4034 strncpy(*targetUNCs, temp, name_len);
4036 /* BB update target_uncs pointers */
4046 cifs_buf_release(pSMB);
4054 /* Query File System Info such as free space to old servers such as Win 9x */
4056 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4058 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4059 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4060 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4061 FILE_SYSTEM_ALLOC_INFO *response_data;
4063 int bytes_returned = 0;
4064 __u16 params, byte_count;
4066 cFYI(1, ("OldQFSInfo"));
4068 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4073 params = 2; /* level */
4074 pSMB->TotalDataCount = 0;
4075 pSMB->MaxParameterCount = cpu_to_le16(2);
4076 pSMB->MaxDataCount = cpu_to_le16(1000);
4077 pSMB->MaxSetupCount = 0;
4081 pSMB->Reserved2 = 0;
4082 byte_count = params + 1 /* pad */ ;
4083 pSMB->TotalParameterCount = cpu_to_le16(params);
4084 pSMB->ParameterCount = pSMB->TotalParameterCount;
4085 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4086 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4087 pSMB->DataCount = 0;
4088 pSMB->DataOffset = 0;
4089 pSMB->SetupCount = 1;
4090 pSMB->Reserved3 = 0;
4091 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4092 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4093 pSMB->hdr.smb_buf_length += byte_count;
4094 pSMB->ByteCount = cpu_to_le16(byte_count);
4096 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4097 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4099 cFYI(1, ("Send error in QFSInfo = %d", rc));
4100 } else { /* decode response */
4101 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4103 if (rc || (pSMBr->ByteCount < 18))
4104 rc = -EIO; /* bad smb */
4106 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4107 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4108 pSMBr->ByteCount, data_offset));
4110 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4111 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4113 le16_to_cpu(response_data->BytesPerSector) *
4114 le32_to_cpu(response_data->
4115 SectorsPerAllocationUnit);
4117 le32_to_cpu(response_data->TotalAllocationUnits);
4118 FSData->f_bfree = FSData->f_bavail =
4119 le32_to_cpu(response_data->FreeAllocationUnits);
4121 ("Blocks: %lld Free: %lld Block size %ld",
4122 (unsigned long long)FSData->f_blocks,
4123 (unsigned long long)FSData->f_bfree,
4127 cifs_buf_release(pSMB);
4130 goto oldQFSInfoRetry;
4136 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4138 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4139 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4140 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4141 FILE_SYSTEM_INFO *response_data;
4143 int bytes_returned = 0;
4144 __u16 params, byte_count;
4146 cFYI(1, ("In QFSInfo"));
4148 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4153 params = 2; /* level */
4154 pSMB->TotalDataCount = 0;
4155 pSMB->MaxParameterCount = cpu_to_le16(2);
4156 pSMB->MaxDataCount = cpu_to_le16(1000);
4157 pSMB->MaxSetupCount = 0;
4161 pSMB->Reserved2 = 0;
4162 byte_count = params + 1 /* pad */ ;
4163 pSMB->TotalParameterCount = cpu_to_le16(params);
4164 pSMB->ParameterCount = pSMB->TotalParameterCount;
4165 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4166 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4167 pSMB->DataCount = 0;
4168 pSMB->DataOffset = 0;
4169 pSMB->SetupCount = 1;
4170 pSMB->Reserved3 = 0;
4171 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4172 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4173 pSMB->hdr.smb_buf_length += byte_count;
4174 pSMB->ByteCount = cpu_to_le16(byte_count);
4176 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4177 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4179 cFYI(1, ("Send error in QFSInfo = %d", rc));
4180 } else { /* decode response */
4181 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4183 if (rc || (pSMBr->ByteCount < 24))
4184 rc = -EIO; /* bad smb */
4186 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4190 *) (((char *) &pSMBr->hdr.Protocol) +
4193 le32_to_cpu(response_data->BytesPerSector) *
4194 le32_to_cpu(response_data->
4195 SectorsPerAllocationUnit);
4197 le64_to_cpu(response_data->TotalAllocationUnits);
4198 FSData->f_bfree = FSData->f_bavail =
4199 le64_to_cpu(response_data->FreeAllocationUnits);
4201 ("Blocks: %lld Free: %lld Block size %ld",
4202 (unsigned long long)FSData->f_blocks,
4203 (unsigned long long)FSData->f_bfree,
4207 cifs_buf_release(pSMB);
4216 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4218 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4219 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4220 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4221 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4223 int bytes_returned = 0;
4224 __u16 params, byte_count;
4226 cFYI(1, ("In QFSAttributeInfo"));
4228 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4233 params = 2; /* level */
4234 pSMB->TotalDataCount = 0;
4235 pSMB->MaxParameterCount = cpu_to_le16(2);
4236 /* BB find exact max SMB PDU from sess structure BB */
4237 pSMB->MaxDataCount = cpu_to_le16(1000);
4238 pSMB->MaxSetupCount = 0;
4242 pSMB->Reserved2 = 0;
4243 byte_count = params + 1 /* pad */ ;
4244 pSMB->TotalParameterCount = cpu_to_le16(params);
4245 pSMB->ParameterCount = pSMB->TotalParameterCount;
4246 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4247 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4248 pSMB->DataCount = 0;
4249 pSMB->DataOffset = 0;
4250 pSMB->SetupCount = 1;
4251 pSMB->Reserved3 = 0;
4252 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4253 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4254 pSMB->hdr.smb_buf_length += byte_count;
4255 pSMB->ByteCount = cpu_to_le16(byte_count);
4257 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4258 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4260 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4261 } else { /* decode response */
4262 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4264 if (rc || (pSMBr->ByteCount < 13)) {
4265 /* BB also check if enough bytes returned */
4266 rc = -EIO; /* bad smb */
4268 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4270 (FILE_SYSTEM_ATTRIBUTE_INFO
4271 *) (((char *) &pSMBr->hdr.Protocol) +
4273 memcpy(&tcon->fsAttrInfo, response_data,
4274 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4277 cifs_buf_release(pSMB);
4280 goto QFSAttributeRetry;
4286 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4288 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4289 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4290 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4291 FILE_SYSTEM_DEVICE_INFO *response_data;
4293 int bytes_returned = 0;
4294 __u16 params, byte_count;
4296 cFYI(1, ("In QFSDeviceInfo"));
4298 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4303 params = 2; /* level */
4304 pSMB->TotalDataCount = 0;
4305 pSMB->MaxParameterCount = cpu_to_le16(2);
4306 /* BB find exact max SMB PDU from sess structure BB */
4307 pSMB->MaxDataCount = cpu_to_le16(1000);
4308 pSMB->MaxSetupCount = 0;
4312 pSMB->Reserved2 = 0;
4313 byte_count = params + 1 /* pad */ ;
4314 pSMB->TotalParameterCount = cpu_to_le16(params);
4315 pSMB->ParameterCount = pSMB->TotalParameterCount;
4316 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4317 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4319 pSMB->DataCount = 0;
4320 pSMB->DataOffset = 0;
4321 pSMB->SetupCount = 1;
4322 pSMB->Reserved3 = 0;
4323 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4324 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4325 pSMB->hdr.smb_buf_length += byte_count;
4326 pSMB->ByteCount = cpu_to_le16(byte_count);
4328 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4329 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4331 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4332 } else { /* decode response */
4333 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4335 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4336 rc = -EIO; /* bad smb */
4338 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4340 (FILE_SYSTEM_DEVICE_INFO *)
4341 (((char *) &pSMBr->hdr.Protocol) +
4343 memcpy(&tcon->fsDevInfo, response_data,
4344 sizeof(FILE_SYSTEM_DEVICE_INFO));
4347 cifs_buf_release(pSMB);
4350 goto QFSDeviceRetry;
4356 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4358 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4359 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4360 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4361 FILE_SYSTEM_UNIX_INFO *response_data;
4363 int bytes_returned = 0;
4364 __u16 params, byte_count;
4366 cFYI(1, ("In QFSUnixInfo"));
4368 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4373 params = 2; /* level */
4374 pSMB->TotalDataCount = 0;
4375 pSMB->DataCount = 0;
4376 pSMB->DataOffset = 0;
4377 pSMB->MaxParameterCount = cpu_to_le16(2);
4378 /* BB find exact max SMB PDU from sess structure BB */
4379 pSMB->MaxDataCount = cpu_to_le16(100);
4380 pSMB->MaxSetupCount = 0;
4384 pSMB->Reserved2 = 0;
4385 byte_count = params + 1 /* pad */ ;
4386 pSMB->ParameterCount = cpu_to_le16(params);
4387 pSMB->TotalParameterCount = pSMB->ParameterCount;
4388 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4389 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4390 pSMB->SetupCount = 1;
4391 pSMB->Reserved3 = 0;
4392 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4393 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4394 pSMB->hdr.smb_buf_length += byte_count;
4395 pSMB->ByteCount = cpu_to_le16(byte_count);
4397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4400 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4401 } else { /* decode response */
4402 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4404 if (rc || (pSMBr->ByteCount < 13)) {
4405 rc = -EIO; /* bad smb */
4407 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4409 (FILE_SYSTEM_UNIX_INFO
4410 *) (((char *) &pSMBr->hdr.Protocol) +
4412 memcpy(&tcon->fsUnixInfo, response_data,
4413 sizeof(FILE_SYSTEM_UNIX_INFO));
4416 cifs_buf_release(pSMB);
4426 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4428 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4429 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4430 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4432 int bytes_returned = 0;
4433 __u16 params, param_offset, offset, byte_count;
4435 cFYI(1, ("In SETFSUnixInfo"));
4437 /* BB switch to small buf init to save memory */
4438 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4443 params = 4; /* 2 bytes zero followed by info level. */
4444 pSMB->MaxSetupCount = 0;
4448 pSMB->Reserved2 = 0;
4449 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4451 offset = param_offset + params;
4453 pSMB->MaxParameterCount = cpu_to_le16(4);
4454 /* BB find exact max SMB PDU from sess structure BB */
4455 pSMB->MaxDataCount = cpu_to_le16(100);
4456 pSMB->SetupCount = 1;
4457 pSMB->Reserved3 = 0;
4458 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4459 byte_count = 1 /* pad */ + params + 12;
4461 pSMB->DataCount = cpu_to_le16(12);
4462 pSMB->ParameterCount = cpu_to_le16(params);
4463 pSMB->TotalDataCount = pSMB->DataCount;
4464 pSMB->TotalParameterCount = pSMB->ParameterCount;
4465 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4466 pSMB->DataOffset = cpu_to_le16(offset);
4470 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4473 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4474 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4475 pSMB->ClientUnixCap = cpu_to_le64(cap);
4477 pSMB->hdr.smb_buf_length += byte_count;
4478 pSMB->ByteCount = cpu_to_le16(byte_count);
4480 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4481 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4483 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4484 } else { /* decode response */
4485 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4487 rc = -EIO; /* bad smb */
4489 cifs_buf_release(pSMB);
4492 goto SETFSUnixRetry;
4500 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4501 struct kstatfs *FSData)
4503 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4504 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4505 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4506 FILE_SYSTEM_POSIX_INFO *response_data;
4508 int bytes_returned = 0;
4509 __u16 params, byte_count;
4511 cFYI(1, ("In QFSPosixInfo"));
4513 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4518 params = 2; /* level */
4519 pSMB->TotalDataCount = 0;
4520 pSMB->DataCount = 0;
4521 pSMB->DataOffset = 0;
4522 pSMB->MaxParameterCount = cpu_to_le16(2);
4523 /* BB find exact max SMB PDU from sess structure BB */
4524 pSMB->MaxDataCount = cpu_to_le16(100);
4525 pSMB->MaxSetupCount = 0;
4529 pSMB->Reserved2 = 0;
4530 byte_count = params + 1 /* pad */ ;
4531 pSMB->ParameterCount = cpu_to_le16(params);
4532 pSMB->TotalParameterCount = pSMB->ParameterCount;
4533 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4534 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4535 pSMB->SetupCount = 1;
4536 pSMB->Reserved3 = 0;
4537 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4538 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4539 pSMB->hdr.smb_buf_length += byte_count;
4540 pSMB->ByteCount = cpu_to_le16(byte_count);
4542 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4543 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4545 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4546 } else { /* decode response */
4547 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4549 if (rc || (pSMBr->ByteCount < 13)) {
4550 rc = -EIO; /* bad smb */
4552 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4554 (FILE_SYSTEM_POSIX_INFO
4555 *) (((char *) &pSMBr->hdr.Protocol) +
4558 le32_to_cpu(response_data->BlockSize);
4560 le64_to_cpu(response_data->TotalBlocks);
4562 le64_to_cpu(response_data->BlocksAvail);
4563 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4564 FSData->f_bavail = FSData->f_bfree;
4567 le64_to_cpu(response_data->UserBlocksAvail);
4569 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4571 le64_to_cpu(response_data->TotalFileNodes);
4572 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4574 le64_to_cpu(response_data->FreeFileNodes);
4577 cifs_buf_release(pSMB);
4586 /* We can not use write of zero bytes trick to
4587 set file size due to need for large file support. Also note that
4588 this SetPathInfo is preferred to SetFileInfo based method in next
4589 routine which is only needed to work around a sharing violation bug
4590 in Samba which this routine can run into */
4593 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4594 __u64 size, bool SetAllocation,
4595 const struct nls_table *nls_codepage, int remap)
4597 struct smb_com_transaction2_spi_req *pSMB = NULL;
4598 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4599 struct file_end_of_file_info *parm_data;
4602 int bytes_returned = 0;
4603 __u16 params, byte_count, data_count, param_offset, offset;
4605 cFYI(1, ("In SetEOF"));
4607 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4612 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4614 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4615 PATH_MAX, nls_codepage, remap);
4616 name_len++; /* trailing null */
4618 } else { /* BB improve the check for buffer overruns BB */
4619 name_len = strnlen(fileName, PATH_MAX);
4620 name_len++; /* trailing null */
4621 strncpy(pSMB->FileName, fileName, name_len);
4623 params = 6 + name_len;
4624 data_count = sizeof(struct file_end_of_file_info);
4625 pSMB->MaxParameterCount = cpu_to_le16(2);
4626 pSMB->MaxDataCount = cpu_to_le16(4100);
4627 pSMB->MaxSetupCount = 0;
4631 pSMB->Reserved2 = 0;
4632 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4633 InformationLevel) - 4;
4634 offset = param_offset + params;
4635 if (SetAllocation) {
4636 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4637 pSMB->InformationLevel =
4638 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4640 pSMB->InformationLevel =
4641 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4642 } else /* Set File Size */ {
4643 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4644 pSMB->InformationLevel =
4645 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4647 pSMB->InformationLevel =
4648 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4652 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4654 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4655 pSMB->DataOffset = cpu_to_le16(offset);
4656 pSMB->SetupCount = 1;
4657 pSMB->Reserved3 = 0;
4658 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4659 byte_count = 3 /* pad */ + params + data_count;
4660 pSMB->DataCount = cpu_to_le16(data_count);
4661 pSMB->TotalDataCount = pSMB->DataCount;
4662 pSMB->ParameterCount = cpu_to_le16(params);
4663 pSMB->TotalParameterCount = pSMB->ParameterCount;
4664 pSMB->Reserved4 = 0;
4665 pSMB->hdr.smb_buf_length += byte_count;
4666 parm_data->FileSize = cpu_to_le64(size);
4667 pSMB->ByteCount = cpu_to_le16(byte_count);
4668 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4669 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4671 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4673 cifs_buf_release(pSMB);
4682 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4683 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4685 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4687 struct file_end_of_file_info *parm_data;
4689 __u16 params, param_offset, offset, byte_count, count;
4691 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4693 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4698 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4699 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4702 pSMB->MaxSetupCount = 0;
4706 pSMB->Reserved2 = 0;
4707 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4708 offset = param_offset + params;
4710 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4712 count = sizeof(struct file_end_of_file_info);
4713 pSMB->MaxParameterCount = cpu_to_le16(2);
4714 /* BB find exact max SMB PDU from sess structure BB */
4715 pSMB->MaxDataCount = cpu_to_le16(1000);
4716 pSMB->SetupCount = 1;
4717 pSMB->Reserved3 = 0;
4718 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4719 byte_count = 3 /* pad */ + params + count;
4720 pSMB->DataCount = cpu_to_le16(count);
4721 pSMB->ParameterCount = cpu_to_le16(params);
4722 pSMB->TotalDataCount = pSMB->DataCount;
4723 pSMB->TotalParameterCount = pSMB->ParameterCount;
4724 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4726 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4728 pSMB->DataOffset = cpu_to_le16(offset);
4729 parm_data->FileSize = cpu_to_le64(size);
4731 if (SetAllocation) {
4732 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4733 pSMB->InformationLevel =
4734 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4736 pSMB->InformationLevel =
4737 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4738 } else /* Set File Size */ {
4739 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4740 pSMB->InformationLevel =
4741 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4743 pSMB->InformationLevel =
4744 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4746 pSMB->Reserved4 = 0;
4747 pSMB->hdr.smb_buf_length += byte_count;
4748 pSMB->ByteCount = cpu_to_le16(byte_count);
4749 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4752 ("Send error in SetFileInfo (SetFileSize) = %d",
4756 /* Note: On -EAGAIN error only caller can retry on handle based calls
4757 since file handle passed in no longer valid */
4762 /* Some legacy servers such as NT4 require that the file times be set on
4763 an open handle, rather than by pathname - this is awkward due to
4764 potential access conflicts on the open, but it is unavoidable for these
4765 old servers since the only other choice is to go from 100 nanosecond DCE
4766 time and resort to the original setpathinfo level which takes the ancient
4767 DOS time format with 2 second granularity */
4769 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4770 const FILE_BASIC_INFO *data, __u16 fid)
4772 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4775 __u16 params, param_offset, offset, byte_count, count;
4777 cFYI(1, ("Set Times (via SetFileInfo)"));
4778 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4783 /* At this point there is no need to override the current pid
4784 with the pid of the opener, but that could change if we someday
4785 use an existing handle (rather than opening one on the fly) */
4786 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4787 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4790 pSMB->MaxSetupCount = 0;
4794 pSMB->Reserved2 = 0;
4795 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4796 offset = param_offset + params;
4798 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4800 count = sizeof(FILE_BASIC_INFO);
4801 pSMB->MaxParameterCount = cpu_to_le16(2);
4802 /* BB find max SMB PDU from sess */
4803 pSMB->MaxDataCount = cpu_to_le16(1000);
4804 pSMB->SetupCount = 1;
4805 pSMB->Reserved3 = 0;
4806 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4807 byte_count = 3 /* pad */ + params + count;
4808 pSMB->DataCount = cpu_to_le16(count);
4809 pSMB->ParameterCount = cpu_to_le16(params);
4810 pSMB->TotalDataCount = pSMB->DataCount;
4811 pSMB->TotalParameterCount = pSMB->ParameterCount;
4812 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4813 pSMB->DataOffset = cpu_to_le16(offset);
4815 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4816 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4818 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4819 pSMB->Reserved4 = 0;
4820 pSMB->hdr.smb_buf_length += byte_count;
4821 pSMB->ByteCount = cpu_to_le16(byte_count);
4822 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4823 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4825 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4827 /* Note: On -EAGAIN error only caller can retry on handle based calls
4828 since file handle passed in no longer valid */
4835 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4836 const FILE_BASIC_INFO *data,
4837 const struct nls_table *nls_codepage, int remap)
4839 TRANSACTION2_SPI_REQ *pSMB = NULL;
4840 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4843 int bytes_returned = 0;
4845 __u16 params, param_offset, offset, byte_count, count;
4847 cFYI(1, ("In SetTimes"));
4850 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4855 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4857 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4858 PATH_MAX, nls_codepage, remap);
4859 name_len++; /* trailing null */
4861 } else { /* BB improve the check for buffer overruns BB */
4862 name_len = strnlen(fileName, PATH_MAX);
4863 name_len++; /* trailing null */
4864 strncpy(pSMB->FileName, fileName, name_len);
4867 params = 6 + name_len;
4868 count = sizeof(FILE_BASIC_INFO);
4869 pSMB->MaxParameterCount = cpu_to_le16(2);
4870 /* BB find max SMB PDU from sess structure BB */
4871 pSMB->MaxDataCount = cpu_to_le16(1000);
4872 pSMB->MaxSetupCount = 0;
4876 pSMB->Reserved2 = 0;
4877 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4878 InformationLevel) - 4;
4879 offset = param_offset + params;
4880 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4881 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4882 pSMB->DataOffset = cpu_to_le16(offset);
4883 pSMB->SetupCount = 1;
4884 pSMB->Reserved3 = 0;
4885 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4886 byte_count = 3 /* pad */ + params + count;
4888 pSMB->DataCount = cpu_to_le16(count);
4889 pSMB->ParameterCount = cpu_to_le16(params);
4890 pSMB->TotalDataCount = pSMB->DataCount;
4891 pSMB->TotalParameterCount = pSMB->ParameterCount;
4892 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4893 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4895 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4896 pSMB->Reserved4 = 0;
4897 pSMB->hdr.smb_buf_length += byte_count;
4898 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4899 pSMB->ByteCount = cpu_to_le16(byte_count);
4900 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4901 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4903 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4905 cifs_buf_release(pSMB);
4913 /* Can not be used to set time stamps yet (due to old DOS time format) */
4914 /* Can be used to set attributes */
4915 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4916 handling it anyway and NT4 was what we thought it would be needed for
4917 Do not delete it until we prove whether needed for Win9x though */
4919 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4920 __u16 dos_attrs, const struct nls_table *nls_codepage)
4922 SETATTR_REQ *pSMB = NULL;
4923 SETATTR_RSP *pSMBr = NULL;
4928 cFYI(1, ("In SetAttrLegacy"));
4931 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4938 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4939 PATH_MAX, nls_codepage);
4940 name_len++; /* trailing null */
4942 } else { /* BB improve the check for buffer overruns BB */
4943 name_len = strnlen(fileName, PATH_MAX);
4944 name_len++; /* trailing null */
4945 strncpy(pSMB->fileName, fileName, name_len);
4947 pSMB->attr = cpu_to_le16(dos_attrs);
4948 pSMB->BufferFormat = 0x04;
4949 pSMB->hdr.smb_buf_length += name_len + 1;
4950 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4951 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4952 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4954 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4956 cifs_buf_release(pSMB);
4959 goto SetAttrLgcyRetry;
4963 #endif /* temporarily unneeded SetAttr legacy function */
4966 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4967 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4968 dev_t device, const struct nls_table *nls_codepage,
4971 TRANSACTION2_SPI_REQ *pSMB = NULL;
4972 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4975 int bytes_returned = 0;
4976 FILE_UNIX_BASIC_INFO *data_offset;
4977 __u16 params, param_offset, offset, count, byte_count;
4979 cFYI(1, ("In SetUID/GID/Mode"));
4981 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4986 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4988 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4989 PATH_MAX, nls_codepage, remap);
4990 name_len++; /* trailing null */
4992 } else { /* BB improve the check for buffer overruns BB */
4993 name_len = strnlen(fileName, PATH_MAX);
4994 name_len++; /* trailing null */
4995 strncpy(pSMB->FileName, fileName, name_len);
4998 params = 6 + name_len;
4999 count = sizeof(FILE_UNIX_BASIC_INFO);
5000 pSMB->MaxParameterCount = cpu_to_le16(2);
5001 /* BB find max SMB PDU from sess structure BB */
5002 pSMB->MaxDataCount = cpu_to_le16(1000);
5003 pSMB->MaxSetupCount = 0;
5007 pSMB->Reserved2 = 0;
5008 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5009 InformationLevel) - 4;
5010 offset = param_offset + params;
5012 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5014 memset(data_offset, 0, count);
5015 pSMB->DataOffset = cpu_to_le16(offset);
5016 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5017 pSMB->SetupCount = 1;
5018 pSMB->Reserved3 = 0;
5019 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5020 byte_count = 3 /* pad */ + params + count;
5021 pSMB->ParameterCount = cpu_to_le16(params);
5022 pSMB->DataCount = cpu_to_le16(count);
5023 pSMB->TotalParameterCount = pSMB->ParameterCount;
5024 pSMB->TotalDataCount = pSMB->DataCount;
5025 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5026 pSMB->Reserved4 = 0;
5027 pSMB->hdr.smb_buf_length += byte_count;
5028 /* Samba server ignores set of file size to zero due to bugs in some
5029 older clients, but we should be precise - we use SetFileSize to
5030 set file size and do not want to truncate file size to zero
5031 accidently as happened on one Samba server beta by putting
5032 zero instead of -1 here */
5033 data_offset->EndOfFile = NO_CHANGE_64;
5034 data_offset->NumOfBytes = NO_CHANGE_64;
5035 data_offset->LastStatusChange = NO_CHANGE_64;
5036 data_offset->LastAccessTime = NO_CHANGE_64;
5037 data_offset->LastModificationTime = NO_CHANGE_64;
5038 data_offset->Uid = cpu_to_le64(uid);
5039 data_offset->Gid = cpu_to_le64(gid);
5040 /* better to leave device as zero when it is */
5041 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5042 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5043 data_offset->Permissions = cpu_to_le64(mode);
5046 data_offset->Type = cpu_to_le32(UNIX_FILE);
5047 else if (S_ISDIR(mode))
5048 data_offset->Type = cpu_to_le32(UNIX_DIR);
5049 else if (S_ISLNK(mode))
5050 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5051 else if (S_ISCHR(mode))
5052 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5053 else if (S_ISBLK(mode))
5054 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5055 else if (S_ISFIFO(mode))
5056 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5057 else if (S_ISSOCK(mode))
5058 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5061 pSMB->ByteCount = cpu_to_le16(byte_count);
5062 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5063 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5065 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5068 cifs_buf_release(pSMB);
5074 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5075 const int notify_subdirs, const __u16 netfid,
5076 __u32 filter, struct file *pfile, int multishot,
5077 const struct nls_table *nls_codepage)
5080 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5081 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5082 struct dir_notify_req *dnotify_req;
5085 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5086 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5091 pSMB->TotalParameterCount = 0 ;
5092 pSMB->TotalDataCount = 0;
5093 pSMB->MaxParameterCount = cpu_to_le32(2);
5094 /* BB find exact data count max from sess structure BB */
5095 pSMB->MaxDataCount = 0; /* same in little endian or be */
5096 /* BB VERIFY verify which is correct for above BB */
5097 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5098 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5100 pSMB->MaxSetupCount = 4;
5102 pSMB->ParameterOffset = 0;
5103 pSMB->DataCount = 0;
5104 pSMB->DataOffset = 0;
5105 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5106 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5107 pSMB->ParameterCount = pSMB->TotalParameterCount;
5109 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5110 pSMB->Reserved2 = 0;
5111 pSMB->CompletionFilter = cpu_to_le32(filter);
5112 pSMB->Fid = netfid; /* file handle always le */
5113 pSMB->ByteCount = 0;
5115 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5116 (struct smb_hdr *)pSMBr, &bytes_returned,
5119 cFYI(1, ("Error in Notify = %d", rc));
5121 /* Add file to outstanding requests */
5122 /* BB change to kmem cache alloc */
5123 dnotify_req = kmalloc(
5124 sizeof(struct dir_notify_req),
5127 dnotify_req->Pid = pSMB->hdr.Pid;
5128 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5129 dnotify_req->Mid = pSMB->hdr.Mid;
5130 dnotify_req->Tid = pSMB->hdr.Tid;
5131 dnotify_req->Uid = pSMB->hdr.Uid;
5132 dnotify_req->netfid = netfid;
5133 dnotify_req->pfile = pfile;
5134 dnotify_req->filter = filter;
5135 dnotify_req->multishot = multishot;
5136 spin_lock(&GlobalMid_Lock);
5137 list_add_tail(&dnotify_req->lhead,
5138 &GlobalDnotifyReqList);
5139 spin_unlock(&GlobalMid_Lock);
5143 cifs_buf_release(pSMB);
5146 #ifdef CONFIG_CIFS_XATTR
5148 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5149 const unsigned char *searchName,
5150 char *EAData, size_t buf_size,
5151 const struct nls_table *nls_codepage, int remap)
5153 /* BB assumes one setup word */
5154 TRANSACTION2_QPI_REQ *pSMB = NULL;
5155 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5159 struct fea *temp_fea;
5161 __u16 params, byte_count;
5163 cFYI(1, ("In Query All EAs path %s", searchName));
5165 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5170 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5172 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5173 PATH_MAX, nls_codepage, remap);
5174 name_len++; /* trailing null */
5176 } else { /* BB improve the check for buffer overruns BB */
5177 name_len = strnlen(searchName, PATH_MAX);
5178 name_len++; /* trailing null */
5179 strncpy(pSMB->FileName, searchName, name_len);
5182 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5183 pSMB->TotalDataCount = 0;
5184 pSMB->MaxParameterCount = cpu_to_le16(2);
5185 /* BB find exact max SMB PDU from sess structure BB */
5186 pSMB->MaxDataCount = cpu_to_le16(4000);
5187 pSMB->MaxSetupCount = 0;
5191 pSMB->Reserved2 = 0;
5192 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5193 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5194 pSMB->DataCount = 0;
5195 pSMB->DataOffset = 0;
5196 pSMB->SetupCount = 1;
5197 pSMB->Reserved3 = 0;
5198 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5199 byte_count = params + 1 /* pad */ ;
5200 pSMB->TotalParameterCount = cpu_to_le16(params);
5201 pSMB->ParameterCount = pSMB->TotalParameterCount;
5202 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5203 pSMB->Reserved4 = 0;
5204 pSMB->hdr.smb_buf_length += byte_count;
5205 pSMB->ByteCount = cpu_to_le16(byte_count);
5207 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5208 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5210 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5211 } else { /* decode response */
5212 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5214 /* BB also check enough total bytes returned */
5215 /* BB we need to improve the validity checking
5216 of these trans2 responses */
5217 if (rc || (pSMBr->ByteCount < 4))
5218 rc = -EIO; /* bad smb */
5219 /* else if (pFindData){
5220 memcpy((char *) pFindData,
5221 (char *) &pSMBr->hdr.Protocol +
5224 /* check that length of list is not more than bcc */
5225 /* check that each entry does not go beyond length
5227 /* check that each element of each entry does not
5228 go beyond end of list */
5229 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5230 struct fealist *ea_response_data;
5232 /* validate_trans2_offsets() */
5233 /* BB check if start of smb + data_offset > &bcc+ bcc */
5234 ea_response_data = (struct fealist *)
5235 (((char *) &pSMBr->hdr.Protocol) +
5237 name_len = le32_to_cpu(ea_response_data->list_len);
5238 cFYI(1, ("ea length %d", name_len));
5239 if (name_len <= 8) {
5240 /* returned EA size zeroed at top of function */
5241 cFYI(1, ("empty EA list returned from server"));
5243 /* account for ea list len */
5245 temp_fea = ea_response_data->list;
5246 temp_ptr = (char *)temp_fea;
5247 while (name_len > 0) {
5251 rc += temp_fea->name_len;
5252 /* account for prefix user. and trailing null */
5254 if (rc < (int)buf_size) {
5255 memcpy(EAData, "user.", 5);
5257 memcpy(EAData, temp_ptr,
5258 temp_fea->name_len);
5259 EAData += temp_fea->name_len;
5260 /* null terminate name */
5262 EAData = EAData + 1;
5263 } else if (buf_size == 0) {
5264 /* skip copy - calc size only */
5266 /* stop before overrun buffer */
5270 name_len -= temp_fea->name_len;
5271 temp_ptr += temp_fea->name_len;
5272 /* account for trailing null */
5276 le16_to_cpu(temp_fea->value_len);
5277 name_len -= value_len;
5278 temp_ptr += value_len;
5279 /* BB check that temp_ptr is still
5282 /* no trailing null to account for
5284 /* go on to next EA */
5285 temp_fea = (struct fea *)temp_ptr;
5291 cifs_buf_release(pSMB);
5298 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5299 const unsigned char *searchName, const unsigned char *ea_name,
5300 unsigned char *ea_value, size_t buf_size,
5301 const struct nls_table *nls_codepage, int remap)
5303 TRANSACTION2_QPI_REQ *pSMB = NULL;
5304 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5308 struct fea *temp_fea;
5310 __u16 params, byte_count;
5312 cFYI(1, ("In Query EA path %s", searchName));
5314 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5319 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5321 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5322 PATH_MAX, nls_codepage, remap);
5323 name_len++; /* trailing null */
5325 } else { /* BB improve the check for buffer overruns BB */
5326 name_len = strnlen(searchName, PATH_MAX);
5327 name_len++; /* trailing null */
5328 strncpy(pSMB->FileName, searchName, name_len);
5331 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5332 pSMB->TotalDataCount = 0;
5333 pSMB->MaxParameterCount = cpu_to_le16(2);
5334 /* BB find exact max SMB PDU from sess structure BB */
5335 pSMB->MaxDataCount = cpu_to_le16(4000);
5336 pSMB->MaxSetupCount = 0;
5340 pSMB->Reserved2 = 0;
5341 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5342 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5343 pSMB->DataCount = 0;
5344 pSMB->DataOffset = 0;
5345 pSMB->SetupCount = 1;
5346 pSMB->Reserved3 = 0;
5347 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5348 byte_count = params + 1 /* pad */ ;
5349 pSMB->TotalParameterCount = cpu_to_le16(params);
5350 pSMB->ParameterCount = pSMB->TotalParameterCount;
5351 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5352 pSMB->Reserved4 = 0;
5353 pSMB->hdr.smb_buf_length += byte_count;
5354 pSMB->ByteCount = cpu_to_le16(byte_count);
5356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5359 cFYI(1, ("Send error in Query EA = %d", rc));
5360 } else { /* decode response */
5361 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5363 /* BB also check enough total bytes returned */
5364 /* BB we need to improve the validity checking
5365 of these trans2 responses */
5366 if (rc || (pSMBr->ByteCount < 4))
5367 rc = -EIO; /* bad smb */
5368 /* else if (pFindData){
5369 memcpy((char *) pFindData,
5370 (char *) &pSMBr->hdr.Protocol +
5373 /* check that length of list is not more than bcc */
5374 /* check that each entry does not go beyond length
5376 /* check that each element of each entry does not
5377 go beyond end of list */
5378 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5379 struct fealist *ea_response_data;
5381 /* validate_trans2_offsets() */
5382 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5383 ea_response_data = (struct fealist *)
5384 (((char *) &pSMBr->hdr.Protocol) +
5386 name_len = le32_to_cpu(ea_response_data->list_len);
5387 cFYI(1, ("ea length %d", name_len));
5388 if (name_len <= 8) {
5389 /* returned EA size zeroed at top of function */
5390 cFYI(1, ("empty EA list returned from server"));
5392 /* account for ea list len */
5394 temp_fea = ea_response_data->list;
5395 temp_ptr = (char *)temp_fea;
5396 /* loop through checking if we have a matching
5397 name and then return the associated value */
5398 while (name_len > 0) {
5403 le16_to_cpu(temp_fea->value_len);
5404 /* BB validate that value_len falls within SMB,
5405 even though maximum for name_len is 255 */
5406 if (memcmp(temp_fea->name, ea_name,
5407 temp_fea->name_len) == 0) {
5410 /* account for prefix user. and trailing null */
5411 if (rc <= (int)buf_size) {
5413 temp_fea->name+temp_fea->name_len+1,
5415 /* ea values, unlike ea
5418 } else if (buf_size == 0) {
5419 /* skip copy - calc size only */
5421 /* stop before overrun buffer */
5426 name_len -= temp_fea->name_len;
5427 temp_ptr += temp_fea->name_len;
5428 /* account for trailing null */
5431 name_len -= value_len;
5432 temp_ptr += value_len;
5433 /* No trailing null to account for in
5434 value_len. Go on to next EA */
5435 temp_fea = (struct fea *)temp_ptr;
5441 cifs_buf_release(pSMB);
5449 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5450 const char *ea_name, const void *ea_value,
5451 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5454 struct smb_com_transaction2_spi_req *pSMB = NULL;
5455 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5456 struct fealist *parm_data;
5459 int bytes_returned = 0;
5460 __u16 params, param_offset, byte_count, offset, count;
5462 cFYI(1, ("In SetEA"));
5464 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5469 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5471 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5472 PATH_MAX, nls_codepage, remap);
5473 name_len++; /* trailing null */
5475 } else { /* BB improve the check for buffer overruns BB */
5476 name_len = strnlen(fileName, PATH_MAX);
5477 name_len++; /* trailing null */
5478 strncpy(pSMB->FileName, fileName, name_len);
5481 params = 6 + name_len;
5483 /* done calculating parms using name_len of file name,
5484 now use name_len to calculate length of ea name
5485 we are going to create in the inode xattrs */
5486 if (ea_name == NULL)
5489 name_len = strnlen(ea_name, 255);
5491 count = sizeof(*parm_data) + ea_value_len + name_len;
5492 pSMB->MaxParameterCount = cpu_to_le16(2);
5493 /* BB find max SMB PDU from sess */
5494 pSMB->MaxDataCount = cpu_to_le16(1000);
5495 pSMB->MaxSetupCount = 0;
5499 pSMB->Reserved2 = 0;
5500 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5501 InformationLevel) - 4;
5502 offset = param_offset + params;
5503 pSMB->InformationLevel =
5504 cpu_to_le16(SMB_SET_FILE_EA);
5507 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5509 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5510 pSMB->DataOffset = cpu_to_le16(offset);
5511 pSMB->SetupCount = 1;
5512 pSMB->Reserved3 = 0;
5513 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5514 byte_count = 3 /* pad */ + params + count;
5515 pSMB->DataCount = cpu_to_le16(count);
5516 parm_data->list_len = cpu_to_le32(count);
5517 parm_data->list[0].EA_flags = 0;
5518 /* we checked above that name len is less than 255 */
5519 parm_data->list[0].name_len = (__u8)name_len;
5520 /* EA names are always ASCII */
5522 strncpy(parm_data->list[0].name, ea_name, name_len);
5523 parm_data->list[0].name[name_len] = 0;
5524 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5525 /* caller ensures that ea_value_len is less than 64K but
5526 we need to ensure that it fits within the smb */
5528 /*BB add length check to see if it would fit in
5529 negotiated SMB buffer size BB */
5530 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5532 memcpy(parm_data->list[0].name+name_len+1,
5533 ea_value, ea_value_len);
5535 pSMB->TotalDataCount = pSMB->DataCount;
5536 pSMB->ParameterCount = cpu_to_le16(params);
5537 pSMB->TotalParameterCount = pSMB->ParameterCount;
5538 pSMB->Reserved4 = 0;
5539 pSMB->hdr.smb_buf_length += byte_count;
5540 pSMB->ByteCount = cpu_to_le16(byte_count);
5541 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5542 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5544 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5546 cifs_buf_release(pSMB);