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)
2577 struct smb_com_transaction_ioctl_req *pSMB;
2578 struct smb_com_transaction_ioctl_rsp *pSMBr;
2580 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2581 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2586 pSMB->TotalParameterCount = 0 ;
2587 pSMB->TotalDataCount = 0;
2588 pSMB->MaxParameterCount = cpu_to_le32(2);
2589 /* BB find exact data count max from sess structure BB */
2590 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2591 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2592 pSMB->MaxSetupCount = 4;
2594 pSMB->ParameterOffset = 0;
2595 pSMB->DataCount = 0;
2596 pSMB->DataOffset = 0;
2597 pSMB->SetupCount = 4;
2598 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2599 pSMB->ParameterCount = pSMB->TotalParameterCount;
2600 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2601 pSMB->IsFsctl = 1; /* FSCTL */
2602 pSMB->IsRootFlag = 0;
2603 pSMB->Fid = fid; /* file handle always le */
2604 pSMB->ByteCount = 0;
2606 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2607 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2609 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2610 } else { /* decode response */
2611 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2612 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2613 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2614 /* BB also check enough total bytes returned */
2615 rc = -EIO; /* bad smb */
2618 if (data_count && (data_count < 2048)) {
2619 char *end_of_smb = 2 /* sizeof byte count */ +
2620 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2622 struct reparse_data *reparse_buf =
2623 (struct reparse_data *)
2624 ((char *)&pSMBr->hdr.Protocol
2626 if ((char *)reparse_buf >= end_of_smb) {
2630 if ((reparse_buf->LinkNamesBuf +
2631 reparse_buf->TargetNameOffset +
2632 reparse_buf->TargetNameLen) > end_of_smb) {
2633 cFYI(1, ("reparse buf beyond SMB"));
2638 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2639 cifs_from_ucs2(symlinkinfo, (__le16 *)
2640 (reparse_buf->LinkNamesBuf +
2641 reparse_buf->TargetNameOffset),
2643 reparse_buf->TargetNameLen,
2645 } else { /* ASCII names */
2646 strncpy(symlinkinfo,
2647 reparse_buf->LinkNamesBuf +
2648 reparse_buf->TargetNameOffset,
2649 min_t(const int, buflen,
2650 reparse_buf->TargetNameLen));
2654 cFYI(1, ("Invalid return data count on "
2655 "get reparse info ioctl"));
2657 symlinkinfo[buflen] = 0; /* just in case so the caller
2658 does not go off the end of the buffer */
2659 cFYI(1, ("readlink result - %s", symlinkinfo));
2663 cifs_buf_release(pSMB);
2665 /* Note: On -EAGAIN error only caller can retry on handle based calls
2666 since file handle passed in no longer valid */
2670 #endif /* CIFS_EXPERIMENTAL */
2672 #ifdef CONFIG_CIFS_POSIX
2674 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2675 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2676 struct cifs_posix_ace *cifs_ace)
2678 /* u8 cifs fields do not need le conversion */
2679 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2680 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2681 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2682 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2687 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2688 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2689 const int acl_type, const int size_of_data_area)
2694 struct cifs_posix_ace *pACE;
2695 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2696 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2698 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2701 if (acl_type & ACL_TYPE_ACCESS) {
2702 count = le16_to_cpu(cifs_acl->access_entry_count);
2703 pACE = &cifs_acl->ace_array[0];
2704 size = sizeof(struct cifs_posix_acl);
2705 size += sizeof(struct cifs_posix_ace) * count;
2706 /* check if we would go beyond end of SMB */
2707 if (size_of_data_area < size) {
2708 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2709 size_of_data_area, size));
2712 } else if (acl_type & ACL_TYPE_DEFAULT) {
2713 count = le16_to_cpu(cifs_acl->access_entry_count);
2714 size = sizeof(struct cifs_posix_acl);
2715 size += sizeof(struct cifs_posix_ace) * count;
2716 /* skip past access ACEs to get to default ACEs */
2717 pACE = &cifs_acl->ace_array[count];
2718 count = le16_to_cpu(cifs_acl->default_entry_count);
2719 size += sizeof(struct cifs_posix_ace) * count;
2720 /* check if we would go beyond end of SMB */
2721 if (size_of_data_area < size)
2728 size = posix_acl_xattr_size(count);
2729 if ((buflen == 0) || (local_acl == NULL)) {
2730 /* used to query ACL EA size */
2731 } else if (size > buflen) {
2733 } else /* buffer big enough */ {
2734 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2735 for (i = 0; i < count ; i++) {
2736 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2743 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2744 const posix_acl_xattr_entry *local_ace)
2746 __u16 rc = 0; /* 0 = ACL converted ok */
2748 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2749 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2750 /* BB is there a better way to handle the large uid? */
2751 if (local_ace->e_id == cpu_to_le32(-1)) {
2752 /* Probably no need to le convert -1 on any arch but can not hurt */
2753 cifs_ace->cifs_uid = cpu_to_le64(-1);
2755 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2756 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2760 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2761 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2762 const int buflen, const int acl_type)
2765 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2766 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2770 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2773 count = posix_acl_xattr_count((size_t)buflen);
2774 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2776 count, buflen, le32_to_cpu(local_acl->a_version)));
2777 if (le32_to_cpu(local_acl->a_version) != 2) {
2778 cFYI(1, ("unknown POSIX ACL version %d",
2779 le32_to_cpu(local_acl->a_version)));
2782 cifs_acl->version = cpu_to_le16(1);
2783 if (acl_type == ACL_TYPE_ACCESS)
2784 cifs_acl->access_entry_count = cpu_to_le16(count);
2785 else if (acl_type == ACL_TYPE_DEFAULT)
2786 cifs_acl->default_entry_count = cpu_to_le16(count);
2788 cFYI(1, ("unknown ACL type %d", acl_type));
2791 for (i = 0; i < count; i++) {
2792 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2793 &local_acl->a_entries[i]);
2795 /* ACE not converted */
2800 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2801 rc += sizeof(struct cifs_posix_acl);
2802 /* BB add check to make sure ACL does not overflow SMB */
2808 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2809 const unsigned char *searchName,
2810 char *acl_inf, const int buflen, const int acl_type,
2811 const struct nls_table *nls_codepage, int remap)
2813 /* SMB_QUERY_POSIX_ACL */
2814 TRANSACTION2_QPI_REQ *pSMB = NULL;
2815 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2819 __u16 params, byte_count;
2821 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2824 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2829 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2831 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2832 PATH_MAX, nls_codepage, remap);
2833 name_len++; /* trailing null */
2835 pSMB->FileName[name_len] = 0;
2836 pSMB->FileName[name_len+1] = 0;
2837 } else { /* BB improve the check for buffer overruns BB */
2838 name_len = strnlen(searchName, PATH_MAX);
2839 name_len++; /* trailing null */
2840 strncpy(pSMB->FileName, searchName, name_len);
2843 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2844 pSMB->TotalDataCount = 0;
2845 pSMB->MaxParameterCount = cpu_to_le16(2);
2846 /* BB find exact max data count below from sess structure BB */
2847 pSMB->MaxDataCount = cpu_to_le16(4000);
2848 pSMB->MaxSetupCount = 0;
2852 pSMB->Reserved2 = 0;
2853 pSMB->ParameterOffset = cpu_to_le16(
2854 offsetof(struct smb_com_transaction2_qpi_req,
2855 InformationLevel) - 4);
2856 pSMB->DataCount = 0;
2857 pSMB->DataOffset = 0;
2858 pSMB->SetupCount = 1;
2859 pSMB->Reserved3 = 0;
2860 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2861 byte_count = params + 1 /* pad */ ;
2862 pSMB->TotalParameterCount = cpu_to_le16(params);
2863 pSMB->ParameterCount = pSMB->TotalParameterCount;
2864 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2865 pSMB->Reserved4 = 0;
2866 pSMB->hdr.smb_buf_length += byte_count;
2867 pSMB->ByteCount = cpu_to_le16(byte_count);
2869 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2870 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2871 cifs_stats_inc(&tcon->num_acl_get);
2873 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2875 /* decode response */
2877 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2878 if (rc || (pSMBr->ByteCount < 2))
2879 /* BB also check enough total bytes returned */
2880 rc = -EIO; /* bad smb */
2882 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2883 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2884 rc = cifs_copy_posix_acl(acl_inf,
2885 (char *)&pSMBr->hdr.Protocol+data_offset,
2886 buflen, acl_type, count);
2889 cifs_buf_release(pSMB);
2896 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2897 const unsigned char *fileName,
2898 const char *local_acl, const int buflen,
2900 const struct nls_table *nls_codepage, int remap)
2902 struct smb_com_transaction2_spi_req *pSMB = NULL;
2903 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2907 int bytes_returned = 0;
2908 __u16 params, byte_count, data_count, param_offset, offset;
2910 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2912 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2916 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2918 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2919 PATH_MAX, nls_codepage, remap);
2920 name_len++; /* trailing null */
2922 } else { /* BB improve the check for buffer overruns BB */
2923 name_len = strnlen(fileName, PATH_MAX);
2924 name_len++; /* trailing null */
2925 strncpy(pSMB->FileName, fileName, name_len);
2927 params = 6 + name_len;
2928 pSMB->MaxParameterCount = cpu_to_le16(2);
2929 /* BB find max SMB size from sess */
2930 pSMB->MaxDataCount = cpu_to_le16(1000);
2931 pSMB->MaxSetupCount = 0;
2935 pSMB->Reserved2 = 0;
2936 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2937 InformationLevel) - 4;
2938 offset = param_offset + params;
2939 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2940 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2942 /* convert to on the wire format for POSIX ACL */
2943 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2945 if (data_count == 0) {
2947 goto setACLerrorExit;
2949 pSMB->DataOffset = cpu_to_le16(offset);
2950 pSMB->SetupCount = 1;
2951 pSMB->Reserved3 = 0;
2952 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2953 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2954 byte_count = 3 /* pad */ + params + data_count;
2955 pSMB->DataCount = cpu_to_le16(data_count);
2956 pSMB->TotalDataCount = pSMB->DataCount;
2957 pSMB->ParameterCount = cpu_to_le16(params);
2958 pSMB->TotalParameterCount = pSMB->ParameterCount;
2959 pSMB->Reserved4 = 0;
2960 pSMB->hdr.smb_buf_length += byte_count;
2961 pSMB->ByteCount = cpu_to_le16(byte_count);
2962 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2963 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2965 cFYI(1, ("Set POSIX ACL returned %d", rc));
2968 cifs_buf_release(pSMB);
2974 /* BB fix tabs in this function FIXME BB */
2976 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2977 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2980 struct smb_t2_qfi_req *pSMB = NULL;
2981 struct smb_t2_qfi_rsp *pSMBr = NULL;
2983 __u16 params, byte_count;
2985 cFYI(1, ("In GetExtAttr"));
2990 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2995 params = 2 /* level */ + 2 /* fid */;
2996 pSMB->t2.TotalDataCount = 0;
2997 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2998 /* BB find exact max data count below from sess structure BB */
2999 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3000 pSMB->t2.MaxSetupCount = 0;
3001 pSMB->t2.Reserved = 0;
3003 pSMB->t2.Timeout = 0;
3004 pSMB->t2.Reserved2 = 0;
3005 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3007 pSMB->t2.DataCount = 0;
3008 pSMB->t2.DataOffset = 0;
3009 pSMB->t2.SetupCount = 1;
3010 pSMB->t2.Reserved3 = 0;
3011 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3012 byte_count = params + 1 /* pad */ ;
3013 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3014 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3015 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3018 pSMB->hdr.smb_buf_length += byte_count;
3019 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3021 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3022 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3024 cFYI(1, ("error %d in GetExtAttr", rc));
3026 /* decode response */
3027 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3028 if (rc || (pSMBr->ByteCount < 2))
3029 /* BB also check enough total bytes returned */
3030 /* If rc should we check for EOPNOSUPP and
3031 disable the srvino flag? or in caller? */
3032 rc = -EIO; /* bad smb */
3034 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3035 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3036 struct file_chattr_info *pfinfo;
3037 /* BB Do we need a cast or hash here ? */
3039 cFYI(1, ("Illegal size ret in GetExtAttr"));
3043 pfinfo = (struct file_chattr_info *)
3044 (data_offset + (char *) &pSMBr->hdr.Protocol);
3045 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3046 *pMask = le64_to_cpu(pfinfo->mask);
3050 cifs_buf_release(pSMB);
3052 goto GetExtAttrRetry;
3056 #endif /* CONFIG_POSIX */
3058 #ifdef CONFIG_CIFS_EXPERIMENTAL
3059 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3061 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3062 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3066 QUERY_SEC_DESC_REQ *pSMB;
3069 cFYI(1, ("GetCifsACL"));
3074 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3075 8 /* parm len */, tcon, (void **) &pSMB);
3079 pSMB->MaxParameterCount = cpu_to_le32(4);
3080 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3081 pSMB->MaxSetupCount = 0;
3082 pSMB->Fid = fid; /* file handle always le */
3083 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3085 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3086 pSMB->hdr.smb_buf_length += 11;
3087 iov[0].iov_base = (char *)pSMB;
3088 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3090 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3092 cifs_stats_inc(&tcon->num_acl_get);
3094 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3095 } else { /* decode response */
3099 struct smb_com_ntransact_rsp *pSMBr;
3102 /* validate_nttransact */
3103 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3104 &pdata, &parm_len, pbuflen);
3107 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3109 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3111 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3112 rc = -EIO; /* bad smb */
3117 /* BB check that data area is minimum length and as big as acl_len */
3119 acl_len = le32_to_cpu(*parm);
3120 if (acl_len != *pbuflen) {
3121 cERROR(1, ("acl length %d does not match %d",
3122 acl_len, *pbuflen));
3123 if (*pbuflen > acl_len)
3127 /* check if buffer is big enough for the acl
3128 header followed by the smallest SID */
3129 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3130 (*pbuflen >= 64 * 1024)) {
3131 cERROR(1, ("bad acl length %d", *pbuflen));
3135 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3136 if (*acl_inf == NULL) {
3140 memcpy(*acl_inf, pdata, *pbuflen);
3144 if (buf_type == CIFS_SMALL_BUFFER)
3145 cifs_small_buf_release(iov[0].iov_base);
3146 else if (buf_type == CIFS_LARGE_BUFFER)
3147 cifs_buf_release(iov[0].iov_base);
3148 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3153 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3154 struct cifs_ntsd *pntsd, __u32 acllen)
3156 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3158 int bytes_returned = 0;
3159 SET_SEC_DESC_REQ *pSMB = NULL;
3160 NTRANSACT_RSP *pSMBr = NULL;
3163 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3168 pSMB->MaxSetupCount = 0;
3172 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3173 data_count = acllen;
3174 data_offset = param_offset + param_count;
3175 byte_count = 3 /* pad */ + param_count;
3177 pSMB->DataCount = cpu_to_le32(data_count);
3178 pSMB->TotalDataCount = pSMB->DataCount;
3179 pSMB->MaxParameterCount = cpu_to_le32(4);
3180 pSMB->MaxDataCount = cpu_to_le32(16384);
3181 pSMB->ParameterCount = cpu_to_le32(param_count);
3182 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3183 pSMB->TotalParameterCount = pSMB->ParameterCount;
3184 pSMB->DataOffset = cpu_to_le32(data_offset);
3185 pSMB->SetupCount = 0;
3186 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3187 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3189 pSMB->Fid = fid; /* file handle always le */
3190 pSMB->Reserved2 = 0;
3191 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3193 if (pntsd && acllen) {
3194 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3197 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3200 pSMB->hdr.smb_buf_length += byte_count;
3202 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3203 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3205 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3207 cFYI(1, ("Set CIFS ACL returned %d", rc));
3208 cifs_buf_release(pSMB);
3211 goto setCifsAclRetry;
3216 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3218 /* Legacy Query Path Information call for lookup to old servers such
3220 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3221 const unsigned char *searchName,
3222 FILE_ALL_INFO *pFinfo,
3223 const struct nls_table *nls_codepage, int remap)
3225 QUERY_INFORMATION_REQ *pSMB;
3226 QUERY_INFORMATION_RSP *pSMBr;
3231 cFYI(1, ("In SMBQPath path %s", searchName));
3233 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3238 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3240 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3241 PATH_MAX, nls_codepage, remap);
3242 name_len++; /* trailing null */
3245 name_len = strnlen(searchName, PATH_MAX);
3246 name_len++; /* trailing null */
3247 strncpy(pSMB->FileName, searchName, name_len);
3249 pSMB->BufferFormat = 0x04;
3250 name_len++; /* account for buffer type byte */
3251 pSMB->hdr.smb_buf_length += (__u16) name_len;
3252 pSMB->ByteCount = cpu_to_le16(name_len);
3254 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3255 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3257 cFYI(1, ("Send error in QueryInfo = %d", rc));
3258 } else if (pFinfo) {
3260 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3262 /* decode response */
3263 /* BB FIXME - add time zone adjustment BB */
3264 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3267 /* decode time fields */
3268 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3269 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3270 pFinfo->LastAccessTime = 0;
3271 pFinfo->AllocationSize =
3272 cpu_to_le64(le32_to_cpu(pSMBr->size));
3273 pFinfo->EndOfFile = pFinfo->AllocationSize;
3274 pFinfo->Attributes =
3275 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3277 rc = -EIO; /* bad buffer passed in */
3279 cifs_buf_release(pSMB);
3291 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3292 const unsigned char *searchName,
3293 FILE_ALL_INFO *pFindData,
3294 int legacy /* old style infolevel */,
3295 const struct nls_table *nls_codepage, int remap)
3297 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3298 TRANSACTION2_QPI_REQ *pSMB = NULL;
3299 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3303 __u16 params, byte_count;
3305 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3307 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3312 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3314 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3315 PATH_MAX, nls_codepage, remap);
3316 name_len++; /* trailing null */
3318 } else { /* BB improve the check for buffer overruns BB */
3319 name_len = strnlen(searchName, PATH_MAX);
3320 name_len++; /* trailing null */
3321 strncpy(pSMB->FileName, searchName, name_len);
3324 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3325 pSMB->TotalDataCount = 0;
3326 pSMB->MaxParameterCount = cpu_to_le16(2);
3327 /* BB find exact max SMB PDU from sess structure BB */
3328 pSMB->MaxDataCount = cpu_to_le16(4000);
3329 pSMB->MaxSetupCount = 0;
3333 pSMB->Reserved2 = 0;
3334 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3335 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3336 pSMB->DataCount = 0;
3337 pSMB->DataOffset = 0;
3338 pSMB->SetupCount = 1;
3339 pSMB->Reserved3 = 0;
3340 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3341 byte_count = params + 1 /* pad */ ;
3342 pSMB->TotalParameterCount = cpu_to_le16(params);
3343 pSMB->ParameterCount = pSMB->TotalParameterCount;
3345 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3347 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3348 pSMB->Reserved4 = 0;
3349 pSMB->hdr.smb_buf_length += byte_count;
3350 pSMB->ByteCount = cpu_to_le16(byte_count);
3352 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3353 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3355 cFYI(1, ("Send error in QPathInfo = %d", rc));
3356 } else { /* decode response */
3357 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3359 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3361 else if (!legacy && (pSMBr->ByteCount < 40))
3362 rc = -EIO; /* bad smb */
3363 else if (legacy && (pSMBr->ByteCount < 24))
3364 rc = -EIO; /* 24 or 26 expected but we do not read
3366 else if (pFindData) {
3368 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3370 /* On legacy responses we do not read the last field,
3371 EAsize, fortunately since it varies by subdialect and
3372 also note it differs on Set vs. Get, ie two bytes or 4
3373 bytes depending but we don't care here */
3375 size = sizeof(FILE_INFO_STANDARD);
3377 size = sizeof(FILE_ALL_INFO);
3378 memcpy((char *) pFindData,
3379 (char *) &pSMBr->hdr.Protocol +
3384 cifs_buf_release(pSMB);
3386 goto QPathInfoRetry;
3392 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3393 const unsigned char *searchName,
3394 FILE_UNIX_BASIC_INFO *pFindData,
3395 const struct nls_table *nls_codepage, int remap)
3397 /* SMB_QUERY_FILE_UNIX_BASIC */
3398 TRANSACTION2_QPI_REQ *pSMB = NULL;
3399 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3401 int bytes_returned = 0;
3403 __u16 params, byte_count;
3405 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3407 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3412 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3414 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3415 PATH_MAX, nls_codepage, remap);
3416 name_len++; /* trailing null */
3418 } else { /* BB improve the check for buffer overruns BB */
3419 name_len = strnlen(searchName, PATH_MAX);
3420 name_len++; /* trailing null */
3421 strncpy(pSMB->FileName, searchName, name_len);
3424 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3425 pSMB->TotalDataCount = 0;
3426 pSMB->MaxParameterCount = cpu_to_le16(2);
3427 /* BB find exact max SMB PDU from sess structure BB */
3428 pSMB->MaxDataCount = cpu_to_le16(4000);
3429 pSMB->MaxSetupCount = 0;
3433 pSMB->Reserved2 = 0;
3434 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3435 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3436 pSMB->DataCount = 0;
3437 pSMB->DataOffset = 0;
3438 pSMB->SetupCount = 1;
3439 pSMB->Reserved3 = 0;
3440 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3441 byte_count = params + 1 /* pad */ ;
3442 pSMB->TotalParameterCount = cpu_to_le16(params);
3443 pSMB->ParameterCount = pSMB->TotalParameterCount;
3444 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3445 pSMB->Reserved4 = 0;
3446 pSMB->hdr.smb_buf_length += byte_count;
3447 pSMB->ByteCount = cpu_to_le16(byte_count);
3449 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3450 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3452 cFYI(1, ("Send error in QPathInfo = %d", rc));
3453 } else { /* decode response */
3454 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3456 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3457 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3458 "Unix Extensions can be disabled on mount "
3459 "by specifying the nosfu mount option."));
3460 rc = -EIO; /* bad smb */
3462 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3463 memcpy((char *) pFindData,
3464 (char *) &pSMBr->hdr.Protocol +
3466 sizeof(FILE_UNIX_BASIC_INFO));
3469 cifs_buf_release(pSMB);
3471 goto UnixQPathInfoRetry;
3476 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3478 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3479 const char *searchName,
3480 const struct nls_table *nls_codepage,
3482 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3484 /* level 257 SMB_ */
3485 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3486 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3487 T2_FFIRST_RSP_PARMS *parms;
3489 int bytes_returned = 0;
3491 __u16 params, byte_count;
3493 cFYI(1, ("In FindFirst for %s", searchName));
3496 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3501 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3503 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3504 PATH_MAX, nls_codepage, remap);
3505 /* We can not add the asterik earlier in case
3506 it got remapped to 0xF03A as if it were part of the
3507 directory name instead of a wildcard */
3509 pSMB->FileName[name_len] = dirsep;
3510 pSMB->FileName[name_len+1] = 0;
3511 pSMB->FileName[name_len+2] = '*';
3512 pSMB->FileName[name_len+3] = 0;
3513 name_len += 4; /* now the trailing null */
3514 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3515 pSMB->FileName[name_len+1] = 0;
3517 } else { /* BB add check for overrun of SMB buf BB */
3518 name_len = strnlen(searchName, PATH_MAX);
3519 /* BB fix here and in unicode clause above ie
3520 if (name_len > buffersize-header)
3521 free buffer exit; BB */
3522 strncpy(pSMB->FileName, searchName, name_len);
3523 pSMB->FileName[name_len] = dirsep;
3524 pSMB->FileName[name_len+1] = '*';
3525 pSMB->FileName[name_len+2] = 0;
3529 params = 12 + name_len /* includes null */ ;
3530 pSMB->TotalDataCount = 0; /* no EAs */
3531 pSMB->MaxParameterCount = cpu_to_le16(10);
3532 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3533 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3534 pSMB->MaxSetupCount = 0;
3538 pSMB->Reserved2 = 0;
3539 byte_count = params + 1 /* pad */ ;
3540 pSMB->TotalParameterCount = cpu_to_le16(params);
3541 pSMB->ParameterCount = pSMB->TotalParameterCount;
3542 pSMB->ParameterOffset = cpu_to_le16(
3543 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3545 pSMB->DataCount = 0;
3546 pSMB->DataOffset = 0;
3547 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3548 pSMB->Reserved3 = 0;
3549 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3550 pSMB->SearchAttributes =
3551 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3553 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3554 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3555 CIFS_SEARCH_RETURN_RESUME);
3556 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3558 /* BB what should we set StorageType to? Does it matter? BB */
3559 pSMB->SearchStorageType = 0;
3560 pSMB->hdr.smb_buf_length += byte_count;
3561 pSMB->ByteCount = cpu_to_le16(byte_count);
3563 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3564 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3565 cifs_stats_inc(&tcon->num_ffirst);
3567 if (rc) {/* BB add logic to retry regular search if Unix search
3568 rejected unexpectedly by server */
3569 /* BB Add code to handle unsupported level rc */
3570 cFYI(1, ("Error in FindFirst = %d", rc));
3572 cifs_buf_release(pSMB);
3574 /* BB eventually could optimize out free and realloc of buf */
3577 goto findFirstRetry;
3578 } else { /* decode response */
3579 /* BB remember to free buffer if error BB */
3580 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3584 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3585 psrch_inf->unicode = true;
3587 psrch_inf->unicode = false;
3589 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3590 psrch_inf->smallBuf = 0;
3591 psrch_inf->srch_entries_start =
3592 (char *) &pSMBr->hdr.Protocol +
3593 le16_to_cpu(pSMBr->t2.DataOffset);
3594 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3595 le16_to_cpu(pSMBr->t2.ParameterOffset));
3597 if (parms->EndofSearch)
3598 psrch_inf->endOfSearch = true;
3600 psrch_inf->endOfSearch = false;
3602 psrch_inf->entries_in_buffer =
3603 le16_to_cpu(parms->SearchCount);
3604 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3605 psrch_inf->entries_in_buffer;
3606 lnoff = le16_to_cpu(parms->LastNameOffset);
3607 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3609 cERROR(1, ("ignoring corrupt resume name"));
3610 psrch_inf->last_entry = NULL;
3614 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3617 *pnetfid = parms->SearchHandle;
3619 cifs_buf_release(pSMB);
3626 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3627 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3629 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3630 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3631 T2_FNEXT_RSP_PARMS *parms;
3632 char *response_data;
3634 int bytes_returned, name_len;
3635 __u16 params, byte_count;
3637 cFYI(1, ("In FindNext"));
3639 if (psrch_inf->endOfSearch)
3642 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3647 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3649 pSMB->TotalDataCount = 0; /* no EAs */
3650 pSMB->MaxParameterCount = cpu_to_le16(8);
3651 pSMB->MaxDataCount =
3652 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3654 pSMB->MaxSetupCount = 0;
3658 pSMB->Reserved2 = 0;
3659 pSMB->ParameterOffset = cpu_to_le16(
3660 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3661 pSMB->DataCount = 0;
3662 pSMB->DataOffset = 0;
3663 pSMB->SetupCount = 1;
3664 pSMB->Reserved3 = 0;
3665 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3666 pSMB->SearchHandle = searchHandle; /* always kept as le */
3668 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3669 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3670 pSMB->ResumeKey = psrch_inf->resume_key;
3672 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3674 name_len = psrch_inf->resume_name_len;
3676 if (name_len < PATH_MAX) {
3677 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3678 byte_count += name_len;
3679 /* 14 byte parm len above enough for 2 byte null terminator */
3680 pSMB->ResumeFileName[name_len] = 0;
3681 pSMB->ResumeFileName[name_len+1] = 0;
3684 goto FNext2_err_exit;
3686 byte_count = params + 1 /* pad */ ;
3687 pSMB->TotalParameterCount = cpu_to_le16(params);
3688 pSMB->ParameterCount = pSMB->TotalParameterCount;
3689 pSMB->hdr.smb_buf_length += byte_count;
3690 pSMB->ByteCount = cpu_to_le16(byte_count);
3692 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3693 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3694 cifs_stats_inc(&tcon->num_fnext);
3697 psrch_inf->endOfSearch = true;
3698 cifs_buf_release(pSMB);
3699 rc = 0; /* search probably was closed at end of search*/
3701 cFYI(1, ("FindNext returned = %d", rc));
3702 } else { /* decode response */
3703 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3708 /* BB fixme add lock for file (srch_info) struct here */
3709 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3710 psrch_inf->unicode = true;
3712 psrch_inf->unicode = false;
3713 response_data = (char *) &pSMBr->hdr.Protocol +
3714 le16_to_cpu(pSMBr->t2.ParameterOffset);
3715 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3716 response_data = (char *)&pSMBr->hdr.Protocol +
3717 le16_to_cpu(pSMBr->t2.DataOffset);
3718 if (psrch_inf->smallBuf)
3719 cifs_small_buf_release(
3720 psrch_inf->ntwrk_buf_start);
3722 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3723 psrch_inf->srch_entries_start = response_data;
3724 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3725 psrch_inf->smallBuf = 0;
3726 if (parms->EndofSearch)
3727 psrch_inf->endOfSearch = true;
3729 psrch_inf->endOfSearch = false;
3730 psrch_inf->entries_in_buffer =
3731 le16_to_cpu(parms->SearchCount);
3732 psrch_inf->index_of_last_entry +=
3733 psrch_inf->entries_in_buffer;
3734 lnoff = le16_to_cpu(parms->LastNameOffset);
3735 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3737 cERROR(1, ("ignoring corrupt resume name"));
3738 psrch_inf->last_entry = NULL;
3741 psrch_inf->last_entry =
3742 psrch_inf->srch_entries_start + lnoff;
3744 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3745 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3747 /* BB fixme add unlock here */
3752 /* BB On error, should we leave previous search buf (and count and
3753 last entry fields) intact or free the previous one? */
3755 /* Note: On -EAGAIN error only caller can retry on handle based calls
3756 since file handle passed in no longer valid */
3759 cifs_buf_release(pSMB);
3764 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3765 const __u16 searchHandle)
3768 FINDCLOSE_REQ *pSMB = NULL;
3770 cFYI(1, ("In CIFSSMBFindClose"));
3771 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3773 /* no sense returning error if session restarted
3774 as file handle has been closed */
3780 pSMB->FileID = searchHandle;
3781 pSMB->ByteCount = 0;
3782 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3784 cERROR(1, ("Send error in FindClose = %d", rc));
3786 cifs_stats_inc(&tcon->num_fclose);
3788 /* Since session is dead, search handle closed on server already */
3796 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3797 const unsigned char *searchName,
3798 __u64 *inode_number,
3799 const struct nls_table *nls_codepage, int remap)
3802 TRANSACTION2_QPI_REQ *pSMB = NULL;
3803 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3804 int name_len, bytes_returned;
3805 __u16 params, byte_count;
3807 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3811 GetInodeNumberRetry:
3812 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3817 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3819 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3820 PATH_MAX, nls_codepage, remap);
3821 name_len++; /* trailing null */
3823 } else { /* BB improve the check for buffer overruns BB */
3824 name_len = strnlen(searchName, PATH_MAX);
3825 name_len++; /* trailing null */
3826 strncpy(pSMB->FileName, searchName, name_len);
3829 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3830 pSMB->TotalDataCount = 0;
3831 pSMB->MaxParameterCount = cpu_to_le16(2);
3832 /* BB find exact max data count below from sess structure BB */
3833 pSMB->MaxDataCount = cpu_to_le16(4000);
3834 pSMB->MaxSetupCount = 0;
3838 pSMB->Reserved2 = 0;
3839 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3840 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3841 pSMB->DataCount = 0;
3842 pSMB->DataOffset = 0;
3843 pSMB->SetupCount = 1;
3844 pSMB->Reserved3 = 0;
3845 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3846 byte_count = params + 1 /* pad */ ;
3847 pSMB->TotalParameterCount = cpu_to_le16(params);
3848 pSMB->ParameterCount = pSMB->TotalParameterCount;
3849 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3850 pSMB->Reserved4 = 0;
3851 pSMB->hdr.smb_buf_length += byte_count;
3852 pSMB->ByteCount = cpu_to_le16(byte_count);
3854 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3855 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3857 cFYI(1, ("error %d in QueryInternalInfo", rc));
3859 /* decode response */
3860 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3861 if (rc || (pSMBr->ByteCount < 2))
3862 /* BB also check enough total bytes returned */
3863 /* If rc should we check for EOPNOSUPP and
3864 disable the srvino flag? or in caller? */
3865 rc = -EIO; /* bad smb */
3867 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3868 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3869 struct file_internal_info *pfinfo;
3870 /* BB Do we need a cast or hash here ? */
3872 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3874 goto GetInodeNumOut;
3876 pfinfo = (struct file_internal_info *)
3877 (data_offset + (char *) &pSMBr->hdr.Protocol);
3878 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3882 cifs_buf_release(pSMB);
3884 goto GetInodeNumberRetry;
3888 /* parses DFS refferal V3 structure
3889 * caller is responsible for freeing target_nodes
3892 * on failure - errno
3895 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3896 unsigned int *num_of_nodes,
3897 struct dfs_info3_param **target_nodes,
3898 const struct nls_table *nls_codepage, int remap,
3899 const char *searchName)
3904 struct dfs_referral_level_3 *ref;
3906 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3910 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3912 if (*num_of_nodes < 1) {
3913 cERROR(1, ("num_referrals: must be at least > 0,"
3914 "but we get num_referrals = %d\n", *num_of_nodes));
3916 goto parse_DFS_referrals_exit;
3919 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3920 if (ref->VersionNumber != cpu_to_le16(3)) {
3921 cERROR(1, ("Referrals of V%d version are not supported,"
3922 "should be V3", le16_to_cpu(ref->VersionNumber)));
3924 goto parse_DFS_referrals_exit;
3927 /* get the upper boundary of the resp buffer */
3928 data_end = (char *)(&(pSMBr->PathConsumed)) +
3929 le16_to_cpu(pSMBr->t2.DataCount);
3931 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3933 le32_to_cpu(pSMBr->DFSFlags)));
3935 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3936 *num_of_nodes, GFP_KERNEL);
3937 if (*target_nodes == NULL) {
3938 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3940 goto parse_DFS_referrals_exit;
3943 /* collect neccessary data from referrals */
3944 for (i = 0; i < *num_of_nodes; i++) {
3947 struct dfs_info3_param *node = (*target_nodes)+i;
3949 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3951 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3953 cifsConvertToUCS((__le16 *) tmp, searchName,
3954 PATH_MAX, nls_codepage, remap);
3955 node->path_consumed = cifs_ucs2_bytes(tmp,
3956 le16_to_cpu(pSMBr->PathConsumed),
3960 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3962 node->server_type = le16_to_cpu(ref->ServerType);
3963 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3966 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3967 max_len = data_end - temp;
3968 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3969 is_unicode, nls_codepage);
3970 if (IS_ERR(node->path_name)) {
3971 rc = PTR_ERR(node->path_name);
3972 node->path_name = NULL;
3973 goto parse_DFS_referrals_exit;
3976 /* copy link target UNC */
3977 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3978 max_len = data_end - temp;
3979 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3980 is_unicode, nls_codepage);
3981 if (IS_ERR(node->node_name)) {
3982 rc = PTR_ERR(node->node_name);
3983 node->node_name = NULL;
3984 goto parse_DFS_referrals_exit;
3988 parse_DFS_referrals_exit:
3990 free_dfs_info_array(*target_nodes, *num_of_nodes);
3991 *target_nodes = NULL;
3998 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3999 const unsigned char *searchName,
4000 struct dfs_info3_param **target_nodes,
4001 unsigned int *num_of_nodes,
4002 const struct nls_table *nls_codepage, int remap)
4004 /* TRANS2_GET_DFS_REFERRAL */
4005 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4006 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4010 __u16 params, byte_count;
4012 *target_nodes = NULL;
4014 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4018 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4023 /* server pointer checked in called function,
4024 but should never be null here anyway */
4025 pSMB->hdr.Mid = GetNextMid(ses->server);
4026 pSMB->hdr.Tid = ses->ipc_tid;
4027 pSMB->hdr.Uid = ses->Suid;
4028 if (ses->capabilities & CAP_STATUS32)
4029 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4030 if (ses->capabilities & CAP_DFS)
4031 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4033 if (ses->capabilities & CAP_UNICODE) {
4034 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4036 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4037 searchName, PATH_MAX, nls_codepage, remap);
4038 name_len++; /* trailing null */
4040 } else { /* BB improve the check for buffer overruns BB */
4041 name_len = strnlen(searchName, PATH_MAX);
4042 name_len++; /* trailing null */
4043 strncpy(pSMB->RequestFileName, searchName, name_len);
4047 if (ses->server->secMode &
4048 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4049 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4052 pSMB->hdr.Uid = ses->Suid;
4054 params = 2 /* level */ + name_len /*includes null */ ;
4055 pSMB->TotalDataCount = 0;
4056 pSMB->DataCount = 0;
4057 pSMB->DataOffset = 0;
4058 pSMB->MaxParameterCount = 0;
4059 /* BB find exact max SMB PDU from sess structure BB */
4060 pSMB->MaxDataCount = cpu_to_le16(4000);
4061 pSMB->MaxSetupCount = 0;
4065 pSMB->Reserved2 = 0;
4066 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4067 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4068 pSMB->SetupCount = 1;
4069 pSMB->Reserved3 = 0;
4070 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4071 byte_count = params + 3 /* pad */ ;
4072 pSMB->ParameterCount = cpu_to_le16(params);
4073 pSMB->TotalParameterCount = pSMB->ParameterCount;
4074 pSMB->MaxReferralLevel = cpu_to_le16(3);
4075 pSMB->hdr.smb_buf_length += byte_count;
4076 pSMB->ByteCount = cpu_to_le16(byte_count);
4078 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4079 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4081 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4084 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4086 /* BB Also check if enough total bytes returned? */
4087 if (rc || (pSMBr->ByteCount < 17)) {
4088 rc = -EIO; /* bad smb */
4092 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4094 le16_to_cpu(pSMBr->t2.DataOffset)));
4096 /* parse returned result into more usable form */
4097 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4098 target_nodes, nls_codepage, remap,
4102 cifs_buf_release(pSMB);
4110 /* Query File System Info such as free space to old servers such as Win 9x */
4112 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4114 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4115 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4116 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4117 FILE_SYSTEM_ALLOC_INFO *response_data;
4119 int bytes_returned = 0;
4120 __u16 params, byte_count;
4122 cFYI(1, ("OldQFSInfo"));
4124 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4129 params = 2; /* level */
4130 pSMB->TotalDataCount = 0;
4131 pSMB->MaxParameterCount = cpu_to_le16(2);
4132 pSMB->MaxDataCount = cpu_to_le16(1000);
4133 pSMB->MaxSetupCount = 0;
4137 pSMB->Reserved2 = 0;
4138 byte_count = params + 1 /* pad */ ;
4139 pSMB->TotalParameterCount = cpu_to_le16(params);
4140 pSMB->ParameterCount = pSMB->TotalParameterCount;
4141 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4142 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4143 pSMB->DataCount = 0;
4144 pSMB->DataOffset = 0;
4145 pSMB->SetupCount = 1;
4146 pSMB->Reserved3 = 0;
4147 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4148 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4149 pSMB->hdr.smb_buf_length += byte_count;
4150 pSMB->ByteCount = cpu_to_le16(byte_count);
4152 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4153 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4155 cFYI(1, ("Send error in QFSInfo = %d", rc));
4156 } else { /* decode response */
4157 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4159 if (rc || (pSMBr->ByteCount < 18))
4160 rc = -EIO; /* bad smb */
4162 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4163 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4164 pSMBr->ByteCount, data_offset));
4166 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4167 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4169 le16_to_cpu(response_data->BytesPerSector) *
4170 le32_to_cpu(response_data->
4171 SectorsPerAllocationUnit);
4173 le32_to_cpu(response_data->TotalAllocationUnits);
4174 FSData->f_bfree = FSData->f_bavail =
4175 le32_to_cpu(response_data->FreeAllocationUnits);
4177 ("Blocks: %lld Free: %lld Block size %ld",
4178 (unsigned long long)FSData->f_blocks,
4179 (unsigned long long)FSData->f_bfree,
4183 cifs_buf_release(pSMB);
4186 goto oldQFSInfoRetry;
4192 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4194 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4195 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4196 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4197 FILE_SYSTEM_INFO *response_data;
4199 int bytes_returned = 0;
4200 __u16 params, byte_count;
4202 cFYI(1, ("In QFSInfo"));
4204 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4209 params = 2; /* level */
4210 pSMB->TotalDataCount = 0;
4211 pSMB->MaxParameterCount = cpu_to_le16(2);
4212 pSMB->MaxDataCount = cpu_to_le16(1000);
4213 pSMB->MaxSetupCount = 0;
4217 pSMB->Reserved2 = 0;
4218 byte_count = params + 1 /* pad */ ;
4219 pSMB->TotalParameterCount = cpu_to_le16(params);
4220 pSMB->ParameterCount = pSMB->TotalParameterCount;
4221 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4222 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4223 pSMB->DataCount = 0;
4224 pSMB->DataOffset = 0;
4225 pSMB->SetupCount = 1;
4226 pSMB->Reserved3 = 0;
4227 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4228 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4229 pSMB->hdr.smb_buf_length += byte_count;
4230 pSMB->ByteCount = cpu_to_le16(byte_count);
4232 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4233 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4235 cFYI(1, ("Send error in QFSInfo = %d", rc));
4236 } else { /* decode response */
4237 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4239 if (rc || (pSMBr->ByteCount < 24))
4240 rc = -EIO; /* bad smb */
4242 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4246 *) (((char *) &pSMBr->hdr.Protocol) +
4249 le32_to_cpu(response_data->BytesPerSector) *
4250 le32_to_cpu(response_data->
4251 SectorsPerAllocationUnit);
4253 le64_to_cpu(response_data->TotalAllocationUnits);
4254 FSData->f_bfree = FSData->f_bavail =
4255 le64_to_cpu(response_data->FreeAllocationUnits);
4257 ("Blocks: %lld Free: %lld Block size %ld",
4258 (unsigned long long)FSData->f_blocks,
4259 (unsigned long long)FSData->f_bfree,
4263 cifs_buf_release(pSMB);
4272 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4274 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4275 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4276 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4277 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4279 int bytes_returned = 0;
4280 __u16 params, byte_count;
4282 cFYI(1, ("In QFSAttributeInfo"));
4284 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4289 params = 2; /* level */
4290 pSMB->TotalDataCount = 0;
4291 pSMB->MaxParameterCount = cpu_to_le16(2);
4292 /* BB find exact max SMB PDU from sess structure BB */
4293 pSMB->MaxDataCount = cpu_to_le16(1000);
4294 pSMB->MaxSetupCount = 0;
4298 pSMB->Reserved2 = 0;
4299 byte_count = params + 1 /* pad */ ;
4300 pSMB->TotalParameterCount = cpu_to_le16(params);
4301 pSMB->ParameterCount = pSMB->TotalParameterCount;
4302 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4303 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4304 pSMB->DataCount = 0;
4305 pSMB->DataOffset = 0;
4306 pSMB->SetupCount = 1;
4307 pSMB->Reserved3 = 0;
4308 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4309 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4310 pSMB->hdr.smb_buf_length += byte_count;
4311 pSMB->ByteCount = cpu_to_le16(byte_count);
4313 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4314 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4316 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4317 } else { /* decode response */
4318 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4320 if (rc || (pSMBr->ByteCount < 13)) {
4321 /* BB also check if enough bytes returned */
4322 rc = -EIO; /* bad smb */
4324 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4326 (FILE_SYSTEM_ATTRIBUTE_INFO
4327 *) (((char *) &pSMBr->hdr.Protocol) +
4329 memcpy(&tcon->fsAttrInfo, response_data,
4330 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4333 cifs_buf_release(pSMB);
4336 goto QFSAttributeRetry;
4342 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4344 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4345 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4346 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4347 FILE_SYSTEM_DEVICE_INFO *response_data;
4349 int bytes_returned = 0;
4350 __u16 params, byte_count;
4352 cFYI(1, ("In QFSDeviceInfo"));
4354 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4359 params = 2; /* level */
4360 pSMB->TotalDataCount = 0;
4361 pSMB->MaxParameterCount = cpu_to_le16(2);
4362 /* BB find exact max SMB PDU from sess structure BB */
4363 pSMB->MaxDataCount = cpu_to_le16(1000);
4364 pSMB->MaxSetupCount = 0;
4368 pSMB->Reserved2 = 0;
4369 byte_count = params + 1 /* pad */ ;
4370 pSMB->TotalParameterCount = cpu_to_le16(params);
4371 pSMB->ParameterCount = pSMB->TotalParameterCount;
4372 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4373 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4375 pSMB->DataCount = 0;
4376 pSMB->DataOffset = 0;
4377 pSMB->SetupCount = 1;
4378 pSMB->Reserved3 = 0;
4379 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4380 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4381 pSMB->hdr.smb_buf_length += byte_count;
4382 pSMB->ByteCount = cpu_to_le16(byte_count);
4384 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4385 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4387 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4388 } else { /* decode response */
4389 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4391 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4392 rc = -EIO; /* bad smb */
4394 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4396 (FILE_SYSTEM_DEVICE_INFO *)
4397 (((char *) &pSMBr->hdr.Protocol) +
4399 memcpy(&tcon->fsDevInfo, response_data,
4400 sizeof(FILE_SYSTEM_DEVICE_INFO));
4403 cifs_buf_release(pSMB);
4406 goto QFSDeviceRetry;
4412 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4414 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4415 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4416 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4417 FILE_SYSTEM_UNIX_INFO *response_data;
4419 int bytes_returned = 0;
4420 __u16 params, byte_count;
4422 cFYI(1, ("In QFSUnixInfo"));
4424 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4429 params = 2; /* level */
4430 pSMB->TotalDataCount = 0;
4431 pSMB->DataCount = 0;
4432 pSMB->DataOffset = 0;
4433 pSMB->MaxParameterCount = cpu_to_le16(2);
4434 /* BB find exact max SMB PDU from sess structure BB */
4435 pSMB->MaxDataCount = cpu_to_le16(100);
4436 pSMB->MaxSetupCount = 0;
4440 pSMB->Reserved2 = 0;
4441 byte_count = params + 1 /* pad */ ;
4442 pSMB->ParameterCount = cpu_to_le16(params);
4443 pSMB->TotalParameterCount = pSMB->ParameterCount;
4444 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4445 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4446 pSMB->SetupCount = 1;
4447 pSMB->Reserved3 = 0;
4448 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4449 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4450 pSMB->hdr.smb_buf_length += byte_count;
4451 pSMB->ByteCount = cpu_to_le16(byte_count);
4453 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4454 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4456 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4457 } else { /* decode response */
4458 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4460 if (rc || (pSMBr->ByteCount < 13)) {
4461 rc = -EIO; /* bad smb */
4463 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4465 (FILE_SYSTEM_UNIX_INFO
4466 *) (((char *) &pSMBr->hdr.Protocol) +
4468 memcpy(&tcon->fsUnixInfo, response_data,
4469 sizeof(FILE_SYSTEM_UNIX_INFO));
4472 cifs_buf_release(pSMB);
4482 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4484 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4485 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4486 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4488 int bytes_returned = 0;
4489 __u16 params, param_offset, offset, byte_count;
4491 cFYI(1, ("In SETFSUnixInfo"));
4493 /* BB switch to small buf init to save memory */
4494 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4499 params = 4; /* 2 bytes zero followed by info level. */
4500 pSMB->MaxSetupCount = 0;
4504 pSMB->Reserved2 = 0;
4505 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4507 offset = param_offset + params;
4509 pSMB->MaxParameterCount = cpu_to_le16(4);
4510 /* BB find exact max SMB PDU from sess structure BB */
4511 pSMB->MaxDataCount = cpu_to_le16(100);
4512 pSMB->SetupCount = 1;
4513 pSMB->Reserved3 = 0;
4514 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4515 byte_count = 1 /* pad */ + params + 12;
4517 pSMB->DataCount = cpu_to_le16(12);
4518 pSMB->ParameterCount = cpu_to_le16(params);
4519 pSMB->TotalDataCount = pSMB->DataCount;
4520 pSMB->TotalParameterCount = pSMB->ParameterCount;
4521 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4522 pSMB->DataOffset = cpu_to_le16(offset);
4526 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4529 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4530 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4531 pSMB->ClientUnixCap = cpu_to_le64(cap);
4533 pSMB->hdr.smb_buf_length += byte_count;
4534 pSMB->ByteCount = cpu_to_le16(byte_count);
4536 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4537 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4539 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4540 } else { /* decode response */
4541 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4543 rc = -EIO; /* bad smb */
4545 cifs_buf_release(pSMB);
4548 goto SETFSUnixRetry;
4556 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4557 struct kstatfs *FSData)
4559 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4560 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4561 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4562 FILE_SYSTEM_POSIX_INFO *response_data;
4564 int bytes_returned = 0;
4565 __u16 params, byte_count;
4567 cFYI(1, ("In QFSPosixInfo"));
4569 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4574 params = 2; /* level */
4575 pSMB->TotalDataCount = 0;
4576 pSMB->DataCount = 0;
4577 pSMB->DataOffset = 0;
4578 pSMB->MaxParameterCount = cpu_to_le16(2);
4579 /* BB find exact max SMB PDU from sess structure BB */
4580 pSMB->MaxDataCount = cpu_to_le16(100);
4581 pSMB->MaxSetupCount = 0;
4585 pSMB->Reserved2 = 0;
4586 byte_count = params + 1 /* pad */ ;
4587 pSMB->ParameterCount = cpu_to_le16(params);
4588 pSMB->TotalParameterCount = pSMB->ParameterCount;
4589 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4590 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4591 pSMB->SetupCount = 1;
4592 pSMB->Reserved3 = 0;
4593 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4594 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4595 pSMB->hdr.smb_buf_length += byte_count;
4596 pSMB->ByteCount = cpu_to_le16(byte_count);
4598 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4599 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4601 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4602 } else { /* decode response */
4603 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4605 if (rc || (pSMBr->ByteCount < 13)) {
4606 rc = -EIO; /* bad smb */
4608 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4610 (FILE_SYSTEM_POSIX_INFO
4611 *) (((char *) &pSMBr->hdr.Protocol) +
4614 le32_to_cpu(response_data->BlockSize);
4616 le64_to_cpu(response_data->TotalBlocks);
4618 le64_to_cpu(response_data->BlocksAvail);
4619 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4620 FSData->f_bavail = FSData->f_bfree;
4623 le64_to_cpu(response_data->UserBlocksAvail);
4625 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4627 le64_to_cpu(response_data->TotalFileNodes);
4628 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4630 le64_to_cpu(response_data->FreeFileNodes);
4633 cifs_buf_release(pSMB);
4642 /* We can not use write of zero bytes trick to
4643 set file size due to need for large file support. Also note that
4644 this SetPathInfo is preferred to SetFileInfo based method in next
4645 routine which is only needed to work around a sharing violation bug
4646 in Samba which this routine can run into */
4649 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4650 __u64 size, bool SetAllocation,
4651 const struct nls_table *nls_codepage, int remap)
4653 struct smb_com_transaction2_spi_req *pSMB = NULL;
4654 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4655 struct file_end_of_file_info *parm_data;
4658 int bytes_returned = 0;
4659 __u16 params, byte_count, data_count, param_offset, offset;
4661 cFYI(1, ("In SetEOF"));
4663 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4668 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4670 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4671 PATH_MAX, nls_codepage, remap);
4672 name_len++; /* trailing null */
4674 } else { /* BB improve the check for buffer overruns BB */
4675 name_len = strnlen(fileName, PATH_MAX);
4676 name_len++; /* trailing null */
4677 strncpy(pSMB->FileName, fileName, name_len);
4679 params = 6 + name_len;
4680 data_count = sizeof(struct file_end_of_file_info);
4681 pSMB->MaxParameterCount = cpu_to_le16(2);
4682 pSMB->MaxDataCount = cpu_to_le16(4100);
4683 pSMB->MaxSetupCount = 0;
4687 pSMB->Reserved2 = 0;
4688 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4689 InformationLevel) - 4;
4690 offset = param_offset + params;
4691 if (SetAllocation) {
4692 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4693 pSMB->InformationLevel =
4694 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4696 pSMB->InformationLevel =
4697 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4698 } else /* Set File Size */ {
4699 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4700 pSMB->InformationLevel =
4701 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4703 pSMB->InformationLevel =
4704 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4708 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4710 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4711 pSMB->DataOffset = cpu_to_le16(offset);
4712 pSMB->SetupCount = 1;
4713 pSMB->Reserved3 = 0;
4714 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4715 byte_count = 3 /* pad */ + params + data_count;
4716 pSMB->DataCount = cpu_to_le16(data_count);
4717 pSMB->TotalDataCount = pSMB->DataCount;
4718 pSMB->ParameterCount = cpu_to_le16(params);
4719 pSMB->TotalParameterCount = pSMB->ParameterCount;
4720 pSMB->Reserved4 = 0;
4721 pSMB->hdr.smb_buf_length += byte_count;
4722 parm_data->FileSize = cpu_to_le64(size);
4723 pSMB->ByteCount = cpu_to_le16(byte_count);
4724 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4725 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4727 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4729 cifs_buf_release(pSMB);
4738 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4739 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4741 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4743 struct file_end_of_file_info *parm_data;
4745 __u16 params, param_offset, offset, byte_count, count;
4747 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4749 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4754 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4755 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4758 pSMB->MaxSetupCount = 0;
4762 pSMB->Reserved2 = 0;
4763 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4764 offset = param_offset + params;
4766 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4768 count = sizeof(struct file_end_of_file_info);
4769 pSMB->MaxParameterCount = cpu_to_le16(2);
4770 /* BB find exact max SMB PDU from sess structure BB */
4771 pSMB->MaxDataCount = cpu_to_le16(1000);
4772 pSMB->SetupCount = 1;
4773 pSMB->Reserved3 = 0;
4774 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4775 byte_count = 3 /* pad */ + params + count;
4776 pSMB->DataCount = cpu_to_le16(count);
4777 pSMB->ParameterCount = cpu_to_le16(params);
4778 pSMB->TotalDataCount = pSMB->DataCount;
4779 pSMB->TotalParameterCount = pSMB->ParameterCount;
4780 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4782 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4784 pSMB->DataOffset = cpu_to_le16(offset);
4785 parm_data->FileSize = cpu_to_le64(size);
4787 if (SetAllocation) {
4788 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4789 pSMB->InformationLevel =
4790 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4792 pSMB->InformationLevel =
4793 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4794 } else /* Set File Size */ {
4795 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4796 pSMB->InformationLevel =
4797 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4799 pSMB->InformationLevel =
4800 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4802 pSMB->Reserved4 = 0;
4803 pSMB->hdr.smb_buf_length += byte_count;
4804 pSMB->ByteCount = cpu_to_le16(byte_count);
4805 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4808 ("Send error in SetFileInfo (SetFileSize) = %d",
4812 /* Note: On -EAGAIN error only caller can retry on handle based calls
4813 since file handle passed in no longer valid */
4818 /* Some legacy servers such as NT4 require that the file times be set on
4819 an open handle, rather than by pathname - this is awkward due to
4820 potential access conflicts on the open, but it is unavoidable for these
4821 old servers since the only other choice is to go from 100 nanosecond DCE
4822 time and resort to the original setpathinfo level which takes the ancient
4823 DOS time format with 2 second granularity */
4825 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4826 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4828 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4831 __u16 params, param_offset, offset, byte_count, count;
4833 cFYI(1, ("Set Times (via SetFileInfo)"));
4834 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4839 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4840 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4843 pSMB->MaxSetupCount = 0;
4847 pSMB->Reserved2 = 0;
4848 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4849 offset = param_offset + params;
4851 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4853 count = sizeof(FILE_BASIC_INFO);
4854 pSMB->MaxParameterCount = cpu_to_le16(2);
4855 /* BB find max SMB PDU from sess */
4856 pSMB->MaxDataCount = cpu_to_le16(1000);
4857 pSMB->SetupCount = 1;
4858 pSMB->Reserved3 = 0;
4859 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4860 byte_count = 3 /* pad */ + params + count;
4861 pSMB->DataCount = cpu_to_le16(count);
4862 pSMB->ParameterCount = cpu_to_le16(params);
4863 pSMB->TotalDataCount = pSMB->DataCount;
4864 pSMB->TotalParameterCount = pSMB->ParameterCount;
4865 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4866 pSMB->DataOffset = cpu_to_le16(offset);
4868 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4869 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4871 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4872 pSMB->Reserved4 = 0;
4873 pSMB->hdr.smb_buf_length += byte_count;
4874 pSMB->ByteCount = cpu_to_le16(byte_count);
4875 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4876 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4878 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4880 /* Note: On -EAGAIN error only caller can retry on handle based calls
4881 since file handle passed in no longer valid */
4887 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4888 bool delete_file, __u16 fid, __u32 pid_of_opener)
4890 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4893 __u16 params, param_offset, offset, byte_count, count;
4895 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4896 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4901 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4902 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4905 pSMB->MaxSetupCount = 0;
4909 pSMB->Reserved2 = 0;
4910 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4911 offset = param_offset + params;
4913 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4916 pSMB->MaxParameterCount = cpu_to_le16(2);
4917 /* BB find max SMB PDU from sess */
4918 pSMB->MaxDataCount = cpu_to_le16(1000);
4919 pSMB->SetupCount = 1;
4920 pSMB->Reserved3 = 0;
4921 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4922 byte_count = 3 /* pad */ + params + count;
4923 pSMB->DataCount = cpu_to_le16(count);
4924 pSMB->ParameterCount = cpu_to_le16(params);
4925 pSMB->TotalDataCount = pSMB->DataCount;
4926 pSMB->TotalParameterCount = pSMB->ParameterCount;
4927 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4928 pSMB->DataOffset = cpu_to_le16(offset);
4930 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4931 pSMB->Reserved4 = 0;
4932 pSMB->hdr.smb_buf_length += byte_count;
4933 pSMB->ByteCount = cpu_to_le16(byte_count);
4934 *data_offset = delete_file ? 1 : 0;
4935 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4937 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4943 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4944 const char *fileName, const FILE_BASIC_INFO *data,
4945 const struct nls_table *nls_codepage, int remap)
4947 TRANSACTION2_SPI_REQ *pSMB = NULL;
4948 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4951 int bytes_returned = 0;
4953 __u16 params, param_offset, offset, byte_count, count;
4955 cFYI(1, ("In SetTimes"));
4958 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4963 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4965 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4966 PATH_MAX, nls_codepage, remap);
4967 name_len++; /* trailing null */
4969 } else { /* BB improve the check for buffer overruns BB */
4970 name_len = strnlen(fileName, PATH_MAX);
4971 name_len++; /* trailing null */
4972 strncpy(pSMB->FileName, fileName, name_len);
4975 params = 6 + name_len;
4976 count = sizeof(FILE_BASIC_INFO);
4977 pSMB->MaxParameterCount = cpu_to_le16(2);
4978 /* BB find max SMB PDU from sess structure BB */
4979 pSMB->MaxDataCount = cpu_to_le16(1000);
4980 pSMB->MaxSetupCount = 0;
4984 pSMB->Reserved2 = 0;
4985 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4986 InformationLevel) - 4;
4987 offset = param_offset + params;
4988 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4989 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4990 pSMB->DataOffset = cpu_to_le16(offset);
4991 pSMB->SetupCount = 1;
4992 pSMB->Reserved3 = 0;
4993 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4994 byte_count = 3 /* pad */ + params + count;
4996 pSMB->DataCount = cpu_to_le16(count);
4997 pSMB->ParameterCount = cpu_to_le16(params);
4998 pSMB->TotalDataCount = pSMB->DataCount;
4999 pSMB->TotalParameterCount = pSMB->ParameterCount;
5000 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5001 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5003 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5004 pSMB->Reserved4 = 0;
5005 pSMB->hdr.smb_buf_length += byte_count;
5006 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5007 pSMB->ByteCount = cpu_to_le16(byte_count);
5008 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5009 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5011 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5013 cifs_buf_release(pSMB);
5021 /* Can not be used to set time stamps yet (due to old DOS time format) */
5022 /* Can be used to set attributes */
5023 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5024 handling it anyway and NT4 was what we thought it would be needed for
5025 Do not delete it until we prove whether needed for Win9x though */
5027 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5028 __u16 dos_attrs, const struct nls_table *nls_codepage)
5030 SETATTR_REQ *pSMB = NULL;
5031 SETATTR_RSP *pSMBr = NULL;
5036 cFYI(1, ("In SetAttrLegacy"));
5039 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5044 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5046 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5047 PATH_MAX, nls_codepage);
5048 name_len++; /* trailing null */
5050 } else { /* BB improve the check for buffer overruns BB */
5051 name_len = strnlen(fileName, PATH_MAX);
5052 name_len++; /* trailing null */
5053 strncpy(pSMB->fileName, fileName, name_len);
5055 pSMB->attr = cpu_to_le16(dos_attrs);
5056 pSMB->BufferFormat = 0x04;
5057 pSMB->hdr.smb_buf_length += name_len + 1;
5058 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5059 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5060 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5062 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5064 cifs_buf_release(pSMB);
5067 goto SetAttrLgcyRetry;
5071 #endif /* temporarily unneeded SetAttr legacy function */
5074 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5075 const struct cifs_unix_set_info_args *args,
5076 const struct nls_table *nls_codepage, int remap)
5078 TRANSACTION2_SPI_REQ *pSMB = NULL;
5079 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5082 int bytes_returned = 0;
5083 FILE_UNIX_BASIC_INFO *data_offset;
5084 __u16 params, param_offset, offset, count, byte_count;
5085 __u64 mode = args->mode;
5087 cFYI(1, ("In SetUID/GID/Mode"));
5089 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5094 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5096 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5097 PATH_MAX, nls_codepage, remap);
5098 name_len++; /* trailing null */
5100 } else { /* BB improve the check for buffer overruns BB */
5101 name_len = strnlen(fileName, PATH_MAX);
5102 name_len++; /* trailing null */
5103 strncpy(pSMB->FileName, fileName, name_len);
5106 params = 6 + name_len;
5107 count = sizeof(FILE_UNIX_BASIC_INFO);
5108 pSMB->MaxParameterCount = cpu_to_le16(2);
5109 /* BB find max SMB PDU from sess structure BB */
5110 pSMB->MaxDataCount = cpu_to_le16(1000);
5111 pSMB->MaxSetupCount = 0;
5115 pSMB->Reserved2 = 0;
5116 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5117 InformationLevel) - 4;
5118 offset = param_offset + params;
5120 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5122 memset(data_offset, 0, count);
5123 pSMB->DataOffset = cpu_to_le16(offset);
5124 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5125 pSMB->SetupCount = 1;
5126 pSMB->Reserved3 = 0;
5127 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5128 byte_count = 3 /* pad */ + params + count;
5129 pSMB->ParameterCount = cpu_to_le16(params);
5130 pSMB->DataCount = cpu_to_le16(count);
5131 pSMB->TotalParameterCount = pSMB->ParameterCount;
5132 pSMB->TotalDataCount = pSMB->DataCount;
5133 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5134 pSMB->Reserved4 = 0;
5135 pSMB->hdr.smb_buf_length += byte_count;
5136 /* Samba server ignores set of file size to zero due to bugs in some
5137 older clients, but we should be precise - we use SetFileSize to
5138 set file size and do not want to truncate file size to zero
5139 accidently as happened on one Samba server beta by putting
5140 zero instead of -1 here */
5141 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5142 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5143 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5144 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5145 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5146 data_offset->Uid = cpu_to_le64(args->uid);
5147 data_offset->Gid = cpu_to_le64(args->gid);
5148 /* better to leave device as zero when it is */
5149 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5150 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5151 data_offset->Permissions = cpu_to_le64(mode);
5154 data_offset->Type = cpu_to_le32(UNIX_FILE);
5155 else if (S_ISDIR(mode))
5156 data_offset->Type = cpu_to_le32(UNIX_DIR);
5157 else if (S_ISLNK(mode))
5158 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5159 else if (S_ISCHR(mode))
5160 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5161 else if (S_ISBLK(mode))
5162 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5163 else if (S_ISFIFO(mode))
5164 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5165 else if (S_ISSOCK(mode))
5166 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5169 pSMB->ByteCount = cpu_to_le16(byte_count);
5170 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5171 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5173 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5175 cifs_buf_release(pSMB);
5181 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5182 const int notify_subdirs, const __u16 netfid,
5183 __u32 filter, struct file *pfile, int multishot,
5184 const struct nls_table *nls_codepage)
5187 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5188 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5189 struct dir_notify_req *dnotify_req;
5192 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5193 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5198 pSMB->TotalParameterCount = 0 ;
5199 pSMB->TotalDataCount = 0;
5200 pSMB->MaxParameterCount = cpu_to_le32(2);
5201 /* BB find exact data count max from sess structure BB */
5202 pSMB->MaxDataCount = 0; /* same in little endian or be */
5203 /* BB VERIFY verify which is correct for above BB */
5204 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5205 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5207 pSMB->MaxSetupCount = 4;
5209 pSMB->ParameterOffset = 0;
5210 pSMB->DataCount = 0;
5211 pSMB->DataOffset = 0;
5212 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5213 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5214 pSMB->ParameterCount = pSMB->TotalParameterCount;
5216 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5217 pSMB->Reserved2 = 0;
5218 pSMB->CompletionFilter = cpu_to_le32(filter);
5219 pSMB->Fid = netfid; /* file handle always le */
5220 pSMB->ByteCount = 0;
5222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5223 (struct smb_hdr *)pSMBr, &bytes_returned,
5226 cFYI(1, ("Error in Notify = %d", rc));
5228 /* Add file to outstanding requests */
5229 /* BB change to kmem cache alloc */
5230 dnotify_req = kmalloc(
5231 sizeof(struct dir_notify_req),
5234 dnotify_req->Pid = pSMB->hdr.Pid;
5235 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5236 dnotify_req->Mid = pSMB->hdr.Mid;
5237 dnotify_req->Tid = pSMB->hdr.Tid;
5238 dnotify_req->Uid = pSMB->hdr.Uid;
5239 dnotify_req->netfid = netfid;
5240 dnotify_req->pfile = pfile;
5241 dnotify_req->filter = filter;
5242 dnotify_req->multishot = multishot;
5243 spin_lock(&GlobalMid_Lock);
5244 list_add_tail(&dnotify_req->lhead,
5245 &GlobalDnotifyReqList);
5246 spin_unlock(&GlobalMid_Lock);
5250 cifs_buf_release(pSMB);
5253 #ifdef CONFIG_CIFS_XATTR
5255 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5256 const unsigned char *searchName,
5257 char *EAData, size_t buf_size,
5258 const struct nls_table *nls_codepage, int remap)
5260 /* BB assumes one setup word */
5261 TRANSACTION2_QPI_REQ *pSMB = NULL;
5262 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5266 struct fea *temp_fea;
5268 __u16 params, byte_count;
5270 cFYI(1, ("In Query All EAs path %s", searchName));
5272 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5279 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5280 PATH_MAX, nls_codepage, remap);
5281 name_len++; /* trailing null */
5283 } else { /* BB improve the check for buffer overruns BB */
5284 name_len = strnlen(searchName, PATH_MAX);
5285 name_len++; /* trailing null */
5286 strncpy(pSMB->FileName, searchName, name_len);
5289 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5290 pSMB->TotalDataCount = 0;
5291 pSMB->MaxParameterCount = cpu_to_le16(2);
5292 /* BB find exact max SMB PDU from sess structure BB */
5293 pSMB->MaxDataCount = cpu_to_le16(4000);
5294 pSMB->MaxSetupCount = 0;
5298 pSMB->Reserved2 = 0;
5299 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5300 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5301 pSMB->DataCount = 0;
5302 pSMB->DataOffset = 0;
5303 pSMB->SetupCount = 1;
5304 pSMB->Reserved3 = 0;
5305 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5306 byte_count = params + 1 /* pad */ ;
5307 pSMB->TotalParameterCount = cpu_to_le16(params);
5308 pSMB->ParameterCount = pSMB->TotalParameterCount;
5309 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5310 pSMB->Reserved4 = 0;
5311 pSMB->hdr.smb_buf_length += byte_count;
5312 pSMB->ByteCount = cpu_to_le16(byte_count);
5314 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5315 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5317 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5318 } else { /* decode response */
5319 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5321 /* BB also check enough total bytes returned */
5322 /* BB we need to improve the validity checking
5323 of these trans2 responses */
5324 if (rc || (pSMBr->ByteCount < 4))
5325 rc = -EIO; /* bad smb */
5326 /* else if (pFindData){
5327 memcpy((char *) pFindData,
5328 (char *) &pSMBr->hdr.Protocol +
5331 /* check that length of list is not more than bcc */
5332 /* check that each entry does not go beyond length
5334 /* check that each element of each entry does not
5335 go beyond end of list */
5336 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5337 struct fealist *ea_response_data;
5339 /* validate_trans2_offsets() */
5340 /* BB check if start of smb + data_offset > &bcc+ bcc */
5341 ea_response_data = (struct fealist *)
5342 (((char *) &pSMBr->hdr.Protocol) +
5344 name_len = le32_to_cpu(ea_response_data->list_len);
5345 cFYI(1, ("ea length %d", name_len));
5346 if (name_len <= 8) {
5347 /* returned EA size zeroed at top of function */
5348 cFYI(1, ("empty EA list returned from server"));
5350 /* account for ea list len */
5352 temp_fea = ea_response_data->list;
5353 temp_ptr = (char *)temp_fea;
5354 while (name_len > 0) {
5358 rc += temp_fea->name_len;
5359 /* account for prefix user. and trailing null */
5361 if (rc < (int)buf_size) {
5362 memcpy(EAData, "user.", 5);
5364 memcpy(EAData, temp_ptr,
5365 temp_fea->name_len);
5366 EAData += temp_fea->name_len;
5367 /* null terminate name */
5369 EAData = EAData + 1;
5370 } else if (buf_size == 0) {
5371 /* skip copy - calc size only */
5373 /* stop before overrun buffer */
5377 name_len -= temp_fea->name_len;
5378 temp_ptr += temp_fea->name_len;
5379 /* account for trailing null */
5383 le16_to_cpu(temp_fea->value_len);
5384 name_len -= value_len;
5385 temp_ptr += value_len;
5386 /* BB check that temp_ptr is still
5389 /* no trailing null to account for
5391 /* go on to next EA */
5392 temp_fea = (struct fea *)temp_ptr;
5397 cifs_buf_release(pSMB);
5404 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5405 const unsigned char *searchName, const unsigned char *ea_name,
5406 unsigned char *ea_value, size_t buf_size,
5407 const struct nls_table *nls_codepage, int remap)
5409 TRANSACTION2_QPI_REQ *pSMB = NULL;
5410 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5414 struct fea *temp_fea;
5416 __u16 params, byte_count;
5418 cFYI(1, ("In Query EA path %s", searchName));
5420 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5425 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5427 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5428 PATH_MAX, nls_codepage, remap);
5429 name_len++; /* trailing null */
5431 } else { /* BB improve the check for buffer overruns BB */
5432 name_len = strnlen(searchName, PATH_MAX);
5433 name_len++; /* trailing null */
5434 strncpy(pSMB->FileName, searchName, name_len);
5437 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5438 pSMB->TotalDataCount = 0;
5439 pSMB->MaxParameterCount = cpu_to_le16(2);
5440 /* BB find exact max SMB PDU from sess structure BB */
5441 pSMB->MaxDataCount = cpu_to_le16(4000);
5442 pSMB->MaxSetupCount = 0;
5446 pSMB->Reserved2 = 0;
5447 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5448 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5449 pSMB->DataCount = 0;
5450 pSMB->DataOffset = 0;
5451 pSMB->SetupCount = 1;
5452 pSMB->Reserved3 = 0;
5453 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5454 byte_count = params + 1 /* pad */ ;
5455 pSMB->TotalParameterCount = cpu_to_le16(params);
5456 pSMB->ParameterCount = pSMB->TotalParameterCount;
5457 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5458 pSMB->Reserved4 = 0;
5459 pSMB->hdr.smb_buf_length += byte_count;
5460 pSMB->ByteCount = cpu_to_le16(byte_count);
5462 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5463 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5465 cFYI(1, ("Send error in Query EA = %d", rc));
5466 } else { /* decode response */
5467 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5469 /* BB also check enough total bytes returned */
5470 /* BB we need to improve the validity checking
5471 of these trans2 responses */
5472 if (rc || (pSMBr->ByteCount < 4))
5473 rc = -EIO; /* bad smb */
5474 /* else if (pFindData){
5475 memcpy((char *) pFindData,
5476 (char *) &pSMBr->hdr.Protocol +
5479 /* check that length of list is not more than bcc */
5480 /* check that each entry does not go beyond length
5482 /* check that each element of each entry does not
5483 go beyond end of list */
5484 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5485 struct fealist *ea_response_data;
5487 /* validate_trans2_offsets() */
5488 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5489 ea_response_data = (struct fealist *)
5490 (((char *) &pSMBr->hdr.Protocol) +
5492 name_len = le32_to_cpu(ea_response_data->list_len);
5493 cFYI(1, ("ea length %d", name_len));
5494 if (name_len <= 8) {
5495 /* returned EA size zeroed at top of function */
5496 cFYI(1, ("empty EA list returned from server"));
5498 /* account for ea list len */
5500 temp_fea = ea_response_data->list;
5501 temp_ptr = (char *)temp_fea;
5502 /* loop through checking if we have a matching
5503 name and then return the associated value */
5504 while (name_len > 0) {
5509 le16_to_cpu(temp_fea->value_len);
5510 /* BB validate that value_len falls within SMB,
5511 even though maximum for name_len is 255 */
5512 if (memcmp(temp_fea->name, ea_name,
5513 temp_fea->name_len) == 0) {
5516 /* account for prefix user. and trailing null */
5517 if (rc <= (int)buf_size) {
5519 temp_fea->name+temp_fea->name_len+1,
5521 /* ea values, unlike ea
5524 } else if (buf_size == 0) {
5525 /* skip copy - calc size only */
5527 /* stop before overrun buffer */
5532 name_len -= temp_fea->name_len;
5533 temp_ptr += temp_fea->name_len;
5534 /* account for trailing null */
5537 name_len -= value_len;
5538 temp_ptr += value_len;
5539 /* No trailing null to account for in
5540 value_len. Go on to next EA */
5541 temp_fea = (struct fea *)temp_ptr;
5546 cifs_buf_release(pSMB);
5554 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5555 const char *ea_name, const void *ea_value,
5556 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5559 struct smb_com_transaction2_spi_req *pSMB = NULL;
5560 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5561 struct fealist *parm_data;
5564 int bytes_returned = 0;
5565 __u16 params, param_offset, byte_count, offset, count;
5567 cFYI(1, ("In SetEA"));
5569 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5574 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5576 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5577 PATH_MAX, nls_codepage, remap);
5578 name_len++; /* trailing null */
5580 } else { /* BB improve the check for buffer overruns BB */
5581 name_len = strnlen(fileName, PATH_MAX);
5582 name_len++; /* trailing null */
5583 strncpy(pSMB->FileName, fileName, name_len);
5586 params = 6 + name_len;
5588 /* done calculating parms using name_len of file name,
5589 now use name_len to calculate length of ea name
5590 we are going to create in the inode xattrs */
5591 if (ea_name == NULL)
5594 name_len = strnlen(ea_name, 255);
5596 count = sizeof(*parm_data) + ea_value_len + name_len;
5597 pSMB->MaxParameterCount = cpu_to_le16(2);
5598 /* BB find max SMB PDU from sess */
5599 pSMB->MaxDataCount = cpu_to_le16(1000);
5600 pSMB->MaxSetupCount = 0;
5604 pSMB->Reserved2 = 0;
5605 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5606 InformationLevel) - 4;
5607 offset = param_offset + params;
5608 pSMB->InformationLevel =
5609 cpu_to_le16(SMB_SET_FILE_EA);
5612 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5614 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5615 pSMB->DataOffset = cpu_to_le16(offset);
5616 pSMB->SetupCount = 1;
5617 pSMB->Reserved3 = 0;
5618 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5619 byte_count = 3 /* pad */ + params + count;
5620 pSMB->DataCount = cpu_to_le16(count);
5621 parm_data->list_len = cpu_to_le32(count);
5622 parm_data->list[0].EA_flags = 0;
5623 /* we checked above that name len is less than 255 */
5624 parm_data->list[0].name_len = (__u8)name_len;
5625 /* EA names are always ASCII */
5627 strncpy(parm_data->list[0].name, ea_name, name_len);
5628 parm_data->list[0].name[name_len] = 0;
5629 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5630 /* caller ensures that ea_value_len is less than 64K but
5631 we need to ensure that it fits within the smb */
5633 /*BB add length check to see if it would fit in
5634 negotiated SMB buffer size BB */
5635 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5637 memcpy(parm_data->list[0].name+name_len+1,
5638 ea_value, ea_value_len);
5640 pSMB->TotalDataCount = pSMB->DataCount;
5641 pSMB->ParameterCount = cpu_to_le16(params);
5642 pSMB->TotalParameterCount = pSMB->ParameterCount;
5643 pSMB->Reserved4 = 0;
5644 pSMB->hdr.smb_buf_length += byte_count;
5645 pSMB->ByteCount = cpu_to_le16(byte_count);
5646 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5647 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5649 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5651 cifs_buf_release(pSMB);