4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* Allocates buffer into dst and copies smb string from src to it.
85 * caller is responsible for freeing dst if function returned 0.
91 cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
92 const bool is_unicode, const struct nls_table *nls_codepage)
97 plen = UniStrnlen((wchar_t *)src, maxlen);
98 *dst = kmalloc(plen + 2, GFP_KERNEL);
100 goto cifs_strncpy_to_host_ErrExit;
101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
103 plen = strnlen(src, maxlen);
104 *dst = kmalloc(plen + 2, GFP_KERNEL);
106 goto cifs_strncpy_to_host_ErrExit;
107 strncpy(*dst, src, plen);
110 (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
113 cifs_strncpy_to_host_ErrExit:
114 cERROR(1, ("Failed to allocate buffer for string\n"));
119 /* Mark as invalid, all open files on tree connections since they
120 were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
123 struct cifsFileInfo *open_file = NULL;
124 struct list_head *tmp;
125 struct list_head *tmp1;
127 /* list all files open on tree connection and mark them invalid */
128 write_lock(&GlobalSMBSeslock);
129 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
130 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
132 open_file->invalidHandle = true;
134 write_unlock(&GlobalSMBSeslock);
135 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
139 /* Allocate and return pointer to an SMB request buffer, and set basic
140 SMB information in the SMB header. If the return code is zero, this
141 function must have filled in request_buf pointer */
143 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
148 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
149 check for tcp and smb session status done differently
150 for those three - in the calling routine */
152 if (tcon->tidStatus == CifsExiting) {
153 /* only tree disconnect, open, and write,
154 (and ulogoff which does not have tcon)
155 are allowed as we start force umount */
156 if ((smb_command != SMB_COM_WRITE_ANDX) &&
157 (smb_command != SMB_COM_OPEN_ANDX) &&
158 (smb_command != SMB_COM_TREE_DISCONNECT)) {
159 cFYI(1, ("can not send cmd %d while umounting",
164 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
165 (tcon->ses->server)) {
166 struct nls_table *nls_codepage;
167 /* Give Demultiplex thread up to 10 seconds to
168 reconnect, should be greater than cifs socket
169 timeout which is 7 seconds */
170 while (tcon->ses->server->tcpStatus ==
172 wait_event_interruptible_timeout(tcon->ses->server->response_q,
173 (tcon->ses->server->tcpStatus ==
175 if (tcon->ses->server->tcpStatus ==
177 /* on "soft" mounts we wait once */
179 (tcon->ses->status == CifsExiting)) {
180 cFYI(1, ("gave up waiting on "
181 "reconnect in smb_init"));
183 } /* else "hard" mount - keep retrying
184 until process is killed or server
185 comes back on-line */
186 } else /* TCP session is reestablished now */
190 nls_codepage = load_nls_default();
191 /* need to prevent multiple threads trying to
192 simultaneously reconnect the same SMB session */
193 down(&tcon->ses->sesSem);
194 if (tcon->ses->status == CifsNeedReconnect)
195 rc = cifs_setup_session(0, tcon->ses,
197 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
198 mark_open_files_invalid(tcon);
199 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
201 up(&tcon->ses->sesSem);
202 /* BB FIXME add code to check if wsize needs
203 update due to negotiated smb buffer size
206 atomic_inc(&tconInfoReconnectCount);
207 /* tell server Unix caps we support */
208 if (tcon->ses->capabilities & CAP_UNIX)
209 reset_cifs_unix_caps(
212 NULL /* we do not know sb */,
213 NULL /* no vol info */);
216 cFYI(1, ("reconnect tcon rc = %d", rc));
217 /* Removed call to reopen open files here.
218 It is safer (and faster) to reopen files
219 one at a time as needed in read and write */
221 /* Check if handle based operation so we
222 know whether we can continue or not without
223 returning to caller to reset file handle */
224 switch (smb_command) {
225 case SMB_COM_READ_ANDX:
226 case SMB_COM_WRITE_ANDX:
228 case SMB_COM_FIND_CLOSE2:
229 case SMB_COM_LOCKING_ANDX: {
230 unload_nls(nls_codepage);
235 up(&tcon->ses->sesSem);
237 unload_nls(nls_codepage);
246 *request_buf = cifs_small_buf_get();
247 if (*request_buf == NULL) {
248 /* BB should we add a retry in here if not a writepage? */
252 header_assemble((struct smb_hdr *) *request_buf, smb_command,
256 cifs_stats_inc(&tcon->num_smbs_sent);
262 small_smb_init_no_tc(const int smb_command, const int wct,
263 struct cifsSesInfo *ses, void **request_buf)
266 struct smb_hdr *buffer;
268 rc = small_smb_init(smb_command, wct, NULL, request_buf);
272 buffer = (struct smb_hdr *)*request_buf;
273 buffer->Mid = GetNextMid(ses->server);
274 if (ses->capabilities & CAP_UNICODE)
275 buffer->Flags2 |= SMBFLG2_UNICODE;
276 if (ses->capabilities & CAP_STATUS32)
277 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
279 /* uid, tid can stay at zero as set in header assemble */
281 /* BB add support for turning on the signing when
282 this function is used after 1st of session setup requests */
287 /* If the return code is zero, this function must fill in request_buf pointer */
289 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
290 void **request_buf /* returned */ ,
291 void **response_buf /* returned */ )
295 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
296 check for tcp and smb session status done differently
297 for those three - in the calling routine */
299 if (tcon->tidStatus == CifsExiting) {
300 /* only tree disconnect, open, and write,
301 (and ulogoff which does not have tcon)
302 are allowed as we start force umount */
303 if ((smb_command != SMB_COM_WRITE_ANDX) &&
304 (smb_command != SMB_COM_OPEN_ANDX) &&
305 (smb_command != SMB_COM_TREE_DISCONNECT)) {
306 cFYI(1, ("can not send cmd %d while umounting",
312 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
313 (tcon->ses->server)) {
314 struct nls_table *nls_codepage;
315 /* Give Demultiplex thread up to 10 seconds to
316 reconnect, should be greater than cifs socket
317 timeout which is 7 seconds */
318 while (tcon->ses->server->tcpStatus ==
320 wait_event_interruptible_timeout(tcon->ses->server->response_q,
321 (tcon->ses->server->tcpStatus ==
323 if (tcon->ses->server->tcpStatus ==
325 /* on "soft" mounts we wait once */
327 (tcon->ses->status == CifsExiting)) {
328 cFYI(1, ("gave up waiting on "
329 "reconnect in smb_init"));
331 } /* else "hard" mount - keep retrying
332 until process is killed or server
334 } else /* TCP session is reestablished now */
337 nls_codepage = load_nls_default();
338 /* need to prevent multiple threads trying to
339 simultaneously reconnect the same SMB session */
340 down(&tcon->ses->sesSem);
341 if (tcon->ses->status == CifsNeedReconnect)
342 rc = cifs_setup_session(0, tcon->ses,
344 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
345 mark_open_files_invalid(tcon);
346 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
348 up(&tcon->ses->sesSem);
349 /* BB FIXME add code to check if wsize needs
350 update due to negotiated smb buffer size
353 atomic_inc(&tconInfoReconnectCount);
354 /* tell server Unix caps we support */
355 if (tcon->ses->capabilities & CAP_UNIX)
356 reset_cifs_unix_caps(
359 NULL /* do not know sb */,
360 NULL /* no vol info */);
363 cFYI(1, ("reconnect tcon rc = %d", rc));
364 /* Removed call to reopen open files here.
365 It is safer (and faster) to reopen files
366 one at a time as needed in read and write */
368 /* Check if handle based operation so we
369 know whether we can continue or not without
370 returning to caller to reset file handle */
371 switch (smb_command) {
372 case SMB_COM_READ_ANDX:
373 case SMB_COM_WRITE_ANDX:
375 case SMB_COM_FIND_CLOSE2:
376 case SMB_COM_LOCKING_ANDX: {
377 unload_nls(nls_codepage);
382 up(&tcon->ses->sesSem);
384 unload_nls(nls_codepage);
393 *request_buf = cifs_buf_get();
394 if (*request_buf == NULL) {
395 /* BB should we add a retry in here if not a writepage? */
398 /* Although the original thought was we needed the response buf for */
399 /* potential retries of smb operations it turns out we can determine */
400 /* from the mid flags when the request buffer can be resent without */
401 /* having to use a second distinct buffer for the response */
403 *response_buf = *request_buf;
405 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
409 cifs_stats_inc(&tcon->num_smbs_sent);
414 static int validate_t2(struct smb_t2_rsp *pSMB)
420 /* check for plausible wct, bcc and t2 data and parm sizes */
421 /* check for parm and data offset going beyond end of smb */
422 if (pSMB->hdr.WordCount >= 10) {
423 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
424 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
425 /* check that bcc is at least as big as parms + data */
426 /* check that bcc is less than negotiated smb buffer */
427 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
428 if (total_size < 512) {
430 le16_to_cpu(pSMB->t2_rsp.DataCount);
431 /* BCC le converted in SendReceive */
432 pBCC = (pSMB->hdr.WordCount * 2) +
433 sizeof(struct smb_hdr) +
435 if ((total_size <= (*(u16 *)pBCC)) &&
437 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
443 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
444 sizeof(struct smb_t2_rsp) + 16);
448 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
451 NEGOTIATE_RSP *pSMBr;
455 struct TCP_Server_Info *server;
457 unsigned int secFlags;
461 server = ses->server;
466 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
467 (void **) &pSMB, (void **) &pSMBr);
471 /* if any of auth flags (ie not sign or seal) are overriden use them */
472 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
473 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
474 else /* if override flags set only sign/seal OR them with global auth */
475 secFlags = extended_security | ses->overrideSecFlg;
477 cFYI(1, ("secFlags 0x%x", secFlags));
479 pSMB->hdr.Mid = GetNextMid(server);
480 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
482 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
483 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
484 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
485 cFYI(1, ("Kerberos only mechanism, enable extended security"));
486 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
490 for (i = 0; i < CIFS_NUM_PROT; i++) {
491 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
492 count += strlen(protocols[i].name) + 1;
493 /* null at end of source and target buffers anyway */
495 pSMB->hdr.smb_buf_length += count;
496 pSMB->ByteCount = cpu_to_le16(count);
498 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
499 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
503 dialect = le16_to_cpu(pSMBr->DialectIndex);
504 cFYI(1, ("Dialect: %d", dialect));
505 /* Check wct = 1 error case */
506 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
507 /* core returns wct = 1, but we do not ask for core - otherwise
508 small wct just comes when dialect index is -1 indicating we
509 could not negotiate a common dialect */
512 #ifdef CONFIG_CIFS_WEAK_PW_HASH
513 } else if ((pSMBr->hdr.WordCount == 13)
514 && ((dialect == LANMAN_PROT)
515 || (dialect == LANMAN2_PROT))) {
517 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
519 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
520 (secFlags & CIFSSEC_MAY_PLNTXT))
521 server->secType = LANMAN;
523 cERROR(1, ("mount failed weak security disabled"
524 " in /proc/fs/cifs/SecurityFlags"));
528 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
529 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
530 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
531 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
532 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
533 /* even though we do not use raw we might as well set this
534 accurately, in case we ever find a need for it */
535 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
536 server->maxRw = 0xFF00;
537 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
539 server->maxRw = 0;/* we do not need to use raw anyway */
540 server->capabilities = CAP_MPX_MODE;
542 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
544 /* OS/2 often does not set timezone therefore
545 * we must use server time to calc time zone.
546 * Could deviate slightly from the right zone.
547 * Smallest defined timezone difference is 15 minutes
548 * (i.e. Nepal). Rounding up/down is done to match
551 int val, seconds, remain, result;
552 struct timespec ts, utc;
554 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
555 le16_to_cpu(rsp->SrvTime.Time));
556 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
557 (int)ts.tv_sec, (int)utc.tv_sec,
558 (int)(utc.tv_sec - ts.tv_sec)));
559 val = (int)(utc.tv_sec - ts.tv_sec);
561 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
562 remain = seconds % MIN_TZ_ADJ;
563 if (remain >= (MIN_TZ_ADJ / 2))
564 result += MIN_TZ_ADJ;
567 server->timeAdj = result;
569 server->timeAdj = (int)tmp;
570 server->timeAdj *= 60; /* also in seconds */
572 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
575 /* BB get server time for time conversions and add
576 code to use it and timezone since this is not UTC */
578 if (rsp->EncryptionKeyLength ==
579 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
580 memcpy(server->cryptKey, rsp->EncryptionKey,
581 CIFS_CRYPTO_KEY_SIZE);
582 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
583 rc = -EIO; /* need cryptkey unless plain text */
587 cFYI(1, ("LANMAN negotiated"));
588 /* we will not end up setting signing flags - as no signing
589 was in LANMAN and server did not return the flags on */
591 #else /* weak security disabled */
592 } else if (pSMBr->hdr.WordCount == 13) {
593 cERROR(1, ("mount failed, cifs module not built "
594 "with CIFS_WEAK_PW_HASH support"));
596 #endif /* WEAK_PW_HASH */
598 } else if (pSMBr->hdr.WordCount != 17) {
603 /* else wct == 17 NTLM */
604 server->secMode = pSMBr->SecurityMode;
605 if ((server->secMode & SECMODE_USER) == 0)
606 cFYI(1, ("share mode security"));
608 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
609 #ifdef CONFIG_CIFS_WEAK_PW_HASH
610 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
611 #endif /* CIFS_WEAK_PW_HASH */
612 cERROR(1, ("Server requests plain text password"
613 " but client support disabled"));
615 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
616 server->secType = NTLMv2;
617 else if (secFlags & CIFSSEC_MAY_NTLM)
618 server->secType = NTLM;
619 else if (secFlags & CIFSSEC_MAY_NTLMV2)
620 server->secType = NTLMv2;
621 else if (secFlags & CIFSSEC_MAY_KRB5)
622 server->secType = Kerberos;
623 else if (secFlags & CIFSSEC_MAY_LANMAN)
624 server->secType = LANMAN;
625 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
626 else if (secFlags & CIFSSEC_MAY_PLNTXT)
631 cERROR(1, ("Invalid security type"));
634 /* else ... any others ...? */
636 /* one byte, so no need to convert this or EncryptionKeyLen from
638 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
639 /* probably no need to store and check maxvcs */
640 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
641 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
642 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
643 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
644 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
645 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
646 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
647 server->timeAdj *= 60;
648 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
649 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
650 CIFS_CRYPTO_KEY_SIZE);
651 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
652 && (pSMBr->EncryptionKeyLength == 0)) {
653 /* decode security blob */
654 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
655 rc = -EIO; /* no crypt key only if plain text pwd */
659 /* BB might be helpful to save off the domain of server here */
661 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
662 (server->capabilities & CAP_EXTENDED_SECURITY)) {
663 count = pSMBr->ByteCount;
669 if (server->socketUseCount.counter > 1) {
670 if (memcmp(server->server_GUID,
671 pSMBr->u.extended_response.
673 cFYI(1, ("server UID changed"));
674 memcpy(server->server_GUID,
675 pSMBr->u.extended_response.GUID,
679 memcpy(server->server_GUID,
680 pSMBr->u.extended_response.GUID, 16);
683 server->secType = RawNTLMSSP;
685 rc = decode_negTokenInit(pSMBr->u.extended_response.
695 server->capabilities &= ~CAP_EXTENDED_SECURITY;
697 #ifdef CONFIG_CIFS_WEAK_PW_HASH
700 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
701 /* MUST_SIGN already includes the MAY_SIGN FLAG
702 so if this is zero it means that signing is disabled */
703 cFYI(1, ("Signing disabled"));
704 if (server->secMode & SECMODE_SIGN_REQUIRED) {
705 cERROR(1, ("Server requires "
706 "packet signing to be enabled in "
707 "/proc/fs/cifs/SecurityFlags."));
711 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
712 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
713 /* signing required */
714 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
715 if ((server->secMode &
716 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
718 ("signing required but server lacks support"));
721 server->secMode |= SECMODE_SIGN_REQUIRED;
723 /* signing optional ie CIFSSEC_MAY_SIGN */
724 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
726 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
730 cifs_buf_release(pSMB);
732 cFYI(1, ("negprot rc %d", rc));
737 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
739 struct smb_hdr *smb_buffer;
742 cFYI(1, ("In tree disconnect"));
744 * If last user of the connection and
745 * connection alive - disconnect it
746 * If this is the last connection on the server session disconnect it
747 * (and inside session disconnect we should check if tcp socket needs
748 * to be freed and kernel thread woken up).
751 down(&tcon->tconSem);
755 atomic_dec(&tcon->useCount);
756 if (atomic_read(&tcon->useCount) > 0) {
761 /* No need to return error on this operation if tid invalidated and
762 closed on server already e.g. due to tcp session crashing */
763 if (tcon->tidStatus == CifsNeedReconnect) {
768 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
772 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
773 (void **)&smb_buffer);
779 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
781 cFYI(1, ("Tree disconnect failed %d", rc));
785 /* No need to return error on this operation if tid invalidated and
786 closed on server already e.g. due to tcp session crashing */
794 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
796 LOGOFF_ANDX_REQ *pSMB;
799 cFYI(1, ("In SMBLogoff for session disconnect"));
805 atomic_dec(&ses->inUse);
806 if (atomic_read(&ses->inUse) > 0) {
810 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
817 pSMB->hdr.Mid = GetNextMid(ses->server);
819 if (ses->server->secMode &
820 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
821 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
824 pSMB->hdr.Uid = ses->Suid;
826 pSMB->AndXCommand = 0xFF;
827 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
829 atomic_dec(&ses->server->socketUseCount);
830 if (atomic_read(&ses->server->socketUseCount) == 0) {
831 spin_lock(&GlobalMid_Lock);
832 ses->server->tcpStatus = CifsExiting;
833 spin_unlock(&GlobalMid_Lock);
839 /* if session dead then we do not need to do ulogoff,
840 since server closed smb session, no sense reporting
848 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
849 __u16 type, const struct nls_table *nls_codepage, int remap)
851 TRANSACTION2_SPI_REQ *pSMB = NULL;
852 TRANSACTION2_SPI_RSP *pSMBr = NULL;
853 struct unlink_psx_rq *pRqD;
856 int bytes_returned = 0;
857 __u16 params, param_offset, offset, byte_count;
859 cFYI(1, ("In POSIX delete"));
861 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
866 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
868 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
869 PATH_MAX, nls_codepage, remap);
870 name_len++; /* trailing null */
872 } else { /* BB add path length overrun check */
873 name_len = strnlen(fileName, PATH_MAX);
874 name_len++; /* trailing null */
875 strncpy(pSMB->FileName, fileName, name_len);
878 params = 6 + name_len;
879 pSMB->MaxParameterCount = cpu_to_le16(2);
880 pSMB->MaxDataCount = 0; /* BB double check this with jra */
881 pSMB->MaxSetupCount = 0;
886 param_offset = offsetof(struct smb_com_transaction2_spi_req,
887 InformationLevel) - 4;
888 offset = param_offset + params;
890 /* Setup pointer to Request Data (inode type) */
891 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
892 pRqD->type = cpu_to_le16(type);
893 pSMB->ParameterOffset = cpu_to_le16(param_offset);
894 pSMB->DataOffset = cpu_to_le16(offset);
895 pSMB->SetupCount = 1;
897 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
898 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
900 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
901 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
902 pSMB->ParameterCount = cpu_to_le16(params);
903 pSMB->TotalParameterCount = pSMB->ParameterCount;
904 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
906 pSMB->hdr.smb_buf_length += byte_count;
907 pSMB->ByteCount = cpu_to_le16(byte_count);
908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
909 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
911 cFYI(1, ("Posix delete returned %d", rc));
912 cifs_buf_release(pSMB);
914 cifs_stats_inc(&tcon->num_deletes);
923 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
924 const struct nls_table *nls_codepage, int remap)
926 DELETE_FILE_REQ *pSMB = NULL;
927 DELETE_FILE_RSP *pSMBr = NULL;
933 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
938 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
940 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
941 PATH_MAX, nls_codepage, remap);
942 name_len++; /* trailing null */
944 } else { /* BB improve check for buffer overruns BB */
945 name_len = strnlen(fileName, PATH_MAX);
946 name_len++; /* trailing null */
947 strncpy(pSMB->fileName, fileName, name_len);
949 pSMB->SearchAttributes =
950 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
951 pSMB->BufferFormat = 0x04;
952 pSMB->hdr.smb_buf_length += name_len + 1;
953 pSMB->ByteCount = cpu_to_le16(name_len + 1);
954 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
955 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
956 cifs_stats_inc(&tcon->num_deletes);
958 cFYI(1, ("Error in RMFile = %d", rc));
960 cifs_buf_release(pSMB);
968 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
969 const struct nls_table *nls_codepage, int remap)
971 DELETE_DIRECTORY_REQ *pSMB = NULL;
972 DELETE_DIRECTORY_RSP *pSMBr = NULL;
977 cFYI(1, ("In CIFSSMBRmDir"));
979 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
984 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
985 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
986 PATH_MAX, nls_codepage, remap);
987 name_len++; /* trailing null */
989 } else { /* BB improve check for buffer overruns BB */
990 name_len = strnlen(dirName, PATH_MAX);
991 name_len++; /* trailing null */
992 strncpy(pSMB->DirName, dirName, name_len);
995 pSMB->BufferFormat = 0x04;
996 pSMB->hdr.smb_buf_length += name_len + 1;
997 pSMB->ByteCount = cpu_to_le16(name_len + 1);
998 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
999 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1000 cifs_stats_inc(&tcon->num_rmdirs);
1002 cFYI(1, ("Error in RMDir = %d", rc));
1004 cifs_buf_release(pSMB);
1011 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
1012 const char *name, const struct nls_table *nls_codepage, int remap)
1015 CREATE_DIRECTORY_REQ *pSMB = NULL;
1016 CREATE_DIRECTORY_RSP *pSMBr = NULL;
1020 cFYI(1, ("In CIFSSMBMkDir"));
1022 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1027 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1028 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1029 PATH_MAX, nls_codepage, remap);
1030 name_len++; /* trailing null */
1032 } else { /* BB improve check for buffer overruns BB */
1033 name_len = strnlen(name, PATH_MAX);
1034 name_len++; /* trailing null */
1035 strncpy(pSMB->DirName, name, name_len);
1038 pSMB->BufferFormat = 0x04;
1039 pSMB->hdr.smb_buf_length += name_len + 1;
1040 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1041 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1042 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1043 cifs_stats_inc(&tcon->num_mkdirs);
1045 cFYI(1, ("Error in Mkdir = %d", rc));
1047 cifs_buf_release(pSMB);
1054 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1055 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1056 __u32 *pOplock, const char *name,
1057 const struct nls_table *nls_codepage, int remap)
1059 TRANSACTION2_SPI_REQ *pSMB = NULL;
1060 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1063 int bytes_returned = 0;
1064 __u16 params, param_offset, offset, byte_count, count;
1065 OPEN_PSX_REQ *pdata;
1066 OPEN_PSX_RSP *psx_rsp;
1068 cFYI(1, ("In POSIX Create"));
1070 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1075 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1077 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1078 PATH_MAX, nls_codepage, remap);
1079 name_len++; /* trailing null */
1081 } else { /* BB improve the check for buffer overruns BB */
1082 name_len = strnlen(name, PATH_MAX);
1083 name_len++; /* trailing null */
1084 strncpy(pSMB->FileName, name, name_len);
1087 params = 6 + name_len;
1088 count = sizeof(OPEN_PSX_REQ);
1089 pSMB->MaxParameterCount = cpu_to_le16(2);
1090 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1091 pSMB->MaxSetupCount = 0;
1095 pSMB->Reserved2 = 0;
1096 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1097 InformationLevel) - 4;
1098 offset = param_offset + params;
1099 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1100 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1101 pdata->Permissions = cpu_to_le64(mode);
1102 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1103 pdata->OpenFlags = cpu_to_le32(*pOplock);
1104 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1105 pSMB->DataOffset = cpu_to_le16(offset);
1106 pSMB->SetupCount = 1;
1107 pSMB->Reserved3 = 0;
1108 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1109 byte_count = 3 /* pad */ + params + count;
1111 pSMB->DataCount = cpu_to_le16(count);
1112 pSMB->ParameterCount = cpu_to_le16(params);
1113 pSMB->TotalDataCount = pSMB->DataCount;
1114 pSMB->TotalParameterCount = pSMB->ParameterCount;
1115 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1116 pSMB->Reserved4 = 0;
1117 pSMB->hdr.smb_buf_length += byte_count;
1118 pSMB->ByteCount = cpu_to_le16(byte_count);
1119 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1120 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1122 cFYI(1, ("Posix create returned %d", rc));
1123 goto psx_create_err;
1126 cFYI(1, ("copying inode info"));
1127 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1129 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1130 rc = -EIO; /* bad smb */
1131 goto psx_create_err;
1134 /* copy return information to pRetData */
1135 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1136 + le16_to_cpu(pSMBr->t2.DataOffset));
1138 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1140 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1141 /* Let caller know file was created so we can set the mode. */
1142 /* Do we care about the CreateAction in any other cases? */
1143 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1144 *pOplock |= CIFS_CREATE_ACTION;
1145 /* check to make sure response data is there */
1146 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1147 pRetData->Type = cpu_to_le32(-1); /* unknown */
1148 cFYI(DBG2, ("unknown type"));
1150 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1151 + sizeof(FILE_UNIX_BASIC_INFO)) {
1152 cERROR(1, ("Open response data too small"));
1153 pRetData->Type = cpu_to_le32(-1);
1154 goto psx_create_err;
1156 memcpy((char *) pRetData,
1157 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1158 sizeof(FILE_UNIX_BASIC_INFO));
1162 cifs_buf_release(pSMB);
1164 cifs_stats_inc(&tcon->num_mkdirs);
1172 static __u16 convert_disposition(int disposition)
1176 switch (disposition) {
1177 case FILE_SUPERSEDE:
1178 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1181 ofun = SMBOPEN_OAPPEND;
1184 ofun = SMBOPEN_OCREATE;
1187 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1189 case FILE_OVERWRITE:
1190 ofun = SMBOPEN_OTRUNC;
1192 case FILE_OVERWRITE_IF:
1193 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1196 cFYI(1, ("unknown disposition %d", disposition));
1197 ofun = SMBOPEN_OAPPEND; /* regular open */
1203 access_flags_to_smbopen_mode(const int access_flags)
1205 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1207 if (masked_flags == GENERIC_READ)
1208 return SMBOPEN_READ;
1209 else if (masked_flags == GENERIC_WRITE)
1210 return SMBOPEN_WRITE;
1212 /* just go for read/write */
1213 return SMBOPEN_READWRITE;
1217 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1218 const char *fileName, const int openDisposition,
1219 const int access_flags, const int create_options, __u16 *netfid,
1220 int *pOplock, FILE_ALL_INFO *pfile_info,
1221 const struct nls_table *nls_codepage, int remap)
1224 OPENX_REQ *pSMB = NULL;
1225 OPENX_RSP *pSMBr = NULL;
1231 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1236 pSMB->AndXCommand = 0xFF; /* none */
1238 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1239 count = 1; /* account for one byte pad to word boundary */
1241 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1242 fileName, PATH_MAX, nls_codepage, remap);
1243 name_len++; /* trailing null */
1245 } else { /* BB improve check for buffer overruns BB */
1246 count = 0; /* no pad */
1247 name_len = strnlen(fileName, PATH_MAX);
1248 name_len++; /* trailing null */
1249 strncpy(pSMB->fileName, fileName, name_len);
1251 if (*pOplock & REQ_OPLOCK)
1252 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1253 else if (*pOplock & REQ_BATCHOPLOCK)
1254 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1256 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1257 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1258 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1259 /* set file as system file if special file such
1260 as fifo and server expecting SFU style and
1261 no Unix extensions */
1263 if (create_options & CREATE_OPTION_SPECIAL)
1264 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1265 else /* BB FIXME BB */
1266 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1268 if (create_options & CREATE_OPTION_READONLY)
1269 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1272 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1273 CREATE_OPTIONS_MASK); */
1274 /* BB FIXME END BB */
1276 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1277 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1279 pSMB->hdr.smb_buf_length += count;
1281 pSMB->ByteCount = cpu_to_le16(count);
1282 /* long_op set to 1 to allow for oplock break timeouts */
1283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1284 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1285 cifs_stats_inc(&tcon->num_opens);
1287 cFYI(1, ("Error in Open = %d", rc));
1289 /* BB verify if wct == 15 */
1291 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1293 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1294 /* Let caller know file was created so we can set the mode. */
1295 /* Do we care about the CreateAction in any other cases? */
1297 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1298 *pOplock |= CIFS_CREATE_ACTION; */
1302 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1303 pfile_info->LastAccessTime = 0; /* BB fixme */
1304 pfile_info->LastWriteTime = 0; /* BB fixme */
1305 pfile_info->ChangeTime = 0; /* BB fixme */
1306 pfile_info->Attributes =
1307 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1308 /* the file_info buf is endian converted by caller */
1309 pfile_info->AllocationSize =
1310 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1311 pfile_info->EndOfFile = pfile_info->AllocationSize;
1312 pfile_info->NumberOfLinks = cpu_to_le32(1);
1316 cifs_buf_release(pSMB);
1323 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1324 const char *fileName, const int openDisposition,
1325 const int access_flags, const int create_options, __u16 *netfid,
1326 int *pOplock, FILE_ALL_INFO *pfile_info,
1327 const struct nls_table *nls_codepage, int remap)
1330 OPEN_REQ *pSMB = NULL;
1331 OPEN_RSP *pSMBr = NULL;
1337 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1342 pSMB->AndXCommand = 0xFF; /* none */
1344 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1345 count = 1; /* account for one byte pad to word boundary */
1347 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1348 fileName, PATH_MAX, nls_codepage, remap);
1349 name_len++; /* trailing null */
1351 pSMB->NameLength = cpu_to_le16(name_len);
1352 } else { /* BB improve check for buffer overruns BB */
1353 count = 0; /* no pad */
1354 name_len = strnlen(fileName, PATH_MAX);
1355 name_len++; /* trailing null */
1356 pSMB->NameLength = cpu_to_le16(name_len);
1357 strncpy(pSMB->fileName, fileName, name_len);
1359 if (*pOplock & REQ_OPLOCK)
1360 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1361 else if (*pOplock & REQ_BATCHOPLOCK)
1362 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1363 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1364 pSMB->AllocationSize = 0;
1365 /* set file as system file if special file such
1366 as fifo and server expecting SFU style and
1367 no Unix extensions */
1368 if (create_options & CREATE_OPTION_SPECIAL)
1369 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1371 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1373 /* XP does not handle ATTR_POSIX_SEMANTICS */
1374 /* but it helps speed up case sensitive checks for other
1375 servers such as Samba */
1376 if (tcon->ses->capabilities & CAP_UNIX)
1377 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1379 if (create_options & CREATE_OPTION_READONLY)
1380 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1382 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1383 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1384 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1385 /* BB Expirement with various impersonation levels and verify */
1386 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1387 pSMB->SecurityFlags =
1388 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1391 pSMB->hdr.smb_buf_length += count;
1393 pSMB->ByteCount = cpu_to_le16(count);
1394 /* long_op set to 1 to allow for oplock break timeouts */
1395 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1396 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1397 cifs_stats_inc(&tcon->num_opens);
1399 cFYI(1, ("Error in Open = %d", rc));
1401 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1402 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1403 /* Let caller know file was created so we can set the mode. */
1404 /* Do we care about the CreateAction in any other cases? */
1405 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1406 *pOplock |= CIFS_CREATE_ACTION;
1408 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1409 36 /* CreationTime to Attributes */);
1410 /* the file_info buf is endian converted by caller */
1411 pfile_info->AllocationSize = pSMBr->AllocationSize;
1412 pfile_info->EndOfFile = pSMBr->EndOfFile;
1413 pfile_info->NumberOfLinks = cpu_to_le32(1);
1417 cifs_buf_release(pSMB);
1424 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1425 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1426 char **buf, int *pbuf_type)
1429 READ_REQ *pSMB = NULL;
1430 READ_RSP *pSMBr = NULL;
1431 char *pReadData = NULL;
1433 int resp_buf_type = 0;
1436 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1437 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1440 wct = 10; /* old style read */
1443 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1447 /* tcon and ses pointer are checked in smb_init */
1448 if (tcon->ses->server == NULL)
1449 return -ECONNABORTED;
1451 pSMB->AndXCommand = 0xFF; /* none */
1453 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1455 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1456 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1459 pSMB->Remaining = 0;
1460 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1461 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1463 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1465 /* old style read */
1466 struct smb_com_readx_req *pSMBW =
1467 (struct smb_com_readx_req *)pSMB;
1468 pSMBW->ByteCount = 0;
1471 iov[0].iov_base = (char *)pSMB;
1472 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1473 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1474 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1475 cifs_stats_inc(&tcon->num_reads);
1476 pSMBr = (READ_RSP *)iov[0].iov_base;
1478 cERROR(1, ("Send error in read = %d", rc));
1480 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1481 data_length = data_length << 16;
1482 data_length += le16_to_cpu(pSMBr->DataLength);
1483 *nbytes = data_length;
1485 /*check that DataLength would not go beyond end of SMB */
1486 if ((data_length > CIFSMaxBufSize)
1487 || (data_length > count)) {
1488 cFYI(1, ("bad length %d for count %d",
1489 data_length, count));
1493 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1494 le16_to_cpu(pSMBr->DataOffset);
1495 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1496 cERROR(1,("Faulting on read rc = %d",rc));
1498 }*/ /* can not use copy_to_user when using page cache*/
1500 memcpy(*buf, pReadData, data_length);
1504 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1506 if (resp_buf_type == CIFS_SMALL_BUFFER)
1507 cifs_small_buf_release(iov[0].iov_base);
1508 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1509 cifs_buf_release(iov[0].iov_base);
1510 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1511 /* return buffer to caller to free */
1512 *buf = iov[0].iov_base;
1513 if (resp_buf_type == CIFS_SMALL_BUFFER)
1514 *pbuf_type = CIFS_SMALL_BUFFER;
1515 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1516 *pbuf_type = CIFS_LARGE_BUFFER;
1517 } /* else no valid buffer on return - leave as null */
1519 /* Note: On -EAGAIN error only caller can retry on handle based calls
1520 since file handle passed in no longer valid */
1526 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1527 const int netfid, const unsigned int count,
1528 const __u64 offset, unsigned int *nbytes, const char *buf,
1529 const char __user *ubuf, const int long_op)
1532 WRITE_REQ *pSMB = NULL;
1533 WRITE_RSP *pSMBr = NULL;
1534 int bytes_returned, wct;
1538 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1539 if (tcon->ses == NULL)
1540 return -ECONNABORTED;
1542 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1547 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1551 /* tcon and ses pointer are checked in smb_init */
1552 if (tcon->ses->server == NULL)
1553 return -ECONNABORTED;
1555 pSMB->AndXCommand = 0xFF; /* none */
1557 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1559 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1560 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1563 pSMB->Reserved = 0xFFFFFFFF;
1564 pSMB->WriteMode = 0;
1565 pSMB->Remaining = 0;
1567 /* Can increase buffer size if buffer is big enough in some cases ie we
1568 can send more if LARGE_WRITE_X capability returned by the server and if
1569 our buffer is big enough or if we convert to iovecs on socket writes
1570 and eliminate the copy to the CIFS buffer */
1571 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1572 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1574 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1578 if (bytes_sent > count)
1581 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1583 memcpy(pSMB->Data, buf, bytes_sent);
1585 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1586 cifs_buf_release(pSMB);
1589 } else if (count != 0) {
1591 cifs_buf_release(pSMB);
1593 } /* else setting file size with write of zero bytes */
1595 byte_count = bytes_sent + 1; /* pad */
1596 else /* wct == 12 */
1597 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1599 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1600 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1601 pSMB->hdr.smb_buf_length += byte_count;
1604 pSMB->ByteCount = cpu_to_le16(byte_count);
1605 else { /* old style write has byte count 4 bytes earlier
1607 struct smb_com_writex_req *pSMBW =
1608 (struct smb_com_writex_req *)pSMB;
1609 pSMBW->ByteCount = cpu_to_le16(byte_count);
1612 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1613 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1614 cifs_stats_inc(&tcon->num_writes);
1616 cFYI(1, ("Send error in write = %d", rc));
1619 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1620 *nbytes = (*nbytes) << 16;
1621 *nbytes += le16_to_cpu(pSMBr->Count);
1624 cifs_buf_release(pSMB);
1626 /* Note: On -EAGAIN error only caller can retry on handle based calls
1627 since file handle passed in no longer valid */
1633 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1634 const int netfid, const unsigned int count,
1635 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1636 int n_vec, const int long_op)
1639 WRITE_REQ *pSMB = NULL;
1642 int resp_buf_type = 0;
1644 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1646 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1650 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1653 /* tcon and ses pointer are checked in smb_init */
1654 if (tcon->ses->server == NULL)
1655 return -ECONNABORTED;
1657 pSMB->AndXCommand = 0xFF; /* none */
1659 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1661 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1662 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1664 pSMB->Reserved = 0xFFFFFFFF;
1665 pSMB->WriteMode = 0;
1666 pSMB->Remaining = 0;
1669 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1671 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1672 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1673 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1675 pSMB->hdr.smb_buf_length += count+1;
1676 else /* wct == 12 */
1677 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1679 pSMB->ByteCount = cpu_to_le16(count + 1);
1680 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1681 struct smb_com_writex_req *pSMBW =
1682 (struct smb_com_writex_req *)pSMB;
1683 pSMBW->ByteCount = cpu_to_le16(count + 5);
1685 iov[0].iov_base = pSMB;
1687 iov[0].iov_len = smb_hdr_len + 4;
1688 else /* wct == 12 pad bigger by four bytes */
1689 iov[0].iov_len = smb_hdr_len + 8;
1692 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1694 cifs_stats_inc(&tcon->num_writes);
1696 cFYI(1, ("Send error Write2 = %d", rc));
1698 } else if (resp_buf_type == 0) {
1699 /* presumably this can not happen, but best to be safe */
1703 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1704 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1705 *nbytes = (*nbytes) << 16;
1706 *nbytes += le16_to_cpu(pSMBr->Count);
1709 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1710 if (resp_buf_type == CIFS_SMALL_BUFFER)
1711 cifs_small_buf_release(iov[0].iov_base);
1712 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1713 cifs_buf_release(iov[0].iov_base);
1715 /* Note: On -EAGAIN error only caller can retry on handle based calls
1716 since file handle passed in no longer valid */
1723 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1724 const __u16 smb_file_id, const __u64 len,
1725 const __u64 offset, const __u32 numUnlock,
1726 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1729 LOCK_REQ *pSMB = NULL;
1730 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1735 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1736 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1741 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1742 timeout = CIFS_ASYNC_OP; /* no response expected */
1744 } else if (waitFlag) {
1745 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1746 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1751 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1752 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1753 pSMB->LockType = lockType;
1754 pSMB->AndXCommand = 0xFF; /* none */
1755 pSMB->Fid = smb_file_id; /* netfid stays le */
1757 if ((numLock != 0) || (numUnlock != 0)) {
1758 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1759 /* BB where to store pid high? */
1760 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1761 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1762 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1763 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1764 count = sizeof(LOCKING_ANDX_RANGE);
1769 pSMB->hdr.smb_buf_length += count;
1770 pSMB->ByteCount = cpu_to_le16(count);
1773 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1774 (struct smb_hdr *) pSMB, &bytes_returned);
1775 cifs_small_buf_release(pSMB);
1777 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1779 /* SMB buffer freed by function above */
1781 cifs_stats_inc(&tcon->num_locks);
1783 cFYI(1, ("Send error in Lock = %d", rc));
1785 /* Note: On -EAGAIN error only caller can retry on handle based calls
1786 since file handle passed in no longer valid */
1791 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1792 const __u16 smb_file_id, const int get_flag, const __u64 len,
1793 struct file_lock *pLockData, const __u16 lock_type,
1794 const bool waitFlag)
1796 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1797 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1798 struct cifs_posix_lock *parm_data;
1801 int bytes_returned = 0;
1802 int resp_buf_type = 0;
1803 __u16 params, param_offset, offset, byte_count, count;
1806 cFYI(1, ("Posix Lock"));
1808 if (pLockData == NULL)
1811 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1816 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1819 pSMB->MaxSetupCount = 0;
1822 pSMB->Reserved2 = 0;
1823 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1824 offset = param_offset + params;
1826 count = sizeof(struct cifs_posix_lock);
1827 pSMB->MaxParameterCount = cpu_to_le16(2);
1828 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1829 pSMB->SetupCount = 1;
1830 pSMB->Reserved3 = 0;
1832 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1834 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1835 byte_count = 3 /* pad */ + params + count;
1836 pSMB->DataCount = cpu_to_le16(count);
1837 pSMB->ParameterCount = cpu_to_le16(params);
1838 pSMB->TotalDataCount = pSMB->DataCount;
1839 pSMB->TotalParameterCount = pSMB->ParameterCount;
1840 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1841 parm_data = (struct cifs_posix_lock *)
1842 (((char *) &pSMB->hdr.Protocol) + offset);
1844 parm_data->lock_type = cpu_to_le16(lock_type);
1846 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1847 parm_data->lock_flags = cpu_to_le16(1);
1848 pSMB->Timeout = cpu_to_le32(-1);
1852 parm_data->pid = cpu_to_le32(current->tgid);
1853 parm_data->start = cpu_to_le64(pLockData->fl_start);
1854 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1856 pSMB->DataOffset = cpu_to_le16(offset);
1857 pSMB->Fid = smb_file_id;
1858 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1859 pSMB->Reserved4 = 0;
1860 pSMB->hdr.smb_buf_length += byte_count;
1861 pSMB->ByteCount = cpu_to_le16(byte_count);
1863 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1864 (struct smb_hdr *) pSMBr, &bytes_returned);
1866 iov[0].iov_base = (char *)pSMB;
1867 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1868 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1869 &resp_buf_type, timeout);
1870 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1871 not try to free it twice below on exit */
1872 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1876 cFYI(1, ("Send error in Posix Lock = %d", rc));
1877 } else if (get_flag) {
1878 /* lock structure can be returned on get */
1881 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1883 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1884 rc = -EIO; /* bad smb */
1887 if (pLockData == NULL) {
1891 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1892 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1893 if (data_count < sizeof(struct cifs_posix_lock)) {
1897 parm_data = (struct cifs_posix_lock *)
1898 ((char *)&pSMBr->hdr.Protocol + data_offset);
1899 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1900 pLockData->fl_type = F_UNLCK;
1905 cifs_small_buf_release(pSMB);
1907 if (resp_buf_type == CIFS_SMALL_BUFFER)
1908 cifs_small_buf_release(iov[0].iov_base);
1909 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1910 cifs_buf_release(iov[0].iov_base);
1912 /* Note: On -EAGAIN error only caller can retry on handle based calls
1913 since file handle passed in no longer valid */
1920 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1923 CLOSE_REQ *pSMB = NULL;
1924 cFYI(1, ("In CIFSSMBClose"));
1926 /* do not retry on dead session on close */
1927 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1933 pSMB->FileID = (__u16) smb_file_id;
1934 pSMB->LastWriteTime = 0xFFFFFFFF;
1935 pSMB->ByteCount = 0;
1936 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1937 cifs_stats_inc(&tcon->num_closes);
1940 /* EINTR is expected when user ctl-c to kill app */
1941 cERROR(1, ("Send error in Close = %d", rc));
1945 /* Since session is dead, file will be closed on server already */
1953 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1954 const char *fromName, const char *toName,
1955 const struct nls_table *nls_codepage, int remap)
1958 RENAME_REQ *pSMB = NULL;
1959 RENAME_RSP *pSMBr = NULL;
1961 int name_len, name_len2;
1964 cFYI(1, ("In CIFSSMBRename"));
1966 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1971 pSMB->BufferFormat = 0x04;
1972 pSMB->SearchAttributes =
1973 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1976 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1978 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1979 PATH_MAX, nls_codepage, remap);
1980 name_len++; /* trailing null */
1982 pSMB->OldFileName[name_len] = 0x04; /* pad */
1983 /* protocol requires ASCII signature byte on Unicode string */
1984 pSMB->OldFileName[name_len + 1] = 0x00;
1986 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1987 toName, PATH_MAX, nls_codepage, remap);
1988 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1989 name_len2 *= 2; /* convert to bytes */
1990 } else { /* BB improve the check for buffer overruns BB */
1991 name_len = strnlen(fromName, PATH_MAX);
1992 name_len++; /* trailing null */
1993 strncpy(pSMB->OldFileName, fromName, name_len);
1994 name_len2 = strnlen(toName, PATH_MAX);
1995 name_len2++; /* trailing null */
1996 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1997 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1998 name_len2++; /* trailing null */
1999 name_len2++; /* signature byte */
2002 count = 1 /* 1st signature byte */ + name_len + name_len2;
2003 pSMB->hdr.smb_buf_length += count;
2004 pSMB->ByteCount = cpu_to_le16(count);
2006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2008 cifs_stats_inc(&tcon->num_renames);
2010 cFYI(1, ("Send error in rename = %d", rc));
2012 cifs_buf_release(pSMB);
2020 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2021 int netfid, char *target_name,
2022 const struct nls_table *nls_codepage, int remap)
2024 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2025 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2026 struct set_file_rename *rename_info;
2028 char dummy_string[30];
2030 int bytes_returned = 0;
2032 __u16 params, param_offset, offset, count, byte_count;
2034 cFYI(1, ("Rename to File by handle"));
2035 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2041 pSMB->MaxSetupCount = 0;
2045 pSMB->Reserved2 = 0;
2046 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2047 offset = param_offset + params;
2049 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2050 rename_info = (struct set_file_rename *) data_offset;
2051 pSMB->MaxParameterCount = cpu_to_le16(2);
2052 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2053 pSMB->SetupCount = 1;
2054 pSMB->Reserved3 = 0;
2055 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2056 byte_count = 3 /* pad */ + params;
2057 pSMB->ParameterCount = cpu_to_le16(params);
2058 pSMB->TotalParameterCount = pSMB->ParameterCount;
2059 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2060 pSMB->DataOffset = cpu_to_le16(offset);
2061 /* construct random name ".cifs_tmp<inodenum><mid>" */
2062 rename_info->overwrite = cpu_to_le32(1);
2063 rename_info->root_fid = 0;
2064 /* unicode only call */
2065 if (target_name == NULL) {
2066 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2067 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2068 dummy_string, 24, nls_codepage, remap);
2070 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2071 target_name, PATH_MAX, nls_codepage,
2074 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2075 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2076 byte_count += count;
2077 pSMB->DataCount = cpu_to_le16(count);
2078 pSMB->TotalDataCount = pSMB->DataCount;
2080 pSMB->InformationLevel =
2081 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2082 pSMB->Reserved4 = 0;
2083 pSMB->hdr.smb_buf_length += byte_count;
2084 pSMB->ByteCount = cpu_to_le16(byte_count);
2085 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2086 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2087 cifs_stats_inc(&pTcon->num_t2renames);
2089 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2091 cifs_buf_release(pSMB);
2093 /* Note: On -EAGAIN error only caller can retry on handle based calls
2094 since file handle passed in no longer valid */
2100 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2101 const __u16 target_tid, const char *toName, const int flags,
2102 const struct nls_table *nls_codepage, int remap)
2105 COPY_REQ *pSMB = NULL;
2106 COPY_RSP *pSMBr = NULL;
2108 int name_len, name_len2;
2111 cFYI(1, ("In CIFSSMBCopy"));
2113 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2118 pSMB->BufferFormat = 0x04;
2119 pSMB->Tid2 = target_tid;
2121 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2123 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2124 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2125 fromName, PATH_MAX, nls_codepage,
2127 name_len++; /* trailing null */
2129 pSMB->OldFileName[name_len] = 0x04; /* pad */
2130 /* protocol requires ASCII signature byte on Unicode string */
2131 pSMB->OldFileName[name_len + 1] = 0x00;
2133 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2134 toName, PATH_MAX, nls_codepage, remap);
2135 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2136 name_len2 *= 2; /* convert to bytes */
2137 } else { /* BB improve the check for buffer overruns BB */
2138 name_len = strnlen(fromName, PATH_MAX);
2139 name_len++; /* trailing null */
2140 strncpy(pSMB->OldFileName, fromName, name_len);
2141 name_len2 = strnlen(toName, PATH_MAX);
2142 name_len2++; /* trailing null */
2143 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2144 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2145 name_len2++; /* trailing null */
2146 name_len2++; /* signature byte */
2149 count = 1 /* 1st signature byte */ + name_len + name_len2;
2150 pSMB->hdr.smb_buf_length += count;
2151 pSMB->ByteCount = cpu_to_le16(count);
2153 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2154 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2156 cFYI(1, ("Send error in copy = %d with %d files copied",
2157 rc, le16_to_cpu(pSMBr->CopyCount)));
2159 cifs_buf_release(pSMB);
2168 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2169 const char *fromName, const char *toName,
2170 const struct nls_table *nls_codepage)
2172 TRANSACTION2_SPI_REQ *pSMB = NULL;
2173 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2176 int name_len_target;
2178 int bytes_returned = 0;
2179 __u16 params, param_offset, offset, byte_count;
2181 cFYI(1, ("In Symlink Unix style"));
2183 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2188 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2190 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2191 /* find define for this maxpathcomponent */
2193 name_len++; /* trailing null */
2196 } else { /* BB improve the check for buffer overruns BB */
2197 name_len = strnlen(fromName, PATH_MAX);
2198 name_len++; /* trailing null */
2199 strncpy(pSMB->FileName, fromName, name_len);
2201 params = 6 + name_len;
2202 pSMB->MaxSetupCount = 0;
2206 pSMB->Reserved2 = 0;
2207 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2208 InformationLevel) - 4;
2209 offset = param_offset + params;
2211 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2212 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2214 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2215 /* find define for this maxpathcomponent */
2217 name_len_target++; /* trailing null */
2218 name_len_target *= 2;
2219 } else { /* BB improve the check for buffer overruns BB */
2220 name_len_target = strnlen(toName, PATH_MAX);
2221 name_len_target++; /* trailing null */
2222 strncpy(data_offset, toName, name_len_target);
2225 pSMB->MaxParameterCount = cpu_to_le16(2);
2226 /* BB find exact max on data count below from sess */
2227 pSMB->MaxDataCount = cpu_to_le16(1000);
2228 pSMB->SetupCount = 1;
2229 pSMB->Reserved3 = 0;
2230 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2231 byte_count = 3 /* pad */ + params + name_len_target;
2232 pSMB->DataCount = cpu_to_le16(name_len_target);
2233 pSMB->ParameterCount = cpu_to_le16(params);
2234 pSMB->TotalDataCount = pSMB->DataCount;
2235 pSMB->TotalParameterCount = pSMB->ParameterCount;
2236 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2237 pSMB->DataOffset = cpu_to_le16(offset);
2238 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2239 pSMB->Reserved4 = 0;
2240 pSMB->hdr.smb_buf_length += byte_count;
2241 pSMB->ByteCount = cpu_to_le16(byte_count);
2242 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2243 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2244 cifs_stats_inc(&tcon->num_symlinks);
2246 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2248 cifs_buf_release(pSMB);
2251 goto createSymLinkRetry;
2257 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2258 const char *fromName, const char *toName,
2259 const struct nls_table *nls_codepage, int remap)
2261 TRANSACTION2_SPI_REQ *pSMB = NULL;
2262 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2265 int name_len_target;
2267 int bytes_returned = 0;
2268 __u16 params, param_offset, offset, byte_count;
2270 cFYI(1, ("In Create Hard link Unix style"));
2271 createHardLinkRetry:
2272 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2278 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2279 PATH_MAX, nls_codepage, remap);
2280 name_len++; /* trailing null */
2283 } else { /* BB improve the check for buffer overruns BB */
2284 name_len = strnlen(toName, PATH_MAX);
2285 name_len++; /* trailing null */
2286 strncpy(pSMB->FileName, toName, name_len);
2288 params = 6 + name_len;
2289 pSMB->MaxSetupCount = 0;
2293 pSMB->Reserved2 = 0;
2294 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2295 InformationLevel) - 4;
2296 offset = param_offset + params;
2298 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2299 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2301 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2302 nls_codepage, remap);
2303 name_len_target++; /* trailing null */
2304 name_len_target *= 2;
2305 } else { /* BB improve the check for buffer overruns BB */
2306 name_len_target = strnlen(fromName, PATH_MAX);
2307 name_len_target++; /* trailing null */
2308 strncpy(data_offset, fromName, name_len_target);
2311 pSMB->MaxParameterCount = cpu_to_le16(2);
2312 /* BB find exact max on data count below from sess*/
2313 pSMB->MaxDataCount = cpu_to_le16(1000);
2314 pSMB->SetupCount = 1;
2315 pSMB->Reserved3 = 0;
2316 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2317 byte_count = 3 /* pad */ + params + name_len_target;
2318 pSMB->ParameterCount = cpu_to_le16(params);
2319 pSMB->TotalParameterCount = pSMB->ParameterCount;
2320 pSMB->DataCount = cpu_to_le16(name_len_target);
2321 pSMB->TotalDataCount = pSMB->DataCount;
2322 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2323 pSMB->DataOffset = cpu_to_le16(offset);
2324 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2325 pSMB->Reserved4 = 0;
2326 pSMB->hdr.smb_buf_length += byte_count;
2327 pSMB->ByteCount = cpu_to_le16(byte_count);
2328 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2329 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2330 cifs_stats_inc(&tcon->num_hardlinks);
2332 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2334 cifs_buf_release(pSMB);
2336 goto createHardLinkRetry;
2342 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2343 const char *fromName, const char *toName,
2344 const struct nls_table *nls_codepage, int remap)
2347 NT_RENAME_REQ *pSMB = NULL;
2348 RENAME_RSP *pSMBr = NULL;
2350 int name_len, name_len2;
2353 cFYI(1, ("In CIFSCreateHardLink"));
2354 winCreateHardLinkRetry:
2356 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2361 pSMB->SearchAttributes =
2362 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2364 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2365 pSMB->ClusterCount = 0;
2367 pSMB->BufferFormat = 0x04;
2369 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2371 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2372 PATH_MAX, nls_codepage, remap);
2373 name_len++; /* trailing null */
2375 pSMB->OldFileName[name_len] = 0; /* pad */
2376 pSMB->OldFileName[name_len + 1] = 0x04;
2378 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2379 toName, PATH_MAX, nls_codepage, remap);
2380 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2381 name_len2 *= 2; /* convert to bytes */
2382 } else { /* BB improve the check for buffer overruns BB */
2383 name_len = strnlen(fromName, PATH_MAX);
2384 name_len++; /* trailing null */
2385 strncpy(pSMB->OldFileName, fromName, name_len);
2386 name_len2 = strnlen(toName, PATH_MAX);
2387 name_len2++; /* trailing null */
2388 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2389 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2390 name_len2++; /* trailing null */
2391 name_len2++; /* signature byte */
2394 count = 1 /* string type byte */ + name_len + name_len2;
2395 pSMB->hdr.smb_buf_length += count;
2396 pSMB->ByteCount = cpu_to_le16(count);
2398 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2399 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2400 cifs_stats_inc(&tcon->num_hardlinks);
2402 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2404 cifs_buf_release(pSMB);
2406 goto winCreateHardLinkRetry;
2412 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2413 const unsigned char *searchName,
2414 char *symlinkinfo, const int buflen,
2415 const struct nls_table *nls_codepage)
2417 /* SMB_QUERY_FILE_UNIX_LINK */
2418 TRANSACTION2_QPI_REQ *pSMB = NULL;
2419 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2423 __u16 params, byte_count;
2425 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2428 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2433 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2435 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2436 PATH_MAX, nls_codepage);
2437 name_len++; /* trailing null */
2439 } else { /* BB improve the check for buffer overruns BB */
2440 name_len = strnlen(searchName, PATH_MAX);
2441 name_len++; /* trailing null */
2442 strncpy(pSMB->FileName, searchName, name_len);
2445 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2446 pSMB->TotalDataCount = 0;
2447 pSMB->MaxParameterCount = cpu_to_le16(2);
2448 /* BB find exact max data count below from sess structure BB */
2449 pSMB->MaxDataCount = cpu_to_le16(4000);
2450 pSMB->MaxSetupCount = 0;
2454 pSMB->Reserved2 = 0;
2455 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2456 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2457 pSMB->DataCount = 0;
2458 pSMB->DataOffset = 0;
2459 pSMB->SetupCount = 1;
2460 pSMB->Reserved3 = 0;
2461 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2462 byte_count = params + 1 /* pad */ ;
2463 pSMB->TotalParameterCount = cpu_to_le16(params);
2464 pSMB->ParameterCount = pSMB->TotalParameterCount;
2465 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2466 pSMB->Reserved4 = 0;
2467 pSMB->hdr.smb_buf_length += byte_count;
2468 pSMB->ByteCount = cpu_to_le16(byte_count);
2470 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2471 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2473 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2475 /* decode response */
2477 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2478 if (rc || (pSMBr->ByteCount < 2))
2479 /* BB also check enough total bytes returned */
2480 rc = -EIO; /* bad smb */
2482 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2483 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2485 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2486 name_len = UniStrnlen((wchar_t *) ((char *)
2487 &pSMBr->hdr.Protocol + data_offset),
2488 min_t(const int, buflen, count) / 2);
2489 /* BB FIXME investigate remapping reserved chars here */
2490 cifs_strfromUCS_le(symlinkinfo,
2491 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2493 name_len, nls_codepage);
2495 strncpy(symlinkinfo,
2496 (char *) &pSMBr->hdr.Protocol +
2498 min_t(const int, buflen, count));
2500 symlinkinfo[buflen] = 0;
2501 /* just in case so calling code does not go off the end of buffer */
2504 cifs_buf_release(pSMB);
2506 goto querySymLinkRetry;
2510 #ifdef CONFIG_CIFS_EXPERIMENTAL
2511 /* Initialize NT TRANSACT SMB into small smb request buffer.
2512 This assumes that all NT TRANSACTS that we init here have
2513 total parm and data under about 400 bytes (to fit in small cifs
2514 buffer size), which is the case so far, it easily fits. NB:
2515 Setup words themselves and ByteCount
2516 MaxSetupCount (size of returned setup area) and
2517 MaxParameterCount (returned parms size) must be set by caller */
2519 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2520 const int parm_len, struct cifsTconInfo *tcon,
2525 struct smb_com_ntransact_req *pSMB;
2527 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2531 *ret_buf = (void *)pSMB;
2533 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2534 pSMB->TotalDataCount = 0;
2535 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2536 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2537 pSMB->ParameterCount = pSMB->TotalParameterCount;
2538 pSMB->DataCount = pSMB->TotalDataCount;
2539 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2540 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2541 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2542 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2543 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2544 pSMB->SubCommand = cpu_to_le16(sub_command);
2549 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2550 __u32 *pparmlen, __u32 *pdatalen)
2553 __u32 data_count, data_offset, parm_count, parm_offset;
2554 struct smb_com_ntransact_rsp *pSMBr;
2562 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2564 /* ByteCount was converted from little endian in SendReceive */
2565 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2566 (char *)&pSMBr->ByteCount;
2568 data_offset = le32_to_cpu(pSMBr->DataOffset);
2569 data_count = le32_to_cpu(pSMBr->DataCount);
2570 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2571 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2573 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2574 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2576 /* should we also check that parm and data areas do not overlap? */
2577 if (*ppparm > end_of_smb) {
2578 cFYI(1, ("parms start after end of smb"));
2580 } else if (parm_count + *ppparm > end_of_smb) {
2581 cFYI(1, ("parm end after end of smb"));
2583 } else if (*ppdata > end_of_smb) {
2584 cFYI(1, ("data starts after end of smb"));
2586 } else if (data_count + *ppdata > end_of_smb) {
2587 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2588 *ppdata, data_count, (data_count + *ppdata),
2589 end_of_smb, pSMBr));
2591 } else if (parm_count + data_count > pSMBr->ByteCount) {
2592 cFYI(1, ("parm count and data count larger than SMB"));
2595 *pdatalen = data_count;
2596 *pparmlen = parm_count;
2599 #endif /* CIFS_EXPERIMENTAL */
2602 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2603 const unsigned char *searchName,
2604 char *symlinkinfo, const int buflen, __u16 fid,
2605 const struct nls_table *nls_codepage)
2610 struct smb_com_transaction_ioctl_req *pSMB;
2611 struct smb_com_transaction_ioctl_rsp *pSMBr;
2613 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2614 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2619 pSMB->TotalParameterCount = 0 ;
2620 pSMB->TotalDataCount = 0;
2621 pSMB->MaxParameterCount = cpu_to_le32(2);
2622 /* BB find exact data count max from sess structure BB */
2623 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2624 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2625 pSMB->MaxSetupCount = 4;
2627 pSMB->ParameterOffset = 0;
2628 pSMB->DataCount = 0;
2629 pSMB->DataOffset = 0;
2630 pSMB->SetupCount = 4;
2631 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2632 pSMB->ParameterCount = pSMB->TotalParameterCount;
2633 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2634 pSMB->IsFsctl = 1; /* FSCTL */
2635 pSMB->IsRootFlag = 0;
2636 pSMB->Fid = fid; /* file handle always le */
2637 pSMB->ByteCount = 0;
2639 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2640 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2642 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2643 } else { /* decode response */
2644 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2645 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2646 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2647 /* BB also check enough total bytes returned */
2648 rc = -EIO; /* bad smb */
2650 if (data_count && (data_count < 2048)) {
2651 char *end_of_smb = 2 /* sizeof byte count */ +
2653 (char *)&pSMBr->ByteCount;
2655 struct reparse_data *reparse_buf =
2656 (struct reparse_data *)
2657 ((char *)&pSMBr->hdr.Protocol
2659 if ((char *)reparse_buf >= end_of_smb) {
2663 if ((reparse_buf->LinkNamesBuf +
2664 reparse_buf->TargetNameOffset +
2665 reparse_buf->TargetNameLen) >
2667 cFYI(1, ("reparse buf beyond SMB"));
2672 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2673 name_len = UniStrnlen((wchar_t *)
2674 (reparse_buf->LinkNamesBuf +
2675 reparse_buf->TargetNameOffset),
2677 reparse_buf->TargetNameLen / 2));
2678 cifs_strfromUCS_le(symlinkinfo,
2679 (__le16 *) (reparse_buf->LinkNamesBuf +
2680 reparse_buf->TargetNameOffset),
2681 name_len, nls_codepage);
2682 } else { /* ASCII names */
2683 strncpy(symlinkinfo,
2684 reparse_buf->LinkNamesBuf +
2685 reparse_buf->TargetNameOffset,
2686 min_t(const int, buflen,
2687 reparse_buf->TargetNameLen));
2691 cFYI(1, ("Invalid return data count on "
2692 "get reparse info ioctl"));
2694 symlinkinfo[buflen] = 0; /* just in case so the caller
2695 does not go off the end of the buffer */
2696 cFYI(1, ("readlink result - %s", symlinkinfo));
2700 cifs_buf_release(pSMB);
2702 /* Note: On -EAGAIN error only caller can retry on handle based calls
2703 since file handle passed in no longer valid */
2708 #ifdef CONFIG_CIFS_POSIX
2710 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2711 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2712 struct cifs_posix_ace *cifs_ace)
2714 /* u8 cifs fields do not need le conversion */
2715 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2716 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2717 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2718 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2723 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2724 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2725 const int acl_type, const int size_of_data_area)
2730 struct cifs_posix_ace *pACE;
2731 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2732 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2734 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2737 if (acl_type & ACL_TYPE_ACCESS) {
2738 count = le16_to_cpu(cifs_acl->access_entry_count);
2739 pACE = &cifs_acl->ace_array[0];
2740 size = sizeof(struct cifs_posix_acl);
2741 size += sizeof(struct cifs_posix_ace) * count;
2742 /* check if we would go beyond end of SMB */
2743 if (size_of_data_area < size) {
2744 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2745 size_of_data_area, size));
2748 } else if (acl_type & ACL_TYPE_DEFAULT) {
2749 count = le16_to_cpu(cifs_acl->access_entry_count);
2750 size = sizeof(struct cifs_posix_acl);
2751 size += sizeof(struct cifs_posix_ace) * count;
2752 /* skip past access ACEs to get to default ACEs */
2753 pACE = &cifs_acl->ace_array[count];
2754 count = le16_to_cpu(cifs_acl->default_entry_count);
2755 size += sizeof(struct cifs_posix_ace) * count;
2756 /* check if we would go beyond end of SMB */
2757 if (size_of_data_area < size)
2764 size = posix_acl_xattr_size(count);
2765 if ((buflen == 0) || (local_acl == NULL)) {
2766 /* used to query ACL EA size */
2767 } else if (size > buflen) {
2769 } else /* buffer big enough */ {
2770 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2771 for (i = 0; i < count ; i++) {
2772 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2779 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2780 const posix_acl_xattr_entry *local_ace)
2782 __u16 rc = 0; /* 0 = ACL converted ok */
2784 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2785 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2786 /* BB is there a better way to handle the large uid? */
2787 if (local_ace->e_id == cpu_to_le32(-1)) {
2788 /* Probably no need to le convert -1 on any arch but can not hurt */
2789 cifs_ace->cifs_uid = cpu_to_le64(-1);
2791 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2792 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2796 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2797 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2798 const int buflen, const int acl_type)
2801 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2802 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2806 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2809 count = posix_acl_xattr_count((size_t)buflen);
2810 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2812 count, buflen, le32_to_cpu(local_acl->a_version)));
2813 if (le32_to_cpu(local_acl->a_version) != 2) {
2814 cFYI(1, ("unknown POSIX ACL version %d",
2815 le32_to_cpu(local_acl->a_version)));
2818 cifs_acl->version = cpu_to_le16(1);
2819 if (acl_type == ACL_TYPE_ACCESS)
2820 cifs_acl->access_entry_count = cpu_to_le16(count);
2821 else if (acl_type == ACL_TYPE_DEFAULT)
2822 cifs_acl->default_entry_count = cpu_to_le16(count);
2824 cFYI(1, ("unknown ACL type %d", acl_type));
2827 for (i = 0; i < count; i++) {
2828 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2829 &local_acl->a_entries[i]);
2831 /* ACE not converted */
2836 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2837 rc += sizeof(struct cifs_posix_acl);
2838 /* BB add check to make sure ACL does not overflow SMB */
2844 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2845 const unsigned char *searchName,
2846 char *acl_inf, const int buflen, const int acl_type,
2847 const struct nls_table *nls_codepage, int remap)
2849 /* SMB_QUERY_POSIX_ACL */
2850 TRANSACTION2_QPI_REQ *pSMB = NULL;
2851 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2855 __u16 params, byte_count;
2857 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2860 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2865 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2867 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2868 PATH_MAX, nls_codepage, remap);
2869 name_len++; /* trailing null */
2871 pSMB->FileName[name_len] = 0;
2872 pSMB->FileName[name_len+1] = 0;
2873 } else { /* BB improve the check for buffer overruns BB */
2874 name_len = strnlen(searchName, PATH_MAX);
2875 name_len++; /* trailing null */
2876 strncpy(pSMB->FileName, searchName, name_len);
2879 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2880 pSMB->TotalDataCount = 0;
2881 pSMB->MaxParameterCount = cpu_to_le16(2);
2882 /* BB find exact max data count below from sess structure BB */
2883 pSMB->MaxDataCount = cpu_to_le16(4000);
2884 pSMB->MaxSetupCount = 0;
2888 pSMB->Reserved2 = 0;
2889 pSMB->ParameterOffset = cpu_to_le16(
2890 offsetof(struct smb_com_transaction2_qpi_req,
2891 InformationLevel) - 4);
2892 pSMB->DataCount = 0;
2893 pSMB->DataOffset = 0;
2894 pSMB->SetupCount = 1;
2895 pSMB->Reserved3 = 0;
2896 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2897 byte_count = params + 1 /* pad */ ;
2898 pSMB->TotalParameterCount = cpu_to_le16(params);
2899 pSMB->ParameterCount = pSMB->TotalParameterCount;
2900 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2901 pSMB->Reserved4 = 0;
2902 pSMB->hdr.smb_buf_length += byte_count;
2903 pSMB->ByteCount = cpu_to_le16(byte_count);
2905 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2906 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2907 cifs_stats_inc(&tcon->num_acl_get);
2909 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2911 /* decode response */
2913 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2914 if (rc || (pSMBr->ByteCount < 2))
2915 /* BB also check enough total bytes returned */
2916 rc = -EIO; /* bad smb */
2918 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2919 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2920 rc = cifs_copy_posix_acl(acl_inf,
2921 (char *)&pSMBr->hdr.Protocol+data_offset,
2922 buflen, acl_type, count);
2925 cifs_buf_release(pSMB);
2932 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2933 const unsigned char *fileName,
2934 const char *local_acl, const int buflen,
2936 const struct nls_table *nls_codepage, int remap)
2938 struct smb_com_transaction2_spi_req *pSMB = NULL;
2939 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2943 int bytes_returned = 0;
2944 __u16 params, byte_count, data_count, param_offset, offset;
2946 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2948 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2952 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2954 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2955 PATH_MAX, nls_codepage, remap);
2956 name_len++; /* trailing null */
2958 } else { /* BB improve the check for buffer overruns BB */
2959 name_len = strnlen(fileName, PATH_MAX);
2960 name_len++; /* trailing null */
2961 strncpy(pSMB->FileName, fileName, name_len);
2963 params = 6 + name_len;
2964 pSMB->MaxParameterCount = cpu_to_le16(2);
2965 /* BB find max SMB size from sess */
2966 pSMB->MaxDataCount = cpu_to_le16(1000);
2967 pSMB->MaxSetupCount = 0;
2971 pSMB->Reserved2 = 0;
2972 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2973 InformationLevel) - 4;
2974 offset = param_offset + params;
2975 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2976 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2978 /* convert to on the wire format for POSIX ACL */
2979 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2981 if (data_count == 0) {
2983 goto setACLerrorExit;
2985 pSMB->DataOffset = cpu_to_le16(offset);
2986 pSMB->SetupCount = 1;
2987 pSMB->Reserved3 = 0;
2988 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2989 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2990 byte_count = 3 /* pad */ + params + data_count;
2991 pSMB->DataCount = cpu_to_le16(data_count);
2992 pSMB->TotalDataCount = pSMB->DataCount;
2993 pSMB->ParameterCount = cpu_to_le16(params);
2994 pSMB->TotalParameterCount = pSMB->ParameterCount;
2995 pSMB->Reserved4 = 0;
2996 pSMB->hdr.smb_buf_length += byte_count;
2997 pSMB->ByteCount = cpu_to_le16(byte_count);
2998 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2999 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3001 cFYI(1, ("Set POSIX ACL returned %d", rc));
3004 cifs_buf_release(pSMB);
3010 /* BB fix tabs in this function FIXME BB */
3012 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3013 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3016 struct smb_t2_qfi_req *pSMB = NULL;
3017 struct smb_t2_qfi_rsp *pSMBr = NULL;
3019 __u16 params, byte_count;
3021 cFYI(1, ("In GetExtAttr"));
3026 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3031 params = 2 /* level */ + 2 /* fid */;
3032 pSMB->t2.TotalDataCount = 0;
3033 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3034 /* BB find exact max data count below from sess structure BB */
3035 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3036 pSMB->t2.MaxSetupCount = 0;
3037 pSMB->t2.Reserved = 0;
3039 pSMB->t2.Timeout = 0;
3040 pSMB->t2.Reserved2 = 0;
3041 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3043 pSMB->t2.DataCount = 0;
3044 pSMB->t2.DataOffset = 0;
3045 pSMB->t2.SetupCount = 1;
3046 pSMB->t2.Reserved3 = 0;
3047 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3048 byte_count = params + 1 /* pad */ ;
3049 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3050 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3051 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3054 pSMB->hdr.smb_buf_length += byte_count;
3055 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3057 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3058 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3060 cFYI(1, ("error %d in GetExtAttr", rc));
3062 /* decode response */
3063 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3064 if (rc || (pSMBr->ByteCount < 2))
3065 /* BB also check enough total bytes returned */
3066 /* If rc should we check for EOPNOSUPP and
3067 disable the srvino flag? or in caller? */
3068 rc = -EIO; /* bad smb */
3070 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3071 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3072 struct file_chattr_info *pfinfo;
3073 /* BB Do we need a cast or hash here ? */
3075 cFYI(1, ("Illegal size ret in GetExtAttr"));
3079 pfinfo = (struct file_chattr_info *)
3080 (data_offset + (char *) &pSMBr->hdr.Protocol);
3081 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3082 *pMask = le64_to_cpu(pfinfo->mask);
3086 cifs_buf_release(pSMB);
3088 goto GetExtAttrRetry;
3092 #endif /* CONFIG_POSIX */
3094 #ifdef CONFIG_CIFS_EXPERIMENTAL
3095 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3097 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3098 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3102 QUERY_SEC_DESC_REQ *pSMB;
3105 cFYI(1, ("GetCifsACL"));
3110 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3111 8 /* parm len */, tcon, (void **) &pSMB);
3115 pSMB->MaxParameterCount = cpu_to_le32(4);
3116 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3117 pSMB->MaxSetupCount = 0;
3118 pSMB->Fid = fid; /* file handle always le */
3119 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3121 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3122 pSMB->hdr.smb_buf_length += 11;
3123 iov[0].iov_base = (char *)pSMB;
3124 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3126 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3128 cifs_stats_inc(&tcon->num_acl_get);
3130 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3131 } else { /* decode response */
3135 struct smb_com_ntransact_rsp *pSMBr;
3138 /* validate_nttransact */
3139 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3140 &pdata, &parm_len, pbuflen);
3143 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3145 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3147 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3148 rc = -EIO; /* bad smb */
3153 /* BB check that data area is minimum length and as big as acl_len */
3155 acl_len = le32_to_cpu(*parm);
3156 if (acl_len != *pbuflen) {
3157 cERROR(1, ("acl length %d does not match %d",
3158 acl_len, *pbuflen));
3159 if (*pbuflen > acl_len)
3163 /* check if buffer is big enough for the acl
3164 header followed by the smallest SID */
3165 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3166 (*pbuflen >= 64 * 1024)) {
3167 cERROR(1, ("bad acl length %d", *pbuflen));
3171 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3172 if (*acl_inf == NULL) {
3176 memcpy(*acl_inf, pdata, *pbuflen);
3180 if (buf_type == CIFS_SMALL_BUFFER)
3181 cifs_small_buf_release(iov[0].iov_base);
3182 else if (buf_type == CIFS_LARGE_BUFFER)
3183 cifs_buf_release(iov[0].iov_base);
3184 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3189 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3190 struct cifs_ntsd *pntsd, __u32 acllen)
3192 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3194 int bytes_returned = 0;
3195 SET_SEC_DESC_REQ *pSMB = NULL;
3196 NTRANSACT_RSP *pSMBr = NULL;
3199 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3204 pSMB->MaxSetupCount = 0;
3208 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3209 data_count = acllen;
3210 data_offset = param_offset + param_count;
3211 byte_count = 3 /* pad */ + param_count;
3213 pSMB->DataCount = cpu_to_le32(data_count);
3214 pSMB->TotalDataCount = pSMB->DataCount;
3215 pSMB->MaxParameterCount = cpu_to_le32(4);
3216 pSMB->MaxDataCount = cpu_to_le32(16384);
3217 pSMB->ParameterCount = cpu_to_le32(param_count);
3218 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3219 pSMB->TotalParameterCount = pSMB->ParameterCount;
3220 pSMB->DataOffset = cpu_to_le32(data_offset);
3221 pSMB->SetupCount = 0;
3222 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3223 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3225 pSMB->Fid = fid; /* file handle always le */
3226 pSMB->Reserved2 = 0;
3227 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3229 if (pntsd && acllen) {
3230 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3233 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3236 pSMB->hdr.smb_buf_length += byte_count;
3238 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3239 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3241 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3243 cFYI(1, ("Set CIFS ACL returned %d", rc));
3244 cifs_buf_release(pSMB);
3247 goto setCifsAclRetry;
3252 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3254 /* Legacy Query Path Information call for lookup to old servers such
3256 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3257 const unsigned char *searchName,
3258 FILE_ALL_INFO *pFinfo,
3259 const struct nls_table *nls_codepage, int remap)
3261 QUERY_INFORMATION_REQ *pSMB;
3262 QUERY_INFORMATION_RSP *pSMBr;
3267 cFYI(1, ("In SMBQPath path %s", searchName));
3269 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3274 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3276 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3277 PATH_MAX, nls_codepage, remap);
3278 name_len++; /* trailing null */
3281 name_len = strnlen(searchName, PATH_MAX);
3282 name_len++; /* trailing null */
3283 strncpy(pSMB->FileName, searchName, name_len);
3285 pSMB->BufferFormat = 0x04;
3286 name_len++; /* account for buffer type byte */
3287 pSMB->hdr.smb_buf_length += (__u16) name_len;
3288 pSMB->ByteCount = cpu_to_le16(name_len);
3290 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3291 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3293 cFYI(1, ("Send error in QueryInfo = %d", rc));
3294 } else if (pFinfo) {
3296 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3298 /* decode response */
3299 /* BB FIXME - add time zone adjustment BB */
3300 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3303 /* decode time fields */
3304 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3305 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3306 pFinfo->LastAccessTime = 0;
3307 pFinfo->AllocationSize =
3308 cpu_to_le64(le32_to_cpu(pSMBr->size));
3309 pFinfo->EndOfFile = pFinfo->AllocationSize;
3310 pFinfo->Attributes =
3311 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3313 rc = -EIO; /* bad buffer passed in */
3315 cifs_buf_release(pSMB);
3327 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3328 const unsigned char *searchName,
3329 FILE_ALL_INFO *pFindData,
3330 int legacy /* old style infolevel */,
3331 const struct nls_table *nls_codepage, int remap)
3333 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3334 TRANSACTION2_QPI_REQ *pSMB = NULL;
3335 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3339 __u16 params, byte_count;
3341 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3343 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3348 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3350 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3351 PATH_MAX, nls_codepage, remap);
3352 name_len++; /* trailing null */
3354 } else { /* BB improve the check for buffer overruns BB */
3355 name_len = strnlen(searchName, PATH_MAX);
3356 name_len++; /* trailing null */
3357 strncpy(pSMB->FileName, searchName, name_len);
3360 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3361 pSMB->TotalDataCount = 0;
3362 pSMB->MaxParameterCount = cpu_to_le16(2);
3363 /* BB find exact max SMB PDU from sess structure BB */
3364 pSMB->MaxDataCount = cpu_to_le16(4000);
3365 pSMB->MaxSetupCount = 0;
3369 pSMB->Reserved2 = 0;
3370 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3371 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3372 pSMB->DataCount = 0;
3373 pSMB->DataOffset = 0;
3374 pSMB->SetupCount = 1;
3375 pSMB->Reserved3 = 0;
3376 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3377 byte_count = params + 1 /* pad */ ;
3378 pSMB->TotalParameterCount = cpu_to_le16(params);
3379 pSMB->ParameterCount = pSMB->TotalParameterCount;
3381 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3383 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3384 pSMB->Reserved4 = 0;
3385 pSMB->hdr.smb_buf_length += byte_count;
3386 pSMB->ByteCount = cpu_to_le16(byte_count);
3388 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3389 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3391 cFYI(1, ("Send error in QPathInfo = %d", rc));
3392 } else { /* decode response */
3393 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3395 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3397 else if (!legacy && (pSMBr->ByteCount < 40))
3398 rc = -EIO; /* bad smb */
3399 else if (legacy && (pSMBr->ByteCount < 24))
3400 rc = -EIO; /* 24 or 26 expected but we do not read
3402 else if (pFindData) {
3404 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3406 /* On legacy responses we do not read the last field,
3407 EAsize, fortunately since it varies by subdialect and
3408 also note it differs on Set vs. Get, ie two bytes or 4
3409 bytes depending but we don't care here */
3411 size = sizeof(FILE_INFO_STANDARD);
3413 size = sizeof(FILE_ALL_INFO);
3414 memcpy((char *) pFindData,
3415 (char *) &pSMBr->hdr.Protocol +
3420 cifs_buf_release(pSMB);
3422 goto QPathInfoRetry;
3428 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3429 const unsigned char *searchName,
3430 FILE_UNIX_BASIC_INFO *pFindData,
3431 const struct nls_table *nls_codepage, int remap)
3433 /* SMB_QUERY_FILE_UNIX_BASIC */
3434 TRANSACTION2_QPI_REQ *pSMB = NULL;
3435 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3437 int bytes_returned = 0;
3439 __u16 params, byte_count;
3441 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3443 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3448 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3450 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3451 PATH_MAX, nls_codepage, remap);
3452 name_len++; /* trailing null */
3454 } else { /* BB improve the check for buffer overruns BB */
3455 name_len = strnlen(searchName, PATH_MAX);
3456 name_len++; /* trailing null */
3457 strncpy(pSMB->FileName, searchName, name_len);
3460 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3461 pSMB->TotalDataCount = 0;
3462 pSMB->MaxParameterCount = cpu_to_le16(2);
3463 /* BB find exact max SMB PDU from sess structure BB */
3464 pSMB->MaxDataCount = cpu_to_le16(4000);
3465 pSMB->MaxSetupCount = 0;
3469 pSMB->Reserved2 = 0;
3470 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3471 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3472 pSMB->DataCount = 0;
3473 pSMB->DataOffset = 0;
3474 pSMB->SetupCount = 1;
3475 pSMB->Reserved3 = 0;
3476 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3477 byte_count = params + 1 /* pad */ ;
3478 pSMB->TotalParameterCount = cpu_to_le16(params);
3479 pSMB->ParameterCount = pSMB->TotalParameterCount;
3480 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3481 pSMB->Reserved4 = 0;
3482 pSMB->hdr.smb_buf_length += byte_count;
3483 pSMB->ByteCount = cpu_to_le16(byte_count);
3485 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3486 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3488 cFYI(1, ("Send error in QPathInfo = %d", rc));
3489 } else { /* decode response */
3490 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3492 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3493 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3494 "Unix Extensions can be disabled on mount "
3495 "by specifying the nosfu mount option."));
3496 rc = -EIO; /* bad smb */
3498 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3499 memcpy((char *) pFindData,
3500 (char *) &pSMBr->hdr.Protocol +
3502 sizeof(FILE_UNIX_BASIC_INFO));
3505 cifs_buf_release(pSMB);
3507 goto UnixQPathInfoRetry;
3512 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3514 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3515 const char *searchName,
3516 const struct nls_table *nls_codepage,
3518 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3520 /* level 257 SMB_ */
3521 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3522 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3523 T2_FFIRST_RSP_PARMS *parms;
3525 int bytes_returned = 0;
3527 __u16 params, byte_count;
3529 cFYI(1, ("In FindFirst for %s", searchName));
3532 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3537 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3539 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3540 PATH_MAX, nls_codepage, remap);
3541 /* We can not add the asterik earlier in case
3542 it got remapped to 0xF03A as if it were part of the
3543 directory name instead of a wildcard */
3545 pSMB->FileName[name_len] = dirsep;
3546 pSMB->FileName[name_len+1] = 0;
3547 pSMB->FileName[name_len+2] = '*';
3548 pSMB->FileName[name_len+3] = 0;
3549 name_len += 4; /* now the trailing null */
3550 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3551 pSMB->FileName[name_len+1] = 0;
3553 } else { /* BB add check for overrun of SMB buf BB */
3554 name_len = strnlen(searchName, PATH_MAX);
3555 /* BB fix here and in unicode clause above ie
3556 if (name_len > buffersize-header)
3557 free buffer exit; BB */
3558 strncpy(pSMB->FileName, searchName, name_len);
3559 pSMB->FileName[name_len] = dirsep;
3560 pSMB->FileName[name_len+1] = '*';
3561 pSMB->FileName[name_len+2] = 0;
3565 params = 12 + name_len /* includes null */ ;
3566 pSMB->TotalDataCount = 0; /* no EAs */
3567 pSMB->MaxParameterCount = cpu_to_le16(10);
3568 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3569 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3570 pSMB->MaxSetupCount = 0;
3574 pSMB->Reserved2 = 0;
3575 byte_count = params + 1 /* pad */ ;
3576 pSMB->TotalParameterCount = cpu_to_le16(params);
3577 pSMB->ParameterCount = pSMB->TotalParameterCount;
3578 pSMB->ParameterOffset = cpu_to_le16(
3579 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3581 pSMB->DataCount = 0;
3582 pSMB->DataOffset = 0;
3583 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3584 pSMB->Reserved3 = 0;
3585 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3586 pSMB->SearchAttributes =
3587 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3589 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3590 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3591 CIFS_SEARCH_RETURN_RESUME);
3592 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3594 /* BB what should we set StorageType to? Does it matter? BB */
3595 pSMB->SearchStorageType = 0;
3596 pSMB->hdr.smb_buf_length += byte_count;
3597 pSMB->ByteCount = cpu_to_le16(byte_count);
3599 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3600 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3601 cifs_stats_inc(&tcon->num_ffirst);
3603 if (rc) {/* BB add logic to retry regular search if Unix search
3604 rejected unexpectedly by server */
3605 /* BB Add code to handle unsupported level rc */
3606 cFYI(1, ("Error in FindFirst = %d", rc));
3608 cifs_buf_release(pSMB);
3610 /* BB eventually could optimize out free and realloc of buf */
3613 goto findFirstRetry;
3614 } else { /* decode response */
3615 /* BB remember to free buffer if error BB */
3616 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3618 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3619 psrch_inf->unicode = true;
3621 psrch_inf->unicode = false;
3623 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3624 psrch_inf->smallBuf = 0;
3625 psrch_inf->srch_entries_start =
3626 (char *) &pSMBr->hdr.Protocol +
3627 le16_to_cpu(pSMBr->t2.DataOffset);
3628 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3629 le16_to_cpu(pSMBr->t2.ParameterOffset));
3631 if (parms->EndofSearch)
3632 psrch_inf->endOfSearch = true;
3634 psrch_inf->endOfSearch = false;
3636 psrch_inf->entries_in_buffer =
3637 le16_to_cpu(parms->SearchCount);
3638 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3639 psrch_inf->entries_in_buffer;
3640 *pnetfid = parms->SearchHandle;
3642 cifs_buf_release(pSMB);
3649 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3650 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3652 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3653 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3654 T2_FNEXT_RSP_PARMS *parms;
3655 char *response_data;
3657 int bytes_returned, name_len;
3658 __u16 params, byte_count;
3660 cFYI(1, ("In FindNext"));
3662 if (psrch_inf->endOfSearch)
3665 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3670 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3672 pSMB->TotalDataCount = 0; /* no EAs */
3673 pSMB->MaxParameterCount = cpu_to_le16(8);
3674 pSMB->MaxDataCount =
3675 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3677 pSMB->MaxSetupCount = 0;
3681 pSMB->Reserved2 = 0;
3682 pSMB->ParameterOffset = cpu_to_le16(
3683 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3684 pSMB->DataCount = 0;
3685 pSMB->DataOffset = 0;
3686 pSMB->SetupCount = 1;
3687 pSMB->Reserved3 = 0;
3688 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3689 pSMB->SearchHandle = searchHandle; /* always kept as le */
3691 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3692 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3693 pSMB->ResumeKey = psrch_inf->resume_key;
3695 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3697 name_len = psrch_inf->resume_name_len;
3699 if (name_len < PATH_MAX) {
3700 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3701 byte_count += name_len;
3702 /* 14 byte parm len above enough for 2 byte null terminator */
3703 pSMB->ResumeFileName[name_len] = 0;
3704 pSMB->ResumeFileName[name_len+1] = 0;
3707 goto FNext2_err_exit;
3709 byte_count = params + 1 /* pad */ ;
3710 pSMB->TotalParameterCount = cpu_to_le16(params);
3711 pSMB->ParameterCount = pSMB->TotalParameterCount;
3712 pSMB->hdr.smb_buf_length += byte_count;
3713 pSMB->ByteCount = cpu_to_le16(byte_count);
3715 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3716 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3717 cifs_stats_inc(&tcon->num_fnext);
3720 psrch_inf->endOfSearch = true;
3721 cifs_buf_release(pSMB);
3722 rc = 0; /* search probably was closed at end of search*/
3724 cFYI(1, ("FindNext returned = %d", rc));
3725 } else { /* decode response */
3726 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3729 /* BB fixme add lock for file (srch_info) struct here */
3730 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3731 psrch_inf->unicode = true;
3733 psrch_inf->unicode = false;
3734 response_data = (char *) &pSMBr->hdr.Protocol +
3735 le16_to_cpu(pSMBr->t2.ParameterOffset);
3736 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3737 response_data = (char *)&pSMBr->hdr.Protocol +
3738 le16_to_cpu(pSMBr->t2.DataOffset);
3739 if (psrch_inf->smallBuf)
3740 cifs_small_buf_release(
3741 psrch_inf->ntwrk_buf_start);
3743 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3744 psrch_inf->srch_entries_start = response_data;
3745 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3746 psrch_inf->smallBuf = 0;
3747 if (parms->EndofSearch)
3748 psrch_inf->endOfSearch = true;
3750 psrch_inf->endOfSearch = false;
3751 psrch_inf->entries_in_buffer =
3752 le16_to_cpu(parms->SearchCount);
3753 psrch_inf->index_of_last_entry +=
3754 psrch_inf->entries_in_buffer;
3755 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3756 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3758 /* BB fixme add unlock here */
3763 /* BB On error, should we leave previous search buf (and count and
3764 last entry fields) intact or free the previous one? */
3766 /* Note: On -EAGAIN error only caller can retry on handle based calls
3767 since file handle passed in no longer valid */
3770 cifs_buf_release(pSMB);
3775 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3776 const __u16 searchHandle)
3779 FINDCLOSE_REQ *pSMB = NULL;
3781 cFYI(1, ("In CIFSSMBFindClose"));
3782 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3784 /* no sense returning error if session restarted
3785 as file handle has been closed */
3791 pSMB->FileID = searchHandle;
3792 pSMB->ByteCount = 0;
3793 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3795 cERROR(1, ("Send error in FindClose = %d", rc));
3797 cifs_stats_inc(&tcon->num_fclose);
3799 /* Since session is dead, search handle closed on server already */
3807 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3808 const unsigned char *searchName,
3809 __u64 *inode_number,
3810 const struct nls_table *nls_codepage, int remap)
3813 TRANSACTION2_QPI_REQ *pSMB = NULL;
3814 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3815 int name_len, bytes_returned;
3816 __u16 params, byte_count;
3818 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3822 GetInodeNumberRetry:
3823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3830 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3831 PATH_MAX, nls_codepage, remap);
3832 name_len++; /* trailing null */
3834 } else { /* BB improve the check for buffer overruns BB */
3835 name_len = strnlen(searchName, PATH_MAX);
3836 name_len++; /* trailing null */
3837 strncpy(pSMB->FileName, searchName, name_len);
3840 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3841 pSMB->TotalDataCount = 0;
3842 pSMB->MaxParameterCount = cpu_to_le16(2);
3843 /* BB find exact max data count below from sess structure BB */
3844 pSMB->MaxDataCount = cpu_to_le16(4000);
3845 pSMB->MaxSetupCount = 0;
3849 pSMB->Reserved2 = 0;
3850 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3851 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3852 pSMB->DataCount = 0;
3853 pSMB->DataOffset = 0;
3854 pSMB->SetupCount = 1;
3855 pSMB->Reserved3 = 0;
3856 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3857 byte_count = params + 1 /* pad */ ;
3858 pSMB->TotalParameterCount = cpu_to_le16(params);
3859 pSMB->ParameterCount = pSMB->TotalParameterCount;
3860 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3861 pSMB->Reserved4 = 0;
3862 pSMB->hdr.smb_buf_length += byte_count;
3863 pSMB->ByteCount = cpu_to_le16(byte_count);
3865 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3866 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3868 cFYI(1, ("error %d in QueryInternalInfo", rc));
3870 /* decode response */
3871 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3872 if (rc || (pSMBr->ByteCount < 2))
3873 /* BB also check enough total bytes returned */
3874 /* If rc should we check for EOPNOSUPP and
3875 disable the srvino flag? or in caller? */
3876 rc = -EIO; /* bad smb */
3878 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3879 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3880 struct file_internal_info *pfinfo;
3881 /* BB Do we need a cast or hash here ? */
3883 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3885 goto GetInodeNumOut;
3887 pfinfo = (struct file_internal_info *)
3888 (data_offset + (char *) &pSMBr->hdr.Protocol);
3889 *inode_number = pfinfo->UniqueId;
3893 cifs_buf_release(pSMB);
3895 goto GetInodeNumberRetry;
3899 /* parses DFS refferal V3 structure
3900 * caller is responsible for freeing target_nodes
3903 * on failure - errno
3906 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3907 unsigned int *num_of_nodes,
3908 struct dfs_info3_param **target_nodes,
3909 const struct nls_table *nls_codepage)
3914 struct dfs_referral_level_3 *ref;
3916 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3920 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3922 if (*num_of_nodes < 1) {
3923 cERROR(1, ("num_referrals: must be at least > 0,"
3924 "but we get num_referrals = %d\n", *num_of_nodes));
3926 goto parse_DFS_referrals_exit;
3929 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3930 if (ref->VersionNumber != cpu_to_le16(3)) {
3931 cERROR(1, ("Referrals of V%d version are not supported,"
3932 "should be V3", le16_to_cpu(ref->VersionNumber)));
3934 goto parse_DFS_referrals_exit;
3937 /* get the upper boundary of the resp buffer */
3938 data_end = (char *)(&(pSMBr->PathConsumed)) +
3939 le16_to_cpu(pSMBr->t2.DataCount);
3941 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3943 le16_to_cpu(pSMBr->DFSFlags)));
3945 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3946 *num_of_nodes, GFP_KERNEL);
3947 if (*target_nodes == NULL) {
3948 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3950 goto parse_DFS_referrals_exit;
3953 /* collect neccessary data from referrals */
3954 for (i = 0; i < *num_of_nodes; i++) {
3957 struct dfs_info3_param *node = (*target_nodes)+i;
3959 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3960 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3961 node->server_type = le16_to_cpu(ref->ServerType);
3962 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3965 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3966 max_len = data_end - temp;
3967 rc = cifs_strncpy_to_host(&(node->path_name), temp,
3968 max_len, is_unicode, nls_codepage);
3970 goto parse_DFS_referrals_exit;
3972 /* copy link target UNC */
3973 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3974 max_len = data_end - temp;
3975 rc = cifs_strncpy_to_host(&(node->node_name), temp,
3976 max_len, is_unicode, nls_codepage);
3978 goto parse_DFS_referrals_exit;
3980 ref += le16_to_cpu(ref->Size);
3983 parse_DFS_referrals_exit:
3985 free_dfs_info_array(*target_nodes, *num_of_nodes);
3986 *target_nodes = NULL;
3993 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3994 const unsigned char *searchName,
3995 struct dfs_info3_param **target_nodes,
3996 unsigned int *num_of_nodes,
3997 const struct nls_table *nls_codepage, int remap)
3999 /* TRANS2_GET_DFS_REFERRAL */
4000 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4001 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4005 __u16 params, byte_count;
4007 *target_nodes = NULL;
4009 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4013 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4018 /* server pointer checked in called function,
4019 but should never be null here anyway */
4020 pSMB->hdr.Mid = GetNextMid(ses->server);
4021 pSMB->hdr.Tid = ses->ipc_tid;
4022 pSMB->hdr.Uid = ses->Suid;
4023 if (ses->capabilities & CAP_STATUS32)
4024 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4025 if (ses->capabilities & CAP_DFS)
4026 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4028 if (ses->capabilities & CAP_UNICODE) {
4029 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4031 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4032 searchName, PATH_MAX, nls_codepage, remap);
4033 name_len++; /* trailing null */
4035 } else { /* BB improve the check for buffer overruns BB */
4036 name_len = strnlen(searchName, PATH_MAX);
4037 name_len++; /* trailing null */
4038 strncpy(pSMB->RequestFileName, searchName, name_len);
4042 if (ses->server->secMode &
4043 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4044 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4047 pSMB->hdr.Uid = ses->Suid;
4049 params = 2 /* level */ + name_len /*includes null */ ;
4050 pSMB->TotalDataCount = 0;
4051 pSMB->DataCount = 0;
4052 pSMB->DataOffset = 0;
4053 pSMB->MaxParameterCount = 0;
4054 /* BB find exact max SMB PDU from sess structure BB */
4055 pSMB->MaxDataCount = cpu_to_le16(4000);
4056 pSMB->MaxSetupCount = 0;
4060 pSMB->Reserved2 = 0;
4061 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4062 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4063 pSMB->SetupCount = 1;
4064 pSMB->Reserved3 = 0;
4065 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4066 byte_count = params + 3 /* pad */ ;
4067 pSMB->ParameterCount = cpu_to_le16(params);
4068 pSMB->TotalParameterCount = pSMB->ParameterCount;
4069 pSMB->MaxReferralLevel = cpu_to_le16(3);
4070 pSMB->hdr.smb_buf_length += byte_count;
4071 pSMB->ByteCount = cpu_to_le16(byte_count);
4073 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4074 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4076 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4079 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4081 /* BB Also check if enough total bytes returned? */
4082 if (rc || (pSMBr->ByteCount < 17)) {
4083 rc = -EIO; /* bad smb */
4087 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4089 le16_to_cpu(pSMBr->t2.DataOffset)));
4091 /* parse returned result into more usable form */
4092 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4093 target_nodes, nls_codepage);
4096 cifs_buf_release(pSMB);
4104 /* Query File System Info such as free space to old servers such as Win 9x */
4106 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4108 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4109 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4110 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4111 FILE_SYSTEM_ALLOC_INFO *response_data;
4113 int bytes_returned = 0;
4114 __u16 params, byte_count;
4116 cFYI(1, ("OldQFSInfo"));
4118 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4123 params = 2; /* level */
4124 pSMB->TotalDataCount = 0;
4125 pSMB->MaxParameterCount = cpu_to_le16(2);
4126 pSMB->MaxDataCount = cpu_to_le16(1000);
4127 pSMB->MaxSetupCount = 0;
4131 pSMB->Reserved2 = 0;
4132 byte_count = params + 1 /* pad */ ;
4133 pSMB->TotalParameterCount = cpu_to_le16(params);
4134 pSMB->ParameterCount = pSMB->TotalParameterCount;
4135 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4136 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4137 pSMB->DataCount = 0;
4138 pSMB->DataOffset = 0;
4139 pSMB->SetupCount = 1;
4140 pSMB->Reserved3 = 0;
4141 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4142 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4143 pSMB->hdr.smb_buf_length += byte_count;
4144 pSMB->ByteCount = cpu_to_le16(byte_count);
4146 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4147 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4149 cFYI(1, ("Send error in QFSInfo = %d", rc));
4150 } else { /* decode response */
4151 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4153 if (rc || (pSMBr->ByteCount < 18))
4154 rc = -EIO; /* bad smb */
4156 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4157 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4158 pSMBr->ByteCount, data_offset));
4160 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4161 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4163 le16_to_cpu(response_data->BytesPerSector) *
4164 le32_to_cpu(response_data->
4165 SectorsPerAllocationUnit);
4167 le32_to_cpu(response_data->TotalAllocationUnits);
4168 FSData->f_bfree = FSData->f_bavail =
4169 le32_to_cpu(response_data->FreeAllocationUnits);
4171 ("Blocks: %lld Free: %lld Block size %ld",
4172 (unsigned long long)FSData->f_blocks,
4173 (unsigned long long)FSData->f_bfree,
4177 cifs_buf_release(pSMB);
4180 goto oldQFSInfoRetry;
4186 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4188 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4189 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4190 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4191 FILE_SYSTEM_INFO *response_data;
4193 int bytes_returned = 0;
4194 __u16 params, byte_count;
4196 cFYI(1, ("In QFSInfo"));
4198 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4203 params = 2; /* level */
4204 pSMB->TotalDataCount = 0;
4205 pSMB->MaxParameterCount = cpu_to_le16(2);
4206 pSMB->MaxDataCount = cpu_to_le16(1000);
4207 pSMB->MaxSetupCount = 0;
4211 pSMB->Reserved2 = 0;
4212 byte_count = params + 1 /* pad */ ;
4213 pSMB->TotalParameterCount = cpu_to_le16(params);
4214 pSMB->ParameterCount = pSMB->TotalParameterCount;
4215 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4216 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4217 pSMB->DataCount = 0;
4218 pSMB->DataOffset = 0;
4219 pSMB->SetupCount = 1;
4220 pSMB->Reserved3 = 0;
4221 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4222 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4223 pSMB->hdr.smb_buf_length += byte_count;
4224 pSMB->ByteCount = cpu_to_le16(byte_count);
4226 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4227 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4229 cFYI(1, ("Send error in QFSInfo = %d", rc));
4230 } else { /* decode response */
4231 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4233 if (rc || (pSMBr->ByteCount < 24))
4234 rc = -EIO; /* bad smb */
4236 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4240 *) (((char *) &pSMBr->hdr.Protocol) +
4243 le32_to_cpu(response_data->BytesPerSector) *
4244 le32_to_cpu(response_data->
4245 SectorsPerAllocationUnit);
4247 le64_to_cpu(response_data->TotalAllocationUnits);
4248 FSData->f_bfree = FSData->f_bavail =
4249 le64_to_cpu(response_data->FreeAllocationUnits);
4251 ("Blocks: %lld Free: %lld Block size %ld",
4252 (unsigned long long)FSData->f_blocks,
4253 (unsigned long long)FSData->f_bfree,
4257 cifs_buf_release(pSMB);
4266 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4268 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4269 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4270 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4271 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4273 int bytes_returned = 0;
4274 __u16 params, byte_count;
4276 cFYI(1, ("In QFSAttributeInfo"));
4278 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4283 params = 2; /* level */
4284 pSMB->TotalDataCount = 0;
4285 pSMB->MaxParameterCount = cpu_to_le16(2);
4286 /* BB find exact max SMB PDU from sess structure BB */
4287 pSMB->MaxDataCount = cpu_to_le16(1000);
4288 pSMB->MaxSetupCount = 0;
4292 pSMB->Reserved2 = 0;
4293 byte_count = params + 1 /* pad */ ;
4294 pSMB->TotalParameterCount = cpu_to_le16(params);
4295 pSMB->ParameterCount = pSMB->TotalParameterCount;
4296 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4297 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4298 pSMB->DataCount = 0;
4299 pSMB->DataOffset = 0;
4300 pSMB->SetupCount = 1;
4301 pSMB->Reserved3 = 0;
4302 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4303 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4304 pSMB->hdr.smb_buf_length += byte_count;
4305 pSMB->ByteCount = cpu_to_le16(byte_count);
4307 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4308 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4310 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4311 } else { /* decode response */
4312 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4314 if (rc || (pSMBr->ByteCount < 13)) {
4315 /* BB also check if enough bytes returned */
4316 rc = -EIO; /* bad smb */
4318 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4320 (FILE_SYSTEM_ATTRIBUTE_INFO
4321 *) (((char *) &pSMBr->hdr.Protocol) +
4323 memcpy(&tcon->fsAttrInfo, response_data,
4324 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4327 cifs_buf_release(pSMB);
4330 goto QFSAttributeRetry;
4336 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4338 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4339 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4340 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4341 FILE_SYSTEM_DEVICE_INFO *response_data;
4343 int bytes_returned = 0;
4344 __u16 params, byte_count;
4346 cFYI(1, ("In QFSDeviceInfo"));
4348 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4353 params = 2; /* level */
4354 pSMB->TotalDataCount = 0;
4355 pSMB->MaxParameterCount = cpu_to_le16(2);
4356 /* BB find exact max SMB PDU from sess structure BB */
4357 pSMB->MaxDataCount = cpu_to_le16(1000);
4358 pSMB->MaxSetupCount = 0;
4362 pSMB->Reserved2 = 0;
4363 byte_count = params + 1 /* pad */ ;
4364 pSMB->TotalParameterCount = cpu_to_le16(params);
4365 pSMB->ParameterCount = pSMB->TotalParameterCount;
4366 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4367 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4369 pSMB->DataCount = 0;
4370 pSMB->DataOffset = 0;
4371 pSMB->SetupCount = 1;
4372 pSMB->Reserved3 = 0;
4373 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4374 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4375 pSMB->hdr.smb_buf_length += byte_count;
4376 pSMB->ByteCount = cpu_to_le16(byte_count);
4378 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4379 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4381 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4382 } else { /* decode response */
4383 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4385 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4386 rc = -EIO; /* bad smb */
4388 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4390 (FILE_SYSTEM_DEVICE_INFO *)
4391 (((char *) &pSMBr->hdr.Protocol) +
4393 memcpy(&tcon->fsDevInfo, response_data,
4394 sizeof(FILE_SYSTEM_DEVICE_INFO));
4397 cifs_buf_release(pSMB);
4400 goto QFSDeviceRetry;
4406 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4408 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4409 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4410 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4411 FILE_SYSTEM_UNIX_INFO *response_data;
4413 int bytes_returned = 0;
4414 __u16 params, byte_count;
4416 cFYI(1, ("In QFSUnixInfo"));
4418 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4423 params = 2; /* level */
4424 pSMB->TotalDataCount = 0;
4425 pSMB->DataCount = 0;
4426 pSMB->DataOffset = 0;
4427 pSMB->MaxParameterCount = cpu_to_le16(2);
4428 /* BB find exact max SMB PDU from sess structure BB */
4429 pSMB->MaxDataCount = cpu_to_le16(100);
4430 pSMB->MaxSetupCount = 0;
4434 pSMB->Reserved2 = 0;
4435 byte_count = params + 1 /* pad */ ;
4436 pSMB->ParameterCount = cpu_to_le16(params);
4437 pSMB->TotalParameterCount = pSMB->ParameterCount;
4438 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4439 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4440 pSMB->SetupCount = 1;
4441 pSMB->Reserved3 = 0;
4442 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4443 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4444 pSMB->hdr.smb_buf_length += byte_count;
4445 pSMB->ByteCount = cpu_to_le16(byte_count);
4447 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4448 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4450 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4451 } else { /* decode response */
4452 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4454 if (rc || (pSMBr->ByteCount < 13)) {
4455 rc = -EIO; /* bad smb */
4457 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4459 (FILE_SYSTEM_UNIX_INFO
4460 *) (((char *) &pSMBr->hdr.Protocol) +
4462 memcpy(&tcon->fsUnixInfo, response_data,
4463 sizeof(FILE_SYSTEM_UNIX_INFO));
4466 cifs_buf_release(pSMB);
4476 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4478 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4479 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4480 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4482 int bytes_returned = 0;
4483 __u16 params, param_offset, offset, byte_count;
4485 cFYI(1, ("In SETFSUnixInfo"));
4487 /* BB switch to small buf init to save memory */
4488 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4493 params = 4; /* 2 bytes zero followed by info level. */
4494 pSMB->MaxSetupCount = 0;
4498 pSMB->Reserved2 = 0;
4499 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4501 offset = param_offset + params;
4503 pSMB->MaxParameterCount = cpu_to_le16(4);
4504 /* BB find exact max SMB PDU from sess structure BB */
4505 pSMB->MaxDataCount = cpu_to_le16(100);
4506 pSMB->SetupCount = 1;
4507 pSMB->Reserved3 = 0;
4508 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4509 byte_count = 1 /* pad */ + params + 12;
4511 pSMB->DataCount = cpu_to_le16(12);
4512 pSMB->ParameterCount = cpu_to_le16(params);
4513 pSMB->TotalDataCount = pSMB->DataCount;
4514 pSMB->TotalParameterCount = pSMB->ParameterCount;
4515 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4516 pSMB->DataOffset = cpu_to_le16(offset);
4520 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4523 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4524 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4525 pSMB->ClientUnixCap = cpu_to_le64(cap);
4527 pSMB->hdr.smb_buf_length += byte_count;
4528 pSMB->ByteCount = cpu_to_le16(byte_count);
4530 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4531 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4533 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4534 } else { /* decode response */
4535 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4537 rc = -EIO; /* bad smb */
4539 cifs_buf_release(pSMB);
4542 goto SETFSUnixRetry;
4550 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4551 struct kstatfs *FSData)
4553 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4554 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4555 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4556 FILE_SYSTEM_POSIX_INFO *response_data;
4558 int bytes_returned = 0;
4559 __u16 params, byte_count;
4561 cFYI(1, ("In QFSPosixInfo"));
4563 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4568 params = 2; /* level */
4569 pSMB->TotalDataCount = 0;
4570 pSMB->DataCount = 0;
4571 pSMB->DataOffset = 0;
4572 pSMB->MaxParameterCount = cpu_to_le16(2);
4573 /* BB find exact max SMB PDU from sess structure BB */
4574 pSMB->MaxDataCount = cpu_to_le16(100);
4575 pSMB->MaxSetupCount = 0;
4579 pSMB->Reserved2 = 0;
4580 byte_count = params + 1 /* pad */ ;
4581 pSMB->ParameterCount = cpu_to_le16(params);
4582 pSMB->TotalParameterCount = pSMB->ParameterCount;
4583 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4584 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4585 pSMB->SetupCount = 1;
4586 pSMB->Reserved3 = 0;
4587 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4588 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4589 pSMB->hdr.smb_buf_length += byte_count;
4590 pSMB->ByteCount = cpu_to_le16(byte_count);
4592 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4593 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4595 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4596 } else { /* decode response */
4597 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4599 if (rc || (pSMBr->ByteCount < 13)) {
4600 rc = -EIO; /* bad smb */
4602 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4604 (FILE_SYSTEM_POSIX_INFO
4605 *) (((char *) &pSMBr->hdr.Protocol) +
4608 le32_to_cpu(response_data->BlockSize);
4610 le64_to_cpu(response_data->TotalBlocks);
4612 le64_to_cpu(response_data->BlocksAvail);
4613 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4614 FSData->f_bavail = FSData->f_bfree;
4617 le64_to_cpu(response_data->UserBlocksAvail);
4619 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4621 le64_to_cpu(response_data->TotalFileNodes);
4622 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4624 le64_to_cpu(response_data->FreeFileNodes);
4627 cifs_buf_release(pSMB);
4636 /* We can not use write of zero bytes trick to
4637 set file size due to need for large file support. Also note that
4638 this SetPathInfo is preferred to SetFileInfo based method in next
4639 routine which is only needed to work around a sharing violation bug
4640 in Samba which this routine can run into */
4643 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4644 __u64 size, bool SetAllocation,
4645 const struct nls_table *nls_codepage, int remap)
4647 struct smb_com_transaction2_spi_req *pSMB = NULL;
4648 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4649 struct file_end_of_file_info *parm_data;
4652 int bytes_returned = 0;
4653 __u16 params, byte_count, data_count, param_offset, offset;
4655 cFYI(1, ("In SetEOF"));
4657 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4662 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4664 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4665 PATH_MAX, nls_codepage, remap);
4666 name_len++; /* trailing null */
4668 } else { /* BB improve the check for buffer overruns BB */
4669 name_len = strnlen(fileName, PATH_MAX);
4670 name_len++; /* trailing null */
4671 strncpy(pSMB->FileName, fileName, name_len);
4673 params = 6 + name_len;
4674 data_count = sizeof(struct file_end_of_file_info);
4675 pSMB->MaxParameterCount = cpu_to_le16(2);
4676 pSMB->MaxDataCount = cpu_to_le16(4100);
4677 pSMB->MaxSetupCount = 0;
4681 pSMB->Reserved2 = 0;
4682 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4683 InformationLevel) - 4;
4684 offset = param_offset + params;
4685 if (SetAllocation) {
4686 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4687 pSMB->InformationLevel =
4688 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4690 pSMB->InformationLevel =
4691 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4692 } else /* Set File Size */ {
4693 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4694 pSMB->InformationLevel =
4695 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4697 pSMB->InformationLevel =
4698 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4702 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4704 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4705 pSMB->DataOffset = cpu_to_le16(offset);
4706 pSMB->SetupCount = 1;
4707 pSMB->Reserved3 = 0;
4708 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4709 byte_count = 3 /* pad */ + params + data_count;
4710 pSMB->DataCount = cpu_to_le16(data_count);
4711 pSMB->TotalDataCount = pSMB->DataCount;
4712 pSMB->ParameterCount = cpu_to_le16(params);
4713 pSMB->TotalParameterCount = pSMB->ParameterCount;
4714 pSMB->Reserved4 = 0;
4715 pSMB->hdr.smb_buf_length += byte_count;
4716 parm_data->FileSize = cpu_to_le64(size);
4717 pSMB->ByteCount = cpu_to_le16(byte_count);
4718 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4719 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4721 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4723 cifs_buf_release(pSMB);
4732 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4733 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4735 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4737 struct file_end_of_file_info *parm_data;
4739 __u16 params, param_offset, offset, byte_count, count;
4741 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4743 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4748 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4749 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4752 pSMB->MaxSetupCount = 0;
4756 pSMB->Reserved2 = 0;
4757 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4758 offset = param_offset + params;
4760 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4762 count = sizeof(struct file_end_of_file_info);
4763 pSMB->MaxParameterCount = cpu_to_le16(2);
4764 /* BB find exact max SMB PDU from sess structure BB */
4765 pSMB->MaxDataCount = cpu_to_le16(1000);
4766 pSMB->SetupCount = 1;
4767 pSMB->Reserved3 = 0;
4768 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4769 byte_count = 3 /* pad */ + params + count;
4770 pSMB->DataCount = cpu_to_le16(count);
4771 pSMB->ParameterCount = cpu_to_le16(params);
4772 pSMB->TotalDataCount = pSMB->DataCount;
4773 pSMB->TotalParameterCount = pSMB->ParameterCount;
4774 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4776 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4778 pSMB->DataOffset = cpu_to_le16(offset);
4779 parm_data->FileSize = cpu_to_le64(size);
4781 if (SetAllocation) {
4782 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4783 pSMB->InformationLevel =
4784 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4786 pSMB->InformationLevel =
4787 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4788 } else /* Set File Size */ {
4789 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4790 pSMB->InformationLevel =
4791 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4793 pSMB->InformationLevel =
4794 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4796 pSMB->Reserved4 = 0;
4797 pSMB->hdr.smb_buf_length += byte_count;
4798 pSMB->ByteCount = cpu_to_le16(byte_count);
4799 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4802 ("Send error in SetFileInfo (SetFileSize) = %d",
4806 /* Note: On -EAGAIN error only caller can retry on handle based calls
4807 since file handle passed in no longer valid */
4812 /* Some legacy servers such as NT4 require that the file times be set on
4813 an open handle, rather than by pathname - this is awkward due to
4814 potential access conflicts on the open, but it is unavoidable for these
4815 old servers since the only other choice is to go from 100 nanosecond DCE
4816 time and resort to the original setpathinfo level which takes the ancient
4817 DOS time format with 2 second granularity */
4819 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4820 const FILE_BASIC_INFO *data, __u16 fid)
4822 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4825 __u16 params, param_offset, offset, byte_count, count;
4827 cFYI(1, ("Set Times (via SetFileInfo)"));
4828 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4833 /* At this point there is no need to override the current pid
4834 with the pid of the opener, but that could change if we someday
4835 use an existing handle (rather than opening one on the fly) */
4836 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4837 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4840 pSMB->MaxSetupCount = 0;
4844 pSMB->Reserved2 = 0;
4845 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4846 offset = param_offset + params;
4848 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4850 count = sizeof(FILE_BASIC_INFO);
4851 pSMB->MaxParameterCount = cpu_to_le16(2);
4852 /* BB find max SMB PDU from sess */
4853 pSMB->MaxDataCount = cpu_to_le16(1000);
4854 pSMB->SetupCount = 1;
4855 pSMB->Reserved3 = 0;
4856 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4857 byte_count = 3 /* pad */ + params + count;
4858 pSMB->DataCount = cpu_to_le16(count);
4859 pSMB->ParameterCount = cpu_to_le16(params);
4860 pSMB->TotalDataCount = pSMB->DataCount;
4861 pSMB->TotalParameterCount = pSMB->ParameterCount;
4862 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4863 pSMB->DataOffset = cpu_to_le16(offset);
4865 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4866 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4868 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4869 pSMB->Reserved4 = 0;
4870 pSMB->hdr.smb_buf_length += byte_count;
4871 pSMB->ByteCount = cpu_to_le16(byte_count);
4872 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4873 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4875 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4877 /* Note: On -EAGAIN error only caller can retry on handle based calls
4878 since file handle passed in no longer valid */
4885 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4886 const FILE_BASIC_INFO *data,
4887 const struct nls_table *nls_codepage, int remap)
4889 TRANSACTION2_SPI_REQ *pSMB = NULL;
4890 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4893 int bytes_returned = 0;
4895 __u16 params, param_offset, offset, byte_count, count;
4897 cFYI(1, ("In SetTimes"));
4900 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4907 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4908 PATH_MAX, nls_codepage, remap);
4909 name_len++; /* trailing null */
4911 } else { /* BB improve the check for buffer overruns BB */
4912 name_len = strnlen(fileName, PATH_MAX);
4913 name_len++; /* trailing null */
4914 strncpy(pSMB->FileName, fileName, name_len);
4917 params = 6 + name_len;
4918 count = sizeof(FILE_BASIC_INFO);
4919 pSMB->MaxParameterCount = cpu_to_le16(2);
4920 /* BB find max SMB PDU from sess structure BB */
4921 pSMB->MaxDataCount = cpu_to_le16(1000);
4922 pSMB->MaxSetupCount = 0;
4926 pSMB->Reserved2 = 0;
4927 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4928 InformationLevel) - 4;
4929 offset = param_offset + params;
4930 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4931 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4932 pSMB->DataOffset = cpu_to_le16(offset);
4933 pSMB->SetupCount = 1;
4934 pSMB->Reserved3 = 0;
4935 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4936 byte_count = 3 /* pad */ + params + count;
4938 pSMB->DataCount = cpu_to_le16(count);
4939 pSMB->ParameterCount = cpu_to_le16(params);
4940 pSMB->TotalDataCount = pSMB->DataCount;
4941 pSMB->TotalParameterCount = pSMB->ParameterCount;
4942 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4943 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4945 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4946 pSMB->Reserved4 = 0;
4947 pSMB->hdr.smb_buf_length += byte_count;
4948 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4949 pSMB->ByteCount = cpu_to_le16(byte_count);
4950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4953 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4955 cifs_buf_release(pSMB);
4963 /* Can not be used to set time stamps yet (due to old DOS time format) */
4964 /* Can be used to set attributes */
4965 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4966 handling it anyway and NT4 was what we thought it would be needed for
4967 Do not delete it until we prove whether needed for Win9x though */
4969 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4970 __u16 dos_attrs, const struct nls_table *nls_codepage)
4972 SETATTR_REQ *pSMB = NULL;
4973 SETATTR_RSP *pSMBr = NULL;
4978 cFYI(1, ("In SetAttrLegacy"));
4981 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4986 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4988 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4989 PATH_MAX, nls_codepage);
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);
4997 pSMB->attr = cpu_to_le16(dos_attrs);
4998 pSMB->BufferFormat = 0x04;
4999 pSMB->hdr.smb_buf_length += name_len + 1;
5000 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5001 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5002 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5004 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5006 cifs_buf_release(pSMB);
5009 goto SetAttrLgcyRetry;
5013 #endif /* temporarily unneeded SetAttr legacy function */
5016 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
5017 char *fileName, __u64 mode, __u64 uid, __u64 gid,
5018 dev_t device, const struct nls_table *nls_codepage,
5021 TRANSACTION2_SPI_REQ *pSMB = NULL;
5022 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5025 int bytes_returned = 0;
5026 FILE_UNIX_BASIC_INFO *data_offset;
5027 __u16 params, param_offset, offset, count, byte_count;
5029 cFYI(1, ("In SetUID/GID/Mode"));
5031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5036 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5038 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5039 PATH_MAX, nls_codepage, remap);
5040 name_len++; /* trailing null */
5042 } else { /* BB improve the check for buffer overruns BB */
5043 name_len = strnlen(fileName, PATH_MAX);
5044 name_len++; /* trailing null */
5045 strncpy(pSMB->FileName, fileName, name_len);
5048 params = 6 + name_len;
5049 count = sizeof(FILE_UNIX_BASIC_INFO);
5050 pSMB->MaxParameterCount = cpu_to_le16(2);
5051 /* BB find max SMB PDU from sess structure BB */
5052 pSMB->MaxDataCount = cpu_to_le16(1000);
5053 pSMB->MaxSetupCount = 0;
5057 pSMB->Reserved2 = 0;
5058 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5059 InformationLevel) - 4;
5060 offset = param_offset + params;
5062 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5064 memset(data_offset, 0, count);
5065 pSMB->DataOffset = cpu_to_le16(offset);
5066 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5067 pSMB->SetupCount = 1;
5068 pSMB->Reserved3 = 0;
5069 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5070 byte_count = 3 /* pad */ + params + count;
5071 pSMB->ParameterCount = cpu_to_le16(params);
5072 pSMB->DataCount = cpu_to_le16(count);
5073 pSMB->TotalParameterCount = pSMB->ParameterCount;
5074 pSMB->TotalDataCount = pSMB->DataCount;
5075 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5076 pSMB->Reserved4 = 0;
5077 pSMB->hdr.smb_buf_length += byte_count;
5078 /* Samba server ignores set of file size to zero due to bugs in some
5079 older clients, but we should be precise - we use SetFileSize to
5080 set file size and do not want to truncate file size to zero
5081 accidently as happened on one Samba server beta by putting
5082 zero instead of -1 here */
5083 data_offset->EndOfFile = NO_CHANGE_64;
5084 data_offset->NumOfBytes = NO_CHANGE_64;
5085 data_offset->LastStatusChange = NO_CHANGE_64;
5086 data_offset->LastAccessTime = NO_CHANGE_64;
5087 data_offset->LastModificationTime = NO_CHANGE_64;
5088 data_offset->Uid = cpu_to_le64(uid);
5089 data_offset->Gid = cpu_to_le64(gid);
5090 /* better to leave device as zero when it is */
5091 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5092 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5093 data_offset->Permissions = cpu_to_le64(mode);
5096 data_offset->Type = cpu_to_le32(UNIX_FILE);
5097 else if (S_ISDIR(mode))
5098 data_offset->Type = cpu_to_le32(UNIX_DIR);
5099 else if (S_ISLNK(mode))
5100 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5101 else if (S_ISCHR(mode))
5102 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5103 else if (S_ISBLK(mode))
5104 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5105 else if (S_ISFIFO(mode))
5106 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5107 else if (S_ISSOCK(mode))
5108 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5111 pSMB->ByteCount = cpu_to_le16(byte_count);
5112 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5113 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5115 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5117 cifs_buf_release(pSMB);
5123 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5124 const int notify_subdirs, const __u16 netfid,
5125 __u32 filter, struct file *pfile, int multishot,
5126 const struct nls_table *nls_codepage)
5129 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5130 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5131 struct dir_notify_req *dnotify_req;
5134 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5135 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5140 pSMB->TotalParameterCount = 0 ;
5141 pSMB->TotalDataCount = 0;
5142 pSMB->MaxParameterCount = cpu_to_le32(2);
5143 /* BB find exact data count max from sess structure BB */
5144 pSMB->MaxDataCount = 0; /* same in little endian or be */
5145 /* BB VERIFY verify which is correct for above BB */
5146 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5147 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5149 pSMB->MaxSetupCount = 4;
5151 pSMB->ParameterOffset = 0;
5152 pSMB->DataCount = 0;
5153 pSMB->DataOffset = 0;
5154 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5155 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5156 pSMB->ParameterCount = pSMB->TotalParameterCount;
5158 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5159 pSMB->Reserved2 = 0;
5160 pSMB->CompletionFilter = cpu_to_le32(filter);
5161 pSMB->Fid = netfid; /* file handle always le */
5162 pSMB->ByteCount = 0;
5164 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5165 (struct smb_hdr *)pSMBr, &bytes_returned,
5168 cFYI(1, ("Error in Notify = %d", rc));
5170 /* Add file to outstanding requests */
5171 /* BB change to kmem cache alloc */
5172 dnotify_req = kmalloc(
5173 sizeof(struct dir_notify_req),
5176 dnotify_req->Pid = pSMB->hdr.Pid;
5177 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5178 dnotify_req->Mid = pSMB->hdr.Mid;
5179 dnotify_req->Tid = pSMB->hdr.Tid;
5180 dnotify_req->Uid = pSMB->hdr.Uid;
5181 dnotify_req->netfid = netfid;
5182 dnotify_req->pfile = pfile;
5183 dnotify_req->filter = filter;
5184 dnotify_req->multishot = multishot;
5185 spin_lock(&GlobalMid_Lock);
5186 list_add_tail(&dnotify_req->lhead,
5187 &GlobalDnotifyReqList);
5188 spin_unlock(&GlobalMid_Lock);
5192 cifs_buf_release(pSMB);
5195 #ifdef CONFIG_CIFS_XATTR
5197 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5198 const unsigned char *searchName,
5199 char *EAData, size_t buf_size,
5200 const struct nls_table *nls_codepage, int remap)
5202 /* BB assumes one setup word */
5203 TRANSACTION2_QPI_REQ *pSMB = NULL;
5204 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5208 struct fea *temp_fea;
5210 __u16 params, byte_count;
5212 cFYI(1, ("In Query All EAs path %s", searchName));
5214 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5219 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5221 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5222 PATH_MAX, nls_codepage, remap);
5223 name_len++; /* trailing null */
5225 } else { /* BB improve the check for buffer overruns BB */
5226 name_len = strnlen(searchName, PATH_MAX);
5227 name_len++; /* trailing null */
5228 strncpy(pSMB->FileName, searchName, name_len);
5231 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5232 pSMB->TotalDataCount = 0;
5233 pSMB->MaxParameterCount = cpu_to_le16(2);
5234 /* BB find exact max SMB PDU from sess structure BB */
5235 pSMB->MaxDataCount = cpu_to_le16(4000);
5236 pSMB->MaxSetupCount = 0;
5240 pSMB->Reserved2 = 0;
5241 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5242 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5243 pSMB->DataCount = 0;
5244 pSMB->DataOffset = 0;
5245 pSMB->SetupCount = 1;
5246 pSMB->Reserved3 = 0;
5247 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5248 byte_count = params + 1 /* pad */ ;
5249 pSMB->TotalParameterCount = cpu_to_le16(params);
5250 pSMB->ParameterCount = pSMB->TotalParameterCount;
5251 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5252 pSMB->Reserved4 = 0;
5253 pSMB->hdr.smb_buf_length += byte_count;
5254 pSMB->ByteCount = cpu_to_le16(byte_count);
5256 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5257 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5259 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5260 } else { /* decode response */
5261 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5263 /* BB also check enough total bytes returned */
5264 /* BB we need to improve the validity checking
5265 of these trans2 responses */
5266 if (rc || (pSMBr->ByteCount < 4))
5267 rc = -EIO; /* bad smb */
5268 /* else if (pFindData){
5269 memcpy((char *) pFindData,
5270 (char *) &pSMBr->hdr.Protocol +
5273 /* check that length of list is not more than bcc */
5274 /* check that each entry does not go beyond length
5276 /* check that each element of each entry does not
5277 go beyond end of list */
5278 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5279 struct fealist *ea_response_data;
5281 /* validate_trans2_offsets() */
5282 /* BB check if start of smb + data_offset > &bcc+ bcc */
5283 ea_response_data = (struct fealist *)
5284 (((char *) &pSMBr->hdr.Protocol) +
5286 name_len = le32_to_cpu(ea_response_data->list_len);
5287 cFYI(1, ("ea length %d", name_len));
5288 if (name_len <= 8) {
5289 /* returned EA size zeroed at top of function */
5290 cFYI(1, ("empty EA list returned from server"));
5292 /* account for ea list len */
5294 temp_fea = ea_response_data->list;
5295 temp_ptr = (char *)temp_fea;
5296 while (name_len > 0) {
5300 rc += temp_fea->name_len;
5301 /* account for prefix user. and trailing null */
5303 if (rc < (int)buf_size) {
5304 memcpy(EAData, "user.", 5);
5306 memcpy(EAData, temp_ptr,
5307 temp_fea->name_len);
5308 EAData += temp_fea->name_len;
5309 /* null terminate name */
5311 EAData = EAData + 1;
5312 } else if (buf_size == 0) {
5313 /* skip copy - calc size only */
5315 /* stop before overrun buffer */
5319 name_len -= temp_fea->name_len;
5320 temp_ptr += temp_fea->name_len;
5321 /* account for trailing null */
5325 le16_to_cpu(temp_fea->value_len);
5326 name_len -= value_len;
5327 temp_ptr += value_len;
5328 /* BB check that temp_ptr is still
5331 /* no trailing null to account for
5333 /* go on to next EA */
5334 temp_fea = (struct fea *)temp_ptr;
5339 cifs_buf_release(pSMB);
5346 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5347 const unsigned char *searchName, const unsigned char *ea_name,
5348 unsigned char *ea_value, size_t buf_size,
5349 const struct nls_table *nls_codepage, int remap)
5351 TRANSACTION2_QPI_REQ *pSMB = NULL;
5352 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5356 struct fea *temp_fea;
5358 __u16 params, byte_count;
5360 cFYI(1, ("In Query EA path %s", searchName));
5362 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5367 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5369 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5370 PATH_MAX, nls_codepage, remap);
5371 name_len++; /* trailing null */
5373 } else { /* BB improve the check for buffer overruns BB */
5374 name_len = strnlen(searchName, PATH_MAX);
5375 name_len++; /* trailing null */
5376 strncpy(pSMB->FileName, searchName, name_len);
5379 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5380 pSMB->TotalDataCount = 0;
5381 pSMB->MaxParameterCount = cpu_to_le16(2);
5382 /* BB find exact max SMB PDU from sess structure BB */
5383 pSMB->MaxDataCount = cpu_to_le16(4000);
5384 pSMB->MaxSetupCount = 0;
5388 pSMB->Reserved2 = 0;
5389 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5390 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5391 pSMB->DataCount = 0;
5392 pSMB->DataOffset = 0;
5393 pSMB->SetupCount = 1;
5394 pSMB->Reserved3 = 0;
5395 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5396 byte_count = params + 1 /* pad */ ;
5397 pSMB->TotalParameterCount = cpu_to_le16(params);
5398 pSMB->ParameterCount = pSMB->TotalParameterCount;
5399 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5400 pSMB->Reserved4 = 0;
5401 pSMB->hdr.smb_buf_length += byte_count;
5402 pSMB->ByteCount = cpu_to_le16(byte_count);
5404 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5405 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5407 cFYI(1, ("Send error in Query EA = %d", rc));
5408 } else { /* decode response */
5409 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5411 /* BB also check enough total bytes returned */
5412 /* BB we need to improve the validity checking
5413 of these trans2 responses */
5414 if (rc || (pSMBr->ByteCount < 4))
5415 rc = -EIO; /* bad smb */
5416 /* else if (pFindData){
5417 memcpy((char *) pFindData,
5418 (char *) &pSMBr->hdr.Protocol +
5421 /* check that length of list is not more than bcc */
5422 /* check that each entry does not go beyond length
5424 /* check that each element of each entry does not
5425 go beyond end of list */
5426 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5427 struct fealist *ea_response_data;
5429 /* validate_trans2_offsets() */
5430 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5431 ea_response_data = (struct fealist *)
5432 (((char *) &pSMBr->hdr.Protocol) +
5434 name_len = le32_to_cpu(ea_response_data->list_len);
5435 cFYI(1, ("ea length %d", name_len));
5436 if (name_len <= 8) {
5437 /* returned EA size zeroed at top of function */
5438 cFYI(1, ("empty EA list returned from server"));
5440 /* account for ea list len */
5442 temp_fea = ea_response_data->list;
5443 temp_ptr = (char *)temp_fea;
5444 /* loop through checking if we have a matching
5445 name and then return the associated value */
5446 while (name_len > 0) {
5451 le16_to_cpu(temp_fea->value_len);
5452 /* BB validate that value_len falls within SMB,
5453 even though maximum for name_len is 255 */
5454 if (memcmp(temp_fea->name, ea_name,
5455 temp_fea->name_len) == 0) {
5458 /* account for prefix user. and trailing null */
5459 if (rc <= (int)buf_size) {
5461 temp_fea->name+temp_fea->name_len+1,
5463 /* ea values, unlike ea
5466 } else if (buf_size == 0) {
5467 /* skip copy - calc size only */
5469 /* stop before overrun buffer */
5474 name_len -= temp_fea->name_len;
5475 temp_ptr += temp_fea->name_len;
5476 /* account for trailing null */
5479 name_len -= value_len;
5480 temp_ptr += value_len;
5481 /* No trailing null to account for in
5482 value_len. Go on to next EA */
5483 temp_fea = (struct fea *)temp_ptr;
5488 cifs_buf_release(pSMB);
5496 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5497 const char *ea_name, const void *ea_value,
5498 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5501 struct smb_com_transaction2_spi_req *pSMB = NULL;
5502 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5503 struct fealist *parm_data;
5506 int bytes_returned = 0;
5507 __u16 params, param_offset, byte_count, offset, count;
5509 cFYI(1, ("In SetEA"));
5511 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5516 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5518 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5519 PATH_MAX, nls_codepage, remap);
5520 name_len++; /* trailing null */
5522 } else { /* BB improve the check for buffer overruns BB */
5523 name_len = strnlen(fileName, PATH_MAX);
5524 name_len++; /* trailing null */
5525 strncpy(pSMB->FileName, fileName, name_len);
5528 params = 6 + name_len;
5530 /* done calculating parms using name_len of file name,
5531 now use name_len to calculate length of ea name
5532 we are going to create in the inode xattrs */
5533 if (ea_name == NULL)
5536 name_len = strnlen(ea_name, 255);
5538 count = sizeof(*parm_data) + ea_value_len + name_len;
5539 pSMB->MaxParameterCount = cpu_to_le16(2);
5540 /* BB find max SMB PDU from sess */
5541 pSMB->MaxDataCount = cpu_to_le16(1000);
5542 pSMB->MaxSetupCount = 0;
5546 pSMB->Reserved2 = 0;
5547 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5548 InformationLevel) - 4;
5549 offset = param_offset + params;
5550 pSMB->InformationLevel =
5551 cpu_to_le16(SMB_SET_FILE_EA);
5554 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5556 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5557 pSMB->DataOffset = cpu_to_le16(offset);
5558 pSMB->SetupCount = 1;
5559 pSMB->Reserved3 = 0;
5560 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5561 byte_count = 3 /* pad */ + params + count;
5562 pSMB->DataCount = cpu_to_le16(count);
5563 parm_data->list_len = cpu_to_le32(count);
5564 parm_data->list[0].EA_flags = 0;
5565 /* we checked above that name len is less than 255 */
5566 parm_data->list[0].name_len = (__u8)name_len;
5567 /* EA names are always ASCII */
5569 strncpy(parm_data->list[0].name, ea_name, name_len);
5570 parm_data->list[0].name[name_len] = 0;
5571 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5572 /* caller ensures that ea_value_len is less than 64K but
5573 we need to ensure that it fits within the smb */
5575 /*BB add length check to see if it would fit in
5576 negotiated SMB buffer size BB */
5577 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5579 memcpy(parm_data->list[0].name+name_len+1,
5580 ea_value, ea_value_len);
5582 pSMB->TotalDataCount = pSMB->DataCount;
5583 pSMB->ParameterCount = cpu_to_le16(params);
5584 pSMB->TotalParameterCount = pSMB->ParameterCount;
5585 pSMB->Reserved4 = 0;
5586 pSMB->hdr.smb_buf_length += byte_count;
5587 pSMB->ByteCount = cpu_to_le16(byte_count);
5588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5589 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5591 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5593 cifs_buf_release(pSMB);