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 */
144 if ((tcon->retry == FALSE) ||
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 */
292 if ((tcon->retry == FALSE) ||
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 ((omode & S_IWUGO) == 0)
1228 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1229 /* Above line causes problems due to vfs splitting create into two
1230 pieces - need to set mode after file created not while it is
1234 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1235 CREATE_OPTIONS_MASK); */
1236 /* BB FIXME END BB */
1238 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1239 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1241 pSMB->hdr.smb_buf_length += count;
1243 pSMB->ByteCount = cpu_to_le16(count);
1244 /* long_op set to 1 to allow for oplock break timeouts */
1245 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1246 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1247 cifs_stats_inc(&tcon->num_opens);
1249 cFYI(1, ("Error in Open = %d", rc));
1251 /* BB verify if wct == 15 */
1253 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1255 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1256 /* Let caller know file was created so we can set the mode. */
1257 /* Do we care about the CreateAction in any other cases? */
1259 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1260 *pOplock |= CIFS_CREATE_ACTION; */
1264 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1265 pfile_info->LastAccessTime = 0; /* BB fixme */
1266 pfile_info->LastWriteTime = 0; /* BB fixme */
1267 pfile_info->ChangeTime = 0; /* BB fixme */
1268 pfile_info->Attributes =
1269 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1270 /* the file_info buf is endian converted by caller */
1271 pfile_info->AllocationSize =
1272 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1273 pfile_info->EndOfFile = pfile_info->AllocationSize;
1274 pfile_info->NumberOfLinks = cpu_to_le32(1);
1278 cifs_buf_release(pSMB);
1285 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1286 const char *fileName, const int openDisposition,
1287 const int access_flags, const int create_options, __u16 *netfid,
1288 int *pOplock, FILE_ALL_INFO *pfile_info,
1289 const struct nls_table *nls_codepage, int remap)
1292 OPEN_REQ *pSMB = NULL;
1293 OPEN_RSP *pSMBr = NULL;
1299 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1304 pSMB->AndXCommand = 0xFF; /* none */
1306 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1307 count = 1; /* account for one byte pad to word boundary */
1309 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1310 fileName, PATH_MAX, nls_codepage, remap);
1311 name_len++; /* trailing null */
1313 pSMB->NameLength = cpu_to_le16(name_len);
1314 } else { /* BB improve check for buffer overruns BB */
1315 count = 0; /* no pad */
1316 name_len = strnlen(fileName, PATH_MAX);
1317 name_len++; /* trailing null */
1318 pSMB->NameLength = cpu_to_le16(name_len);
1319 strncpy(pSMB->fileName, fileName, name_len);
1321 if (*pOplock & REQ_OPLOCK)
1322 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1323 else if (*pOplock & REQ_BATCHOPLOCK)
1324 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1325 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1326 pSMB->AllocationSize = 0;
1327 /* set file as system file if special file such
1328 as fifo and server expecting SFU style and
1329 no Unix extensions */
1330 if (create_options & CREATE_OPTION_SPECIAL)
1331 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1333 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1334 /* XP does not handle ATTR_POSIX_SEMANTICS */
1335 /* but it helps speed up case sensitive checks for other
1336 servers such as Samba */
1337 if (tcon->ses->capabilities & CAP_UNIX)
1338 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1340 /* if ((omode & S_IWUGO) == 0)
1341 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1342 /* Above line causes problems due to vfs splitting create into two
1343 pieces - need to set mode after file created not while it is
1345 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1346 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1347 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1348 /* BB Expirement with various impersonation levels and verify */
1349 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1350 pSMB->SecurityFlags =
1351 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1354 pSMB->hdr.smb_buf_length += count;
1356 pSMB->ByteCount = cpu_to_le16(count);
1357 /* long_op set to 1 to allow for oplock break timeouts */
1358 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1359 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1360 cifs_stats_inc(&tcon->num_opens);
1362 cFYI(1, ("Error in Open = %d", rc));
1364 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1365 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1366 /* Let caller know file was created so we can set the mode. */
1367 /* Do we care about the CreateAction in any other cases? */
1368 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1369 *pOplock |= CIFS_CREATE_ACTION;
1371 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1372 36 /* CreationTime to Attributes */);
1373 /* the file_info buf is endian converted by caller */
1374 pfile_info->AllocationSize = pSMBr->AllocationSize;
1375 pfile_info->EndOfFile = pSMBr->EndOfFile;
1376 pfile_info->NumberOfLinks = cpu_to_le32(1);
1380 cifs_buf_release(pSMB);
1387 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1388 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1389 char **buf, int *pbuf_type)
1392 READ_REQ *pSMB = NULL;
1393 READ_RSP *pSMBr = NULL;
1394 char *pReadData = NULL;
1396 int resp_buf_type = 0;
1399 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1400 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1403 wct = 10; /* old style read */
1406 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1410 /* tcon and ses pointer are checked in smb_init */
1411 if (tcon->ses->server == NULL)
1412 return -ECONNABORTED;
1414 pSMB->AndXCommand = 0xFF; /* none */
1416 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1418 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1419 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1422 pSMB->Remaining = 0;
1423 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1424 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1426 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1428 /* old style read */
1429 struct smb_com_readx_req *pSMBW =
1430 (struct smb_com_readx_req *)pSMB;
1431 pSMBW->ByteCount = 0;
1434 iov[0].iov_base = (char *)pSMB;
1435 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1436 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1437 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1438 cifs_stats_inc(&tcon->num_reads);
1439 pSMBr = (READ_RSP *)iov[0].iov_base;
1441 cERROR(1, ("Send error in read = %d", rc));
1443 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1444 data_length = data_length << 16;
1445 data_length += le16_to_cpu(pSMBr->DataLength);
1446 *nbytes = data_length;
1448 /*check that DataLength would not go beyond end of SMB */
1449 if ((data_length > CIFSMaxBufSize)
1450 || (data_length > count)) {
1451 cFYI(1, ("bad length %d for count %d",
1452 data_length, count));
1456 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1457 le16_to_cpu(pSMBr->DataOffset);
1458 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1459 cERROR(1,("Faulting on read rc = %d",rc));
1461 }*/ /* can not use copy_to_user when using page cache*/
1463 memcpy(*buf, pReadData, data_length);
1467 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1469 if (resp_buf_type == CIFS_SMALL_BUFFER)
1470 cifs_small_buf_release(iov[0].iov_base);
1471 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1472 cifs_buf_release(iov[0].iov_base);
1473 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1474 /* return buffer to caller to free */
1475 *buf = iov[0].iov_base;
1476 if (resp_buf_type == CIFS_SMALL_BUFFER)
1477 *pbuf_type = CIFS_SMALL_BUFFER;
1478 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1479 *pbuf_type = CIFS_LARGE_BUFFER;
1480 } /* else no valid buffer on return - leave as null */
1482 /* Note: On -EAGAIN error only caller can retry on handle based calls
1483 since file handle passed in no longer valid */
1489 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1490 const int netfid, const unsigned int count,
1491 const __u64 offset, unsigned int *nbytes, const char *buf,
1492 const char __user *ubuf, const int long_op)
1495 WRITE_REQ *pSMB = NULL;
1496 WRITE_RSP *pSMBr = NULL;
1497 int bytes_returned, wct;
1501 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1502 if (tcon->ses == NULL)
1503 return -ECONNABORTED;
1505 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1510 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1514 /* tcon and ses pointer are checked in smb_init */
1515 if (tcon->ses->server == NULL)
1516 return -ECONNABORTED;
1518 pSMB->AndXCommand = 0xFF; /* none */
1520 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1522 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1523 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1526 pSMB->Reserved = 0xFFFFFFFF;
1527 pSMB->WriteMode = 0;
1528 pSMB->Remaining = 0;
1530 /* Can increase buffer size if buffer is big enough in some cases ie we
1531 can send more if LARGE_WRITE_X capability returned by the server and if
1532 our buffer is big enough or if we convert to iovecs on socket writes
1533 and eliminate the copy to the CIFS buffer */
1534 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1535 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1537 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1541 if (bytes_sent > count)
1544 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1546 memcpy(pSMB->Data, buf, bytes_sent);
1548 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1549 cifs_buf_release(pSMB);
1552 } else if (count != 0) {
1554 cifs_buf_release(pSMB);
1556 } /* else setting file size with write of zero bytes */
1558 byte_count = bytes_sent + 1; /* pad */
1559 else /* wct == 12 */
1560 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1562 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1563 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1564 pSMB->hdr.smb_buf_length += byte_count;
1567 pSMB->ByteCount = cpu_to_le16(byte_count);
1568 else { /* old style write has byte count 4 bytes earlier
1570 struct smb_com_writex_req *pSMBW =
1571 (struct smb_com_writex_req *)pSMB;
1572 pSMBW->ByteCount = cpu_to_le16(byte_count);
1575 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1576 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1577 cifs_stats_inc(&tcon->num_writes);
1579 cFYI(1, ("Send error in write = %d", rc));
1582 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1583 *nbytes = (*nbytes) << 16;
1584 *nbytes += le16_to_cpu(pSMBr->Count);
1587 cifs_buf_release(pSMB);
1589 /* Note: On -EAGAIN error only caller can retry on handle based calls
1590 since file handle passed in no longer valid */
1596 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1597 const int netfid, const unsigned int count,
1598 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1599 int n_vec, const int long_op)
1602 WRITE_REQ *pSMB = NULL;
1605 int resp_buf_type = 0;
1607 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1609 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1613 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1616 /* tcon and ses pointer are checked in smb_init */
1617 if (tcon->ses->server == NULL)
1618 return -ECONNABORTED;
1620 pSMB->AndXCommand = 0xFF; /* none */
1622 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1624 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1625 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1627 pSMB->Reserved = 0xFFFFFFFF;
1628 pSMB->WriteMode = 0;
1629 pSMB->Remaining = 0;
1632 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1634 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1635 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1636 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1638 pSMB->hdr.smb_buf_length += count+1;
1639 else /* wct == 12 */
1640 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1642 pSMB->ByteCount = cpu_to_le16(count + 1);
1643 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1644 struct smb_com_writex_req *pSMBW =
1645 (struct smb_com_writex_req *)pSMB;
1646 pSMBW->ByteCount = cpu_to_le16(count + 5);
1648 iov[0].iov_base = pSMB;
1650 iov[0].iov_len = smb_hdr_len + 4;
1651 else /* wct == 12 pad bigger by four bytes */
1652 iov[0].iov_len = smb_hdr_len + 8;
1655 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1657 cifs_stats_inc(&tcon->num_writes);
1659 cFYI(1, ("Send error Write2 = %d", rc));
1661 } else if (resp_buf_type == 0) {
1662 /* presumably this can not happen, but best to be safe */
1666 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1667 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1668 *nbytes = (*nbytes) << 16;
1669 *nbytes += le16_to_cpu(pSMBr->Count);
1672 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1673 if (resp_buf_type == CIFS_SMALL_BUFFER)
1674 cifs_small_buf_release(iov[0].iov_base);
1675 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1676 cifs_buf_release(iov[0].iov_base);
1678 /* Note: On -EAGAIN error only caller can retry on handle based calls
1679 since file handle passed in no longer valid */
1686 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1687 const __u16 smb_file_id, const __u64 len,
1688 const __u64 offset, const __u32 numUnlock,
1689 const __u32 numLock, const __u8 lockType, const int waitFlag)
1692 LOCK_REQ *pSMB = NULL;
1693 LOCK_RSP *pSMBr = NULL;
1698 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock));
1699 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1704 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1706 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1707 timeout = CIFS_ASYNC_OP; /* no response expected */
1709 } else if (waitFlag == TRUE) {
1710 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1711 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1716 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1717 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1718 pSMB->LockType = lockType;
1719 pSMB->AndXCommand = 0xFF; /* none */
1720 pSMB->Fid = smb_file_id; /* netfid stays le */
1722 if ((numLock != 0) || (numUnlock != 0)) {
1723 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1724 /* BB where to store pid high? */
1725 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1726 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1727 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1728 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1729 count = sizeof(LOCKING_ANDX_RANGE);
1734 pSMB->hdr.smb_buf_length += count;
1735 pSMB->ByteCount = cpu_to_le16(count);
1738 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1739 (struct smb_hdr *) pSMBr, &bytes_returned);
1740 cifs_small_buf_release(pSMB);
1742 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1744 /* SMB buffer freed by function above */
1746 cifs_stats_inc(&tcon->num_locks);
1748 cFYI(1, ("Send error in Lock = %d", rc));
1750 /* Note: On -EAGAIN error only caller can retry on handle based calls
1751 since file handle passed in no longer valid */
1756 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1757 const __u16 smb_file_id, const int get_flag, const __u64 len,
1758 struct file_lock *pLockData, const __u16 lock_type,
1761 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1762 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1763 struct cifs_posix_lock *parm_data;
1766 int bytes_returned = 0;
1767 int resp_buf_type = 0;
1768 __u16 params, param_offset, offset, byte_count, count;
1771 cFYI(1, ("Posix Lock"));
1773 if (pLockData == NULL)
1776 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1781 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1784 pSMB->MaxSetupCount = 0;
1787 pSMB->Reserved2 = 0;
1788 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1789 offset = param_offset + params;
1791 count = sizeof(struct cifs_posix_lock);
1792 pSMB->MaxParameterCount = cpu_to_le16(2);
1793 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1794 pSMB->SetupCount = 1;
1795 pSMB->Reserved3 = 0;
1797 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1799 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1800 byte_count = 3 /* pad */ + params + count;
1801 pSMB->DataCount = cpu_to_le16(count);
1802 pSMB->ParameterCount = cpu_to_le16(params);
1803 pSMB->TotalDataCount = pSMB->DataCount;
1804 pSMB->TotalParameterCount = pSMB->ParameterCount;
1805 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1806 parm_data = (struct cifs_posix_lock *)
1807 (((char *) &pSMB->hdr.Protocol) + offset);
1809 parm_data->lock_type = cpu_to_le16(lock_type);
1811 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1812 parm_data->lock_flags = cpu_to_le16(1);
1813 pSMB->Timeout = cpu_to_le32(-1);
1817 parm_data->pid = cpu_to_le32(current->tgid);
1818 parm_data->start = cpu_to_le64(pLockData->fl_start);
1819 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1821 pSMB->DataOffset = cpu_to_le16(offset);
1822 pSMB->Fid = smb_file_id;
1823 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1824 pSMB->Reserved4 = 0;
1825 pSMB->hdr.smb_buf_length += byte_count;
1826 pSMB->ByteCount = cpu_to_le16(byte_count);
1828 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1829 (struct smb_hdr *) pSMBr, &bytes_returned);
1831 iov[0].iov_base = (char *)pSMB;
1832 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1833 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1834 &resp_buf_type, timeout);
1835 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1836 not try to free it twice below on exit */
1837 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1841 cFYI(1, ("Send error in Posix Lock = %d", rc));
1842 } else if (get_flag) {
1843 /* lock structure can be returned on get */
1846 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1848 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1849 rc = -EIO; /* bad smb */
1852 if (pLockData == NULL) {
1856 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1857 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1858 if (data_count < sizeof(struct cifs_posix_lock)) {
1862 parm_data = (struct cifs_posix_lock *)
1863 ((char *)&pSMBr->hdr.Protocol + data_offset);
1864 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1865 pLockData->fl_type = F_UNLCK;
1870 cifs_small_buf_release(pSMB);
1872 if (resp_buf_type == CIFS_SMALL_BUFFER)
1873 cifs_small_buf_release(iov[0].iov_base);
1874 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1875 cifs_buf_release(iov[0].iov_base);
1877 /* Note: On -EAGAIN error only caller can retry on handle based calls
1878 since file handle passed in no longer valid */
1885 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1888 CLOSE_REQ *pSMB = NULL;
1889 cFYI(1, ("In CIFSSMBClose"));
1891 /* do not retry on dead session on close */
1892 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1898 pSMB->FileID = (__u16) smb_file_id;
1899 pSMB->LastWriteTime = 0xFFFFFFFF;
1900 pSMB->ByteCount = 0;
1901 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1902 cifs_stats_inc(&tcon->num_closes);
1905 /* EINTR is expected when user ctl-c to kill app */
1906 cERROR(1, ("Send error in Close = %d", rc));
1910 /* Since session is dead, file will be closed on server already */
1918 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1919 const char *fromName, const char *toName,
1920 const struct nls_table *nls_codepage, int remap)
1923 RENAME_REQ *pSMB = NULL;
1924 RENAME_RSP *pSMBr = NULL;
1926 int name_len, name_len2;
1929 cFYI(1, ("In CIFSSMBRename"));
1931 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1936 pSMB->BufferFormat = 0x04;
1937 pSMB->SearchAttributes =
1938 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1941 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1943 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1944 PATH_MAX, nls_codepage, remap);
1945 name_len++; /* trailing null */
1947 pSMB->OldFileName[name_len] = 0x04; /* pad */
1948 /* protocol requires ASCII signature byte on Unicode string */
1949 pSMB->OldFileName[name_len + 1] = 0x00;
1951 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1952 toName, PATH_MAX, nls_codepage, remap);
1953 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1954 name_len2 *= 2; /* convert to bytes */
1955 } else { /* BB improve the check for buffer overruns BB */
1956 name_len = strnlen(fromName, PATH_MAX);
1957 name_len++; /* trailing null */
1958 strncpy(pSMB->OldFileName, fromName, name_len);
1959 name_len2 = strnlen(toName, PATH_MAX);
1960 name_len2++; /* trailing null */
1961 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1962 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1963 name_len2++; /* trailing null */
1964 name_len2++; /* signature byte */
1967 count = 1 /* 1st signature byte */ + name_len + name_len2;
1968 pSMB->hdr.smb_buf_length += count;
1969 pSMB->ByteCount = cpu_to_le16(count);
1971 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1972 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1973 cifs_stats_inc(&tcon->num_renames);
1975 cFYI(1, ("Send error in rename = %d", rc));
1977 cifs_buf_release(pSMB);
1985 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1986 int netfid, char *target_name,
1987 const struct nls_table *nls_codepage, int remap)
1989 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1990 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1991 struct set_file_rename *rename_info;
1993 char dummy_string[30];
1995 int bytes_returned = 0;
1997 __u16 params, param_offset, offset, count, byte_count;
1999 cFYI(1, ("Rename to File by handle"));
2000 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2006 pSMB->MaxSetupCount = 0;
2010 pSMB->Reserved2 = 0;
2011 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2012 offset = param_offset + params;
2014 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2015 rename_info = (struct set_file_rename *) data_offset;
2016 pSMB->MaxParameterCount = cpu_to_le16(2);
2017 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2018 pSMB->SetupCount = 1;
2019 pSMB->Reserved3 = 0;
2020 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2021 byte_count = 3 /* pad */ + params;
2022 pSMB->ParameterCount = cpu_to_le16(params);
2023 pSMB->TotalParameterCount = pSMB->ParameterCount;
2024 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2025 pSMB->DataOffset = cpu_to_le16(offset);
2026 /* construct random name ".cifs_tmp<inodenum><mid>" */
2027 rename_info->overwrite = cpu_to_le32(1);
2028 rename_info->root_fid = 0;
2029 /* unicode only call */
2030 if (target_name == NULL) {
2031 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2032 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2033 dummy_string, 24, nls_codepage, remap);
2035 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2036 target_name, PATH_MAX, nls_codepage,
2039 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2040 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2041 byte_count += count;
2042 pSMB->DataCount = cpu_to_le16(count);
2043 pSMB->TotalDataCount = pSMB->DataCount;
2045 pSMB->InformationLevel =
2046 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2047 pSMB->Reserved4 = 0;
2048 pSMB->hdr.smb_buf_length += byte_count;
2049 pSMB->ByteCount = cpu_to_le16(byte_count);
2050 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2051 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2052 cifs_stats_inc(&pTcon->num_t2renames);
2054 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2056 cifs_buf_release(pSMB);
2058 /* Note: On -EAGAIN error only caller can retry on handle based calls
2059 since file handle passed in no longer valid */
2065 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2066 const __u16 target_tid, const char *toName, const int flags,
2067 const struct nls_table *nls_codepage, int remap)
2070 COPY_REQ *pSMB = NULL;
2071 COPY_RSP *pSMBr = NULL;
2073 int name_len, name_len2;
2076 cFYI(1, ("In CIFSSMBCopy"));
2078 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2083 pSMB->BufferFormat = 0x04;
2084 pSMB->Tid2 = target_tid;
2086 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2088 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2089 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2090 fromName, PATH_MAX, nls_codepage,
2092 name_len++; /* trailing null */
2094 pSMB->OldFileName[name_len] = 0x04; /* pad */
2095 /* protocol requires ASCII signature byte on Unicode string */
2096 pSMB->OldFileName[name_len + 1] = 0x00;
2098 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2099 toName, PATH_MAX, nls_codepage, remap);
2100 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2101 name_len2 *= 2; /* convert to bytes */
2102 } else { /* BB improve the check for buffer overruns BB */
2103 name_len = strnlen(fromName, PATH_MAX);
2104 name_len++; /* trailing null */
2105 strncpy(pSMB->OldFileName, fromName, name_len);
2106 name_len2 = strnlen(toName, PATH_MAX);
2107 name_len2++; /* trailing null */
2108 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2109 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2110 name_len2++; /* trailing null */
2111 name_len2++; /* signature byte */
2114 count = 1 /* 1st signature byte */ + name_len + name_len2;
2115 pSMB->hdr.smb_buf_length += count;
2116 pSMB->ByteCount = cpu_to_le16(count);
2118 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2119 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2121 cFYI(1, ("Send error in copy = %d with %d files copied",
2122 rc, le16_to_cpu(pSMBr->CopyCount)));
2125 cifs_buf_release(pSMB);
2134 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2135 const char *fromName, const char *toName,
2136 const struct nls_table *nls_codepage)
2138 TRANSACTION2_SPI_REQ *pSMB = NULL;
2139 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2142 int name_len_target;
2144 int bytes_returned = 0;
2145 __u16 params, param_offset, offset, byte_count;
2147 cFYI(1, ("In Symlink Unix style"));
2149 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2154 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2156 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2157 /* find define for this maxpathcomponent */
2159 name_len++; /* trailing null */
2162 } else { /* BB improve the check for buffer overruns BB */
2163 name_len = strnlen(fromName, PATH_MAX);
2164 name_len++; /* trailing null */
2165 strncpy(pSMB->FileName, fromName, name_len);
2167 params = 6 + name_len;
2168 pSMB->MaxSetupCount = 0;
2172 pSMB->Reserved2 = 0;
2173 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2174 InformationLevel) - 4;
2175 offset = param_offset + params;
2177 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2178 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2180 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2181 /* find define for this maxpathcomponent */
2183 name_len_target++; /* trailing null */
2184 name_len_target *= 2;
2185 } else { /* BB improve the check for buffer overruns BB */
2186 name_len_target = strnlen(toName, PATH_MAX);
2187 name_len_target++; /* trailing null */
2188 strncpy(data_offset, toName, name_len_target);
2191 pSMB->MaxParameterCount = cpu_to_le16(2);
2192 /* BB find exact max on data count below from sess */
2193 pSMB->MaxDataCount = cpu_to_le16(1000);
2194 pSMB->SetupCount = 1;
2195 pSMB->Reserved3 = 0;
2196 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2197 byte_count = 3 /* pad */ + params + name_len_target;
2198 pSMB->DataCount = cpu_to_le16(name_len_target);
2199 pSMB->ParameterCount = cpu_to_le16(params);
2200 pSMB->TotalDataCount = pSMB->DataCount;
2201 pSMB->TotalParameterCount = pSMB->ParameterCount;
2202 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2203 pSMB->DataOffset = cpu_to_le16(offset);
2204 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2205 pSMB->Reserved4 = 0;
2206 pSMB->hdr.smb_buf_length += byte_count;
2207 pSMB->ByteCount = cpu_to_le16(byte_count);
2208 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2209 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2210 cifs_stats_inc(&tcon->num_symlinks);
2212 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2215 cifs_buf_release(pSMB);
2218 goto createSymLinkRetry;
2224 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2225 const char *fromName, const char *toName,
2226 const struct nls_table *nls_codepage, int remap)
2228 TRANSACTION2_SPI_REQ *pSMB = NULL;
2229 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2232 int name_len_target;
2234 int bytes_returned = 0;
2235 __u16 params, param_offset, offset, byte_count;
2237 cFYI(1, ("In Create Hard link Unix style"));
2238 createHardLinkRetry:
2239 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2244 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2245 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2246 PATH_MAX, nls_codepage, remap);
2247 name_len++; /* trailing null */
2250 } else { /* BB improve the check for buffer overruns BB */
2251 name_len = strnlen(toName, PATH_MAX);
2252 name_len++; /* trailing null */
2253 strncpy(pSMB->FileName, toName, name_len);
2255 params = 6 + name_len;
2256 pSMB->MaxSetupCount = 0;
2260 pSMB->Reserved2 = 0;
2261 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2262 InformationLevel) - 4;
2263 offset = param_offset + params;
2265 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2266 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2268 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2269 nls_codepage, remap);
2270 name_len_target++; /* trailing null */
2271 name_len_target *= 2;
2272 } else { /* BB improve the check for buffer overruns BB */
2273 name_len_target = strnlen(fromName, PATH_MAX);
2274 name_len_target++; /* trailing null */
2275 strncpy(data_offset, fromName, name_len_target);
2278 pSMB->MaxParameterCount = cpu_to_le16(2);
2279 /* BB find exact max on data count below from sess*/
2280 pSMB->MaxDataCount = cpu_to_le16(1000);
2281 pSMB->SetupCount = 1;
2282 pSMB->Reserved3 = 0;
2283 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2284 byte_count = 3 /* pad */ + params + name_len_target;
2285 pSMB->ParameterCount = cpu_to_le16(params);
2286 pSMB->TotalParameterCount = pSMB->ParameterCount;
2287 pSMB->DataCount = cpu_to_le16(name_len_target);
2288 pSMB->TotalDataCount = pSMB->DataCount;
2289 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2290 pSMB->DataOffset = cpu_to_le16(offset);
2291 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2292 pSMB->Reserved4 = 0;
2293 pSMB->hdr.smb_buf_length += byte_count;
2294 pSMB->ByteCount = cpu_to_le16(byte_count);
2295 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2296 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2297 cifs_stats_inc(&tcon->num_hardlinks);
2299 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2301 cifs_buf_release(pSMB);
2303 goto createHardLinkRetry;
2309 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2310 const char *fromName, const char *toName,
2311 const struct nls_table *nls_codepage, int remap)
2314 NT_RENAME_REQ *pSMB = NULL;
2315 RENAME_RSP *pSMBr = NULL;
2317 int name_len, name_len2;
2320 cFYI(1, ("In CIFSCreateHardLink"));
2321 winCreateHardLinkRetry:
2323 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2328 pSMB->SearchAttributes =
2329 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2331 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2332 pSMB->ClusterCount = 0;
2334 pSMB->BufferFormat = 0x04;
2336 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2338 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2339 PATH_MAX, nls_codepage, remap);
2340 name_len++; /* trailing null */
2342 pSMB->OldFileName[name_len] = 0; /* pad */
2343 pSMB->OldFileName[name_len + 1] = 0x04;
2345 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2346 toName, PATH_MAX, nls_codepage, remap);
2347 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2348 name_len2 *= 2; /* convert to bytes */
2349 } else { /* BB improve the check for buffer overruns BB */
2350 name_len = strnlen(fromName, PATH_MAX);
2351 name_len++; /* trailing null */
2352 strncpy(pSMB->OldFileName, fromName, name_len);
2353 name_len2 = strnlen(toName, PATH_MAX);
2354 name_len2++; /* trailing null */
2355 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2356 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2357 name_len2++; /* trailing null */
2358 name_len2++; /* signature byte */
2361 count = 1 /* string type byte */ + name_len + name_len2;
2362 pSMB->hdr.smb_buf_length += count;
2363 pSMB->ByteCount = cpu_to_le16(count);
2365 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2366 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2367 cifs_stats_inc(&tcon->num_hardlinks);
2369 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2371 cifs_buf_release(pSMB);
2373 goto winCreateHardLinkRetry;
2379 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2380 const unsigned char *searchName,
2381 char *symlinkinfo, const int buflen,
2382 const struct nls_table *nls_codepage)
2384 /* SMB_QUERY_FILE_UNIX_LINK */
2385 TRANSACTION2_QPI_REQ *pSMB = NULL;
2386 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2390 __u16 params, byte_count;
2392 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2395 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2400 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2402 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2403 PATH_MAX, nls_codepage);
2404 name_len++; /* trailing null */
2406 } else { /* BB improve the check for buffer overruns BB */
2407 name_len = strnlen(searchName, PATH_MAX);
2408 name_len++; /* trailing null */
2409 strncpy(pSMB->FileName, searchName, name_len);
2412 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2413 pSMB->TotalDataCount = 0;
2414 pSMB->MaxParameterCount = cpu_to_le16(2);
2415 /* BB find exact max data count below from sess structure BB */
2416 pSMB->MaxDataCount = cpu_to_le16(4000);
2417 pSMB->MaxSetupCount = 0;
2421 pSMB->Reserved2 = 0;
2422 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2423 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2424 pSMB->DataCount = 0;
2425 pSMB->DataOffset = 0;
2426 pSMB->SetupCount = 1;
2427 pSMB->Reserved3 = 0;
2428 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2429 byte_count = params + 1 /* pad */ ;
2430 pSMB->TotalParameterCount = cpu_to_le16(params);
2431 pSMB->ParameterCount = pSMB->TotalParameterCount;
2432 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2433 pSMB->Reserved4 = 0;
2434 pSMB->hdr.smb_buf_length += byte_count;
2435 pSMB->ByteCount = cpu_to_le16(byte_count);
2437 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2438 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2440 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2442 /* decode response */
2444 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2445 if (rc || (pSMBr->ByteCount < 2))
2446 /* BB also check enough total bytes returned */
2447 rc = -EIO; /* bad smb */
2449 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2450 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2452 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2453 name_len = UniStrnlen((wchar_t *) ((char *)
2454 &pSMBr->hdr.Protocol + data_offset),
2455 min_t(const int, buflen, count) / 2);
2456 /* BB FIXME investigate remapping reserved chars here */
2457 cifs_strfromUCS_le(symlinkinfo,
2458 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2460 name_len, nls_codepage);
2462 strncpy(symlinkinfo,
2463 (char *) &pSMBr->hdr.Protocol +
2465 min_t(const int, buflen, count));
2467 symlinkinfo[buflen] = 0;
2468 /* just in case so calling code does not go off the end of buffer */
2471 cifs_buf_release(pSMB);
2473 goto querySymLinkRetry;
2477 #ifdef CONFIG_CIFS_EXPERIMENTAL
2478 /* Initialize NT TRANSACT SMB into small smb request buffer.
2479 This assumes that all NT TRANSACTS that we init here have
2480 total parm and data under about 400 bytes (to fit in small cifs
2481 buffer size), which is the case so far, it easily fits. NB:
2482 Setup words themselves and ByteCount
2483 MaxSetupCount (size of returned setup area) and
2484 MaxParameterCount (returned parms size) must be set by caller */
2486 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2487 const int parm_len, struct cifsTconInfo *tcon,
2492 struct smb_com_ntransact_req *pSMB;
2494 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2498 *ret_buf = (void *)pSMB;
2500 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2501 pSMB->TotalDataCount = 0;
2502 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2503 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2504 pSMB->ParameterCount = pSMB->TotalParameterCount;
2505 pSMB->DataCount = pSMB->TotalDataCount;
2506 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2507 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2508 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2509 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2510 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2511 pSMB->SubCommand = cpu_to_le16(sub_command);
2516 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2517 __u32 *pparmlen, __u32 *pdatalen)
2520 __u32 data_count, data_offset, parm_count, parm_offset;
2521 struct smb_com_ntransact_rsp *pSMBr;
2529 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2531 /* ByteCount was converted from little endian in SendReceive */
2532 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2533 (char *)&pSMBr->ByteCount;
2535 data_offset = le32_to_cpu(pSMBr->DataOffset);
2536 data_count = le32_to_cpu(pSMBr->DataCount);
2537 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2538 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2540 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2541 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2543 /* should we also check that parm and data areas do not overlap? */
2544 if (*ppparm > end_of_smb) {
2545 cFYI(1, ("parms start after end of smb"));
2547 } else if (parm_count + *ppparm > end_of_smb) {
2548 cFYI(1, ("parm end after end of smb"));
2550 } else if (*ppdata > end_of_smb) {
2551 cFYI(1, ("data starts after end of smb"));
2553 } else if (data_count + *ppdata > end_of_smb) {
2554 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2555 *ppdata, data_count, (data_count + *ppdata),
2556 end_of_smb, pSMBr));
2558 } else if (parm_count + data_count > pSMBr->ByteCount) {
2559 cFYI(1, ("parm count and data count larger than SMB"));
2562 *pdatalen = data_count;
2563 *pparmlen = parm_count;
2566 #endif /* CIFS_EXPERIMENTAL */
2569 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2570 const unsigned char *searchName,
2571 char *symlinkinfo, const int buflen, __u16 fid,
2572 const struct nls_table *nls_codepage)
2577 struct smb_com_transaction_ioctl_req *pSMB;
2578 struct smb_com_transaction_ioctl_rsp *pSMBr;
2580 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2581 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2586 pSMB->TotalParameterCount = 0 ;
2587 pSMB->TotalDataCount = 0;
2588 pSMB->MaxParameterCount = cpu_to_le32(2);
2589 /* BB find exact data count max from sess structure BB */
2590 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2591 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2592 pSMB->MaxSetupCount = 4;
2594 pSMB->ParameterOffset = 0;
2595 pSMB->DataCount = 0;
2596 pSMB->DataOffset = 0;
2597 pSMB->SetupCount = 4;
2598 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2599 pSMB->ParameterCount = pSMB->TotalParameterCount;
2600 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2601 pSMB->IsFsctl = 1; /* FSCTL */
2602 pSMB->IsRootFlag = 0;
2603 pSMB->Fid = fid; /* file handle always le */
2604 pSMB->ByteCount = 0;
2606 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2607 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2609 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2610 } else { /* decode response */
2611 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2612 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2613 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2614 /* BB also check enough total bytes returned */
2615 rc = -EIO; /* bad smb */
2617 if (data_count && (data_count < 2048)) {
2618 char *end_of_smb = 2 /* sizeof byte count */ +
2620 (char *)&pSMBr->ByteCount;
2622 struct reparse_data *reparse_buf =
2623 (struct reparse_data *)
2624 ((char *)&pSMBr->hdr.Protocol
2626 if ((char *)reparse_buf >= end_of_smb) {
2630 if ((reparse_buf->LinkNamesBuf +
2631 reparse_buf->TargetNameOffset +
2632 reparse_buf->TargetNameLen) >
2634 cFYI(1, ("reparse buf beyond SMB"));
2639 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2640 name_len = UniStrnlen((wchar_t *)
2641 (reparse_buf->LinkNamesBuf +
2642 reparse_buf->TargetNameOffset),
2644 reparse_buf->TargetNameLen / 2));
2645 cifs_strfromUCS_le(symlinkinfo,
2646 (__le16 *) (reparse_buf->LinkNamesBuf +
2647 reparse_buf->TargetNameOffset),
2648 name_len, nls_codepage);
2649 } else { /* ASCII names */
2650 strncpy(symlinkinfo,
2651 reparse_buf->LinkNamesBuf +
2652 reparse_buf->TargetNameOffset,
2653 min_t(const int, buflen,
2654 reparse_buf->TargetNameLen));
2658 cFYI(1, ("Invalid return data count on "
2659 "get reparse info ioctl"));
2661 symlinkinfo[buflen] = 0; /* just in case so the caller
2662 does not go off the end of the buffer */
2663 cFYI(1, ("readlink result - %s", symlinkinfo));
2667 cifs_buf_release(pSMB);
2669 /* Note: On -EAGAIN error only caller can retry on handle based calls
2670 since file handle passed in no longer valid */
2675 #ifdef CONFIG_CIFS_POSIX
2677 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2678 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2679 struct cifs_posix_ace *cifs_ace)
2681 /* u8 cifs fields do not need le conversion */
2682 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2683 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2684 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2685 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2690 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2691 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2692 const int acl_type, const int size_of_data_area)
2697 struct cifs_posix_ace *pACE;
2698 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2699 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2701 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2704 if (acl_type & ACL_TYPE_ACCESS) {
2705 count = le16_to_cpu(cifs_acl->access_entry_count);
2706 pACE = &cifs_acl->ace_array[0];
2707 size = sizeof(struct cifs_posix_acl);
2708 size += sizeof(struct cifs_posix_ace) * count;
2709 /* check if we would go beyond end of SMB */
2710 if (size_of_data_area < size) {
2711 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2712 size_of_data_area, size));
2715 } else if (acl_type & ACL_TYPE_DEFAULT) {
2716 count = le16_to_cpu(cifs_acl->access_entry_count);
2717 size = sizeof(struct cifs_posix_acl);
2718 size += sizeof(struct cifs_posix_ace) * count;
2719 /* skip past access ACEs to get to default ACEs */
2720 pACE = &cifs_acl->ace_array[count];
2721 count = le16_to_cpu(cifs_acl->default_entry_count);
2722 size += sizeof(struct cifs_posix_ace) * count;
2723 /* check if we would go beyond end of SMB */
2724 if (size_of_data_area < size)
2731 size = posix_acl_xattr_size(count);
2732 if ((buflen == 0) || (local_acl == NULL)) {
2733 /* used to query ACL EA size */
2734 } else if (size > buflen) {
2736 } else /* buffer big enough */ {
2737 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2738 for (i = 0; i < count ; i++) {
2739 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2746 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2747 const posix_acl_xattr_entry *local_ace)
2749 __u16 rc = 0; /* 0 = ACL converted ok */
2751 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2752 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2753 /* BB is there a better way to handle the large uid? */
2754 if (local_ace->e_id == cpu_to_le32(-1)) {
2755 /* Probably no need to le convert -1 on any arch but can not hurt */
2756 cifs_ace->cifs_uid = cpu_to_le64(-1);
2758 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2759 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2763 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2764 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2765 const int buflen, const int acl_type)
2768 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2769 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2773 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2776 count = posix_acl_xattr_count((size_t)buflen);
2777 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2779 count, buflen, le32_to_cpu(local_acl->a_version)));
2780 if (le32_to_cpu(local_acl->a_version) != 2) {
2781 cFYI(1, ("unknown POSIX ACL version %d",
2782 le32_to_cpu(local_acl->a_version)));
2785 cifs_acl->version = cpu_to_le16(1);
2786 if (acl_type == ACL_TYPE_ACCESS)
2787 cifs_acl->access_entry_count = cpu_to_le16(count);
2788 else if (acl_type == ACL_TYPE_DEFAULT)
2789 cifs_acl->default_entry_count = cpu_to_le16(count);
2791 cFYI(1, ("unknown ACL type %d", acl_type));
2794 for (i = 0; i < count; i++) {
2795 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2796 &local_acl->a_entries[i]);
2798 /* ACE not converted */
2803 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2804 rc += sizeof(struct cifs_posix_acl);
2805 /* BB add check to make sure ACL does not overflow SMB */
2811 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2812 const unsigned char *searchName,
2813 char *acl_inf, const int buflen, const int acl_type,
2814 const struct nls_table *nls_codepage, int remap)
2816 /* SMB_QUERY_POSIX_ACL */
2817 TRANSACTION2_QPI_REQ *pSMB = NULL;
2818 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2822 __u16 params, byte_count;
2824 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2827 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2832 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2834 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2835 PATH_MAX, nls_codepage, remap);
2836 name_len++; /* trailing null */
2838 pSMB->FileName[name_len] = 0;
2839 pSMB->FileName[name_len+1] = 0;
2840 } else { /* BB improve the check for buffer overruns BB */
2841 name_len = strnlen(searchName, PATH_MAX);
2842 name_len++; /* trailing null */
2843 strncpy(pSMB->FileName, searchName, name_len);
2846 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2847 pSMB->TotalDataCount = 0;
2848 pSMB->MaxParameterCount = cpu_to_le16(2);
2849 /* BB find exact max data count below from sess structure BB */
2850 pSMB->MaxDataCount = cpu_to_le16(4000);
2851 pSMB->MaxSetupCount = 0;
2855 pSMB->Reserved2 = 0;
2856 pSMB->ParameterOffset = cpu_to_le16(
2857 offsetof(struct smb_com_transaction2_qpi_req,
2858 InformationLevel) - 4);
2859 pSMB->DataCount = 0;
2860 pSMB->DataOffset = 0;
2861 pSMB->SetupCount = 1;
2862 pSMB->Reserved3 = 0;
2863 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2864 byte_count = params + 1 /* pad */ ;
2865 pSMB->TotalParameterCount = cpu_to_le16(params);
2866 pSMB->ParameterCount = pSMB->TotalParameterCount;
2867 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2868 pSMB->Reserved4 = 0;
2869 pSMB->hdr.smb_buf_length += byte_count;
2870 pSMB->ByteCount = cpu_to_le16(byte_count);
2872 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2873 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2874 cifs_stats_inc(&tcon->num_acl_get);
2876 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2878 /* decode response */
2880 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2881 if (rc || (pSMBr->ByteCount < 2))
2882 /* BB also check enough total bytes returned */
2883 rc = -EIO; /* bad smb */
2885 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2886 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2887 rc = cifs_copy_posix_acl(acl_inf,
2888 (char *)&pSMBr->hdr.Protocol+data_offset,
2889 buflen, acl_type, count);
2892 cifs_buf_release(pSMB);
2899 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2900 const unsigned char *fileName,
2901 const char *local_acl, const int buflen,
2903 const struct nls_table *nls_codepage, int remap)
2905 struct smb_com_transaction2_spi_req *pSMB = NULL;
2906 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2910 int bytes_returned = 0;
2911 __u16 params, byte_count, data_count, param_offset, offset;
2913 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2915 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2919 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2921 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2922 PATH_MAX, nls_codepage, remap);
2923 name_len++; /* trailing null */
2925 } else { /* BB improve the check for buffer overruns BB */
2926 name_len = strnlen(fileName, PATH_MAX);
2927 name_len++; /* trailing null */
2928 strncpy(pSMB->FileName, fileName, name_len);
2930 params = 6 + name_len;
2931 pSMB->MaxParameterCount = cpu_to_le16(2);
2932 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2933 pSMB->MaxSetupCount = 0;
2937 pSMB->Reserved2 = 0;
2938 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2939 InformationLevel) - 4;
2940 offset = param_offset + params;
2941 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2942 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2944 /* convert to on the wire format for POSIX ACL */
2945 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2947 if (data_count == 0) {
2949 goto setACLerrorExit;
2951 pSMB->DataOffset = cpu_to_le16(offset);
2952 pSMB->SetupCount = 1;
2953 pSMB->Reserved3 = 0;
2954 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2955 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2956 byte_count = 3 /* pad */ + params + data_count;
2957 pSMB->DataCount = cpu_to_le16(data_count);
2958 pSMB->TotalDataCount = pSMB->DataCount;
2959 pSMB->ParameterCount = cpu_to_le16(params);
2960 pSMB->TotalParameterCount = pSMB->ParameterCount;
2961 pSMB->Reserved4 = 0;
2962 pSMB->hdr.smb_buf_length += byte_count;
2963 pSMB->ByteCount = cpu_to_le16(byte_count);
2964 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2965 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2967 cFYI(1, ("Set POSIX ACL returned %d", rc));
2970 cifs_buf_release(pSMB);
2976 /* BB fix tabs in this function FIXME BB */
2978 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2979 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2982 struct smb_t2_qfi_req *pSMB = NULL;
2983 struct smb_t2_qfi_rsp *pSMBr = NULL;
2985 __u16 params, byte_count;
2987 cFYI(1, ("In GetExtAttr"));
2992 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2997 params = 2 /* level */ + 2 /* fid */;
2998 pSMB->t2.TotalDataCount = 0;
2999 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3000 /* BB find exact max data count below from sess structure BB */
3001 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3002 pSMB->t2.MaxSetupCount = 0;
3003 pSMB->t2.Reserved = 0;
3005 pSMB->t2.Timeout = 0;
3006 pSMB->t2.Reserved2 = 0;
3007 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3009 pSMB->t2.DataCount = 0;
3010 pSMB->t2.DataOffset = 0;
3011 pSMB->t2.SetupCount = 1;
3012 pSMB->t2.Reserved3 = 0;
3013 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3014 byte_count = params + 1 /* pad */ ;
3015 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3016 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3017 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3020 pSMB->hdr.smb_buf_length += byte_count;
3021 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3023 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3024 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3026 cFYI(1, ("error %d in GetExtAttr", rc));
3028 /* decode response */
3029 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3030 if (rc || (pSMBr->ByteCount < 2))
3031 /* BB also check enough total bytes returned */
3032 /* If rc should we check for EOPNOSUPP and
3033 disable the srvino flag? or in caller? */
3034 rc = -EIO; /* bad smb */
3036 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3037 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3038 struct file_chattr_info *pfinfo;
3039 /* BB Do we need a cast or hash here ? */
3041 cFYI(1, ("Illegal size ret in GetExtAttr"));