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(rsp->SrvTime.Date,
528 rsp->SrvTime.Time, 0);
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 = RawNTLMSSP;
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) || (tcon->ses->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 if (posix_flags & SMB_O_DIRECTORY)
1117 cifs_stats_inc(&tcon->num_posixmkdirs);
1119 cifs_stats_inc(&tcon->num_posixopens);
1127 static __u16 convert_disposition(int disposition)
1131 switch (disposition) {
1132 case FILE_SUPERSEDE:
1133 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1136 ofun = SMBOPEN_OAPPEND;
1139 ofun = SMBOPEN_OCREATE;
1142 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1144 case FILE_OVERWRITE:
1145 ofun = SMBOPEN_OTRUNC;
1147 case FILE_OVERWRITE_IF:
1148 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1151 cFYI(1, ("unknown disposition %d", disposition));
1152 ofun = SMBOPEN_OAPPEND; /* regular open */
1158 access_flags_to_smbopen_mode(const int access_flags)
1160 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1162 if (masked_flags == GENERIC_READ)
1163 return SMBOPEN_READ;
1164 else if (masked_flags == GENERIC_WRITE)
1165 return SMBOPEN_WRITE;
1167 /* just go for read/write */
1168 return SMBOPEN_READWRITE;
1172 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1173 const char *fileName, const int openDisposition,
1174 const int access_flags, const int create_options, __u16 *netfid,
1175 int *pOplock, FILE_ALL_INFO *pfile_info,
1176 const struct nls_table *nls_codepage, int remap)
1179 OPENX_REQ *pSMB = NULL;
1180 OPENX_RSP *pSMBr = NULL;
1186 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1191 pSMB->AndXCommand = 0xFF; /* none */
1193 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1194 count = 1; /* account for one byte pad to word boundary */
1196 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1197 fileName, PATH_MAX, nls_codepage, remap);
1198 name_len++; /* trailing null */
1200 } else { /* BB improve check for buffer overruns BB */
1201 count = 0; /* no pad */
1202 name_len = strnlen(fileName, PATH_MAX);
1203 name_len++; /* trailing null */
1204 strncpy(pSMB->fileName, fileName, name_len);
1206 if (*pOplock & REQ_OPLOCK)
1207 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1208 else if (*pOplock & REQ_BATCHOPLOCK)
1209 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1211 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1212 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1213 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1214 /* set file as system file if special file such
1215 as fifo and server expecting SFU style and
1216 no Unix extensions */
1218 if (create_options & CREATE_OPTION_SPECIAL)
1219 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1220 else /* BB FIXME BB */
1221 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1223 if (create_options & CREATE_OPTION_READONLY)
1224 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1227 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1228 CREATE_OPTIONS_MASK); */
1229 /* BB FIXME END BB */
1231 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1232 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1234 pSMB->hdr.smb_buf_length += count;
1236 pSMB->ByteCount = cpu_to_le16(count);
1237 /* long_op set to 1 to allow for oplock break timeouts */
1238 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1239 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1240 cifs_stats_inc(&tcon->num_opens);
1242 cFYI(1, ("Error in Open = %d", rc));
1244 /* BB verify if wct == 15 */
1246 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1248 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1249 /* Let caller know file was created so we can set the mode. */
1250 /* Do we care about the CreateAction in any other cases? */
1252 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1253 *pOplock |= CIFS_CREATE_ACTION; */
1257 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1258 pfile_info->LastAccessTime = 0; /* BB fixme */
1259 pfile_info->LastWriteTime = 0; /* BB fixme */
1260 pfile_info->ChangeTime = 0; /* BB fixme */
1261 pfile_info->Attributes =
1262 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1263 /* the file_info buf is endian converted by caller */
1264 pfile_info->AllocationSize =
1265 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1266 pfile_info->EndOfFile = pfile_info->AllocationSize;
1267 pfile_info->NumberOfLinks = cpu_to_le32(1);
1268 pfile_info->DeletePending = 0;
1272 cifs_buf_release(pSMB);
1279 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1280 const char *fileName, const int openDisposition,
1281 const int access_flags, const int create_options, __u16 *netfid,
1282 int *pOplock, FILE_ALL_INFO *pfile_info,
1283 const struct nls_table *nls_codepage, int remap)
1286 OPEN_REQ *pSMB = NULL;
1287 OPEN_RSP *pSMBr = NULL;
1293 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1298 pSMB->AndXCommand = 0xFF; /* none */
1300 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1301 count = 1; /* account for one byte pad to word boundary */
1303 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1304 fileName, PATH_MAX, nls_codepage, remap);
1305 name_len++; /* trailing null */
1307 pSMB->NameLength = cpu_to_le16(name_len);
1308 } else { /* BB improve check for buffer overruns BB */
1309 count = 0; /* no pad */
1310 name_len = strnlen(fileName, PATH_MAX);
1311 name_len++; /* trailing null */
1312 pSMB->NameLength = cpu_to_le16(name_len);
1313 strncpy(pSMB->fileName, fileName, name_len);
1315 if (*pOplock & REQ_OPLOCK)
1316 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1317 else if (*pOplock & REQ_BATCHOPLOCK)
1318 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1319 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1320 pSMB->AllocationSize = 0;
1321 /* set file as system file if special file such
1322 as fifo and server expecting SFU style and
1323 no Unix extensions */
1324 if (create_options & CREATE_OPTION_SPECIAL)
1325 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1327 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1329 /* XP does not handle ATTR_POSIX_SEMANTICS */
1330 /* but it helps speed up case sensitive checks for other
1331 servers such as Samba */
1332 if (tcon->ses->capabilities & CAP_UNIX)
1333 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1335 if (create_options & CREATE_OPTION_READONLY)
1336 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1338 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1339 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1340 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1341 /* BB Expirement with various impersonation levels and verify */
1342 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1343 pSMB->SecurityFlags =
1344 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1347 pSMB->hdr.smb_buf_length += count;
1349 pSMB->ByteCount = cpu_to_le16(count);
1350 /* long_op set to 1 to allow for oplock break timeouts */
1351 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1352 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1353 cifs_stats_inc(&tcon->num_opens);
1355 cFYI(1, ("Error in Open = %d", rc));
1357 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1358 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1359 /* Let caller know file was created so we can set the mode. */
1360 /* Do we care about the CreateAction in any other cases? */
1361 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1362 *pOplock |= CIFS_CREATE_ACTION;
1364 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1365 36 /* CreationTime to Attributes */);
1366 /* the file_info buf is endian converted by caller */
1367 pfile_info->AllocationSize = pSMBr->AllocationSize;
1368 pfile_info->EndOfFile = pSMBr->EndOfFile;
1369 pfile_info->NumberOfLinks = cpu_to_le32(1);
1370 pfile_info->DeletePending = 0;
1374 cifs_buf_release(pSMB);
1381 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1382 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1383 char **buf, int *pbuf_type)
1386 READ_REQ *pSMB = NULL;
1387 READ_RSP *pSMBr = NULL;
1388 char *pReadData = NULL;
1390 int resp_buf_type = 0;
1393 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1394 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1397 wct = 10; /* old style read */
1398 if ((lseek >> 32) > 0) {
1399 /* can not handle this big offset for old */
1405 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1409 /* tcon and ses pointer are checked in smb_init */
1410 if (tcon->ses->server == NULL)
1411 return -ECONNABORTED;
1413 pSMB->AndXCommand = 0xFF; /* none */
1415 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1417 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1419 pSMB->Remaining = 0;
1420 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1421 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1423 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1425 /* old style read */
1426 struct smb_com_readx_req *pSMBW =
1427 (struct smb_com_readx_req *)pSMB;
1428 pSMBW->ByteCount = 0;
1431 iov[0].iov_base = (char *)pSMB;
1432 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1433 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1434 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1435 cifs_stats_inc(&tcon->num_reads);
1436 pSMBr = (READ_RSP *)iov[0].iov_base;
1438 cERROR(1, ("Send error in read = %d", rc));
1440 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1441 data_length = data_length << 16;
1442 data_length += le16_to_cpu(pSMBr->DataLength);
1443 *nbytes = data_length;
1445 /*check that DataLength would not go beyond end of SMB */
1446 if ((data_length > CIFSMaxBufSize)
1447 || (data_length > count)) {
1448 cFYI(1, ("bad length %d for count %d",
1449 data_length, count));
1453 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1454 le16_to_cpu(pSMBr->DataOffset);
1455 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1456 cERROR(1,("Faulting on read rc = %d",rc));
1458 }*/ /* can not use copy_to_user when using page cache*/
1460 memcpy(*buf, pReadData, data_length);
1464 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1466 if (resp_buf_type == CIFS_SMALL_BUFFER)
1467 cifs_small_buf_release(iov[0].iov_base);
1468 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1469 cifs_buf_release(iov[0].iov_base);
1470 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1471 /* return buffer to caller to free */
1472 *buf = iov[0].iov_base;
1473 if (resp_buf_type == CIFS_SMALL_BUFFER)
1474 *pbuf_type = CIFS_SMALL_BUFFER;
1475 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1476 *pbuf_type = CIFS_LARGE_BUFFER;
1477 } /* else no valid buffer on return - leave as null */
1479 /* Note: On -EAGAIN error only caller can retry on handle based calls
1480 since file handle passed in no longer valid */
1486 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1487 const int netfid, const unsigned int count,
1488 const __u64 offset, unsigned int *nbytes, const char *buf,
1489 const char __user *ubuf, const int long_op)
1492 WRITE_REQ *pSMB = NULL;
1493 WRITE_RSP *pSMBr = NULL;
1494 int bytes_returned, wct;
1498 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1499 if (tcon->ses == NULL)
1500 return -ECONNABORTED;
1502 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1506 if ((offset >> 32) > 0) {
1507 /* can not handle big offset for old srv */
1512 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1516 /* tcon and ses pointer are checked in smb_init */
1517 if (tcon->ses->server == NULL)
1518 return -ECONNABORTED;
1520 pSMB->AndXCommand = 0xFF; /* none */
1522 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1524 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1526 pSMB->Reserved = 0xFFFFFFFF;
1527 pSMB->WriteMode = 0;
1528 pSMB->Remaining = 0;
1530 /* Can increase buffer size if buffer is big enough in some cases ie we
1531 can send more if LARGE_WRITE_X capability returned by the server and if
1532 our buffer is big enough or if we convert to iovecs on socket writes
1533 and eliminate the copy to the CIFS buffer */
1534 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1535 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1537 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1541 if (bytes_sent > count)
1544 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1546 memcpy(pSMB->Data, buf, bytes_sent);
1548 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1549 cifs_buf_release(pSMB);
1552 } else if (count != 0) {
1554 cifs_buf_release(pSMB);
1556 } /* else setting file size with write of zero bytes */
1558 byte_count = bytes_sent + 1; /* pad */
1559 else /* wct == 12 */
1560 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1562 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1563 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1564 pSMB->hdr.smb_buf_length += byte_count;
1567 pSMB->ByteCount = cpu_to_le16(byte_count);
1568 else { /* old style write has byte count 4 bytes earlier
1570 struct smb_com_writex_req *pSMBW =
1571 (struct smb_com_writex_req *)pSMB;
1572 pSMBW->ByteCount = cpu_to_le16(byte_count);
1575 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1576 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1577 cifs_stats_inc(&tcon->num_writes);
1579 cFYI(1, ("Send error in write = %d", rc));
1582 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1583 *nbytes = (*nbytes) << 16;
1584 *nbytes += le16_to_cpu(pSMBr->Count);
1587 cifs_buf_release(pSMB);
1589 /* Note: On -EAGAIN error only caller can retry on handle based calls
1590 since file handle passed in no longer valid */
1596 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1597 const int netfid, const unsigned int count,
1598 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1599 int n_vec, const int long_op)
1602 WRITE_REQ *pSMB = NULL;
1605 int resp_buf_type = 0;
1609 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1611 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1615 if ((offset >> 32) > 0) {
1616 /* can not handle big offset for old srv */
1620 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1623 /* tcon and ses pointer are checked in smb_init */
1624 if (tcon->ses->server == NULL)
1625 return -ECONNABORTED;
1627 pSMB->AndXCommand = 0xFF; /* none */
1629 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1631 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1632 pSMB->Reserved = 0xFFFFFFFF;
1633 pSMB->WriteMode = 0;
1634 pSMB->Remaining = 0;
1637 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1639 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1640 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1641 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1643 pSMB->hdr.smb_buf_length += count+1;
1644 else /* wct == 12 */
1645 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1647 pSMB->ByteCount = cpu_to_le16(count + 1);
1648 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1649 struct smb_com_writex_req *pSMBW =
1650 (struct smb_com_writex_req *)pSMB;
1651 pSMBW->ByteCount = cpu_to_le16(count + 5);
1653 iov[0].iov_base = pSMB;
1655 iov[0].iov_len = smb_hdr_len + 4;
1656 else /* wct == 12 pad bigger by four bytes */
1657 iov[0].iov_len = smb_hdr_len + 8;
1660 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1662 cifs_stats_inc(&tcon->num_writes);
1664 cFYI(1, ("Send error Write2 = %d", rc));
1665 } else if (resp_buf_type == 0) {
1666 /* presumably this can not happen, but best to be safe */
1669 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1670 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1671 *nbytes = (*nbytes) << 16;
1672 *nbytes += le16_to_cpu(pSMBr->Count);
1675 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1676 if (resp_buf_type == CIFS_SMALL_BUFFER)
1677 cifs_small_buf_release(iov[0].iov_base);
1678 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1679 cifs_buf_release(iov[0].iov_base);
1681 /* Note: On -EAGAIN error only caller can retry on handle based calls
1682 since file handle passed in no longer valid */
1689 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1690 const __u16 smb_file_id, const __u64 len,
1691 const __u64 offset, const __u32 numUnlock,
1692 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1695 LOCK_REQ *pSMB = NULL;
1696 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1701 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1702 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1707 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1708 timeout = CIFS_ASYNC_OP; /* no response expected */
1710 } else if (waitFlag) {
1711 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1712 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1717 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1718 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1719 pSMB->LockType = lockType;
1720 pSMB->AndXCommand = 0xFF; /* none */
1721 pSMB->Fid = smb_file_id; /* netfid stays le */
1723 if ((numLock != 0) || (numUnlock != 0)) {
1724 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1725 /* BB where to store pid high? */
1726 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1727 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1728 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1729 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1730 count = sizeof(LOCKING_ANDX_RANGE);
1735 pSMB->hdr.smb_buf_length += count;
1736 pSMB->ByteCount = cpu_to_le16(count);
1739 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1740 (struct smb_hdr *) pSMB, &bytes_returned);
1741 cifs_small_buf_release(pSMB);
1743 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1745 /* SMB buffer freed by function above */
1747 cifs_stats_inc(&tcon->num_locks);
1749 cFYI(1, ("Send error in Lock = %d", rc));
1751 /* Note: On -EAGAIN error only caller can retry on handle based calls
1752 since file handle passed in no longer valid */
1757 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1758 const __u16 smb_file_id, const int get_flag, const __u64 len,
1759 struct file_lock *pLockData, const __u16 lock_type,
1760 const bool waitFlag)
1762 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1763 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1764 struct cifs_posix_lock *parm_data;
1767 int bytes_returned = 0;
1768 int resp_buf_type = 0;
1769 __u16 params, param_offset, offset, byte_count, count;
1772 cFYI(1, ("Posix Lock"));
1774 if (pLockData == NULL)
1777 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1782 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1785 pSMB->MaxSetupCount = 0;
1788 pSMB->Reserved2 = 0;
1789 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1790 offset = param_offset + params;
1792 count = sizeof(struct cifs_posix_lock);
1793 pSMB->MaxParameterCount = cpu_to_le16(2);
1794 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1795 pSMB->SetupCount = 1;
1796 pSMB->Reserved3 = 0;
1798 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1800 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1801 byte_count = 3 /* pad */ + params + count;
1802 pSMB->DataCount = cpu_to_le16(count);
1803 pSMB->ParameterCount = cpu_to_le16(params);
1804 pSMB->TotalDataCount = pSMB->DataCount;
1805 pSMB->TotalParameterCount = pSMB->ParameterCount;
1806 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1807 parm_data = (struct cifs_posix_lock *)
1808 (((char *) &pSMB->hdr.Protocol) + offset);
1810 parm_data->lock_type = cpu_to_le16(lock_type);
1812 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1813 parm_data->lock_flags = cpu_to_le16(1);
1814 pSMB->Timeout = cpu_to_le32(-1);
1818 parm_data->pid = cpu_to_le32(current->tgid);
1819 parm_data->start = cpu_to_le64(pLockData->fl_start);
1820 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1822 pSMB->DataOffset = cpu_to_le16(offset);
1823 pSMB->Fid = smb_file_id;
1824 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1825 pSMB->Reserved4 = 0;
1826 pSMB->hdr.smb_buf_length += byte_count;
1827 pSMB->ByteCount = cpu_to_le16(byte_count);
1829 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1830 (struct smb_hdr *) pSMBr, &bytes_returned);
1832 iov[0].iov_base = (char *)pSMB;
1833 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1834 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1835 &resp_buf_type, timeout);
1836 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1837 not try to free it twice below on exit */
1838 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1842 cFYI(1, ("Send error in Posix Lock = %d", rc));
1843 } else if (get_flag) {
1844 /* lock structure can be returned on get */
1847 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1849 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1850 rc = -EIO; /* bad smb */
1853 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1854 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1855 if (data_count < sizeof(struct cifs_posix_lock)) {
1859 parm_data = (struct cifs_posix_lock *)
1860 ((char *)&pSMBr->hdr.Protocol + data_offset);
1861 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1862 pLockData->fl_type = F_UNLCK;
1867 cifs_small_buf_release(pSMB);
1869 if (resp_buf_type == CIFS_SMALL_BUFFER)
1870 cifs_small_buf_release(iov[0].iov_base);
1871 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1872 cifs_buf_release(iov[0].iov_base);
1874 /* Note: On -EAGAIN error only caller can retry on handle based calls
1875 since file handle passed in no longer valid */
1882 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1885 CLOSE_REQ *pSMB = NULL;
1886 cFYI(1, ("In CIFSSMBClose"));
1888 /* do not retry on dead session on close */
1889 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1895 pSMB->FileID = (__u16) smb_file_id;
1896 pSMB->LastWriteTime = 0xFFFFFFFF;
1897 pSMB->ByteCount = 0;
1898 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1899 cifs_stats_inc(&tcon->num_closes);
1902 /* EINTR is expected when user ctl-c to kill app */
1903 cERROR(1, ("Send error in Close = %d", rc));
1907 /* Since session is dead, file will be closed on server already */
1915 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1918 FLUSH_REQ *pSMB = NULL;
1919 cFYI(1, ("In CIFSSMBFlush"));
1921 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1925 pSMB->FileID = (__u16) smb_file_id;
1926 pSMB->ByteCount = 0;
1927 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1928 cifs_stats_inc(&tcon->num_flushes);
1930 cERROR(1, ("Send error in Flush = %d", rc));
1936 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1937 const char *fromName, const char *toName,
1938 const struct nls_table *nls_codepage, int remap)
1941 RENAME_REQ *pSMB = NULL;
1942 RENAME_RSP *pSMBr = NULL;
1944 int name_len, name_len2;
1947 cFYI(1, ("In CIFSSMBRename"));
1949 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1954 pSMB->BufferFormat = 0x04;
1955 pSMB->SearchAttributes =
1956 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1959 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1961 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1962 PATH_MAX, nls_codepage, remap);
1963 name_len++; /* trailing null */
1965 pSMB->OldFileName[name_len] = 0x04; /* pad */
1966 /* protocol requires ASCII signature byte on Unicode string */
1967 pSMB->OldFileName[name_len + 1] = 0x00;
1969 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1970 toName, PATH_MAX, nls_codepage, remap);
1971 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1972 name_len2 *= 2; /* convert to bytes */
1973 } else { /* BB improve the check for buffer overruns BB */
1974 name_len = strnlen(fromName, PATH_MAX);
1975 name_len++; /* trailing null */
1976 strncpy(pSMB->OldFileName, fromName, name_len);
1977 name_len2 = strnlen(toName, PATH_MAX);
1978 name_len2++; /* trailing null */
1979 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1980 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1981 name_len2++; /* trailing null */
1982 name_len2++; /* signature byte */
1985 count = 1 /* 1st signature byte */ + name_len + name_len2;
1986 pSMB->hdr.smb_buf_length += count;
1987 pSMB->ByteCount = cpu_to_le16(count);
1989 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1990 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1991 cifs_stats_inc(&tcon->num_renames);
1993 cFYI(1, ("Send error in rename = %d", rc));
1995 cifs_buf_release(pSMB);
2003 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2004 int netfid, const char *target_name,
2005 const struct nls_table *nls_codepage, int remap)
2007 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2008 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2009 struct set_file_rename *rename_info;
2011 char dummy_string[30];
2013 int bytes_returned = 0;
2015 __u16 params, param_offset, offset, count, byte_count;
2017 cFYI(1, ("Rename to File by handle"));
2018 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2024 pSMB->MaxSetupCount = 0;
2028 pSMB->Reserved2 = 0;
2029 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2030 offset = param_offset + params;
2032 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2033 rename_info = (struct set_file_rename *) data_offset;
2034 pSMB->MaxParameterCount = cpu_to_le16(2);
2035 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2036 pSMB->SetupCount = 1;
2037 pSMB->Reserved3 = 0;
2038 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2039 byte_count = 3 /* pad */ + params;
2040 pSMB->ParameterCount = cpu_to_le16(params);
2041 pSMB->TotalParameterCount = pSMB->ParameterCount;
2042 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2043 pSMB->DataOffset = cpu_to_le16(offset);
2044 /* construct random name ".cifs_tmp<inodenum><mid>" */
2045 rename_info->overwrite = cpu_to_le32(1);
2046 rename_info->root_fid = 0;
2047 /* unicode only call */
2048 if (target_name == NULL) {
2049 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2050 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2051 dummy_string, 24, nls_codepage, remap);
2053 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2054 target_name, PATH_MAX, nls_codepage,
2057 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2058 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2059 byte_count += count;
2060 pSMB->DataCount = cpu_to_le16(count);
2061 pSMB->TotalDataCount = pSMB->DataCount;
2063 pSMB->InformationLevel =
2064 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2065 pSMB->Reserved4 = 0;
2066 pSMB->hdr.smb_buf_length += byte_count;
2067 pSMB->ByteCount = cpu_to_le16(byte_count);
2068 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2070 cifs_stats_inc(&pTcon->num_t2renames);
2072 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2074 cifs_buf_release(pSMB);
2076 /* Note: On -EAGAIN error only caller can retry on handle based calls
2077 since file handle passed in no longer valid */
2083 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2084 const __u16 target_tid, const char *toName, const int flags,
2085 const struct nls_table *nls_codepage, int remap)
2088 COPY_REQ *pSMB = NULL;
2089 COPY_RSP *pSMBr = NULL;
2091 int name_len, name_len2;
2094 cFYI(1, ("In CIFSSMBCopy"));
2096 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2101 pSMB->BufferFormat = 0x04;
2102 pSMB->Tid2 = target_tid;
2104 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2106 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2107 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2108 fromName, PATH_MAX, nls_codepage,
2110 name_len++; /* trailing null */
2112 pSMB->OldFileName[name_len] = 0x04; /* pad */
2113 /* protocol requires ASCII signature byte on Unicode string */
2114 pSMB->OldFileName[name_len + 1] = 0x00;
2116 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2117 toName, PATH_MAX, nls_codepage, remap);
2118 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2119 name_len2 *= 2; /* convert to bytes */
2120 } else { /* BB improve the check for buffer overruns BB */
2121 name_len = strnlen(fromName, PATH_MAX);
2122 name_len++; /* trailing null */
2123 strncpy(pSMB->OldFileName, fromName, name_len);
2124 name_len2 = strnlen(toName, PATH_MAX);
2125 name_len2++; /* trailing null */
2126 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2127 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2128 name_len2++; /* trailing null */
2129 name_len2++; /* signature byte */
2132 count = 1 /* 1st signature byte */ + name_len + name_len2;
2133 pSMB->hdr.smb_buf_length += count;
2134 pSMB->ByteCount = cpu_to_le16(count);
2136 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2137 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2139 cFYI(1, ("Send error in copy = %d with %d files copied",
2140 rc, le16_to_cpu(pSMBr->CopyCount)));
2142 cifs_buf_release(pSMB);
2151 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2152 const char *fromName, const char *toName,
2153 const struct nls_table *nls_codepage)
2155 TRANSACTION2_SPI_REQ *pSMB = NULL;
2156 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2159 int name_len_target;
2161 int bytes_returned = 0;
2162 __u16 params, param_offset, offset, byte_count;
2164 cFYI(1, ("In Symlink Unix style"));
2166 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2171 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2173 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2174 /* find define for this maxpathcomponent */
2176 name_len++; /* trailing null */
2179 } else { /* BB improve the check for buffer overruns BB */
2180 name_len = strnlen(fromName, PATH_MAX);
2181 name_len++; /* trailing null */
2182 strncpy(pSMB->FileName, fromName, name_len);
2184 params = 6 + name_len;
2185 pSMB->MaxSetupCount = 0;
2189 pSMB->Reserved2 = 0;
2190 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2191 InformationLevel) - 4;
2192 offset = param_offset + params;
2194 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2197 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2198 /* find define for this maxpathcomponent */
2200 name_len_target++; /* trailing null */
2201 name_len_target *= 2;
2202 } else { /* BB improve the check for buffer overruns BB */
2203 name_len_target = strnlen(toName, PATH_MAX);
2204 name_len_target++; /* trailing null */
2205 strncpy(data_offset, toName, name_len_target);
2208 pSMB->MaxParameterCount = cpu_to_le16(2);
2209 /* BB find exact max on data count below from sess */
2210 pSMB->MaxDataCount = cpu_to_le16(1000);
2211 pSMB->SetupCount = 1;
2212 pSMB->Reserved3 = 0;
2213 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2214 byte_count = 3 /* pad */ + params + name_len_target;
2215 pSMB->DataCount = cpu_to_le16(name_len_target);
2216 pSMB->ParameterCount = cpu_to_le16(params);
2217 pSMB->TotalDataCount = pSMB->DataCount;
2218 pSMB->TotalParameterCount = pSMB->ParameterCount;
2219 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2220 pSMB->DataOffset = cpu_to_le16(offset);
2221 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2222 pSMB->Reserved4 = 0;
2223 pSMB->hdr.smb_buf_length += byte_count;
2224 pSMB->ByteCount = cpu_to_le16(byte_count);
2225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2227 cifs_stats_inc(&tcon->num_symlinks);
2229 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2231 cifs_buf_release(pSMB);
2234 goto createSymLinkRetry;
2240 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2241 const char *fromName, const char *toName,
2242 const struct nls_table *nls_codepage, int remap)
2244 TRANSACTION2_SPI_REQ *pSMB = NULL;
2245 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2248 int name_len_target;
2250 int bytes_returned = 0;
2251 __u16 params, param_offset, offset, byte_count;
2253 cFYI(1, ("In Create Hard link Unix style"));
2254 createHardLinkRetry:
2255 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2260 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2261 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2262 PATH_MAX, nls_codepage, remap);
2263 name_len++; /* trailing null */
2266 } else { /* BB improve the check for buffer overruns BB */
2267 name_len = strnlen(toName, PATH_MAX);
2268 name_len++; /* trailing null */
2269 strncpy(pSMB->FileName, toName, name_len);
2271 params = 6 + name_len;
2272 pSMB->MaxSetupCount = 0;
2276 pSMB->Reserved2 = 0;
2277 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2278 InformationLevel) - 4;
2279 offset = param_offset + params;
2281 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2282 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2284 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2285 nls_codepage, remap);
2286 name_len_target++; /* trailing null */
2287 name_len_target *= 2;
2288 } else { /* BB improve the check for buffer overruns BB */
2289 name_len_target = strnlen(fromName, PATH_MAX);
2290 name_len_target++; /* trailing null */
2291 strncpy(data_offset, fromName, name_len_target);
2294 pSMB->MaxParameterCount = cpu_to_le16(2);
2295 /* BB find exact max on data count below from sess*/
2296 pSMB->MaxDataCount = cpu_to_le16(1000);
2297 pSMB->SetupCount = 1;
2298 pSMB->Reserved3 = 0;
2299 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2300 byte_count = 3 /* pad */ + params + name_len_target;
2301 pSMB->ParameterCount = cpu_to_le16(params);
2302 pSMB->TotalParameterCount = pSMB->ParameterCount;
2303 pSMB->DataCount = cpu_to_le16(name_len_target);
2304 pSMB->TotalDataCount = pSMB->DataCount;
2305 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2306 pSMB->DataOffset = cpu_to_le16(offset);
2307 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2308 pSMB->Reserved4 = 0;
2309 pSMB->hdr.smb_buf_length += byte_count;
2310 pSMB->ByteCount = cpu_to_le16(byte_count);
2311 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2312 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2313 cifs_stats_inc(&tcon->num_hardlinks);
2315 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2317 cifs_buf_release(pSMB);
2319 goto createHardLinkRetry;
2325 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2326 const char *fromName, const char *toName,
2327 const struct nls_table *nls_codepage, int remap)
2330 NT_RENAME_REQ *pSMB = NULL;
2331 RENAME_RSP *pSMBr = NULL;
2333 int name_len, name_len2;
2336 cFYI(1, ("In CIFSCreateHardLink"));
2337 winCreateHardLinkRetry:
2339 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2344 pSMB->SearchAttributes =
2345 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2347 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2348 pSMB->ClusterCount = 0;
2350 pSMB->BufferFormat = 0x04;
2352 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2354 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2355 PATH_MAX, nls_codepage, remap);
2356 name_len++; /* trailing null */
2359 /* protocol specifies ASCII buffer format (0x04) for unicode */
2360 pSMB->OldFileName[name_len] = 0x04;
2361 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2363 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2364 toName, PATH_MAX, nls_codepage, remap);
2365 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2366 name_len2 *= 2; /* convert to bytes */
2367 } else { /* BB improve the check for buffer overruns BB */
2368 name_len = strnlen(fromName, PATH_MAX);
2369 name_len++; /* trailing null */
2370 strncpy(pSMB->OldFileName, fromName, name_len);
2371 name_len2 = strnlen(toName, PATH_MAX);
2372 name_len2++; /* trailing null */
2373 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2374 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2375 name_len2++; /* trailing null */
2376 name_len2++; /* signature byte */
2379 count = 1 /* string type byte */ + name_len + name_len2;
2380 pSMB->hdr.smb_buf_length += count;
2381 pSMB->ByteCount = cpu_to_le16(count);
2383 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2384 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2385 cifs_stats_inc(&tcon->num_hardlinks);
2387 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2389 cifs_buf_release(pSMB);
2391 goto winCreateHardLinkRetry;
2397 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2398 const unsigned char *searchName, char **symlinkinfo,
2399 const struct nls_table *nls_codepage)
2401 /* SMB_QUERY_FILE_UNIX_LINK */
2402 TRANSACTION2_QPI_REQ *pSMB = NULL;
2403 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2407 __u16 params, byte_count;
2410 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2413 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2418 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2420 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2421 PATH_MAX, nls_codepage);
2422 name_len++; /* trailing null */
2424 } else { /* BB improve the check for buffer overruns BB */
2425 name_len = strnlen(searchName, PATH_MAX);
2426 name_len++; /* trailing null */
2427 strncpy(pSMB->FileName, searchName, name_len);
2430 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2431 pSMB->TotalDataCount = 0;
2432 pSMB->MaxParameterCount = cpu_to_le16(2);
2433 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2434 pSMB->MaxSetupCount = 0;
2438 pSMB->Reserved2 = 0;
2439 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2440 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2441 pSMB->DataCount = 0;
2442 pSMB->DataOffset = 0;
2443 pSMB->SetupCount = 1;
2444 pSMB->Reserved3 = 0;
2445 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2446 byte_count = params + 1 /* pad */ ;
2447 pSMB->TotalParameterCount = cpu_to_le16(params);
2448 pSMB->ParameterCount = pSMB->TotalParameterCount;
2449 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2450 pSMB->Reserved4 = 0;
2451 pSMB->hdr.smb_buf_length += byte_count;
2452 pSMB->ByteCount = cpu_to_le16(byte_count);
2454 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2455 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2457 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2459 /* decode response */
2461 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2462 /* BB also check enough total bytes returned */
2463 if (rc || (pSMBr->ByteCount < 2))
2467 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2469 data_start = ((char *) &pSMBr->hdr.Protocol) +
2470 le16_to_cpu(pSMBr->t2.DataOffset);
2472 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2477 /* BB FIXME investigate remapping reserved chars here */
2478 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2479 is_unicode, nls_codepage);
2484 cifs_buf_release(pSMB);
2486 goto querySymLinkRetry;
2490 #ifdef CONFIG_CIFS_EXPERIMENTAL
2491 /* Initialize NT TRANSACT SMB into small smb request buffer.
2492 This assumes that all NT TRANSACTS that we init here have
2493 total parm and data under about 400 bytes (to fit in small cifs
2494 buffer size), which is the case so far, it easily fits. NB:
2495 Setup words themselves and ByteCount
2496 MaxSetupCount (size of returned setup area) and
2497 MaxParameterCount (returned parms size) must be set by caller */
2499 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2500 const int parm_len, struct cifsTconInfo *tcon,
2505 struct smb_com_ntransact_req *pSMB;
2507 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2511 *ret_buf = (void *)pSMB;
2513 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2514 pSMB->TotalDataCount = 0;
2515 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2516 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2517 pSMB->ParameterCount = pSMB->TotalParameterCount;
2518 pSMB->DataCount = pSMB->TotalDataCount;
2519 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2520 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2521 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2522 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2523 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2524 pSMB->SubCommand = cpu_to_le16(sub_command);
2529 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2530 __u32 *pparmlen, __u32 *pdatalen)
2533 __u32 data_count, data_offset, parm_count, parm_offset;
2534 struct smb_com_ntransact_rsp *pSMBr;
2542 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2544 /* ByteCount was converted from little endian in SendReceive */
2545 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2546 (char *)&pSMBr->ByteCount;
2548 data_offset = le32_to_cpu(pSMBr->DataOffset);
2549 data_count = le32_to_cpu(pSMBr->DataCount);
2550 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2551 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2553 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2554 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2556 /* should we also check that parm and data areas do not overlap? */
2557 if (*ppparm > end_of_smb) {
2558 cFYI(1, ("parms start after end of smb"));
2560 } else if (parm_count + *ppparm > end_of_smb) {
2561 cFYI(1, ("parm end after end of smb"));
2563 } else if (*ppdata > end_of_smb) {
2564 cFYI(1, ("data starts after end of smb"));
2566 } else if (data_count + *ppdata > end_of_smb) {
2567 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2568 *ppdata, data_count, (data_count + *ppdata),
2569 end_of_smb, pSMBr));
2571 } else if (parm_count + data_count > pSMBr->ByteCount) {
2572 cFYI(1, ("parm count and data count larger than SMB"));
2575 *pdatalen = data_count;
2576 *pparmlen = parm_count;
2581 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2582 const unsigned char *searchName,
2583 char *symlinkinfo, const int buflen, __u16 fid,
2584 const struct nls_table *nls_codepage)
2588 struct smb_com_transaction_ioctl_req *pSMB;
2589 struct smb_com_transaction_ioctl_rsp *pSMBr;
2591 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2592 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2597 pSMB->TotalParameterCount = 0 ;
2598 pSMB->TotalDataCount = 0;
2599 pSMB->MaxParameterCount = cpu_to_le32(2);
2600 /* BB find exact data count max from sess structure BB */
2601 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2602 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2603 pSMB->MaxSetupCount = 4;
2605 pSMB->ParameterOffset = 0;
2606 pSMB->DataCount = 0;
2607 pSMB->DataOffset = 0;
2608 pSMB->SetupCount = 4;
2609 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2610 pSMB->ParameterCount = pSMB->TotalParameterCount;
2611 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2612 pSMB->IsFsctl = 1; /* FSCTL */
2613 pSMB->IsRootFlag = 0;
2614 pSMB->Fid = fid; /* file handle always le */
2615 pSMB->ByteCount = 0;
2617 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2618 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2621 } else { /* decode response */
2622 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2623 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2624 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2625 /* BB also check enough total bytes returned */
2626 rc = -EIO; /* bad smb */
2629 if (data_count && (data_count < 2048)) {
2630 char *end_of_smb = 2 /* sizeof byte count */ +
2631 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2633 struct reparse_data *reparse_buf =
2634 (struct reparse_data *)
2635 ((char *)&pSMBr->hdr.Protocol
2637 if ((char *)reparse_buf >= end_of_smb) {
2641 if ((reparse_buf->LinkNamesBuf +
2642 reparse_buf->TargetNameOffset +
2643 reparse_buf->TargetNameLen) > end_of_smb) {
2644 cFYI(1, ("reparse buf beyond SMB"));
2649 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2650 cifs_from_ucs2(symlinkinfo, (__le16 *)
2651 (reparse_buf->LinkNamesBuf +
2652 reparse_buf->TargetNameOffset),
2654 reparse_buf->TargetNameLen,
2656 } else { /* ASCII names */
2657 strncpy(symlinkinfo,
2658 reparse_buf->LinkNamesBuf +
2659 reparse_buf->TargetNameOffset,
2660 min_t(const int, buflen,
2661 reparse_buf->TargetNameLen));
2665 cFYI(1, ("Invalid return data count on "
2666 "get reparse info ioctl"));
2668 symlinkinfo[buflen] = 0; /* just in case so the caller
2669 does not go off the end of the buffer */
2670 cFYI(1, ("readlink result - %s", symlinkinfo));
2674 cifs_buf_release(pSMB);
2676 /* Note: On -EAGAIN error only caller can retry on handle based calls
2677 since file handle passed in no longer valid */
2681 #endif /* CIFS_EXPERIMENTAL */
2683 #ifdef CONFIG_CIFS_POSIX
2685 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2686 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2687 struct cifs_posix_ace *cifs_ace)
2689 /* u8 cifs fields do not need le conversion */
2690 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2691 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2692 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2693 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2698 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2699 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2700 const int acl_type, const int size_of_data_area)
2705 struct cifs_posix_ace *pACE;
2706 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2707 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2709 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2712 if (acl_type & ACL_TYPE_ACCESS) {
2713 count = le16_to_cpu(cifs_acl->access_entry_count);
2714 pACE = &cifs_acl->ace_array[0];
2715 size = sizeof(struct cifs_posix_acl);
2716 size += sizeof(struct cifs_posix_ace) * count;
2717 /* check if we would go beyond end of SMB */
2718 if (size_of_data_area < size) {
2719 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2720 size_of_data_area, size));
2723 } else if (acl_type & ACL_TYPE_DEFAULT) {
2724 count = le16_to_cpu(cifs_acl->access_entry_count);
2725 size = sizeof(struct cifs_posix_acl);
2726 size += sizeof(struct cifs_posix_ace) * count;
2727 /* skip past access ACEs to get to default ACEs */
2728 pACE = &cifs_acl->ace_array[count];
2729 count = le16_to_cpu(cifs_acl->default_entry_count);
2730 size += sizeof(struct cifs_posix_ace) * count;
2731 /* check if we would go beyond end of SMB */
2732 if (size_of_data_area < size)
2739 size = posix_acl_xattr_size(count);
2740 if ((buflen == 0) || (local_acl == NULL)) {
2741 /* used to query ACL EA size */
2742 } else if (size > buflen) {
2744 } else /* buffer big enough */ {
2745 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2746 for (i = 0; i < count ; i++) {
2747 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2754 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2755 const posix_acl_xattr_entry *local_ace)
2757 __u16 rc = 0; /* 0 = ACL converted ok */
2759 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2760 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2761 /* BB is there a better way to handle the large uid? */
2762 if (local_ace->e_id == cpu_to_le32(-1)) {
2763 /* Probably no need to le convert -1 on any arch but can not hurt */
2764 cifs_ace->cifs_uid = cpu_to_le64(-1);
2766 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2767 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2771 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2772 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2773 const int buflen, const int acl_type)
2776 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2777 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2781 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2784 count = posix_acl_xattr_count((size_t)buflen);
2785 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2787 count, buflen, le32_to_cpu(local_acl->a_version)));
2788 if (le32_to_cpu(local_acl->a_version) != 2) {
2789 cFYI(1, ("unknown POSIX ACL version %d",
2790 le32_to_cpu(local_acl->a_version)));
2793 cifs_acl->version = cpu_to_le16(1);
2794 if (acl_type == ACL_TYPE_ACCESS)
2795 cifs_acl->access_entry_count = cpu_to_le16(count);
2796 else if (acl_type == ACL_TYPE_DEFAULT)
2797 cifs_acl->default_entry_count = cpu_to_le16(count);
2799 cFYI(1, ("unknown ACL type %d", acl_type));
2802 for (i = 0; i < count; i++) {
2803 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2804 &local_acl->a_entries[i]);
2806 /* ACE not converted */
2811 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2812 rc += sizeof(struct cifs_posix_acl);
2813 /* BB add check to make sure ACL does not overflow SMB */
2819 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2820 const unsigned char *searchName,
2821 char *acl_inf, const int buflen, const int acl_type,
2822 const struct nls_table *nls_codepage, int remap)
2824 /* SMB_QUERY_POSIX_ACL */
2825 TRANSACTION2_QPI_REQ *pSMB = NULL;
2826 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2830 __u16 params, byte_count;
2832 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2835 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2840 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2842 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2843 PATH_MAX, nls_codepage, remap);
2844 name_len++; /* trailing null */
2846 pSMB->FileName[name_len] = 0;
2847 pSMB->FileName[name_len+1] = 0;
2848 } else { /* BB improve the check for buffer overruns BB */
2849 name_len = strnlen(searchName, PATH_MAX);
2850 name_len++; /* trailing null */
2851 strncpy(pSMB->FileName, searchName, name_len);
2854 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2855 pSMB->TotalDataCount = 0;
2856 pSMB->MaxParameterCount = cpu_to_le16(2);
2857 /* BB find exact max data count below from sess structure BB */
2858 pSMB->MaxDataCount = cpu_to_le16(4000);
2859 pSMB->MaxSetupCount = 0;
2863 pSMB->Reserved2 = 0;
2864 pSMB->ParameterOffset = cpu_to_le16(
2865 offsetof(struct smb_com_transaction2_qpi_req,
2866 InformationLevel) - 4);
2867 pSMB->DataCount = 0;
2868 pSMB->DataOffset = 0;
2869 pSMB->SetupCount = 1;
2870 pSMB->Reserved3 = 0;
2871 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2872 byte_count = params + 1 /* pad */ ;
2873 pSMB->TotalParameterCount = cpu_to_le16(params);
2874 pSMB->ParameterCount = pSMB->TotalParameterCount;
2875 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2876 pSMB->Reserved4 = 0;
2877 pSMB->hdr.smb_buf_length += byte_count;
2878 pSMB->ByteCount = cpu_to_le16(byte_count);
2880 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2881 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2882 cifs_stats_inc(&tcon->num_acl_get);
2884 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2886 /* decode response */
2888 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2889 if (rc || (pSMBr->ByteCount < 2))
2890 /* BB also check enough total bytes returned */
2891 rc = -EIO; /* bad smb */
2893 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2894 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2895 rc = cifs_copy_posix_acl(acl_inf,
2896 (char *)&pSMBr->hdr.Protocol+data_offset,
2897 buflen, acl_type, count);
2900 cifs_buf_release(pSMB);
2907 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2908 const unsigned char *fileName,
2909 const char *local_acl, const int buflen,
2911 const struct nls_table *nls_codepage, int remap)
2913 struct smb_com_transaction2_spi_req *pSMB = NULL;
2914 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2918 int bytes_returned = 0;
2919 __u16 params, byte_count, data_count, param_offset, offset;
2921 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2923 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2927 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2929 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2930 PATH_MAX, nls_codepage, remap);
2931 name_len++; /* trailing null */
2933 } else { /* BB improve the check for buffer overruns BB */
2934 name_len = strnlen(fileName, PATH_MAX);
2935 name_len++; /* trailing null */
2936 strncpy(pSMB->FileName, fileName, name_len);
2938 params = 6 + name_len;
2939 pSMB->MaxParameterCount = cpu_to_le16(2);
2940 /* BB find max SMB size from sess */
2941 pSMB->MaxDataCount = cpu_to_le16(1000);
2942 pSMB->MaxSetupCount = 0;
2946 pSMB->Reserved2 = 0;
2947 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2948 InformationLevel) - 4;
2949 offset = param_offset + params;
2950 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2951 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2953 /* convert to on the wire format for POSIX ACL */
2954 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2956 if (data_count == 0) {
2958 goto setACLerrorExit;
2960 pSMB->DataOffset = cpu_to_le16(offset);
2961 pSMB->SetupCount = 1;
2962 pSMB->Reserved3 = 0;
2963 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2964 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2965 byte_count = 3 /* pad */ + params + data_count;
2966 pSMB->DataCount = cpu_to_le16(data_count);
2967 pSMB->TotalDataCount = pSMB->DataCount;
2968 pSMB->ParameterCount = cpu_to_le16(params);
2969 pSMB->TotalParameterCount = pSMB->ParameterCount;
2970 pSMB->Reserved4 = 0;
2971 pSMB->hdr.smb_buf_length += byte_count;
2972 pSMB->ByteCount = cpu_to_le16(byte_count);
2973 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2976 cFYI(1, ("Set POSIX ACL returned %d", rc));
2979 cifs_buf_release(pSMB);
2985 /* BB fix tabs in this function FIXME BB */
2987 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2988 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2991 struct smb_t2_qfi_req *pSMB = NULL;
2992 struct smb_t2_qfi_rsp *pSMBr = NULL;
2994 __u16 params, byte_count;
2996 cFYI(1, ("In GetExtAttr"));
3001 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3006 params = 2 /* level */ + 2 /* fid */;
3007 pSMB->t2.TotalDataCount = 0;
3008 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3009 /* BB find exact max data count below from sess structure BB */
3010 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3011 pSMB->t2.MaxSetupCount = 0;
3012 pSMB->t2.Reserved = 0;
3014 pSMB->t2.Timeout = 0;
3015 pSMB->t2.Reserved2 = 0;
3016 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3018 pSMB->t2.DataCount = 0;
3019 pSMB->t2.DataOffset = 0;
3020 pSMB->t2.SetupCount = 1;
3021 pSMB->t2.Reserved3 = 0;
3022 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3023 byte_count = params + 1 /* pad */ ;
3024 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3025 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3026 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3029 pSMB->hdr.smb_buf_length += byte_count;
3030 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3032 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3033 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3035 cFYI(1, ("error %d in GetExtAttr", rc));
3037 /* decode response */
3038 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3039 if (rc || (pSMBr->ByteCount < 2))
3040 /* BB also check enough total bytes returned */
3041 /* If rc should we check for EOPNOSUPP and
3042 disable the srvino flag? or in caller? */
3043 rc = -EIO; /* bad smb */
3045 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3046 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3047 struct file_chattr_info *pfinfo;
3048 /* BB Do we need a cast or hash here ? */
3050 cFYI(1, ("Illegal size ret in GetExtAttr"));
3054 pfinfo = (struct file_chattr_info *)
3055 (data_offset + (char *) &pSMBr->hdr.Protocol);
3056 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3057 *pMask = le64_to_cpu(pfinfo->mask);
3061 cifs_buf_release(pSMB);
3063 goto GetExtAttrRetry;
3067 #endif /* CONFIG_POSIX */
3069 #ifdef CONFIG_CIFS_EXPERIMENTAL
3070 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3072 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3073 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3077 QUERY_SEC_DESC_REQ *pSMB;
3080 cFYI(1, ("GetCifsACL"));
3085 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3086 8 /* parm len */, tcon, (void **) &pSMB);
3090 pSMB->MaxParameterCount = cpu_to_le32(4);
3091 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3092 pSMB->MaxSetupCount = 0;
3093 pSMB->Fid = fid; /* file handle always le */
3094 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3096 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3097 pSMB->hdr.smb_buf_length += 11;
3098 iov[0].iov_base = (char *)pSMB;
3099 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3101 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3103 cifs_stats_inc(&tcon->num_acl_get);
3105 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3106 } else { /* decode response */
3110 struct smb_com_ntransact_rsp *pSMBr;
3113 /* validate_nttransact */
3114 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3115 &pdata, &parm_len, pbuflen);
3118 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3120 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3122 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3123 rc = -EIO; /* bad smb */
3128 /* BB check that data area is minimum length and as big as acl_len */
3130 acl_len = le32_to_cpu(*parm);
3131 if (acl_len != *pbuflen) {
3132 cERROR(1, ("acl length %d does not match %d",
3133 acl_len, *pbuflen));
3134 if (*pbuflen > acl_len)
3138 /* check if buffer is big enough for the acl
3139 header followed by the smallest SID */
3140 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3141 (*pbuflen >= 64 * 1024)) {
3142 cERROR(1, ("bad acl length %d", *pbuflen));
3146 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3147 if (*acl_inf == NULL) {
3151 memcpy(*acl_inf, pdata, *pbuflen);
3155 if (buf_type == CIFS_SMALL_BUFFER)
3156 cifs_small_buf_release(iov[0].iov_base);
3157 else if (buf_type == CIFS_LARGE_BUFFER)
3158 cifs_buf_release(iov[0].iov_base);
3159 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3164 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3165 struct cifs_ntsd *pntsd, __u32 acllen)
3167 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3169 int bytes_returned = 0;
3170 SET_SEC_DESC_REQ *pSMB = NULL;
3171 NTRANSACT_RSP *pSMBr = NULL;
3174 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3179 pSMB->MaxSetupCount = 0;
3183 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3184 data_count = acllen;
3185 data_offset = param_offset + param_count;
3186 byte_count = 3 /* pad */ + param_count;
3188 pSMB->DataCount = cpu_to_le32(data_count);
3189 pSMB->TotalDataCount = pSMB->DataCount;
3190 pSMB->MaxParameterCount = cpu_to_le32(4);
3191 pSMB->MaxDataCount = cpu_to_le32(16384);
3192 pSMB->ParameterCount = cpu_to_le32(param_count);
3193 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3194 pSMB->TotalParameterCount = pSMB->ParameterCount;
3195 pSMB->DataOffset = cpu_to_le32(data_offset);
3196 pSMB->SetupCount = 0;
3197 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3198 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3200 pSMB->Fid = fid; /* file handle always le */
3201 pSMB->Reserved2 = 0;
3202 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3204 if (pntsd && acllen) {
3205 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3208 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3211 pSMB->hdr.smb_buf_length += byte_count;
3213 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3214 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3216 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3218 cFYI(1, ("Set CIFS ACL returned %d", rc));
3219 cifs_buf_release(pSMB);
3222 goto setCifsAclRetry;
3227 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3229 /* Legacy Query Path Information call for lookup to old servers such
3231 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3232 const unsigned char *searchName,
3233 FILE_ALL_INFO *pFinfo,
3234 const struct nls_table *nls_codepage, int remap)
3236 QUERY_INFORMATION_REQ *pSMB;
3237 QUERY_INFORMATION_RSP *pSMBr;
3242 cFYI(1, ("In SMBQPath path %s", searchName));
3244 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3249 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3251 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3252 PATH_MAX, nls_codepage, remap);
3253 name_len++; /* trailing null */
3256 name_len = strnlen(searchName, PATH_MAX);
3257 name_len++; /* trailing null */
3258 strncpy(pSMB->FileName, searchName, name_len);
3260 pSMB->BufferFormat = 0x04;
3261 name_len++; /* account for buffer type byte */
3262 pSMB->hdr.smb_buf_length += (__u16) name_len;
3263 pSMB->ByteCount = cpu_to_le16(name_len);
3265 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3266 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3268 cFYI(1, ("Send error in QueryInfo = %d", rc));
3269 } else if (pFinfo) {
3271 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3273 /* decode response */
3274 /* BB FIXME - add time zone adjustment BB */
3275 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3278 /* decode time fields */
3279 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3280 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3281 pFinfo->LastAccessTime = 0;
3282 pFinfo->AllocationSize =
3283 cpu_to_le64(le32_to_cpu(pSMBr->size));
3284 pFinfo->EndOfFile = pFinfo->AllocationSize;
3285 pFinfo->Attributes =
3286 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3288 rc = -EIO; /* bad buffer passed in */
3290 cifs_buf_release(pSMB);
3302 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3303 const unsigned char *searchName,
3304 FILE_ALL_INFO *pFindData,
3305 int legacy /* old style infolevel */,
3306 const struct nls_table *nls_codepage, int remap)
3308 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3309 TRANSACTION2_QPI_REQ *pSMB = NULL;
3310 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3314 __u16 params, byte_count;
3316 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3318 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3323 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3325 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3326 PATH_MAX, nls_codepage, remap);
3327 name_len++; /* trailing null */
3329 } else { /* BB improve the check for buffer overruns BB */
3330 name_len = strnlen(searchName, PATH_MAX);
3331 name_len++; /* trailing null */
3332 strncpy(pSMB->FileName, searchName, name_len);
3335 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3336 pSMB->TotalDataCount = 0;
3337 pSMB->MaxParameterCount = cpu_to_le16(2);
3338 /* BB find exact max SMB PDU from sess structure BB */
3339 pSMB->MaxDataCount = cpu_to_le16(4000);
3340 pSMB->MaxSetupCount = 0;
3344 pSMB->Reserved2 = 0;
3345 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3346 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3347 pSMB->DataCount = 0;
3348 pSMB->DataOffset = 0;
3349 pSMB->SetupCount = 1;
3350 pSMB->Reserved3 = 0;
3351 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3352 byte_count = params + 1 /* pad */ ;
3353 pSMB->TotalParameterCount = cpu_to_le16(params);
3354 pSMB->ParameterCount = pSMB->TotalParameterCount;
3356 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3358 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3359 pSMB->Reserved4 = 0;
3360 pSMB->hdr.smb_buf_length += byte_count;
3361 pSMB->ByteCount = cpu_to_le16(byte_count);
3363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3366 cFYI(1, ("Send error in QPathInfo = %d", rc));
3367 } else { /* decode response */
3368 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3370 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3372 else if (!legacy && (pSMBr->ByteCount < 40))
3373 rc = -EIO; /* bad smb */
3374 else if (legacy && (pSMBr->ByteCount < 24))
3375 rc = -EIO; /* 24 or 26 expected but we do not read
3377 else if (pFindData) {
3379 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3381 /* On legacy responses we do not read the last field,
3382 EAsize, fortunately since it varies by subdialect and
3383 also note it differs on Set vs. Get, ie two bytes or 4
3384 bytes depending but we don't care here */
3386 size = sizeof(FILE_INFO_STANDARD);
3388 size = sizeof(FILE_ALL_INFO);
3389 memcpy((char *) pFindData,
3390 (char *) &pSMBr->hdr.Protocol +
3395 cifs_buf_release(pSMB);
3397 goto QPathInfoRetry;
3403 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3404 const unsigned char *searchName,
3405 FILE_UNIX_BASIC_INFO *pFindData,
3406 const struct nls_table *nls_codepage, int remap)
3408 /* SMB_QUERY_FILE_UNIX_BASIC */
3409 TRANSACTION2_QPI_REQ *pSMB = NULL;
3410 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3412 int bytes_returned = 0;
3414 __u16 params, byte_count;
3416 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3418 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3423 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3425 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3426 PATH_MAX, nls_codepage, remap);
3427 name_len++; /* trailing null */
3429 } else { /* BB improve the check for buffer overruns BB */
3430 name_len = strnlen(searchName, PATH_MAX);
3431 name_len++; /* trailing null */
3432 strncpy(pSMB->FileName, searchName, name_len);
3435 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3436 pSMB->TotalDataCount = 0;
3437 pSMB->MaxParameterCount = cpu_to_le16(2);
3438 /* BB find exact max SMB PDU from sess structure BB */
3439 pSMB->MaxDataCount = cpu_to_le16(4000);
3440 pSMB->MaxSetupCount = 0;
3444 pSMB->Reserved2 = 0;
3445 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3446 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3447 pSMB->DataCount = 0;
3448 pSMB->DataOffset = 0;
3449 pSMB->SetupCount = 1;
3450 pSMB->Reserved3 = 0;
3451 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3452 byte_count = params + 1 /* pad */ ;
3453 pSMB->TotalParameterCount = cpu_to_le16(params);
3454 pSMB->ParameterCount = pSMB->TotalParameterCount;
3455 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3456 pSMB->Reserved4 = 0;
3457 pSMB->hdr.smb_buf_length += byte_count;
3458 pSMB->ByteCount = cpu_to_le16(byte_count);
3460 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3461 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3463 cFYI(1, ("Send error in QPathInfo = %d", rc));
3464 } else { /* decode response */
3465 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3467 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3468 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3469 "Unix Extensions can be disabled on mount "
3470 "by specifying the nosfu mount option."));
3471 rc = -EIO; /* bad smb */
3473 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3474 memcpy((char *) pFindData,
3475 (char *) &pSMBr->hdr.Protocol +
3477 sizeof(FILE_UNIX_BASIC_INFO));
3480 cifs_buf_release(pSMB);
3482 goto UnixQPathInfoRetry;
3487 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3489 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3490 const char *searchName,
3491 const struct nls_table *nls_codepage,
3493 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3495 /* level 257 SMB_ */
3496 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3497 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3498 T2_FFIRST_RSP_PARMS *parms;
3500 int bytes_returned = 0;
3502 __u16 params, byte_count;
3504 cFYI(1, ("In FindFirst for %s", searchName));
3507 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3512 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3514 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3515 PATH_MAX, nls_codepage, remap);
3516 /* We can not add the asterik earlier in case
3517 it got remapped to 0xF03A as if it were part of the
3518 directory name instead of a wildcard */
3520 pSMB->FileName[name_len] = dirsep;
3521 pSMB->FileName[name_len+1] = 0;
3522 pSMB->FileName[name_len+2] = '*';
3523 pSMB->FileName[name_len+3] = 0;
3524 name_len += 4; /* now the trailing null */
3525 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3526 pSMB->FileName[name_len+1] = 0;
3528 } else { /* BB add check for overrun of SMB buf BB */
3529 name_len = strnlen(searchName, PATH_MAX);
3530 /* BB fix here and in unicode clause above ie
3531 if (name_len > buffersize-header)
3532 free buffer exit; BB */
3533 strncpy(pSMB->FileName, searchName, name_len);
3534 pSMB->FileName[name_len] = dirsep;
3535 pSMB->FileName[name_len+1] = '*';
3536 pSMB->FileName[name_len+2] = 0;
3540 params = 12 + name_len /* includes null */ ;
3541 pSMB->TotalDataCount = 0; /* no EAs */
3542 pSMB->MaxParameterCount = cpu_to_le16(10);
3543 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3544 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3545 pSMB->MaxSetupCount = 0;
3549 pSMB->Reserved2 = 0;
3550 byte_count = params + 1 /* pad */ ;
3551 pSMB->TotalParameterCount = cpu_to_le16(params);
3552 pSMB->ParameterCount = pSMB->TotalParameterCount;
3553 pSMB->ParameterOffset = cpu_to_le16(
3554 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3556 pSMB->DataCount = 0;
3557 pSMB->DataOffset = 0;
3558 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3559 pSMB->Reserved3 = 0;
3560 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3561 pSMB->SearchAttributes =
3562 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3564 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3565 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3566 CIFS_SEARCH_RETURN_RESUME);
3567 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3569 /* BB what should we set StorageType to? Does it matter? BB */
3570 pSMB->SearchStorageType = 0;
3571 pSMB->hdr.smb_buf_length += byte_count;
3572 pSMB->ByteCount = cpu_to_le16(byte_count);
3574 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3575 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3576 cifs_stats_inc(&tcon->num_ffirst);
3578 if (rc) {/* BB add logic to retry regular search if Unix search
3579 rejected unexpectedly by server */
3580 /* BB Add code to handle unsupported level rc */
3581 cFYI(1, ("Error in FindFirst = %d", rc));
3583 cifs_buf_release(pSMB);
3585 /* BB eventually could optimize out free and realloc of buf */
3588 goto findFirstRetry;
3589 } else { /* decode response */
3590 /* BB remember to free buffer if error BB */
3591 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3595 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3596 psrch_inf->unicode = true;
3598 psrch_inf->unicode = false;
3600 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3601 psrch_inf->smallBuf = 0;
3602 psrch_inf->srch_entries_start =
3603 (char *) &pSMBr->hdr.Protocol +
3604 le16_to_cpu(pSMBr->t2.DataOffset);
3605 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3606 le16_to_cpu(pSMBr->t2.ParameterOffset));
3608 if (parms->EndofSearch)
3609 psrch_inf->endOfSearch = true;
3611 psrch_inf->endOfSearch = false;
3613 psrch_inf->entries_in_buffer =
3614 le16_to_cpu(parms->SearchCount);
3615 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3616 psrch_inf->entries_in_buffer;
3617 lnoff = le16_to_cpu(parms->LastNameOffset);
3618 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3620 cERROR(1, ("ignoring corrupt resume name"));
3621 psrch_inf->last_entry = NULL;
3625 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3628 *pnetfid = parms->SearchHandle;
3630 cifs_buf_release(pSMB);
3637 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3638 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3640 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3641 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3642 T2_FNEXT_RSP_PARMS *parms;
3643 char *response_data;
3645 int bytes_returned, name_len;
3646 __u16 params, byte_count;
3648 cFYI(1, ("In FindNext"));
3650 if (psrch_inf->endOfSearch)
3653 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3658 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3660 pSMB->TotalDataCount = 0; /* no EAs */
3661 pSMB->MaxParameterCount = cpu_to_le16(8);
3662 pSMB->MaxDataCount =
3663 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3665 pSMB->MaxSetupCount = 0;
3669 pSMB->Reserved2 = 0;
3670 pSMB->ParameterOffset = cpu_to_le16(
3671 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3672 pSMB->DataCount = 0;
3673 pSMB->DataOffset = 0;
3674 pSMB->SetupCount = 1;
3675 pSMB->Reserved3 = 0;
3676 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3677 pSMB->SearchHandle = searchHandle; /* always kept as le */
3679 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3680 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3681 pSMB->ResumeKey = psrch_inf->resume_key;
3683 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3685 name_len = psrch_inf->resume_name_len;
3687 if (name_len < PATH_MAX) {
3688 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3689 byte_count += name_len;
3690 /* 14 byte parm len above enough for 2 byte null terminator */
3691 pSMB->ResumeFileName[name_len] = 0;
3692 pSMB->ResumeFileName[name_len+1] = 0;
3695 goto FNext2_err_exit;
3697 byte_count = params + 1 /* pad */ ;
3698 pSMB->TotalParameterCount = cpu_to_le16(params);
3699 pSMB->ParameterCount = pSMB->TotalParameterCount;
3700 pSMB->hdr.smb_buf_length += byte_count;
3701 pSMB->ByteCount = cpu_to_le16(byte_count);
3703 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3704 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3705 cifs_stats_inc(&tcon->num_fnext);
3708 psrch_inf->endOfSearch = true;
3709 cifs_buf_release(pSMB);
3710 rc = 0; /* search probably was closed at end of search*/
3712 cFYI(1, ("FindNext returned = %d", rc));
3713 } else { /* decode response */
3714 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3719 /* BB fixme add lock for file (srch_info) struct here */
3720 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3721 psrch_inf->unicode = true;
3723 psrch_inf->unicode = false;
3724 response_data = (char *) &pSMBr->hdr.Protocol +
3725 le16_to_cpu(pSMBr->t2.ParameterOffset);
3726 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3727 response_data = (char *)&pSMBr->hdr.Protocol +
3728 le16_to_cpu(pSMBr->t2.DataOffset);
3729 if (psrch_inf->smallBuf)
3730 cifs_small_buf_release(
3731 psrch_inf->ntwrk_buf_start);
3733 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3734 psrch_inf->srch_entries_start = response_data;
3735 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3736 psrch_inf->smallBuf = 0;
3737 if (parms->EndofSearch)
3738 psrch_inf->endOfSearch = true;
3740 psrch_inf->endOfSearch = false;
3741 psrch_inf->entries_in_buffer =
3742 le16_to_cpu(parms->SearchCount);
3743 psrch_inf->index_of_last_entry +=
3744 psrch_inf->entries_in_buffer;
3745 lnoff = le16_to_cpu(parms->LastNameOffset);
3746 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3748 cERROR(1, ("ignoring corrupt resume name"));
3749 psrch_inf->last_entry = NULL;
3752 psrch_inf->last_entry =
3753 psrch_inf->srch_entries_start + lnoff;
3755 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3756 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3758 /* BB fixme add unlock here */
3763 /* BB On error, should we leave previous search buf (and count and
3764 last entry fields) intact or free the previous one? */
3766 /* Note: On -EAGAIN error only caller can retry on handle based calls
3767 since file handle passed in no longer valid */
3770 cifs_buf_release(pSMB);
3775 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3776 const __u16 searchHandle)
3779 FINDCLOSE_REQ *pSMB = NULL;
3781 cFYI(1, ("In CIFSSMBFindClose"));
3782 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3784 /* no sense returning error if session restarted
3785 as file handle has been closed */
3791 pSMB->FileID = searchHandle;
3792 pSMB->ByteCount = 0;
3793 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3795 cERROR(1, ("Send error in FindClose = %d", rc));
3797 cifs_stats_inc(&tcon->num_fclose);
3799 /* Since session is dead, search handle closed on server already */
3807 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3808 const unsigned char *searchName,
3809 __u64 *inode_number,
3810 const struct nls_table *nls_codepage, int remap)
3813 TRANSACTION2_QPI_REQ *pSMB = NULL;
3814 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3815 int name_len, bytes_returned;
3816 __u16 params, byte_count;
3818 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3822 GetInodeNumberRetry:
3823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3830 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3831 PATH_MAX, nls_codepage, remap);
3832 name_len++; /* trailing null */
3834 } else { /* BB improve the check for buffer overruns BB */
3835 name_len = strnlen(searchName, PATH_MAX);
3836 name_len++; /* trailing null */
3837 strncpy(pSMB->FileName, searchName, name_len);
3840 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3841 pSMB->TotalDataCount = 0;
3842 pSMB->MaxParameterCount = cpu_to_le16(2);
3843 /* BB find exact max data count below from sess structure BB */
3844 pSMB->MaxDataCount = cpu_to_le16(4000);
3845 pSMB->MaxSetupCount = 0;
3849 pSMB->Reserved2 = 0;
3850 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3851 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3852 pSMB->DataCount = 0;
3853 pSMB->DataOffset = 0;
3854 pSMB->SetupCount = 1;
3855 pSMB->Reserved3 = 0;
3856 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3857 byte_count = params + 1 /* pad */ ;
3858 pSMB->TotalParameterCount = cpu_to_le16(params);
3859 pSMB->ParameterCount = pSMB->TotalParameterCount;
3860 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3861 pSMB->Reserved4 = 0;
3862 pSMB->hdr.smb_buf_length += byte_count;
3863 pSMB->ByteCount = cpu_to_le16(byte_count);
3865 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3866 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3868 cFYI(1, ("error %d in QueryInternalInfo", rc));
3870 /* decode response */
3871 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3872 if (rc || (pSMBr->ByteCount < 2))
3873 /* BB also check enough total bytes returned */
3874 /* If rc should we check for EOPNOSUPP and
3875 disable the srvino flag? or in caller? */
3876 rc = -EIO; /* bad smb */
3878 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3879 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3880 struct file_internal_info *pfinfo;
3881 /* BB Do we need a cast or hash here ? */
3883 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3885 goto GetInodeNumOut;
3887 pfinfo = (struct file_internal_info *)
3888 (data_offset + (char *) &pSMBr->hdr.Protocol);
3889 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3893 cifs_buf_release(pSMB);
3895 goto GetInodeNumberRetry;
3899 /* parses DFS refferal V3 structure
3900 * caller is responsible for freeing target_nodes
3903 * on failure - errno
3906 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3907 unsigned int *num_of_nodes,
3908 struct dfs_info3_param **target_nodes,
3909 const struct nls_table *nls_codepage, int remap,
3910 const char *searchName)
3915 struct dfs_referral_level_3 *ref;
3917 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3921 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3923 if (*num_of_nodes < 1) {
3924 cERROR(1, ("num_referrals: must be at least > 0,"
3925 "but we get num_referrals = %d\n", *num_of_nodes));
3927 goto parse_DFS_referrals_exit;
3930 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3931 if (ref->VersionNumber != cpu_to_le16(3)) {
3932 cERROR(1, ("Referrals of V%d version are not supported,"
3933 "should be V3", le16_to_cpu(ref->VersionNumber)));
3935 goto parse_DFS_referrals_exit;
3938 /* get the upper boundary of the resp buffer */
3939 data_end = (char *)(&(pSMBr->PathConsumed)) +
3940 le16_to_cpu(pSMBr->t2.DataCount);
3942 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3944 le32_to_cpu(pSMBr->DFSFlags)));
3946 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3947 *num_of_nodes, GFP_KERNEL);
3948 if (*target_nodes == NULL) {
3949 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3951 goto parse_DFS_referrals_exit;
3954 /* collect neccessary data from referrals */
3955 for (i = 0; i < *num_of_nodes; i++) {
3958 struct dfs_info3_param *node = (*target_nodes)+i;
3960 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3962 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3966 goto parse_DFS_referrals_exit;
3968 cifsConvertToUCS((__le16 *) tmp, searchName,
3969 PATH_MAX, nls_codepage, remap);
3970 node->path_consumed = cifs_ucs2_bytes(tmp,
3971 le16_to_cpu(pSMBr->PathConsumed),
3975 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3977 node->server_type = le16_to_cpu(ref->ServerType);
3978 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3981 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3982 max_len = data_end - temp;
3983 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3984 is_unicode, nls_codepage);
3985 if (!node->path_name) {
3987 goto parse_DFS_referrals_exit;
3990 /* copy link target UNC */
3991 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3992 max_len = data_end - temp;
3993 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3994 is_unicode, nls_codepage);
3995 if (!node->node_name)
3999 parse_DFS_referrals_exit:
4001 free_dfs_info_array(*target_nodes, *num_of_nodes);
4002 *target_nodes = NULL;
4009 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4010 const unsigned char *searchName,
4011 struct dfs_info3_param **target_nodes,
4012 unsigned int *num_of_nodes,
4013 const struct nls_table *nls_codepage, int remap)
4015 /* TRANS2_GET_DFS_REFERRAL */
4016 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4017 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4021 __u16 params, byte_count;
4023 *target_nodes = NULL;
4025 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4029 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4034 /* server pointer checked in called function,
4035 but should never be null here anyway */
4036 pSMB->hdr.Mid = GetNextMid(ses->server);
4037 pSMB->hdr.Tid = ses->ipc_tid;
4038 pSMB->hdr.Uid = ses->Suid;
4039 if (ses->capabilities & CAP_STATUS32)
4040 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4041 if (ses->capabilities & CAP_DFS)
4042 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4044 if (ses->capabilities & CAP_UNICODE) {
4045 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4047 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4048 searchName, PATH_MAX, nls_codepage, remap);
4049 name_len++; /* trailing null */
4051 } else { /* BB improve the check for buffer overruns BB */
4052 name_len = strnlen(searchName, PATH_MAX);
4053 name_len++; /* trailing null */
4054 strncpy(pSMB->RequestFileName, searchName, name_len);
4058 if (ses->server->secMode &
4059 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4060 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4063 pSMB->hdr.Uid = ses->Suid;
4065 params = 2 /* level */ + name_len /*includes null */ ;
4066 pSMB->TotalDataCount = 0;
4067 pSMB->DataCount = 0;
4068 pSMB->DataOffset = 0;
4069 pSMB->MaxParameterCount = 0;
4070 /* BB find exact max SMB PDU from sess structure BB */
4071 pSMB->MaxDataCount = cpu_to_le16(4000);
4072 pSMB->MaxSetupCount = 0;
4076 pSMB->Reserved2 = 0;
4077 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4078 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4079 pSMB->SetupCount = 1;
4080 pSMB->Reserved3 = 0;
4081 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4082 byte_count = params + 3 /* pad */ ;
4083 pSMB->ParameterCount = cpu_to_le16(params);
4084 pSMB->TotalParameterCount = pSMB->ParameterCount;
4085 pSMB->MaxReferralLevel = cpu_to_le16(3);
4086 pSMB->hdr.smb_buf_length += byte_count;
4087 pSMB->ByteCount = cpu_to_le16(byte_count);
4089 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4090 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4092 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4095 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4097 /* BB Also check if enough total bytes returned? */
4098 if (rc || (pSMBr->ByteCount < 17)) {
4099 rc = -EIO; /* bad smb */
4103 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4105 le16_to_cpu(pSMBr->t2.DataOffset)));
4107 /* parse returned result into more usable form */
4108 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4109 target_nodes, nls_codepage, remap,
4113 cifs_buf_release(pSMB);
4121 /* Query File System Info such as free space to old servers such as Win 9x */
4123 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4125 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4126 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4127 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4128 FILE_SYSTEM_ALLOC_INFO *response_data;
4130 int bytes_returned = 0;
4131 __u16 params, byte_count;
4133 cFYI(1, ("OldQFSInfo"));
4135 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4140 params = 2; /* level */
4141 pSMB->TotalDataCount = 0;
4142 pSMB->MaxParameterCount = cpu_to_le16(2);
4143 pSMB->MaxDataCount = cpu_to_le16(1000);
4144 pSMB->MaxSetupCount = 0;
4148 pSMB->Reserved2 = 0;
4149 byte_count = params + 1 /* pad */ ;
4150 pSMB->TotalParameterCount = cpu_to_le16(params);
4151 pSMB->ParameterCount = pSMB->TotalParameterCount;
4152 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4153 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4154 pSMB->DataCount = 0;
4155 pSMB->DataOffset = 0;
4156 pSMB->SetupCount = 1;
4157 pSMB->Reserved3 = 0;
4158 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4159 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4160 pSMB->hdr.smb_buf_length += byte_count;
4161 pSMB->ByteCount = cpu_to_le16(byte_count);
4163 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4164 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4166 cFYI(1, ("Send error in QFSInfo = %d", rc));
4167 } else { /* decode response */
4168 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4170 if (rc || (pSMBr->ByteCount < 18))
4171 rc = -EIO; /* bad smb */
4173 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4174 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4175 pSMBr->ByteCount, data_offset));
4177 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4178 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4180 le16_to_cpu(response_data->BytesPerSector) *
4181 le32_to_cpu(response_data->
4182 SectorsPerAllocationUnit);
4184 le32_to_cpu(response_data->TotalAllocationUnits);
4185 FSData->f_bfree = FSData->f_bavail =
4186 le32_to_cpu(response_data->FreeAllocationUnits);
4188 ("Blocks: %lld Free: %lld Block size %ld",
4189 (unsigned long long)FSData->f_blocks,
4190 (unsigned long long)FSData->f_bfree,
4194 cifs_buf_release(pSMB);
4197 goto oldQFSInfoRetry;
4203 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4205 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4206 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4207 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4208 FILE_SYSTEM_INFO *response_data;
4210 int bytes_returned = 0;
4211 __u16 params, byte_count;
4213 cFYI(1, ("In QFSInfo"));
4215 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4220 params = 2; /* level */
4221 pSMB->TotalDataCount = 0;
4222 pSMB->MaxParameterCount = cpu_to_le16(2);
4223 pSMB->MaxDataCount = cpu_to_le16(1000);
4224 pSMB->MaxSetupCount = 0;
4228 pSMB->Reserved2 = 0;
4229 byte_count = params + 1 /* pad */ ;
4230 pSMB->TotalParameterCount = cpu_to_le16(params);
4231 pSMB->ParameterCount = pSMB->TotalParameterCount;
4232 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4233 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4234 pSMB->DataCount = 0;
4235 pSMB->DataOffset = 0;
4236 pSMB->SetupCount = 1;
4237 pSMB->Reserved3 = 0;
4238 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4239 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4240 pSMB->hdr.smb_buf_length += byte_count;
4241 pSMB->ByteCount = cpu_to_le16(byte_count);
4243 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4244 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4246 cFYI(1, ("Send error in QFSInfo = %d", rc));
4247 } else { /* decode response */
4248 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4250 if (rc || (pSMBr->ByteCount < 24))
4251 rc = -EIO; /* bad smb */
4253 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4257 *) (((char *) &pSMBr->hdr.Protocol) +
4260 le32_to_cpu(response_data->BytesPerSector) *
4261 le32_to_cpu(response_data->
4262 SectorsPerAllocationUnit);
4264 le64_to_cpu(response_data->TotalAllocationUnits);
4265 FSData->f_bfree = FSData->f_bavail =
4266 le64_to_cpu(response_data->FreeAllocationUnits);
4268 ("Blocks: %lld Free: %lld Block size %ld",
4269 (unsigned long long)FSData->f_blocks,
4270 (unsigned long long)FSData->f_bfree,
4274 cifs_buf_release(pSMB);
4283 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4285 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4286 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4287 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4288 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4290 int bytes_returned = 0;
4291 __u16 params, byte_count;
4293 cFYI(1, ("In QFSAttributeInfo"));
4295 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4300 params = 2; /* level */
4301 pSMB->TotalDataCount = 0;
4302 pSMB->MaxParameterCount = cpu_to_le16(2);
4303 /* BB find exact max SMB PDU from sess structure BB */
4304 pSMB->MaxDataCount = cpu_to_le16(1000);
4305 pSMB->MaxSetupCount = 0;
4309 pSMB->Reserved2 = 0;
4310 byte_count = params + 1 /* pad */ ;
4311 pSMB->TotalParameterCount = cpu_to_le16(params);
4312 pSMB->ParameterCount = pSMB->TotalParameterCount;
4313 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4314 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4315 pSMB->DataCount = 0;
4316 pSMB->DataOffset = 0;
4317 pSMB->SetupCount = 1;
4318 pSMB->Reserved3 = 0;
4319 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4320 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4321 pSMB->hdr.smb_buf_length += byte_count;
4322 pSMB->ByteCount = cpu_to_le16(byte_count);
4324 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4325 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4327 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4328 } else { /* decode response */
4329 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4331 if (rc || (pSMBr->ByteCount < 13)) {
4332 /* BB also check if enough bytes returned */
4333 rc = -EIO; /* bad smb */
4335 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4337 (FILE_SYSTEM_ATTRIBUTE_INFO
4338 *) (((char *) &pSMBr->hdr.Protocol) +
4340 memcpy(&tcon->fsAttrInfo, response_data,
4341 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4344 cifs_buf_release(pSMB);
4347 goto QFSAttributeRetry;
4353 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4355 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4356 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4357 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4358 FILE_SYSTEM_DEVICE_INFO *response_data;
4360 int bytes_returned = 0;
4361 __u16 params, byte_count;
4363 cFYI(1, ("In QFSDeviceInfo"));
4365 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4370 params = 2; /* level */
4371 pSMB->TotalDataCount = 0;
4372 pSMB->MaxParameterCount = cpu_to_le16(2);
4373 /* BB find exact max SMB PDU from sess structure BB */
4374 pSMB->MaxDataCount = cpu_to_le16(1000);
4375 pSMB->MaxSetupCount = 0;
4379 pSMB->Reserved2 = 0;
4380 byte_count = params + 1 /* pad */ ;
4381 pSMB->TotalParameterCount = cpu_to_le16(params);
4382 pSMB->ParameterCount = pSMB->TotalParameterCount;
4383 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4384 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4386 pSMB->DataCount = 0;
4387 pSMB->DataOffset = 0;
4388 pSMB->SetupCount = 1;
4389 pSMB->Reserved3 = 0;
4390 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4391 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4392 pSMB->hdr.smb_buf_length += byte_count;
4393 pSMB->ByteCount = cpu_to_le16(byte_count);
4395 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4396 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4398 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4399 } else { /* decode response */
4400 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4402 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4403 rc = -EIO; /* bad smb */
4405 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4407 (FILE_SYSTEM_DEVICE_INFO *)
4408 (((char *) &pSMBr->hdr.Protocol) +
4410 memcpy(&tcon->fsDevInfo, response_data,
4411 sizeof(FILE_SYSTEM_DEVICE_INFO));
4414 cifs_buf_release(pSMB);
4417 goto QFSDeviceRetry;
4423 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4425 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4426 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4427 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4428 FILE_SYSTEM_UNIX_INFO *response_data;
4430 int bytes_returned = 0;
4431 __u16 params, byte_count;
4433 cFYI(1, ("In QFSUnixInfo"));
4435 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4440 params = 2; /* level */
4441 pSMB->TotalDataCount = 0;
4442 pSMB->DataCount = 0;
4443 pSMB->DataOffset = 0;
4444 pSMB->MaxParameterCount = cpu_to_le16(2);
4445 /* BB find exact max SMB PDU from sess structure BB */
4446 pSMB->MaxDataCount = cpu_to_le16(100);
4447 pSMB->MaxSetupCount = 0;
4451 pSMB->Reserved2 = 0;
4452 byte_count = params + 1 /* pad */ ;
4453 pSMB->ParameterCount = cpu_to_le16(params);
4454 pSMB->TotalParameterCount = pSMB->ParameterCount;
4455 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4456 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4457 pSMB->SetupCount = 1;
4458 pSMB->Reserved3 = 0;
4459 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4460 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4461 pSMB->hdr.smb_buf_length += byte_count;
4462 pSMB->ByteCount = cpu_to_le16(byte_count);
4464 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4465 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4467 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4468 } else { /* decode response */
4469 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4471 if (rc || (pSMBr->ByteCount < 13)) {
4472 rc = -EIO; /* bad smb */
4474 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4476 (FILE_SYSTEM_UNIX_INFO
4477 *) (((char *) &pSMBr->hdr.Protocol) +
4479 memcpy(&tcon->fsUnixInfo, response_data,
4480 sizeof(FILE_SYSTEM_UNIX_INFO));
4483 cifs_buf_release(pSMB);
4493 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4495 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4496 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4497 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4499 int bytes_returned = 0;
4500 __u16 params, param_offset, offset, byte_count;
4502 cFYI(1, ("In SETFSUnixInfo"));
4504 /* BB switch to small buf init to save memory */
4505 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4510 params = 4; /* 2 bytes zero followed by info level. */
4511 pSMB->MaxSetupCount = 0;
4515 pSMB->Reserved2 = 0;
4516 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4518 offset = param_offset + params;
4520 pSMB->MaxParameterCount = cpu_to_le16(4);
4521 /* BB find exact max SMB PDU from sess structure BB */
4522 pSMB->MaxDataCount = cpu_to_le16(100);
4523 pSMB->SetupCount = 1;
4524 pSMB->Reserved3 = 0;
4525 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4526 byte_count = 1 /* pad */ + params + 12;
4528 pSMB->DataCount = cpu_to_le16(12);
4529 pSMB->ParameterCount = cpu_to_le16(params);
4530 pSMB->TotalDataCount = pSMB->DataCount;
4531 pSMB->TotalParameterCount = pSMB->ParameterCount;
4532 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4533 pSMB->DataOffset = cpu_to_le16(offset);
4537 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4540 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4541 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4542 pSMB->ClientUnixCap = cpu_to_le64(cap);
4544 pSMB->hdr.smb_buf_length += byte_count;
4545 pSMB->ByteCount = cpu_to_le16(byte_count);
4547 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4548 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4550 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4551 } else { /* decode response */
4552 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4554 rc = -EIO; /* bad smb */
4556 cifs_buf_release(pSMB);
4559 goto SETFSUnixRetry;
4567 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4568 struct kstatfs *FSData)
4570 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4571 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4572 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4573 FILE_SYSTEM_POSIX_INFO *response_data;
4575 int bytes_returned = 0;
4576 __u16 params, byte_count;
4578 cFYI(1, ("In QFSPosixInfo"));
4580 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4585 params = 2; /* level */
4586 pSMB->TotalDataCount = 0;
4587 pSMB->DataCount = 0;
4588 pSMB->DataOffset = 0;
4589 pSMB->MaxParameterCount = cpu_to_le16(2);
4590 /* BB find exact max SMB PDU from sess structure BB */
4591 pSMB->MaxDataCount = cpu_to_le16(100);
4592 pSMB->MaxSetupCount = 0;
4596 pSMB->Reserved2 = 0;
4597 byte_count = params + 1 /* pad */ ;
4598 pSMB->ParameterCount = cpu_to_le16(params);
4599 pSMB->TotalParameterCount = pSMB->ParameterCount;
4600 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4601 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4602 pSMB->SetupCount = 1;
4603 pSMB->Reserved3 = 0;
4604 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4605 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4606 pSMB->hdr.smb_buf_length += byte_count;
4607 pSMB->ByteCount = cpu_to_le16(byte_count);
4609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4610 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4612 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4613 } else { /* decode response */
4614 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4616 if (rc || (pSMBr->ByteCount < 13)) {
4617 rc = -EIO; /* bad smb */
4619 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4621 (FILE_SYSTEM_POSIX_INFO
4622 *) (((char *) &pSMBr->hdr.Protocol) +
4625 le32_to_cpu(response_data->BlockSize);
4627 le64_to_cpu(response_data->TotalBlocks);
4629 le64_to_cpu(response_data->BlocksAvail);
4630 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4631 FSData->f_bavail = FSData->f_bfree;
4634 le64_to_cpu(response_data->UserBlocksAvail);
4636 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4638 le64_to_cpu(response_data->TotalFileNodes);
4639 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4641 le64_to_cpu(response_data->FreeFileNodes);
4644 cifs_buf_release(pSMB);
4653 /* We can not use write of zero bytes trick to
4654 set file size due to need for large file support. Also note that
4655 this SetPathInfo is preferred to SetFileInfo based method in next
4656 routine which is only needed to work around a sharing violation bug
4657 in Samba which this routine can run into */
4660 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4661 __u64 size, bool SetAllocation,
4662 const struct nls_table *nls_codepage, int remap)
4664 struct smb_com_transaction2_spi_req *pSMB = NULL;
4665 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4666 struct file_end_of_file_info *parm_data;
4669 int bytes_returned = 0;
4670 __u16 params, byte_count, data_count, param_offset, offset;
4672 cFYI(1, ("In SetEOF"));
4674 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4679 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4681 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4682 PATH_MAX, nls_codepage, remap);
4683 name_len++; /* trailing null */
4685 } else { /* BB improve the check for buffer overruns BB */
4686 name_len = strnlen(fileName, PATH_MAX);
4687 name_len++; /* trailing null */
4688 strncpy(pSMB->FileName, fileName, name_len);
4690 params = 6 + name_len;
4691 data_count = sizeof(struct file_end_of_file_info);
4692 pSMB->MaxParameterCount = cpu_to_le16(2);
4693 pSMB->MaxDataCount = cpu_to_le16(4100);
4694 pSMB->MaxSetupCount = 0;
4698 pSMB->Reserved2 = 0;
4699 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4700 InformationLevel) - 4;
4701 offset = param_offset + params;
4702 if (SetAllocation) {
4703 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4704 pSMB->InformationLevel =
4705 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4707 pSMB->InformationLevel =
4708 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4709 } else /* Set File Size */ {
4710 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4711 pSMB->InformationLevel =
4712 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4714 pSMB->InformationLevel =
4715 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4719 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4721 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4722 pSMB->DataOffset = cpu_to_le16(offset);
4723 pSMB->SetupCount = 1;
4724 pSMB->Reserved3 = 0;
4725 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4726 byte_count = 3 /* pad */ + params + data_count;
4727 pSMB->DataCount = cpu_to_le16(data_count);
4728 pSMB->TotalDataCount = pSMB->DataCount;
4729 pSMB->ParameterCount = cpu_to_le16(params);
4730 pSMB->TotalParameterCount = pSMB->ParameterCount;
4731 pSMB->Reserved4 = 0;
4732 pSMB->hdr.smb_buf_length += byte_count;
4733 parm_data->FileSize = cpu_to_le64(size);
4734 pSMB->ByteCount = cpu_to_le16(byte_count);
4735 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4736 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4738 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4740 cifs_buf_release(pSMB);
4749 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4750 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4752 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4754 struct file_end_of_file_info *parm_data;
4756 __u16 params, param_offset, offset, byte_count, count;
4758 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4760 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4765 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4766 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4769 pSMB->MaxSetupCount = 0;
4773 pSMB->Reserved2 = 0;
4774 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4775 offset = param_offset + params;
4777 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4779 count = sizeof(struct file_end_of_file_info);
4780 pSMB->MaxParameterCount = cpu_to_le16(2);
4781 /* BB find exact max SMB PDU from sess structure BB */
4782 pSMB->MaxDataCount = cpu_to_le16(1000);
4783 pSMB->SetupCount = 1;
4784 pSMB->Reserved3 = 0;
4785 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4786 byte_count = 3 /* pad */ + params + count;
4787 pSMB->DataCount = cpu_to_le16(count);
4788 pSMB->ParameterCount = cpu_to_le16(params);
4789 pSMB->TotalDataCount = pSMB->DataCount;
4790 pSMB->TotalParameterCount = pSMB->ParameterCount;
4791 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4793 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4795 pSMB->DataOffset = cpu_to_le16(offset);
4796 parm_data->FileSize = cpu_to_le64(size);
4798 if (SetAllocation) {
4799 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4800 pSMB->InformationLevel =
4801 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4803 pSMB->InformationLevel =
4804 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4805 } else /* Set File Size */ {
4806 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4807 pSMB->InformationLevel =
4808 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4810 pSMB->InformationLevel =
4811 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4813 pSMB->Reserved4 = 0;
4814 pSMB->hdr.smb_buf_length += byte_count;
4815 pSMB->ByteCount = cpu_to_le16(byte_count);
4816 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4819 ("Send error in SetFileInfo (SetFileSize) = %d",
4823 /* Note: On -EAGAIN error only caller can retry on handle based calls
4824 since file handle passed in no longer valid */
4829 /* Some legacy servers such as NT4 require that the file times be set on
4830 an open handle, rather than by pathname - this is awkward due to
4831 potential access conflicts on the open, but it is unavoidable for these
4832 old servers since the only other choice is to go from 100 nanosecond DCE
4833 time and resort to the original setpathinfo level which takes the ancient
4834 DOS time format with 2 second granularity */
4836 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4837 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4839 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4842 __u16 params, param_offset, offset, byte_count, count;
4844 cFYI(1, ("Set Times (via SetFileInfo)"));
4845 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4850 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4851 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4854 pSMB->MaxSetupCount = 0;
4858 pSMB->Reserved2 = 0;
4859 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4860 offset = param_offset + params;
4862 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4864 count = sizeof(FILE_BASIC_INFO);
4865 pSMB->MaxParameterCount = cpu_to_le16(2);
4866 /* BB find max SMB PDU from sess */
4867 pSMB->MaxDataCount = cpu_to_le16(1000);
4868 pSMB->SetupCount = 1;
4869 pSMB->Reserved3 = 0;
4870 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4871 byte_count = 3 /* pad */ + params + count;
4872 pSMB->DataCount = cpu_to_le16(count);
4873 pSMB->ParameterCount = cpu_to_le16(params);
4874 pSMB->TotalDataCount = pSMB->DataCount;
4875 pSMB->TotalParameterCount = pSMB->ParameterCount;
4876 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4877 pSMB->DataOffset = cpu_to_le16(offset);
4879 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4880 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4882 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4883 pSMB->Reserved4 = 0;
4884 pSMB->hdr.smb_buf_length += byte_count;
4885 pSMB->ByteCount = cpu_to_le16(byte_count);
4886 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4887 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4889 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4891 /* Note: On -EAGAIN error only caller can retry on handle based calls
4892 since file handle passed in no longer valid */
4898 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4899 bool delete_file, __u16 fid, __u32 pid_of_opener)
4901 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4904 __u16 params, param_offset, offset, byte_count, count;
4906 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4907 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4912 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4913 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4916 pSMB->MaxSetupCount = 0;
4920 pSMB->Reserved2 = 0;
4921 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4922 offset = param_offset + params;
4924 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4927 pSMB->MaxParameterCount = cpu_to_le16(2);
4928 /* BB find max SMB PDU from sess */
4929 pSMB->MaxDataCount = cpu_to_le16(1000);
4930 pSMB->SetupCount = 1;
4931 pSMB->Reserved3 = 0;
4932 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4933 byte_count = 3 /* pad */ + params + count;
4934 pSMB->DataCount = cpu_to_le16(count);
4935 pSMB->ParameterCount = cpu_to_le16(params);
4936 pSMB->TotalDataCount = pSMB->DataCount;
4937 pSMB->TotalParameterCount = pSMB->ParameterCount;
4938 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4939 pSMB->DataOffset = cpu_to_le16(offset);
4941 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4942 pSMB->Reserved4 = 0;
4943 pSMB->hdr.smb_buf_length += byte_count;
4944 pSMB->ByteCount = cpu_to_le16(byte_count);
4945 *data_offset = delete_file ? 1 : 0;
4946 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4948 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4954 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4955 const char *fileName, const FILE_BASIC_INFO *data,
4956 const struct nls_table *nls_codepage, int remap)
4958 TRANSACTION2_SPI_REQ *pSMB = NULL;
4959 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4962 int bytes_returned = 0;
4964 __u16 params, param_offset, offset, byte_count, count;
4966 cFYI(1, ("In SetTimes"));
4969 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4974 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4976 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4977 PATH_MAX, nls_codepage, remap);
4978 name_len++; /* trailing null */
4980 } else { /* BB improve the check for buffer overruns BB */
4981 name_len = strnlen(fileName, PATH_MAX);
4982 name_len++; /* trailing null */
4983 strncpy(pSMB->FileName, fileName, name_len);
4986 params = 6 + name_len;
4987 count = sizeof(FILE_BASIC_INFO);
4988 pSMB->MaxParameterCount = cpu_to_le16(2);
4989 /* BB find max SMB PDU from sess structure BB */
4990 pSMB->MaxDataCount = cpu_to_le16(1000);
4991 pSMB->MaxSetupCount = 0;
4995 pSMB->Reserved2 = 0;
4996 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4997 InformationLevel) - 4;
4998 offset = param_offset + params;
4999 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5000 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5001 pSMB->DataOffset = cpu_to_le16(offset);
5002 pSMB->SetupCount = 1;
5003 pSMB->Reserved3 = 0;
5004 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5005 byte_count = 3 /* pad */ + params + count;
5007 pSMB->DataCount = cpu_to_le16(count);
5008 pSMB->ParameterCount = cpu_to_le16(params);
5009 pSMB->TotalDataCount = pSMB->DataCount;
5010 pSMB->TotalParameterCount = pSMB->ParameterCount;
5011 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5012 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5014 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5015 pSMB->Reserved4 = 0;
5016 pSMB->hdr.smb_buf_length += byte_count;
5017 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5018 pSMB->ByteCount = cpu_to_le16(byte_count);
5019 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5020 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5022 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5024 cifs_buf_release(pSMB);
5032 /* Can not be used to set time stamps yet (due to old DOS time format) */
5033 /* Can be used to set attributes */
5034 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5035 handling it anyway and NT4 was what we thought it would be needed for
5036 Do not delete it until we prove whether needed for Win9x though */
5038 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5039 __u16 dos_attrs, const struct nls_table *nls_codepage)
5041 SETATTR_REQ *pSMB = NULL;
5042 SETATTR_RSP *pSMBr = NULL;
5047 cFYI(1, ("In SetAttrLegacy"));
5050 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5055 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5057 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5058 PATH_MAX, nls_codepage);
5059 name_len++; /* trailing null */
5061 } else { /* BB improve the check for buffer overruns BB */
5062 name_len = strnlen(fileName, PATH_MAX);
5063 name_len++; /* trailing null */
5064 strncpy(pSMB->fileName, fileName, name_len);
5066 pSMB->attr = cpu_to_le16(dos_attrs);
5067 pSMB->BufferFormat = 0x04;
5068 pSMB->hdr.smb_buf_length += name_len + 1;
5069 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5070 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5071 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5073 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5075 cifs_buf_release(pSMB);
5078 goto SetAttrLgcyRetry;
5082 #endif /* temporarily unneeded SetAttr legacy function */
5085 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5086 const struct cifs_unix_set_info_args *args)
5088 u64 mode = args->mode;
5091 * Samba server ignores set of file size to zero due to bugs in some
5092 * older clients, but we should be precise - we use SetFileSize to
5093 * set file size and do not want to truncate file size to zero
5094 * accidently as happened on one Samba server beta by putting
5095 * zero instead of -1 here
5097 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5098 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5099 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5100 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5101 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5102 data_offset->Uid = cpu_to_le64(args->uid);
5103 data_offset->Gid = cpu_to_le64(args->gid);
5104 /* better to leave device as zero when it is */
5105 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5106 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5107 data_offset->Permissions = cpu_to_le64(mode);
5110 data_offset->Type = cpu_to_le32(UNIX_FILE);
5111 else if (S_ISDIR(mode))
5112 data_offset->Type = cpu_to_le32(UNIX_DIR);
5113 else if (S_ISLNK(mode))
5114 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5115 else if (S_ISCHR(mode))
5116 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5117 else if (S_ISBLK(mode))
5118 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5119 else if (S_ISFIFO(mode))
5120 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5121 else if (S_ISSOCK(mode))
5122 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5126 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5127 const struct cifs_unix_set_info_args *args,
5128 u16 fid, u32 pid_of_opener)
5130 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5131 FILE_UNIX_BASIC_INFO *data_offset;
5133 u16 params, param_offset, offset, byte_count, count;
5135 cFYI(1, ("Set Unix Info (via SetFileInfo)"));
5136 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5141 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5142 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5145 pSMB->MaxSetupCount = 0;
5149 pSMB->Reserved2 = 0;
5150 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5151 offset = param_offset + params;
5153 data_offset = (FILE_UNIX_BASIC_INFO *)
5154 ((char *)(&pSMB->hdr.Protocol) + offset);
5155 count = sizeof(FILE_UNIX_BASIC_INFO);
5157 pSMB->MaxParameterCount = cpu_to_le16(2);
5158 /* BB find max SMB PDU from sess */
5159 pSMB->MaxDataCount = cpu_to_le16(1000);
5160 pSMB->SetupCount = 1;
5161 pSMB->Reserved3 = 0;
5162 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5163 byte_count = 3 /* pad */ + params + count;
5164 pSMB->DataCount = cpu_to_le16(count);
5165 pSMB->ParameterCount = cpu_to_le16(params);
5166 pSMB->TotalDataCount = pSMB->DataCount;
5167 pSMB->TotalParameterCount = pSMB->ParameterCount;
5168 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5169 pSMB->DataOffset = cpu_to_le16(offset);
5171 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5172 pSMB->Reserved4 = 0;
5173 pSMB->hdr.smb_buf_length += byte_count;
5174 pSMB->ByteCount = cpu_to_le16(byte_count);
5176 cifs_fill_unix_set_info(data_offset, args);
5178 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5180 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
5182 /* Note: On -EAGAIN error only caller can retry on handle based calls
5183 since file handle passed in no longer valid */
5189 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5190 const struct cifs_unix_set_info_args *args,
5191 const struct nls_table *nls_codepage, int remap)
5193 TRANSACTION2_SPI_REQ *pSMB = NULL;
5194 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5197 int bytes_returned = 0;
5198 FILE_UNIX_BASIC_INFO *data_offset;
5199 __u16 params, param_offset, offset, count, byte_count;
5201 cFYI(1, ("In SetUID/GID/Mode"));
5203 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5208 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5210 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5211 PATH_MAX, nls_codepage, remap);
5212 name_len++; /* trailing null */
5214 } else { /* BB improve the check for buffer overruns BB */
5215 name_len = strnlen(fileName, PATH_MAX);
5216 name_len++; /* trailing null */
5217 strncpy(pSMB->FileName, fileName, name_len);
5220 params = 6 + name_len;
5221 count = sizeof(FILE_UNIX_BASIC_INFO);
5222 pSMB->MaxParameterCount = cpu_to_le16(2);
5223 /* BB find max SMB PDU from sess structure BB */
5224 pSMB->MaxDataCount = cpu_to_le16(1000);
5225 pSMB->MaxSetupCount = 0;
5229 pSMB->Reserved2 = 0;
5230 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5231 InformationLevel) - 4;
5232 offset = param_offset + params;
5234 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5236 memset(data_offset, 0, count);
5237 pSMB->DataOffset = cpu_to_le16(offset);
5238 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5239 pSMB->SetupCount = 1;
5240 pSMB->Reserved3 = 0;
5241 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5242 byte_count = 3 /* pad */ + params + count;
5243 pSMB->ParameterCount = cpu_to_le16(params);
5244 pSMB->DataCount = cpu_to_le16(count);
5245 pSMB->TotalParameterCount = pSMB->ParameterCount;
5246 pSMB->TotalDataCount = pSMB->DataCount;
5247 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5248 pSMB->Reserved4 = 0;
5249 pSMB->hdr.smb_buf_length += byte_count;
5251 cifs_fill_unix_set_info(data_offset, args);
5253 pSMB->ByteCount = cpu_to_le16(byte_count);
5254 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5255 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5257 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5259 cifs_buf_release(pSMB);
5265 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5266 const int notify_subdirs, const __u16 netfid,
5267 __u32 filter, struct file *pfile, int multishot,
5268 const struct nls_table *nls_codepage)
5271 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5272 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5273 struct dir_notify_req *dnotify_req;
5276 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5277 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5282 pSMB->TotalParameterCount = 0 ;
5283 pSMB->TotalDataCount = 0;
5284 pSMB->MaxParameterCount = cpu_to_le32(2);
5285 /* BB find exact data count max from sess structure BB */
5286 pSMB->MaxDataCount = 0; /* same in little endian or be */
5287 /* BB VERIFY verify which is correct for above BB */
5288 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5289 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5291 pSMB->MaxSetupCount = 4;
5293 pSMB->ParameterOffset = 0;
5294 pSMB->DataCount = 0;
5295 pSMB->DataOffset = 0;
5296 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5297 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5298 pSMB->ParameterCount = pSMB->TotalParameterCount;
5300 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5301 pSMB->Reserved2 = 0;
5302 pSMB->CompletionFilter = cpu_to_le32(filter);
5303 pSMB->Fid = netfid; /* file handle always le */
5304 pSMB->ByteCount = 0;
5306 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5307 (struct smb_hdr *)pSMBr, &bytes_returned,
5310 cFYI(1, ("Error in Notify = %d", rc));
5312 /* Add file to outstanding requests */
5313 /* BB change to kmem cache alloc */
5314 dnotify_req = kmalloc(
5315 sizeof(struct dir_notify_req),
5318 dnotify_req->Pid = pSMB->hdr.Pid;
5319 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5320 dnotify_req->Mid = pSMB->hdr.Mid;
5321 dnotify_req->Tid = pSMB->hdr.Tid;
5322 dnotify_req->Uid = pSMB->hdr.Uid;
5323 dnotify_req->netfid = netfid;
5324 dnotify_req->pfile = pfile;
5325 dnotify_req->filter = filter;
5326 dnotify_req->multishot = multishot;
5327 spin_lock(&GlobalMid_Lock);
5328 list_add_tail(&dnotify_req->lhead,
5329 &GlobalDnotifyReqList);
5330 spin_unlock(&GlobalMid_Lock);
5334 cifs_buf_release(pSMB);
5337 #ifdef CONFIG_CIFS_XATTR
5339 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5340 const unsigned char *searchName,
5341 char *EAData, size_t buf_size,
5342 const struct nls_table *nls_codepage, int remap)
5344 /* BB assumes one setup word */
5345 TRANSACTION2_QPI_REQ *pSMB = NULL;
5346 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5350 struct fea *temp_fea;
5352 __u16 params, byte_count;
5354 cFYI(1, ("In Query All EAs path %s", searchName));
5356 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5361 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5363 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5364 PATH_MAX, nls_codepage, remap);
5365 name_len++; /* trailing null */
5367 } else { /* BB improve the check for buffer overruns BB */
5368 name_len = strnlen(searchName, PATH_MAX);
5369 name_len++; /* trailing null */
5370 strncpy(pSMB->FileName, searchName, name_len);
5373 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5374 pSMB->TotalDataCount = 0;
5375 pSMB->MaxParameterCount = cpu_to_le16(2);
5376 /* BB find exact max SMB PDU from sess structure BB */
5377 pSMB->MaxDataCount = cpu_to_le16(4000);
5378 pSMB->MaxSetupCount = 0;
5382 pSMB->Reserved2 = 0;
5383 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5384 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5385 pSMB->DataCount = 0;
5386 pSMB->DataOffset = 0;
5387 pSMB->SetupCount = 1;
5388 pSMB->Reserved3 = 0;
5389 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5390 byte_count = params + 1 /* pad */ ;
5391 pSMB->TotalParameterCount = cpu_to_le16(params);
5392 pSMB->ParameterCount = pSMB->TotalParameterCount;
5393 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5394 pSMB->Reserved4 = 0;
5395 pSMB->hdr.smb_buf_length += byte_count;
5396 pSMB->ByteCount = cpu_to_le16(byte_count);
5398 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5399 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5401 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5402 } else { /* decode response */
5403 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5405 /* BB also check enough total bytes returned */
5406 /* BB we need to improve the validity checking
5407 of these trans2 responses */
5408 if (rc || (pSMBr->ByteCount < 4))
5409 rc = -EIO; /* bad smb */
5410 /* else if (pFindData){
5411 memcpy((char *) pFindData,
5412 (char *) &pSMBr->hdr.Protocol +
5415 /* check that length of list is not more than bcc */
5416 /* check that each entry does not go beyond length
5418 /* check that each element of each entry does not
5419 go beyond end of list */
5420 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5421 struct fealist *ea_response_data;
5423 /* validate_trans2_offsets() */
5424 /* BB check if start of smb + data_offset > &bcc+ bcc */
5425 ea_response_data = (struct fealist *)
5426 (((char *) &pSMBr->hdr.Protocol) +
5428 name_len = le32_to_cpu(ea_response_data->list_len);
5429 cFYI(1, ("ea length %d", name_len));
5430 if (name_len <= 8) {
5431 /* returned EA size zeroed at top of function */
5432 cFYI(1, ("empty EA list returned from server"));
5434 /* account for ea list len */
5436 temp_fea = ea_response_data->list;
5437 temp_ptr = (char *)temp_fea;
5438 while (name_len > 0) {
5442 rc += temp_fea->name_len;
5443 /* account for prefix user. and trailing null */
5445 if (rc < (int)buf_size) {
5446 memcpy(EAData, "user.", 5);
5448 memcpy(EAData, temp_ptr,
5449 temp_fea->name_len);
5450 EAData += temp_fea->name_len;
5451 /* null terminate name */
5453 EAData = EAData + 1;
5454 } else if (buf_size == 0) {
5455 /* skip copy - calc size only */
5457 /* stop before overrun buffer */
5461 name_len -= temp_fea->name_len;
5462 temp_ptr += temp_fea->name_len;
5463 /* account for trailing null */
5467 le16_to_cpu(temp_fea->value_len);
5468 name_len -= value_len;
5469 temp_ptr += value_len;
5470 /* BB check that temp_ptr is still
5473 /* no trailing null to account for
5475 /* go on to next EA */
5476 temp_fea = (struct fea *)temp_ptr;
5481 cifs_buf_release(pSMB);
5488 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5489 const unsigned char *searchName, const unsigned char *ea_name,
5490 unsigned char *ea_value, size_t buf_size,
5491 const struct nls_table *nls_codepage, int remap)
5493 TRANSACTION2_QPI_REQ *pSMB = NULL;
5494 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5498 struct fea *temp_fea;
5500 __u16 params, byte_count;
5502 cFYI(1, ("In Query EA path %s", searchName));
5504 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5509 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5511 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5512 PATH_MAX, nls_codepage, remap);
5513 name_len++; /* trailing null */
5515 } else { /* BB improve the check for buffer overruns BB */
5516 name_len = strnlen(searchName, PATH_MAX);
5517 name_len++; /* trailing null */
5518 strncpy(pSMB->FileName, searchName, name_len);
5521 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5522 pSMB->TotalDataCount = 0;
5523 pSMB->MaxParameterCount = cpu_to_le16(2);
5524 /* BB find exact max SMB PDU from sess structure BB */
5525 pSMB->MaxDataCount = cpu_to_le16(4000);
5526 pSMB->MaxSetupCount = 0;
5530 pSMB->Reserved2 = 0;
5531 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5532 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5533 pSMB->DataCount = 0;
5534 pSMB->DataOffset = 0;
5535 pSMB->SetupCount = 1;
5536 pSMB->Reserved3 = 0;
5537 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5538 byte_count = params + 1 /* pad */ ;
5539 pSMB->TotalParameterCount = cpu_to_le16(params);
5540 pSMB->ParameterCount = pSMB->TotalParameterCount;
5541 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5542 pSMB->Reserved4 = 0;
5543 pSMB->hdr.smb_buf_length += byte_count;
5544 pSMB->ByteCount = cpu_to_le16(byte_count);
5546 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5547 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5549 cFYI(1, ("Send error in Query EA = %d", rc));
5550 } else { /* decode response */
5551 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5553 /* BB also check enough total bytes returned */
5554 /* BB we need to improve the validity checking
5555 of these trans2 responses */
5556 if (rc || (pSMBr->ByteCount < 4))
5557 rc = -EIO; /* bad smb */
5558 /* else if (pFindData){
5559 memcpy((char *) pFindData,
5560 (char *) &pSMBr->hdr.Protocol +
5563 /* check that length of list is not more than bcc */
5564 /* check that each entry does not go beyond length
5566 /* check that each element of each entry does not
5567 go beyond end of list */
5568 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5569 struct fealist *ea_response_data;
5571 /* validate_trans2_offsets() */
5572 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5573 ea_response_data = (struct fealist *)
5574 (((char *) &pSMBr->hdr.Protocol) +
5576 name_len = le32_to_cpu(ea_response_data->list_len);
5577 cFYI(1, ("ea length %d", name_len));
5578 if (name_len <= 8) {
5579 /* returned EA size zeroed at top of function */
5580 cFYI(1, ("empty EA list returned from server"));
5582 /* account for ea list len */
5584 temp_fea = ea_response_data->list;
5585 temp_ptr = (char *)temp_fea;
5586 /* loop through checking if we have a matching
5587 name and then return the associated value */
5588 while (name_len > 0) {
5593 le16_to_cpu(temp_fea->value_len);
5594 /* BB validate that value_len falls within SMB,
5595 even though maximum for name_len is 255 */
5596 if (memcmp(temp_fea->name, ea_name,
5597 temp_fea->name_len) == 0) {
5600 /* account for prefix user. and trailing null */
5601 if (rc <= (int)buf_size) {
5603 temp_fea->name+temp_fea->name_len+1,
5605 /* ea values, unlike ea
5608 } else if (buf_size == 0) {
5609 /* skip copy - calc size only */
5611 /* stop before overrun buffer */
5616 name_len -= temp_fea->name_len;
5617 temp_ptr += temp_fea->name_len;
5618 /* account for trailing null */
5621 name_len -= value_len;
5622 temp_ptr += value_len;
5623 /* No trailing null to account for in
5624 value_len. Go on to next EA */
5625 temp_fea = (struct fea *)temp_ptr;
5630 cifs_buf_release(pSMB);
5638 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5639 const char *ea_name, const void *ea_value,
5640 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5643 struct smb_com_transaction2_spi_req *pSMB = NULL;
5644 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5645 struct fealist *parm_data;
5648 int bytes_returned = 0;
5649 __u16 params, param_offset, byte_count, offset, count;
5651 cFYI(1, ("In SetEA"));
5653 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5658 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5660 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5661 PATH_MAX, nls_codepage, remap);
5662 name_len++; /* trailing null */
5664 } else { /* BB improve the check for buffer overruns BB */
5665 name_len = strnlen(fileName, PATH_MAX);
5666 name_len++; /* trailing null */
5667 strncpy(pSMB->FileName, fileName, name_len);
5670 params = 6 + name_len;
5672 /* done calculating parms using name_len of file name,
5673 now use name_len to calculate length of ea name
5674 we are going to create in the inode xattrs */
5675 if (ea_name == NULL)
5678 name_len = strnlen(ea_name, 255);
5680 count = sizeof(*parm_data) + ea_value_len + name_len;
5681 pSMB->MaxParameterCount = cpu_to_le16(2);
5682 /* BB find max SMB PDU from sess */
5683 pSMB->MaxDataCount = cpu_to_le16(1000);
5684 pSMB->MaxSetupCount = 0;
5688 pSMB->Reserved2 = 0;
5689 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5690 InformationLevel) - 4;
5691 offset = param_offset + params;
5692 pSMB->InformationLevel =
5693 cpu_to_le16(SMB_SET_FILE_EA);
5696 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5698 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5699 pSMB->DataOffset = cpu_to_le16(offset);
5700 pSMB->SetupCount = 1;
5701 pSMB->Reserved3 = 0;
5702 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5703 byte_count = 3 /* pad */ + params + count;
5704 pSMB->DataCount = cpu_to_le16(count);
5705 parm_data->list_len = cpu_to_le32(count);
5706 parm_data->list[0].EA_flags = 0;
5707 /* we checked above that name len is less than 255 */
5708 parm_data->list[0].name_len = (__u8)name_len;
5709 /* EA names are always ASCII */
5711 strncpy(parm_data->list[0].name, ea_name, name_len);
5712 parm_data->list[0].name[name_len] = 0;
5713 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5714 /* caller ensures that ea_value_len is less than 64K but
5715 we need to ensure that it fits within the smb */
5717 /*BB add length check to see if it would fit in
5718 negotiated SMB buffer size BB */
5719 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5721 memcpy(parm_data->list[0].name+name_len+1,
5722 ea_value, ea_value_len);
5724 pSMB->TotalDataCount = pSMB->DataCount;
5725 pSMB->ParameterCount = cpu_to_le16(params);
5726 pSMB->TotalParameterCount = pSMB->ParameterCount;
5727 pSMB->Reserved4 = 0;
5728 pSMB->hdr.smb_buf_length += byte_count;
5729 pSMB->ByteCount = cpu_to_le16(byte_count);
5730 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5731 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5733 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5735 cifs_buf_release(pSMB);