4 * Copyright (C) International Business Machines Corp., 2002,2009
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* Mark as invalid, all open files on tree connections since they
85 were closed when session to server was lost */
86 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
88 struct cifsFileInfo *open_file = NULL;
89 struct list_head *tmp;
90 struct list_head *tmp1;
92 /* list all files open on tree connection and mark them invalid */
93 write_lock(&GlobalSMBSeslock);
94 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
95 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
96 open_file->invalidHandle = true;
98 write_unlock(&GlobalSMBSeslock);
99 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
103 /* Allocate and return pointer to an SMB request buffer, and set basic
104 SMB information in the SMB header. If the return code is zero, this
105 function must have filled in request_buf pointer */
107 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
113 check for tcp and smb session status done differently
114 for those three - in the calling routine */
116 if (tcon->tidStatus == CifsExiting) {
117 /* only tree disconnect, open, and write,
118 (and ulogoff which does not have tcon)
119 are allowed as we start force umount */
120 if ((smb_command != SMB_COM_WRITE_ANDX) &&
121 (smb_command != SMB_COM_OPEN_ANDX) &&
122 (smb_command != SMB_COM_TREE_DISCONNECT)) {
123 cFYI(1, ("can not send cmd %d while umounting",
128 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
129 (tcon->ses->server)) {
130 struct nls_table *nls_codepage;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while (tcon->ses->server->tcpStatus ==
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus ==
139 if (tcon->ses->server->tcpStatus ==
141 /* on "soft" mounts we wait once */
143 (tcon->ses->status == CifsExiting)) {
144 cFYI(1, ("gave up waiting on "
145 "reconnect in smb_init"));
147 } /* else "hard" mount - keep retrying
148 until process is killed or server
149 comes back on-line */
150 } else /* TCP session is reestablished now */
154 nls_codepage = load_nls_default();
155 /* need to prevent multiple threads trying to
156 simultaneously reconnect the same SMB session */
157 down(&tcon->ses->sesSem);
158 if (tcon->ses->need_reconnect)
159 rc = cifs_setup_session(0, tcon->ses,
161 if (!rc && (tcon->need_reconnect)) {
162 mark_open_files_invalid(tcon);
163 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
165 up(&tcon->ses->sesSem);
166 /* BB FIXME add code to check if wsize needs
167 update due to negotiated smb buffer size
170 atomic_inc(&tconInfoReconnectCount);
171 /* tell server Unix caps we support */
172 if (tcon->ses->capabilities & CAP_UNIX)
173 reset_cifs_unix_caps(
176 NULL /* we do not know sb */,
177 NULL /* no vol info */);
180 cFYI(1, ("reconnect tcon rc = %d", rc));
181 /* Removed call to reopen open files here.
182 It is safer (and faster) to reopen files
183 one at a time as needed in read and write */
185 /* Check if handle based operation so we
186 know whether we can continue or not without
187 returning to caller to reset file handle */
188 switch (smb_command) {
189 case SMB_COM_READ_ANDX:
190 case SMB_COM_WRITE_ANDX:
192 case SMB_COM_FIND_CLOSE2:
193 case SMB_COM_LOCKING_ANDX: {
194 unload_nls(nls_codepage);
199 up(&tcon->ses->sesSem);
201 unload_nls(nls_codepage);
210 *request_buf = cifs_small_buf_get();
211 if (*request_buf == NULL) {
212 /* BB should we add a retry in here if not a writepage? */
216 header_assemble((struct smb_hdr *) *request_buf, smb_command,
220 cifs_stats_inc(&tcon->num_smbs_sent);
226 small_smb_init_no_tc(const int smb_command, const int wct,
227 struct cifsSesInfo *ses, void **request_buf)
230 struct smb_hdr *buffer;
232 rc = small_smb_init(smb_command, wct, NULL, request_buf);
236 buffer = (struct smb_hdr *)*request_buf;
237 buffer->Mid = GetNextMid(ses->server);
238 if (ses->capabilities & CAP_UNICODE)
239 buffer->Flags2 |= SMBFLG2_UNICODE;
240 if (ses->capabilities & CAP_STATUS32)
241 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
243 /* uid, tid can stay at zero as set in header assemble */
245 /* BB add support for turning on the signing when
246 this function is used after 1st of session setup requests */
251 /* If the return code is zero, this function must fill in request_buf pointer */
253 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
254 void **request_buf /* returned */ ,
255 void **response_buf /* returned */ )
259 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
260 check for tcp and smb session status done differently
261 for those three - in the calling routine */
263 if (tcon->tidStatus == CifsExiting) {
264 /* only tree disconnect, open, and write,
265 (and ulogoff which does not have tcon)
266 are allowed as we start force umount */
267 if ((smb_command != SMB_COM_WRITE_ANDX) &&
268 (smb_command != SMB_COM_OPEN_ANDX) &&
269 (smb_command != SMB_COM_TREE_DISCONNECT)) {
270 cFYI(1, ("can not send cmd %d while umounting",
276 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
277 (tcon->ses->server)) {
278 struct nls_table *nls_codepage;
279 /* Give Demultiplex thread up to 10 seconds to
280 reconnect, should be greater than cifs socket
281 timeout which is 7 seconds */
282 while (tcon->ses->server->tcpStatus ==
284 wait_event_interruptible_timeout(tcon->ses->server->response_q,
285 (tcon->ses->server->tcpStatus ==
287 if (tcon->ses->server->tcpStatus ==
289 /* on "soft" mounts we wait once */
291 (tcon->ses->status == CifsExiting)) {
292 cFYI(1, ("gave up waiting on "
293 "reconnect in smb_init"));
295 } /* else "hard" mount - keep retrying
296 until process is killed or server
298 } else /* TCP session is reestablished now */
301 nls_codepage = load_nls_default();
302 /* need to prevent multiple threads trying to
303 simultaneously reconnect the same SMB session */
304 down(&tcon->ses->sesSem);
305 if (tcon->ses->need_reconnect)
306 rc = cifs_setup_session(0, tcon->ses,
308 if (!rc && (tcon->need_reconnect)) {
309 mark_open_files_invalid(tcon);
310 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
312 up(&tcon->ses->sesSem);
313 /* BB FIXME add code to check if wsize needs
314 update due to negotiated smb buffer size
317 atomic_inc(&tconInfoReconnectCount);
318 /* tell server Unix caps we support */
319 if (tcon->ses->capabilities & CAP_UNIX)
320 reset_cifs_unix_caps(
323 NULL /* do not know sb */,
324 NULL /* no vol info */);
327 cFYI(1, ("reconnect tcon rc = %d", rc));
328 /* Removed call to reopen open files here.
329 It is safer (and faster) to reopen files
330 one at a time as needed in read and write */
332 /* Check if handle based operation so we
333 know whether we can continue or not without
334 returning to caller to reset file handle */
335 switch (smb_command) {
336 case SMB_COM_READ_ANDX:
337 case SMB_COM_WRITE_ANDX:
339 case SMB_COM_FIND_CLOSE2:
340 case SMB_COM_LOCKING_ANDX: {
341 unload_nls(nls_codepage);
346 up(&tcon->ses->sesSem);
348 unload_nls(nls_codepage);
357 *request_buf = cifs_buf_get();
358 if (*request_buf == NULL) {
359 /* BB should we add a retry in here if not a writepage? */
362 /* Although the original thought was we needed the response buf for */
363 /* potential retries of smb operations it turns out we can determine */
364 /* from the mid flags when the request buffer can be resent without */
365 /* having to use a second distinct buffer for the response */
367 *response_buf = *request_buf;
369 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
373 cifs_stats_inc(&tcon->num_smbs_sent);
378 static int validate_t2(struct smb_t2_rsp *pSMB)
384 /* check for plausible wct, bcc and t2 data and parm sizes */
385 /* check for parm and data offset going beyond end of smb */
386 if (pSMB->hdr.WordCount >= 10) {
387 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
388 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
389 /* check that bcc is at least as big as parms + data */
390 /* check that bcc is less than negotiated smb buffer */
391 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
392 if (total_size < 512) {
394 le16_to_cpu(pSMB->t2_rsp.DataCount);
395 /* BCC le converted in SendReceive */
396 pBCC = (pSMB->hdr.WordCount * 2) +
397 sizeof(struct smb_hdr) +
399 if ((total_size <= (*(u16 *)pBCC)) &&
401 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
407 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
408 sizeof(struct smb_t2_rsp) + 16);
412 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
415 NEGOTIATE_RSP *pSMBr;
419 struct TCP_Server_Info *server;
421 unsigned int secFlags;
425 server = ses->server;
430 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
431 (void **) &pSMB, (void **) &pSMBr);
435 /* if any of auth flags (ie not sign or seal) are overriden use them */
436 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
437 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
438 else /* if override flags set only sign/seal OR them with global auth */
439 secFlags = extended_security | ses->overrideSecFlg;
441 cFYI(1, ("secFlags 0x%x", secFlags));
443 pSMB->hdr.Mid = GetNextMid(server);
444 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
446 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
447 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
448 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
449 cFYI(1, ("Kerberos only mechanism, enable extended security"));
450 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
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, char **symlinkinfo,
2386 const struct nls_table *nls_codepage)
2388 /* SMB_QUERY_FILE_UNIX_LINK */
2389 TRANSACTION2_QPI_REQ *pSMB = NULL;
2390 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2394 __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 /* BB also check enough total bytes returned */
2451 if (rc || (pSMBr->ByteCount < 2))
2455 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2457 data_start = ((char *) &pSMBr->hdr.Protocol) +
2458 le16_to_cpu(pSMBr->t2.DataOffset);
2460 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2465 /* BB FIXME investigate remapping reserved chars here */
2466 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2467 is_unicode, nls_codepage);
2472 cifs_buf_release(pSMB);
2474 goto querySymLinkRetry;
2478 #ifdef CONFIG_CIFS_EXPERIMENTAL
2479 /* Initialize NT TRANSACT SMB into small smb request buffer.
2480 This assumes that all NT TRANSACTS that we init here have
2481 total parm and data under about 400 bytes (to fit in small cifs
2482 buffer size), which is the case so far, it easily fits. NB:
2483 Setup words themselves and ByteCount
2484 MaxSetupCount (size of returned setup area) and
2485 MaxParameterCount (returned parms size) must be set by caller */
2487 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2488 const int parm_len, struct cifsTconInfo *tcon,
2493 struct smb_com_ntransact_req *pSMB;
2495 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2499 *ret_buf = (void *)pSMB;
2501 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2502 pSMB->TotalDataCount = 0;
2503 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2504 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2505 pSMB->ParameterCount = pSMB->TotalParameterCount;
2506 pSMB->DataCount = pSMB->TotalDataCount;
2507 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2508 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2509 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2510 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2511 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2512 pSMB->SubCommand = cpu_to_le16(sub_command);
2517 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2518 __u32 *pparmlen, __u32 *pdatalen)
2521 __u32 data_count, data_offset, parm_count, parm_offset;
2522 struct smb_com_ntransact_rsp *pSMBr;
2530 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2532 /* ByteCount was converted from little endian in SendReceive */
2533 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2534 (char *)&pSMBr->ByteCount;
2536 data_offset = le32_to_cpu(pSMBr->DataOffset);
2537 data_count = le32_to_cpu(pSMBr->DataCount);
2538 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2539 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2541 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2542 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2544 /* should we also check that parm and data areas do not overlap? */
2545 if (*ppparm > end_of_smb) {
2546 cFYI(1, ("parms start after end of smb"));
2548 } else if (parm_count + *ppparm > end_of_smb) {
2549 cFYI(1, ("parm end after end of smb"));
2551 } else if (*ppdata > end_of_smb) {
2552 cFYI(1, ("data starts after end of smb"));
2554 } else if (data_count + *ppdata > end_of_smb) {
2555 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2556 *ppdata, data_count, (data_count + *ppdata),
2557 end_of_smb, pSMBr));
2559 } else if (parm_count + data_count > pSMBr->ByteCount) {
2560 cFYI(1, ("parm count and data count larger than SMB"));
2563 *pdatalen = data_count;
2564 *pparmlen = parm_count;
2569 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2570 const unsigned char *searchName,
2571 char *symlinkinfo, const int buflen, __u16 fid,
2572 const struct nls_table *nls_codepage)
2576 struct smb_com_transaction_ioctl_req *pSMB;
2577 struct smb_com_transaction_ioctl_rsp *pSMBr;
2579 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2580 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2585 pSMB->TotalParameterCount = 0 ;
2586 pSMB->TotalDataCount = 0;
2587 pSMB->MaxParameterCount = cpu_to_le32(2);
2588 /* BB find exact data count max from sess structure BB */
2589 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2590 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2591 pSMB->MaxSetupCount = 4;
2593 pSMB->ParameterOffset = 0;
2594 pSMB->DataCount = 0;
2595 pSMB->DataOffset = 0;
2596 pSMB->SetupCount = 4;
2597 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2598 pSMB->ParameterCount = pSMB->TotalParameterCount;
2599 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2600 pSMB->IsFsctl = 1; /* FSCTL */
2601 pSMB->IsRootFlag = 0;
2602 pSMB->Fid = fid; /* file handle always le */
2603 pSMB->ByteCount = 0;
2605 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2606 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2608 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2609 } else { /* decode response */
2610 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2611 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2612 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2613 /* BB also check enough total bytes returned */
2614 rc = -EIO; /* bad smb */
2617 if (data_count && (data_count < 2048)) {
2618 char *end_of_smb = 2 /* sizeof byte count */ +
2619 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2621 struct reparse_data *reparse_buf =
2622 (struct reparse_data *)
2623 ((char *)&pSMBr->hdr.Protocol
2625 if ((char *)reparse_buf >= end_of_smb) {
2629 if ((reparse_buf->LinkNamesBuf +
2630 reparse_buf->TargetNameOffset +
2631 reparse_buf->TargetNameLen) > end_of_smb) {
2632 cFYI(1, ("reparse buf beyond SMB"));
2637 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2638 cifs_from_ucs2(symlinkinfo, (__le16 *)
2639 (reparse_buf->LinkNamesBuf +
2640 reparse_buf->TargetNameOffset),
2642 reparse_buf->TargetNameLen,
2644 } else { /* ASCII names */
2645 strncpy(symlinkinfo,
2646 reparse_buf->LinkNamesBuf +
2647 reparse_buf->TargetNameOffset,
2648 min_t(const int, buflen,
2649 reparse_buf->TargetNameLen));
2653 cFYI(1, ("Invalid return data count on "
2654 "get reparse info ioctl"));
2656 symlinkinfo[buflen] = 0; /* just in case so the caller
2657 does not go off the end of the buffer */
2658 cFYI(1, ("readlink result - %s", symlinkinfo));
2662 cifs_buf_release(pSMB);
2664 /* Note: On -EAGAIN error only caller can retry on handle based calls
2665 since file handle passed in no longer valid */
2669 #endif /* CIFS_EXPERIMENTAL */
2671 #ifdef CONFIG_CIFS_POSIX
2673 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2674 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2675 struct cifs_posix_ace *cifs_ace)
2677 /* u8 cifs fields do not need le conversion */
2678 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2679 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2680 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2681 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2686 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2687 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2688 const int acl_type, const int size_of_data_area)
2693 struct cifs_posix_ace *pACE;
2694 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2695 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2697 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2700 if (acl_type & ACL_TYPE_ACCESS) {
2701 count = le16_to_cpu(cifs_acl->access_entry_count);
2702 pACE = &cifs_acl->ace_array[0];
2703 size = sizeof(struct cifs_posix_acl);
2704 size += sizeof(struct cifs_posix_ace) * count;
2705 /* check if we would go beyond end of SMB */
2706 if (size_of_data_area < size) {
2707 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2708 size_of_data_area, size));
2711 } else if (acl_type & ACL_TYPE_DEFAULT) {
2712 count = le16_to_cpu(cifs_acl->access_entry_count);
2713 size = sizeof(struct cifs_posix_acl);
2714 size += sizeof(struct cifs_posix_ace) * count;
2715 /* skip past access ACEs to get to default ACEs */
2716 pACE = &cifs_acl->ace_array[count];
2717 count = le16_to_cpu(cifs_acl->default_entry_count);
2718 size += sizeof(struct cifs_posix_ace) * count;
2719 /* check if we would go beyond end of SMB */
2720 if (size_of_data_area < size)
2727 size = posix_acl_xattr_size(count);
2728 if ((buflen == 0) || (local_acl == NULL)) {
2729 /* used to query ACL EA size */
2730 } else if (size > buflen) {
2732 } else /* buffer big enough */ {
2733 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2734 for (i = 0; i < count ; i++) {
2735 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2742 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2743 const posix_acl_xattr_entry *local_ace)
2745 __u16 rc = 0; /* 0 = ACL converted ok */
2747 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2748 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2749 /* BB is there a better way to handle the large uid? */
2750 if (local_ace->e_id == cpu_to_le32(-1)) {
2751 /* Probably no need to le convert -1 on any arch but can not hurt */
2752 cifs_ace->cifs_uid = cpu_to_le64(-1);
2754 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2755 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2759 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2760 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2761 const int buflen, const int acl_type)
2764 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2765 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2769 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2772 count = posix_acl_xattr_count((size_t)buflen);
2773 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2775 count, buflen, le32_to_cpu(local_acl->a_version)));
2776 if (le32_to_cpu(local_acl->a_version) != 2) {
2777 cFYI(1, ("unknown POSIX ACL version %d",
2778 le32_to_cpu(local_acl->a_version)));
2781 cifs_acl->version = cpu_to_le16(1);
2782 if (acl_type == ACL_TYPE_ACCESS)
2783 cifs_acl->access_entry_count = cpu_to_le16(count);
2784 else if (acl_type == ACL_TYPE_DEFAULT)
2785 cifs_acl->default_entry_count = cpu_to_le16(count);
2787 cFYI(1, ("unknown ACL type %d", acl_type));
2790 for (i = 0; i < count; i++) {
2791 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2792 &local_acl->a_entries[i]);
2794 /* ACE not converted */
2799 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2800 rc += sizeof(struct cifs_posix_acl);
2801 /* BB add check to make sure ACL does not overflow SMB */
2807 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2808 const unsigned char *searchName,
2809 char *acl_inf, const int buflen, const int acl_type,
2810 const struct nls_table *nls_codepage, int remap)
2812 /* SMB_QUERY_POSIX_ACL */
2813 TRANSACTION2_QPI_REQ *pSMB = NULL;
2814 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2818 __u16 params, byte_count;
2820 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2830 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2831 PATH_MAX, nls_codepage, remap);
2832 name_len++; /* trailing null */
2834 pSMB->FileName[name_len] = 0;
2835 pSMB->FileName[name_len+1] = 0;
2836 } else { /* BB improve the check for buffer overruns BB */
2837 name_len = strnlen(searchName, PATH_MAX);
2838 name_len++; /* trailing null */
2839 strncpy(pSMB->FileName, searchName, name_len);
2842 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2843 pSMB->TotalDataCount = 0;
2844 pSMB->MaxParameterCount = cpu_to_le16(2);
2845 /* BB find exact max data count below from sess structure BB */
2846 pSMB->MaxDataCount = cpu_to_le16(4000);
2847 pSMB->MaxSetupCount = 0;
2851 pSMB->Reserved2 = 0;
2852 pSMB->ParameterOffset = cpu_to_le16(
2853 offsetof(struct smb_com_transaction2_qpi_req,
2854 InformationLevel) - 4);
2855 pSMB->DataCount = 0;
2856 pSMB->DataOffset = 0;
2857 pSMB->SetupCount = 1;
2858 pSMB->Reserved3 = 0;
2859 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2860 byte_count = params + 1 /* pad */ ;
2861 pSMB->TotalParameterCount = cpu_to_le16(params);
2862 pSMB->ParameterCount = pSMB->TotalParameterCount;
2863 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2864 pSMB->Reserved4 = 0;
2865 pSMB->hdr.smb_buf_length += byte_count;
2866 pSMB->ByteCount = cpu_to_le16(byte_count);
2868 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2869 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2870 cifs_stats_inc(&tcon->num_acl_get);
2872 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2874 /* decode response */
2876 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2877 if (rc || (pSMBr->ByteCount < 2))
2878 /* BB also check enough total bytes returned */
2879 rc = -EIO; /* bad smb */
2881 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2882 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2883 rc = cifs_copy_posix_acl(acl_inf,
2884 (char *)&pSMBr->hdr.Protocol+data_offset,
2885 buflen, acl_type, count);
2888 cifs_buf_release(pSMB);
2895 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2896 const unsigned char *fileName,
2897 const char *local_acl, const int buflen,
2899 const struct nls_table *nls_codepage, int remap)
2901 struct smb_com_transaction2_spi_req *pSMB = NULL;
2902 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2906 int bytes_returned = 0;
2907 __u16 params, byte_count, data_count, param_offset, offset;
2909 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2911 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2915 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2917 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2918 PATH_MAX, nls_codepage, remap);
2919 name_len++; /* trailing null */
2921 } else { /* BB improve the check for buffer overruns BB */
2922 name_len = strnlen(fileName, PATH_MAX);
2923 name_len++; /* trailing null */
2924 strncpy(pSMB->FileName, fileName, name_len);
2926 params = 6 + name_len;
2927 pSMB->MaxParameterCount = cpu_to_le16(2);
2928 /* BB find max SMB size from sess */
2929 pSMB->MaxDataCount = cpu_to_le16(1000);
2930 pSMB->MaxSetupCount = 0;
2934 pSMB->Reserved2 = 0;
2935 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2936 InformationLevel) - 4;
2937 offset = param_offset + params;
2938 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2939 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2941 /* convert to on the wire format for POSIX ACL */
2942 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2944 if (data_count == 0) {
2946 goto setACLerrorExit;
2948 pSMB->DataOffset = cpu_to_le16(offset);
2949 pSMB->SetupCount = 1;
2950 pSMB->Reserved3 = 0;
2951 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2952 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2953 byte_count = 3 /* pad */ + params + data_count;
2954 pSMB->DataCount = cpu_to_le16(data_count);
2955 pSMB->TotalDataCount = pSMB->DataCount;
2956 pSMB->ParameterCount = cpu_to_le16(params);
2957 pSMB->TotalParameterCount = pSMB->ParameterCount;
2958 pSMB->Reserved4 = 0;
2959 pSMB->hdr.smb_buf_length += byte_count;
2960 pSMB->ByteCount = cpu_to_le16(byte_count);
2961 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2962 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2964 cFYI(1, ("Set POSIX ACL returned %d", rc));
2967 cifs_buf_release(pSMB);
2973 /* BB fix tabs in this function FIXME BB */
2975 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2976 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2979 struct smb_t2_qfi_req *pSMB = NULL;
2980 struct smb_t2_qfi_rsp *pSMBr = NULL;
2982 __u16 params, byte_count;
2984 cFYI(1, ("In GetExtAttr"));
2989 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2994 params = 2 /* level */ + 2 /* fid */;
2995 pSMB->t2.TotalDataCount = 0;
2996 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2997 /* BB find exact max data count below from sess structure BB */
2998 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2999 pSMB->t2.MaxSetupCount = 0;
3000 pSMB->t2.Reserved = 0;
3002 pSMB->t2.Timeout = 0;
3003 pSMB->t2.Reserved2 = 0;
3004 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3006 pSMB->t2.DataCount = 0;
3007 pSMB->t2.DataOffset = 0;
3008 pSMB->t2.SetupCount = 1;
3009 pSMB->t2.Reserved3 = 0;
3010 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3011 byte_count = params + 1 /* pad */ ;
3012 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3013 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3014 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3017 pSMB->hdr.smb_buf_length += byte_count;
3018 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3020 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3021 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3023 cFYI(1, ("error %d in GetExtAttr", rc));
3025 /* decode response */
3026 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3027 if (rc || (pSMBr->ByteCount < 2))
3028 /* BB also check enough total bytes returned */
3029 /* If rc should we check for EOPNOSUPP and
3030 disable the srvino flag? or in caller? */
3031 rc = -EIO; /* bad smb */
3033 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3034 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3035 struct file_chattr_info *pfinfo;
3036 /* BB Do we need a cast or hash here ? */
3038 cFYI(1, ("Illegal size ret in GetExtAttr"));
3042 pfinfo = (struct file_chattr_info *)
3043 (data_offset + (char *) &pSMBr->hdr.Protocol);
3044 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3045 *pMask = le64_to_cpu(pfinfo->mask);
3049 cifs_buf_release(pSMB);
3051 goto GetExtAttrRetry;
3055 #endif /* CONFIG_POSIX */
3057 #ifdef CONFIG_CIFS_EXPERIMENTAL
3058 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3060 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3061 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3065 QUERY_SEC_DESC_REQ *pSMB;
3068 cFYI(1, ("GetCifsACL"));
3073 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3074 8 /* parm len */, tcon, (void **) &pSMB);
3078 pSMB->MaxParameterCount = cpu_to_le32(4);
3079 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3080 pSMB->MaxSetupCount = 0;
3081 pSMB->Fid = fid; /* file handle always le */
3082 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3084 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3085 pSMB->hdr.smb_buf_length += 11;
3086 iov[0].iov_base = (char *)pSMB;
3087 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3089 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3091 cifs_stats_inc(&tcon->num_acl_get);
3093 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3094 } else { /* decode response */
3098 struct smb_com_ntransact_rsp *pSMBr;
3101 /* validate_nttransact */
3102 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3103 &pdata, &parm_len, pbuflen);
3106 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3108 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3110 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3111 rc = -EIO; /* bad smb */
3116 /* BB check that data area is minimum length and as big as acl_len */
3118 acl_len = le32_to_cpu(*parm);
3119 if (acl_len != *pbuflen) {
3120 cERROR(1, ("acl length %d does not match %d",
3121 acl_len, *pbuflen));
3122 if (*pbuflen > acl_len)
3126 /* check if buffer is big enough for the acl
3127 header followed by the smallest SID */
3128 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3129 (*pbuflen >= 64 * 1024)) {
3130 cERROR(1, ("bad acl length %d", *pbuflen));
3134 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3135 if (*acl_inf == NULL) {
3139 memcpy(*acl_inf, pdata, *pbuflen);
3143 if (buf_type == CIFS_SMALL_BUFFER)
3144 cifs_small_buf_release(iov[0].iov_base);
3145 else if (buf_type == CIFS_LARGE_BUFFER)
3146 cifs_buf_release(iov[0].iov_base);
3147 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3152 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3153 struct cifs_ntsd *pntsd, __u32 acllen)
3155 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3157 int bytes_returned = 0;
3158 SET_SEC_DESC_REQ *pSMB = NULL;
3159 NTRANSACT_RSP *pSMBr = NULL;
3162 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3167 pSMB->MaxSetupCount = 0;
3171 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3172 data_count = acllen;
3173 data_offset = param_offset + param_count;
3174 byte_count = 3 /* pad */ + param_count;
3176 pSMB->DataCount = cpu_to_le32(data_count);
3177 pSMB->TotalDataCount = pSMB->DataCount;
3178 pSMB->MaxParameterCount = cpu_to_le32(4);
3179 pSMB->MaxDataCount = cpu_to_le32(16384);
3180 pSMB->ParameterCount = cpu_to_le32(param_count);
3181 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3182 pSMB->TotalParameterCount = pSMB->ParameterCount;
3183 pSMB->DataOffset = cpu_to_le32(data_offset);
3184 pSMB->SetupCount = 0;
3185 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3186 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3188 pSMB->Fid = fid; /* file handle always le */
3189 pSMB->Reserved2 = 0;
3190 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3192 if (pntsd && acllen) {
3193 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3196 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3199 pSMB->hdr.smb_buf_length += byte_count;
3201 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3202 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3204 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3206 cFYI(1, ("Set CIFS ACL returned %d", rc));
3207 cifs_buf_release(pSMB);
3210 goto setCifsAclRetry;
3215 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3217 /* Legacy Query Path Information call for lookup to old servers such
3219 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3220 const unsigned char *searchName,
3221 FILE_ALL_INFO *pFinfo,
3222 const struct nls_table *nls_codepage, int remap)
3224 QUERY_INFORMATION_REQ *pSMB;
3225 QUERY_INFORMATION_RSP *pSMBr;
3230 cFYI(1, ("In SMBQPath path %s", searchName));
3232 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3237 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3239 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3240 PATH_MAX, nls_codepage, remap);
3241 name_len++; /* trailing null */
3244 name_len = strnlen(searchName, PATH_MAX);
3245 name_len++; /* trailing null */
3246 strncpy(pSMB->FileName, searchName, name_len);
3248 pSMB->BufferFormat = 0x04;
3249 name_len++; /* account for buffer type byte */
3250 pSMB->hdr.smb_buf_length += (__u16) name_len;
3251 pSMB->ByteCount = cpu_to_le16(name_len);
3253 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3254 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3256 cFYI(1, ("Send error in QueryInfo = %d", rc));
3257 } else if (pFinfo) {
3259 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3261 /* decode response */
3262 /* BB FIXME - add time zone adjustment BB */
3263 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3266 /* decode time fields */
3267 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3268 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3269 pFinfo->LastAccessTime = 0;
3270 pFinfo->AllocationSize =
3271 cpu_to_le64(le32_to_cpu(pSMBr->size));
3272 pFinfo->EndOfFile = pFinfo->AllocationSize;
3273 pFinfo->Attributes =
3274 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3276 rc = -EIO; /* bad buffer passed in */
3278 cifs_buf_release(pSMB);
3290 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3291 const unsigned char *searchName,
3292 FILE_ALL_INFO *pFindData,
3293 int legacy /* old style infolevel */,
3294 const struct nls_table *nls_codepage, int remap)
3296 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3297 TRANSACTION2_QPI_REQ *pSMB = NULL;
3298 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3302 __u16 params, byte_count;
3304 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3306 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3311 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3313 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3314 PATH_MAX, nls_codepage, remap);
3315 name_len++; /* trailing null */
3317 } else { /* BB improve the check for buffer overruns BB */
3318 name_len = strnlen(searchName, PATH_MAX);
3319 name_len++; /* trailing null */
3320 strncpy(pSMB->FileName, searchName, name_len);
3323 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3324 pSMB->TotalDataCount = 0;
3325 pSMB->MaxParameterCount = cpu_to_le16(2);
3326 /* BB find exact max SMB PDU from sess structure BB */
3327 pSMB->MaxDataCount = cpu_to_le16(4000);
3328 pSMB->MaxSetupCount = 0;
3332 pSMB->Reserved2 = 0;
3333 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3334 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3335 pSMB->DataCount = 0;
3336 pSMB->DataOffset = 0;
3337 pSMB->SetupCount = 1;
3338 pSMB->Reserved3 = 0;
3339 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3340 byte_count = params + 1 /* pad */ ;
3341 pSMB->TotalParameterCount = cpu_to_le16(params);
3342 pSMB->ParameterCount = pSMB->TotalParameterCount;
3344 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3346 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3347 pSMB->Reserved4 = 0;
3348 pSMB->hdr.smb_buf_length += byte_count;
3349 pSMB->ByteCount = cpu_to_le16(byte_count);
3351 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3352 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3354 cFYI(1, ("Send error in QPathInfo = %d", rc));
3355 } else { /* decode response */
3356 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3358 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3360 else if (!legacy && (pSMBr->ByteCount < 40))
3361 rc = -EIO; /* bad smb */
3362 else if (legacy && (pSMBr->ByteCount < 24))
3363 rc = -EIO; /* 24 or 26 expected but we do not read
3365 else if (pFindData) {
3367 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3369 /* On legacy responses we do not read the last field,
3370 EAsize, fortunately since it varies by subdialect and
3371 also note it differs on Set vs. Get, ie two bytes or 4
3372 bytes depending but we don't care here */
3374 size = sizeof(FILE_INFO_STANDARD);
3376 size = sizeof(FILE_ALL_INFO);
3377 memcpy((char *) pFindData,
3378 (char *) &pSMBr->hdr.Protocol +
3383 cifs_buf_release(pSMB);
3385 goto QPathInfoRetry;
3391 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3392 const unsigned char *searchName,
3393 FILE_UNIX_BASIC_INFO *pFindData,
3394 const struct nls_table *nls_codepage, int remap)
3396 /* SMB_QUERY_FILE_UNIX_BASIC */
3397 TRANSACTION2_QPI_REQ *pSMB = NULL;
3398 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3400 int bytes_returned = 0;
3402 __u16 params, byte_count;
3404 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3406 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3411 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3413 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3414 PATH_MAX, nls_codepage, remap);
3415 name_len++; /* trailing null */
3417 } else { /* BB improve the check for buffer overruns BB */
3418 name_len = strnlen(searchName, PATH_MAX);
3419 name_len++; /* trailing null */
3420 strncpy(pSMB->FileName, searchName, name_len);
3423 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3424 pSMB->TotalDataCount = 0;
3425 pSMB->MaxParameterCount = cpu_to_le16(2);
3426 /* BB find exact max SMB PDU from sess structure BB */
3427 pSMB->MaxDataCount = cpu_to_le16(4000);
3428 pSMB->MaxSetupCount = 0;
3432 pSMB->Reserved2 = 0;
3433 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3434 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3435 pSMB->DataCount = 0;
3436 pSMB->DataOffset = 0;
3437 pSMB->SetupCount = 1;
3438 pSMB->Reserved3 = 0;
3439 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3440 byte_count = params + 1 /* pad */ ;
3441 pSMB->TotalParameterCount = cpu_to_le16(params);
3442 pSMB->ParameterCount = pSMB->TotalParameterCount;
3443 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3444 pSMB->Reserved4 = 0;
3445 pSMB->hdr.smb_buf_length += byte_count;
3446 pSMB->ByteCount = cpu_to_le16(byte_count);
3448 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3449 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3451 cFYI(1, ("Send error in QPathInfo = %d", rc));
3452 } else { /* decode response */
3453 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3455 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3456 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3457 "Unix Extensions can be disabled on mount "
3458 "by specifying the nosfu mount option."));
3459 rc = -EIO; /* bad smb */
3461 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3462 memcpy((char *) pFindData,
3463 (char *) &pSMBr->hdr.Protocol +
3465 sizeof(FILE_UNIX_BASIC_INFO));
3468 cifs_buf_release(pSMB);
3470 goto UnixQPathInfoRetry;
3475 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3477 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3478 const char *searchName,
3479 const struct nls_table *nls_codepage,
3481 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3483 /* level 257 SMB_ */
3484 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3485 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3486 T2_FFIRST_RSP_PARMS *parms;
3488 int bytes_returned = 0;
3490 __u16 params, byte_count;
3492 cFYI(1, ("In FindFirst for %s", searchName));
3495 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3500 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3502 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3503 PATH_MAX, nls_codepage, remap);
3504 /* We can not add the asterik earlier in case
3505 it got remapped to 0xF03A as if it were part of the
3506 directory name instead of a wildcard */
3508 pSMB->FileName[name_len] = dirsep;
3509 pSMB->FileName[name_len+1] = 0;
3510 pSMB->FileName[name_len+2] = '*';
3511 pSMB->FileName[name_len+3] = 0;
3512 name_len += 4; /* now the trailing null */
3513 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3514 pSMB->FileName[name_len+1] = 0;
3516 } else { /* BB add check for overrun of SMB buf BB */
3517 name_len = strnlen(searchName, PATH_MAX);
3518 /* BB fix here and in unicode clause above ie
3519 if (name_len > buffersize-header)
3520 free buffer exit; BB */
3521 strncpy(pSMB->FileName, searchName, name_len);
3522 pSMB->FileName[name_len] = dirsep;
3523 pSMB->FileName[name_len+1] = '*';
3524 pSMB->FileName[name_len+2] = 0;
3528 params = 12 + name_len /* includes null */ ;
3529 pSMB->TotalDataCount = 0; /* no EAs */
3530 pSMB->MaxParameterCount = cpu_to_le16(10);
3531 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3532 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3533 pSMB->MaxSetupCount = 0;
3537 pSMB->Reserved2 = 0;
3538 byte_count = params + 1 /* pad */ ;
3539 pSMB->TotalParameterCount = cpu_to_le16(params);
3540 pSMB->ParameterCount = pSMB->TotalParameterCount;
3541 pSMB->ParameterOffset = cpu_to_le16(
3542 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3544 pSMB->DataCount = 0;
3545 pSMB->DataOffset = 0;
3546 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3547 pSMB->Reserved3 = 0;
3548 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3549 pSMB->SearchAttributes =
3550 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3552 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3553 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3554 CIFS_SEARCH_RETURN_RESUME);
3555 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3557 /* BB what should we set StorageType to? Does it matter? BB */
3558 pSMB->SearchStorageType = 0;
3559 pSMB->hdr.smb_buf_length += byte_count;
3560 pSMB->ByteCount = cpu_to_le16(byte_count);
3562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3563 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3564 cifs_stats_inc(&tcon->num_ffirst);
3566 if (rc) {/* BB add logic to retry regular search if Unix search
3567 rejected unexpectedly by server */
3568 /* BB Add code to handle unsupported level rc */
3569 cFYI(1, ("Error in FindFirst = %d", rc));
3571 cifs_buf_release(pSMB);
3573 /* BB eventually could optimize out free and realloc of buf */
3576 goto findFirstRetry;
3577 } else { /* decode response */
3578 /* BB remember to free buffer if error BB */
3579 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3583 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3584 psrch_inf->unicode = true;
3586 psrch_inf->unicode = false;
3588 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3589 psrch_inf->smallBuf = 0;
3590 psrch_inf->srch_entries_start =
3591 (char *) &pSMBr->hdr.Protocol +
3592 le16_to_cpu(pSMBr->t2.DataOffset);
3593 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3594 le16_to_cpu(pSMBr->t2.ParameterOffset));
3596 if (parms->EndofSearch)
3597 psrch_inf->endOfSearch = true;
3599 psrch_inf->endOfSearch = false;
3601 psrch_inf->entries_in_buffer =
3602 le16_to_cpu(parms->SearchCount);
3603 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3604 psrch_inf->entries_in_buffer;
3605 lnoff = le16_to_cpu(parms->LastNameOffset);
3606 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3608 cERROR(1, ("ignoring corrupt resume name"));
3609 psrch_inf->last_entry = NULL;
3613 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3616 *pnetfid = parms->SearchHandle;
3618 cifs_buf_release(pSMB);
3625 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3626 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3628 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3629 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3630 T2_FNEXT_RSP_PARMS *parms;
3631 char *response_data;
3633 int bytes_returned, name_len;
3634 __u16 params, byte_count;
3636 cFYI(1, ("In FindNext"));
3638 if (psrch_inf->endOfSearch)
3641 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3646 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3648 pSMB->TotalDataCount = 0; /* no EAs */
3649 pSMB->MaxParameterCount = cpu_to_le16(8);
3650 pSMB->MaxDataCount =
3651 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3653 pSMB->MaxSetupCount = 0;
3657 pSMB->Reserved2 = 0;
3658 pSMB->ParameterOffset = cpu_to_le16(
3659 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3660 pSMB->DataCount = 0;
3661 pSMB->DataOffset = 0;
3662 pSMB->SetupCount = 1;
3663 pSMB->Reserved3 = 0;
3664 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3665 pSMB->SearchHandle = searchHandle; /* always kept as le */
3667 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3668 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3669 pSMB->ResumeKey = psrch_inf->resume_key;
3671 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3673 name_len = psrch_inf->resume_name_len;
3675 if (name_len < PATH_MAX) {
3676 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3677 byte_count += name_len;
3678 /* 14 byte parm len above enough for 2 byte null terminator */
3679 pSMB->ResumeFileName[name_len] = 0;
3680 pSMB->ResumeFileName[name_len+1] = 0;
3683 goto FNext2_err_exit;
3685 byte_count = params + 1 /* pad */ ;
3686 pSMB->TotalParameterCount = cpu_to_le16(params);
3687 pSMB->ParameterCount = pSMB->TotalParameterCount;
3688 pSMB->hdr.smb_buf_length += byte_count;
3689 pSMB->ByteCount = cpu_to_le16(byte_count);
3691 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3692 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3693 cifs_stats_inc(&tcon->num_fnext);
3696 psrch_inf->endOfSearch = true;
3697 cifs_buf_release(pSMB);
3698 rc = 0; /* search probably was closed at end of search*/
3700 cFYI(1, ("FindNext returned = %d", rc));
3701 } else { /* decode response */
3702 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3707 /* BB fixme add lock for file (srch_info) struct here */
3708 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3709 psrch_inf->unicode = true;
3711 psrch_inf->unicode = false;
3712 response_data = (char *) &pSMBr->hdr.Protocol +
3713 le16_to_cpu(pSMBr->t2.ParameterOffset);
3714 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3715 response_data = (char *)&pSMBr->hdr.Protocol +
3716 le16_to_cpu(pSMBr->t2.DataOffset);
3717 if (psrch_inf->smallBuf)
3718 cifs_small_buf_release(
3719 psrch_inf->ntwrk_buf_start);
3721 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3722 psrch_inf->srch_entries_start = response_data;
3723 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3724 psrch_inf->smallBuf = 0;
3725 if (parms->EndofSearch)
3726 psrch_inf->endOfSearch = true;
3728 psrch_inf->endOfSearch = false;
3729 psrch_inf->entries_in_buffer =
3730 le16_to_cpu(parms->SearchCount);
3731 psrch_inf->index_of_last_entry +=
3732 psrch_inf->entries_in_buffer;
3733 lnoff = le16_to_cpu(parms->LastNameOffset);
3734 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3736 cERROR(1, ("ignoring corrupt resume name"));
3737 psrch_inf->last_entry = NULL;
3740 psrch_inf->last_entry =
3741 psrch_inf->srch_entries_start + lnoff;
3743 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3744 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3746 /* BB fixme add unlock here */
3751 /* BB On error, should we leave previous search buf (and count and
3752 last entry fields) intact or free the previous one? */
3754 /* Note: On -EAGAIN error only caller can retry on handle based calls
3755 since file handle passed in no longer valid */
3758 cifs_buf_release(pSMB);
3763 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3764 const __u16 searchHandle)
3767 FINDCLOSE_REQ *pSMB = NULL;
3769 cFYI(1, ("In CIFSSMBFindClose"));
3770 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3772 /* no sense returning error if session restarted
3773 as file handle has been closed */
3779 pSMB->FileID = searchHandle;
3780 pSMB->ByteCount = 0;
3781 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3783 cERROR(1, ("Send error in FindClose = %d", rc));
3785 cifs_stats_inc(&tcon->num_fclose);
3787 /* Since session is dead, search handle closed on server already */
3795 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3796 const unsigned char *searchName,
3797 __u64 *inode_number,
3798 const struct nls_table *nls_codepage, int remap)
3801 TRANSACTION2_QPI_REQ *pSMB = NULL;
3802 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3803 int name_len, bytes_returned;
3804 __u16 params, byte_count;
3806 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3810 GetInodeNumberRetry:
3811 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3816 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3818 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3819 PATH_MAX, nls_codepage, remap);
3820 name_len++; /* trailing null */
3822 } else { /* BB improve the check for buffer overruns BB */
3823 name_len = strnlen(searchName, PATH_MAX);
3824 name_len++; /* trailing null */
3825 strncpy(pSMB->FileName, searchName, name_len);
3828 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3829 pSMB->TotalDataCount = 0;
3830 pSMB->MaxParameterCount = cpu_to_le16(2);
3831 /* BB find exact max data count below from sess structure BB */
3832 pSMB->MaxDataCount = cpu_to_le16(4000);
3833 pSMB->MaxSetupCount = 0;
3837 pSMB->Reserved2 = 0;
3838 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3839 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3840 pSMB->DataCount = 0;
3841 pSMB->DataOffset = 0;
3842 pSMB->SetupCount = 1;
3843 pSMB->Reserved3 = 0;
3844 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3845 byte_count = params + 1 /* pad */ ;
3846 pSMB->TotalParameterCount = cpu_to_le16(params);
3847 pSMB->ParameterCount = pSMB->TotalParameterCount;
3848 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3849 pSMB->Reserved4 = 0;
3850 pSMB->hdr.smb_buf_length += byte_count;
3851 pSMB->ByteCount = cpu_to_le16(byte_count);
3853 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3854 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3856 cFYI(1, ("error %d in QueryInternalInfo", rc));
3858 /* decode response */
3859 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3860 if (rc || (pSMBr->ByteCount < 2))
3861 /* BB also check enough total bytes returned */
3862 /* If rc should we check for EOPNOSUPP and
3863 disable the srvino flag? or in caller? */
3864 rc = -EIO; /* bad smb */
3866 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3867 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3868 struct file_internal_info *pfinfo;
3869 /* BB Do we need a cast or hash here ? */
3871 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3873 goto GetInodeNumOut;
3875 pfinfo = (struct file_internal_info *)
3876 (data_offset + (char *) &pSMBr->hdr.Protocol);
3877 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3881 cifs_buf_release(pSMB);
3883 goto GetInodeNumberRetry;
3887 /* parses DFS refferal V3 structure
3888 * caller is responsible for freeing target_nodes
3891 * on failure - errno
3894 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3895 unsigned int *num_of_nodes,
3896 struct dfs_info3_param **target_nodes,
3897 const struct nls_table *nls_codepage, int remap,
3898 const char *searchName)
3903 struct dfs_referral_level_3 *ref;
3905 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3909 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3911 if (*num_of_nodes < 1) {
3912 cERROR(1, ("num_referrals: must be at least > 0,"
3913 "but we get num_referrals = %d\n", *num_of_nodes));
3915 goto parse_DFS_referrals_exit;
3918 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3919 if (ref->VersionNumber != cpu_to_le16(3)) {
3920 cERROR(1, ("Referrals of V%d version are not supported,"
3921 "should be V3", le16_to_cpu(ref->VersionNumber)));
3923 goto parse_DFS_referrals_exit;
3926 /* get the upper boundary of the resp buffer */
3927 data_end = (char *)(&(pSMBr->PathConsumed)) +
3928 le16_to_cpu(pSMBr->t2.DataCount);
3930 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3932 le32_to_cpu(pSMBr->DFSFlags)));
3934 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3935 *num_of_nodes, GFP_KERNEL);
3936 if (*target_nodes == NULL) {
3937 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3939 goto parse_DFS_referrals_exit;
3942 /* collect neccessary data from referrals */
3943 for (i = 0; i < *num_of_nodes; i++) {
3946 struct dfs_info3_param *node = (*target_nodes)+i;
3948 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3950 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3952 cifsConvertToUCS((__le16 *) tmp, searchName,
3953 PATH_MAX, nls_codepage, remap);
3954 node->path_consumed = cifs_ucs2_bytes(tmp,
3955 le16_to_cpu(pSMBr->PathConsumed),
3959 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3961 node->server_type = le16_to_cpu(ref->ServerType);
3962 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3965 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3966 max_len = data_end - temp;
3967 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3968 is_unicode, nls_codepage);
3969 if (IS_ERR(node->path_name)) {
3970 rc = PTR_ERR(node->path_name);
3971 node->path_name = NULL;
3972 goto parse_DFS_referrals_exit;
3975 /* copy link target UNC */
3976 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3977 max_len = data_end - temp;
3978 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3979 is_unicode, nls_codepage);
3980 if (IS_ERR(node->node_name)) {
3981 rc = PTR_ERR(node->node_name);
3982 node->node_name = NULL;
3983 goto parse_DFS_referrals_exit;
3987 parse_DFS_referrals_exit:
3989 free_dfs_info_array(*target_nodes, *num_of_nodes);
3990 *target_nodes = NULL;
3997 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3998 const unsigned char *searchName,
3999 struct dfs_info3_param **target_nodes,
4000 unsigned int *num_of_nodes,
4001 const struct nls_table *nls_codepage, int remap)
4003 /* TRANS2_GET_DFS_REFERRAL */
4004 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4005 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4009 __u16 params, byte_count;
4011 *target_nodes = NULL;
4013 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4017 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4022 /* server pointer checked in called function,
4023 but should never be null here anyway */
4024 pSMB->hdr.Mid = GetNextMid(ses->server);
4025 pSMB->hdr.Tid = ses->ipc_tid;
4026 pSMB->hdr.Uid = ses->Suid;
4027 if (ses->capabilities & CAP_STATUS32)
4028 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4029 if (ses->capabilities & CAP_DFS)
4030 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4032 if (ses->capabilities & CAP_UNICODE) {
4033 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4035 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4036 searchName, PATH_MAX, nls_codepage, remap);
4037 name_len++; /* trailing null */
4039 } else { /* BB improve the check for buffer overruns BB */
4040 name_len = strnlen(searchName, PATH_MAX);
4041 name_len++; /* trailing null */
4042 strncpy(pSMB->RequestFileName, searchName, name_len);
4046 if (ses->server->secMode &
4047 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4048 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4051 pSMB->hdr.Uid = ses->Suid;
4053 params = 2 /* level */ + name_len /*includes null */ ;
4054 pSMB->TotalDataCount = 0;
4055 pSMB->DataCount = 0;
4056 pSMB->DataOffset = 0;
4057 pSMB->MaxParameterCount = 0;
4058 /* BB find exact max SMB PDU from sess structure BB */
4059 pSMB->MaxDataCount = cpu_to_le16(4000);
4060 pSMB->MaxSetupCount = 0;
4064 pSMB->Reserved2 = 0;
4065 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4066 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4067 pSMB->SetupCount = 1;
4068 pSMB->Reserved3 = 0;
4069 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4070 byte_count = params + 3 /* pad */ ;
4071 pSMB->ParameterCount = cpu_to_le16(params);
4072 pSMB->TotalParameterCount = pSMB->ParameterCount;
4073 pSMB->MaxReferralLevel = cpu_to_le16(3);
4074 pSMB->hdr.smb_buf_length += byte_count;
4075 pSMB->ByteCount = cpu_to_le16(byte_count);
4077 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4078 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4080 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4083 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4085 /* BB Also check if enough total bytes returned? */
4086 if (rc || (pSMBr->ByteCount < 17)) {
4087 rc = -EIO; /* bad smb */
4091 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4093 le16_to_cpu(pSMBr->t2.DataOffset)));
4095 /* parse returned result into more usable form */
4096 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4097 target_nodes, nls_codepage, remap,
4101 cifs_buf_release(pSMB);
4109 /* Query File System Info such as free space to old servers such as Win 9x */
4111 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4113 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4114 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4115 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4116 FILE_SYSTEM_ALLOC_INFO *response_data;
4118 int bytes_returned = 0;
4119 __u16 params, byte_count;
4121 cFYI(1, ("OldQFSInfo"));
4123 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4128 params = 2; /* level */
4129 pSMB->TotalDataCount = 0;
4130 pSMB->MaxParameterCount = cpu_to_le16(2);
4131 pSMB->MaxDataCount = cpu_to_le16(1000);
4132 pSMB->MaxSetupCount = 0;
4136 pSMB->Reserved2 = 0;
4137 byte_count = params + 1 /* pad */ ;
4138 pSMB->TotalParameterCount = cpu_to_le16(params);
4139 pSMB->ParameterCount = pSMB->TotalParameterCount;
4140 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4141 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4142 pSMB->DataCount = 0;
4143 pSMB->DataOffset = 0;
4144 pSMB->SetupCount = 1;
4145 pSMB->Reserved3 = 0;
4146 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4147 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4148 pSMB->hdr.smb_buf_length += byte_count;
4149 pSMB->ByteCount = cpu_to_le16(byte_count);
4151 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4152 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4154 cFYI(1, ("Send error in QFSInfo = %d", rc));
4155 } else { /* decode response */
4156 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4158 if (rc || (pSMBr->ByteCount < 18))
4159 rc = -EIO; /* bad smb */
4161 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4162 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4163 pSMBr->ByteCount, data_offset));
4165 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4166 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4168 le16_to_cpu(response_data->BytesPerSector) *
4169 le32_to_cpu(response_data->
4170 SectorsPerAllocationUnit);
4172 le32_to_cpu(response_data->TotalAllocationUnits);
4173 FSData->f_bfree = FSData->f_bavail =
4174 le32_to_cpu(response_data->FreeAllocationUnits);
4176 ("Blocks: %lld Free: %lld Block size %ld",
4177 (unsigned long long)FSData->f_blocks,
4178 (unsigned long long)FSData->f_bfree,
4182 cifs_buf_release(pSMB);
4185 goto oldQFSInfoRetry;
4191 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4193 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4194 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4195 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4196 FILE_SYSTEM_INFO *response_data;
4198 int bytes_returned = 0;
4199 __u16 params, byte_count;
4201 cFYI(1, ("In QFSInfo"));
4203 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4208 params = 2; /* level */
4209 pSMB->TotalDataCount = 0;
4210 pSMB->MaxParameterCount = cpu_to_le16(2);
4211 pSMB->MaxDataCount = cpu_to_le16(1000);
4212 pSMB->MaxSetupCount = 0;
4216 pSMB->Reserved2 = 0;
4217 byte_count = params + 1 /* pad */ ;
4218 pSMB->TotalParameterCount = cpu_to_le16(params);
4219 pSMB->ParameterCount = pSMB->TotalParameterCount;
4220 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4221 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4222 pSMB->DataCount = 0;
4223 pSMB->DataOffset = 0;
4224 pSMB->SetupCount = 1;
4225 pSMB->Reserved3 = 0;
4226 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4227 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4228 pSMB->hdr.smb_buf_length += byte_count;
4229 pSMB->ByteCount = cpu_to_le16(byte_count);
4231 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4232 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4234 cFYI(1, ("Send error in QFSInfo = %d", rc));
4235 } else { /* decode response */
4236 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4238 if (rc || (pSMBr->ByteCount < 24))
4239 rc = -EIO; /* bad smb */
4241 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4245 *) (((char *) &pSMBr->hdr.Protocol) +
4248 le32_to_cpu(response_data->BytesPerSector) *
4249 le32_to_cpu(response_data->
4250 SectorsPerAllocationUnit);
4252 le64_to_cpu(response_data->TotalAllocationUnits);
4253 FSData->f_bfree = FSData->f_bavail =
4254 le64_to_cpu(response_data->FreeAllocationUnits);
4256 ("Blocks: %lld Free: %lld Block size %ld",
4257 (unsigned long long)FSData->f_blocks,
4258 (unsigned long long)FSData->f_bfree,
4262 cifs_buf_release(pSMB);
4271 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4273 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4274 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4275 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4276 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4278 int bytes_returned = 0;
4279 __u16 params, byte_count;
4281 cFYI(1, ("In QFSAttributeInfo"));
4283 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4288 params = 2; /* level */
4289 pSMB->TotalDataCount = 0;
4290 pSMB->MaxParameterCount = cpu_to_le16(2);
4291 /* BB find exact max SMB PDU from sess structure BB */
4292 pSMB->MaxDataCount = cpu_to_le16(1000);
4293 pSMB->MaxSetupCount = 0;
4297 pSMB->Reserved2 = 0;
4298 byte_count = params + 1 /* pad */ ;
4299 pSMB->TotalParameterCount = cpu_to_le16(params);
4300 pSMB->ParameterCount = pSMB->TotalParameterCount;
4301 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4302 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4303 pSMB->DataCount = 0;
4304 pSMB->DataOffset = 0;
4305 pSMB->SetupCount = 1;
4306 pSMB->Reserved3 = 0;
4307 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4308 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4309 pSMB->hdr.smb_buf_length += byte_count;
4310 pSMB->ByteCount = cpu_to_le16(byte_count);
4312 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4313 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4315 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4316 } else { /* decode response */
4317 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4319 if (rc || (pSMBr->ByteCount < 13)) {
4320 /* BB also check if enough bytes returned */
4321 rc = -EIO; /* bad smb */
4323 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4325 (FILE_SYSTEM_ATTRIBUTE_INFO
4326 *) (((char *) &pSMBr->hdr.Protocol) +
4328 memcpy(&tcon->fsAttrInfo, response_data,
4329 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4332 cifs_buf_release(pSMB);
4335 goto QFSAttributeRetry;
4341 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4343 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4344 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4345 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4346 FILE_SYSTEM_DEVICE_INFO *response_data;
4348 int bytes_returned = 0;
4349 __u16 params, byte_count;
4351 cFYI(1, ("In QFSDeviceInfo"));
4353 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4358 params = 2; /* level */
4359 pSMB->TotalDataCount = 0;
4360 pSMB->MaxParameterCount = cpu_to_le16(2);
4361 /* BB find exact max SMB PDU from sess structure BB */
4362 pSMB->MaxDataCount = cpu_to_le16(1000);
4363 pSMB->MaxSetupCount = 0;
4367 pSMB->Reserved2 = 0;
4368 byte_count = params + 1 /* pad */ ;
4369 pSMB->TotalParameterCount = cpu_to_le16(params);
4370 pSMB->ParameterCount = pSMB->TotalParameterCount;
4371 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4372 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4374 pSMB->DataCount = 0;
4375 pSMB->DataOffset = 0;
4376 pSMB->SetupCount = 1;
4377 pSMB->Reserved3 = 0;
4378 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4379 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4380 pSMB->hdr.smb_buf_length += byte_count;
4381 pSMB->ByteCount = cpu_to_le16(byte_count);
4383 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4384 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4386 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4387 } else { /* decode response */
4388 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4390 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4391 rc = -EIO; /* bad smb */
4393 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4395 (FILE_SYSTEM_DEVICE_INFO *)
4396 (((char *) &pSMBr->hdr.Protocol) +
4398 memcpy(&tcon->fsDevInfo, response_data,
4399 sizeof(FILE_SYSTEM_DEVICE_INFO));
4402 cifs_buf_release(pSMB);
4405 goto QFSDeviceRetry;
4411 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4413 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4414 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4415 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4416 FILE_SYSTEM_UNIX_INFO *response_data;
4418 int bytes_returned = 0;
4419 __u16 params, byte_count;
4421 cFYI(1, ("In QFSUnixInfo"));
4423 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4428 params = 2; /* level */
4429 pSMB->TotalDataCount = 0;
4430 pSMB->DataCount = 0;
4431 pSMB->DataOffset = 0;
4432 pSMB->MaxParameterCount = cpu_to_le16(2);
4433 /* BB find exact max SMB PDU from sess structure BB */
4434 pSMB->MaxDataCount = cpu_to_le16(100);
4435 pSMB->MaxSetupCount = 0;
4439 pSMB->Reserved2 = 0;
4440 byte_count = params + 1 /* pad */ ;
4441 pSMB->ParameterCount = cpu_to_le16(params);
4442 pSMB->TotalParameterCount = pSMB->ParameterCount;
4443 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4444 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4445 pSMB->SetupCount = 1;
4446 pSMB->Reserved3 = 0;
4447 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4448 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4449 pSMB->hdr.smb_buf_length += byte_count;
4450 pSMB->ByteCount = cpu_to_le16(byte_count);
4452 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4453 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4455 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4456 } else { /* decode response */
4457 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4459 if (rc || (pSMBr->ByteCount < 13)) {
4460 rc = -EIO; /* bad smb */
4462 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4464 (FILE_SYSTEM_UNIX_INFO
4465 *) (((char *) &pSMBr->hdr.Protocol) +
4467 memcpy(&tcon->fsUnixInfo, response_data,
4468 sizeof(FILE_SYSTEM_UNIX_INFO));
4471 cifs_buf_release(pSMB);
4481 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4483 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4484 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4485 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4487 int bytes_returned = 0;
4488 __u16 params, param_offset, offset, byte_count;
4490 cFYI(1, ("In SETFSUnixInfo"));
4492 /* BB switch to small buf init to save memory */
4493 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4498 params = 4; /* 2 bytes zero followed by info level. */
4499 pSMB->MaxSetupCount = 0;
4503 pSMB->Reserved2 = 0;
4504 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4506 offset = param_offset + params;
4508 pSMB->MaxParameterCount = cpu_to_le16(4);
4509 /* BB find exact max SMB PDU from sess structure BB */
4510 pSMB->MaxDataCount = cpu_to_le16(100);
4511 pSMB->SetupCount = 1;
4512 pSMB->Reserved3 = 0;
4513 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4514 byte_count = 1 /* pad */ + params + 12;
4516 pSMB->DataCount = cpu_to_le16(12);
4517 pSMB->ParameterCount = cpu_to_le16(params);
4518 pSMB->TotalDataCount = pSMB->DataCount;
4519 pSMB->TotalParameterCount = pSMB->ParameterCount;
4520 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4521 pSMB->DataOffset = cpu_to_le16(offset);
4525 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4528 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4529 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4530 pSMB->ClientUnixCap = cpu_to_le64(cap);
4532 pSMB->hdr.smb_buf_length += byte_count;
4533 pSMB->ByteCount = cpu_to_le16(byte_count);
4535 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4536 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4538 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4539 } else { /* decode response */
4540 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4542 rc = -EIO; /* bad smb */
4544 cifs_buf_release(pSMB);
4547 goto SETFSUnixRetry;
4555 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4556 struct kstatfs *FSData)
4558 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4559 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4560 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4561 FILE_SYSTEM_POSIX_INFO *response_data;
4563 int bytes_returned = 0;
4564 __u16 params, byte_count;
4566 cFYI(1, ("In QFSPosixInfo"));
4568 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4573 params = 2; /* level */
4574 pSMB->TotalDataCount = 0;
4575 pSMB->DataCount = 0;
4576 pSMB->DataOffset = 0;
4577 pSMB->MaxParameterCount = cpu_to_le16(2);
4578 /* BB find exact max SMB PDU from sess structure BB */
4579 pSMB->MaxDataCount = cpu_to_le16(100);
4580 pSMB->MaxSetupCount = 0;
4584 pSMB->Reserved2 = 0;
4585 byte_count = params + 1 /* pad */ ;
4586 pSMB->ParameterCount = cpu_to_le16(params);
4587 pSMB->TotalParameterCount = pSMB->ParameterCount;
4588 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4589 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4590 pSMB->SetupCount = 1;
4591 pSMB->Reserved3 = 0;
4592 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4593 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4594 pSMB->hdr.smb_buf_length += byte_count;
4595 pSMB->ByteCount = cpu_to_le16(byte_count);
4597 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4598 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4600 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4601 } else { /* decode response */
4602 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4604 if (rc || (pSMBr->ByteCount < 13)) {
4605 rc = -EIO; /* bad smb */
4607 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4609 (FILE_SYSTEM_POSIX_INFO
4610 *) (((char *) &pSMBr->hdr.Protocol) +
4613 le32_to_cpu(response_data->BlockSize);
4615 le64_to_cpu(response_data->TotalBlocks);
4617 le64_to_cpu(response_data->BlocksAvail);
4618 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4619 FSData->f_bavail = FSData->f_bfree;
4622 le64_to_cpu(response_data->UserBlocksAvail);
4624 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4626 le64_to_cpu(response_data->TotalFileNodes);
4627 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4629 le64_to_cpu(response_data->FreeFileNodes);
4632 cifs_buf_release(pSMB);
4641 /* We can not use write of zero bytes trick to
4642 set file size due to need for large file support. Also note that
4643 this SetPathInfo is preferred to SetFileInfo based method in next
4644 routine which is only needed to work around a sharing violation bug
4645 in Samba which this routine can run into */
4648 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4649 __u64 size, bool SetAllocation,
4650 const struct nls_table *nls_codepage, int remap)
4652 struct smb_com_transaction2_spi_req *pSMB = NULL;
4653 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4654 struct file_end_of_file_info *parm_data;
4657 int bytes_returned = 0;
4658 __u16 params, byte_count, data_count, param_offset, offset;
4660 cFYI(1, ("In SetEOF"));
4662 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4669 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4670 PATH_MAX, nls_codepage, remap);
4671 name_len++; /* trailing null */
4673 } else { /* BB improve the check for buffer overruns BB */
4674 name_len = strnlen(fileName, PATH_MAX);
4675 name_len++; /* trailing null */
4676 strncpy(pSMB->FileName, fileName, name_len);
4678 params = 6 + name_len;
4679 data_count = sizeof(struct file_end_of_file_info);
4680 pSMB->MaxParameterCount = cpu_to_le16(2);
4681 pSMB->MaxDataCount = cpu_to_le16(4100);
4682 pSMB->MaxSetupCount = 0;
4686 pSMB->Reserved2 = 0;
4687 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4688 InformationLevel) - 4;
4689 offset = param_offset + params;
4690 if (SetAllocation) {
4691 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4692 pSMB->InformationLevel =
4693 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4695 pSMB->InformationLevel =
4696 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4697 } else /* Set File Size */ {
4698 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4699 pSMB->InformationLevel =
4700 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4702 pSMB->InformationLevel =
4703 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4707 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4709 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4710 pSMB->DataOffset = cpu_to_le16(offset);
4711 pSMB->SetupCount = 1;
4712 pSMB->Reserved3 = 0;
4713 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4714 byte_count = 3 /* pad */ + params + data_count;
4715 pSMB->DataCount = cpu_to_le16(data_count);
4716 pSMB->TotalDataCount = pSMB->DataCount;
4717 pSMB->ParameterCount = cpu_to_le16(params);
4718 pSMB->TotalParameterCount = pSMB->ParameterCount;
4719 pSMB->Reserved4 = 0;
4720 pSMB->hdr.smb_buf_length += byte_count;
4721 parm_data->FileSize = cpu_to_le64(size);
4722 pSMB->ByteCount = cpu_to_le16(byte_count);
4723 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4724 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4726 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4728 cifs_buf_release(pSMB);
4737 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4738 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4740 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4742 struct file_end_of_file_info *parm_data;
4744 __u16 params, param_offset, offset, byte_count, count;
4746 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4748 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4753 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4754 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4757 pSMB->MaxSetupCount = 0;
4761 pSMB->Reserved2 = 0;
4762 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4763 offset = param_offset + params;
4765 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4767 count = sizeof(struct file_end_of_file_info);
4768 pSMB->MaxParameterCount = cpu_to_le16(2);
4769 /* BB find exact max SMB PDU from sess structure BB */
4770 pSMB->MaxDataCount = cpu_to_le16(1000);
4771 pSMB->SetupCount = 1;
4772 pSMB->Reserved3 = 0;
4773 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4774 byte_count = 3 /* pad */ + params + count;
4775 pSMB->DataCount = cpu_to_le16(count);
4776 pSMB->ParameterCount = cpu_to_le16(params);
4777 pSMB->TotalDataCount = pSMB->DataCount;
4778 pSMB->TotalParameterCount = pSMB->ParameterCount;
4779 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4781 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4783 pSMB->DataOffset = cpu_to_le16(offset);
4784 parm_data->FileSize = cpu_to_le64(size);
4786 if (SetAllocation) {
4787 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4788 pSMB->InformationLevel =
4789 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4791 pSMB->InformationLevel =
4792 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4793 } else /* Set File Size */ {
4794 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4795 pSMB->InformationLevel =
4796 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4798 pSMB->InformationLevel =
4799 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4801 pSMB->Reserved4 = 0;
4802 pSMB->hdr.smb_buf_length += byte_count;
4803 pSMB->ByteCount = cpu_to_le16(byte_count);
4804 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4807 ("Send error in SetFileInfo (SetFileSize) = %d",
4811 /* Note: On -EAGAIN error only caller can retry on handle based calls
4812 since file handle passed in no longer valid */
4817 /* Some legacy servers such as NT4 require that the file times be set on
4818 an open handle, rather than by pathname - this is awkward due to
4819 potential access conflicts on the open, but it is unavoidable for these
4820 old servers since the only other choice is to go from 100 nanosecond DCE
4821 time and resort to the original setpathinfo level which takes the ancient
4822 DOS time format with 2 second granularity */
4824 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4825 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4827 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4830 __u16 params, param_offset, offset, byte_count, count;
4832 cFYI(1, ("Set Times (via SetFileInfo)"));
4833 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4838 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4839 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4842 pSMB->MaxSetupCount = 0;
4846 pSMB->Reserved2 = 0;
4847 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4848 offset = param_offset + params;
4850 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4852 count = sizeof(FILE_BASIC_INFO);
4853 pSMB->MaxParameterCount = cpu_to_le16(2);
4854 /* BB find max SMB PDU from sess */
4855 pSMB->MaxDataCount = cpu_to_le16(1000);
4856 pSMB->SetupCount = 1;
4857 pSMB->Reserved3 = 0;
4858 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4859 byte_count = 3 /* pad */ + params + count;
4860 pSMB->DataCount = cpu_to_le16(count);
4861 pSMB->ParameterCount = cpu_to_le16(params);
4862 pSMB->TotalDataCount = pSMB->DataCount;
4863 pSMB->TotalParameterCount = pSMB->ParameterCount;
4864 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4865 pSMB->DataOffset = cpu_to_le16(offset);
4867 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4868 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4870 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4871 pSMB->Reserved4 = 0;
4872 pSMB->hdr.smb_buf_length += byte_count;
4873 pSMB->ByteCount = cpu_to_le16(byte_count);
4874 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4875 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4877 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4879 /* Note: On -EAGAIN error only caller can retry on handle based calls
4880 since file handle passed in no longer valid */
4886 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4887 bool delete_file, __u16 fid, __u32 pid_of_opener)
4889 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4892 __u16 params, param_offset, offset, byte_count, count;
4894 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4895 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4900 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4901 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4904 pSMB->MaxSetupCount = 0;
4908 pSMB->Reserved2 = 0;
4909 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4910 offset = param_offset + params;
4912 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4915 pSMB->MaxParameterCount = cpu_to_le16(2);
4916 /* BB find max SMB PDU from sess */
4917 pSMB->MaxDataCount = cpu_to_le16(1000);
4918 pSMB->SetupCount = 1;
4919 pSMB->Reserved3 = 0;
4920 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4921 byte_count = 3 /* pad */ + params + count;
4922 pSMB->DataCount = cpu_to_le16(count);
4923 pSMB->ParameterCount = cpu_to_le16(params);
4924 pSMB->TotalDataCount = pSMB->DataCount;
4925 pSMB->TotalParameterCount = pSMB->ParameterCount;
4926 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4927 pSMB->DataOffset = cpu_to_le16(offset);
4929 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4930 pSMB->Reserved4 = 0;
4931 pSMB->hdr.smb_buf_length += byte_count;
4932 pSMB->ByteCount = cpu_to_le16(byte_count);
4933 *data_offset = delete_file ? 1 : 0;
4934 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4936 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4942 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4943 const char *fileName, const FILE_BASIC_INFO *data,
4944 const struct nls_table *nls_codepage, int remap)
4946 TRANSACTION2_SPI_REQ *pSMB = NULL;
4947 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4950 int bytes_returned = 0;
4952 __u16 params, param_offset, offset, byte_count, count;
4954 cFYI(1, ("In SetTimes"));
4957 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4962 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4964 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4965 PATH_MAX, nls_codepage, remap);
4966 name_len++; /* trailing null */
4968 } else { /* BB improve the check for buffer overruns BB */
4969 name_len = strnlen(fileName, PATH_MAX);
4970 name_len++; /* trailing null */
4971 strncpy(pSMB->FileName, fileName, name_len);
4974 params = 6 + name_len;
4975 count = sizeof(FILE_BASIC_INFO);
4976 pSMB->MaxParameterCount = cpu_to_le16(2);
4977 /* BB find max SMB PDU from sess structure BB */
4978 pSMB->MaxDataCount = cpu_to_le16(1000);
4979 pSMB->MaxSetupCount = 0;
4983 pSMB->Reserved2 = 0;
4984 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4985 InformationLevel) - 4;
4986 offset = param_offset + params;
4987 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4988 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4989 pSMB->DataOffset = cpu_to_le16(offset);
4990 pSMB->SetupCount = 1;
4991 pSMB->Reserved3 = 0;
4992 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4993 byte_count = 3 /* pad */ + params + count;
4995 pSMB->DataCount = cpu_to_le16(count);
4996 pSMB->ParameterCount = cpu_to_le16(params);
4997 pSMB->TotalDataCount = pSMB->DataCount;
4998 pSMB->TotalParameterCount = pSMB->ParameterCount;
4999 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5000 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5002 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5003 pSMB->Reserved4 = 0;
5004 pSMB->hdr.smb_buf_length += byte_count;
5005 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5006 pSMB->ByteCount = cpu_to_le16(byte_count);
5007 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5008 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5010 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5012 cifs_buf_release(pSMB);
5020 /* Can not be used to set time stamps yet (due to old DOS time format) */
5021 /* Can be used to set attributes */
5022 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5023 handling it anyway and NT4 was what we thought it would be needed for
5024 Do not delete it until we prove whether needed for Win9x though */
5026 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5027 __u16 dos_attrs, const struct nls_table *nls_codepage)
5029 SETATTR_REQ *pSMB = NULL;
5030 SETATTR_RSP *pSMBr = NULL;
5035 cFYI(1, ("In SetAttrLegacy"));
5038 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5043 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5045 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5046 PATH_MAX, nls_codepage);
5047 name_len++; /* trailing null */
5049 } else { /* BB improve the check for buffer overruns BB */
5050 name_len = strnlen(fileName, PATH_MAX);
5051 name_len++; /* trailing null */
5052 strncpy(pSMB->fileName, fileName, name_len);
5054 pSMB->attr = cpu_to_le16(dos_attrs);
5055 pSMB->BufferFormat = 0x04;
5056 pSMB->hdr.smb_buf_length += name_len + 1;
5057 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5058 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5059 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5061 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5063 cifs_buf_release(pSMB);
5066 goto SetAttrLgcyRetry;
5070 #endif /* temporarily unneeded SetAttr legacy function */
5073 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5074 const struct cifs_unix_set_info_args *args,
5075 const struct nls_table *nls_codepage, int remap)
5077 TRANSACTION2_SPI_REQ *pSMB = NULL;
5078 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5081 int bytes_returned = 0;
5082 FILE_UNIX_BASIC_INFO *data_offset;
5083 __u16 params, param_offset, offset, count, byte_count;
5084 __u64 mode = args->mode;
5086 cFYI(1, ("In SetUID/GID/Mode"));
5088 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5093 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5095 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5096 PATH_MAX, nls_codepage, remap);
5097 name_len++; /* trailing null */
5099 } else { /* BB improve the check for buffer overruns BB */
5100 name_len = strnlen(fileName, PATH_MAX);
5101 name_len++; /* trailing null */
5102 strncpy(pSMB->FileName, fileName, name_len);
5105 params = 6 + name_len;
5106 count = sizeof(FILE_UNIX_BASIC_INFO);
5107 pSMB->MaxParameterCount = cpu_to_le16(2);
5108 /* BB find max SMB PDU from sess structure BB */
5109 pSMB->MaxDataCount = cpu_to_le16(1000);
5110 pSMB->MaxSetupCount = 0;
5114 pSMB->Reserved2 = 0;
5115 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5116 InformationLevel) - 4;
5117 offset = param_offset + params;
5119 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5121 memset(data_offset, 0, count);
5122 pSMB->DataOffset = cpu_to_le16(offset);
5123 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5124 pSMB->SetupCount = 1;
5125 pSMB->Reserved3 = 0;
5126 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5127 byte_count = 3 /* pad */ + params + count;
5128 pSMB->ParameterCount = cpu_to_le16(params);
5129 pSMB->DataCount = cpu_to_le16(count);
5130 pSMB->TotalParameterCount = pSMB->ParameterCount;
5131 pSMB->TotalDataCount = pSMB->DataCount;
5132 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5133 pSMB->Reserved4 = 0;
5134 pSMB->hdr.smb_buf_length += byte_count;
5135 /* Samba server ignores set of file size to zero due to bugs in some
5136 older clients, but we should be precise - we use SetFileSize to
5137 set file size and do not want to truncate file size to zero
5138 accidently as happened on one Samba server beta by putting
5139 zero instead of -1 here */
5140 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5141 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5142 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5143 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5144 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5145 data_offset->Uid = cpu_to_le64(args->uid);
5146 data_offset->Gid = cpu_to_le64(args->gid);
5147 /* better to leave device as zero when it is */
5148 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5149 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5150 data_offset->Permissions = cpu_to_le64(mode);
5153 data_offset->Type = cpu_to_le32(UNIX_FILE);
5154 else if (S_ISDIR(mode))
5155 data_offset->Type = cpu_to_le32(UNIX_DIR);
5156 else if (S_ISLNK(mode))
5157 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5158 else if (S_ISCHR(mode))
5159 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5160 else if (S_ISBLK(mode))
5161 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5162 else if (S_ISFIFO(mode))
5163 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5164 else if (S_ISSOCK(mode))
5165 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5168 pSMB->ByteCount = cpu_to_le16(byte_count);
5169 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5170 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5172 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5174 cifs_buf_release(pSMB);
5180 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5181 const int notify_subdirs, const __u16 netfid,
5182 __u32 filter, struct file *pfile, int multishot,
5183 const struct nls_table *nls_codepage)
5186 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5187 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5188 struct dir_notify_req *dnotify_req;
5191 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5192 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5197 pSMB->TotalParameterCount = 0 ;
5198 pSMB->TotalDataCount = 0;
5199 pSMB->MaxParameterCount = cpu_to_le32(2);
5200 /* BB find exact data count max from sess structure BB */
5201 pSMB->MaxDataCount = 0; /* same in little endian or be */
5202 /* BB VERIFY verify which is correct for above BB */
5203 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5204 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5206 pSMB->MaxSetupCount = 4;
5208 pSMB->ParameterOffset = 0;
5209 pSMB->DataCount = 0;
5210 pSMB->DataOffset = 0;
5211 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5212 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5213 pSMB->ParameterCount = pSMB->TotalParameterCount;
5215 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5216 pSMB->Reserved2 = 0;
5217 pSMB->CompletionFilter = cpu_to_le32(filter);
5218 pSMB->Fid = netfid; /* file handle always le */
5219 pSMB->ByteCount = 0;
5221 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5222 (struct smb_hdr *)pSMBr, &bytes_returned,
5225 cFYI(1, ("Error in Notify = %d", rc));
5227 /* Add file to outstanding requests */
5228 /* BB change to kmem cache alloc */
5229 dnotify_req = kmalloc(
5230 sizeof(struct dir_notify_req),
5233 dnotify_req->Pid = pSMB->hdr.Pid;
5234 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5235 dnotify_req->Mid = pSMB->hdr.Mid;
5236 dnotify_req->Tid = pSMB->hdr.Tid;
5237 dnotify_req->Uid = pSMB->hdr.Uid;
5238 dnotify_req->netfid = netfid;
5239 dnotify_req->pfile = pfile;
5240 dnotify_req->filter = filter;
5241 dnotify_req->multishot = multishot;
5242 spin_lock(&GlobalMid_Lock);
5243 list_add_tail(&dnotify_req->lhead,
5244 &GlobalDnotifyReqList);
5245 spin_unlock(&GlobalMid_Lock);
5249 cifs_buf_release(pSMB);
5252 #ifdef CONFIG_CIFS_XATTR
5254 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5255 const unsigned char *searchName,
5256 char *EAData, size_t buf_size,
5257 const struct nls_table *nls_codepage, int remap)
5259 /* BB assumes one setup word */
5260 TRANSACTION2_QPI_REQ *pSMB = NULL;
5261 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5265 struct fea *temp_fea;
5267 __u16 params, byte_count;
5269 cFYI(1, ("In Query All EAs path %s", searchName));
5271 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5276 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5278 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5279 PATH_MAX, nls_codepage, remap);
5280 name_len++; /* trailing null */
5282 } else { /* BB improve the check for buffer overruns BB */
5283 name_len = strnlen(searchName, PATH_MAX);
5284 name_len++; /* trailing null */
5285 strncpy(pSMB->FileName, searchName, name_len);
5288 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5289 pSMB->TotalDataCount = 0;
5290 pSMB->MaxParameterCount = cpu_to_le16(2);
5291 /* BB find exact max SMB PDU from sess structure BB */
5292 pSMB->MaxDataCount = cpu_to_le16(4000);
5293 pSMB->MaxSetupCount = 0;
5297 pSMB->Reserved2 = 0;
5298 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5299 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5300 pSMB->DataCount = 0;
5301 pSMB->DataOffset = 0;
5302 pSMB->SetupCount = 1;
5303 pSMB->Reserved3 = 0;
5304 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5305 byte_count = params + 1 /* pad */ ;
5306 pSMB->TotalParameterCount = cpu_to_le16(params);
5307 pSMB->ParameterCount = pSMB->TotalParameterCount;
5308 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5309 pSMB->Reserved4 = 0;
5310 pSMB->hdr.smb_buf_length += byte_count;
5311 pSMB->ByteCount = cpu_to_le16(byte_count);
5313 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5314 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5316 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5317 } else { /* decode response */
5318 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5320 /* BB also check enough total bytes returned */
5321 /* BB we need to improve the validity checking
5322 of these trans2 responses */
5323 if (rc || (pSMBr->ByteCount < 4))
5324 rc = -EIO; /* bad smb */
5325 /* else if (pFindData){
5326 memcpy((char *) pFindData,
5327 (char *) &pSMBr->hdr.Protocol +
5330 /* check that length of list is not more than bcc */
5331 /* check that each entry does not go beyond length
5333 /* check that each element of each entry does not
5334 go beyond end of list */
5335 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5336 struct fealist *ea_response_data;
5338 /* validate_trans2_offsets() */
5339 /* BB check if start of smb + data_offset > &bcc+ bcc */
5340 ea_response_data = (struct fealist *)
5341 (((char *) &pSMBr->hdr.Protocol) +
5343 name_len = le32_to_cpu(ea_response_data->list_len);
5344 cFYI(1, ("ea length %d", name_len));
5345 if (name_len <= 8) {
5346 /* returned EA size zeroed at top of function */
5347 cFYI(1, ("empty EA list returned from server"));
5349 /* account for ea list len */
5351 temp_fea = ea_response_data->list;
5352 temp_ptr = (char *)temp_fea;
5353 while (name_len > 0) {
5357 rc += temp_fea->name_len;
5358 /* account for prefix user. and trailing null */
5360 if (rc < (int)buf_size) {
5361 memcpy(EAData, "user.", 5);
5363 memcpy(EAData, temp_ptr,
5364 temp_fea->name_len);
5365 EAData += temp_fea->name_len;
5366 /* null terminate name */
5368 EAData = EAData + 1;
5369 } else if (buf_size == 0) {
5370 /* skip copy - calc size only */
5372 /* stop before overrun buffer */
5376 name_len -= temp_fea->name_len;
5377 temp_ptr += temp_fea->name_len;
5378 /* account for trailing null */
5382 le16_to_cpu(temp_fea->value_len);
5383 name_len -= value_len;
5384 temp_ptr += value_len;
5385 /* BB check that temp_ptr is still
5388 /* no trailing null to account for
5390 /* go on to next EA */
5391 temp_fea = (struct fea *)temp_ptr;
5396 cifs_buf_release(pSMB);
5403 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5404 const unsigned char *searchName, const unsigned char *ea_name,
5405 unsigned char *ea_value, size_t buf_size,
5406 const struct nls_table *nls_codepage, int remap)
5408 TRANSACTION2_QPI_REQ *pSMB = NULL;
5409 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5413 struct fea *temp_fea;
5415 __u16 params, byte_count;
5417 cFYI(1, ("In Query EA path %s", searchName));
5419 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5424 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5426 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5427 PATH_MAX, nls_codepage, remap);
5428 name_len++; /* trailing null */
5430 } else { /* BB improve the check for buffer overruns BB */
5431 name_len = strnlen(searchName, PATH_MAX);
5432 name_len++; /* trailing null */
5433 strncpy(pSMB->FileName, searchName, name_len);
5436 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5437 pSMB->TotalDataCount = 0;
5438 pSMB->MaxParameterCount = cpu_to_le16(2);
5439 /* BB find exact max SMB PDU from sess structure BB */
5440 pSMB->MaxDataCount = cpu_to_le16(4000);
5441 pSMB->MaxSetupCount = 0;
5445 pSMB->Reserved2 = 0;
5446 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5447 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5448 pSMB->DataCount = 0;
5449 pSMB->DataOffset = 0;
5450 pSMB->SetupCount = 1;
5451 pSMB->Reserved3 = 0;
5452 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5453 byte_count = params + 1 /* pad */ ;
5454 pSMB->TotalParameterCount = cpu_to_le16(params);
5455 pSMB->ParameterCount = pSMB->TotalParameterCount;
5456 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5457 pSMB->Reserved4 = 0;
5458 pSMB->hdr.smb_buf_length += byte_count;
5459 pSMB->ByteCount = cpu_to_le16(byte_count);
5461 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5462 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5464 cFYI(1, ("Send error in Query EA = %d", rc));
5465 } else { /* decode response */
5466 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5468 /* BB also check enough total bytes returned */
5469 /* BB we need to improve the validity checking
5470 of these trans2 responses */
5471 if (rc || (pSMBr->ByteCount < 4))
5472 rc = -EIO; /* bad smb */
5473 /* else if (pFindData){
5474 memcpy((char *) pFindData,
5475 (char *) &pSMBr->hdr.Protocol +
5478 /* check that length of list is not more than bcc */
5479 /* check that each entry does not go beyond length
5481 /* check that each element of each entry does not
5482 go beyond end of list */
5483 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5484 struct fealist *ea_response_data;
5486 /* validate_trans2_offsets() */
5487 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5488 ea_response_data = (struct fealist *)
5489 (((char *) &pSMBr->hdr.Protocol) +
5491 name_len = le32_to_cpu(ea_response_data->list_len);
5492 cFYI(1, ("ea length %d", name_len));
5493 if (name_len <= 8) {
5494 /* returned EA size zeroed at top of function */
5495 cFYI(1, ("empty EA list returned from server"));
5497 /* account for ea list len */
5499 temp_fea = ea_response_data->list;
5500 temp_ptr = (char *)temp_fea;
5501 /* loop through checking if we have a matching
5502 name and then return the associated value */
5503 while (name_len > 0) {
5508 le16_to_cpu(temp_fea->value_len);
5509 /* BB validate that value_len falls within SMB,
5510 even though maximum for name_len is 255 */
5511 if (memcmp(temp_fea->name, ea_name,
5512 temp_fea->name_len) == 0) {
5515 /* account for prefix user. and trailing null */
5516 if (rc <= (int)buf_size) {
5518 temp_fea->name+temp_fea->name_len+1,
5520 /* ea values, unlike ea
5523 } else if (buf_size == 0) {
5524 /* skip copy - calc size only */
5526 /* stop before overrun buffer */
5531 name_len -= temp_fea->name_len;
5532 temp_ptr += temp_fea->name_len;
5533 /* account for trailing null */
5536 name_len -= value_len;
5537 temp_ptr += value_len;
5538 /* No trailing null to account for in
5539 value_len. Go on to next EA */
5540 temp_fea = (struct fea *)temp_ptr;
5545 cifs_buf_release(pSMB);
5553 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5554 const char *ea_name, const void *ea_value,
5555 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5558 struct smb_com_transaction2_spi_req *pSMB = NULL;
5559 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5560 struct fealist *parm_data;
5563 int bytes_returned = 0;
5564 __u16 params, param_offset, byte_count, offset, count;
5566 cFYI(1, ("In SetEA"));
5568 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5573 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5575 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5576 PATH_MAX, nls_codepage, remap);
5577 name_len++; /* trailing null */
5579 } else { /* BB improve the check for buffer overruns BB */
5580 name_len = strnlen(fileName, PATH_MAX);
5581 name_len++; /* trailing null */
5582 strncpy(pSMB->FileName, fileName, name_len);
5585 params = 6 + name_len;
5587 /* done calculating parms using name_len of file name,
5588 now use name_len to calculate length of ea name
5589 we are going to create in the inode xattrs */
5590 if (ea_name == NULL)
5593 name_len = strnlen(ea_name, 255);
5595 count = sizeof(*parm_data) + ea_value_len + name_len;
5596 pSMB->MaxParameterCount = cpu_to_le16(2);
5597 /* BB find max SMB PDU from sess */
5598 pSMB->MaxDataCount = cpu_to_le16(1000);
5599 pSMB->MaxSetupCount = 0;
5603 pSMB->Reserved2 = 0;
5604 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5605 InformationLevel) - 4;
5606 offset = param_offset + params;
5607 pSMB->InformationLevel =
5608 cpu_to_le16(SMB_SET_FILE_EA);
5611 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5613 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5614 pSMB->DataOffset = cpu_to_le16(offset);
5615 pSMB->SetupCount = 1;
5616 pSMB->Reserved3 = 0;
5617 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5618 byte_count = 3 /* pad */ + params + count;
5619 pSMB->DataCount = cpu_to_le16(count);
5620 parm_data->list_len = cpu_to_le32(count);
5621 parm_data->list[0].EA_flags = 0;
5622 /* we checked above that name len is less than 255 */
5623 parm_data->list[0].name_len = (__u8)name_len;
5624 /* EA names are always ASCII */
5626 strncpy(parm_data->list[0].name, ea_name, name_len);
5627 parm_data->list[0].name[name_len] = 0;
5628 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5629 /* caller ensures that ea_value_len is less than 64K but
5630 we need to ensure that it fits within the smb */
5632 /*BB add length check to see if it would fit in
5633 negotiated SMB buffer size BB */
5634 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5636 memcpy(parm_data->list[0].name+name_len+1,
5637 ea_value, ea_value_len);
5639 pSMB->TotalDataCount = pSMB->DataCount;
5640 pSMB->ParameterCount = cpu_to_le16(params);
5641 pSMB->TotalParameterCount = pSMB->ParameterCount;
5642 pSMB->Reserved4 = 0;
5643 pSMB->hdr.smb_buf_length += byte_count;
5644 pSMB->ByteCount = cpu_to_le16(byte_count);
5645 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5646 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5648 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5650 cifs_buf_release(pSMB);