4 * Copyright (C) International Business Machines Corp., 2002,2009
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 /* Mark as invalid, all open files on tree connections since they
85 were closed when session to server was lost */
86 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
88 struct cifsFileInfo *open_file = NULL;
89 struct list_head *tmp;
90 struct list_head *tmp1;
92 /* list all files open on tree connection and mark them invalid */
93 write_lock(&GlobalSMBSeslock);
94 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
95 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
96 open_file->invalidHandle = true;
98 write_unlock(&GlobalSMBSeslock);
99 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
103 /* Allocate and return pointer to an SMB request buffer, and set basic
104 SMB information in the SMB header. If the return code is zero, this
105 function must have filled in request_buf pointer */
107 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
113 check for tcp and smb session status done differently
114 for those three - in the calling routine */
116 if (tcon->tidStatus == CifsExiting) {
117 /* only tree disconnect, open, and write,
118 (and ulogoff which does not have tcon)
119 are allowed as we start force umount */
120 if ((smb_command != SMB_COM_WRITE_ANDX) &&
121 (smb_command != SMB_COM_OPEN_ANDX) &&
122 (smb_command != SMB_COM_TREE_DISCONNECT)) {
123 cFYI(1, ("can not send cmd %d while umounting",
128 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
129 (tcon->ses->server)) {
130 struct nls_table *nls_codepage;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while (tcon->ses->server->tcpStatus ==
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus ==
139 if (tcon->ses->server->tcpStatus ==
141 /* on "soft" mounts we wait once */
143 (tcon->ses->status == CifsExiting)) {
144 cFYI(1, ("gave up waiting on "
145 "reconnect in smb_init"));
147 } /* else "hard" mount - keep retrying
148 until process is killed or server
149 comes back on-line */
150 } else /* TCP session is reestablished now */
154 nls_codepage = load_nls_default();
155 /* need to prevent multiple threads trying to
156 simultaneously reconnect the same SMB session */
157 down(&tcon->ses->sesSem);
158 if (tcon->ses->need_reconnect)
159 rc = cifs_setup_session(0, tcon->ses,
161 if (!rc && (tcon->need_reconnect)) {
162 mark_open_files_invalid(tcon);
163 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
165 up(&tcon->ses->sesSem);
166 /* BB FIXME add code to check if wsize needs
167 update due to negotiated smb buffer size
170 atomic_inc(&tconInfoReconnectCount);
171 /* tell server Unix caps we support */
172 if (tcon->ses->capabilities & CAP_UNIX)
173 reset_cifs_unix_caps(
176 NULL /* we do not know sb */,
177 NULL /* no vol info */);
180 cFYI(1, ("reconnect tcon rc = %d", rc));
181 /* Removed call to reopen open files here.
182 It is safer (and faster) to reopen files
183 one at a time as needed in read and write */
185 /* Check if handle based operation so we
186 know whether we can continue or not without
187 returning to caller to reset file handle */
188 switch (smb_command) {
189 case SMB_COM_READ_ANDX:
190 case SMB_COM_WRITE_ANDX:
192 case SMB_COM_FIND_CLOSE2:
193 case SMB_COM_LOCKING_ANDX: {
194 unload_nls(nls_codepage);
199 up(&tcon->ses->sesSem);
201 unload_nls(nls_codepage);
210 *request_buf = cifs_small_buf_get();
211 if (*request_buf == NULL) {
212 /* BB should we add a retry in here if not a writepage? */
216 header_assemble((struct smb_hdr *) *request_buf, smb_command,
220 cifs_stats_inc(&tcon->num_smbs_sent);
226 small_smb_init_no_tc(const int smb_command, const int wct,
227 struct cifsSesInfo *ses, void **request_buf)
230 struct smb_hdr *buffer;
232 rc = small_smb_init(smb_command, wct, NULL, request_buf);
236 buffer = (struct smb_hdr *)*request_buf;
237 buffer->Mid = GetNextMid(ses->server);
238 if (ses->capabilities & CAP_UNICODE)
239 buffer->Flags2 |= SMBFLG2_UNICODE;
240 if (ses->capabilities & CAP_STATUS32)
241 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
243 /* uid, tid can stay at zero as set in header assemble */
245 /* BB add support for turning on the signing when
246 this function is used after 1st of session setup requests */
251 /* If the return code is zero, this function must fill in request_buf pointer */
253 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
254 void **request_buf /* returned */ ,
255 void **response_buf /* returned */ )
259 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
260 check for tcp and smb session status done differently
261 for those three - in the calling routine */
263 if (tcon->tidStatus == CifsExiting) {
264 /* only tree disconnect, open, and write,
265 (and ulogoff which does not have tcon)
266 are allowed as we start force umount */
267 if ((smb_command != SMB_COM_WRITE_ANDX) &&
268 (smb_command != SMB_COM_OPEN_ANDX) &&
269 (smb_command != SMB_COM_TREE_DISCONNECT)) {
270 cFYI(1, ("can not send cmd %d while umounting",
276 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
277 (tcon->ses->server)) {
278 struct nls_table *nls_codepage;
279 /* Give Demultiplex thread up to 10 seconds to
280 reconnect, should be greater than cifs socket
281 timeout which is 7 seconds */
282 while (tcon->ses->server->tcpStatus ==
284 wait_event_interruptible_timeout(tcon->ses->server->response_q,
285 (tcon->ses->server->tcpStatus ==
287 if (tcon->ses->server->tcpStatus ==
289 /* on "soft" mounts we wait once */
291 (tcon->ses->status == CifsExiting)) {
292 cFYI(1, ("gave up waiting on "
293 "reconnect in smb_init"));
295 } /* else "hard" mount - keep retrying
296 until process is killed or server
298 } else /* TCP session is reestablished now */
301 nls_codepage = load_nls_default();
302 /* need to prevent multiple threads trying to
303 simultaneously reconnect the same SMB session */
304 down(&tcon->ses->sesSem);
305 if (tcon->ses->need_reconnect)
306 rc = cifs_setup_session(0, tcon->ses,
308 if (!rc && (tcon->need_reconnect)) {
309 mark_open_files_invalid(tcon);
310 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
312 up(&tcon->ses->sesSem);
313 /* BB FIXME add code to check if wsize needs
314 update due to negotiated smb buffer size
317 atomic_inc(&tconInfoReconnectCount);
318 /* tell server Unix caps we support */
319 if (tcon->ses->capabilities & CAP_UNIX)
320 reset_cifs_unix_caps(
323 NULL /* do not know sb */,
324 NULL /* no vol info */);
327 cFYI(1, ("reconnect tcon rc = %d", rc));
328 /* Removed call to reopen open files here.
329 It is safer (and faster) to reopen files
330 one at a time as needed in read and write */
332 /* Check if handle based operation so we
333 know whether we can continue or not without
334 returning to caller to reset file handle */
335 switch (smb_command) {
336 case SMB_COM_READ_ANDX:
337 case SMB_COM_WRITE_ANDX:
339 case SMB_COM_FIND_CLOSE2:
340 case SMB_COM_LOCKING_ANDX: {
341 unload_nls(nls_codepage);
346 up(&tcon->ses->sesSem);
348 unload_nls(nls_codepage);
357 *request_buf = cifs_buf_get();
358 if (*request_buf == NULL) {
359 /* BB should we add a retry in here if not a writepage? */
362 /* Although the original thought was we needed the response buf for */
363 /* potential retries of smb operations it turns out we can determine */
364 /* from the mid flags when the request buffer can be resent without */
365 /* having to use a second distinct buffer for the response */
367 *response_buf = *request_buf;
369 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
373 cifs_stats_inc(&tcon->num_smbs_sent);
378 static int validate_t2(struct smb_t2_rsp *pSMB)
384 /* check for plausible wct, bcc and t2 data and parm sizes */
385 /* check for parm and data offset going beyond end of smb */
386 if (pSMB->hdr.WordCount >= 10) {
387 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
388 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
389 /* check that bcc is at least as big as parms + data */
390 /* check that bcc is less than negotiated smb buffer */
391 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
392 if (total_size < 512) {
394 le16_to_cpu(pSMB->t2_rsp.DataCount);
395 /* BCC le converted in SendReceive */
396 pBCC = (pSMB->hdr.WordCount * 2) +
397 sizeof(struct smb_hdr) +
399 if ((total_size <= (*(u16 *)pBCC)) &&
401 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
407 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
408 sizeof(struct smb_t2_rsp) + 16);
412 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
415 NEGOTIATE_RSP *pSMBr;
419 struct TCP_Server_Info *server;
421 unsigned int secFlags;
425 server = ses->server;
430 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
431 (void **) &pSMB, (void **) &pSMBr);
435 /* if any of auth flags (ie not sign or seal) are overriden use them */
436 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
437 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
438 else /* if override flags set only sign/seal OR them with global auth */
439 secFlags = extended_security | ses->overrideSecFlg;
441 cFYI(1, ("secFlags 0x%x", secFlags));
443 pSMB->hdr.Mid = GetNextMid(server);
444 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
446 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
447 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
448 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
449 cFYI(1, ("Kerberos only mechanism, enable extended security"));
450 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
452 #ifdef CONFIG_CIFS_EXPERIMENTAL
453 else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
454 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
455 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
456 cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
457 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
462 for (i = 0; i < CIFS_NUM_PROT; i++) {
463 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
464 count += strlen(protocols[i].name) + 1;
465 /* null at end of source and target buffers anyway */
467 pSMB->hdr.smb_buf_length += count;
468 pSMB->ByteCount = cpu_to_le16(count);
470 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
471 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
475 dialect = le16_to_cpu(pSMBr->DialectIndex);
476 cFYI(1, ("Dialect: %d", dialect));
477 /* Check wct = 1 error case */
478 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
479 /* core returns wct = 1, but we do not ask for core - otherwise
480 small wct just comes when dialect index is -1 indicating we
481 could not negotiate a common dialect */
484 #ifdef CONFIG_CIFS_WEAK_PW_HASH
485 } else if ((pSMBr->hdr.WordCount == 13)
486 && ((dialect == LANMAN_PROT)
487 || (dialect == LANMAN2_PROT))) {
489 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
491 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
492 (secFlags & CIFSSEC_MAY_PLNTXT))
493 server->secType = LANMAN;
495 cERROR(1, ("mount failed weak security disabled"
496 " in /proc/fs/cifs/SecurityFlags"));
500 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
501 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
502 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
503 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
504 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
505 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
506 /* even though we do not use raw we might as well set this
507 accurately, in case we ever find a need for it */
508 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
509 server->max_rw = 0xFF00;
510 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
512 server->max_rw = 0;/* do not need to use raw anyway */
513 server->capabilities = CAP_MPX_MODE;
515 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
517 /* OS/2 often does not set timezone therefore
518 * we must use server time to calc time zone.
519 * Could deviate slightly from the right zone.
520 * Smallest defined timezone difference is 15 minutes
521 * (i.e. Nepal). Rounding up/down is done to match
524 int val, seconds, remain, result;
525 struct timespec ts, utc;
527 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
528 le16_to_cpu(rsp->SrvTime.Time));
529 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
530 (int)ts.tv_sec, (int)utc.tv_sec,
531 (int)(utc.tv_sec - ts.tv_sec)));
532 val = (int)(utc.tv_sec - ts.tv_sec);
534 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
535 remain = seconds % MIN_TZ_ADJ;
536 if (remain >= (MIN_TZ_ADJ / 2))
537 result += MIN_TZ_ADJ;
540 server->timeAdj = result;
542 server->timeAdj = (int)tmp;
543 server->timeAdj *= 60; /* also in seconds */
545 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
548 /* BB get server time for time conversions and add
549 code to use it and timezone since this is not UTC */
551 if (rsp->EncryptionKeyLength ==
552 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
553 memcpy(server->cryptKey, rsp->EncryptionKey,
554 CIFS_CRYPTO_KEY_SIZE);
555 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
556 rc = -EIO; /* need cryptkey unless plain text */
560 cFYI(1, ("LANMAN negotiated"));
561 /* we will not end up setting signing flags - as no signing
562 was in LANMAN and server did not return the flags on */
564 #else /* weak security disabled */
565 } else if (pSMBr->hdr.WordCount == 13) {
566 cERROR(1, ("mount failed, cifs module not built "
567 "with CIFS_WEAK_PW_HASH support"));
569 #endif /* WEAK_PW_HASH */
571 } else if (pSMBr->hdr.WordCount != 17) {
576 /* else wct == 17 NTLM */
577 server->secMode = pSMBr->SecurityMode;
578 if ((server->secMode & SECMODE_USER) == 0)
579 cFYI(1, ("share mode security"));
581 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
582 #ifdef CONFIG_CIFS_WEAK_PW_HASH
583 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
584 #endif /* CIFS_WEAK_PW_HASH */
585 cERROR(1, ("Server requests plain text password"
586 " but client support disabled"));
588 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
589 server->secType = NTLMv2;
590 else if (secFlags & CIFSSEC_MAY_NTLM)
591 server->secType = NTLM;
592 else if (secFlags & CIFSSEC_MAY_NTLMV2)
593 server->secType = NTLMv2;
594 else if (secFlags & CIFSSEC_MAY_KRB5)
595 server->secType = Kerberos;
596 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
597 server->secType = NTLMSSP;
598 else if (secFlags & CIFSSEC_MAY_LANMAN)
599 server->secType = LANMAN;
600 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
601 else if (secFlags & CIFSSEC_MAY_PLNTXT)
606 cERROR(1, ("Invalid security type"));
609 /* else ... any others ...? */
611 /* one byte, so no need to convert this or EncryptionKeyLen from
613 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
614 /* probably no need to store and check maxvcs */
615 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
616 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
617 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
618 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
619 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
620 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
621 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
622 server->timeAdj *= 60;
623 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
624 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
625 CIFS_CRYPTO_KEY_SIZE);
626 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
627 && (pSMBr->EncryptionKeyLength == 0)) {
628 /* decode security blob */
629 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
630 rc = -EIO; /* no crypt key only if plain text pwd */
634 /* BB might be helpful to save off the domain of server here */
636 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
637 (server->capabilities & CAP_EXTENDED_SECURITY)) {
638 count = pSMBr->ByteCount;
643 read_lock(&cifs_tcp_ses_lock);
644 if (server->srv_count > 1) {
645 read_unlock(&cifs_tcp_ses_lock);
646 if (memcmp(server->server_GUID,
647 pSMBr->u.extended_response.
649 cFYI(1, ("server UID changed"));
650 memcpy(server->server_GUID,
651 pSMBr->u.extended_response.GUID,
655 read_unlock(&cifs_tcp_ses_lock);
656 memcpy(server->server_GUID,
657 pSMBr->u.extended_response.GUID, 16);
661 server->secType = RawNTLMSSP;
663 rc = decode_negTokenInit(pSMBr->u.extended_response.
673 server->capabilities &= ~CAP_EXTENDED_SECURITY;
675 #ifdef CONFIG_CIFS_WEAK_PW_HASH
678 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
679 /* MUST_SIGN already includes the MAY_SIGN FLAG
680 so if this is zero it means that signing is disabled */
681 cFYI(1, ("Signing disabled"));
682 if (server->secMode & SECMODE_SIGN_REQUIRED) {
683 cERROR(1, ("Server requires "
684 "packet signing to be enabled in "
685 "/proc/fs/cifs/SecurityFlags."));
689 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
690 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
691 /* signing required */
692 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
693 if ((server->secMode &
694 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
696 ("signing required but server lacks support"));
699 server->secMode |= SECMODE_SIGN_REQUIRED;
701 /* signing optional ie CIFSSEC_MAY_SIGN */
702 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
704 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
708 cifs_buf_release(pSMB);
710 cFYI(1, ("negprot rc %d", rc));
715 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
717 struct smb_hdr *smb_buffer;
720 cFYI(1, ("In tree disconnect"));
722 /* BB: do we need to check this? These should never be NULL. */
723 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
727 * No need to return error on this operation if tid invalidated and
728 * closed on server already e.g. due to tcp session crashing. Also,
729 * the tcon is no longer on the list, so no need to take lock before
732 if (tcon->need_reconnect)
735 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
736 (void **)&smb_buffer);
740 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
742 cFYI(1, ("Tree disconnect failed %d", rc));
744 /* No need to return error on this operation if tid invalidated and
745 closed on server already e.g. due to tcp session crashing */
753 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
755 LOGOFF_ANDX_REQ *pSMB;
758 cFYI(1, ("In SMBLogoff for session disconnect"));
761 * BB: do we need to check validity of ses and server? They should
762 * always be valid since we have an active reference. If not, that
763 * should probably be a BUG()
765 if (!ses || !ses->server)
769 if (ses->need_reconnect)
770 goto session_already_dead; /* no need to send SMBlogoff if uid
771 already closed due to reconnect */
772 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
778 pSMB->hdr.Mid = GetNextMid(ses->server);
780 if (ses->server->secMode &
781 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
782 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
784 pSMB->hdr.Uid = ses->Suid;
786 pSMB->AndXCommand = 0xFF;
787 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
788 session_already_dead:
791 /* if session dead then we do not need to do ulogoff,
792 since server closed smb session, no sense reporting
800 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
801 __u16 type, const struct nls_table *nls_codepage, int remap)
803 TRANSACTION2_SPI_REQ *pSMB = NULL;
804 TRANSACTION2_SPI_RSP *pSMBr = NULL;
805 struct unlink_psx_rq *pRqD;
808 int bytes_returned = 0;
809 __u16 params, param_offset, offset, byte_count;
811 cFYI(1, ("In POSIX delete"));
813 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
818 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
820 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
821 PATH_MAX, nls_codepage, remap);
822 name_len++; /* trailing null */
824 } else { /* BB add path length overrun check */
825 name_len = strnlen(fileName, PATH_MAX);
826 name_len++; /* trailing null */
827 strncpy(pSMB->FileName, fileName, name_len);
830 params = 6 + name_len;
831 pSMB->MaxParameterCount = cpu_to_le16(2);
832 pSMB->MaxDataCount = 0; /* BB double check this with jra */
833 pSMB->MaxSetupCount = 0;
838 param_offset = offsetof(struct smb_com_transaction2_spi_req,
839 InformationLevel) - 4;
840 offset = param_offset + params;
842 /* Setup pointer to Request Data (inode type) */
843 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
844 pRqD->type = cpu_to_le16(type);
845 pSMB->ParameterOffset = cpu_to_le16(param_offset);
846 pSMB->DataOffset = cpu_to_le16(offset);
847 pSMB->SetupCount = 1;
849 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
850 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
852 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
853 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
854 pSMB->ParameterCount = cpu_to_le16(params);
855 pSMB->TotalParameterCount = pSMB->ParameterCount;
856 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
858 pSMB->hdr.smb_buf_length += byte_count;
859 pSMB->ByteCount = cpu_to_le16(byte_count);
860 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
861 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
863 cFYI(1, ("Posix delete returned %d", rc));
864 cifs_buf_release(pSMB);
866 cifs_stats_inc(&tcon->num_deletes);
875 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
876 const struct nls_table *nls_codepage, int remap)
878 DELETE_FILE_REQ *pSMB = NULL;
879 DELETE_FILE_RSP *pSMBr = NULL;
885 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
890 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
892 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
893 PATH_MAX, nls_codepage, remap);
894 name_len++; /* trailing null */
896 } else { /* BB improve check for buffer overruns BB */
897 name_len = strnlen(fileName, PATH_MAX);
898 name_len++; /* trailing null */
899 strncpy(pSMB->fileName, fileName, name_len);
901 pSMB->SearchAttributes =
902 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
903 pSMB->BufferFormat = 0x04;
904 pSMB->hdr.smb_buf_length += name_len + 1;
905 pSMB->ByteCount = cpu_to_le16(name_len + 1);
906 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
907 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
908 cifs_stats_inc(&tcon->num_deletes);
910 cFYI(1, ("Error in RMFile = %d", rc));
912 cifs_buf_release(pSMB);
920 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
921 const struct nls_table *nls_codepage, int remap)
923 DELETE_DIRECTORY_REQ *pSMB = NULL;
924 DELETE_DIRECTORY_RSP *pSMBr = NULL;
929 cFYI(1, ("In CIFSSMBRmDir"));
931 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
937 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
938 PATH_MAX, nls_codepage, remap);
939 name_len++; /* trailing null */
941 } else { /* BB improve check for buffer overruns BB */
942 name_len = strnlen(dirName, PATH_MAX);
943 name_len++; /* trailing null */
944 strncpy(pSMB->DirName, dirName, name_len);
947 pSMB->BufferFormat = 0x04;
948 pSMB->hdr.smb_buf_length += name_len + 1;
949 pSMB->ByteCount = cpu_to_le16(name_len + 1);
950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
952 cifs_stats_inc(&tcon->num_rmdirs);
954 cFYI(1, ("Error in RMDir = %d", rc));
956 cifs_buf_release(pSMB);
963 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
964 const char *name, const struct nls_table *nls_codepage, int remap)
967 CREATE_DIRECTORY_REQ *pSMB = NULL;
968 CREATE_DIRECTORY_RSP *pSMBr = NULL;
972 cFYI(1, ("In CIFSSMBMkDir"));
974 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
979 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
980 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
981 PATH_MAX, nls_codepage, remap);
982 name_len++; /* trailing null */
984 } else { /* BB improve check for buffer overruns BB */
985 name_len = strnlen(name, PATH_MAX);
986 name_len++; /* trailing null */
987 strncpy(pSMB->DirName, name, name_len);
990 pSMB->BufferFormat = 0x04;
991 pSMB->hdr.smb_buf_length += name_len + 1;
992 pSMB->ByteCount = cpu_to_le16(name_len + 1);
993 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
994 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
995 cifs_stats_inc(&tcon->num_mkdirs);
997 cFYI(1, ("Error in Mkdir = %d", rc));
999 cifs_buf_release(pSMB);
1006 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1007 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1008 __u32 *pOplock, const char *name,
1009 const struct nls_table *nls_codepage, int remap)
1011 TRANSACTION2_SPI_REQ *pSMB = NULL;
1012 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1015 int bytes_returned = 0;
1016 __u16 params, param_offset, offset, byte_count, count;
1017 OPEN_PSX_REQ *pdata;
1018 OPEN_PSX_RSP *psx_rsp;
1020 cFYI(1, ("In POSIX Create"));
1022 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1027 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1029 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1030 PATH_MAX, nls_codepage, remap);
1031 name_len++; /* trailing null */
1033 } else { /* BB improve the check for buffer overruns BB */
1034 name_len = strnlen(name, PATH_MAX);
1035 name_len++; /* trailing null */
1036 strncpy(pSMB->FileName, name, name_len);
1039 params = 6 + name_len;
1040 count = sizeof(OPEN_PSX_REQ);
1041 pSMB->MaxParameterCount = cpu_to_le16(2);
1042 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1043 pSMB->MaxSetupCount = 0;
1047 pSMB->Reserved2 = 0;
1048 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1049 InformationLevel) - 4;
1050 offset = param_offset + params;
1051 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1052 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1053 pdata->Permissions = cpu_to_le64(mode);
1054 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1055 pdata->OpenFlags = cpu_to_le32(*pOplock);
1056 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1057 pSMB->DataOffset = cpu_to_le16(offset);
1058 pSMB->SetupCount = 1;
1059 pSMB->Reserved3 = 0;
1060 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1061 byte_count = 3 /* pad */ + params + count;
1063 pSMB->DataCount = cpu_to_le16(count);
1064 pSMB->ParameterCount = cpu_to_le16(params);
1065 pSMB->TotalDataCount = pSMB->DataCount;
1066 pSMB->TotalParameterCount = pSMB->ParameterCount;
1067 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1068 pSMB->Reserved4 = 0;
1069 pSMB->hdr.smb_buf_length += byte_count;
1070 pSMB->ByteCount = cpu_to_le16(byte_count);
1071 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1072 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1074 cFYI(1, ("Posix create returned %d", rc));
1075 goto psx_create_err;
1078 cFYI(1, ("copying inode info"));
1079 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1081 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1082 rc = -EIO; /* bad smb */
1083 goto psx_create_err;
1086 /* copy return information to pRetData */
1087 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1088 + le16_to_cpu(pSMBr->t2.DataOffset));
1090 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1092 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1093 /* Let caller know file was created so we can set the mode. */
1094 /* Do we care about the CreateAction in any other cases? */
1095 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1096 *pOplock |= CIFS_CREATE_ACTION;
1097 /* check to make sure response data is there */
1098 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1099 pRetData->Type = cpu_to_le32(-1); /* unknown */
1100 cFYI(DBG2, ("unknown type"));
1102 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1103 + sizeof(FILE_UNIX_BASIC_INFO)) {
1104 cERROR(1, ("Open response data too small"));
1105 pRetData->Type = cpu_to_le32(-1);
1106 goto psx_create_err;
1108 memcpy((char *) pRetData,
1109 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1110 sizeof(FILE_UNIX_BASIC_INFO));
1114 cifs_buf_release(pSMB);
1116 cifs_stats_inc(&tcon->num_mkdirs);
1124 static __u16 convert_disposition(int disposition)
1128 switch (disposition) {
1129 case FILE_SUPERSEDE:
1130 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1133 ofun = SMBOPEN_OAPPEND;
1136 ofun = SMBOPEN_OCREATE;
1139 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1141 case FILE_OVERWRITE:
1142 ofun = SMBOPEN_OTRUNC;
1144 case FILE_OVERWRITE_IF:
1145 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1148 cFYI(1, ("unknown disposition %d", disposition));
1149 ofun = SMBOPEN_OAPPEND; /* regular open */
1155 access_flags_to_smbopen_mode(const int access_flags)
1157 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1159 if (masked_flags == GENERIC_READ)
1160 return SMBOPEN_READ;
1161 else if (masked_flags == GENERIC_WRITE)
1162 return SMBOPEN_WRITE;
1164 /* just go for read/write */
1165 return SMBOPEN_READWRITE;
1169 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1170 const char *fileName, const int openDisposition,
1171 const int access_flags, const int create_options, __u16 *netfid,
1172 int *pOplock, FILE_ALL_INFO *pfile_info,
1173 const struct nls_table *nls_codepage, int remap)
1176 OPENX_REQ *pSMB = NULL;
1177 OPENX_RSP *pSMBr = NULL;
1183 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1188 pSMB->AndXCommand = 0xFF; /* none */
1190 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1191 count = 1; /* account for one byte pad to word boundary */
1193 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1194 fileName, PATH_MAX, nls_codepage, remap);
1195 name_len++; /* trailing null */
1197 } else { /* BB improve check for buffer overruns BB */
1198 count = 0; /* no pad */
1199 name_len = strnlen(fileName, PATH_MAX);
1200 name_len++; /* trailing null */
1201 strncpy(pSMB->fileName, fileName, name_len);
1203 if (*pOplock & REQ_OPLOCK)
1204 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1205 else if (*pOplock & REQ_BATCHOPLOCK)
1206 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1208 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1209 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1210 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1211 /* set file as system file if special file such
1212 as fifo and server expecting SFU style and
1213 no Unix extensions */
1215 if (create_options & CREATE_OPTION_SPECIAL)
1216 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1217 else /* BB FIXME BB */
1218 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1220 if (create_options & CREATE_OPTION_READONLY)
1221 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1224 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1225 CREATE_OPTIONS_MASK); */
1226 /* BB FIXME END BB */
1228 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1229 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1231 pSMB->hdr.smb_buf_length += count;
1233 pSMB->ByteCount = cpu_to_le16(count);
1234 /* long_op set to 1 to allow for oplock break timeouts */
1235 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1236 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1237 cifs_stats_inc(&tcon->num_opens);
1239 cFYI(1, ("Error in Open = %d", rc));
1241 /* BB verify if wct == 15 */
1243 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1245 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1246 /* Let caller know file was created so we can set the mode. */
1247 /* Do we care about the CreateAction in any other cases? */
1249 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1250 *pOplock |= CIFS_CREATE_ACTION; */
1254 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1255 pfile_info->LastAccessTime = 0; /* BB fixme */
1256 pfile_info->LastWriteTime = 0; /* BB fixme */
1257 pfile_info->ChangeTime = 0; /* BB fixme */
1258 pfile_info->Attributes =
1259 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1260 /* the file_info buf is endian converted by caller */
1261 pfile_info->AllocationSize =
1262 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1263 pfile_info->EndOfFile = pfile_info->AllocationSize;
1264 pfile_info->NumberOfLinks = cpu_to_le32(1);
1265 pfile_info->DeletePending = 0;
1269 cifs_buf_release(pSMB);
1276 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1277 const char *fileName, const int openDisposition,
1278 const int access_flags, const int create_options, __u16 *netfid,
1279 int *pOplock, FILE_ALL_INFO *pfile_info,
1280 const struct nls_table *nls_codepage, int remap)
1283 OPEN_REQ *pSMB = NULL;
1284 OPEN_RSP *pSMBr = NULL;
1290 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1295 pSMB->AndXCommand = 0xFF; /* none */
1297 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1298 count = 1; /* account for one byte pad to word boundary */
1300 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1301 fileName, PATH_MAX, nls_codepage, remap);
1302 name_len++; /* trailing null */
1304 pSMB->NameLength = cpu_to_le16(name_len);
1305 } else { /* BB improve check for buffer overruns BB */
1306 count = 0; /* no pad */
1307 name_len = strnlen(fileName, PATH_MAX);
1308 name_len++; /* trailing null */
1309 pSMB->NameLength = cpu_to_le16(name_len);
1310 strncpy(pSMB->fileName, fileName, name_len);
1312 if (*pOplock & REQ_OPLOCK)
1313 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1314 else if (*pOplock & REQ_BATCHOPLOCK)
1315 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1316 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1317 pSMB->AllocationSize = 0;
1318 /* set file as system file if special file such
1319 as fifo and server expecting SFU style and
1320 no Unix extensions */
1321 if (create_options & CREATE_OPTION_SPECIAL)
1322 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1324 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1326 /* XP does not handle ATTR_POSIX_SEMANTICS */
1327 /* but it helps speed up case sensitive checks for other
1328 servers such as Samba */
1329 if (tcon->ses->capabilities & CAP_UNIX)
1330 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1332 if (create_options & CREATE_OPTION_READONLY)
1333 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1335 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1336 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1337 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1338 /* BB Expirement with various impersonation levels and verify */
1339 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1340 pSMB->SecurityFlags =
1341 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1344 pSMB->hdr.smb_buf_length += count;
1346 pSMB->ByteCount = cpu_to_le16(count);
1347 /* long_op set to 1 to allow for oplock break timeouts */
1348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1349 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1350 cifs_stats_inc(&tcon->num_opens);
1352 cFYI(1, ("Error in Open = %d", rc));
1354 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1355 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1356 /* Let caller know file was created so we can set the mode. */
1357 /* Do we care about the CreateAction in any other cases? */
1358 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1359 *pOplock |= CIFS_CREATE_ACTION;
1361 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1362 36 /* CreationTime to Attributes */);
1363 /* the file_info buf is endian converted by caller */
1364 pfile_info->AllocationSize = pSMBr->AllocationSize;
1365 pfile_info->EndOfFile = pSMBr->EndOfFile;
1366 pfile_info->NumberOfLinks = cpu_to_le32(1);
1367 pfile_info->DeletePending = 0;
1371 cifs_buf_release(pSMB);
1378 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1379 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1380 char **buf, int *pbuf_type)
1383 READ_REQ *pSMB = NULL;
1384 READ_RSP *pSMBr = NULL;
1385 char *pReadData = NULL;
1387 int resp_buf_type = 0;
1390 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1391 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1394 wct = 10; /* old style read */
1395 if ((lseek >> 32) > 0) {
1396 /* can not handle this big offset for old */
1402 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1406 /* tcon and ses pointer are checked in smb_init */
1407 if (tcon->ses->server == NULL)
1408 return -ECONNABORTED;
1410 pSMB->AndXCommand = 0xFF; /* none */
1412 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1414 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1416 pSMB->Remaining = 0;
1417 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1418 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1420 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1422 /* old style read */
1423 struct smb_com_readx_req *pSMBW =
1424 (struct smb_com_readx_req *)pSMB;
1425 pSMBW->ByteCount = 0;
1428 iov[0].iov_base = (char *)pSMB;
1429 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1430 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1431 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1432 cifs_stats_inc(&tcon->num_reads);
1433 pSMBr = (READ_RSP *)iov[0].iov_base;
1435 cERROR(1, ("Send error in read = %d", rc));
1437 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1438 data_length = data_length << 16;
1439 data_length += le16_to_cpu(pSMBr->DataLength);
1440 *nbytes = data_length;
1442 /*check that DataLength would not go beyond end of SMB */
1443 if ((data_length > CIFSMaxBufSize)
1444 || (data_length > count)) {
1445 cFYI(1, ("bad length %d for count %d",
1446 data_length, count));
1450 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1451 le16_to_cpu(pSMBr->DataOffset);
1452 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1453 cERROR(1,("Faulting on read rc = %d",rc));
1455 }*/ /* can not use copy_to_user when using page cache*/
1457 memcpy(*buf, pReadData, data_length);
1461 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1463 if (resp_buf_type == CIFS_SMALL_BUFFER)
1464 cifs_small_buf_release(iov[0].iov_base);
1465 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1466 cifs_buf_release(iov[0].iov_base);
1467 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1468 /* return buffer to caller to free */
1469 *buf = iov[0].iov_base;
1470 if (resp_buf_type == CIFS_SMALL_BUFFER)
1471 *pbuf_type = CIFS_SMALL_BUFFER;
1472 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1473 *pbuf_type = CIFS_LARGE_BUFFER;
1474 } /* else no valid buffer on return - leave as null */
1476 /* Note: On -EAGAIN error only caller can retry on handle based calls
1477 since file handle passed in no longer valid */
1483 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1484 const int netfid, const unsigned int count,
1485 const __u64 offset, unsigned int *nbytes, const char *buf,
1486 const char __user *ubuf, const int long_op)
1489 WRITE_REQ *pSMB = NULL;
1490 WRITE_RSP *pSMBr = NULL;
1491 int bytes_returned, wct;
1495 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1496 if (tcon->ses == NULL)
1497 return -ECONNABORTED;
1499 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1503 if ((offset >> 32) > 0) {
1504 /* can not handle big offset for old srv */
1509 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1513 /* tcon and ses pointer are checked in smb_init */
1514 if (tcon->ses->server == NULL)
1515 return -ECONNABORTED;
1517 pSMB->AndXCommand = 0xFF; /* none */
1519 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1521 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1523 pSMB->Reserved = 0xFFFFFFFF;
1524 pSMB->WriteMode = 0;
1525 pSMB->Remaining = 0;
1527 /* Can increase buffer size if buffer is big enough in some cases ie we
1528 can send more if LARGE_WRITE_X capability returned by the server and if
1529 our buffer is big enough or if we convert to iovecs on socket writes
1530 and eliminate the copy to the CIFS buffer */
1531 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1532 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1534 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1538 if (bytes_sent > count)
1541 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1543 memcpy(pSMB->Data, buf, bytes_sent);
1545 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1546 cifs_buf_release(pSMB);
1549 } else if (count != 0) {
1551 cifs_buf_release(pSMB);
1553 } /* else setting file size with write of zero bytes */
1555 byte_count = bytes_sent + 1; /* pad */
1556 else /* wct == 12 */
1557 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1559 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1560 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1561 pSMB->hdr.smb_buf_length += byte_count;
1564 pSMB->ByteCount = cpu_to_le16(byte_count);
1565 else { /* old style write has byte count 4 bytes earlier
1567 struct smb_com_writex_req *pSMBW =
1568 (struct smb_com_writex_req *)pSMB;
1569 pSMBW->ByteCount = cpu_to_le16(byte_count);
1572 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1573 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1574 cifs_stats_inc(&tcon->num_writes);
1576 cFYI(1, ("Send error in write = %d", rc));
1579 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1580 *nbytes = (*nbytes) << 16;
1581 *nbytes += le16_to_cpu(pSMBr->Count);
1584 cifs_buf_release(pSMB);
1586 /* Note: On -EAGAIN error only caller can retry on handle based calls
1587 since file handle passed in no longer valid */
1593 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1594 const int netfid, const unsigned int count,
1595 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1596 int n_vec, const int long_op)
1599 WRITE_REQ *pSMB = NULL;
1602 int resp_buf_type = 0;
1606 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1608 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1612 if ((offset >> 32) > 0) {
1613 /* can not handle big offset for old srv */
1617 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1620 /* tcon and ses pointer are checked in smb_init */
1621 if (tcon->ses->server == NULL)
1622 return -ECONNABORTED;
1624 pSMB->AndXCommand = 0xFF; /* none */
1626 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1628 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1629 pSMB->Reserved = 0xFFFFFFFF;
1630 pSMB->WriteMode = 0;
1631 pSMB->Remaining = 0;
1634 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1636 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1637 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1638 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1640 pSMB->hdr.smb_buf_length += count+1;
1641 else /* wct == 12 */
1642 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1644 pSMB->ByteCount = cpu_to_le16(count + 1);
1645 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1646 struct smb_com_writex_req *pSMBW =
1647 (struct smb_com_writex_req *)pSMB;
1648 pSMBW->ByteCount = cpu_to_le16(count + 5);
1650 iov[0].iov_base = pSMB;
1652 iov[0].iov_len = smb_hdr_len + 4;
1653 else /* wct == 12 pad bigger by four bytes */
1654 iov[0].iov_len = smb_hdr_len + 8;
1657 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1659 cifs_stats_inc(&tcon->num_writes);
1661 cFYI(1, ("Send error Write2 = %d", rc));
1662 } else if (resp_buf_type == 0) {
1663 /* presumably this can not happen, but best to be safe */
1666 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1667 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1668 *nbytes = (*nbytes) << 16;
1669 *nbytes += le16_to_cpu(pSMBr->Count);
1672 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1673 if (resp_buf_type == CIFS_SMALL_BUFFER)
1674 cifs_small_buf_release(iov[0].iov_base);
1675 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1676 cifs_buf_release(iov[0].iov_base);
1678 /* Note: On -EAGAIN error only caller can retry on handle based calls
1679 since file handle passed in no longer valid */
1686 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1687 const __u16 smb_file_id, const __u64 len,
1688 const __u64 offset, const __u32 numUnlock,
1689 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1692 LOCK_REQ *pSMB = NULL;
1693 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1698 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1699 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1704 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1705 timeout = CIFS_ASYNC_OP; /* no response expected */
1707 } else if (waitFlag) {
1708 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1709 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1714 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1715 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1716 pSMB->LockType = lockType;
1717 pSMB->AndXCommand = 0xFF; /* none */
1718 pSMB->Fid = smb_file_id; /* netfid stays le */
1720 if ((numLock != 0) || (numUnlock != 0)) {
1721 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1722 /* BB where to store pid high? */
1723 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1724 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1725 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1726 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1727 count = sizeof(LOCKING_ANDX_RANGE);
1732 pSMB->hdr.smb_buf_length += count;
1733 pSMB->ByteCount = cpu_to_le16(count);
1736 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1737 (struct smb_hdr *) pSMB, &bytes_returned);
1738 cifs_small_buf_release(pSMB);
1740 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1742 /* SMB buffer freed by function above */
1744 cifs_stats_inc(&tcon->num_locks);
1746 cFYI(1, ("Send error in Lock = %d", rc));
1748 /* Note: On -EAGAIN error only caller can retry on handle based calls
1749 since file handle passed in no longer valid */
1754 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1755 const __u16 smb_file_id, const int get_flag, const __u64 len,
1756 struct file_lock *pLockData, const __u16 lock_type,
1757 const bool waitFlag)
1759 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1760 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1761 struct cifs_posix_lock *parm_data;
1764 int bytes_returned = 0;
1765 int resp_buf_type = 0;
1766 __u16 params, param_offset, offset, byte_count, count;
1769 cFYI(1, ("Posix Lock"));
1771 if (pLockData == NULL)
1774 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1779 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1782 pSMB->MaxSetupCount = 0;
1785 pSMB->Reserved2 = 0;
1786 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1787 offset = param_offset + params;
1789 count = sizeof(struct cifs_posix_lock);
1790 pSMB->MaxParameterCount = cpu_to_le16(2);
1791 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1792 pSMB->SetupCount = 1;
1793 pSMB->Reserved3 = 0;
1795 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1797 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1798 byte_count = 3 /* pad */ + params + count;
1799 pSMB->DataCount = cpu_to_le16(count);
1800 pSMB->ParameterCount = cpu_to_le16(params);
1801 pSMB->TotalDataCount = pSMB->DataCount;
1802 pSMB->TotalParameterCount = pSMB->ParameterCount;
1803 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1804 parm_data = (struct cifs_posix_lock *)
1805 (((char *) &pSMB->hdr.Protocol) + offset);
1807 parm_data->lock_type = cpu_to_le16(lock_type);
1809 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1810 parm_data->lock_flags = cpu_to_le16(1);
1811 pSMB->Timeout = cpu_to_le32(-1);
1815 parm_data->pid = cpu_to_le32(current->tgid);
1816 parm_data->start = cpu_to_le64(pLockData->fl_start);
1817 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1819 pSMB->DataOffset = cpu_to_le16(offset);
1820 pSMB->Fid = smb_file_id;
1821 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1822 pSMB->Reserved4 = 0;
1823 pSMB->hdr.smb_buf_length += byte_count;
1824 pSMB->ByteCount = cpu_to_le16(byte_count);
1826 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1827 (struct smb_hdr *) pSMBr, &bytes_returned);
1829 iov[0].iov_base = (char *)pSMB;
1830 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1831 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1832 &resp_buf_type, timeout);
1833 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1834 not try to free it twice below on exit */
1835 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1839 cFYI(1, ("Send error in Posix Lock = %d", rc));
1840 } else if (get_flag) {
1841 /* lock structure can be returned on get */
1844 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1846 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1847 rc = -EIO; /* bad smb */
1850 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1851 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1852 if (data_count < sizeof(struct cifs_posix_lock)) {
1856 parm_data = (struct cifs_posix_lock *)
1857 ((char *)&pSMBr->hdr.Protocol + data_offset);
1858 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1859 pLockData->fl_type = F_UNLCK;
1864 cifs_small_buf_release(pSMB);
1866 if (resp_buf_type == CIFS_SMALL_BUFFER)
1867 cifs_small_buf_release(iov[0].iov_base);
1868 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1869 cifs_buf_release(iov[0].iov_base);
1871 /* Note: On -EAGAIN error only caller can retry on handle based calls
1872 since file handle passed in no longer valid */
1879 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1882 CLOSE_REQ *pSMB = NULL;
1883 cFYI(1, ("In CIFSSMBClose"));
1885 /* do not retry on dead session on close */
1886 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1892 pSMB->FileID = (__u16) smb_file_id;
1893 pSMB->LastWriteTime = 0xFFFFFFFF;
1894 pSMB->ByteCount = 0;
1895 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1896 cifs_stats_inc(&tcon->num_closes);
1899 /* EINTR is expected when user ctl-c to kill app */
1900 cERROR(1, ("Send error in Close = %d", rc));
1904 /* Since session is dead, file will be closed on server already */
1912 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1915 FLUSH_REQ *pSMB = NULL;
1916 cFYI(1, ("In CIFSSMBFlush"));
1918 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1922 pSMB->FileID = (__u16) smb_file_id;
1923 pSMB->ByteCount = 0;
1924 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1925 cifs_stats_inc(&tcon->num_flushes);
1927 cERROR(1, ("Send error in Flush = %d", rc));
1933 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1934 const char *fromName, const char *toName,
1935 const struct nls_table *nls_codepage, int remap)
1938 RENAME_REQ *pSMB = NULL;
1939 RENAME_RSP *pSMBr = NULL;
1941 int name_len, name_len2;
1944 cFYI(1, ("In CIFSSMBRename"));
1946 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1951 pSMB->BufferFormat = 0x04;
1952 pSMB->SearchAttributes =
1953 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1956 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1958 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1959 PATH_MAX, nls_codepage, remap);
1960 name_len++; /* trailing null */
1962 pSMB->OldFileName[name_len] = 0x04; /* pad */
1963 /* protocol requires ASCII signature byte on Unicode string */
1964 pSMB->OldFileName[name_len + 1] = 0x00;
1966 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1967 toName, PATH_MAX, nls_codepage, remap);
1968 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1969 name_len2 *= 2; /* convert to bytes */
1970 } else { /* BB improve the check for buffer overruns BB */
1971 name_len = strnlen(fromName, PATH_MAX);
1972 name_len++; /* trailing null */
1973 strncpy(pSMB->OldFileName, fromName, name_len);
1974 name_len2 = strnlen(toName, PATH_MAX);
1975 name_len2++; /* trailing null */
1976 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1977 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1978 name_len2++; /* trailing null */
1979 name_len2++; /* signature byte */
1982 count = 1 /* 1st signature byte */ + name_len + name_len2;
1983 pSMB->hdr.smb_buf_length += count;
1984 pSMB->ByteCount = cpu_to_le16(count);
1986 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1987 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1988 cifs_stats_inc(&tcon->num_renames);
1990 cFYI(1, ("Send error in rename = %d", rc));
1992 cifs_buf_release(pSMB);
2000 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2001 int netfid, const char *target_name,
2002 const struct nls_table *nls_codepage, int remap)
2004 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2005 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2006 struct set_file_rename *rename_info;
2008 char dummy_string[30];
2010 int bytes_returned = 0;
2012 __u16 params, param_offset, offset, count, byte_count;
2014 cFYI(1, ("Rename to File by handle"));
2015 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2021 pSMB->MaxSetupCount = 0;
2025 pSMB->Reserved2 = 0;
2026 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2027 offset = param_offset + params;
2029 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2030 rename_info = (struct set_file_rename *) data_offset;
2031 pSMB->MaxParameterCount = cpu_to_le16(2);
2032 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2033 pSMB->SetupCount = 1;
2034 pSMB->Reserved3 = 0;
2035 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2036 byte_count = 3 /* pad */ + params;
2037 pSMB->ParameterCount = cpu_to_le16(params);
2038 pSMB->TotalParameterCount = pSMB->ParameterCount;
2039 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2040 pSMB->DataOffset = cpu_to_le16(offset);
2041 /* construct random name ".cifs_tmp<inodenum><mid>" */
2042 rename_info->overwrite = cpu_to_le32(1);
2043 rename_info->root_fid = 0;
2044 /* unicode only call */
2045 if (target_name == NULL) {
2046 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2047 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2048 dummy_string, 24, nls_codepage, remap);
2050 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2051 target_name, PATH_MAX, nls_codepage,
2054 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2055 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2056 byte_count += count;
2057 pSMB->DataCount = cpu_to_le16(count);
2058 pSMB->TotalDataCount = pSMB->DataCount;
2060 pSMB->InformationLevel =
2061 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2062 pSMB->Reserved4 = 0;
2063 pSMB->hdr.smb_buf_length += byte_count;
2064 pSMB->ByteCount = cpu_to_le16(byte_count);
2065 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2066 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2067 cifs_stats_inc(&pTcon->num_t2renames);
2069 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2071 cifs_buf_release(pSMB);
2073 /* Note: On -EAGAIN error only caller can retry on handle based calls
2074 since file handle passed in no longer valid */
2080 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2081 const __u16 target_tid, const char *toName, const int flags,
2082 const struct nls_table *nls_codepage, int remap)
2085 COPY_REQ *pSMB = NULL;
2086 COPY_RSP *pSMBr = NULL;
2088 int name_len, name_len2;
2091 cFYI(1, ("In CIFSSMBCopy"));
2093 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2098 pSMB->BufferFormat = 0x04;
2099 pSMB->Tid2 = target_tid;
2101 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2103 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2104 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2105 fromName, PATH_MAX, nls_codepage,
2107 name_len++; /* trailing null */
2109 pSMB->OldFileName[name_len] = 0x04; /* pad */
2110 /* protocol requires ASCII signature byte on Unicode string */
2111 pSMB->OldFileName[name_len + 1] = 0x00;
2113 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2114 toName, PATH_MAX, nls_codepage, remap);
2115 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2116 name_len2 *= 2; /* convert to bytes */
2117 } else { /* BB improve the check for buffer overruns BB */
2118 name_len = strnlen(fromName, PATH_MAX);
2119 name_len++; /* trailing null */
2120 strncpy(pSMB->OldFileName, fromName, name_len);
2121 name_len2 = strnlen(toName, PATH_MAX);
2122 name_len2++; /* trailing null */
2123 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2124 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2125 name_len2++; /* trailing null */
2126 name_len2++; /* signature byte */
2129 count = 1 /* 1st signature byte */ + name_len + name_len2;
2130 pSMB->hdr.smb_buf_length += count;
2131 pSMB->ByteCount = cpu_to_le16(count);
2133 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2134 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2136 cFYI(1, ("Send error in copy = %d with %d files copied",
2137 rc, le16_to_cpu(pSMBr->CopyCount)));
2139 cifs_buf_release(pSMB);
2148 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2149 const char *fromName, const char *toName,
2150 const struct nls_table *nls_codepage)
2152 TRANSACTION2_SPI_REQ *pSMB = NULL;
2153 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2156 int name_len_target;
2158 int bytes_returned = 0;
2159 __u16 params, param_offset, offset, byte_count;
2161 cFYI(1, ("In Symlink Unix style"));
2163 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2168 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2170 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2171 /* find define for this maxpathcomponent */
2173 name_len++; /* trailing null */
2176 } else { /* BB improve the check for buffer overruns BB */
2177 name_len = strnlen(fromName, PATH_MAX);
2178 name_len++; /* trailing null */
2179 strncpy(pSMB->FileName, fromName, name_len);
2181 params = 6 + name_len;
2182 pSMB->MaxSetupCount = 0;
2186 pSMB->Reserved2 = 0;
2187 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2188 InformationLevel) - 4;
2189 offset = param_offset + params;
2191 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2192 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2194 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2195 /* find define for this maxpathcomponent */
2197 name_len_target++; /* trailing null */
2198 name_len_target *= 2;
2199 } else { /* BB improve the check for buffer overruns BB */
2200 name_len_target = strnlen(toName, PATH_MAX);
2201 name_len_target++; /* trailing null */
2202 strncpy(data_offset, toName, name_len_target);
2205 pSMB->MaxParameterCount = cpu_to_le16(2);
2206 /* BB find exact max on data count below from sess */
2207 pSMB->MaxDataCount = cpu_to_le16(1000);
2208 pSMB->SetupCount = 1;
2209 pSMB->Reserved3 = 0;
2210 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2211 byte_count = 3 /* pad */ + params + name_len_target;
2212 pSMB->DataCount = cpu_to_le16(name_len_target);
2213 pSMB->ParameterCount = cpu_to_le16(params);
2214 pSMB->TotalDataCount = pSMB->DataCount;
2215 pSMB->TotalParameterCount = pSMB->ParameterCount;
2216 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2217 pSMB->DataOffset = cpu_to_le16(offset);
2218 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2219 pSMB->Reserved4 = 0;
2220 pSMB->hdr.smb_buf_length += byte_count;
2221 pSMB->ByteCount = cpu_to_le16(byte_count);
2222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2223 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2224 cifs_stats_inc(&tcon->num_symlinks);
2226 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2228 cifs_buf_release(pSMB);
2231 goto createSymLinkRetry;
2237 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2238 const char *fromName, const char *toName,
2239 const struct nls_table *nls_codepage, int remap)
2241 TRANSACTION2_SPI_REQ *pSMB = NULL;
2242 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2245 int name_len_target;
2247 int bytes_returned = 0;
2248 __u16 params, param_offset, offset, byte_count;
2250 cFYI(1, ("In Create Hard link Unix style"));
2251 createHardLinkRetry:
2252 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2257 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2258 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2259 PATH_MAX, nls_codepage, remap);
2260 name_len++; /* trailing null */
2263 } else { /* BB improve the check for buffer overruns BB */
2264 name_len = strnlen(toName, PATH_MAX);
2265 name_len++; /* trailing null */
2266 strncpy(pSMB->FileName, toName, name_len);
2268 params = 6 + name_len;
2269 pSMB->MaxSetupCount = 0;
2273 pSMB->Reserved2 = 0;
2274 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2275 InformationLevel) - 4;
2276 offset = param_offset + params;
2278 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2279 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2281 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2282 nls_codepage, remap);
2283 name_len_target++; /* trailing null */
2284 name_len_target *= 2;
2285 } else { /* BB improve the check for buffer overruns BB */
2286 name_len_target = strnlen(fromName, PATH_MAX);
2287 name_len_target++; /* trailing null */
2288 strncpy(data_offset, fromName, name_len_target);
2291 pSMB->MaxParameterCount = cpu_to_le16(2);
2292 /* BB find exact max on data count below from sess*/
2293 pSMB->MaxDataCount = cpu_to_le16(1000);
2294 pSMB->SetupCount = 1;
2295 pSMB->Reserved3 = 0;
2296 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2297 byte_count = 3 /* pad */ + params + name_len_target;
2298 pSMB->ParameterCount = cpu_to_le16(params);
2299 pSMB->TotalParameterCount = pSMB->ParameterCount;
2300 pSMB->DataCount = cpu_to_le16(name_len_target);
2301 pSMB->TotalDataCount = pSMB->DataCount;
2302 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2303 pSMB->DataOffset = cpu_to_le16(offset);
2304 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2305 pSMB->Reserved4 = 0;
2306 pSMB->hdr.smb_buf_length += byte_count;
2307 pSMB->ByteCount = cpu_to_le16(byte_count);
2308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2309 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2310 cifs_stats_inc(&tcon->num_hardlinks);
2312 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2314 cifs_buf_release(pSMB);
2316 goto createHardLinkRetry;
2322 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2323 const char *fromName, const char *toName,
2324 const struct nls_table *nls_codepage, int remap)
2327 NT_RENAME_REQ *pSMB = NULL;
2328 RENAME_RSP *pSMBr = NULL;
2330 int name_len, name_len2;
2333 cFYI(1, ("In CIFSCreateHardLink"));
2334 winCreateHardLinkRetry:
2336 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2341 pSMB->SearchAttributes =
2342 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2344 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2345 pSMB->ClusterCount = 0;
2347 pSMB->BufferFormat = 0x04;
2349 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2351 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2352 PATH_MAX, nls_codepage, remap);
2353 name_len++; /* trailing null */
2356 /* protocol specifies ASCII buffer format (0x04) for unicode */
2357 pSMB->OldFileName[name_len] = 0x04;
2358 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2360 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2361 toName, PATH_MAX, nls_codepage, remap);
2362 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2363 name_len2 *= 2; /* convert to bytes */
2364 } else { /* BB improve the check for buffer overruns BB */
2365 name_len = strnlen(fromName, PATH_MAX);
2366 name_len++; /* trailing null */
2367 strncpy(pSMB->OldFileName, fromName, name_len);
2368 name_len2 = strnlen(toName, PATH_MAX);
2369 name_len2++; /* trailing null */
2370 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2371 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2372 name_len2++; /* trailing null */
2373 name_len2++; /* signature byte */
2376 count = 1 /* string type byte */ + name_len + name_len2;
2377 pSMB->hdr.smb_buf_length += count;
2378 pSMB->ByteCount = cpu_to_le16(count);
2380 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2381 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2382 cifs_stats_inc(&tcon->num_hardlinks);
2384 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2386 cifs_buf_release(pSMB);
2388 goto winCreateHardLinkRetry;
2394 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2395 const unsigned char *searchName, char **symlinkinfo,
2396 const struct nls_table *nls_codepage)
2398 /* SMB_QUERY_FILE_UNIX_LINK */
2399 TRANSACTION2_QPI_REQ *pSMB = NULL;
2400 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2404 __u16 params, byte_count;
2407 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2410 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2415 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2417 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2418 PATH_MAX, nls_codepage);
2419 name_len++; /* trailing null */
2421 } else { /* BB improve the check for buffer overruns BB */
2422 name_len = strnlen(searchName, PATH_MAX);
2423 name_len++; /* trailing null */
2424 strncpy(pSMB->FileName, searchName, name_len);
2427 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2428 pSMB->TotalDataCount = 0;
2429 pSMB->MaxParameterCount = cpu_to_le16(2);
2430 /* BB find exact max data count below from sess structure BB */
2431 pSMB->MaxDataCount = cpu_to_le16(4000);
2432 pSMB->MaxSetupCount = 0;
2436 pSMB->Reserved2 = 0;
2437 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2438 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2439 pSMB->DataCount = 0;
2440 pSMB->DataOffset = 0;
2441 pSMB->SetupCount = 1;
2442 pSMB->Reserved3 = 0;
2443 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2444 byte_count = params + 1 /* pad */ ;
2445 pSMB->TotalParameterCount = cpu_to_le16(params);
2446 pSMB->ParameterCount = pSMB->TotalParameterCount;
2447 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2448 pSMB->Reserved4 = 0;
2449 pSMB->hdr.smb_buf_length += byte_count;
2450 pSMB->ByteCount = cpu_to_le16(byte_count);
2452 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2453 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2455 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2457 /* decode response */
2459 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2460 /* BB also check enough total bytes returned */
2461 if (rc || (pSMBr->ByteCount < 2))
2465 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2467 data_start = ((char *) &pSMBr->hdr.Protocol) +
2468 le16_to_cpu(pSMBr->t2.DataOffset);
2470 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2475 /* BB FIXME investigate remapping reserved chars here */
2476 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2477 is_unicode, nls_codepage);
2482 cifs_buf_release(pSMB);
2484 goto querySymLinkRetry;
2488 #ifdef CONFIG_CIFS_EXPERIMENTAL
2489 /* Initialize NT TRANSACT SMB into small smb request buffer.
2490 This assumes that all NT TRANSACTS that we init here have
2491 total parm and data under about 400 bytes (to fit in small cifs
2492 buffer size), which is the case so far, it easily fits. NB:
2493 Setup words themselves and ByteCount
2494 MaxSetupCount (size of returned setup area) and
2495 MaxParameterCount (returned parms size) must be set by caller */
2497 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2498 const int parm_len, struct cifsTconInfo *tcon,
2503 struct smb_com_ntransact_req *pSMB;
2505 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2509 *ret_buf = (void *)pSMB;
2511 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2512 pSMB->TotalDataCount = 0;
2513 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2514 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2515 pSMB->ParameterCount = pSMB->TotalParameterCount;
2516 pSMB->DataCount = pSMB->TotalDataCount;
2517 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2518 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2519 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2520 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2521 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2522 pSMB->SubCommand = cpu_to_le16(sub_command);
2527 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2528 __u32 *pparmlen, __u32 *pdatalen)
2531 __u32 data_count, data_offset, parm_count, parm_offset;
2532 struct smb_com_ntransact_rsp *pSMBr;
2540 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2542 /* ByteCount was converted from little endian in SendReceive */
2543 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2544 (char *)&pSMBr->ByteCount;
2546 data_offset = le32_to_cpu(pSMBr->DataOffset);
2547 data_count = le32_to_cpu(pSMBr->DataCount);
2548 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2549 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2551 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2552 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2554 /* should we also check that parm and data areas do not overlap? */
2555 if (*ppparm > end_of_smb) {
2556 cFYI(1, ("parms start after end of smb"));
2558 } else if (parm_count + *ppparm > end_of_smb) {
2559 cFYI(1, ("parm end after end of smb"));
2561 } else if (*ppdata > end_of_smb) {
2562 cFYI(1, ("data starts after end of smb"));
2564 } else if (data_count + *ppdata > end_of_smb) {
2565 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2566 *ppdata, data_count, (data_count + *ppdata),
2567 end_of_smb, pSMBr));
2569 } else if (parm_count + data_count > pSMBr->ByteCount) {
2570 cFYI(1, ("parm count and data count larger than SMB"));
2573 *pdatalen = data_count;
2574 *pparmlen = parm_count;
2579 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2580 const unsigned char *searchName,
2581 char *symlinkinfo, const int buflen, __u16 fid,
2582 const struct nls_table *nls_codepage)
2586 struct smb_com_transaction_ioctl_req *pSMB;
2587 struct smb_com_transaction_ioctl_rsp *pSMBr;
2589 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2590 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2595 pSMB->TotalParameterCount = 0 ;
2596 pSMB->TotalDataCount = 0;
2597 pSMB->MaxParameterCount = cpu_to_le32(2);
2598 /* BB find exact data count max from sess structure BB */
2599 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2600 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2601 pSMB->MaxSetupCount = 4;
2603 pSMB->ParameterOffset = 0;
2604 pSMB->DataCount = 0;
2605 pSMB->DataOffset = 0;
2606 pSMB->SetupCount = 4;
2607 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2608 pSMB->ParameterCount = pSMB->TotalParameterCount;
2609 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2610 pSMB->IsFsctl = 1; /* FSCTL */
2611 pSMB->IsRootFlag = 0;
2612 pSMB->Fid = fid; /* file handle always le */
2613 pSMB->ByteCount = 0;
2615 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2616 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2618 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2619 } else { /* decode response */
2620 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2621 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2622 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2623 /* BB also check enough total bytes returned */
2624 rc = -EIO; /* bad smb */
2627 if (data_count && (data_count < 2048)) {
2628 char *end_of_smb = 2 /* sizeof byte count */ +
2629 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2631 struct reparse_data *reparse_buf =
2632 (struct reparse_data *)
2633 ((char *)&pSMBr->hdr.Protocol
2635 if ((char *)reparse_buf >= end_of_smb) {
2639 if ((reparse_buf->LinkNamesBuf +
2640 reparse_buf->TargetNameOffset +
2641 reparse_buf->TargetNameLen) > end_of_smb) {
2642 cFYI(1, ("reparse buf beyond SMB"));
2647 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2648 cifs_from_ucs2(symlinkinfo, (__le16 *)
2649 (reparse_buf->LinkNamesBuf +
2650 reparse_buf->TargetNameOffset),
2652 reparse_buf->TargetNameLen,
2654 } else { /* ASCII names */
2655 strncpy(symlinkinfo,
2656 reparse_buf->LinkNamesBuf +
2657 reparse_buf->TargetNameOffset,
2658 min_t(const int, buflen,
2659 reparse_buf->TargetNameLen));
2663 cFYI(1, ("Invalid return data count on "
2664 "get reparse info ioctl"));
2666 symlinkinfo[buflen] = 0; /* just in case so the caller
2667 does not go off the end of the buffer */
2668 cFYI(1, ("readlink result - %s", symlinkinfo));
2672 cifs_buf_release(pSMB);
2674 /* Note: On -EAGAIN error only caller can retry on handle based calls
2675 since file handle passed in no longer valid */
2679 #endif /* CIFS_EXPERIMENTAL */
2681 #ifdef CONFIG_CIFS_POSIX
2683 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2684 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2685 struct cifs_posix_ace *cifs_ace)
2687 /* u8 cifs fields do not need le conversion */
2688 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2689 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2690 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2691 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2696 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2697 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2698 const int acl_type, const int size_of_data_area)
2703 struct cifs_posix_ace *pACE;
2704 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2705 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2707 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2710 if (acl_type & ACL_TYPE_ACCESS) {
2711 count = le16_to_cpu(cifs_acl->access_entry_count);
2712 pACE = &cifs_acl->ace_array[0];
2713 size = sizeof(struct cifs_posix_acl);
2714 size += sizeof(struct cifs_posix_ace) * count;
2715 /* check if we would go beyond end of SMB */
2716 if (size_of_data_area < size) {
2717 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2718 size_of_data_area, size));
2721 } else if (acl_type & ACL_TYPE_DEFAULT) {
2722 count = le16_to_cpu(cifs_acl->access_entry_count);
2723 size = sizeof(struct cifs_posix_acl);
2724 size += sizeof(struct cifs_posix_ace) * count;
2725 /* skip past access ACEs to get to default ACEs */
2726 pACE = &cifs_acl->ace_array[count];
2727 count = le16_to_cpu(cifs_acl->default_entry_count);
2728 size += sizeof(struct cifs_posix_ace) * count;
2729 /* check if we would go beyond end of SMB */
2730 if (size_of_data_area < size)
2737 size = posix_acl_xattr_size(count);
2738 if ((buflen == 0) || (local_acl == NULL)) {
2739 /* used to query ACL EA size */
2740 } else if (size > buflen) {
2742 } else /* buffer big enough */ {
2743 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2744 for (i = 0; i < count ; i++) {
2745 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2752 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2753 const posix_acl_xattr_entry *local_ace)
2755 __u16 rc = 0; /* 0 = ACL converted ok */
2757 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2758 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2759 /* BB is there a better way to handle the large uid? */
2760 if (local_ace->e_id == cpu_to_le32(-1)) {
2761 /* Probably no need to le convert -1 on any arch but can not hurt */
2762 cifs_ace->cifs_uid = cpu_to_le64(-1);
2764 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2765 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2769 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2770 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2771 const int buflen, const int acl_type)
2774 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2775 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2779 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2782 count = posix_acl_xattr_count((size_t)buflen);
2783 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2785 count, buflen, le32_to_cpu(local_acl->a_version)));
2786 if (le32_to_cpu(local_acl->a_version) != 2) {
2787 cFYI(1, ("unknown POSIX ACL version %d",
2788 le32_to_cpu(local_acl->a_version)));
2791 cifs_acl->version = cpu_to_le16(1);
2792 if (acl_type == ACL_TYPE_ACCESS)
2793 cifs_acl->access_entry_count = cpu_to_le16(count);
2794 else if (acl_type == ACL_TYPE_DEFAULT)
2795 cifs_acl->default_entry_count = cpu_to_le16(count);
2797 cFYI(1, ("unknown ACL type %d", acl_type));
2800 for (i = 0; i < count; i++) {
2801 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2802 &local_acl->a_entries[i]);
2804 /* ACE not converted */
2809 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2810 rc += sizeof(struct cifs_posix_acl);
2811 /* BB add check to make sure ACL does not overflow SMB */
2817 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2818 const unsigned char *searchName,
2819 char *acl_inf, const int buflen, const int acl_type,
2820 const struct nls_table *nls_codepage, int remap)
2822 /* SMB_QUERY_POSIX_ACL */
2823 TRANSACTION2_QPI_REQ *pSMB = NULL;
2824 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2828 __u16 params, byte_count;
2830 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2833 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2838 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2840 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2841 PATH_MAX, nls_codepage, remap);
2842 name_len++; /* trailing null */
2844 pSMB->FileName[name_len] = 0;
2845 pSMB->FileName[name_len+1] = 0;
2846 } else { /* BB improve the check for buffer overruns BB */
2847 name_len = strnlen(searchName, PATH_MAX);
2848 name_len++; /* trailing null */
2849 strncpy(pSMB->FileName, searchName, name_len);
2852 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2853 pSMB->TotalDataCount = 0;
2854 pSMB->MaxParameterCount = cpu_to_le16(2);
2855 /* BB find exact max data count below from sess structure BB */
2856 pSMB->MaxDataCount = cpu_to_le16(4000);
2857 pSMB->MaxSetupCount = 0;
2861 pSMB->Reserved2 = 0;
2862 pSMB->ParameterOffset = cpu_to_le16(
2863 offsetof(struct smb_com_transaction2_qpi_req,
2864 InformationLevel) - 4);
2865 pSMB->DataCount = 0;
2866 pSMB->DataOffset = 0;
2867 pSMB->SetupCount = 1;
2868 pSMB->Reserved3 = 0;
2869 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2870 byte_count = params + 1 /* pad */ ;
2871 pSMB->TotalParameterCount = cpu_to_le16(params);
2872 pSMB->ParameterCount = pSMB->TotalParameterCount;
2873 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2874 pSMB->Reserved4 = 0;
2875 pSMB->hdr.smb_buf_length += byte_count;
2876 pSMB->ByteCount = cpu_to_le16(byte_count);
2878 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2879 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2880 cifs_stats_inc(&tcon->num_acl_get);
2882 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2884 /* decode response */
2886 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2887 if (rc || (pSMBr->ByteCount < 2))
2888 /* BB also check enough total bytes returned */
2889 rc = -EIO; /* bad smb */
2891 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2892 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2893 rc = cifs_copy_posix_acl(acl_inf,
2894 (char *)&pSMBr->hdr.Protocol+data_offset,
2895 buflen, acl_type, count);
2898 cifs_buf_release(pSMB);
2905 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2906 const unsigned char *fileName,
2907 const char *local_acl, const int buflen,
2909 const struct nls_table *nls_codepage, int remap)
2911 struct smb_com_transaction2_spi_req *pSMB = NULL;
2912 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2916 int bytes_returned = 0;
2917 __u16 params, byte_count, data_count, param_offset, offset;
2919 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2921 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2925 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2927 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2928 PATH_MAX, nls_codepage, remap);
2929 name_len++; /* trailing null */
2931 } else { /* BB improve the check for buffer overruns BB */
2932 name_len = strnlen(fileName, PATH_MAX);
2933 name_len++; /* trailing null */
2934 strncpy(pSMB->FileName, fileName, name_len);
2936 params = 6 + name_len;
2937 pSMB->MaxParameterCount = cpu_to_le16(2);
2938 /* BB find max SMB size from sess */
2939 pSMB->MaxDataCount = cpu_to_le16(1000);
2940 pSMB->MaxSetupCount = 0;
2944 pSMB->Reserved2 = 0;
2945 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2946 InformationLevel) - 4;
2947 offset = param_offset + params;
2948 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2949 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2951 /* convert to on the wire format for POSIX ACL */
2952 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2954 if (data_count == 0) {
2956 goto setACLerrorExit;
2958 pSMB->DataOffset = cpu_to_le16(offset);
2959 pSMB->SetupCount = 1;
2960 pSMB->Reserved3 = 0;
2961 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2962 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2963 byte_count = 3 /* pad */ + params + data_count;
2964 pSMB->DataCount = cpu_to_le16(data_count);
2965 pSMB->TotalDataCount = pSMB->DataCount;
2966 pSMB->ParameterCount = cpu_to_le16(params);
2967 pSMB->TotalParameterCount = pSMB->ParameterCount;
2968 pSMB->Reserved4 = 0;
2969 pSMB->hdr.smb_buf_length += byte_count;
2970 pSMB->ByteCount = cpu_to_le16(byte_count);
2971 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2972 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2974 cFYI(1, ("Set POSIX ACL returned %d", rc));
2977 cifs_buf_release(pSMB);
2983 /* BB fix tabs in this function FIXME BB */
2985 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2986 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2989 struct smb_t2_qfi_req *pSMB = NULL;
2990 struct smb_t2_qfi_rsp *pSMBr = NULL;
2992 __u16 params, byte_count;
2994 cFYI(1, ("In GetExtAttr"));
2999 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3004 params = 2 /* level */ + 2 /* fid */;
3005 pSMB->t2.TotalDataCount = 0;
3006 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3007 /* BB find exact max data count below from sess structure BB */
3008 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3009 pSMB->t2.MaxSetupCount = 0;
3010 pSMB->t2.Reserved = 0;
3012 pSMB->t2.Timeout = 0;
3013 pSMB->t2.Reserved2 = 0;
3014 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3016 pSMB->t2.DataCount = 0;
3017 pSMB->t2.DataOffset = 0;
3018 pSMB->t2.SetupCount = 1;
3019 pSMB->t2.Reserved3 = 0;
3020 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3021 byte_count = params + 1 /* pad */ ;
3022 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3023 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3024 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3027 pSMB->hdr.smb_buf_length += byte_count;
3028 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3030 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3031 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3033 cFYI(1, ("error %d in GetExtAttr", rc));
3035 /* decode response */
3036 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3037 if (rc || (pSMBr->ByteCount < 2))
3038 /* BB also check enough total bytes returned */
3039 /* If rc should we check for EOPNOSUPP and
3040 disable the srvino flag? or in caller? */
3041 rc = -EIO; /* bad smb */
3043 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3044 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3045 struct file_chattr_info *pfinfo;
3046 /* BB Do we need a cast or hash here ? */
3048 cFYI(1, ("Illegal size ret in GetExtAttr"));
3052 pfinfo = (struct file_chattr_info *)
3053 (data_offset + (char *) &pSMBr->hdr.Protocol);
3054 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3055 *pMask = le64_to_cpu(pfinfo->mask);
3059 cifs_buf_release(pSMB);
3061 goto GetExtAttrRetry;
3065 #endif /* CONFIG_POSIX */
3067 #ifdef CONFIG_CIFS_EXPERIMENTAL
3068 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3070 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3071 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3075 QUERY_SEC_DESC_REQ *pSMB;
3078 cFYI(1, ("GetCifsACL"));
3083 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3084 8 /* parm len */, tcon, (void **) &pSMB);
3088 pSMB->MaxParameterCount = cpu_to_le32(4);
3089 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3090 pSMB->MaxSetupCount = 0;
3091 pSMB->Fid = fid; /* file handle always le */
3092 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3094 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3095 pSMB->hdr.smb_buf_length += 11;
3096 iov[0].iov_base = (char *)pSMB;
3097 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3099 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3101 cifs_stats_inc(&tcon->num_acl_get);
3103 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3104 } else { /* decode response */
3108 struct smb_com_ntransact_rsp *pSMBr;
3111 /* validate_nttransact */
3112 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3113 &pdata, &parm_len, pbuflen);
3116 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3118 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3120 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3121 rc = -EIO; /* bad smb */
3126 /* BB check that data area is minimum length and as big as acl_len */
3128 acl_len = le32_to_cpu(*parm);
3129 if (acl_len != *pbuflen) {
3130 cERROR(1, ("acl length %d does not match %d",
3131 acl_len, *pbuflen));
3132 if (*pbuflen > acl_len)
3136 /* check if buffer is big enough for the acl
3137 header followed by the smallest SID */
3138 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3139 (*pbuflen >= 64 * 1024)) {
3140 cERROR(1, ("bad acl length %d", *pbuflen));
3144 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3145 if (*acl_inf == NULL) {
3149 memcpy(*acl_inf, pdata, *pbuflen);
3153 if (buf_type == CIFS_SMALL_BUFFER)
3154 cifs_small_buf_release(iov[0].iov_base);
3155 else if (buf_type == CIFS_LARGE_BUFFER)
3156 cifs_buf_release(iov[0].iov_base);
3157 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3162 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3163 struct cifs_ntsd *pntsd, __u32 acllen)
3165 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3167 int bytes_returned = 0;
3168 SET_SEC_DESC_REQ *pSMB = NULL;
3169 NTRANSACT_RSP *pSMBr = NULL;
3172 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3177 pSMB->MaxSetupCount = 0;
3181 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3182 data_count = acllen;
3183 data_offset = param_offset + param_count;
3184 byte_count = 3 /* pad */ + param_count;
3186 pSMB->DataCount = cpu_to_le32(data_count);
3187 pSMB->TotalDataCount = pSMB->DataCount;
3188 pSMB->MaxParameterCount = cpu_to_le32(4);
3189 pSMB->MaxDataCount = cpu_to_le32(16384);
3190 pSMB->ParameterCount = cpu_to_le32(param_count);
3191 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3192 pSMB->TotalParameterCount = pSMB->ParameterCount;
3193 pSMB->DataOffset = cpu_to_le32(data_offset);
3194 pSMB->SetupCount = 0;
3195 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3196 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3198 pSMB->Fid = fid; /* file handle always le */
3199 pSMB->Reserved2 = 0;
3200 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3202 if (pntsd && acllen) {
3203 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3206 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3209 pSMB->hdr.smb_buf_length += byte_count;
3211 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3212 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3214 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3216 cFYI(1, ("Set CIFS ACL returned %d", rc));
3217 cifs_buf_release(pSMB);
3220 goto setCifsAclRetry;
3225 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3227 /* Legacy Query Path Information call for lookup to old servers such
3229 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3230 const unsigned char *searchName,
3231 FILE_ALL_INFO *pFinfo,
3232 const struct nls_table *nls_codepage, int remap)
3234 QUERY_INFORMATION_REQ *pSMB;
3235 QUERY_INFORMATION_RSP *pSMBr;
3240 cFYI(1, ("In SMBQPath path %s", searchName));
3242 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3247 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3249 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3250 PATH_MAX, nls_codepage, remap);
3251 name_len++; /* trailing null */
3254 name_len = strnlen(searchName, PATH_MAX);
3255 name_len++; /* trailing null */
3256 strncpy(pSMB->FileName, searchName, name_len);
3258 pSMB->BufferFormat = 0x04;
3259 name_len++; /* account for buffer type byte */
3260 pSMB->hdr.smb_buf_length += (__u16) name_len;
3261 pSMB->ByteCount = cpu_to_le16(name_len);
3263 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3264 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3266 cFYI(1, ("Send error in QueryInfo = %d", rc));
3267 } else if (pFinfo) {
3269 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3271 /* decode response */
3272 /* BB FIXME - add time zone adjustment BB */
3273 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3276 /* decode time fields */
3277 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3278 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3279 pFinfo->LastAccessTime = 0;
3280 pFinfo->AllocationSize =
3281 cpu_to_le64(le32_to_cpu(pSMBr->size));
3282 pFinfo->EndOfFile = pFinfo->AllocationSize;
3283 pFinfo->Attributes =
3284 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3286 rc = -EIO; /* bad buffer passed in */
3288 cifs_buf_release(pSMB);
3300 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3301 const unsigned char *searchName,
3302 FILE_ALL_INFO *pFindData,
3303 int legacy /* old style infolevel */,
3304 const struct nls_table *nls_codepage, int remap)
3306 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3307 TRANSACTION2_QPI_REQ *pSMB = NULL;
3308 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3312 __u16 params, byte_count;
3314 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3316 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3321 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3323 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3324 PATH_MAX, nls_codepage, remap);
3325 name_len++; /* trailing null */
3327 } else { /* BB improve the check for buffer overruns BB */
3328 name_len = strnlen(searchName, PATH_MAX);
3329 name_len++; /* trailing null */
3330 strncpy(pSMB->FileName, searchName, name_len);
3333 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3334 pSMB->TotalDataCount = 0;
3335 pSMB->MaxParameterCount = cpu_to_le16(2);
3336 /* BB find exact max SMB PDU from sess structure BB */
3337 pSMB->MaxDataCount = cpu_to_le16(4000);
3338 pSMB->MaxSetupCount = 0;
3342 pSMB->Reserved2 = 0;
3343 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3344 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3345 pSMB->DataCount = 0;
3346 pSMB->DataOffset = 0;
3347 pSMB->SetupCount = 1;
3348 pSMB->Reserved3 = 0;
3349 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3350 byte_count = params + 1 /* pad */ ;
3351 pSMB->TotalParameterCount = cpu_to_le16(params);
3352 pSMB->ParameterCount = pSMB->TotalParameterCount;
3354 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3356 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3357 pSMB->Reserved4 = 0;
3358 pSMB->hdr.smb_buf_length += byte_count;
3359 pSMB->ByteCount = cpu_to_le16(byte_count);
3361 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3362 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3364 cFYI(1, ("Send error in QPathInfo = %d", rc));
3365 } else { /* decode response */
3366 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3368 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3370 else if (!legacy && (pSMBr->ByteCount < 40))
3371 rc = -EIO; /* bad smb */
3372 else if (legacy && (pSMBr->ByteCount < 24))
3373 rc = -EIO; /* 24 or 26 expected but we do not read
3375 else if (pFindData) {
3377 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3379 /* On legacy responses we do not read the last field,
3380 EAsize, fortunately since it varies by subdialect and
3381 also note it differs on Set vs. Get, ie two bytes or 4
3382 bytes depending but we don't care here */
3384 size = sizeof(FILE_INFO_STANDARD);
3386 size = sizeof(FILE_ALL_INFO);
3387 memcpy((char *) pFindData,
3388 (char *) &pSMBr->hdr.Protocol +
3393 cifs_buf_release(pSMB);
3395 goto QPathInfoRetry;
3401 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3402 const unsigned char *searchName,
3403 FILE_UNIX_BASIC_INFO *pFindData,
3404 const struct nls_table *nls_codepage, int remap)
3406 /* SMB_QUERY_FILE_UNIX_BASIC */
3407 TRANSACTION2_QPI_REQ *pSMB = NULL;
3408 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3410 int bytes_returned = 0;
3412 __u16 params, byte_count;
3414 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3416 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3421 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3423 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3424 PATH_MAX, nls_codepage, remap);
3425 name_len++; /* trailing null */
3427 } else { /* BB improve the check for buffer overruns BB */
3428 name_len = strnlen(searchName, PATH_MAX);
3429 name_len++; /* trailing null */
3430 strncpy(pSMB->FileName, searchName, name_len);
3433 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3434 pSMB->TotalDataCount = 0;
3435 pSMB->MaxParameterCount = cpu_to_le16(2);
3436 /* BB find exact max SMB PDU from sess structure BB */
3437 pSMB->MaxDataCount = cpu_to_le16(4000);
3438 pSMB->MaxSetupCount = 0;
3442 pSMB->Reserved2 = 0;
3443 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3444 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3445 pSMB->DataCount = 0;
3446 pSMB->DataOffset = 0;
3447 pSMB->SetupCount = 1;
3448 pSMB->Reserved3 = 0;
3449 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3450 byte_count = params + 1 /* pad */ ;
3451 pSMB->TotalParameterCount = cpu_to_le16(params);
3452 pSMB->ParameterCount = pSMB->TotalParameterCount;
3453 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3454 pSMB->Reserved4 = 0;
3455 pSMB->hdr.smb_buf_length += byte_count;
3456 pSMB->ByteCount = cpu_to_le16(byte_count);
3458 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3459 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3461 cFYI(1, ("Send error in QPathInfo = %d", rc));
3462 } else { /* decode response */
3463 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3465 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3466 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3467 "Unix Extensions can be disabled on mount "
3468 "by specifying the nosfu mount option."));
3469 rc = -EIO; /* bad smb */
3471 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3472 memcpy((char *) pFindData,
3473 (char *) &pSMBr->hdr.Protocol +
3475 sizeof(FILE_UNIX_BASIC_INFO));
3478 cifs_buf_release(pSMB);
3480 goto UnixQPathInfoRetry;
3485 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3487 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3488 const char *searchName,
3489 const struct nls_table *nls_codepage,
3491 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3493 /* level 257 SMB_ */
3494 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3495 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3496 T2_FFIRST_RSP_PARMS *parms;
3498 int bytes_returned = 0;
3500 __u16 params, byte_count;
3502 cFYI(1, ("In FindFirst for %s", searchName));
3505 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3510 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3512 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3513 PATH_MAX, nls_codepage, remap);
3514 /* We can not add the asterik earlier in case
3515 it got remapped to 0xF03A as if it were part of the
3516 directory name instead of a wildcard */
3518 pSMB->FileName[name_len] = dirsep;
3519 pSMB->FileName[name_len+1] = 0;
3520 pSMB->FileName[name_len+2] = '*';
3521 pSMB->FileName[name_len+3] = 0;
3522 name_len += 4; /* now the trailing null */
3523 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3524 pSMB->FileName[name_len+1] = 0;
3526 } else { /* BB add check for overrun of SMB buf BB */
3527 name_len = strnlen(searchName, PATH_MAX);
3528 /* BB fix here and in unicode clause above ie
3529 if (name_len > buffersize-header)
3530 free buffer exit; BB */
3531 strncpy(pSMB->FileName, searchName, name_len);
3532 pSMB->FileName[name_len] = dirsep;
3533 pSMB->FileName[name_len+1] = '*';
3534 pSMB->FileName[name_len+2] = 0;
3538 params = 12 + name_len /* includes null */ ;
3539 pSMB->TotalDataCount = 0; /* no EAs */
3540 pSMB->MaxParameterCount = cpu_to_le16(10);
3541 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3542 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3543 pSMB->MaxSetupCount = 0;
3547 pSMB->Reserved2 = 0;
3548 byte_count = params + 1 /* pad */ ;
3549 pSMB->TotalParameterCount = cpu_to_le16(params);
3550 pSMB->ParameterCount = pSMB->TotalParameterCount;
3551 pSMB->ParameterOffset = cpu_to_le16(
3552 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3554 pSMB->DataCount = 0;
3555 pSMB->DataOffset = 0;
3556 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3557 pSMB->Reserved3 = 0;
3558 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3559 pSMB->SearchAttributes =
3560 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3562 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3563 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3564 CIFS_SEARCH_RETURN_RESUME);
3565 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3567 /* BB what should we set StorageType to? Does it matter? BB */
3568 pSMB->SearchStorageType = 0;
3569 pSMB->hdr.smb_buf_length += byte_count;
3570 pSMB->ByteCount = cpu_to_le16(byte_count);
3572 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3573 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3574 cifs_stats_inc(&tcon->num_ffirst);
3576 if (rc) {/* BB add logic to retry regular search if Unix search
3577 rejected unexpectedly by server */
3578 /* BB Add code to handle unsupported level rc */
3579 cFYI(1, ("Error in FindFirst = %d", rc));
3581 cifs_buf_release(pSMB);
3583 /* BB eventually could optimize out free and realloc of buf */
3586 goto findFirstRetry;
3587 } else { /* decode response */
3588 /* BB remember to free buffer if error BB */
3589 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3593 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3594 psrch_inf->unicode = true;
3596 psrch_inf->unicode = false;
3598 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3599 psrch_inf->smallBuf = 0;
3600 psrch_inf->srch_entries_start =
3601 (char *) &pSMBr->hdr.Protocol +
3602 le16_to_cpu(pSMBr->t2.DataOffset);
3603 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3604 le16_to_cpu(pSMBr->t2.ParameterOffset));
3606 if (parms->EndofSearch)
3607 psrch_inf->endOfSearch = true;
3609 psrch_inf->endOfSearch = false;
3611 psrch_inf->entries_in_buffer =
3612 le16_to_cpu(parms->SearchCount);
3613 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3614 psrch_inf->entries_in_buffer;
3615 lnoff = le16_to_cpu(parms->LastNameOffset);
3616 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3618 cERROR(1, ("ignoring corrupt resume name"));
3619 psrch_inf->last_entry = NULL;
3623 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3626 *pnetfid = parms->SearchHandle;
3628 cifs_buf_release(pSMB);
3635 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3636 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3638 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3639 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3640 T2_FNEXT_RSP_PARMS *parms;
3641 char *response_data;
3643 int bytes_returned, name_len;
3644 __u16 params, byte_count;
3646 cFYI(1, ("In FindNext"));
3648 if (psrch_inf->endOfSearch)
3651 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3656 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3658 pSMB->TotalDataCount = 0; /* no EAs */
3659 pSMB->MaxParameterCount = cpu_to_le16(8);
3660 pSMB->MaxDataCount =
3661 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3663 pSMB->MaxSetupCount = 0;
3667 pSMB->Reserved2 = 0;
3668 pSMB->ParameterOffset = cpu_to_le16(
3669 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3670 pSMB->DataCount = 0;
3671 pSMB->DataOffset = 0;
3672 pSMB->SetupCount = 1;
3673 pSMB->Reserved3 = 0;
3674 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3675 pSMB->SearchHandle = searchHandle; /* always kept as le */
3677 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3678 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3679 pSMB->ResumeKey = psrch_inf->resume_key;
3681 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3683 name_len = psrch_inf->resume_name_len;
3685 if (name_len < PATH_MAX) {
3686 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3687 byte_count += name_len;
3688 /* 14 byte parm len above enough for 2 byte null terminator */
3689 pSMB->ResumeFileName[name_len] = 0;
3690 pSMB->ResumeFileName[name_len+1] = 0;
3693 goto FNext2_err_exit;
3695 byte_count = params + 1 /* pad */ ;
3696 pSMB->TotalParameterCount = cpu_to_le16(params);
3697 pSMB->ParameterCount = pSMB->TotalParameterCount;
3698 pSMB->hdr.smb_buf_length += byte_count;
3699 pSMB->ByteCount = cpu_to_le16(byte_count);
3701 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3702 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3703 cifs_stats_inc(&tcon->num_fnext);
3706 psrch_inf->endOfSearch = true;
3707 cifs_buf_release(pSMB);
3708 rc = 0; /* search probably was closed at end of search*/
3710 cFYI(1, ("FindNext returned = %d", rc));
3711 } else { /* decode response */
3712 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3717 /* BB fixme add lock for file (srch_info) struct here */
3718 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3719 psrch_inf->unicode = true;
3721 psrch_inf->unicode = false;
3722 response_data = (char *) &pSMBr->hdr.Protocol +
3723 le16_to_cpu(pSMBr->t2.ParameterOffset);
3724 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3725 response_data = (char *)&pSMBr->hdr.Protocol +
3726 le16_to_cpu(pSMBr->t2.DataOffset);
3727 if (psrch_inf->smallBuf)
3728 cifs_small_buf_release(
3729 psrch_inf->ntwrk_buf_start);
3731 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3732 psrch_inf->srch_entries_start = response_data;
3733 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3734 psrch_inf->smallBuf = 0;
3735 if (parms->EndofSearch)
3736 psrch_inf->endOfSearch = true;
3738 psrch_inf->endOfSearch = false;
3739 psrch_inf->entries_in_buffer =
3740 le16_to_cpu(parms->SearchCount);
3741 psrch_inf->index_of_last_entry +=
3742 psrch_inf->entries_in_buffer;
3743 lnoff = le16_to_cpu(parms->LastNameOffset);
3744 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3746 cERROR(1, ("ignoring corrupt resume name"));
3747 psrch_inf->last_entry = NULL;
3750 psrch_inf->last_entry =
3751 psrch_inf->srch_entries_start + lnoff;
3753 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3754 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3756 /* BB fixme add unlock here */
3761 /* BB On error, should we leave previous search buf (and count and
3762 last entry fields) intact or free the previous one? */
3764 /* Note: On -EAGAIN error only caller can retry on handle based calls
3765 since file handle passed in no longer valid */
3768 cifs_buf_release(pSMB);
3773 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3774 const __u16 searchHandle)
3777 FINDCLOSE_REQ *pSMB = NULL;
3779 cFYI(1, ("In CIFSSMBFindClose"));
3780 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3782 /* no sense returning error if session restarted
3783 as file handle has been closed */
3789 pSMB->FileID = searchHandle;
3790 pSMB->ByteCount = 0;
3791 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3793 cERROR(1, ("Send error in FindClose = %d", rc));
3795 cifs_stats_inc(&tcon->num_fclose);
3797 /* Since session is dead, search handle closed on server already */
3805 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3806 const unsigned char *searchName,
3807 __u64 *inode_number,
3808 const struct nls_table *nls_codepage, int remap)
3811 TRANSACTION2_QPI_REQ *pSMB = NULL;
3812 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3813 int name_len, bytes_returned;
3814 __u16 params, byte_count;
3816 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3820 GetInodeNumberRetry:
3821 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3826 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3828 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3829 PATH_MAX, nls_codepage, remap);
3830 name_len++; /* trailing null */
3832 } else { /* BB improve the check for buffer overruns BB */
3833 name_len = strnlen(searchName, PATH_MAX);
3834 name_len++; /* trailing null */
3835 strncpy(pSMB->FileName, searchName, name_len);
3838 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3839 pSMB->TotalDataCount = 0;
3840 pSMB->MaxParameterCount = cpu_to_le16(2);
3841 /* BB find exact max data count below from sess structure BB */
3842 pSMB->MaxDataCount = cpu_to_le16(4000);
3843 pSMB->MaxSetupCount = 0;
3847 pSMB->Reserved2 = 0;
3848 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3849 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3850 pSMB->DataCount = 0;
3851 pSMB->DataOffset = 0;
3852 pSMB->SetupCount = 1;
3853 pSMB->Reserved3 = 0;
3854 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3855 byte_count = params + 1 /* pad */ ;
3856 pSMB->TotalParameterCount = cpu_to_le16(params);
3857 pSMB->ParameterCount = pSMB->TotalParameterCount;
3858 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3859 pSMB->Reserved4 = 0;
3860 pSMB->hdr.smb_buf_length += byte_count;
3861 pSMB->ByteCount = cpu_to_le16(byte_count);
3863 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3864 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3866 cFYI(1, ("error %d in QueryInternalInfo", rc));
3868 /* decode response */
3869 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3870 if (rc || (pSMBr->ByteCount < 2))
3871 /* BB also check enough total bytes returned */
3872 /* If rc should we check for EOPNOSUPP and
3873 disable the srvino flag? or in caller? */
3874 rc = -EIO; /* bad smb */
3876 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3877 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3878 struct file_internal_info *pfinfo;
3879 /* BB Do we need a cast or hash here ? */
3881 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3883 goto GetInodeNumOut;
3885 pfinfo = (struct file_internal_info *)
3886 (data_offset + (char *) &pSMBr->hdr.Protocol);
3887 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3891 cifs_buf_release(pSMB);
3893 goto GetInodeNumberRetry;
3897 /* parses DFS refferal V3 structure
3898 * caller is responsible for freeing target_nodes
3901 * on failure - errno
3904 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3905 unsigned int *num_of_nodes,
3906 struct dfs_info3_param **target_nodes,
3907 const struct nls_table *nls_codepage, int remap,
3908 const char *searchName)
3913 struct dfs_referral_level_3 *ref;
3915 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3919 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3921 if (*num_of_nodes < 1) {
3922 cERROR(1, ("num_referrals: must be at least > 0,"
3923 "but we get num_referrals = %d\n", *num_of_nodes));
3925 goto parse_DFS_referrals_exit;
3928 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3929 if (ref->VersionNumber != cpu_to_le16(3)) {
3930 cERROR(1, ("Referrals of V%d version are not supported,"
3931 "should be V3", le16_to_cpu(ref->VersionNumber)));
3933 goto parse_DFS_referrals_exit;
3936 /* get the upper boundary of the resp buffer */
3937 data_end = (char *)(&(pSMBr->PathConsumed)) +
3938 le16_to_cpu(pSMBr->t2.DataCount);
3940 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3942 le32_to_cpu(pSMBr->DFSFlags)));
3944 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3945 *num_of_nodes, GFP_KERNEL);
3946 if (*target_nodes == NULL) {
3947 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3949 goto parse_DFS_referrals_exit;
3952 /* collect neccessary data from referrals */
3953 for (i = 0; i < *num_of_nodes; i++) {
3956 struct dfs_info3_param *node = (*target_nodes)+i;
3958 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3960 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3962 cifsConvertToUCS((__le16 *) tmp, searchName,
3963 PATH_MAX, nls_codepage, remap);
3964 node->path_consumed = cifs_ucs2_bytes(tmp,
3965 le16_to_cpu(pSMBr->PathConsumed),
3969 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3971 node->server_type = le16_to_cpu(ref->ServerType);
3972 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3975 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3976 max_len = data_end - temp;
3977 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3978 is_unicode, nls_codepage);
3979 if (IS_ERR(node->path_name)) {
3980 rc = PTR_ERR(node->path_name);
3981 node->path_name = NULL;
3982 goto parse_DFS_referrals_exit;
3985 /* copy link target UNC */
3986 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3987 max_len = data_end - temp;
3988 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3989 is_unicode, nls_codepage);
3990 if (IS_ERR(node->node_name)) {
3991 rc = PTR_ERR(node->node_name);
3992 node->node_name = NULL;
3993 goto parse_DFS_referrals_exit;
3997 parse_DFS_referrals_exit:
3999 free_dfs_info_array(*target_nodes, *num_of_nodes);
4000 *target_nodes = NULL;
4007 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4008 const unsigned char *searchName,
4009 struct dfs_info3_param **target_nodes,
4010 unsigned int *num_of_nodes,
4011 const struct nls_table *nls_codepage, int remap)
4013 /* TRANS2_GET_DFS_REFERRAL */
4014 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4015 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4019 __u16 params, byte_count;
4021 *target_nodes = NULL;
4023 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4027 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4032 /* server pointer checked in called function,
4033 but should never be null here anyway */
4034 pSMB->hdr.Mid = GetNextMid(ses->server);
4035 pSMB->hdr.Tid = ses->ipc_tid;
4036 pSMB->hdr.Uid = ses->Suid;
4037 if (ses->capabilities & CAP_STATUS32)
4038 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4039 if (ses->capabilities & CAP_DFS)
4040 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4042 if (ses->capabilities & CAP_UNICODE) {
4043 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4045 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4046 searchName, PATH_MAX, nls_codepage, remap);
4047 name_len++; /* trailing null */
4049 } else { /* BB improve the check for buffer overruns BB */
4050 name_len = strnlen(searchName, PATH_MAX);
4051 name_len++; /* trailing null */
4052 strncpy(pSMB->RequestFileName, searchName, name_len);
4056 if (ses->server->secMode &
4057 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4058 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4061 pSMB->hdr.Uid = ses->Suid;
4063 params = 2 /* level */ + name_len /*includes null */ ;
4064 pSMB->TotalDataCount = 0;
4065 pSMB->DataCount = 0;
4066 pSMB->DataOffset = 0;
4067 pSMB->MaxParameterCount = 0;
4068 /* BB find exact max SMB PDU from sess structure BB */
4069 pSMB->MaxDataCount = cpu_to_le16(4000);
4070 pSMB->MaxSetupCount = 0;
4074 pSMB->Reserved2 = 0;
4075 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4076 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4077 pSMB->SetupCount = 1;
4078 pSMB->Reserved3 = 0;
4079 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4080 byte_count = params + 3 /* pad */ ;
4081 pSMB->ParameterCount = cpu_to_le16(params);
4082 pSMB->TotalParameterCount = pSMB->ParameterCount;
4083 pSMB->MaxReferralLevel = cpu_to_le16(3);
4084 pSMB->hdr.smb_buf_length += byte_count;
4085 pSMB->ByteCount = cpu_to_le16(byte_count);
4087 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4088 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4090 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4093 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4095 /* BB Also check if enough total bytes returned? */
4096 if (rc || (pSMBr->ByteCount < 17)) {
4097 rc = -EIO; /* bad smb */
4101 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4103 le16_to_cpu(pSMBr->t2.DataOffset)));
4105 /* parse returned result into more usable form */
4106 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4107 target_nodes, nls_codepage, remap,
4111 cifs_buf_release(pSMB);
4119 /* Query File System Info such as free space to old servers such as Win 9x */
4121 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4123 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4124 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4125 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4126 FILE_SYSTEM_ALLOC_INFO *response_data;
4128 int bytes_returned = 0;
4129 __u16 params, byte_count;
4131 cFYI(1, ("OldQFSInfo"));
4133 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4138 params = 2; /* level */
4139 pSMB->TotalDataCount = 0;
4140 pSMB->MaxParameterCount = cpu_to_le16(2);
4141 pSMB->MaxDataCount = cpu_to_le16(1000);
4142 pSMB->MaxSetupCount = 0;
4146 pSMB->Reserved2 = 0;
4147 byte_count = params + 1 /* pad */ ;
4148 pSMB->TotalParameterCount = cpu_to_le16(params);
4149 pSMB->ParameterCount = pSMB->TotalParameterCount;
4150 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4151 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4152 pSMB->DataCount = 0;
4153 pSMB->DataOffset = 0;
4154 pSMB->SetupCount = 1;
4155 pSMB->Reserved3 = 0;
4156 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4157 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4158 pSMB->hdr.smb_buf_length += byte_count;
4159 pSMB->ByteCount = cpu_to_le16(byte_count);
4161 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4162 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4164 cFYI(1, ("Send error in QFSInfo = %d", rc));
4165 } else { /* decode response */
4166 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4168 if (rc || (pSMBr->ByteCount < 18))
4169 rc = -EIO; /* bad smb */
4171 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4172 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4173 pSMBr->ByteCount, data_offset));
4175 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4176 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4178 le16_to_cpu(response_data->BytesPerSector) *
4179 le32_to_cpu(response_data->
4180 SectorsPerAllocationUnit);
4182 le32_to_cpu(response_data->TotalAllocationUnits);
4183 FSData->f_bfree = FSData->f_bavail =
4184 le32_to_cpu(response_data->FreeAllocationUnits);
4186 ("Blocks: %lld Free: %lld Block size %ld",
4187 (unsigned long long)FSData->f_blocks,
4188 (unsigned long long)FSData->f_bfree,
4192 cifs_buf_release(pSMB);
4195 goto oldQFSInfoRetry;
4201 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4203 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4204 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4205 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4206 FILE_SYSTEM_INFO *response_data;
4208 int bytes_returned = 0;
4209 __u16 params, byte_count;
4211 cFYI(1, ("In QFSInfo"));
4213 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4218 params = 2; /* level */
4219 pSMB->TotalDataCount = 0;
4220 pSMB->MaxParameterCount = cpu_to_le16(2);
4221 pSMB->MaxDataCount = cpu_to_le16(1000);
4222 pSMB->MaxSetupCount = 0;
4226 pSMB->Reserved2 = 0;
4227 byte_count = params + 1 /* pad */ ;
4228 pSMB->TotalParameterCount = cpu_to_le16(params);
4229 pSMB->ParameterCount = pSMB->TotalParameterCount;
4230 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4231 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4232 pSMB->DataCount = 0;
4233 pSMB->DataOffset = 0;
4234 pSMB->SetupCount = 1;
4235 pSMB->Reserved3 = 0;
4236 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4237 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4238 pSMB->hdr.smb_buf_length += byte_count;
4239 pSMB->ByteCount = cpu_to_le16(byte_count);
4241 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4242 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4244 cFYI(1, ("Send error in QFSInfo = %d", rc));
4245 } else { /* decode response */
4246 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4248 if (rc || (pSMBr->ByteCount < 24))
4249 rc = -EIO; /* bad smb */
4251 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4255 *) (((char *) &pSMBr->hdr.Protocol) +
4258 le32_to_cpu(response_data->BytesPerSector) *
4259 le32_to_cpu(response_data->
4260 SectorsPerAllocationUnit);
4262 le64_to_cpu(response_data->TotalAllocationUnits);
4263 FSData->f_bfree = FSData->f_bavail =
4264 le64_to_cpu(response_data->FreeAllocationUnits);
4266 ("Blocks: %lld Free: %lld Block size %ld",
4267 (unsigned long long)FSData->f_blocks,
4268 (unsigned long long)FSData->f_bfree,
4272 cifs_buf_release(pSMB);
4281 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4283 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4284 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4285 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4286 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4288 int bytes_returned = 0;
4289 __u16 params, byte_count;
4291 cFYI(1, ("In QFSAttributeInfo"));
4293 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4298 params = 2; /* level */
4299 pSMB->TotalDataCount = 0;
4300 pSMB->MaxParameterCount = cpu_to_le16(2);
4301 /* BB find exact max SMB PDU from sess structure BB */
4302 pSMB->MaxDataCount = cpu_to_le16(1000);
4303 pSMB->MaxSetupCount = 0;
4307 pSMB->Reserved2 = 0;
4308 byte_count = params + 1 /* pad */ ;
4309 pSMB->TotalParameterCount = cpu_to_le16(params);
4310 pSMB->ParameterCount = pSMB->TotalParameterCount;
4311 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4312 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4313 pSMB->DataCount = 0;
4314 pSMB->DataOffset = 0;
4315 pSMB->SetupCount = 1;
4316 pSMB->Reserved3 = 0;
4317 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4318 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4319 pSMB->hdr.smb_buf_length += byte_count;
4320 pSMB->ByteCount = cpu_to_le16(byte_count);
4322 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4323 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4325 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4326 } else { /* decode response */
4327 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4329 if (rc || (pSMBr->ByteCount < 13)) {
4330 /* BB also check if enough bytes returned */
4331 rc = -EIO; /* bad smb */
4333 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4335 (FILE_SYSTEM_ATTRIBUTE_INFO
4336 *) (((char *) &pSMBr->hdr.Protocol) +
4338 memcpy(&tcon->fsAttrInfo, response_data,
4339 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4342 cifs_buf_release(pSMB);
4345 goto QFSAttributeRetry;
4351 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4353 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4354 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4355 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4356 FILE_SYSTEM_DEVICE_INFO *response_data;
4358 int bytes_returned = 0;
4359 __u16 params, byte_count;
4361 cFYI(1, ("In QFSDeviceInfo"));
4363 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4368 params = 2; /* level */
4369 pSMB->TotalDataCount = 0;
4370 pSMB->MaxParameterCount = cpu_to_le16(2);
4371 /* BB find exact max SMB PDU from sess structure BB */
4372 pSMB->MaxDataCount = cpu_to_le16(1000);
4373 pSMB->MaxSetupCount = 0;
4377 pSMB->Reserved2 = 0;
4378 byte_count = params + 1 /* pad */ ;
4379 pSMB->TotalParameterCount = cpu_to_le16(params);
4380 pSMB->ParameterCount = pSMB->TotalParameterCount;
4381 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4382 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4384 pSMB->DataCount = 0;
4385 pSMB->DataOffset = 0;
4386 pSMB->SetupCount = 1;
4387 pSMB->Reserved3 = 0;
4388 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4389 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4390 pSMB->hdr.smb_buf_length += byte_count;
4391 pSMB->ByteCount = cpu_to_le16(byte_count);
4393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4396 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4397 } else { /* decode response */
4398 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4400 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4401 rc = -EIO; /* bad smb */
4403 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4405 (FILE_SYSTEM_DEVICE_INFO *)
4406 (((char *) &pSMBr->hdr.Protocol) +
4408 memcpy(&tcon->fsDevInfo, response_data,
4409 sizeof(FILE_SYSTEM_DEVICE_INFO));
4412 cifs_buf_release(pSMB);
4415 goto QFSDeviceRetry;
4421 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4423 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4424 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4425 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4426 FILE_SYSTEM_UNIX_INFO *response_data;
4428 int bytes_returned = 0;
4429 __u16 params, byte_count;
4431 cFYI(1, ("In QFSUnixInfo"));
4433 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4438 params = 2; /* level */
4439 pSMB->TotalDataCount = 0;
4440 pSMB->DataCount = 0;
4441 pSMB->DataOffset = 0;
4442 pSMB->MaxParameterCount = cpu_to_le16(2);
4443 /* BB find exact max SMB PDU from sess structure BB */
4444 pSMB->MaxDataCount = cpu_to_le16(100);
4445 pSMB->MaxSetupCount = 0;
4449 pSMB->Reserved2 = 0;
4450 byte_count = params + 1 /* pad */ ;
4451 pSMB->ParameterCount = cpu_to_le16(params);
4452 pSMB->TotalParameterCount = pSMB->ParameterCount;
4453 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4454 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4455 pSMB->SetupCount = 1;
4456 pSMB->Reserved3 = 0;
4457 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4458 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4459 pSMB->hdr.smb_buf_length += byte_count;
4460 pSMB->ByteCount = cpu_to_le16(byte_count);
4462 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4463 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4465 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4466 } else { /* decode response */
4467 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4469 if (rc || (pSMBr->ByteCount < 13)) {
4470 rc = -EIO; /* bad smb */
4472 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4474 (FILE_SYSTEM_UNIX_INFO
4475 *) (((char *) &pSMBr->hdr.Protocol) +
4477 memcpy(&tcon->fsUnixInfo, response_data,
4478 sizeof(FILE_SYSTEM_UNIX_INFO));
4481 cifs_buf_release(pSMB);
4491 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4493 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4494 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4495 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4497 int bytes_returned = 0;
4498 __u16 params, param_offset, offset, byte_count;
4500 cFYI(1, ("In SETFSUnixInfo"));
4502 /* BB switch to small buf init to save memory */
4503 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4508 params = 4; /* 2 bytes zero followed by info level. */
4509 pSMB->MaxSetupCount = 0;
4513 pSMB->Reserved2 = 0;
4514 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4516 offset = param_offset + params;
4518 pSMB->MaxParameterCount = cpu_to_le16(4);
4519 /* BB find exact max SMB PDU from sess structure BB */
4520 pSMB->MaxDataCount = cpu_to_le16(100);
4521 pSMB->SetupCount = 1;
4522 pSMB->Reserved3 = 0;
4523 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4524 byte_count = 1 /* pad */ + params + 12;
4526 pSMB->DataCount = cpu_to_le16(12);
4527 pSMB->ParameterCount = cpu_to_le16(params);
4528 pSMB->TotalDataCount = pSMB->DataCount;
4529 pSMB->TotalParameterCount = pSMB->ParameterCount;
4530 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4531 pSMB->DataOffset = cpu_to_le16(offset);
4535 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4538 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4539 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4540 pSMB->ClientUnixCap = cpu_to_le64(cap);
4542 pSMB->hdr.smb_buf_length += byte_count;
4543 pSMB->ByteCount = cpu_to_le16(byte_count);
4545 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4546 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4548 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4549 } else { /* decode response */
4550 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4552 rc = -EIO; /* bad smb */
4554 cifs_buf_release(pSMB);
4557 goto SETFSUnixRetry;
4565 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4566 struct kstatfs *FSData)
4568 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4569 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4570 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4571 FILE_SYSTEM_POSIX_INFO *response_data;
4573 int bytes_returned = 0;
4574 __u16 params, byte_count;
4576 cFYI(1, ("In QFSPosixInfo"));
4578 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4583 params = 2; /* level */
4584 pSMB->TotalDataCount = 0;
4585 pSMB->DataCount = 0;
4586 pSMB->DataOffset = 0;
4587 pSMB->MaxParameterCount = cpu_to_le16(2);
4588 /* BB find exact max SMB PDU from sess structure BB */
4589 pSMB->MaxDataCount = cpu_to_le16(100);
4590 pSMB->MaxSetupCount = 0;
4594 pSMB->Reserved2 = 0;
4595 byte_count = params + 1 /* pad */ ;
4596 pSMB->ParameterCount = cpu_to_le16(params);
4597 pSMB->TotalParameterCount = pSMB->ParameterCount;
4598 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4599 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4600 pSMB->SetupCount = 1;
4601 pSMB->Reserved3 = 0;
4602 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4603 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4604 pSMB->hdr.smb_buf_length += byte_count;
4605 pSMB->ByteCount = cpu_to_le16(byte_count);
4607 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4608 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4610 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4611 } else { /* decode response */
4612 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4614 if (rc || (pSMBr->ByteCount < 13)) {
4615 rc = -EIO; /* bad smb */
4617 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4619 (FILE_SYSTEM_POSIX_INFO
4620 *) (((char *) &pSMBr->hdr.Protocol) +
4623 le32_to_cpu(response_data->BlockSize);
4625 le64_to_cpu(response_data->TotalBlocks);
4627 le64_to_cpu(response_data->BlocksAvail);
4628 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4629 FSData->f_bavail = FSData->f_bfree;
4632 le64_to_cpu(response_data->UserBlocksAvail);
4634 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4636 le64_to_cpu(response_data->TotalFileNodes);
4637 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4639 le64_to_cpu(response_data->FreeFileNodes);
4642 cifs_buf_release(pSMB);
4651 /* We can not use write of zero bytes trick to
4652 set file size due to need for large file support. Also note that
4653 this SetPathInfo is preferred to SetFileInfo based method in next
4654 routine which is only needed to work around a sharing violation bug
4655 in Samba which this routine can run into */
4658 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4659 __u64 size, bool SetAllocation,
4660 const struct nls_table *nls_codepage, int remap)
4662 struct smb_com_transaction2_spi_req *pSMB = NULL;
4663 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4664 struct file_end_of_file_info *parm_data;
4667 int bytes_returned = 0;
4668 __u16 params, byte_count, data_count, param_offset, offset;
4670 cFYI(1, ("In SetEOF"));
4672 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4677 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4679 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4680 PATH_MAX, nls_codepage, remap);
4681 name_len++; /* trailing null */
4683 } else { /* BB improve the check for buffer overruns BB */
4684 name_len = strnlen(fileName, PATH_MAX);
4685 name_len++; /* trailing null */
4686 strncpy(pSMB->FileName, fileName, name_len);
4688 params = 6 + name_len;
4689 data_count = sizeof(struct file_end_of_file_info);
4690 pSMB->MaxParameterCount = cpu_to_le16(2);
4691 pSMB->MaxDataCount = cpu_to_le16(4100);
4692 pSMB->MaxSetupCount = 0;
4696 pSMB->Reserved2 = 0;
4697 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4698 InformationLevel) - 4;
4699 offset = param_offset + params;
4700 if (SetAllocation) {
4701 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4702 pSMB->InformationLevel =
4703 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4705 pSMB->InformationLevel =
4706 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4707 } else /* Set File Size */ {
4708 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4709 pSMB->InformationLevel =
4710 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4712 pSMB->InformationLevel =
4713 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4717 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4719 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4720 pSMB->DataOffset = cpu_to_le16(offset);
4721 pSMB->SetupCount = 1;
4722 pSMB->Reserved3 = 0;
4723 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4724 byte_count = 3 /* pad */ + params + data_count;
4725 pSMB->DataCount = cpu_to_le16(data_count);
4726 pSMB->TotalDataCount = pSMB->DataCount;
4727 pSMB->ParameterCount = cpu_to_le16(params);
4728 pSMB->TotalParameterCount = pSMB->ParameterCount;
4729 pSMB->Reserved4 = 0;
4730 pSMB->hdr.smb_buf_length += byte_count;
4731 parm_data->FileSize = cpu_to_le64(size);
4732 pSMB->ByteCount = cpu_to_le16(byte_count);
4733 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4734 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4736 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4738 cifs_buf_release(pSMB);
4747 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4748 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4750 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4752 struct file_end_of_file_info *parm_data;
4754 __u16 params, param_offset, offset, byte_count, count;
4756 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4758 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4763 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4764 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4767 pSMB->MaxSetupCount = 0;
4771 pSMB->Reserved2 = 0;
4772 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4773 offset = param_offset + params;
4775 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4777 count = sizeof(struct file_end_of_file_info);
4778 pSMB->MaxParameterCount = cpu_to_le16(2);
4779 /* BB find exact max SMB PDU from sess structure BB */
4780 pSMB->MaxDataCount = cpu_to_le16(1000);
4781 pSMB->SetupCount = 1;
4782 pSMB->Reserved3 = 0;
4783 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4784 byte_count = 3 /* pad */ + params + count;
4785 pSMB->DataCount = cpu_to_le16(count);
4786 pSMB->ParameterCount = cpu_to_le16(params);
4787 pSMB->TotalDataCount = pSMB->DataCount;
4788 pSMB->TotalParameterCount = pSMB->ParameterCount;
4789 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4791 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4793 pSMB->DataOffset = cpu_to_le16(offset);
4794 parm_data->FileSize = cpu_to_le64(size);
4796 if (SetAllocation) {
4797 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4798 pSMB->InformationLevel =
4799 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4801 pSMB->InformationLevel =
4802 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4803 } else /* Set File Size */ {
4804 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4805 pSMB->InformationLevel =
4806 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4808 pSMB->InformationLevel =
4809 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4811 pSMB->Reserved4 = 0;
4812 pSMB->hdr.smb_buf_length += byte_count;
4813 pSMB->ByteCount = cpu_to_le16(byte_count);
4814 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4817 ("Send error in SetFileInfo (SetFileSize) = %d",
4821 /* Note: On -EAGAIN error only caller can retry on handle based calls
4822 since file handle passed in no longer valid */
4827 /* Some legacy servers such as NT4 require that the file times be set on
4828 an open handle, rather than by pathname - this is awkward due to
4829 potential access conflicts on the open, but it is unavoidable for these
4830 old servers since the only other choice is to go from 100 nanosecond DCE
4831 time and resort to the original setpathinfo level which takes the ancient
4832 DOS time format with 2 second granularity */
4834 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4835 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4837 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4840 __u16 params, param_offset, offset, byte_count, count;
4842 cFYI(1, ("Set Times (via SetFileInfo)"));
4843 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4848 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4849 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4852 pSMB->MaxSetupCount = 0;
4856 pSMB->Reserved2 = 0;
4857 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4858 offset = param_offset + params;
4860 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4862 count = sizeof(FILE_BASIC_INFO);
4863 pSMB->MaxParameterCount = cpu_to_le16(2);
4864 /* BB find max SMB PDU from sess */
4865 pSMB->MaxDataCount = cpu_to_le16(1000);
4866 pSMB->SetupCount = 1;
4867 pSMB->Reserved3 = 0;
4868 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4869 byte_count = 3 /* pad */ + params + count;
4870 pSMB->DataCount = cpu_to_le16(count);
4871 pSMB->ParameterCount = cpu_to_le16(params);
4872 pSMB->TotalDataCount = pSMB->DataCount;
4873 pSMB->TotalParameterCount = pSMB->ParameterCount;
4874 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4875 pSMB->DataOffset = cpu_to_le16(offset);
4877 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4878 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4880 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4881 pSMB->Reserved4 = 0;
4882 pSMB->hdr.smb_buf_length += byte_count;
4883 pSMB->ByteCount = cpu_to_le16(byte_count);
4884 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4885 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4887 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4889 /* Note: On -EAGAIN error only caller can retry on handle based calls
4890 since file handle passed in no longer valid */
4896 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4897 bool delete_file, __u16 fid, __u32 pid_of_opener)
4899 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4902 __u16 params, param_offset, offset, byte_count, count;
4904 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4905 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4910 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4911 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4914 pSMB->MaxSetupCount = 0;
4918 pSMB->Reserved2 = 0;
4919 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4920 offset = param_offset + params;
4922 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4925 pSMB->MaxParameterCount = cpu_to_le16(2);
4926 /* BB find max SMB PDU from sess */
4927 pSMB->MaxDataCount = cpu_to_le16(1000);
4928 pSMB->SetupCount = 1;
4929 pSMB->Reserved3 = 0;
4930 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4931 byte_count = 3 /* pad */ + params + count;
4932 pSMB->DataCount = cpu_to_le16(count);
4933 pSMB->ParameterCount = cpu_to_le16(params);
4934 pSMB->TotalDataCount = pSMB->DataCount;
4935 pSMB->TotalParameterCount = pSMB->ParameterCount;
4936 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4937 pSMB->DataOffset = cpu_to_le16(offset);
4939 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4940 pSMB->Reserved4 = 0;
4941 pSMB->hdr.smb_buf_length += byte_count;
4942 pSMB->ByteCount = cpu_to_le16(byte_count);
4943 *data_offset = delete_file ? 1 : 0;
4944 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4946 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4952 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4953 const char *fileName, const FILE_BASIC_INFO *data,
4954 const struct nls_table *nls_codepage, int remap)
4956 TRANSACTION2_SPI_REQ *pSMB = NULL;
4957 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4960 int bytes_returned = 0;
4962 __u16 params, param_offset, offset, byte_count, count;
4964 cFYI(1, ("In SetTimes"));
4967 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4972 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4974 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4975 PATH_MAX, nls_codepage, remap);
4976 name_len++; /* trailing null */
4978 } else { /* BB improve the check for buffer overruns BB */
4979 name_len = strnlen(fileName, PATH_MAX);
4980 name_len++; /* trailing null */
4981 strncpy(pSMB->FileName, fileName, name_len);
4984 params = 6 + name_len;
4985 count = sizeof(FILE_BASIC_INFO);
4986 pSMB->MaxParameterCount = cpu_to_le16(2);
4987 /* BB find max SMB PDU from sess structure BB */
4988 pSMB->MaxDataCount = cpu_to_le16(1000);
4989 pSMB->MaxSetupCount = 0;
4993 pSMB->Reserved2 = 0;
4994 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4995 InformationLevel) - 4;
4996 offset = param_offset + params;
4997 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4998 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4999 pSMB->DataOffset = cpu_to_le16(offset);
5000 pSMB->SetupCount = 1;
5001 pSMB->Reserved3 = 0;
5002 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5003 byte_count = 3 /* pad */ + params + count;
5005 pSMB->DataCount = cpu_to_le16(count);
5006 pSMB->ParameterCount = cpu_to_le16(params);
5007 pSMB->TotalDataCount = pSMB->DataCount;
5008 pSMB->TotalParameterCount = pSMB->ParameterCount;
5009 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5010 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5012 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5013 pSMB->Reserved4 = 0;
5014 pSMB->hdr.smb_buf_length += byte_count;
5015 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5016 pSMB->ByteCount = cpu_to_le16(byte_count);
5017 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5018 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5020 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5022 cifs_buf_release(pSMB);
5030 /* Can not be used to set time stamps yet (due to old DOS time format) */
5031 /* Can be used to set attributes */
5032 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5033 handling it anyway and NT4 was what we thought it would be needed for
5034 Do not delete it until we prove whether needed for Win9x though */
5036 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5037 __u16 dos_attrs, const struct nls_table *nls_codepage)
5039 SETATTR_REQ *pSMB = NULL;
5040 SETATTR_RSP *pSMBr = NULL;
5045 cFYI(1, ("In SetAttrLegacy"));
5048 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5053 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5055 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5056 PATH_MAX, nls_codepage);
5057 name_len++; /* trailing null */
5059 } else { /* BB improve the check for buffer overruns BB */
5060 name_len = strnlen(fileName, PATH_MAX);
5061 name_len++; /* trailing null */
5062 strncpy(pSMB->fileName, fileName, name_len);
5064 pSMB->attr = cpu_to_le16(dos_attrs);
5065 pSMB->BufferFormat = 0x04;
5066 pSMB->hdr.smb_buf_length += name_len + 1;
5067 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5068 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5071 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5073 cifs_buf_release(pSMB);
5076 goto SetAttrLgcyRetry;
5080 #endif /* temporarily unneeded SetAttr legacy function */
5083 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5084 const struct cifs_unix_set_info_args *args,
5085 const struct nls_table *nls_codepage, int remap)
5087 TRANSACTION2_SPI_REQ *pSMB = NULL;
5088 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5091 int bytes_returned = 0;
5092 FILE_UNIX_BASIC_INFO *data_offset;
5093 __u16 params, param_offset, offset, count, byte_count;
5094 __u64 mode = args->mode;
5096 cFYI(1, ("In SetUID/GID/Mode"));
5098 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5103 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5105 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5106 PATH_MAX, nls_codepage, remap);
5107 name_len++; /* trailing null */
5109 } else { /* BB improve the check for buffer overruns BB */
5110 name_len = strnlen(fileName, PATH_MAX);
5111 name_len++; /* trailing null */
5112 strncpy(pSMB->FileName, fileName, name_len);
5115 params = 6 + name_len;
5116 count = sizeof(FILE_UNIX_BASIC_INFO);
5117 pSMB->MaxParameterCount = cpu_to_le16(2);
5118 /* BB find max SMB PDU from sess structure BB */
5119 pSMB->MaxDataCount = cpu_to_le16(1000);
5120 pSMB->MaxSetupCount = 0;
5124 pSMB->Reserved2 = 0;
5125 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5126 InformationLevel) - 4;
5127 offset = param_offset + params;
5129 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5131 memset(data_offset, 0, count);
5132 pSMB->DataOffset = cpu_to_le16(offset);
5133 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5134 pSMB->SetupCount = 1;
5135 pSMB->Reserved3 = 0;
5136 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5137 byte_count = 3 /* pad */ + params + count;
5138 pSMB->ParameterCount = cpu_to_le16(params);
5139 pSMB->DataCount = cpu_to_le16(count);
5140 pSMB->TotalParameterCount = pSMB->ParameterCount;
5141 pSMB->TotalDataCount = pSMB->DataCount;
5142 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5143 pSMB->Reserved4 = 0;
5144 pSMB->hdr.smb_buf_length += byte_count;
5145 /* Samba server ignores set of file size to zero due to bugs in some
5146 older clients, but we should be precise - we use SetFileSize to
5147 set file size and do not want to truncate file size to zero
5148 accidently as happened on one Samba server beta by putting
5149 zero instead of -1 here */
5150 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5151 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5152 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5153 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5154 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5155 data_offset->Uid = cpu_to_le64(args->uid);
5156 data_offset->Gid = cpu_to_le64(args->gid);
5157 /* better to leave device as zero when it is */
5158 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5159 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5160 data_offset->Permissions = cpu_to_le64(mode);
5163 data_offset->Type = cpu_to_le32(UNIX_FILE);
5164 else if (S_ISDIR(mode))
5165 data_offset->Type = cpu_to_le32(UNIX_DIR);
5166 else if (S_ISLNK(mode))
5167 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5168 else if (S_ISCHR(mode))
5169 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5170 else if (S_ISBLK(mode))
5171 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5172 else if (S_ISFIFO(mode))
5173 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5174 else if (S_ISSOCK(mode))
5175 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5178 pSMB->ByteCount = cpu_to_le16(byte_count);
5179 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5180 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5182 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5184 cifs_buf_release(pSMB);
5190 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5191 const int notify_subdirs, const __u16 netfid,
5192 __u32 filter, struct file *pfile, int multishot,
5193 const struct nls_table *nls_codepage)
5196 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5197 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5198 struct dir_notify_req *dnotify_req;
5201 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5202 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5207 pSMB->TotalParameterCount = 0 ;
5208 pSMB->TotalDataCount = 0;
5209 pSMB->MaxParameterCount = cpu_to_le32(2);
5210 /* BB find exact data count max from sess structure BB */
5211 pSMB->MaxDataCount = 0; /* same in little endian or be */
5212 /* BB VERIFY verify which is correct for above BB */
5213 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5214 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5216 pSMB->MaxSetupCount = 4;
5218 pSMB->ParameterOffset = 0;
5219 pSMB->DataCount = 0;
5220 pSMB->DataOffset = 0;
5221 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5222 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5223 pSMB->ParameterCount = pSMB->TotalParameterCount;
5225 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5226 pSMB->Reserved2 = 0;
5227 pSMB->CompletionFilter = cpu_to_le32(filter);
5228 pSMB->Fid = netfid; /* file handle always le */
5229 pSMB->ByteCount = 0;
5231 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5232 (struct smb_hdr *)pSMBr, &bytes_returned,
5235 cFYI(1, ("Error in Notify = %d", rc));
5237 /* Add file to outstanding requests */
5238 /* BB change to kmem cache alloc */
5239 dnotify_req = kmalloc(
5240 sizeof(struct dir_notify_req),
5243 dnotify_req->Pid = pSMB->hdr.Pid;
5244 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5245 dnotify_req->Mid = pSMB->hdr.Mid;
5246 dnotify_req->Tid = pSMB->hdr.Tid;
5247 dnotify_req->Uid = pSMB->hdr.Uid;
5248 dnotify_req->netfid = netfid;
5249 dnotify_req->pfile = pfile;
5250 dnotify_req->filter = filter;
5251 dnotify_req->multishot = multishot;
5252 spin_lock(&GlobalMid_Lock);
5253 list_add_tail(&dnotify_req->lhead,
5254 &GlobalDnotifyReqList);
5255 spin_unlock(&GlobalMid_Lock);
5259 cifs_buf_release(pSMB);
5262 #ifdef CONFIG_CIFS_XATTR
5264 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5265 const unsigned char *searchName,
5266 char *EAData, size_t buf_size,
5267 const struct nls_table *nls_codepage, int remap)
5269 /* BB assumes one setup word */
5270 TRANSACTION2_QPI_REQ *pSMB = NULL;
5271 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5275 struct fea *temp_fea;
5277 __u16 params, byte_count;
5279 cFYI(1, ("In Query All EAs path %s", searchName));
5281 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5286 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5288 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5289 PATH_MAX, nls_codepage, remap);
5290 name_len++; /* trailing null */
5292 } else { /* BB improve the check for buffer overruns BB */
5293 name_len = strnlen(searchName, PATH_MAX);
5294 name_len++; /* trailing null */
5295 strncpy(pSMB->FileName, searchName, name_len);
5298 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5299 pSMB->TotalDataCount = 0;
5300 pSMB->MaxParameterCount = cpu_to_le16(2);
5301 /* BB find exact max SMB PDU from sess structure BB */
5302 pSMB->MaxDataCount = cpu_to_le16(4000);
5303 pSMB->MaxSetupCount = 0;
5307 pSMB->Reserved2 = 0;
5308 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5309 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5310 pSMB->DataCount = 0;
5311 pSMB->DataOffset = 0;
5312 pSMB->SetupCount = 1;
5313 pSMB->Reserved3 = 0;
5314 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5315 byte_count = params + 1 /* pad */ ;
5316 pSMB->TotalParameterCount = cpu_to_le16(params);
5317 pSMB->ParameterCount = pSMB->TotalParameterCount;
5318 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5319 pSMB->Reserved4 = 0;
5320 pSMB->hdr.smb_buf_length += byte_count;
5321 pSMB->ByteCount = cpu_to_le16(byte_count);
5323 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5324 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5326 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5327 } else { /* decode response */
5328 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5330 /* BB also check enough total bytes returned */
5331 /* BB we need to improve the validity checking
5332 of these trans2 responses */
5333 if (rc || (pSMBr->ByteCount < 4))
5334 rc = -EIO; /* bad smb */
5335 /* else if (pFindData){
5336 memcpy((char *) pFindData,
5337 (char *) &pSMBr->hdr.Protocol +
5340 /* check that length of list is not more than bcc */
5341 /* check that each entry does not go beyond length
5343 /* check that each element of each entry does not
5344 go beyond end of list */
5345 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5346 struct fealist *ea_response_data;
5348 /* validate_trans2_offsets() */
5349 /* BB check if start of smb + data_offset > &bcc+ bcc */
5350 ea_response_data = (struct fealist *)
5351 (((char *) &pSMBr->hdr.Protocol) +
5353 name_len = le32_to_cpu(ea_response_data->list_len);
5354 cFYI(1, ("ea length %d", name_len));
5355 if (name_len <= 8) {
5356 /* returned EA size zeroed at top of function */
5357 cFYI(1, ("empty EA list returned from server"));
5359 /* account for ea list len */
5361 temp_fea = ea_response_data->list;
5362 temp_ptr = (char *)temp_fea;
5363 while (name_len > 0) {
5367 rc += temp_fea->name_len;
5368 /* account for prefix user. and trailing null */
5370 if (rc < (int)buf_size) {
5371 memcpy(EAData, "user.", 5);
5373 memcpy(EAData, temp_ptr,
5374 temp_fea->name_len);
5375 EAData += temp_fea->name_len;
5376 /* null terminate name */
5378 EAData = EAData + 1;
5379 } else if (buf_size == 0) {
5380 /* skip copy - calc size only */
5382 /* stop before overrun buffer */
5386 name_len -= temp_fea->name_len;
5387 temp_ptr += temp_fea->name_len;
5388 /* account for trailing null */
5392 le16_to_cpu(temp_fea->value_len);
5393 name_len -= value_len;
5394 temp_ptr += value_len;
5395 /* BB check that temp_ptr is still
5398 /* no trailing null to account for
5400 /* go on to next EA */
5401 temp_fea = (struct fea *)temp_ptr;
5406 cifs_buf_release(pSMB);
5413 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5414 const unsigned char *searchName, const unsigned char *ea_name,
5415 unsigned char *ea_value, size_t buf_size,
5416 const struct nls_table *nls_codepage, int remap)
5418 TRANSACTION2_QPI_REQ *pSMB = NULL;
5419 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5423 struct fea *temp_fea;
5425 __u16 params, byte_count;
5427 cFYI(1, ("In Query EA path %s", searchName));
5429 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5434 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5436 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5437 PATH_MAX, nls_codepage, remap);
5438 name_len++; /* trailing null */
5440 } else { /* BB improve the check for buffer overruns BB */
5441 name_len = strnlen(searchName, PATH_MAX);
5442 name_len++; /* trailing null */
5443 strncpy(pSMB->FileName, searchName, name_len);
5446 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5447 pSMB->TotalDataCount = 0;
5448 pSMB->MaxParameterCount = cpu_to_le16(2);
5449 /* BB find exact max SMB PDU from sess structure BB */
5450 pSMB->MaxDataCount = cpu_to_le16(4000);
5451 pSMB->MaxSetupCount = 0;
5455 pSMB->Reserved2 = 0;
5456 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5457 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5458 pSMB->DataCount = 0;
5459 pSMB->DataOffset = 0;
5460 pSMB->SetupCount = 1;
5461 pSMB->Reserved3 = 0;
5462 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5463 byte_count = params + 1 /* pad */ ;
5464 pSMB->TotalParameterCount = cpu_to_le16(params);
5465 pSMB->ParameterCount = pSMB->TotalParameterCount;
5466 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5467 pSMB->Reserved4 = 0;
5468 pSMB->hdr.smb_buf_length += byte_count;
5469 pSMB->ByteCount = cpu_to_le16(byte_count);
5471 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5472 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5474 cFYI(1, ("Send error in Query EA = %d", rc));
5475 } else { /* decode response */
5476 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5478 /* BB also check enough total bytes returned */
5479 /* BB we need to improve the validity checking
5480 of these trans2 responses */
5481 if (rc || (pSMBr->ByteCount < 4))
5482 rc = -EIO; /* bad smb */
5483 /* else if (pFindData){
5484 memcpy((char *) pFindData,
5485 (char *) &pSMBr->hdr.Protocol +
5488 /* check that length of list is not more than bcc */
5489 /* check that each entry does not go beyond length
5491 /* check that each element of each entry does not
5492 go beyond end of list */
5493 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5494 struct fealist *ea_response_data;
5496 /* validate_trans2_offsets() */
5497 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5498 ea_response_data = (struct fealist *)
5499 (((char *) &pSMBr->hdr.Protocol) +
5501 name_len = le32_to_cpu(ea_response_data->list_len);
5502 cFYI(1, ("ea length %d", name_len));
5503 if (name_len <= 8) {
5504 /* returned EA size zeroed at top of function */
5505 cFYI(1, ("empty EA list returned from server"));
5507 /* account for ea list len */
5509 temp_fea = ea_response_data->list;
5510 temp_ptr = (char *)temp_fea;
5511 /* loop through checking if we have a matching
5512 name and then return the associated value */
5513 while (name_len > 0) {
5518 le16_to_cpu(temp_fea->value_len);
5519 /* BB validate that value_len falls within SMB,
5520 even though maximum for name_len is 255 */
5521 if (memcmp(temp_fea->name, ea_name,
5522 temp_fea->name_len) == 0) {
5525 /* account for prefix user. and trailing null */
5526 if (rc <= (int)buf_size) {
5528 temp_fea->name+temp_fea->name_len+1,
5530 /* ea values, unlike ea
5533 } else if (buf_size == 0) {
5534 /* skip copy - calc size only */
5536 /* stop before overrun buffer */
5541 name_len -= temp_fea->name_len;
5542 temp_ptr += temp_fea->name_len;
5543 /* account for trailing null */
5546 name_len -= value_len;
5547 temp_ptr += value_len;
5548 /* No trailing null to account for in
5549 value_len. Go on to next EA */
5550 temp_fea = (struct fea *)temp_ptr;
5555 cifs_buf_release(pSMB);
5563 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5564 const char *ea_name, const void *ea_value,
5565 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5568 struct smb_com_transaction2_spi_req *pSMB = NULL;
5569 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5570 struct fealist *parm_data;
5573 int bytes_returned = 0;
5574 __u16 params, param_offset, byte_count, offset, count;
5576 cFYI(1, ("In SetEA"));
5578 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5583 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5585 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5586 PATH_MAX, nls_codepage, remap);
5587 name_len++; /* trailing null */
5589 } else { /* BB improve the check for buffer overruns BB */
5590 name_len = strnlen(fileName, PATH_MAX);
5591 name_len++; /* trailing null */
5592 strncpy(pSMB->FileName, fileName, name_len);
5595 params = 6 + name_len;
5597 /* done calculating parms using name_len of file name,
5598 now use name_len to calculate length of ea name
5599 we are going to create in the inode xattrs */
5600 if (ea_name == NULL)
5603 name_len = strnlen(ea_name, 255);
5605 count = sizeof(*parm_data) + ea_value_len + name_len;
5606 pSMB->MaxParameterCount = cpu_to_le16(2);
5607 /* BB find max SMB PDU from sess */
5608 pSMB->MaxDataCount = cpu_to_le16(1000);
5609 pSMB->MaxSetupCount = 0;
5613 pSMB->Reserved2 = 0;
5614 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5615 InformationLevel) - 4;
5616 offset = param_offset + params;
5617 pSMB->InformationLevel =
5618 cpu_to_le16(SMB_SET_FILE_EA);
5621 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5623 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5624 pSMB->DataOffset = cpu_to_le16(offset);
5625 pSMB->SetupCount = 1;
5626 pSMB->Reserved3 = 0;
5627 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5628 byte_count = 3 /* pad */ + params + count;
5629 pSMB->DataCount = cpu_to_le16(count);
5630 parm_data->list_len = cpu_to_le32(count);
5631 parm_data->list[0].EA_flags = 0;
5632 /* we checked above that name len is less than 255 */
5633 parm_data->list[0].name_len = (__u8)name_len;
5634 /* EA names are always ASCII */
5636 strncpy(parm_data->list[0].name, ea_name, name_len);
5637 parm_data->list[0].name[name_len] = 0;
5638 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5639 /* caller ensures that ea_value_len is less than 64K but
5640 we need to ensure that it fits within the smb */
5642 /*BB add length check to see if it would fit in
5643 negotiated SMB buffer size BB */
5644 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5646 memcpy(parm_data->list[0].name+name_len+1,
5647 ea_value, ea_value_len);
5649 pSMB->TotalDataCount = pSMB->DataCount;
5650 pSMB->ParameterCount = cpu_to_le16(params);
5651 pSMB->TotalParameterCount = pSMB->ParameterCount;
5652 pSMB->Reserved4 = 0;
5653 pSMB->hdr.smb_buf_length += byte_count;
5654 pSMB->ByteCount = cpu_to_le16(byte_count);
5655 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5656 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5658 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5660 cifs_buf_release(pSMB);