4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* 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;
454 for (i = 0; i < CIFS_NUM_PROT; i++) {
455 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
456 count += strlen(protocols[i].name) + 1;
457 /* null at end of source and target buffers anyway */
459 pSMB->hdr.smb_buf_length += count;
460 pSMB->ByteCount = cpu_to_le16(count);
462 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
463 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
467 dialect = le16_to_cpu(pSMBr->DialectIndex);
468 cFYI(1, ("Dialect: %d", dialect));
469 /* Check wct = 1 error case */
470 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
471 /* core returns wct = 1, but we do not ask for core - otherwise
472 small wct just comes when dialect index is -1 indicating we
473 could not negotiate a common dialect */
476 #ifdef CONFIG_CIFS_WEAK_PW_HASH
477 } else if ((pSMBr->hdr.WordCount == 13)
478 && ((dialect == LANMAN_PROT)
479 || (dialect == LANMAN2_PROT))) {
481 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
483 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
484 (secFlags & CIFSSEC_MAY_PLNTXT))
485 server->secType = LANMAN;
487 cERROR(1, ("mount failed weak security disabled"
488 " in /proc/fs/cifs/SecurityFlags"));
492 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
493 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
494 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
495 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
496 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
497 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
498 /* even though we do not use raw we might as well set this
499 accurately, in case we ever find a need for it */
500 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
501 server->max_rw = 0xFF00;
502 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
504 server->max_rw = 0;/* do not need to use raw anyway */
505 server->capabilities = CAP_MPX_MODE;
507 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
509 /* OS/2 often does not set timezone therefore
510 * we must use server time to calc time zone.
511 * Could deviate slightly from the right zone.
512 * Smallest defined timezone difference is 15 minutes
513 * (i.e. Nepal). Rounding up/down is done to match
516 int val, seconds, remain, result;
517 struct timespec ts, utc;
519 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
520 le16_to_cpu(rsp->SrvTime.Time));
521 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
522 (int)ts.tv_sec, (int)utc.tv_sec,
523 (int)(utc.tv_sec - ts.tv_sec)));
524 val = (int)(utc.tv_sec - ts.tv_sec);
526 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
527 remain = seconds % MIN_TZ_ADJ;
528 if (remain >= (MIN_TZ_ADJ / 2))
529 result += MIN_TZ_ADJ;
532 server->timeAdj = result;
534 server->timeAdj = (int)tmp;
535 server->timeAdj *= 60; /* also in seconds */
537 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
540 /* BB get server time for time conversions and add
541 code to use it and timezone since this is not UTC */
543 if (rsp->EncryptionKeyLength ==
544 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
545 memcpy(server->cryptKey, rsp->EncryptionKey,
546 CIFS_CRYPTO_KEY_SIZE);
547 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
548 rc = -EIO; /* need cryptkey unless plain text */
552 cFYI(1, ("LANMAN negotiated"));
553 /* we will not end up setting signing flags - as no signing
554 was in LANMAN and server did not return the flags on */
556 #else /* weak security disabled */
557 } else if (pSMBr->hdr.WordCount == 13) {
558 cERROR(1, ("mount failed, cifs module not built "
559 "with CIFS_WEAK_PW_HASH support"));
561 #endif /* WEAK_PW_HASH */
563 } else if (pSMBr->hdr.WordCount != 17) {
568 /* else wct == 17 NTLM */
569 server->secMode = pSMBr->SecurityMode;
570 if ((server->secMode & SECMODE_USER) == 0)
571 cFYI(1, ("share mode security"));
573 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
574 #ifdef CONFIG_CIFS_WEAK_PW_HASH
575 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
576 #endif /* CIFS_WEAK_PW_HASH */
577 cERROR(1, ("Server requests plain text password"
578 " but client support disabled"));
580 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
581 server->secType = NTLMv2;
582 else if (secFlags & CIFSSEC_MAY_NTLM)
583 server->secType = NTLM;
584 else if (secFlags & CIFSSEC_MAY_NTLMV2)
585 server->secType = NTLMv2;
586 else if (secFlags & CIFSSEC_MAY_KRB5)
587 server->secType = Kerberos;
588 else if (secFlags & CIFSSEC_MAY_LANMAN)
589 server->secType = LANMAN;
590 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
591 else if (secFlags & CIFSSEC_MAY_PLNTXT)
596 cERROR(1, ("Invalid security type"));
599 /* else ... any others ...? */
601 /* one byte, so no need to convert this or EncryptionKeyLen from
603 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
604 /* probably no need to store and check maxvcs */
605 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
606 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
607 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
608 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
609 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
610 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
611 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
612 server->timeAdj *= 60;
613 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
614 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
615 CIFS_CRYPTO_KEY_SIZE);
616 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
617 && (pSMBr->EncryptionKeyLength == 0)) {
618 /* decode security blob */
619 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
620 rc = -EIO; /* no crypt key only if plain text pwd */
624 /* BB might be helpful to save off the domain of server here */
626 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
627 (server->capabilities & CAP_EXTENDED_SECURITY)) {
628 count = pSMBr->ByteCount;
633 read_lock(&cifs_tcp_ses_lock);
634 if (server->srv_count > 1) {
635 read_unlock(&cifs_tcp_ses_lock);
636 if (memcmp(server->server_GUID,
637 pSMBr->u.extended_response.
639 cFYI(1, ("server UID changed"));
640 memcpy(server->server_GUID,
641 pSMBr->u.extended_response.GUID,
645 read_unlock(&cifs_tcp_ses_lock);
646 memcpy(server->server_GUID,
647 pSMBr->u.extended_response.GUID, 16);
651 server->secType = RawNTLMSSP;
653 rc = decode_negTokenInit(pSMBr->u.extended_response.
663 server->capabilities &= ~CAP_EXTENDED_SECURITY;
665 #ifdef CONFIG_CIFS_WEAK_PW_HASH
668 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
669 /* MUST_SIGN already includes the MAY_SIGN FLAG
670 so if this is zero it means that signing is disabled */
671 cFYI(1, ("Signing disabled"));
672 if (server->secMode & SECMODE_SIGN_REQUIRED) {
673 cERROR(1, ("Server requires "
674 "packet signing to be enabled in "
675 "/proc/fs/cifs/SecurityFlags."));
679 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
680 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
681 /* signing required */
682 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
683 if ((server->secMode &
684 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
686 ("signing required but server lacks support"));
689 server->secMode |= SECMODE_SIGN_REQUIRED;
691 /* signing optional ie CIFSSEC_MAY_SIGN */
692 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
694 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
698 cifs_buf_release(pSMB);
700 cFYI(1, ("negprot rc %d", rc));
705 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
707 struct smb_hdr *smb_buffer;
710 cFYI(1, ("In tree disconnect"));
712 /* BB: do we need to check this? These should never be NULL. */
713 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
717 * No need to return error on this operation if tid invalidated and
718 * closed on server already e.g. due to tcp session crashing. Also,
719 * the tcon is no longer on the list, so no need to take lock before
722 if (tcon->need_reconnect)
725 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
726 (void **)&smb_buffer);
730 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
732 cFYI(1, ("Tree disconnect failed %d", rc));
734 /* No need to return error on this operation if tid invalidated and
735 closed on server already e.g. due to tcp session crashing */
743 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
745 LOGOFF_ANDX_REQ *pSMB;
748 cFYI(1, ("In SMBLogoff for session disconnect"));
751 * BB: do we need to check validity of ses and server? They should
752 * always be valid since we have an active reference. If not, that
753 * should probably be a BUG()
755 if (!ses || !ses->server)
759 if (ses->need_reconnect)
760 goto session_already_dead; /* no need to send SMBlogoff if uid
761 already closed due to reconnect */
762 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
768 pSMB->hdr.Mid = GetNextMid(ses->server);
770 if (ses->server->secMode &
771 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
772 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
774 pSMB->hdr.Uid = ses->Suid;
776 pSMB->AndXCommand = 0xFF;
777 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
778 session_already_dead:
781 /* if session dead then we do not need to do ulogoff,
782 since server closed smb session, no sense reporting
790 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
791 __u16 type, const struct nls_table *nls_codepage, int remap)
793 TRANSACTION2_SPI_REQ *pSMB = NULL;
794 TRANSACTION2_SPI_RSP *pSMBr = NULL;
795 struct unlink_psx_rq *pRqD;
798 int bytes_returned = 0;
799 __u16 params, param_offset, offset, byte_count;
801 cFYI(1, ("In POSIX delete"));
803 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
808 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
810 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
811 PATH_MAX, nls_codepage, remap);
812 name_len++; /* trailing null */
814 } else { /* BB add path length overrun check */
815 name_len = strnlen(fileName, PATH_MAX);
816 name_len++; /* trailing null */
817 strncpy(pSMB->FileName, fileName, name_len);
820 params = 6 + name_len;
821 pSMB->MaxParameterCount = cpu_to_le16(2);
822 pSMB->MaxDataCount = 0; /* BB double check this with jra */
823 pSMB->MaxSetupCount = 0;
828 param_offset = offsetof(struct smb_com_transaction2_spi_req,
829 InformationLevel) - 4;
830 offset = param_offset + params;
832 /* Setup pointer to Request Data (inode type) */
833 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
834 pRqD->type = cpu_to_le16(type);
835 pSMB->ParameterOffset = cpu_to_le16(param_offset);
836 pSMB->DataOffset = cpu_to_le16(offset);
837 pSMB->SetupCount = 1;
839 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
840 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
842 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
843 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
844 pSMB->ParameterCount = cpu_to_le16(params);
845 pSMB->TotalParameterCount = pSMB->ParameterCount;
846 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
848 pSMB->hdr.smb_buf_length += byte_count;
849 pSMB->ByteCount = cpu_to_le16(byte_count);
850 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
851 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
853 cFYI(1, ("Posix delete returned %d", rc));
854 cifs_buf_release(pSMB);
856 cifs_stats_inc(&tcon->num_deletes);
865 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
866 const struct nls_table *nls_codepage, int remap)
868 DELETE_FILE_REQ *pSMB = NULL;
869 DELETE_FILE_RSP *pSMBr = NULL;
875 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
880 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
882 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
883 PATH_MAX, nls_codepage, remap);
884 name_len++; /* trailing null */
886 } else { /* BB improve check for buffer overruns BB */
887 name_len = strnlen(fileName, PATH_MAX);
888 name_len++; /* trailing null */
889 strncpy(pSMB->fileName, fileName, name_len);
891 pSMB->SearchAttributes =
892 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
893 pSMB->BufferFormat = 0x04;
894 pSMB->hdr.smb_buf_length += name_len + 1;
895 pSMB->ByteCount = cpu_to_le16(name_len + 1);
896 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
897 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
898 cifs_stats_inc(&tcon->num_deletes);
900 cFYI(1, ("Error in RMFile = %d", rc));
902 cifs_buf_release(pSMB);
910 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
911 const struct nls_table *nls_codepage, int remap)
913 DELETE_DIRECTORY_REQ *pSMB = NULL;
914 DELETE_DIRECTORY_RSP *pSMBr = NULL;
919 cFYI(1, ("In CIFSSMBRmDir"));
921 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
926 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
927 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
928 PATH_MAX, nls_codepage, remap);
929 name_len++; /* trailing null */
931 } else { /* BB improve check for buffer overruns BB */
932 name_len = strnlen(dirName, PATH_MAX);
933 name_len++; /* trailing null */
934 strncpy(pSMB->DirName, dirName, name_len);
937 pSMB->BufferFormat = 0x04;
938 pSMB->hdr.smb_buf_length += name_len + 1;
939 pSMB->ByteCount = cpu_to_le16(name_len + 1);
940 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
941 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
942 cifs_stats_inc(&tcon->num_rmdirs);
944 cFYI(1, ("Error in RMDir = %d", rc));
946 cifs_buf_release(pSMB);
953 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
954 const char *name, const struct nls_table *nls_codepage, int remap)
957 CREATE_DIRECTORY_REQ *pSMB = NULL;
958 CREATE_DIRECTORY_RSP *pSMBr = NULL;
962 cFYI(1, ("In CIFSSMBMkDir"));
964 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
969 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
970 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
971 PATH_MAX, nls_codepage, remap);
972 name_len++; /* trailing null */
974 } else { /* BB improve check for buffer overruns BB */
975 name_len = strnlen(name, PATH_MAX);
976 name_len++; /* trailing null */
977 strncpy(pSMB->DirName, name, name_len);
980 pSMB->BufferFormat = 0x04;
981 pSMB->hdr.smb_buf_length += name_len + 1;
982 pSMB->ByteCount = cpu_to_le16(name_len + 1);
983 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
984 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
985 cifs_stats_inc(&tcon->num_mkdirs);
987 cFYI(1, ("Error in Mkdir = %d", rc));
989 cifs_buf_release(pSMB);
996 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
997 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
998 __u32 *pOplock, const char *name,
999 const struct nls_table *nls_codepage, int remap)
1001 TRANSACTION2_SPI_REQ *pSMB = NULL;
1002 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1005 int bytes_returned = 0;
1006 __u16 params, param_offset, offset, byte_count, count;
1007 OPEN_PSX_REQ *pdata;
1008 OPEN_PSX_RSP *psx_rsp;
1010 cFYI(1, ("In POSIX Create"));
1012 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1017 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1019 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1020 PATH_MAX, nls_codepage, remap);
1021 name_len++; /* trailing null */
1023 } else { /* BB improve the check for buffer overruns BB */
1024 name_len = strnlen(name, PATH_MAX);
1025 name_len++; /* trailing null */
1026 strncpy(pSMB->FileName, name, name_len);
1029 params = 6 + name_len;
1030 count = sizeof(OPEN_PSX_REQ);
1031 pSMB->MaxParameterCount = cpu_to_le16(2);
1032 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1033 pSMB->MaxSetupCount = 0;
1037 pSMB->Reserved2 = 0;
1038 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1039 InformationLevel) - 4;
1040 offset = param_offset + params;
1041 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1042 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1043 pdata->Permissions = cpu_to_le64(mode);
1044 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1045 pdata->OpenFlags = cpu_to_le32(*pOplock);
1046 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1047 pSMB->DataOffset = cpu_to_le16(offset);
1048 pSMB->SetupCount = 1;
1049 pSMB->Reserved3 = 0;
1050 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1051 byte_count = 3 /* pad */ + params + count;
1053 pSMB->DataCount = cpu_to_le16(count);
1054 pSMB->ParameterCount = cpu_to_le16(params);
1055 pSMB->TotalDataCount = pSMB->DataCount;
1056 pSMB->TotalParameterCount = pSMB->ParameterCount;
1057 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1058 pSMB->Reserved4 = 0;
1059 pSMB->hdr.smb_buf_length += byte_count;
1060 pSMB->ByteCount = cpu_to_le16(byte_count);
1061 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1062 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1064 cFYI(1, ("Posix create returned %d", rc));
1065 goto psx_create_err;
1068 cFYI(1, ("copying inode info"));
1069 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1071 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1072 rc = -EIO; /* bad smb */
1073 goto psx_create_err;
1076 /* copy return information to pRetData */
1077 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1078 + le16_to_cpu(pSMBr->t2.DataOffset));
1080 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1082 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1083 /* Let caller know file was created so we can set the mode. */
1084 /* Do we care about the CreateAction in any other cases? */
1085 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1086 *pOplock |= CIFS_CREATE_ACTION;
1087 /* check to make sure response data is there */
1088 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1089 pRetData->Type = cpu_to_le32(-1); /* unknown */
1090 cFYI(DBG2, ("unknown type"));
1092 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1093 + sizeof(FILE_UNIX_BASIC_INFO)) {
1094 cERROR(1, ("Open response data too small"));
1095 pRetData->Type = cpu_to_le32(-1);
1096 goto psx_create_err;
1098 memcpy((char *) pRetData,
1099 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1100 sizeof(FILE_UNIX_BASIC_INFO));
1104 cifs_buf_release(pSMB);
1106 cifs_stats_inc(&tcon->num_mkdirs);
1114 static __u16 convert_disposition(int disposition)
1118 switch (disposition) {
1119 case FILE_SUPERSEDE:
1120 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1123 ofun = SMBOPEN_OAPPEND;
1126 ofun = SMBOPEN_OCREATE;
1129 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1131 case FILE_OVERWRITE:
1132 ofun = SMBOPEN_OTRUNC;
1134 case FILE_OVERWRITE_IF:
1135 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1138 cFYI(1, ("unknown disposition %d", disposition));
1139 ofun = SMBOPEN_OAPPEND; /* regular open */
1145 access_flags_to_smbopen_mode(const int access_flags)
1147 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1149 if (masked_flags == GENERIC_READ)
1150 return SMBOPEN_READ;
1151 else if (masked_flags == GENERIC_WRITE)
1152 return SMBOPEN_WRITE;
1154 /* just go for read/write */
1155 return SMBOPEN_READWRITE;
1159 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1160 const char *fileName, const int openDisposition,
1161 const int access_flags, const int create_options, __u16 *netfid,
1162 int *pOplock, FILE_ALL_INFO *pfile_info,
1163 const struct nls_table *nls_codepage, int remap)
1166 OPENX_REQ *pSMB = NULL;
1167 OPENX_RSP *pSMBr = NULL;
1173 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1178 pSMB->AndXCommand = 0xFF; /* none */
1180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1181 count = 1; /* account for one byte pad to word boundary */
1183 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1184 fileName, PATH_MAX, nls_codepage, remap);
1185 name_len++; /* trailing null */
1187 } else { /* BB improve check for buffer overruns BB */
1188 count = 0; /* no pad */
1189 name_len = strnlen(fileName, PATH_MAX);
1190 name_len++; /* trailing null */
1191 strncpy(pSMB->fileName, fileName, name_len);
1193 if (*pOplock & REQ_OPLOCK)
1194 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1195 else if (*pOplock & REQ_BATCHOPLOCK)
1196 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1198 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1199 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1200 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1201 /* set file as system file if special file such
1202 as fifo and server expecting SFU style and
1203 no Unix extensions */
1205 if (create_options & CREATE_OPTION_SPECIAL)
1206 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1207 else /* BB FIXME BB */
1208 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1210 if (create_options & CREATE_OPTION_READONLY)
1211 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1214 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1215 CREATE_OPTIONS_MASK); */
1216 /* BB FIXME END BB */
1218 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1219 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1221 pSMB->hdr.smb_buf_length += count;
1223 pSMB->ByteCount = cpu_to_le16(count);
1224 /* long_op set to 1 to allow for oplock break timeouts */
1225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1226 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1227 cifs_stats_inc(&tcon->num_opens);
1229 cFYI(1, ("Error in Open = %d", rc));
1231 /* BB verify if wct == 15 */
1233 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1235 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1236 /* Let caller know file was created so we can set the mode. */
1237 /* Do we care about the CreateAction in any other cases? */
1239 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1240 *pOplock |= CIFS_CREATE_ACTION; */
1244 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1245 pfile_info->LastAccessTime = 0; /* BB fixme */
1246 pfile_info->LastWriteTime = 0; /* BB fixme */
1247 pfile_info->ChangeTime = 0; /* BB fixme */
1248 pfile_info->Attributes =
1249 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1250 /* the file_info buf is endian converted by caller */
1251 pfile_info->AllocationSize =
1252 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1253 pfile_info->EndOfFile = pfile_info->AllocationSize;
1254 pfile_info->NumberOfLinks = cpu_to_le32(1);
1255 pfile_info->DeletePending = 0;
1259 cifs_buf_release(pSMB);
1266 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1267 const char *fileName, const int openDisposition,
1268 const int access_flags, const int create_options, __u16 *netfid,
1269 int *pOplock, FILE_ALL_INFO *pfile_info,
1270 const struct nls_table *nls_codepage, int remap)
1273 OPEN_REQ *pSMB = NULL;
1274 OPEN_RSP *pSMBr = NULL;
1280 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1285 pSMB->AndXCommand = 0xFF; /* none */
1287 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1288 count = 1; /* account for one byte pad to word boundary */
1290 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1291 fileName, PATH_MAX, nls_codepage, remap);
1292 name_len++; /* trailing null */
1294 pSMB->NameLength = cpu_to_le16(name_len);
1295 } else { /* BB improve check for buffer overruns BB */
1296 count = 0; /* no pad */
1297 name_len = strnlen(fileName, PATH_MAX);
1298 name_len++; /* trailing null */
1299 pSMB->NameLength = cpu_to_le16(name_len);
1300 strncpy(pSMB->fileName, fileName, name_len);
1302 if (*pOplock & REQ_OPLOCK)
1303 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1304 else if (*pOplock & REQ_BATCHOPLOCK)
1305 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1306 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1307 pSMB->AllocationSize = 0;
1308 /* set file as system file if special file such
1309 as fifo and server expecting SFU style and
1310 no Unix extensions */
1311 if (create_options & CREATE_OPTION_SPECIAL)
1312 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1314 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1316 /* XP does not handle ATTR_POSIX_SEMANTICS */
1317 /* but it helps speed up case sensitive checks for other
1318 servers such as Samba */
1319 if (tcon->ses->capabilities & CAP_UNIX)
1320 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1322 if (create_options & CREATE_OPTION_READONLY)
1323 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1325 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1326 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1327 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1328 /* BB Expirement with various impersonation levels and verify */
1329 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1330 pSMB->SecurityFlags =
1331 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1334 pSMB->hdr.smb_buf_length += count;
1336 pSMB->ByteCount = cpu_to_le16(count);
1337 /* long_op set to 1 to allow for oplock break timeouts */
1338 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1339 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1340 cifs_stats_inc(&tcon->num_opens);
1342 cFYI(1, ("Error in Open = %d", rc));
1344 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1345 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1346 /* Let caller know file was created so we can set the mode. */
1347 /* Do we care about the CreateAction in any other cases? */
1348 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1349 *pOplock |= CIFS_CREATE_ACTION;
1351 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1352 36 /* CreationTime to Attributes */);
1353 /* the file_info buf is endian converted by caller */
1354 pfile_info->AllocationSize = pSMBr->AllocationSize;
1355 pfile_info->EndOfFile = pSMBr->EndOfFile;
1356 pfile_info->NumberOfLinks = cpu_to_le32(1);
1357 pfile_info->DeletePending = 0;
1361 cifs_buf_release(pSMB);
1368 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1369 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1370 char **buf, int *pbuf_type)
1373 READ_REQ *pSMB = NULL;
1374 READ_RSP *pSMBr = NULL;
1375 char *pReadData = NULL;
1377 int resp_buf_type = 0;
1380 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1381 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1384 wct = 10; /* old style read */
1385 if ((lseek >> 32) > 0) {
1386 /* can not handle this big offset for old */
1392 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1396 /* tcon and ses pointer are checked in smb_init */
1397 if (tcon->ses->server == NULL)
1398 return -ECONNABORTED;
1400 pSMB->AndXCommand = 0xFF; /* none */
1402 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1404 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1406 pSMB->Remaining = 0;
1407 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1408 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1410 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1412 /* old style read */
1413 struct smb_com_readx_req *pSMBW =
1414 (struct smb_com_readx_req *)pSMB;
1415 pSMBW->ByteCount = 0;
1418 iov[0].iov_base = (char *)pSMB;
1419 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1420 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1421 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1422 cifs_stats_inc(&tcon->num_reads);
1423 pSMBr = (READ_RSP *)iov[0].iov_base;
1425 cERROR(1, ("Send error in read = %d", rc));
1427 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1428 data_length = data_length << 16;
1429 data_length += le16_to_cpu(pSMBr->DataLength);
1430 *nbytes = data_length;
1432 /*check that DataLength would not go beyond end of SMB */
1433 if ((data_length > CIFSMaxBufSize)
1434 || (data_length > count)) {
1435 cFYI(1, ("bad length %d for count %d",
1436 data_length, count));
1440 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1441 le16_to_cpu(pSMBr->DataOffset);
1442 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1443 cERROR(1,("Faulting on read rc = %d",rc));
1445 }*/ /* can not use copy_to_user when using page cache*/
1447 memcpy(*buf, pReadData, data_length);
1451 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1453 if (resp_buf_type == CIFS_SMALL_BUFFER)
1454 cifs_small_buf_release(iov[0].iov_base);
1455 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1456 cifs_buf_release(iov[0].iov_base);
1457 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1458 /* return buffer to caller to free */
1459 *buf = iov[0].iov_base;
1460 if (resp_buf_type == CIFS_SMALL_BUFFER)
1461 *pbuf_type = CIFS_SMALL_BUFFER;
1462 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1463 *pbuf_type = CIFS_LARGE_BUFFER;
1464 } /* else no valid buffer on return - leave as null */
1466 /* Note: On -EAGAIN error only caller can retry on handle based calls
1467 since file handle passed in no longer valid */
1473 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1474 const int netfid, const unsigned int count,
1475 const __u64 offset, unsigned int *nbytes, const char *buf,
1476 const char __user *ubuf, const int long_op)
1479 WRITE_REQ *pSMB = NULL;
1480 WRITE_RSP *pSMBr = NULL;
1481 int bytes_returned, wct;
1485 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1486 if (tcon->ses == NULL)
1487 return -ECONNABORTED;
1489 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1493 if ((offset >> 32) > 0) {
1494 /* can not handle big offset for old srv */
1499 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1503 /* tcon and ses pointer are checked in smb_init */
1504 if (tcon->ses->server == NULL)
1505 return -ECONNABORTED;
1507 pSMB->AndXCommand = 0xFF; /* none */
1509 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1511 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1513 pSMB->Reserved = 0xFFFFFFFF;
1514 pSMB->WriteMode = 0;
1515 pSMB->Remaining = 0;
1517 /* Can increase buffer size if buffer is big enough in some cases ie we
1518 can send more if LARGE_WRITE_X capability returned by the server and if
1519 our buffer is big enough or if we convert to iovecs on socket writes
1520 and eliminate the copy to the CIFS buffer */
1521 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1522 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1524 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1528 if (bytes_sent > count)
1531 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1533 memcpy(pSMB->Data, buf, bytes_sent);
1535 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1536 cifs_buf_release(pSMB);
1539 } else if (count != 0) {
1541 cifs_buf_release(pSMB);
1543 } /* else setting file size with write of zero bytes */
1545 byte_count = bytes_sent + 1; /* pad */
1546 else /* wct == 12 */
1547 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1549 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1550 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1551 pSMB->hdr.smb_buf_length += byte_count;
1554 pSMB->ByteCount = cpu_to_le16(byte_count);
1555 else { /* old style write has byte count 4 bytes earlier
1557 struct smb_com_writex_req *pSMBW =
1558 (struct smb_com_writex_req *)pSMB;
1559 pSMBW->ByteCount = cpu_to_le16(byte_count);
1562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1563 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1564 cifs_stats_inc(&tcon->num_writes);
1566 cFYI(1, ("Send error in write = %d", rc));
1569 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1570 *nbytes = (*nbytes) << 16;
1571 *nbytes += le16_to_cpu(pSMBr->Count);
1574 cifs_buf_release(pSMB);
1576 /* Note: On -EAGAIN error only caller can retry on handle based calls
1577 since file handle passed in no longer valid */
1583 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1584 const int netfid, const unsigned int count,
1585 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1586 int n_vec, const int long_op)
1589 WRITE_REQ *pSMB = NULL;
1592 int resp_buf_type = 0;
1596 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1598 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1602 if ((offset >> 32) > 0) {
1603 /* can not handle big offset for old srv */
1607 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1610 /* tcon and ses pointer are checked in smb_init */
1611 if (tcon->ses->server == NULL)
1612 return -ECONNABORTED;
1614 pSMB->AndXCommand = 0xFF; /* none */
1616 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1618 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1619 pSMB->Reserved = 0xFFFFFFFF;
1620 pSMB->WriteMode = 0;
1621 pSMB->Remaining = 0;
1624 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1626 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1627 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1628 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1630 pSMB->hdr.smb_buf_length += count+1;
1631 else /* wct == 12 */
1632 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1634 pSMB->ByteCount = cpu_to_le16(count + 1);
1635 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1636 struct smb_com_writex_req *pSMBW =
1637 (struct smb_com_writex_req *)pSMB;
1638 pSMBW->ByteCount = cpu_to_le16(count + 5);
1640 iov[0].iov_base = pSMB;
1642 iov[0].iov_len = smb_hdr_len + 4;
1643 else /* wct == 12 pad bigger by four bytes */
1644 iov[0].iov_len = smb_hdr_len + 8;
1647 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1649 cifs_stats_inc(&tcon->num_writes);
1651 cFYI(1, ("Send error Write2 = %d", rc));
1652 } else if (resp_buf_type == 0) {
1653 /* presumably this can not happen, but best to be safe */
1656 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1657 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1658 *nbytes = (*nbytes) << 16;
1659 *nbytes += le16_to_cpu(pSMBr->Count);
1662 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1663 if (resp_buf_type == CIFS_SMALL_BUFFER)
1664 cifs_small_buf_release(iov[0].iov_base);
1665 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1666 cifs_buf_release(iov[0].iov_base);
1668 /* Note: On -EAGAIN error only caller can retry on handle based calls
1669 since file handle passed in no longer valid */
1676 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1677 const __u16 smb_file_id, const __u64 len,
1678 const __u64 offset, const __u32 numUnlock,
1679 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1682 LOCK_REQ *pSMB = NULL;
1683 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1688 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1689 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1694 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1695 timeout = CIFS_ASYNC_OP; /* no response expected */
1697 } else if (waitFlag) {
1698 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1699 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1704 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1705 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1706 pSMB->LockType = lockType;
1707 pSMB->AndXCommand = 0xFF; /* none */
1708 pSMB->Fid = smb_file_id; /* netfid stays le */
1710 if ((numLock != 0) || (numUnlock != 0)) {
1711 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1712 /* BB where to store pid high? */
1713 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1714 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1715 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1716 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1717 count = sizeof(LOCKING_ANDX_RANGE);
1722 pSMB->hdr.smb_buf_length += count;
1723 pSMB->ByteCount = cpu_to_le16(count);
1726 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1727 (struct smb_hdr *) pSMB, &bytes_returned);
1728 cifs_small_buf_release(pSMB);
1730 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1732 /* SMB buffer freed by function above */
1734 cifs_stats_inc(&tcon->num_locks);
1736 cFYI(1, ("Send error in Lock = %d", rc));
1738 /* Note: On -EAGAIN error only caller can retry on handle based calls
1739 since file handle passed in no longer valid */
1744 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1745 const __u16 smb_file_id, const int get_flag, const __u64 len,
1746 struct file_lock *pLockData, const __u16 lock_type,
1747 const bool waitFlag)
1749 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1750 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1751 struct cifs_posix_lock *parm_data;
1754 int bytes_returned = 0;
1755 int resp_buf_type = 0;
1756 __u16 params, param_offset, offset, byte_count, count;
1759 cFYI(1, ("Posix Lock"));
1761 if (pLockData == NULL)
1764 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1769 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1772 pSMB->MaxSetupCount = 0;
1775 pSMB->Reserved2 = 0;
1776 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1777 offset = param_offset + params;
1779 count = sizeof(struct cifs_posix_lock);
1780 pSMB->MaxParameterCount = cpu_to_le16(2);
1781 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1782 pSMB->SetupCount = 1;
1783 pSMB->Reserved3 = 0;
1785 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1787 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1788 byte_count = 3 /* pad */ + params + count;
1789 pSMB->DataCount = cpu_to_le16(count);
1790 pSMB->ParameterCount = cpu_to_le16(params);
1791 pSMB->TotalDataCount = pSMB->DataCount;
1792 pSMB->TotalParameterCount = pSMB->ParameterCount;
1793 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1794 parm_data = (struct cifs_posix_lock *)
1795 (((char *) &pSMB->hdr.Protocol) + offset);
1797 parm_data->lock_type = cpu_to_le16(lock_type);
1799 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1800 parm_data->lock_flags = cpu_to_le16(1);
1801 pSMB->Timeout = cpu_to_le32(-1);
1805 parm_data->pid = cpu_to_le32(current->tgid);
1806 parm_data->start = cpu_to_le64(pLockData->fl_start);
1807 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1809 pSMB->DataOffset = cpu_to_le16(offset);
1810 pSMB->Fid = smb_file_id;
1811 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1812 pSMB->Reserved4 = 0;
1813 pSMB->hdr.smb_buf_length += byte_count;
1814 pSMB->ByteCount = cpu_to_le16(byte_count);
1816 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1817 (struct smb_hdr *) pSMBr, &bytes_returned);
1819 iov[0].iov_base = (char *)pSMB;
1820 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1821 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1822 &resp_buf_type, timeout);
1823 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1824 not try to free it twice below on exit */
1825 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1829 cFYI(1, ("Send error in Posix Lock = %d", rc));
1830 } else if (get_flag) {
1831 /* lock structure can be returned on get */
1834 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1836 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1837 rc = -EIO; /* bad smb */
1840 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1841 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1842 if (data_count < sizeof(struct cifs_posix_lock)) {
1846 parm_data = (struct cifs_posix_lock *)
1847 ((char *)&pSMBr->hdr.Protocol + data_offset);
1848 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1849 pLockData->fl_type = F_UNLCK;
1854 cifs_small_buf_release(pSMB);
1856 if (resp_buf_type == CIFS_SMALL_BUFFER)
1857 cifs_small_buf_release(iov[0].iov_base);
1858 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1859 cifs_buf_release(iov[0].iov_base);
1861 /* Note: On -EAGAIN error only caller can retry on handle based calls
1862 since file handle passed in no longer valid */
1869 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1872 CLOSE_REQ *pSMB = NULL;
1873 cFYI(1, ("In CIFSSMBClose"));
1875 /* do not retry on dead session on close */
1876 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1882 pSMB->FileID = (__u16) smb_file_id;
1883 pSMB->LastWriteTime = 0xFFFFFFFF;
1884 pSMB->ByteCount = 0;
1885 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1886 cifs_stats_inc(&tcon->num_closes);
1889 /* EINTR is expected when user ctl-c to kill app */
1890 cERROR(1, ("Send error in Close = %d", rc));
1894 /* Since session is dead, file will be closed on server already */
1902 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1905 FLUSH_REQ *pSMB = NULL;
1906 cFYI(1, ("In CIFSSMBFlush"));
1908 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1912 pSMB->FileID = (__u16) smb_file_id;
1913 pSMB->ByteCount = 0;
1914 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1915 cifs_stats_inc(&tcon->num_flushes);
1917 cERROR(1, ("Send error in Flush = %d", rc));
1923 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1924 const char *fromName, const char *toName,
1925 const struct nls_table *nls_codepage, int remap)
1928 RENAME_REQ *pSMB = NULL;
1929 RENAME_RSP *pSMBr = NULL;
1931 int name_len, name_len2;
1934 cFYI(1, ("In CIFSSMBRename"));
1936 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1941 pSMB->BufferFormat = 0x04;
1942 pSMB->SearchAttributes =
1943 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1946 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1948 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1949 PATH_MAX, nls_codepage, remap);
1950 name_len++; /* trailing null */
1952 pSMB->OldFileName[name_len] = 0x04; /* pad */
1953 /* protocol requires ASCII signature byte on Unicode string */
1954 pSMB->OldFileName[name_len + 1] = 0x00;
1956 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1957 toName, PATH_MAX, nls_codepage, remap);
1958 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1959 name_len2 *= 2; /* convert to bytes */
1960 } else { /* BB improve the check for buffer overruns BB */
1961 name_len = strnlen(fromName, PATH_MAX);
1962 name_len++; /* trailing null */
1963 strncpy(pSMB->OldFileName, fromName, name_len);
1964 name_len2 = strnlen(toName, PATH_MAX);
1965 name_len2++; /* trailing null */
1966 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1967 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1968 name_len2++; /* trailing null */
1969 name_len2++; /* signature byte */
1972 count = 1 /* 1st signature byte */ + name_len + name_len2;
1973 pSMB->hdr.smb_buf_length += count;
1974 pSMB->ByteCount = cpu_to_le16(count);
1976 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1978 cifs_stats_inc(&tcon->num_renames);
1980 cFYI(1, ("Send error in rename = %d", rc));
1982 cifs_buf_release(pSMB);
1990 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1991 int netfid, const char *target_name,
1992 const struct nls_table *nls_codepage, int remap)
1994 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1995 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1996 struct set_file_rename *rename_info;
1998 char dummy_string[30];
2000 int bytes_returned = 0;
2002 __u16 params, param_offset, offset, count, byte_count;
2004 cFYI(1, ("Rename to File by handle"));
2005 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2011 pSMB->MaxSetupCount = 0;
2015 pSMB->Reserved2 = 0;
2016 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2017 offset = param_offset + params;
2019 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2020 rename_info = (struct set_file_rename *) data_offset;
2021 pSMB->MaxParameterCount = cpu_to_le16(2);
2022 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2023 pSMB->SetupCount = 1;
2024 pSMB->Reserved3 = 0;
2025 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2026 byte_count = 3 /* pad */ + params;
2027 pSMB->ParameterCount = cpu_to_le16(params);
2028 pSMB->TotalParameterCount = pSMB->ParameterCount;
2029 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2030 pSMB->DataOffset = cpu_to_le16(offset);
2031 /* construct random name ".cifs_tmp<inodenum><mid>" */
2032 rename_info->overwrite = cpu_to_le32(1);
2033 rename_info->root_fid = 0;
2034 /* unicode only call */
2035 if (target_name == NULL) {
2036 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2037 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2038 dummy_string, 24, nls_codepage, remap);
2040 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2041 target_name, PATH_MAX, nls_codepage,
2044 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2045 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2046 byte_count += count;
2047 pSMB->DataCount = cpu_to_le16(count);
2048 pSMB->TotalDataCount = pSMB->DataCount;
2050 pSMB->InformationLevel =
2051 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2052 pSMB->Reserved4 = 0;
2053 pSMB->hdr.smb_buf_length += byte_count;
2054 pSMB->ByteCount = cpu_to_le16(byte_count);
2055 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2056 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2057 cifs_stats_inc(&pTcon->num_t2renames);
2059 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2061 cifs_buf_release(pSMB);
2063 /* Note: On -EAGAIN error only caller can retry on handle based calls
2064 since file handle passed in no longer valid */
2070 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2071 const __u16 target_tid, const char *toName, const int flags,
2072 const struct nls_table *nls_codepage, int remap)
2075 COPY_REQ *pSMB = NULL;
2076 COPY_RSP *pSMBr = NULL;
2078 int name_len, name_len2;
2081 cFYI(1, ("In CIFSSMBCopy"));
2083 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2088 pSMB->BufferFormat = 0x04;
2089 pSMB->Tid2 = target_tid;
2091 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2093 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2094 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2095 fromName, PATH_MAX, nls_codepage,
2097 name_len++; /* trailing null */
2099 pSMB->OldFileName[name_len] = 0x04; /* pad */
2100 /* protocol requires ASCII signature byte on Unicode string */
2101 pSMB->OldFileName[name_len + 1] = 0x00;
2103 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2104 toName, PATH_MAX, nls_codepage, remap);
2105 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2106 name_len2 *= 2; /* convert to bytes */
2107 } else { /* BB improve the check for buffer overruns BB */
2108 name_len = strnlen(fromName, PATH_MAX);
2109 name_len++; /* trailing null */
2110 strncpy(pSMB->OldFileName, fromName, name_len);
2111 name_len2 = strnlen(toName, PATH_MAX);
2112 name_len2++; /* trailing null */
2113 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2114 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2115 name_len2++; /* trailing null */
2116 name_len2++; /* signature byte */
2119 count = 1 /* 1st signature byte */ + name_len + name_len2;
2120 pSMB->hdr.smb_buf_length += count;
2121 pSMB->ByteCount = cpu_to_le16(count);
2123 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2124 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2126 cFYI(1, ("Send error in copy = %d with %d files copied",
2127 rc, le16_to_cpu(pSMBr->CopyCount)));
2129 cifs_buf_release(pSMB);
2138 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2139 const char *fromName, const char *toName,
2140 const struct nls_table *nls_codepage)
2142 TRANSACTION2_SPI_REQ *pSMB = NULL;
2143 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2146 int name_len_target;
2148 int bytes_returned = 0;
2149 __u16 params, param_offset, offset, byte_count;
2151 cFYI(1, ("In Symlink Unix style"));
2153 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2158 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2160 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2161 /* find define for this maxpathcomponent */
2163 name_len++; /* trailing null */
2166 } else { /* BB improve the check for buffer overruns BB */
2167 name_len = strnlen(fromName, PATH_MAX);
2168 name_len++; /* trailing null */
2169 strncpy(pSMB->FileName, fromName, name_len);
2171 params = 6 + name_len;
2172 pSMB->MaxSetupCount = 0;
2176 pSMB->Reserved2 = 0;
2177 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2178 InformationLevel) - 4;
2179 offset = param_offset + params;
2181 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2182 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2184 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2185 /* find define for this maxpathcomponent */
2187 name_len_target++; /* trailing null */
2188 name_len_target *= 2;
2189 } else { /* BB improve the check for buffer overruns BB */
2190 name_len_target = strnlen(toName, PATH_MAX);
2191 name_len_target++; /* trailing null */
2192 strncpy(data_offset, toName, name_len_target);
2195 pSMB->MaxParameterCount = cpu_to_le16(2);
2196 /* BB find exact max on data count below from sess */
2197 pSMB->MaxDataCount = cpu_to_le16(1000);
2198 pSMB->SetupCount = 1;
2199 pSMB->Reserved3 = 0;
2200 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2201 byte_count = 3 /* pad */ + params + name_len_target;
2202 pSMB->DataCount = cpu_to_le16(name_len_target);
2203 pSMB->ParameterCount = cpu_to_le16(params);
2204 pSMB->TotalDataCount = pSMB->DataCount;
2205 pSMB->TotalParameterCount = pSMB->ParameterCount;
2206 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2207 pSMB->DataOffset = cpu_to_le16(offset);
2208 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2209 pSMB->Reserved4 = 0;
2210 pSMB->hdr.smb_buf_length += byte_count;
2211 pSMB->ByteCount = cpu_to_le16(byte_count);
2212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2214 cifs_stats_inc(&tcon->num_symlinks);
2216 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2218 cifs_buf_release(pSMB);
2221 goto createSymLinkRetry;
2227 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2228 const char *fromName, const char *toName,
2229 const struct nls_table *nls_codepage, int remap)
2231 TRANSACTION2_SPI_REQ *pSMB = NULL;
2232 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2235 int name_len_target;
2237 int bytes_returned = 0;
2238 __u16 params, param_offset, offset, byte_count;
2240 cFYI(1, ("In Create Hard link Unix style"));
2241 createHardLinkRetry:
2242 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2247 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2248 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2249 PATH_MAX, nls_codepage, remap);
2250 name_len++; /* trailing null */
2253 } else { /* BB improve the check for buffer overruns BB */
2254 name_len = strnlen(toName, PATH_MAX);
2255 name_len++; /* trailing null */
2256 strncpy(pSMB->FileName, toName, name_len);
2258 params = 6 + name_len;
2259 pSMB->MaxSetupCount = 0;
2263 pSMB->Reserved2 = 0;
2264 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2265 InformationLevel) - 4;
2266 offset = param_offset + params;
2268 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2269 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2271 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2272 nls_codepage, remap);
2273 name_len_target++; /* trailing null */
2274 name_len_target *= 2;
2275 } else { /* BB improve the check for buffer overruns BB */
2276 name_len_target = strnlen(fromName, PATH_MAX);
2277 name_len_target++; /* trailing null */
2278 strncpy(data_offset, fromName, name_len_target);
2281 pSMB->MaxParameterCount = cpu_to_le16(2);
2282 /* BB find exact max on data count below from sess*/
2283 pSMB->MaxDataCount = cpu_to_le16(1000);
2284 pSMB->SetupCount = 1;
2285 pSMB->Reserved3 = 0;
2286 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2287 byte_count = 3 /* pad */ + params + name_len_target;
2288 pSMB->ParameterCount = cpu_to_le16(params);
2289 pSMB->TotalParameterCount = pSMB->ParameterCount;
2290 pSMB->DataCount = cpu_to_le16(name_len_target);
2291 pSMB->TotalDataCount = pSMB->DataCount;
2292 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2293 pSMB->DataOffset = cpu_to_le16(offset);
2294 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2295 pSMB->Reserved4 = 0;
2296 pSMB->hdr.smb_buf_length += byte_count;
2297 pSMB->ByteCount = cpu_to_le16(byte_count);
2298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2300 cifs_stats_inc(&tcon->num_hardlinks);
2302 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2304 cifs_buf_release(pSMB);
2306 goto createHardLinkRetry;
2312 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2313 const char *fromName, const char *toName,
2314 const struct nls_table *nls_codepage, int remap)
2317 NT_RENAME_REQ *pSMB = NULL;
2318 RENAME_RSP *pSMBr = NULL;
2320 int name_len, name_len2;
2323 cFYI(1, ("In CIFSCreateHardLink"));
2324 winCreateHardLinkRetry:
2326 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2331 pSMB->SearchAttributes =
2332 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2334 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2335 pSMB->ClusterCount = 0;
2337 pSMB->BufferFormat = 0x04;
2339 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2341 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2342 PATH_MAX, nls_codepage, remap);
2343 name_len++; /* trailing null */
2346 /* protocol specifies ASCII buffer format (0x04) for unicode */
2347 pSMB->OldFileName[name_len] = 0x04;
2348 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2350 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2351 toName, PATH_MAX, nls_codepage, remap);
2352 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2353 name_len2 *= 2; /* convert to bytes */
2354 } else { /* BB improve the check for buffer overruns BB */
2355 name_len = strnlen(fromName, PATH_MAX);
2356 name_len++; /* trailing null */
2357 strncpy(pSMB->OldFileName, fromName, name_len);
2358 name_len2 = strnlen(toName, PATH_MAX);
2359 name_len2++; /* trailing null */
2360 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2361 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2362 name_len2++; /* trailing null */
2363 name_len2++; /* signature byte */
2366 count = 1 /* string type byte */ + name_len + name_len2;
2367 pSMB->hdr.smb_buf_length += count;
2368 pSMB->ByteCount = cpu_to_le16(count);
2370 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2371 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2372 cifs_stats_inc(&tcon->num_hardlinks);
2374 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2376 cifs_buf_release(pSMB);
2378 goto winCreateHardLinkRetry;
2384 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2385 const unsigned char *searchName,
2386 char *symlinkinfo, const int buflen,
2387 const struct nls_table *nls_codepage)
2389 /* SMB_QUERY_FILE_UNIX_LINK */
2390 TRANSACTION2_QPI_REQ *pSMB = NULL;
2391 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2395 __u16 params, byte_count;
2397 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2400 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2405 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2407 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2408 PATH_MAX, nls_codepage);
2409 name_len++; /* trailing null */
2411 } else { /* BB improve the check for buffer overruns BB */
2412 name_len = strnlen(searchName, PATH_MAX);
2413 name_len++; /* trailing null */
2414 strncpy(pSMB->FileName, searchName, name_len);
2417 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2418 pSMB->TotalDataCount = 0;
2419 pSMB->MaxParameterCount = cpu_to_le16(2);
2420 /* BB find exact max data count below from sess structure BB */
2421 pSMB->MaxDataCount = cpu_to_le16(4000);
2422 pSMB->MaxSetupCount = 0;
2426 pSMB->Reserved2 = 0;
2427 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2428 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2429 pSMB->DataCount = 0;
2430 pSMB->DataOffset = 0;
2431 pSMB->SetupCount = 1;
2432 pSMB->Reserved3 = 0;
2433 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2434 byte_count = params + 1 /* pad */ ;
2435 pSMB->TotalParameterCount = cpu_to_le16(params);
2436 pSMB->ParameterCount = pSMB->TotalParameterCount;
2437 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2438 pSMB->Reserved4 = 0;
2439 pSMB->hdr.smb_buf_length += byte_count;
2440 pSMB->ByteCount = cpu_to_le16(byte_count);
2442 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2443 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2445 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2447 /* decode response */
2449 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2450 if (rc || (pSMBr->ByteCount < 2))
2451 /* BB also check enough total bytes returned */
2452 rc = -EIO; /* bad smb */
2454 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2455 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2457 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2458 name_len = UniStrnlen((wchar_t *) ((char *)
2459 &pSMBr->hdr.Protocol + data_offset),
2460 min_t(const int, buflen, count) / 2);
2461 /* BB FIXME investigate remapping reserved chars here */
2462 cifs_strfromUCS_le(symlinkinfo,
2463 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2465 name_len, nls_codepage);
2467 strncpy(symlinkinfo,
2468 (char *) &pSMBr->hdr.Protocol +
2470 min_t(const int, buflen, count));
2472 symlinkinfo[buflen] = 0;
2473 /* just in case so calling code does not go off the end of buffer */
2476 cifs_buf_release(pSMB);
2478 goto querySymLinkRetry;
2482 #ifdef CONFIG_CIFS_EXPERIMENTAL
2483 /* Initialize NT TRANSACT SMB into small smb request buffer.
2484 This assumes that all NT TRANSACTS that we init here have
2485 total parm and data under about 400 bytes (to fit in small cifs
2486 buffer size), which is the case so far, it easily fits. NB:
2487 Setup words themselves and ByteCount
2488 MaxSetupCount (size of returned setup area) and
2489 MaxParameterCount (returned parms size) must be set by caller */
2491 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2492 const int parm_len, struct cifsTconInfo *tcon,
2497 struct smb_com_ntransact_req *pSMB;
2499 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2503 *ret_buf = (void *)pSMB;
2505 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2506 pSMB->TotalDataCount = 0;
2507 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2508 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2509 pSMB->ParameterCount = pSMB->TotalParameterCount;
2510 pSMB->DataCount = pSMB->TotalDataCount;
2511 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2512 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2513 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2514 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2515 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2516 pSMB->SubCommand = cpu_to_le16(sub_command);
2521 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2522 __u32 *pparmlen, __u32 *pdatalen)
2525 __u32 data_count, data_offset, parm_count, parm_offset;
2526 struct smb_com_ntransact_rsp *pSMBr;
2534 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2536 /* ByteCount was converted from little endian in SendReceive */
2537 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2538 (char *)&pSMBr->ByteCount;
2540 data_offset = le32_to_cpu(pSMBr->DataOffset);
2541 data_count = le32_to_cpu(pSMBr->DataCount);
2542 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2543 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2545 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2546 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2548 /* should we also check that parm and data areas do not overlap? */
2549 if (*ppparm > end_of_smb) {
2550 cFYI(1, ("parms start after end of smb"));
2552 } else if (parm_count + *ppparm > end_of_smb) {
2553 cFYI(1, ("parm end after end of smb"));
2555 } else if (*ppdata > end_of_smb) {
2556 cFYI(1, ("data starts after end of smb"));
2558 } else if (data_count + *ppdata > end_of_smb) {
2559 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2560 *ppdata, data_count, (data_count + *ppdata),
2561 end_of_smb, pSMBr));
2563 } else if (parm_count + data_count > pSMBr->ByteCount) {
2564 cFYI(1, ("parm count and data count larger than SMB"));
2567 *pdatalen = data_count;
2568 *pparmlen = parm_count;
2571 #endif /* CIFS_EXPERIMENTAL */
2574 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2575 const unsigned char *searchName,
2576 char *symlinkinfo, const int buflen, __u16 fid,
2577 const struct nls_table *nls_codepage)
2582 struct smb_com_transaction_ioctl_req *pSMB;
2583 struct smb_com_transaction_ioctl_rsp *pSMBr;
2585 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2586 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2591 pSMB->TotalParameterCount = 0 ;
2592 pSMB->TotalDataCount = 0;
2593 pSMB->MaxParameterCount = cpu_to_le32(2);
2594 /* BB find exact data count max from sess structure BB */
2595 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2596 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2597 pSMB->MaxSetupCount = 4;
2599 pSMB->ParameterOffset = 0;
2600 pSMB->DataCount = 0;
2601 pSMB->DataOffset = 0;
2602 pSMB->SetupCount = 4;
2603 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2604 pSMB->ParameterCount = pSMB->TotalParameterCount;
2605 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2606 pSMB->IsFsctl = 1; /* FSCTL */
2607 pSMB->IsRootFlag = 0;
2608 pSMB->Fid = fid; /* file handle always le */
2609 pSMB->ByteCount = 0;
2611 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2612 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2614 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2615 } else { /* decode response */
2616 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2617 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2618 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2619 /* BB also check enough total bytes returned */
2620 rc = -EIO; /* bad smb */
2622 if (data_count && (data_count < 2048)) {
2623 char *end_of_smb = 2 /* sizeof byte count */ +
2625 (char *)&pSMBr->ByteCount;
2627 struct reparse_data *reparse_buf =
2628 (struct reparse_data *)
2629 ((char *)&pSMBr->hdr.Protocol
2631 if ((char *)reparse_buf >= end_of_smb) {
2635 if ((reparse_buf->LinkNamesBuf +
2636 reparse_buf->TargetNameOffset +
2637 reparse_buf->TargetNameLen) >
2639 cFYI(1, ("reparse buf beyond SMB"));
2644 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2645 name_len = UniStrnlen((wchar_t *)
2646 (reparse_buf->LinkNamesBuf +
2647 reparse_buf->TargetNameOffset),
2649 reparse_buf->TargetNameLen / 2));
2650 cifs_strfromUCS_le(symlinkinfo,
2651 (__le16 *) (reparse_buf->LinkNamesBuf +
2652 reparse_buf->TargetNameOffset),
2653 name_len, nls_codepage);
2654 } else { /* ASCII names */
2655 strncpy(symlinkinfo,
2656 reparse_buf->LinkNamesBuf +
2657 reparse_buf->TargetNameOffset,
2658 min_t(const int, buflen,
2659 reparse_buf->TargetNameLen));
2663 cFYI(1, ("Invalid return data count on "
2664 "get reparse info ioctl"));
2666 symlinkinfo[buflen] = 0; /* just in case so the caller
2667 does not go off the end of the buffer */
2668 cFYI(1, ("readlink result - %s", symlinkinfo));
2672 cifs_buf_release(pSMB);
2674 /* Note: On -EAGAIN error only caller can retry on handle based calls
2675 since file handle passed in no longer valid */
2680 #ifdef CONFIG_CIFS_POSIX
2682 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2683 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2684 struct cifs_posix_ace *cifs_ace)
2686 /* u8 cifs fields do not need le conversion */
2687 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2688 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2689 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2690 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2695 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2696 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2697 const int acl_type, const int size_of_data_area)
2702 struct cifs_posix_ace *pACE;
2703 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2704 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2706 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2709 if (acl_type & ACL_TYPE_ACCESS) {
2710 count = le16_to_cpu(cifs_acl->access_entry_count);
2711 pACE = &cifs_acl->ace_array[0];
2712 size = sizeof(struct cifs_posix_acl);
2713 size += sizeof(struct cifs_posix_ace) * count;
2714 /* check if we would go beyond end of SMB */
2715 if (size_of_data_area < size) {
2716 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2717 size_of_data_area, size));
2720 } else if (acl_type & ACL_TYPE_DEFAULT) {
2721 count = le16_to_cpu(cifs_acl->access_entry_count);
2722 size = sizeof(struct cifs_posix_acl);
2723 size += sizeof(struct cifs_posix_ace) * count;
2724 /* skip past access ACEs to get to default ACEs */
2725 pACE = &cifs_acl->ace_array[count];
2726 count = le16_to_cpu(cifs_acl->default_entry_count);
2727 size += sizeof(struct cifs_posix_ace) * count;
2728 /* check if we would go beyond end of SMB */
2729 if (size_of_data_area < size)
2736 size = posix_acl_xattr_size(count);
2737 if ((buflen == 0) || (local_acl == NULL)) {
2738 /* used to query ACL EA size */
2739 } else if (size > buflen) {
2741 } else /* buffer big enough */ {
2742 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2743 for (i = 0; i < count ; i++) {
2744 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2751 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2752 const posix_acl_xattr_entry *local_ace)
2754 __u16 rc = 0; /* 0 = ACL converted ok */
2756 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2757 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2758 /* BB is there a better way to handle the large uid? */
2759 if (local_ace->e_id == cpu_to_le32(-1)) {
2760 /* Probably no need to le convert -1 on any arch but can not hurt */
2761 cifs_ace->cifs_uid = cpu_to_le64(-1);
2763 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2764 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2768 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2769 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2770 const int buflen, const int acl_type)
2773 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2774 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2778 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2781 count = posix_acl_xattr_count((size_t)buflen);
2782 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2784 count, buflen, le32_to_cpu(local_acl->a_version)));
2785 if (le32_to_cpu(local_acl->a_version) != 2) {
2786 cFYI(1, ("unknown POSIX ACL version %d",
2787 le32_to_cpu(local_acl->a_version)));
2790 cifs_acl->version = cpu_to_le16(1);
2791 if (acl_type == ACL_TYPE_ACCESS)
2792 cifs_acl->access_entry_count = cpu_to_le16(count);
2793 else if (acl_type == ACL_TYPE_DEFAULT)
2794 cifs_acl->default_entry_count = cpu_to_le16(count);
2796 cFYI(1, ("unknown ACL type %d", acl_type));
2799 for (i = 0; i < count; i++) {
2800 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2801 &local_acl->a_entries[i]);
2803 /* ACE not converted */
2808 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2809 rc += sizeof(struct cifs_posix_acl);
2810 /* BB add check to make sure ACL does not overflow SMB */
2816 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2817 const unsigned char *searchName,
2818 char *acl_inf, const int buflen, const int acl_type,
2819 const struct nls_table *nls_codepage, int remap)
2821 /* SMB_QUERY_POSIX_ACL */
2822 TRANSACTION2_QPI_REQ *pSMB = NULL;
2823 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2827 __u16 params, byte_count;
2829 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2832 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2837 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2839 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2840 PATH_MAX, nls_codepage, remap);
2841 name_len++; /* trailing null */
2843 pSMB->FileName[name_len] = 0;
2844 pSMB->FileName[name_len+1] = 0;
2845 } else { /* BB improve the check for buffer overruns BB */
2846 name_len = strnlen(searchName, PATH_MAX);
2847 name_len++; /* trailing null */
2848 strncpy(pSMB->FileName, searchName, name_len);
2851 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2852 pSMB->TotalDataCount = 0;
2853 pSMB->MaxParameterCount = cpu_to_le16(2);
2854 /* BB find exact max data count below from sess structure BB */
2855 pSMB->MaxDataCount = cpu_to_le16(4000);
2856 pSMB->MaxSetupCount = 0;
2860 pSMB->Reserved2 = 0;
2861 pSMB->ParameterOffset = cpu_to_le16(
2862 offsetof(struct smb_com_transaction2_qpi_req,
2863 InformationLevel) - 4);
2864 pSMB->DataCount = 0;
2865 pSMB->DataOffset = 0;
2866 pSMB->SetupCount = 1;
2867 pSMB->Reserved3 = 0;
2868 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2869 byte_count = params + 1 /* pad */ ;
2870 pSMB->TotalParameterCount = cpu_to_le16(params);
2871 pSMB->ParameterCount = pSMB->TotalParameterCount;
2872 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2873 pSMB->Reserved4 = 0;
2874 pSMB->hdr.smb_buf_length += byte_count;
2875 pSMB->ByteCount = cpu_to_le16(byte_count);
2877 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2878 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2879 cifs_stats_inc(&tcon->num_acl_get);
2881 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2883 /* decode response */
2885 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2886 if (rc || (pSMBr->ByteCount < 2))
2887 /* BB also check enough total bytes returned */
2888 rc = -EIO; /* bad smb */
2890 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2891 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2892 rc = cifs_copy_posix_acl(acl_inf,
2893 (char *)&pSMBr->hdr.Protocol+data_offset,
2894 buflen, acl_type, count);
2897 cifs_buf_release(pSMB);
2904 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2905 const unsigned char *fileName,
2906 const char *local_acl, const int buflen,
2908 const struct nls_table *nls_codepage, int remap)
2910 struct smb_com_transaction2_spi_req *pSMB = NULL;
2911 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2915 int bytes_returned = 0;
2916 __u16 params, byte_count, data_count, param_offset, offset;
2918 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2920 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2924 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2926 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2927 PATH_MAX, nls_codepage, remap);
2928 name_len++; /* trailing null */
2930 } else { /* BB improve the check for buffer overruns BB */
2931 name_len = strnlen(fileName, PATH_MAX);
2932 name_len++; /* trailing null */
2933 strncpy(pSMB->FileName, fileName, name_len);
2935 params = 6 + name_len;
2936 pSMB->MaxParameterCount = cpu_to_le16(2);
2937 /* BB find max SMB size from sess */
2938 pSMB->MaxDataCount = cpu_to_le16(1000);
2939 pSMB->MaxSetupCount = 0;
2943 pSMB->Reserved2 = 0;
2944 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2945 InformationLevel) - 4;
2946 offset = param_offset + params;
2947 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2948 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2950 /* convert to on the wire format for POSIX ACL */
2951 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2953 if (data_count == 0) {
2955 goto setACLerrorExit;
2957 pSMB->DataOffset = cpu_to_le16(offset);
2958 pSMB->SetupCount = 1;
2959 pSMB->Reserved3 = 0;
2960 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2961 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2962 byte_count = 3 /* pad */ + params + data_count;
2963 pSMB->DataCount = cpu_to_le16(data_count);
2964 pSMB->TotalDataCount = pSMB->DataCount;
2965 pSMB->ParameterCount = cpu_to_le16(params);
2966 pSMB->TotalParameterCount = pSMB->ParameterCount;
2967 pSMB->Reserved4 = 0;
2968 pSMB->hdr.smb_buf_length += byte_count;
2969 pSMB->ByteCount = cpu_to_le16(byte_count);
2970 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2971 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2973 cFYI(1, ("Set POSIX ACL returned %d", rc));
2976 cifs_buf_release(pSMB);
2982 /* BB fix tabs in this function FIXME BB */
2984 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2985 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2988 struct smb_t2_qfi_req *pSMB = NULL;
2989 struct smb_t2_qfi_rsp *pSMBr = NULL;
2991 __u16 params, byte_count;
2993 cFYI(1, ("In GetExtAttr"));
2998 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3003 params = 2 /* level */ + 2 /* fid */;
3004 pSMB->t2.TotalDataCount = 0;
3005 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3006 /* BB find exact max data count below from sess structure BB */
3007 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3008 pSMB->t2.MaxSetupCount = 0;
3009 pSMB->t2.Reserved = 0;
3011 pSMB->t2.Timeout = 0;
3012 pSMB->t2.Reserved2 = 0;
3013 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3015 pSMB->t2.DataCount = 0;
3016 pSMB->t2.DataOffset = 0;
3017 pSMB->t2.SetupCount = 1;
3018 pSMB->t2.Reserved3 = 0;
3019 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3020 byte_count = params + 1 /* pad */ ;
3021 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3022 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3023 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3026 pSMB->hdr.smb_buf_length += byte_count;
3027 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3029 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3030 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3032 cFYI(1, ("error %d in GetExtAttr", rc));
3034 /* decode response */
3035 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3036 if (rc || (pSMBr->ByteCount < 2))
3037 /* BB also check enough total bytes returned */
3038 /* If rc should we check for EOPNOSUPP and
3039 disable the srvino flag? or in caller? */
3040 rc = -EIO; /* bad smb */
3042 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3043 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3044 struct file_chattr_info *pfinfo;
3045 /* BB Do we need a cast or hash here ? */
3047 cFYI(1, ("Illegal size ret in GetExtAttr"));
3051 pfinfo = (struct file_chattr_info *)
3052 (data_offset + (char *) &pSMBr->hdr.Protocol);
3053 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3054 *pMask = le64_to_cpu(pfinfo->mask);
3058 cifs_buf_release(pSMB);
3060 goto GetExtAttrRetry;
3064 #endif /* CONFIG_POSIX */
3066 #ifdef CONFIG_CIFS_EXPERIMENTAL
3067 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3069 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3070 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3074 QUERY_SEC_DESC_REQ *pSMB;
3077 cFYI(1, ("GetCifsACL"));
3082 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3083 8 /* parm len */, tcon, (void **) &pSMB);
3087 pSMB->MaxParameterCount = cpu_to_le32(4);
3088 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3089 pSMB->MaxSetupCount = 0;
3090 pSMB->Fid = fid; /* file handle always le */
3091 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3093 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3094 pSMB->hdr.smb_buf_length += 11;
3095 iov[0].iov_base = (char *)pSMB;
3096 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3098 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3100 cifs_stats_inc(&tcon->num_acl_get);
3102 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3103 } else { /* decode response */
3107 struct smb_com_ntransact_rsp *pSMBr;
3110 /* validate_nttransact */
3111 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3112 &pdata, &parm_len, pbuflen);
3115 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3117 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3119 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3120 rc = -EIO; /* bad smb */
3125 /* BB check that data area is minimum length and as big as acl_len */
3127 acl_len = le32_to_cpu(*parm);
3128 if (acl_len != *pbuflen) {
3129 cERROR(1, ("acl length %d does not match %d",
3130 acl_len, *pbuflen));
3131 if (*pbuflen > acl_len)
3135 /* check if buffer is big enough for the acl
3136 header followed by the smallest SID */
3137 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3138 (*pbuflen >= 64 * 1024)) {
3139 cERROR(1, ("bad acl length %d", *pbuflen));
3143 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3144 if (*acl_inf == NULL) {
3148 memcpy(*acl_inf, pdata, *pbuflen);
3152 if (buf_type == CIFS_SMALL_BUFFER)
3153 cifs_small_buf_release(iov[0].iov_base);
3154 else if (buf_type == CIFS_LARGE_BUFFER)
3155 cifs_buf_release(iov[0].iov_base);
3156 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3161 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3162 struct cifs_ntsd *pntsd, __u32 acllen)
3164 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3166 int bytes_returned = 0;
3167 SET_SEC_DESC_REQ *pSMB = NULL;
3168 NTRANSACT_RSP *pSMBr = NULL;
3171 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3176 pSMB->MaxSetupCount = 0;
3180 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3181 data_count = acllen;
3182 data_offset = param_offset + param_count;
3183 byte_count = 3 /* pad */ + param_count;
3185 pSMB->DataCount = cpu_to_le32(data_count);
3186 pSMB->TotalDataCount = pSMB->DataCount;
3187 pSMB->MaxParameterCount = cpu_to_le32(4);
3188 pSMB->MaxDataCount = cpu_to_le32(16384);
3189 pSMB->ParameterCount = cpu_to_le32(param_count);
3190 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3191 pSMB->TotalParameterCount = pSMB->ParameterCount;
3192 pSMB->DataOffset = cpu_to_le32(data_offset);
3193 pSMB->SetupCount = 0;
3194 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3195 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3197 pSMB->Fid = fid; /* file handle always le */
3198 pSMB->Reserved2 = 0;
3199 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3201 if (pntsd && acllen) {
3202 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3205 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3208 pSMB->hdr.smb_buf_length += byte_count;
3210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3213 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3215 cFYI(1, ("Set CIFS ACL returned %d", rc));
3216 cifs_buf_release(pSMB);
3219 goto setCifsAclRetry;
3224 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3226 /* Legacy Query Path Information call for lookup to old servers such
3228 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3229 const unsigned char *searchName,
3230 FILE_ALL_INFO *pFinfo,
3231 const struct nls_table *nls_codepage, int remap)
3233 QUERY_INFORMATION_REQ *pSMB;
3234 QUERY_INFORMATION_RSP *pSMBr;
3239 cFYI(1, ("In SMBQPath path %s", searchName));
3241 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3246 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3248 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3249 PATH_MAX, nls_codepage, remap);
3250 name_len++; /* trailing null */
3253 name_len = strnlen(searchName, PATH_MAX);
3254 name_len++; /* trailing null */
3255 strncpy(pSMB->FileName, searchName, name_len);
3257 pSMB->BufferFormat = 0x04;
3258 name_len++; /* account for buffer type byte */
3259 pSMB->hdr.smb_buf_length += (__u16) name_len;
3260 pSMB->ByteCount = cpu_to_le16(name_len);
3262 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3263 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3265 cFYI(1, ("Send error in QueryInfo = %d", rc));
3266 } else if (pFinfo) {
3268 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3270 /* decode response */
3271 /* BB FIXME - add time zone adjustment BB */
3272 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3275 /* decode time fields */
3276 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3277 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3278 pFinfo->LastAccessTime = 0;
3279 pFinfo->AllocationSize =
3280 cpu_to_le64(le32_to_cpu(pSMBr->size));
3281 pFinfo->EndOfFile = pFinfo->AllocationSize;
3282 pFinfo->Attributes =
3283 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3285 rc = -EIO; /* bad buffer passed in */
3287 cifs_buf_release(pSMB);
3299 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3300 const unsigned char *searchName,
3301 FILE_ALL_INFO *pFindData,
3302 int legacy /* old style infolevel */,
3303 const struct nls_table *nls_codepage, int remap)
3305 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3306 TRANSACTION2_QPI_REQ *pSMB = NULL;
3307 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3311 __u16 params, byte_count;
3313 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3315 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3320 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3322 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3323 PATH_MAX, nls_codepage, remap);
3324 name_len++; /* trailing null */
3326 } else { /* BB improve the check for buffer overruns BB */
3327 name_len = strnlen(searchName, PATH_MAX);
3328 name_len++; /* trailing null */
3329 strncpy(pSMB->FileName, searchName, name_len);
3332 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3333 pSMB->TotalDataCount = 0;
3334 pSMB->MaxParameterCount = cpu_to_le16(2);
3335 /* BB find exact max SMB PDU from sess structure BB */
3336 pSMB->MaxDataCount = cpu_to_le16(4000);
3337 pSMB->MaxSetupCount = 0;
3341 pSMB->Reserved2 = 0;
3342 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3343 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3344 pSMB->DataCount = 0;
3345 pSMB->DataOffset = 0;
3346 pSMB->SetupCount = 1;
3347 pSMB->Reserved3 = 0;
3348 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3349 byte_count = params + 1 /* pad */ ;
3350 pSMB->TotalParameterCount = cpu_to_le16(params);
3351 pSMB->ParameterCount = pSMB->TotalParameterCount;
3353 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3355 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3356 pSMB->Reserved4 = 0;
3357 pSMB->hdr.smb_buf_length += byte_count;
3358 pSMB->ByteCount = cpu_to_le16(byte_count);
3360 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3361 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3363 cFYI(1, ("Send error in QPathInfo = %d", rc));
3364 } else { /* decode response */
3365 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3367 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3369 else if (!legacy && (pSMBr->ByteCount < 40))
3370 rc = -EIO; /* bad smb */
3371 else if (legacy && (pSMBr->ByteCount < 24))
3372 rc = -EIO; /* 24 or 26 expected but we do not read
3374 else if (pFindData) {
3376 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3378 /* On legacy responses we do not read the last field,
3379 EAsize, fortunately since it varies by subdialect and
3380 also note it differs on Set vs. Get, ie two bytes or 4
3381 bytes depending but we don't care here */
3383 size = sizeof(FILE_INFO_STANDARD);
3385 size = sizeof(FILE_ALL_INFO);
3386 memcpy((char *) pFindData,
3387 (char *) &pSMBr->hdr.Protocol +
3392 cifs_buf_release(pSMB);
3394 goto QPathInfoRetry;
3400 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3401 const unsigned char *searchName,
3402 FILE_UNIX_BASIC_INFO *pFindData,
3403 const struct nls_table *nls_codepage, int remap)
3405 /* SMB_QUERY_FILE_UNIX_BASIC */
3406 TRANSACTION2_QPI_REQ *pSMB = NULL;
3407 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3409 int bytes_returned = 0;
3411 __u16 params, byte_count;
3413 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3415 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3420 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3422 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3423 PATH_MAX, nls_codepage, remap);
3424 name_len++; /* trailing null */
3426 } else { /* BB improve the check for buffer overruns BB */
3427 name_len = strnlen(searchName, PATH_MAX);
3428 name_len++; /* trailing null */
3429 strncpy(pSMB->FileName, searchName, name_len);
3432 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3433 pSMB->TotalDataCount = 0;
3434 pSMB->MaxParameterCount = cpu_to_le16(2);
3435 /* BB find exact max SMB PDU from sess structure BB */
3436 pSMB->MaxDataCount = cpu_to_le16(4000);
3437 pSMB->MaxSetupCount = 0;
3441 pSMB->Reserved2 = 0;
3442 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3443 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3444 pSMB->DataCount = 0;
3445 pSMB->DataOffset = 0;
3446 pSMB->SetupCount = 1;
3447 pSMB->Reserved3 = 0;
3448 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3449 byte_count = params + 1 /* pad */ ;
3450 pSMB->TotalParameterCount = cpu_to_le16(params);
3451 pSMB->ParameterCount = pSMB->TotalParameterCount;
3452 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3453 pSMB->Reserved4 = 0;
3454 pSMB->hdr.smb_buf_length += byte_count;
3455 pSMB->ByteCount = cpu_to_le16(byte_count);
3457 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3458 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3460 cFYI(1, ("Send error in QPathInfo = %d", rc));
3461 } else { /* decode response */
3462 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3464 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3465 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3466 "Unix Extensions can be disabled on mount "
3467 "by specifying the nosfu mount option."));
3468 rc = -EIO; /* bad smb */
3470 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3471 memcpy((char *) pFindData,
3472 (char *) &pSMBr->hdr.Protocol +
3474 sizeof(FILE_UNIX_BASIC_INFO));
3477 cifs_buf_release(pSMB);
3479 goto UnixQPathInfoRetry;
3484 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3486 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3487 const char *searchName,
3488 const struct nls_table *nls_codepage,
3490 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3492 /* level 257 SMB_ */
3493 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3494 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3495 T2_FFIRST_RSP_PARMS *parms;
3497 int bytes_returned = 0;
3499 __u16 params, byte_count;
3501 cFYI(1, ("In FindFirst for %s", searchName));
3504 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3509 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3511 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3512 PATH_MAX, nls_codepage, remap);
3513 /* We can not add the asterik earlier in case
3514 it got remapped to 0xF03A as if it were part of the
3515 directory name instead of a wildcard */
3517 pSMB->FileName[name_len] = dirsep;
3518 pSMB->FileName[name_len+1] = 0;
3519 pSMB->FileName[name_len+2] = '*';
3520 pSMB->FileName[name_len+3] = 0;
3521 name_len += 4; /* now the trailing null */
3522 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3523 pSMB->FileName[name_len+1] = 0;
3525 } else { /* BB add check for overrun of SMB buf BB */
3526 name_len = strnlen(searchName, PATH_MAX);
3527 /* BB fix here and in unicode clause above ie
3528 if (name_len > buffersize-header)
3529 free buffer exit; BB */
3530 strncpy(pSMB->FileName, searchName, name_len);
3531 pSMB->FileName[name_len] = dirsep;
3532 pSMB->FileName[name_len+1] = '*';
3533 pSMB->FileName[name_len+2] = 0;
3537 params = 12 + name_len /* includes null */ ;
3538 pSMB->TotalDataCount = 0; /* no EAs */
3539 pSMB->MaxParameterCount = cpu_to_le16(10);
3540 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3541 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3542 pSMB->MaxSetupCount = 0;
3546 pSMB->Reserved2 = 0;
3547 byte_count = params + 1 /* pad */ ;
3548 pSMB->TotalParameterCount = cpu_to_le16(params);
3549 pSMB->ParameterCount = pSMB->TotalParameterCount;
3550 pSMB->ParameterOffset = cpu_to_le16(
3551 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3553 pSMB->DataCount = 0;
3554 pSMB->DataOffset = 0;
3555 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3556 pSMB->Reserved3 = 0;
3557 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3558 pSMB->SearchAttributes =
3559 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3561 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3562 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3563 CIFS_SEARCH_RETURN_RESUME);
3564 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3566 /* BB what should we set StorageType to? Does it matter? BB */
3567 pSMB->SearchStorageType = 0;
3568 pSMB->hdr.smb_buf_length += byte_count;
3569 pSMB->ByteCount = cpu_to_le16(byte_count);
3571 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3572 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3573 cifs_stats_inc(&tcon->num_ffirst);
3575 if (rc) {/* BB add logic to retry regular search if Unix search
3576 rejected unexpectedly by server */
3577 /* BB Add code to handle unsupported level rc */
3578 cFYI(1, ("Error in FindFirst = %d", rc));
3580 cifs_buf_release(pSMB);
3582 /* BB eventually could optimize out free and realloc of buf */
3585 goto findFirstRetry;
3586 } else { /* decode response */
3587 /* BB remember to free buffer if error BB */
3588 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3592 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3593 psrch_inf->unicode = true;
3595 psrch_inf->unicode = false;
3597 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3598 psrch_inf->smallBuf = 0;
3599 psrch_inf->srch_entries_start =
3600 (char *) &pSMBr->hdr.Protocol +
3601 le16_to_cpu(pSMBr->t2.DataOffset);
3602 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3603 le16_to_cpu(pSMBr->t2.ParameterOffset));
3605 if (parms->EndofSearch)
3606 psrch_inf->endOfSearch = true;
3608 psrch_inf->endOfSearch = false;
3610 psrch_inf->entries_in_buffer =
3611 le16_to_cpu(parms->SearchCount);
3612 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3613 psrch_inf->entries_in_buffer;
3614 lnoff = le16_to_cpu(parms->LastNameOffset);
3615 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3617 cERROR(1, ("ignoring corrupt resume name"));
3618 psrch_inf->last_entry = NULL;
3622 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3625 *pnetfid = parms->SearchHandle;
3627 cifs_buf_release(pSMB);
3634 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3635 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3637 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3638 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3639 T2_FNEXT_RSP_PARMS *parms;
3640 char *response_data;
3642 int bytes_returned, name_len;
3643 __u16 params, byte_count;
3645 cFYI(1, ("In FindNext"));
3647 if (psrch_inf->endOfSearch)
3650 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3655 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3657 pSMB->TotalDataCount = 0; /* no EAs */
3658 pSMB->MaxParameterCount = cpu_to_le16(8);
3659 pSMB->MaxDataCount =
3660 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3662 pSMB->MaxSetupCount = 0;
3666 pSMB->Reserved2 = 0;
3667 pSMB->ParameterOffset = cpu_to_le16(
3668 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3669 pSMB->DataCount = 0;
3670 pSMB->DataOffset = 0;
3671 pSMB->SetupCount = 1;
3672 pSMB->Reserved3 = 0;
3673 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3674 pSMB->SearchHandle = searchHandle; /* always kept as le */
3676 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3677 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3678 pSMB->ResumeKey = psrch_inf->resume_key;
3680 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3682 name_len = psrch_inf->resume_name_len;
3684 if (name_len < PATH_MAX) {
3685 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3686 byte_count += name_len;
3687 /* 14 byte parm len above enough for 2 byte null terminator */
3688 pSMB->ResumeFileName[name_len] = 0;
3689 pSMB->ResumeFileName[name_len+1] = 0;
3692 goto FNext2_err_exit;
3694 byte_count = params + 1 /* pad */ ;
3695 pSMB->TotalParameterCount = cpu_to_le16(params);
3696 pSMB->ParameterCount = pSMB->TotalParameterCount;
3697 pSMB->hdr.smb_buf_length += byte_count;
3698 pSMB->ByteCount = cpu_to_le16(byte_count);
3700 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3701 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3702 cifs_stats_inc(&tcon->num_fnext);
3705 psrch_inf->endOfSearch = true;
3706 cifs_buf_release(pSMB);
3707 rc = 0; /* search probably was closed at end of search*/
3709 cFYI(1, ("FindNext returned = %d", rc));
3710 } else { /* decode response */
3711 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3716 /* BB fixme add lock for file (srch_info) struct here */
3717 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3718 psrch_inf->unicode = true;
3720 psrch_inf->unicode = false;
3721 response_data = (char *) &pSMBr->hdr.Protocol +
3722 le16_to_cpu(pSMBr->t2.ParameterOffset);
3723 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3724 response_data = (char *)&pSMBr->hdr.Protocol +
3725 le16_to_cpu(pSMBr->t2.DataOffset);
3726 if (psrch_inf->smallBuf)
3727 cifs_small_buf_release(
3728 psrch_inf->ntwrk_buf_start);
3730 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3731 psrch_inf->srch_entries_start = response_data;
3732 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3733 psrch_inf->smallBuf = 0;
3734 if (parms->EndofSearch)
3735 psrch_inf->endOfSearch = true;
3737 psrch_inf->endOfSearch = false;
3738 psrch_inf->entries_in_buffer =
3739 le16_to_cpu(parms->SearchCount);
3740 psrch_inf->index_of_last_entry +=
3741 psrch_inf->entries_in_buffer;
3742 lnoff = le16_to_cpu(parms->LastNameOffset);
3743 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3745 cERROR(1, ("ignoring corrupt resume name"));
3746 psrch_inf->last_entry = NULL;
3749 psrch_inf->last_entry =
3750 psrch_inf->srch_entries_start + lnoff;
3752 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3753 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3755 /* BB fixme add unlock here */
3760 /* BB On error, should we leave previous search buf (and count and
3761 last entry fields) intact or free the previous one? */
3763 /* Note: On -EAGAIN error only caller can retry on handle based calls
3764 since file handle passed in no longer valid */
3767 cifs_buf_release(pSMB);
3772 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3773 const __u16 searchHandle)
3776 FINDCLOSE_REQ *pSMB = NULL;
3778 cFYI(1, ("In CIFSSMBFindClose"));
3779 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3781 /* no sense returning error if session restarted
3782 as file handle has been closed */
3788 pSMB->FileID = searchHandle;
3789 pSMB->ByteCount = 0;
3790 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3792 cERROR(1, ("Send error in FindClose = %d", rc));
3794 cifs_stats_inc(&tcon->num_fclose);
3796 /* Since session is dead, search handle closed on server already */
3804 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3805 const unsigned char *searchName,
3806 __u64 *inode_number,
3807 const struct nls_table *nls_codepage, int remap)
3810 TRANSACTION2_QPI_REQ *pSMB = NULL;
3811 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3812 int name_len, bytes_returned;
3813 __u16 params, byte_count;
3815 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3819 GetInodeNumberRetry:
3820 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3825 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3827 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3828 PATH_MAX, nls_codepage, remap);
3829 name_len++; /* trailing null */
3831 } else { /* BB improve the check for buffer overruns BB */
3832 name_len = strnlen(searchName, PATH_MAX);
3833 name_len++; /* trailing null */
3834 strncpy(pSMB->FileName, searchName, name_len);
3837 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3838 pSMB->TotalDataCount = 0;
3839 pSMB->MaxParameterCount = cpu_to_le16(2);
3840 /* BB find exact max data count below from sess structure BB */
3841 pSMB->MaxDataCount = cpu_to_le16(4000);
3842 pSMB->MaxSetupCount = 0;
3846 pSMB->Reserved2 = 0;
3847 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3848 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3849 pSMB->DataCount = 0;
3850 pSMB->DataOffset = 0;
3851 pSMB->SetupCount = 1;
3852 pSMB->Reserved3 = 0;
3853 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3854 byte_count = params + 1 /* pad */ ;
3855 pSMB->TotalParameterCount = cpu_to_le16(params);
3856 pSMB->ParameterCount = pSMB->TotalParameterCount;
3857 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3858 pSMB->Reserved4 = 0;
3859 pSMB->hdr.smb_buf_length += byte_count;
3860 pSMB->ByteCount = cpu_to_le16(byte_count);
3862 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3863 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3865 cFYI(1, ("error %d in QueryInternalInfo", rc));
3867 /* decode response */
3868 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3869 if (rc || (pSMBr->ByteCount < 2))
3870 /* BB also check enough total bytes returned */
3871 /* If rc should we check for EOPNOSUPP and
3872 disable the srvino flag? or in caller? */
3873 rc = -EIO; /* bad smb */
3875 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3876 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3877 struct file_internal_info *pfinfo;
3878 /* BB Do we need a cast or hash here ? */
3880 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3882 goto GetInodeNumOut;
3884 pfinfo = (struct file_internal_info *)
3885 (data_offset + (char *) &pSMBr->hdr.Protocol);
3886 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3890 cifs_buf_release(pSMB);
3892 goto GetInodeNumberRetry;
3896 /* parses DFS refferal V3 structure
3897 * caller is responsible for freeing target_nodes
3900 * on failure - errno
3903 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3904 unsigned int *num_of_nodes,
3905 struct dfs_info3_param **target_nodes,
3906 const struct nls_table *nls_codepage, int remap,
3907 const char *searchName)
3912 struct dfs_referral_level_3 *ref;
3914 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3918 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3920 if (*num_of_nodes < 1) {
3921 cERROR(1, ("num_referrals: must be at least > 0,"
3922 "but we get num_referrals = %d\n", *num_of_nodes));
3924 goto parse_DFS_referrals_exit;
3927 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3928 if (ref->VersionNumber != cpu_to_le16(3)) {
3929 cERROR(1, ("Referrals of V%d version are not supported,"
3930 "should be V3", le16_to_cpu(ref->VersionNumber)));
3932 goto parse_DFS_referrals_exit;
3935 /* get the upper boundary of the resp buffer */
3936 data_end = (char *)(&(pSMBr->PathConsumed)) +
3937 le16_to_cpu(pSMBr->t2.DataCount);
3939 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3941 le16_to_cpu(pSMBr->DFSFlags)));
3943 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3944 *num_of_nodes, GFP_KERNEL);
3945 if (*target_nodes == NULL) {
3946 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3948 goto parse_DFS_referrals_exit;
3951 /* collect neccessary data from referrals */
3952 for (i = 0; i < *num_of_nodes; i++) {
3955 struct dfs_info3_param *node = (*target_nodes)+i;
3957 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3959 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3961 cifsConvertToUCS((__le16 *) tmp, searchName,
3962 PATH_MAX, nls_codepage, remap);
3963 node->path_consumed = cifs_ucs2_bytes(tmp,
3964 le16_to_cpu(pSMBr->PathConsumed),
3968 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3970 node->server_type = le16_to_cpu(ref->ServerType);
3971 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3974 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3975 max_len = data_end - temp;
3976 node->path_name = cifs_strndup(temp, max_len, is_unicode,
3978 if (IS_ERR(node->path_name)) {
3979 rc = PTR_ERR(node->path_name);
3980 node->path_name = NULL;
3981 goto parse_DFS_referrals_exit;
3984 /* copy link target UNC */
3985 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3986 max_len = data_end - temp;
3987 node->node_name = cifs_strndup(temp, max_len, is_unicode,
3989 if (IS_ERR(node->node_name)) {
3990 rc = PTR_ERR(node->node_name);
3991 node->node_name = NULL;
3992 goto parse_DFS_referrals_exit;
3996 parse_DFS_referrals_exit:
3998 free_dfs_info_array(*target_nodes, *num_of_nodes);
3999 *target_nodes = NULL;
4006 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4007 const unsigned char *searchName,
4008 struct dfs_info3_param **target_nodes,
4009 unsigned int *num_of_nodes,
4010 const struct nls_table *nls_codepage, int remap)
4012 /* TRANS2_GET_DFS_REFERRAL */
4013 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4014 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4018 __u16 params, byte_count;
4020 *target_nodes = NULL;
4022 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4026 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4031 /* server pointer checked in called function,
4032 but should never be null here anyway */
4033 pSMB->hdr.Mid = GetNextMid(ses->server);
4034 pSMB->hdr.Tid = ses->ipc_tid;
4035 pSMB->hdr.Uid = ses->Suid;
4036 if (ses->capabilities & CAP_STATUS32)
4037 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4038 if (ses->capabilities & CAP_DFS)
4039 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4041 if (ses->capabilities & CAP_UNICODE) {
4042 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4044 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4045 searchName, PATH_MAX, nls_codepage, remap);
4046 name_len++; /* trailing null */
4048 } else { /* BB improve the check for buffer overruns BB */
4049 name_len = strnlen(searchName, PATH_MAX);
4050 name_len++; /* trailing null */
4051 strncpy(pSMB->RequestFileName, searchName, name_len);
4055 if (ses->server->secMode &
4056 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4057 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4060 pSMB->hdr.Uid = ses->Suid;
4062 params = 2 /* level */ + name_len /*includes null */ ;
4063 pSMB->TotalDataCount = 0;
4064 pSMB->DataCount = 0;
4065 pSMB->DataOffset = 0;
4066 pSMB->MaxParameterCount = 0;
4067 /* BB find exact max SMB PDU from sess structure BB */
4068 pSMB->MaxDataCount = cpu_to_le16(4000);
4069 pSMB->MaxSetupCount = 0;
4073 pSMB->Reserved2 = 0;
4074 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4075 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4076 pSMB->SetupCount = 1;
4077 pSMB->Reserved3 = 0;
4078 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4079 byte_count = params + 3 /* pad */ ;
4080 pSMB->ParameterCount = cpu_to_le16(params);
4081 pSMB->TotalParameterCount = pSMB->ParameterCount;
4082 pSMB->MaxReferralLevel = cpu_to_le16(3);
4083 pSMB->hdr.smb_buf_length += byte_count;
4084 pSMB->ByteCount = cpu_to_le16(byte_count);
4086 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4089 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4092 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4094 /* BB Also check if enough total bytes returned? */
4095 if (rc || (pSMBr->ByteCount < 17)) {
4096 rc = -EIO; /* bad smb */
4100 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4102 le16_to_cpu(pSMBr->t2.DataOffset)));
4104 /* parse returned result into more usable form */
4105 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4106 target_nodes, nls_codepage, remap,
4110 cifs_buf_release(pSMB);
4118 /* Query File System Info such as free space to old servers such as Win 9x */
4120 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4122 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4123 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4124 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4125 FILE_SYSTEM_ALLOC_INFO *response_data;
4127 int bytes_returned = 0;
4128 __u16 params, byte_count;
4130 cFYI(1, ("OldQFSInfo"));
4132 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4137 params = 2; /* level */
4138 pSMB->TotalDataCount = 0;
4139 pSMB->MaxParameterCount = cpu_to_le16(2);
4140 pSMB->MaxDataCount = cpu_to_le16(1000);
4141 pSMB->MaxSetupCount = 0;
4145 pSMB->Reserved2 = 0;
4146 byte_count = params + 1 /* pad */ ;
4147 pSMB->TotalParameterCount = cpu_to_le16(params);
4148 pSMB->ParameterCount = pSMB->TotalParameterCount;
4149 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4150 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4151 pSMB->DataCount = 0;
4152 pSMB->DataOffset = 0;
4153 pSMB->SetupCount = 1;
4154 pSMB->Reserved3 = 0;
4155 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4156 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4157 pSMB->hdr.smb_buf_length += byte_count;
4158 pSMB->ByteCount = cpu_to_le16(byte_count);
4160 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4161 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4163 cFYI(1, ("Send error in QFSInfo = %d", rc));
4164 } else { /* decode response */
4165 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4167 if (rc || (pSMBr->ByteCount < 18))
4168 rc = -EIO; /* bad smb */
4170 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4171 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4172 pSMBr->ByteCount, data_offset));
4174 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4175 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4177 le16_to_cpu(response_data->BytesPerSector) *
4178 le32_to_cpu(response_data->
4179 SectorsPerAllocationUnit);
4181 le32_to_cpu(response_data->TotalAllocationUnits);
4182 FSData->f_bfree = FSData->f_bavail =
4183 le32_to_cpu(response_data->FreeAllocationUnits);
4185 ("Blocks: %lld Free: %lld Block size %ld",
4186 (unsigned long long)FSData->f_blocks,
4187 (unsigned long long)FSData->f_bfree,
4191 cifs_buf_release(pSMB);
4194 goto oldQFSInfoRetry;
4200 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4202 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4203 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4204 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4205 FILE_SYSTEM_INFO *response_data;
4207 int bytes_returned = 0;
4208 __u16 params, byte_count;
4210 cFYI(1, ("In QFSInfo"));
4212 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4217 params = 2; /* level */
4218 pSMB->TotalDataCount = 0;
4219 pSMB->MaxParameterCount = cpu_to_le16(2);
4220 pSMB->MaxDataCount = cpu_to_le16(1000);
4221 pSMB->MaxSetupCount = 0;
4225 pSMB->Reserved2 = 0;
4226 byte_count = params + 1 /* pad */ ;
4227 pSMB->TotalParameterCount = cpu_to_le16(params);
4228 pSMB->ParameterCount = pSMB->TotalParameterCount;
4229 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4230 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4231 pSMB->DataCount = 0;
4232 pSMB->DataOffset = 0;
4233 pSMB->SetupCount = 1;
4234 pSMB->Reserved3 = 0;
4235 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4236 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4237 pSMB->hdr.smb_buf_length += byte_count;
4238 pSMB->ByteCount = cpu_to_le16(byte_count);
4240 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4241 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4243 cFYI(1, ("Send error in QFSInfo = %d", rc));
4244 } else { /* decode response */
4245 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4247 if (rc || (pSMBr->ByteCount < 24))
4248 rc = -EIO; /* bad smb */
4250 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4254 *) (((char *) &pSMBr->hdr.Protocol) +
4257 le32_to_cpu(response_data->BytesPerSector) *
4258 le32_to_cpu(response_data->
4259 SectorsPerAllocationUnit);
4261 le64_to_cpu(response_data->TotalAllocationUnits);
4262 FSData->f_bfree = FSData->f_bavail =
4263 le64_to_cpu(response_data->FreeAllocationUnits);
4265 ("Blocks: %lld Free: %lld Block size %ld",
4266 (unsigned long long)FSData->f_blocks,
4267 (unsigned long long)FSData->f_bfree,
4271 cifs_buf_release(pSMB);
4280 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4282 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4283 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4284 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4285 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4287 int bytes_returned = 0;
4288 __u16 params, byte_count;
4290 cFYI(1, ("In QFSAttributeInfo"));
4292 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4297 params = 2; /* level */
4298 pSMB->TotalDataCount = 0;
4299 pSMB->MaxParameterCount = cpu_to_le16(2);
4300 /* BB find exact max SMB PDU from sess structure BB */
4301 pSMB->MaxDataCount = cpu_to_le16(1000);
4302 pSMB->MaxSetupCount = 0;
4306 pSMB->Reserved2 = 0;
4307 byte_count = params + 1 /* pad */ ;
4308 pSMB->TotalParameterCount = cpu_to_le16(params);
4309 pSMB->ParameterCount = pSMB->TotalParameterCount;
4310 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4311 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4312 pSMB->DataCount = 0;
4313 pSMB->DataOffset = 0;
4314 pSMB->SetupCount = 1;
4315 pSMB->Reserved3 = 0;
4316 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4317 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4318 pSMB->hdr.smb_buf_length += byte_count;
4319 pSMB->ByteCount = cpu_to_le16(byte_count);
4321 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4322 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4324 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4325 } else { /* decode response */
4326 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4328 if (rc || (pSMBr->ByteCount < 13)) {
4329 /* BB also check if enough bytes returned */
4330 rc = -EIO; /* bad smb */
4332 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4334 (FILE_SYSTEM_ATTRIBUTE_INFO
4335 *) (((char *) &pSMBr->hdr.Protocol) +
4337 memcpy(&tcon->fsAttrInfo, response_data,
4338 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4341 cifs_buf_release(pSMB);
4344 goto QFSAttributeRetry;
4350 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4352 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4353 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4354 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4355 FILE_SYSTEM_DEVICE_INFO *response_data;
4357 int bytes_returned = 0;
4358 __u16 params, byte_count;
4360 cFYI(1, ("In QFSDeviceInfo"));
4362 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4367 params = 2; /* level */
4368 pSMB->TotalDataCount = 0;
4369 pSMB->MaxParameterCount = cpu_to_le16(2);
4370 /* BB find exact max SMB PDU from sess structure BB */
4371 pSMB->MaxDataCount = cpu_to_le16(1000);
4372 pSMB->MaxSetupCount = 0;
4376 pSMB->Reserved2 = 0;
4377 byte_count = params + 1 /* pad */ ;
4378 pSMB->TotalParameterCount = cpu_to_le16(params);
4379 pSMB->ParameterCount = pSMB->TotalParameterCount;
4380 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4381 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4383 pSMB->DataCount = 0;
4384 pSMB->DataOffset = 0;
4385 pSMB->SetupCount = 1;
4386 pSMB->Reserved3 = 0;
4387 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4388 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4389 pSMB->hdr.smb_buf_length += byte_count;
4390 pSMB->ByteCount = cpu_to_le16(byte_count);
4392 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4393 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4395 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4396 } else { /* decode response */
4397 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4399 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4400 rc = -EIO; /* bad smb */
4402 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4404 (FILE_SYSTEM_DEVICE_INFO *)
4405 (((char *) &pSMBr->hdr.Protocol) +
4407 memcpy(&tcon->fsDevInfo, response_data,
4408 sizeof(FILE_SYSTEM_DEVICE_INFO));
4411 cifs_buf_release(pSMB);
4414 goto QFSDeviceRetry;
4420 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4422 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4423 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4424 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4425 FILE_SYSTEM_UNIX_INFO *response_data;
4427 int bytes_returned = 0;
4428 __u16 params, byte_count;
4430 cFYI(1, ("In QFSUnixInfo"));
4432 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4437 params = 2; /* level */
4438 pSMB->TotalDataCount = 0;
4439 pSMB->DataCount = 0;
4440 pSMB->DataOffset = 0;
4441 pSMB->MaxParameterCount = cpu_to_le16(2);
4442 /* BB find exact max SMB PDU from sess structure BB */
4443 pSMB->MaxDataCount = cpu_to_le16(100);
4444 pSMB->MaxSetupCount = 0;
4448 pSMB->Reserved2 = 0;
4449 byte_count = params + 1 /* pad */ ;
4450 pSMB->ParameterCount = cpu_to_le16(params);
4451 pSMB->TotalParameterCount = pSMB->ParameterCount;
4452 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4453 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4454 pSMB->SetupCount = 1;
4455 pSMB->Reserved3 = 0;
4456 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4457 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4458 pSMB->hdr.smb_buf_length += byte_count;
4459 pSMB->ByteCount = cpu_to_le16(byte_count);
4461 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4462 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4464 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4465 } else { /* decode response */
4466 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4468 if (rc || (pSMBr->ByteCount < 13)) {
4469 rc = -EIO; /* bad smb */
4471 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4473 (FILE_SYSTEM_UNIX_INFO
4474 *) (((char *) &pSMBr->hdr.Protocol) +
4476 memcpy(&tcon->fsUnixInfo, response_data,
4477 sizeof(FILE_SYSTEM_UNIX_INFO));
4480 cifs_buf_release(pSMB);
4490 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4492 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4493 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4494 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4496 int bytes_returned = 0;
4497 __u16 params, param_offset, offset, byte_count;
4499 cFYI(1, ("In SETFSUnixInfo"));
4501 /* BB switch to small buf init to save memory */
4502 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4507 params = 4; /* 2 bytes zero followed by info level. */
4508 pSMB->MaxSetupCount = 0;
4512 pSMB->Reserved2 = 0;
4513 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4515 offset = param_offset + params;
4517 pSMB->MaxParameterCount = cpu_to_le16(4);
4518 /* BB find exact max SMB PDU from sess structure BB */
4519 pSMB->MaxDataCount = cpu_to_le16(100);
4520 pSMB->SetupCount = 1;
4521 pSMB->Reserved3 = 0;
4522 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4523 byte_count = 1 /* pad */ + params + 12;
4525 pSMB->DataCount = cpu_to_le16(12);
4526 pSMB->ParameterCount = cpu_to_le16(params);
4527 pSMB->TotalDataCount = pSMB->DataCount;
4528 pSMB->TotalParameterCount = pSMB->ParameterCount;
4529 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4530 pSMB->DataOffset = cpu_to_le16(offset);
4534 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4537 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4538 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4539 pSMB->ClientUnixCap = cpu_to_le64(cap);
4541 pSMB->hdr.smb_buf_length += byte_count;
4542 pSMB->ByteCount = cpu_to_le16(byte_count);
4544 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4545 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4547 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4548 } else { /* decode response */
4549 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4551 rc = -EIO; /* bad smb */
4553 cifs_buf_release(pSMB);
4556 goto SETFSUnixRetry;
4564 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4565 struct kstatfs *FSData)
4567 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4568 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4569 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4570 FILE_SYSTEM_POSIX_INFO *response_data;
4572 int bytes_returned = 0;
4573 __u16 params, byte_count;
4575 cFYI(1, ("In QFSPosixInfo"));
4577 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4582 params = 2; /* level */
4583 pSMB->TotalDataCount = 0;
4584 pSMB->DataCount = 0;
4585 pSMB->DataOffset = 0;
4586 pSMB->MaxParameterCount = cpu_to_le16(2);
4587 /* BB find exact max SMB PDU from sess structure BB */
4588 pSMB->MaxDataCount = cpu_to_le16(100);
4589 pSMB->MaxSetupCount = 0;
4593 pSMB->Reserved2 = 0;
4594 byte_count = params + 1 /* pad */ ;
4595 pSMB->ParameterCount = cpu_to_le16(params);
4596 pSMB->TotalParameterCount = pSMB->ParameterCount;
4597 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4598 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4599 pSMB->SetupCount = 1;
4600 pSMB->Reserved3 = 0;
4601 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4602 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4603 pSMB->hdr.smb_buf_length += byte_count;
4604 pSMB->ByteCount = cpu_to_le16(byte_count);
4606 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4607 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4609 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4610 } else { /* decode response */
4611 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4613 if (rc || (pSMBr->ByteCount < 13)) {
4614 rc = -EIO; /* bad smb */
4616 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4618 (FILE_SYSTEM_POSIX_INFO
4619 *) (((char *) &pSMBr->hdr.Protocol) +
4622 le32_to_cpu(response_data->BlockSize);
4624 le64_to_cpu(response_data->TotalBlocks);
4626 le64_to_cpu(response_data->BlocksAvail);
4627 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4628 FSData->f_bavail = FSData->f_bfree;
4631 le64_to_cpu(response_data->UserBlocksAvail);
4633 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4635 le64_to_cpu(response_data->TotalFileNodes);
4636 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4638 le64_to_cpu(response_data->FreeFileNodes);
4641 cifs_buf_release(pSMB);
4650 /* We can not use write of zero bytes trick to
4651 set file size due to need for large file support. Also note that
4652 this SetPathInfo is preferred to SetFileInfo based method in next
4653 routine which is only needed to work around a sharing violation bug
4654 in Samba which this routine can run into */
4657 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4658 __u64 size, bool SetAllocation,
4659 const struct nls_table *nls_codepage, int remap)
4661 struct smb_com_transaction2_spi_req *pSMB = NULL;
4662 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4663 struct file_end_of_file_info *parm_data;
4666 int bytes_returned = 0;
4667 __u16 params, byte_count, data_count, param_offset, offset;
4669 cFYI(1, ("In SetEOF"));
4671 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4676 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4678 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4679 PATH_MAX, nls_codepage, remap);
4680 name_len++; /* trailing null */
4682 } else { /* BB improve the check for buffer overruns BB */
4683 name_len = strnlen(fileName, PATH_MAX);
4684 name_len++; /* trailing null */
4685 strncpy(pSMB->FileName, fileName, name_len);
4687 params = 6 + name_len;
4688 data_count = sizeof(struct file_end_of_file_info);
4689 pSMB->MaxParameterCount = cpu_to_le16(2);
4690 pSMB->MaxDataCount = cpu_to_le16(4100);
4691 pSMB->MaxSetupCount = 0;
4695 pSMB->Reserved2 = 0;
4696 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4697 InformationLevel) - 4;
4698 offset = param_offset + params;
4699 if (SetAllocation) {
4700 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4701 pSMB->InformationLevel =
4702 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4704 pSMB->InformationLevel =
4705 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4706 } else /* Set File Size */ {
4707 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4708 pSMB->InformationLevel =
4709 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4711 pSMB->InformationLevel =
4712 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4716 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4718 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4719 pSMB->DataOffset = cpu_to_le16(offset);
4720 pSMB->SetupCount = 1;
4721 pSMB->Reserved3 = 0;
4722 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4723 byte_count = 3 /* pad */ + params + data_count;
4724 pSMB->DataCount = cpu_to_le16(data_count);
4725 pSMB->TotalDataCount = pSMB->DataCount;
4726 pSMB->ParameterCount = cpu_to_le16(params);
4727 pSMB->TotalParameterCount = pSMB->ParameterCount;
4728 pSMB->Reserved4 = 0;
4729 pSMB->hdr.smb_buf_length += byte_count;
4730 parm_data->FileSize = cpu_to_le64(size);
4731 pSMB->ByteCount = cpu_to_le16(byte_count);
4732 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4733 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4735 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4737 cifs_buf_release(pSMB);
4746 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4747 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4749 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4751 struct file_end_of_file_info *parm_data;
4753 __u16 params, param_offset, offset, byte_count, count;
4755 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4757 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4762 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4763 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4766 pSMB->MaxSetupCount = 0;
4770 pSMB->Reserved2 = 0;
4771 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4772 offset = param_offset + params;
4774 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4776 count = sizeof(struct file_end_of_file_info);
4777 pSMB->MaxParameterCount = cpu_to_le16(2);
4778 /* BB find exact max SMB PDU from sess structure BB */
4779 pSMB->MaxDataCount = cpu_to_le16(1000);
4780 pSMB->SetupCount = 1;
4781 pSMB->Reserved3 = 0;
4782 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4783 byte_count = 3 /* pad */ + params + count;
4784 pSMB->DataCount = cpu_to_le16(count);
4785 pSMB->ParameterCount = cpu_to_le16(params);
4786 pSMB->TotalDataCount = pSMB->DataCount;
4787 pSMB->TotalParameterCount = pSMB->ParameterCount;
4788 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4790 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4792 pSMB->DataOffset = cpu_to_le16(offset);
4793 parm_data->FileSize = cpu_to_le64(size);
4795 if (SetAllocation) {
4796 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4797 pSMB->InformationLevel =
4798 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4800 pSMB->InformationLevel =
4801 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4802 } else /* Set File Size */ {
4803 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4804 pSMB->InformationLevel =
4805 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4807 pSMB->InformationLevel =
4808 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4810 pSMB->Reserved4 = 0;
4811 pSMB->hdr.smb_buf_length += byte_count;
4812 pSMB->ByteCount = cpu_to_le16(byte_count);
4813 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4816 ("Send error in SetFileInfo (SetFileSize) = %d",
4820 /* Note: On -EAGAIN error only caller can retry on handle based calls
4821 since file handle passed in no longer valid */
4826 /* Some legacy servers such as NT4 require that the file times be set on
4827 an open handle, rather than by pathname - this is awkward due to
4828 potential access conflicts on the open, but it is unavoidable for these
4829 old servers since the only other choice is to go from 100 nanosecond DCE
4830 time and resort to the original setpathinfo level which takes the ancient
4831 DOS time format with 2 second granularity */
4833 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4834 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4836 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4839 __u16 params, param_offset, offset, byte_count, count;
4841 cFYI(1, ("Set Times (via SetFileInfo)"));
4842 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4847 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4848 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4851 pSMB->MaxSetupCount = 0;
4855 pSMB->Reserved2 = 0;
4856 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4857 offset = param_offset + params;
4859 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4861 count = sizeof(FILE_BASIC_INFO);
4862 pSMB->MaxParameterCount = cpu_to_le16(2);
4863 /* BB find max SMB PDU from sess */
4864 pSMB->MaxDataCount = cpu_to_le16(1000);
4865 pSMB->SetupCount = 1;
4866 pSMB->Reserved3 = 0;
4867 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4868 byte_count = 3 /* pad */ + params + count;
4869 pSMB->DataCount = cpu_to_le16(count);
4870 pSMB->ParameterCount = cpu_to_le16(params);
4871 pSMB->TotalDataCount = pSMB->DataCount;
4872 pSMB->TotalParameterCount = pSMB->ParameterCount;
4873 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4874 pSMB->DataOffset = cpu_to_le16(offset);
4876 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4877 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4879 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4880 pSMB->Reserved4 = 0;
4881 pSMB->hdr.smb_buf_length += byte_count;
4882 pSMB->ByteCount = cpu_to_le16(byte_count);
4883 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4884 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4886 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4888 /* Note: On -EAGAIN error only caller can retry on handle based calls
4889 since file handle passed in no longer valid */
4895 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4896 bool delete_file, __u16 fid, __u32 pid_of_opener)
4898 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4901 __u16 params, param_offset, offset, byte_count, count;
4903 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4904 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4909 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4910 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4913 pSMB->MaxSetupCount = 0;
4917 pSMB->Reserved2 = 0;
4918 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4919 offset = param_offset + params;
4921 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4924 pSMB->MaxParameterCount = cpu_to_le16(2);
4925 /* BB find max SMB PDU from sess */
4926 pSMB->MaxDataCount = cpu_to_le16(1000);
4927 pSMB->SetupCount = 1;
4928 pSMB->Reserved3 = 0;
4929 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4930 byte_count = 3 /* pad */ + params + count;
4931 pSMB->DataCount = cpu_to_le16(count);
4932 pSMB->ParameterCount = cpu_to_le16(params);
4933 pSMB->TotalDataCount = pSMB->DataCount;
4934 pSMB->TotalParameterCount = pSMB->ParameterCount;
4935 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4936 pSMB->DataOffset = cpu_to_le16(offset);
4938 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4939 pSMB->Reserved4 = 0;
4940 pSMB->hdr.smb_buf_length += byte_count;
4941 pSMB->ByteCount = cpu_to_le16(byte_count);
4942 *data_offset = delete_file ? 1 : 0;
4943 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4945 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4951 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4952 const char *fileName, const FILE_BASIC_INFO *data,
4953 const struct nls_table *nls_codepage, int remap)
4955 TRANSACTION2_SPI_REQ *pSMB = NULL;
4956 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4959 int bytes_returned = 0;
4961 __u16 params, param_offset, offset, byte_count, count;
4963 cFYI(1, ("In SetTimes"));
4966 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4971 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4973 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4974 PATH_MAX, nls_codepage, remap);
4975 name_len++; /* trailing null */
4977 } else { /* BB improve the check for buffer overruns BB */
4978 name_len = strnlen(fileName, PATH_MAX);
4979 name_len++; /* trailing null */
4980 strncpy(pSMB->FileName, fileName, name_len);
4983 params = 6 + name_len;
4984 count = sizeof(FILE_BASIC_INFO);
4985 pSMB->MaxParameterCount = cpu_to_le16(2);
4986 /* BB find max SMB PDU from sess structure BB */
4987 pSMB->MaxDataCount = cpu_to_le16(1000);
4988 pSMB->MaxSetupCount = 0;
4992 pSMB->Reserved2 = 0;
4993 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4994 InformationLevel) - 4;
4995 offset = param_offset + params;
4996 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4997 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4998 pSMB->DataOffset = cpu_to_le16(offset);
4999 pSMB->SetupCount = 1;
5000 pSMB->Reserved3 = 0;
5001 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5002 byte_count = 3 /* pad */ + params + count;
5004 pSMB->DataCount = cpu_to_le16(count);
5005 pSMB->ParameterCount = cpu_to_le16(params);
5006 pSMB->TotalDataCount = pSMB->DataCount;
5007 pSMB->TotalParameterCount = pSMB->ParameterCount;
5008 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5009 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5011 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5012 pSMB->Reserved4 = 0;
5013 pSMB->hdr.smb_buf_length += byte_count;
5014 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5015 pSMB->ByteCount = cpu_to_le16(byte_count);
5016 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5017 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5019 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5021 cifs_buf_release(pSMB);
5029 /* Can not be used to set time stamps yet (due to old DOS time format) */
5030 /* Can be used to set attributes */
5031 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5032 handling it anyway and NT4 was what we thought it would be needed for
5033 Do not delete it until we prove whether needed for Win9x though */
5035 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5036 __u16 dos_attrs, const struct nls_table *nls_codepage)
5038 SETATTR_REQ *pSMB = NULL;
5039 SETATTR_RSP *pSMBr = NULL;
5044 cFYI(1, ("In SetAttrLegacy"));
5047 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5052 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5054 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5055 PATH_MAX, nls_codepage);
5056 name_len++; /* trailing null */
5058 } else { /* BB improve the check for buffer overruns BB */
5059 name_len = strnlen(fileName, PATH_MAX);
5060 name_len++; /* trailing null */
5061 strncpy(pSMB->fileName, fileName, name_len);
5063 pSMB->attr = cpu_to_le16(dos_attrs);
5064 pSMB->BufferFormat = 0x04;
5065 pSMB->hdr.smb_buf_length += name_len + 1;
5066 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5067 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5068 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5070 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5072 cifs_buf_release(pSMB);
5075 goto SetAttrLgcyRetry;
5079 #endif /* temporarily unneeded SetAttr legacy function */
5082 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5083 const struct cifs_unix_set_info_args *args,
5084 const struct nls_table *nls_codepage, int remap)
5086 TRANSACTION2_SPI_REQ *pSMB = NULL;
5087 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5090 int bytes_returned = 0;
5091 FILE_UNIX_BASIC_INFO *data_offset;
5092 __u16 params, param_offset, offset, count, byte_count;
5093 __u64 mode = args->mode;
5095 cFYI(1, ("In SetUID/GID/Mode"));
5097 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5104 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5105 PATH_MAX, nls_codepage, remap);
5106 name_len++; /* trailing null */
5108 } else { /* BB improve the check for buffer overruns BB */
5109 name_len = strnlen(fileName, PATH_MAX);
5110 name_len++; /* trailing null */
5111 strncpy(pSMB->FileName, fileName, name_len);
5114 params = 6 + name_len;
5115 count = sizeof(FILE_UNIX_BASIC_INFO);
5116 pSMB->MaxParameterCount = cpu_to_le16(2);
5117 /* BB find max SMB PDU from sess structure BB */
5118 pSMB->MaxDataCount = cpu_to_le16(1000);
5119 pSMB->MaxSetupCount = 0;
5123 pSMB->Reserved2 = 0;
5124 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5125 InformationLevel) - 4;
5126 offset = param_offset + params;
5128 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5130 memset(data_offset, 0, count);
5131 pSMB->DataOffset = cpu_to_le16(offset);
5132 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5133 pSMB->SetupCount = 1;
5134 pSMB->Reserved3 = 0;
5135 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5136 byte_count = 3 /* pad */ + params + count;
5137 pSMB->ParameterCount = cpu_to_le16(params);
5138 pSMB->DataCount = cpu_to_le16(count);
5139 pSMB->TotalParameterCount = pSMB->ParameterCount;
5140 pSMB->TotalDataCount = pSMB->DataCount;
5141 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5142 pSMB->Reserved4 = 0;
5143 pSMB->hdr.smb_buf_length += byte_count;
5144 /* Samba server ignores set of file size to zero due to bugs in some
5145 older clients, but we should be precise - we use SetFileSize to
5146 set file size and do not want to truncate file size to zero
5147 accidently as happened on one Samba server beta by putting
5148 zero instead of -1 here */
5149 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5150 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5151 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5152 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5153 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5154 data_offset->Uid = cpu_to_le64(args->uid);
5155 data_offset->Gid = cpu_to_le64(args->gid);
5156 /* better to leave device as zero when it is */
5157 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5158 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5159 data_offset->Permissions = cpu_to_le64(mode);
5162 data_offset->Type = cpu_to_le32(UNIX_FILE);
5163 else if (S_ISDIR(mode))
5164 data_offset->Type = cpu_to_le32(UNIX_DIR);
5165 else if (S_ISLNK(mode))
5166 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5167 else if (S_ISCHR(mode))
5168 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5169 else if (S_ISBLK(mode))
5170 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5171 else if (S_ISFIFO(mode))
5172 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5173 else if (S_ISSOCK(mode))
5174 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5177 pSMB->ByteCount = cpu_to_le16(byte_count);
5178 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5179 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5181 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5183 cifs_buf_release(pSMB);
5189 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5190 const int notify_subdirs, const __u16 netfid,
5191 __u32 filter, struct file *pfile, int multishot,
5192 const struct nls_table *nls_codepage)
5195 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5196 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5197 struct dir_notify_req *dnotify_req;
5200 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5201 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5206 pSMB->TotalParameterCount = 0 ;
5207 pSMB->TotalDataCount = 0;
5208 pSMB->MaxParameterCount = cpu_to_le32(2);
5209 /* BB find exact data count max from sess structure BB */
5210 pSMB->MaxDataCount = 0; /* same in little endian or be */
5211 /* BB VERIFY verify which is correct for above BB */
5212 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5213 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5215 pSMB->MaxSetupCount = 4;
5217 pSMB->ParameterOffset = 0;
5218 pSMB->DataCount = 0;
5219 pSMB->DataOffset = 0;
5220 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5221 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5222 pSMB->ParameterCount = pSMB->TotalParameterCount;
5224 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5225 pSMB->Reserved2 = 0;
5226 pSMB->CompletionFilter = cpu_to_le32(filter);
5227 pSMB->Fid = netfid; /* file handle always le */
5228 pSMB->ByteCount = 0;
5230 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5231 (struct smb_hdr *)pSMBr, &bytes_returned,
5234 cFYI(1, ("Error in Notify = %d", rc));
5236 /* Add file to outstanding requests */
5237 /* BB change to kmem cache alloc */
5238 dnotify_req = kmalloc(
5239 sizeof(struct dir_notify_req),
5242 dnotify_req->Pid = pSMB->hdr.Pid;
5243 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5244 dnotify_req->Mid = pSMB->hdr.Mid;
5245 dnotify_req->Tid = pSMB->hdr.Tid;
5246 dnotify_req->Uid = pSMB->hdr.Uid;
5247 dnotify_req->netfid = netfid;
5248 dnotify_req->pfile = pfile;
5249 dnotify_req->filter = filter;
5250 dnotify_req->multishot = multishot;
5251 spin_lock(&GlobalMid_Lock);
5252 list_add_tail(&dnotify_req->lhead,
5253 &GlobalDnotifyReqList);
5254 spin_unlock(&GlobalMid_Lock);
5258 cifs_buf_release(pSMB);
5261 #ifdef CONFIG_CIFS_XATTR
5263 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5264 const unsigned char *searchName,
5265 char *EAData, size_t buf_size,
5266 const struct nls_table *nls_codepage, int remap)
5268 /* BB assumes one setup word */
5269 TRANSACTION2_QPI_REQ *pSMB = NULL;
5270 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5274 struct fea *temp_fea;
5276 __u16 params, byte_count;
5278 cFYI(1, ("In Query All EAs path %s", searchName));
5280 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5285 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5287 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5288 PATH_MAX, nls_codepage, remap);
5289 name_len++; /* trailing null */
5291 } else { /* BB improve the check for buffer overruns BB */
5292 name_len = strnlen(searchName, PATH_MAX);
5293 name_len++; /* trailing null */
5294 strncpy(pSMB->FileName, searchName, name_len);
5297 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5298 pSMB->TotalDataCount = 0;
5299 pSMB->MaxParameterCount = cpu_to_le16(2);
5300 /* BB find exact max SMB PDU from sess structure BB */
5301 pSMB->MaxDataCount = cpu_to_le16(4000);
5302 pSMB->MaxSetupCount = 0;
5306 pSMB->Reserved2 = 0;
5307 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5308 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5309 pSMB->DataCount = 0;
5310 pSMB->DataOffset = 0;
5311 pSMB->SetupCount = 1;
5312 pSMB->Reserved3 = 0;
5313 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5314 byte_count = params + 1 /* pad */ ;
5315 pSMB->TotalParameterCount = cpu_to_le16(params);
5316 pSMB->ParameterCount = pSMB->TotalParameterCount;
5317 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5318 pSMB->Reserved4 = 0;
5319 pSMB->hdr.smb_buf_length += byte_count;
5320 pSMB->ByteCount = cpu_to_le16(byte_count);
5322 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5323 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5325 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5326 } else { /* decode response */
5327 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5329 /* BB also check enough total bytes returned */
5330 /* BB we need to improve the validity checking
5331 of these trans2 responses */
5332 if (rc || (pSMBr->ByteCount < 4))
5333 rc = -EIO; /* bad smb */
5334 /* else if (pFindData){
5335 memcpy((char *) pFindData,
5336 (char *) &pSMBr->hdr.Protocol +
5339 /* check that length of list is not more than bcc */
5340 /* check that each entry does not go beyond length
5342 /* check that each element of each entry does not
5343 go beyond end of list */
5344 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5345 struct fealist *ea_response_data;
5347 /* validate_trans2_offsets() */
5348 /* BB check if start of smb + data_offset > &bcc+ bcc */
5349 ea_response_data = (struct fealist *)
5350 (((char *) &pSMBr->hdr.Protocol) +
5352 name_len = le32_to_cpu(ea_response_data->list_len);
5353 cFYI(1, ("ea length %d", name_len));
5354 if (name_len <= 8) {
5355 /* returned EA size zeroed at top of function */
5356 cFYI(1, ("empty EA list returned from server"));
5358 /* account for ea list len */
5360 temp_fea = ea_response_data->list;
5361 temp_ptr = (char *)temp_fea;
5362 while (name_len > 0) {
5366 rc += temp_fea->name_len;
5367 /* account for prefix user. and trailing null */
5369 if (rc < (int)buf_size) {
5370 memcpy(EAData, "user.", 5);
5372 memcpy(EAData, temp_ptr,
5373 temp_fea->name_len);
5374 EAData += temp_fea->name_len;
5375 /* null terminate name */
5377 EAData = EAData + 1;
5378 } else if (buf_size == 0) {
5379 /* skip copy - calc size only */
5381 /* stop before overrun buffer */
5385 name_len -= temp_fea->name_len;
5386 temp_ptr += temp_fea->name_len;
5387 /* account for trailing null */
5391 le16_to_cpu(temp_fea->value_len);
5392 name_len -= value_len;
5393 temp_ptr += value_len;
5394 /* BB check that temp_ptr is still
5397 /* no trailing null to account for
5399 /* go on to next EA */
5400 temp_fea = (struct fea *)temp_ptr;
5405 cifs_buf_release(pSMB);
5412 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5413 const unsigned char *searchName, const unsigned char *ea_name,
5414 unsigned char *ea_value, size_t buf_size,
5415 const struct nls_table *nls_codepage, int remap)
5417 TRANSACTION2_QPI_REQ *pSMB = NULL;
5418 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5422 struct fea *temp_fea;
5424 __u16 params, byte_count;
5426 cFYI(1, ("In Query EA path %s", searchName));
5428 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5433 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5435 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5436 PATH_MAX, nls_codepage, remap);
5437 name_len++; /* trailing null */
5439 } else { /* BB improve the check for buffer overruns BB */
5440 name_len = strnlen(searchName, PATH_MAX);
5441 name_len++; /* trailing null */
5442 strncpy(pSMB->FileName, searchName, name_len);
5445 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5446 pSMB->TotalDataCount = 0;
5447 pSMB->MaxParameterCount = cpu_to_le16(2);
5448 /* BB find exact max SMB PDU from sess structure BB */
5449 pSMB->MaxDataCount = cpu_to_le16(4000);
5450 pSMB->MaxSetupCount = 0;
5454 pSMB->Reserved2 = 0;
5455 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5456 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5457 pSMB->DataCount = 0;
5458 pSMB->DataOffset = 0;
5459 pSMB->SetupCount = 1;
5460 pSMB->Reserved3 = 0;
5461 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5462 byte_count = params + 1 /* pad */ ;
5463 pSMB->TotalParameterCount = cpu_to_le16(params);
5464 pSMB->ParameterCount = pSMB->TotalParameterCount;
5465 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5466 pSMB->Reserved4 = 0;
5467 pSMB->hdr.smb_buf_length += byte_count;
5468 pSMB->ByteCount = cpu_to_le16(byte_count);
5470 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5471 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5473 cFYI(1, ("Send error in Query EA = %d", rc));
5474 } else { /* decode response */
5475 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5477 /* BB also check enough total bytes returned */
5478 /* BB we need to improve the validity checking
5479 of these trans2 responses */
5480 if (rc || (pSMBr->ByteCount < 4))
5481 rc = -EIO; /* bad smb */
5482 /* else if (pFindData){
5483 memcpy((char *) pFindData,
5484 (char *) &pSMBr->hdr.Protocol +
5487 /* check that length of list is not more than bcc */
5488 /* check that each entry does not go beyond length
5490 /* check that each element of each entry does not
5491 go beyond end of list */
5492 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5493 struct fealist *ea_response_data;
5495 /* validate_trans2_offsets() */
5496 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5497 ea_response_data = (struct fealist *)
5498 (((char *) &pSMBr->hdr.Protocol) +
5500 name_len = le32_to_cpu(ea_response_data->list_len);
5501 cFYI(1, ("ea length %d", name_len));
5502 if (name_len <= 8) {
5503 /* returned EA size zeroed at top of function */
5504 cFYI(1, ("empty EA list returned from server"));
5506 /* account for ea list len */
5508 temp_fea = ea_response_data->list;
5509 temp_ptr = (char *)temp_fea;
5510 /* loop through checking if we have a matching
5511 name and then return the associated value */
5512 while (name_len > 0) {
5517 le16_to_cpu(temp_fea->value_len);
5518 /* BB validate that value_len falls within SMB,
5519 even though maximum for name_len is 255 */
5520 if (memcmp(temp_fea->name, ea_name,
5521 temp_fea->name_len) == 0) {
5524 /* account for prefix user. and trailing null */
5525 if (rc <= (int)buf_size) {
5527 temp_fea->name+temp_fea->name_len+1,
5529 /* ea values, unlike ea
5532 } else if (buf_size == 0) {
5533 /* skip copy - calc size only */
5535 /* stop before overrun buffer */
5540 name_len -= temp_fea->name_len;
5541 temp_ptr += temp_fea->name_len;
5542 /* account for trailing null */
5545 name_len -= value_len;
5546 temp_ptr += value_len;
5547 /* No trailing null to account for in
5548 value_len. Go on to next EA */
5549 temp_fea = (struct fea *)temp_ptr;
5554 cifs_buf_release(pSMB);
5562 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5563 const char *ea_name, const void *ea_value,
5564 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5567 struct smb_com_transaction2_spi_req *pSMB = NULL;
5568 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5569 struct fealist *parm_data;
5572 int bytes_returned = 0;
5573 __u16 params, param_offset, byte_count, offset, count;
5575 cFYI(1, ("In SetEA"));
5577 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5582 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5584 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5585 PATH_MAX, nls_codepage, remap);
5586 name_len++; /* trailing null */
5588 } else { /* BB improve the check for buffer overruns BB */
5589 name_len = strnlen(fileName, PATH_MAX);
5590 name_len++; /* trailing null */
5591 strncpy(pSMB->FileName, fileName, name_len);
5594 params = 6 + name_len;
5596 /* done calculating parms using name_len of file name,
5597 now use name_len to calculate length of ea name
5598 we are going to create in the inode xattrs */
5599 if (ea_name == NULL)
5602 name_len = strnlen(ea_name, 255);
5604 count = sizeof(*parm_data) + ea_value_len + name_len;
5605 pSMB->MaxParameterCount = cpu_to_le16(2);
5606 /* BB find max SMB PDU from sess */
5607 pSMB->MaxDataCount = cpu_to_le16(1000);
5608 pSMB->MaxSetupCount = 0;
5612 pSMB->Reserved2 = 0;
5613 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5614 InformationLevel) - 4;
5615 offset = param_offset + params;
5616 pSMB->InformationLevel =
5617 cpu_to_le16(SMB_SET_FILE_EA);
5620 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5622 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5623 pSMB->DataOffset = cpu_to_le16(offset);
5624 pSMB->SetupCount = 1;
5625 pSMB->Reserved3 = 0;
5626 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5627 byte_count = 3 /* pad */ + params + count;
5628 pSMB->DataCount = cpu_to_le16(count);
5629 parm_data->list_len = cpu_to_le32(count);
5630 parm_data->list[0].EA_flags = 0;
5631 /* we checked above that name len is less than 255 */
5632 parm_data->list[0].name_len = (__u8)name_len;
5633 /* EA names are always ASCII */
5635 strncpy(parm_data->list[0].name, ea_name, name_len);
5636 parm_data->list[0].name[name_len] = 0;
5637 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5638 /* caller ensures that ea_value_len is less than 64K but
5639 we need to ensure that it fits within the smb */
5641 /*BB add length check to see if it would fit in
5642 negotiated SMB buffer size BB */
5643 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5645 memcpy(parm_data->list[0].name+name_len+1,
5646 ea_value, ea_value_len);
5648 pSMB->TotalDataCount = pSMB->DataCount;
5649 pSMB->ParameterCount = cpu_to_le16(params);
5650 pSMB->TotalParameterCount = pSMB->ParameterCount;
5651 pSMB->Reserved4 = 0;
5652 pSMB->hdr.smb_buf_length += byte_count;
5653 pSMB->ByteCount = cpu_to_le16(byte_count);
5654 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5655 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5657 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5659 cifs_buf_release(pSMB);