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;
2567 #endif /* CIFS_EXPERIMENTAL */
2570 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2571 const unsigned char *searchName,
2572 char *symlinkinfo, const int buflen, __u16 fid,
2573 const struct nls_table *nls_codepage)
2578 struct smb_com_transaction_ioctl_req *pSMB;
2579 struct smb_com_transaction_ioctl_rsp *pSMBr;
2581 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2582 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2587 pSMB->TotalParameterCount = 0 ;
2588 pSMB->TotalDataCount = 0;
2589 pSMB->MaxParameterCount = cpu_to_le32(2);
2590 /* BB find exact data count max from sess structure BB */
2591 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2592 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2593 pSMB->MaxSetupCount = 4;
2595 pSMB->ParameterOffset = 0;
2596 pSMB->DataCount = 0;
2597 pSMB->DataOffset = 0;
2598 pSMB->SetupCount = 4;
2599 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2600 pSMB->ParameterCount = pSMB->TotalParameterCount;
2601 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2602 pSMB->IsFsctl = 1; /* FSCTL */
2603 pSMB->IsRootFlag = 0;
2604 pSMB->Fid = fid; /* file handle always le */
2605 pSMB->ByteCount = 0;
2607 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2608 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2610 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2611 } else { /* decode response */
2612 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2613 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2614 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2615 /* BB also check enough total bytes returned */
2616 rc = -EIO; /* bad smb */
2618 if (data_count && (data_count < 2048)) {
2619 char *end_of_smb = 2 /* sizeof byte count */ +
2621 (char *)&pSMBr->ByteCount;
2623 struct reparse_data *reparse_buf =
2624 (struct reparse_data *)
2625 ((char *)&pSMBr->hdr.Protocol
2627 if ((char *)reparse_buf >= end_of_smb) {
2631 if ((reparse_buf->LinkNamesBuf +
2632 reparse_buf->TargetNameOffset +
2633 reparse_buf->TargetNameLen) >
2635 cFYI(1, ("reparse buf beyond SMB"));
2640 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2641 name_len = UniStrnlen((wchar_t *)
2642 (reparse_buf->LinkNamesBuf +
2643 reparse_buf->TargetNameOffset),
2645 reparse_buf->TargetNameLen / 2));
2646 cifs_strfromUCS_le(symlinkinfo,
2647 (__le16 *) (reparse_buf->LinkNamesBuf +
2648 reparse_buf->TargetNameOffset),
2649 name_len, nls_codepage);
2650 } else { /* ASCII names */
2651 strncpy(symlinkinfo,
2652 reparse_buf->LinkNamesBuf +
2653 reparse_buf->TargetNameOffset,
2654 min_t(const int, buflen,
2655 reparse_buf->TargetNameLen));
2659 cFYI(1, ("Invalid return data count on "
2660 "get reparse info ioctl"));
2662 symlinkinfo[buflen] = 0; /* just in case so the caller
2663 does not go off the end of the buffer */
2664 cFYI(1, ("readlink result - %s", symlinkinfo));
2668 cifs_buf_release(pSMB);
2670 /* Note: On -EAGAIN error only caller can retry on handle based calls
2671 since file handle passed in no longer valid */
2676 #ifdef CONFIG_CIFS_POSIX
2678 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2679 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2680 struct cifs_posix_ace *cifs_ace)
2682 /* u8 cifs fields do not need le conversion */
2683 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2684 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2685 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2686 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2691 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2692 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2693 const int acl_type, const int size_of_data_area)
2698 struct cifs_posix_ace *pACE;
2699 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2700 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2702 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2705 if (acl_type & ACL_TYPE_ACCESS) {
2706 count = le16_to_cpu(cifs_acl->access_entry_count);
2707 pACE = &cifs_acl->ace_array[0];
2708 size = sizeof(struct cifs_posix_acl);
2709 size += sizeof(struct cifs_posix_ace) * count;
2710 /* check if we would go beyond end of SMB */
2711 if (size_of_data_area < size) {
2712 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2713 size_of_data_area, size));
2716 } else if (acl_type & ACL_TYPE_DEFAULT) {
2717 count = le16_to_cpu(cifs_acl->access_entry_count);
2718 size = sizeof(struct cifs_posix_acl);
2719 size += sizeof(struct cifs_posix_ace) * count;
2720 /* skip past access ACEs to get to default ACEs */
2721 pACE = &cifs_acl->ace_array[count];
2722 count = le16_to_cpu(cifs_acl->default_entry_count);
2723 size += sizeof(struct cifs_posix_ace) * count;
2724 /* check if we would go beyond end of SMB */
2725 if (size_of_data_area < size)
2732 size = posix_acl_xattr_size(count);
2733 if ((buflen == 0) || (local_acl == NULL)) {
2734 /* used to query ACL EA size */
2735 } else if (size > buflen) {
2737 } else /* buffer big enough */ {
2738 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2739 for (i = 0; i < count ; i++) {
2740 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2747 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2748 const posix_acl_xattr_entry *local_ace)
2750 __u16 rc = 0; /* 0 = ACL converted ok */
2752 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2753 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2754 /* BB is there a better way to handle the large uid? */
2755 if (local_ace->e_id == cpu_to_le32(-1)) {
2756 /* Probably no need to le convert -1 on any arch but can not hurt */
2757 cifs_ace->cifs_uid = cpu_to_le64(-1);
2759 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2760 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2764 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2765 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2766 const int buflen, const int acl_type)
2769 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2770 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2774 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2777 count = posix_acl_xattr_count((size_t)buflen);
2778 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2780 count, buflen, le32_to_cpu(local_acl->a_version)));
2781 if (le32_to_cpu(local_acl->a_version) != 2) {
2782 cFYI(1, ("unknown POSIX ACL version %d",
2783 le32_to_cpu(local_acl->a_version)));
2786 cifs_acl->version = cpu_to_le16(1);
2787 if (acl_type == ACL_TYPE_ACCESS)
2788 cifs_acl->access_entry_count = cpu_to_le16(count);
2789 else if (acl_type == ACL_TYPE_DEFAULT)
2790 cifs_acl->default_entry_count = cpu_to_le16(count);
2792 cFYI(1, ("unknown ACL type %d", acl_type));
2795 for (i = 0; i < count; i++) {
2796 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2797 &local_acl->a_entries[i]);
2799 /* ACE not converted */
2804 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2805 rc += sizeof(struct cifs_posix_acl);
2806 /* BB add check to make sure ACL does not overflow SMB */
2812 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2813 const unsigned char *searchName,
2814 char *acl_inf, const int buflen, const int acl_type,
2815 const struct nls_table *nls_codepage, int remap)
2817 /* SMB_QUERY_POSIX_ACL */
2818 TRANSACTION2_QPI_REQ *pSMB = NULL;
2819 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2823 __u16 params, byte_count;
2825 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2828 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2833 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2835 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2836 PATH_MAX, nls_codepage, remap);
2837 name_len++; /* trailing null */
2839 pSMB->FileName[name_len] = 0;
2840 pSMB->FileName[name_len+1] = 0;
2841 } else { /* BB improve the check for buffer overruns BB */
2842 name_len = strnlen(searchName, PATH_MAX);
2843 name_len++; /* trailing null */
2844 strncpy(pSMB->FileName, searchName, name_len);
2847 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2848 pSMB->TotalDataCount = 0;
2849 pSMB->MaxParameterCount = cpu_to_le16(2);
2850 /* BB find exact max data count below from sess structure BB */
2851 pSMB->MaxDataCount = cpu_to_le16(4000);
2852 pSMB->MaxSetupCount = 0;
2856 pSMB->Reserved2 = 0;
2857 pSMB->ParameterOffset = cpu_to_le16(
2858 offsetof(struct smb_com_transaction2_qpi_req,
2859 InformationLevel) - 4);
2860 pSMB->DataCount = 0;
2861 pSMB->DataOffset = 0;
2862 pSMB->SetupCount = 1;
2863 pSMB->Reserved3 = 0;
2864 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2865 byte_count = params + 1 /* pad */ ;
2866 pSMB->TotalParameterCount = cpu_to_le16(params);
2867 pSMB->ParameterCount = pSMB->TotalParameterCount;
2868 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2869 pSMB->Reserved4 = 0;
2870 pSMB->hdr.smb_buf_length += byte_count;
2871 pSMB->ByteCount = cpu_to_le16(byte_count);
2873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2875 cifs_stats_inc(&tcon->num_acl_get);
2877 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2879 /* decode response */
2881 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2882 if (rc || (pSMBr->ByteCount < 2))
2883 /* BB also check enough total bytes returned */
2884 rc = -EIO; /* bad smb */
2886 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2887 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2888 rc = cifs_copy_posix_acl(acl_inf,
2889 (char *)&pSMBr->hdr.Protocol+data_offset,
2890 buflen, acl_type, count);
2893 cifs_buf_release(pSMB);
2900 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2901 const unsigned char *fileName,
2902 const char *local_acl, const int buflen,
2904 const struct nls_table *nls_codepage, int remap)
2906 struct smb_com_transaction2_spi_req *pSMB = NULL;
2907 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2911 int bytes_returned = 0;
2912 __u16 params, byte_count, data_count, param_offset, offset;
2914 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2916 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2920 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2922 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2923 PATH_MAX, nls_codepage, remap);
2924 name_len++; /* trailing null */
2926 } else { /* BB improve the check for buffer overruns BB */
2927 name_len = strnlen(fileName, PATH_MAX);
2928 name_len++; /* trailing null */
2929 strncpy(pSMB->FileName, fileName, name_len);
2931 params = 6 + name_len;
2932 pSMB->MaxParameterCount = cpu_to_le16(2);
2933 /* BB find max SMB size from sess */
2934 pSMB->MaxDataCount = cpu_to_le16(1000);
2935 pSMB->MaxSetupCount = 0;
2939 pSMB->Reserved2 = 0;
2940 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2941 InformationLevel) - 4;
2942 offset = param_offset + params;
2943 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2944 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2946 /* convert to on the wire format for POSIX ACL */
2947 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2949 if (data_count == 0) {
2951 goto setACLerrorExit;
2953 pSMB->DataOffset = cpu_to_le16(offset);
2954 pSMB->SetupCount = 1;
2955 pSMB->Reserved3 = 0;
2956 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2957 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2958 byte_count = 3 /* pad */ + params + data_count;
2959 pSMB->DataCount = cpu_to_le16(data_count);
2960 pSMB->TotalDataCount = pSMB->DataCount;
2961 pSMB->ParameterCount = cpu_to_le16(params);
2962 pSMB->TotalParameterCount = pSMB->ParameterCount;
2963 pSMB->Reserved4 = 0;
2964 pSMB->hdr.smb_buf_length += byte_count;
2965 pSMB->ByteCount = cpu_to_le16(byte_count);
2966 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2967 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2969 cFYI(1, ("Set POSIX ACL returned %d", rc));
2972 cifs_buf_release(pSMB);
2978 /* BB fix tabs in this function FIXME BB */
2980 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2981 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2984 struct smb_t2_qfi_req *pSMB = NULL;
2985 struct smb_t2_qfi_rsp *pSMBr = NULL;
2987 __u16 params, byte_count;
2989 cFYI(1, ("In GetExtAttr"));
2994 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2999 params = 2 /* level */ + 2 /* fid */;
3000 pSMB->t2.TotalDataCount = 0;
3001 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3002 /* BB find exact max data count below from sess structure BB */
3003 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3004 pSMB->t2.MaxSetupCount = 0;
3005 pSMB->t2.Reserved = 0;
3007 pSMB->t2.Timeout = 0;
3008 pSMB->t2.Reserved2 = 0;
3009 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3011 pSMB->t2.DataCount = 0;
3012 pSMB->t2.DataOffset = 0;
3013 pSMB->t2.SetupCount = 1;
3014 pSMB->t2.Reserved3 = 0;
3015 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3016 byte_count = params + 1 /* pad */ ;
3017 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3018 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3019 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3022 pSMB->hdr.smb_buf_length += byte_count;
3023 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3025 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3026 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3028 cFYI(1, ("error %d in GetExtAttr", rc));
3030 /* decode response */
3031 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3032 if (rc || (pSMBr->ByteCount < 2))
3033 /* BB also check enough total bytes returned */
3034 /* If rc should we check for EOPNOSUPP and
3035 disable the srvino flag? or in caller? */
3036 rc = -EIO; /* bad smb */
3038 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3039 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3040 struct file_chattr_info *pfinfo;
3041 /* BB Do we need a cast or hash here ? */
3043 cFYI(1, ("Illegal size ret in GetExtAttr"));
3047 pfinfo = (struct file_chattr_info *)
3048 (data_offset + (char *) &pSMBr->hdr.Protocol);
3049 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3050 *pMask = le64_to_cpu(pfinfo->mask);
3054 cifs_buf_release(pSMB);
3056 goto GetExtAttrRetry;
3060 #endif /* CONFIG_POSIX */
3062 #ifdef CONFIG_CIFS_EXPERIMENTAL
3063 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3065 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3066 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3070 QUERY_SEC_DESC_REQ *pSMB;
3073 cFYI(1, ("GetCifsACL"));
3078 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3079 8 /* parm len */, tcon, (void **) &pSMB);
3083 pSMB->MaxParameterCount = cpu_to_le32(4);
3084 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3085 pSMB->MaxSetupCount = 0;
3086 pSMB->Fid = fid; /* file handle always le */
3087 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3089 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3090 pSMB->hdr.smb_buf_length += 11;
3091 iov[0].iov_base = (char *)pSMB;
3092 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3094 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3096 cifs_stats_inc(&tcon->num_acl_get);
3098 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3099 } else { /* decode response */
3103 struct smb_com_ntransact_rsp *pSMBr;
3106 /* validate_nttransact */
3107 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3108 &pdata, &parm_len, pbuflen);
3111 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3113 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3115 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3116 rc = -EIO; /* bad smb */
3121 /* BB check that data area is minimum length and as big as acl_len */
3123 acl_len = le32_to_cpu(*parm);
3124 if (acl_len != *pbuflen) {
3125 cERROR(1, ("acl length %d does not match %d",
3126 acl_len, *pbuflen));
3127 if (*pbuflen > acl_len)
3131 /* check if buffer is big enough for the acl
3132 header followed by the smallest SID */
3133 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3134 (*pbuflen >= 64 * 1024)) {
3135 cERROR(1, ("bad acl length %d", *pbuflen));
3139 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3140 if (*acl_inf == NULL) {
3144 memcpy(*acl_inf, pdata, *pbuflen);
3148 if (buf_type == CIFS_SMALL_BUFFER)
3149 cifs_small_buf_release(iov[0].iov_base);
3150 else if (buf_type == CIFS_LARGE_BUFFER)
3151 cifs_buf_release(iov[0].iov_base);
3152 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3157 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3158 struct cifs_ntsd *pntsd, __u32 acllen)
3160 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3162 int bytes_returned = 0;
3163 SET_SEC_DESC_REQ *pSMB = NULL;
3164 NTRANSACT_RSP *pSMBr = NULL;
3167 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3172 pSMB->MaxSetupCount = 0;
3176 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3177 data_count = acllen;
3178 data_offset = param_offset + param_count;
3179 byte_count = 3 /* pad */ + param_count;
3181 pSMB->DataCount = cpu_to_le32(data_count);
3182 pSMB->TotalDataCount = pSMB->DataCount;
3183 pSMB->MaxParameterCount = cpu_to_le32(4);
3184 pSMB->MaxDataCount = cpu_to_le32(16384);
3185 pSMB->ParameterCount = cpu_to_le32(param_count);
3186 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3187 pSMB->TotalParameterCount = pSMB->ParameterCount;
3188 pSMB->DataOffset = cpu_to_le32(data_offset);
3189 pSMB->SetupCount = 0;
3190 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3191 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3193 pSMB->Fid = fid; /* file handle always le */
3194 pSMB->Reserved2 = 0;
3195 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3197 if (pntsd && acllen) {
3198 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3201 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3204 pSMB->hdr.smb_buf_length += byte_count;
3206 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3207 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3209 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3211 cFYI(1, ("Set CIFS ACL returned %d", rc));
3212 cifs_buf_release(pSMB);
3215 goto setCifsAclRetry;
3220 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3222 /* Legacy Query Path Information call for lookup to old servers such
3224 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3225 const unsigned char *searchName,
3226 FILE_ALL_INFO *pFinfo,
3227 const struct nls_table *nls_codepage, int remap)
3229 QUERY_INFORMATION_REQ *pSMB;
3230 QUERY_INFORMATION_RSP *pSMBr;
3235 cFYI(1, ("In SMBQPath path %s", searchName));
3237 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3242 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3244 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3245 PATH_MAX, nls_codepage, remap);
3246 name_len++; /* trailing null */
3249 name_len = strnlen(searchName, PATH_MAX);
3250 name_len++; /* trailing null */
3251 strncpy(pSMB->FileName, searchName, name_len);
3253 pSMB->BufferFormat = 0x04;
3254 name_len++; /* account for buffer type byte */
3255 pSMB->hdr.smb_buf_length += (__u16) name_len;
3256 pSMB->ByteCount = cpu_to_le16(name_len);
3258 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3259 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3261 cFYI(1, ("Send error in QueryInfo = %d", rc));
3262 } else if (pFinfo) {
3264 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3266 /* decode response */
3267 /* BB FIXME - add time zone adjustment BB */
3268 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3271 /* decode time fields */
3272 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3273 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3274 pFinfo->LastAccessTime = 0;
3275 pFinfo->AllocationSize =
3276 cpu_to_le64(le32_to_cpu(pSMBr->size));
3277 pFinfo->EndOfFile = pFinfo->AllocationSize;
3278 pFinfo->Attributes =
3279 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3281 rc = -EIO; /* bad buffer passed in */
3283 cifs_buf_release(pSMB);
3295 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3296 const unsigned char *searchName,
3297 FILE_ALL_INFO *pFindData,
3298 int legacy /* old style infolevel */,
3299 const struct nls_table *nls_codepage, int remap)
3301 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3302 TRANSACTION2_QPI_REQ *pSMB = NULL;
3303 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3307 __u16 params, byte_count;
3309 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3311 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3316 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3318 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3319 PATH_MAX, nls_codepage, remap);
3320 name_len++; /* trailing null */
3322 } else { /* BB improve the check for buffer overruns BB */
3323 name_len = strnlen(searchName, PATH_MAX);
3324 name_len++; /* trailing null */
3325 strncpy(pSMB->FileName, searchName, name_len);
3328 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3329 pSMB->TotalDataCount = 0;
3330 pSMB->MaxParameterCount = cpu_to_le16(2);
3331 /* BB find exact max SMB PDU from sess structure BB */
3332 pSMB->MaxDataCount = cpu_to_le16(4000);
3333 pSMB->MaxSetupCount = 0;
3337 pSMB->Reserved2 = 0;
3338 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3339 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3340 pSMB->DataCount = 0;
3341 pSMB->DataOffset = 0;
3342 pSMB->SetupCount = 1;
3343 pSMB->Reserved3 = 0;
3344 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3345 byte_count = params + 1 /* pad */ ;
3346 pSMB->TotalParameterCount = cpu_to_le16(params);
3347 pSMB->ParameterCount = pSMB->TotalParameterCount;
3349 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3351 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3352 pSMB->Reserved4 = 0;
3353 pSMB->hdr.smb_buf_length += byte_count;
3354 pSMB->ByteCount = cpu_to_le16(byte_count);
3356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3359 cFYI(1, ("Send error in QPathInfo = %d", rc));
3360 } else { /* decode response */
3361 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3363 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3365 else if (!legacy && (pSMBr->ByteCount < 40))
3366 rc = -EIO; /* bad smb */
3367 else if (legacy && (pSMBr->ByteCount < 24))
3368 rc = -EIO; /* 24 or 26 expected but we do not read
3370 else if (pFindData) {
3372 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3374 /* On legacy responses we do not read the last field,
3375 EAsize, fortunately since it varies by subdialect and
3376 also note it differs on Set vs. Get, ie two bytes or 4
3377 bytes depending but we don't care here */
3379 size = sizeof(FILE_INFO_STANDARD);
3381 size = sizeof(FILE_ALL_INFO);
3382 memcpy((char *) pFindData,
3383 (char *) &pSMBr->hdr.Protocol +
3388 cifs_buf_release(pSMB);
3390 goto QPathInfoRetry;
3396 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3397 const unsigned char *searchName,
3398 FILE_UNIX_BASIC_INFO *pFindData,
3399 const struct nls_table *nls_codepage, int remap)
3401 /* SMB_QUERY_FILE_UNIX_BASIC */
3402 TRANSACTION2_QPI_REQ *pSMB = NULL;
3403 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3405 int bytes_returned = 0;
3407 __u16 params, byte_count;
3409 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3411 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3416 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3418 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3419 PATH_MAX, nls_codepage, remap);
3420 name_len++; /* trailing null */
3422 } else { /* BB improve the check for buffer overruns BB */
3423 name_len = strnlen(searchName, PATH_MAX);
3424 name_len++; /* trailing null */
3425 strncpy(pSMB->FileName, searchName, name_len);
3428 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3429 pSMB->TotalDataCount = 0;
3430 pSMB->MaxParameterCount = cpu_to_le16(2);
3431 /* BB find exact max SMB PDU from sess structure BB */
3432 pSMB->MaxDataCount = cpu_to_le16(4000);
3433 pSMB->MaxSetupCount = 0;
3437 pSMB->Reserved2 = 0;
3438 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3439 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3440 pSMB->DataCount = 0;
3441 pSMB->DataOffset = 0;
3442 pSMB->SetupCount = 1;
3443 pSMB->Reserved3 = 0;
3444 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3445 byte_count = params + 1 /* pad */ ;
3446 pSMB->TotalParameterCount = cpu_to_le16(params);
3447 pSMB->ParameterCount = pSMB->TotalParameterCount;
3448 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3449 pSMB->Reserved4 = 0;
3450 pSMB->hdr.smb_buf_length += byte_count;
3451 pSMB->ByteCount = cpu_to_le16(byte_count);
3453 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3454 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3456 cFYI(1, ("Send error in QPathInfo = %d", rc));
3457 } else { /* decode response */
3458 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3460 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3461 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3462 "Unix Extensions can be disabled on mount "
3463 "by specifying the nosfu mount option."));
3464 rc = -EIO; /* bad smb */
3466 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3467 memcpy((char *) pFindData,
3468 (char *) &pSMBr->hdr.Protocol +
3470 sizeof(FILE_UNIX_BASIC_INFO));
3473 cifs_buf_release(pSMB);
3475 goto UnixQPathInfoRetry;
3480 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3482 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3483 const char *searchName,
3484 const struct nls_table *nls_codepage,
3486 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3488 /* level 257 SMB_ */
3489 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3490 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3491 T2_FFIRST_RSP_PARMS *parms;
3493 int bytes_returned = 0;
3495 __u16 params, byte_count;
3497 cFYI(1, ("In FindFirst for %s", searchName));
3500 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3505 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3507 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3508 PATH_MAX, nls_codepage, remap);
3509 /* We can not add the asterik earlier in case
3510 it got remapped to 0xF03A as if it were part of the
3511 directory name instead of a wildcard */
3513 pSMB->FileName[name_len] = dirsep;
3514 pSMB->FileName[name_len+1] = 0;
3515 pSMB->FileName[name_len+2] = '*';
3516 pSMB->FileName[name_len+3] = 0;
3517 name_len += 4; /* now the trailing null */
3518 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3519 pSMB->FileName[name_len+1] = 0;
3521 } else { /* BB add check for overrun of SMB buf BB */
3522 name_len = strnlen(searchName, PATH_MAX);
3523 /* BB fix here and in unicode clause above ie
3524 if (name_len > buffersize-header)
3525 free buffer exit; BB */
3526 strncpy(pSMB->FileName, searchName, name_len);
3527 pSMB->FileName[name_len] = dirsep;
3528 pSMB->FileName[name_len+1] = '*';
3529 pSMB->FileName[name_len+2] = 0;
3533 params = 12 + name_len /* includes null */ ;
3534 pSMB->TotalDataCount = 0; /* no EAs */
3535 pSMB->MaxParameterCount = cpu_to_le16(10);
3536 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3537 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3538 pSMB->MaxSetupCount = 0;
3542 pSMB->Reserved2 = 0;
3543 byte_count = params + 1 /* pad */ ;
3544 pSMB->TotalParameterCount = cpu_to_le16(params);
3545 pSMB->ParameterCount = pSMB->TotalParameterCount;
3546 pSMB->ParameterOffset = cpu_to_le16(
3547 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3549 pSMB->DataCount = 0;
3550 pSMB->DataOffset = 0;
3551 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3552 pSMB->Reserved3 = 0;
3553 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3554 pSMB->SearchAttributes =
3555 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3557 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3558 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3559 CIFS_SEARCH_RETURN_RESUME);
3560 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3562 /* BB what should we set StorageType to? Does it matter? BB */
3563 pSMB->SearchStorageType = 0;
3564 pSMB->hdr.smb_buf_length += byte_count;
3565 pSMB->ByteCount = cpu_to_le16(byte_count);
3567 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3568 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3569 cifs_stats_inc(&tcon->num_ffirst);
3571 if (rc) {/* BB add logic to retry regular search if Unix search
3572 rejected unexpectedly by server */
3573 /* BB Add code to handle unsupported level rc */
3574 cFYI(1, ("Error in FindFirst = %d", rc));
3576 cifs_buf_release(pSMB);
3578 /* BB eventually could optimize out free and realloc of buf */
3581 goto findFirstRetry;
3582 } else { /* decode response */
3583 /* BB remember to free buffer if error BB */
3584 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3588 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3589 psrch_inf->unicode = true;
3591 psrch_inf->unicode = false;
3593 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3594 psrch_inf->smallBuf = 0;
3595 psrch_inf->srch_entries_start =
3596 (char *) &pSMBr->hdr.Protocol +
3597 le16_to_cpu(pSMBr->t2.DataOffset);
3598 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3599 le16_to_cpu(pSMBr->t2.ParameterOffset));
3601 if (parms->EndofSearch)
3602 psrch_inf->endOfSearch = true;
3604 psrch_inf->endOfSearch = false;
3606 psrch_inf->entries_in_buffer =
3607 le16_to_cpu(parms->SearchCount);
3608 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3609 psrch_inf->entries_in_buffer;
3610 lnoff = le16_to_cpu(parms->LastNameOffset);
3611 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3613 cERROR(1, ("ignoring corrupt resume name"));
3614 psrch_inf->last_entry = NULL;
3618 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3621 *pnetfid = parms->SearchHandle;
3623 cifs_buf_release(pSMB);
3630 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3631 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3633 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3634 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3635 T2_FNEXT_RSP_PARMS *parms;
3636 char *response_data;
3638 int bytes_returned, name_len;
3639 __u16 params, byte_count;
3641 cFYI(1, ("In FindNext"));
3643 if (psrch_inf->endOfSearch)
3646 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3651 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3653 pSMB->TotalDataCount = 0; /* no EAs */
3654 pSMB->MaxParameterCount = cpu_to_le16(8);
3655 pSMB->MaxDataCount =
3656 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3658 pSMB->MaxSetupCount = 0;
3662 pSMB->Reserved2 = 0;
3663 pSMB->ParameterOffset = cpu_to_le16(
3664 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3665 pSMB->DataCount = 0;
3666 pSMB->DataOffset = 0;
3667 pSMB->SetupCount = 1;
3668 pSMB->Reserved3 = 0;
3669 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3670 pSMB->SearchHandle = searchHandle; /* always kept as le */
3672 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3673 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3674 pSMB->ResumeKey = psrch_inf->resume_key;
3676 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3678 name_len = psrch_inf->resume_name_len;
3680 if (name_len < PATH_MAX) {
3681 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3682 byte_count += name_len;
3683 /* 14 byte parm len above enough for 2 byte null terminator */
3684 pSMB->ResumeFileName[name_len] = 0;
3685 pSMB->ResumeFileName[name_len+1] = 0;
3688 goto FNext2_err_exit;
3690 byte_count = params + 1 /* pad */ ;
3691 pSMB->TotalParameterCount = cpu_to_le16(params);
3692 pSMB->ParameterCount = pSMB->TotalParameterCount;
3693 pSMB->hdr.smb_buf_length += byte_count;
3694 pSMB->ByteCount = cpu_to_le16(byte_count);
3696 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3697 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3698 cifs_stats_inc(&tcon->num_fnext);
3701 psrch_inf->endOfSearch = true;
3702 cifs_buf_release(pSMB);
3703 rc = 0; /* search probably was closed at end of search*/
3705 cFYI(1, ("FindNext returned = %d", rc));
3706 } else { /* decode response */
3707 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3712 /* BB fixme add lock for file (srch_info) struct here */
3713 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3714 psrch_inf->unicode = true;
3716 psrch_inf->unicode = false;
3717 response_data = (char *) &pSMBr->hdr.Protocol +
3718 le16_to_cpu(pSMBr->t2.ParameterOffset);
3719 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3720 response_data = (char *)&pSMBr->hdr.Protocol +
3721 le16_to_cpu(pSMBr->t2.DataOffset);
3722 if (psrch_inf->smallBuf)
3723 cifs_small_buf_release(
3724 psrch_inf->ntwrk_buf_start);
3726 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3727 psrch_inf->srch_entries_start = response_data;
3728 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3729 psrch_inf->smallBuf = 0;
3730 if (parms->EndofSearch)
3731 psrch_inf->endOfSearch = true;
3733 psrch_inf->endOfSearch = false;
3734 psrch_inf->entries_in_buffer =
3735 le16_to_cpu(parms->SearchCount);
3736 psrch_inf->index_of_last_entry +=
3737 psrch_inf->entries_in_buffer;
3738 lnoff = le16_to_cpu(parms->LastNameOffset);
3739 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3741 cERROR(1, ("ignoring corrupt resume name"));
3742 psrch_inf->last_entry = NULL;
3745 psrch_inf->last_entry =
3746 psrch_inf->srch_entries_start + lnoff;
3748 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3749 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3751 /* BB fixme add unlock here */
3756 /* BB On error, should we leave previous search buf (and count and
3757 last entry fields) intact or free the previous one? */
3759 /* Note: On -EAGAIN error only caller can retry on handle based calls
3760 since file handle passed in no longer valid */
3763 cifs_buf_release(pSMB);
3768 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3769 const __u16 searchHandle)
3772 FINDCLOSE_REQ *pSMB = NULL;
3774 cFYI(1, ("In CIFSSMBFindClose"));
3775 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3777 /* no sense returning error if session restarted
3778 as file handle has been closed */
3784 pSMB->FileID = searchHandle;
3785 pSMB->ByteCount = 0;
3786 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3788 cERROR(1, ("Send error in FindClose = %d", rc));
3790 cifs_stats_inc(&tcon->num_fclose);
3792 /* Since session is dead, search handle closed on server already */
3800 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3801 const unsigned char *searchName,
3802 __u64 *inode_number,
3803 const struct nls_table *nls_codepage, int remap)
3806 TRANSACTION2_QPI_REQ *pSMB = NULL;
3807 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3808 int name_len, bytes_returned;
3809 __u16 params, byte_count;
3811 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3815 GetInodeNumberRetry:
3816 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3821 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3823 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3824 PATH_MAX, nls_codepage, remap);
3825 name_len++; /* trailing null */
3827 } else { /* BB improve the check for buffer overruns BB */
3828 name_len = strnlen(searchName, PATH_MAX);
3829 name_len++; /* trailing null */
3830 strncpy(pSMB->FileName, searchName, name_len);
3833 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3834 pSMB->TotalDataCount = 0;
3835 pSMB->MaxParameterCount = cpu_to_le16(2);
3836 /* BB find exact max data count below from sess structure BB */
3837 pSMB->MaxDataCount = cpu_to_le16(4000);
3838 pSMB->MaxSetupCount = 0;
3842 pSMB->Reserved2 = 0;
3843 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3844 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3845 pSMB->DataCount = 0;
3846 pSMB->DataOffset = 0;
3847 pSMB->SetupCount = 1;
3848 pSMB->Reserved3 = 0;
3849 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3850 byte_count = params + 1 /* pad */ ;
3851 pSMB->TotalParameterCount = cpu_to_le16(params);
3852 pSMB->ParameterCount = pSMB->TotalParameterCount;
3853 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3854 pSMB->Reserved4 = 0;
3855 pSMB->hdr.smb_buf_length += byte_count;
3856 pSMB->ByteCount = cpu_to_le16(byte_count);
3858 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3859 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3861 cFYI(1, ("error %d in QueryInternalInfo", rc));
3863 /* decode response */
3864 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3865 if (rc || (pSMBr->ByteCount < 2))
3866 /* BB also check enough total bytes returned */
3867 /* If rc should we check for EOPNOSUPP and
3868 disable the srvino flag? or in caller? */
3869 rc = -EIO; /* bad smb */
3871 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3872 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3873 struct file_internal_info *pfinfo;
3874 /* BB Do we need a cast or hash here ? */
3876 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3878 goto GetInodeNumOut;
3880 pfinfo = (struct file_internal_info *)
3881 (data_offset + (char *) &pSMBr->hdr.Protocol);
3882 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3886 cifs_buf_release(pSMB);
3888 goto GetInodeNumberRetry;
3892 /* parses DFS refferal V3 structure
3893 * caller is responsible for freeing target_nodes
3896 * on failure - errno
3899 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3900 unsigned int *num_of_nodes,
3901 struct dfs_info3_param **target_nodes,
3902 const struct nls_table *nls_codepage, int remap,
3903 const char *searchName)
3908 struct dfs_referral_level_3 *ref;
3910 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3914 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3916 if (*num_of_nodes < 1) {
3917 cERROR(1, ("num_referrals: must be at least > 0,"
3918 "but we get num_referrals = %d\n", *num_of_nodes));
3920 goto parse_DFS_referrals_exit;
3923 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3924 if (ref->VersionNumber != cpu_to_le16(3)) {
3925 cERROR(1, ("Referrals of V%d version are not supported,"
3926 "should be V3", le16_to_cpu(ref->VersionNumber)));
3928 goto parse_DFS_referrals_exit;
3931 /* get the upper boundary of the resp buffer */
3932 data_end = (char *)(&(pSMBr->PathConsumed)) +
3933 le16_to_cpu(pSMBr->t2.DataCount);
3935 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3937 le32_to_cpu(pSMBr->DFSFlags)));
3939 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3940 *num_of_nodes, GFP_KERNEL);
3941 if (*target_nodes == NULL) {
3942 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3944 goto parse_DFS_referrals_exit;
3947 /* collect neccessary data from referrals */
3948 for (i = 0; i < *num_of_nodes; i++) {
3951 struct dfs_info3_param *node = (*target_nodes)+i;
3953 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3955 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3957 cifsConvertToUCS((__le16 *) tmp, searchName,
3958 PATH_MAX, nls_codepage, remap);
3959 node->path_consumed = cifs_ucs2_bytes(tmp,
3960 le16_to_cpu(pSMBr->PathConsumed),
3964 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3966 node->server_type = le16_to_cpu(ref->ServerType);
3967 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3970 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3971 max_len = data_end - temp;
3972 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3973 is_unicode, nls_codepage);
3974 if (IS_ERR(node->path_name)) {
3975 rc = PTR_ERR(node->path_name);
3976 node->path_name = NULL;
3977 goto parse_DFS_referrals_exit;
3980 /* copy link target UNC */
3981 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3982 max_len = data_end - temp;
3983 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3984 is_unicode, nls_codepage);
3985 if (IS_ERR(node->node_name)) {
3986 rc = PTR_ERR(node->node_name);
3987 node->node_name = NULL;
3988 goto parse_DFS_referrals_exit;
3992 parse_DFS_referrals_exit:
3994 free_dfs_info_array(*target_nodes, *num_of_nodes);
3995 *target_nodes = NULL;
4002 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4003 const unsigned char *searchName,
4004 struct dfs_info3_param **target_nodes,
4005 unsigned int *num_of_nodes,
4006 const struct nls_table *nls_codepage, int remap)
4008 /* TRANS2_GET_DFS_REFERRAL */
4009 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4010 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4014 __u16 params, byte_count;
4016 *target_nodes = NULL;
4018 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4022 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4027 /* server pointer checked in called function,
4028 but should never be null here anyway */
4029 pSMB->hdr.Mid = GetNextMid(ses->server);
4030 pSMB->hdr.Tid = ses->ipc_tid;
4031 pSMB->hdr.Uid = ses->Suid;
4032 if (ses->capabilities & CAP_STATUS32)
4033 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4034 if (ses->capabilities & CAP_DFS)
4035 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4037 if (ses->capabilities & CAP_UNICODE) {
4038 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4040 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4041 searchName, PATH_MAX, nls_codepage, remap);
4042 name_len++; /* trailing null */
4044 } else { /* BB improve the check for buffer overruns BB */
4045 name_len = strnlen(searchName, PATH_MAX);
4046 name_len++; /* trailing null */
4047 strncpy(pSMB->RequestFileName, searchName, name_len);
4051 if (ses->server->secMode &
4052 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4053 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4056 pSMB->hdr.Uid = ses->Suid;
4058 params = 2 /* level */ + name_len /*includes null */ ;
4059 pSMB->TotalDataCount = 0;
4060 pSMB->DataCount = 0;
4061 pSMB->DataOffset = 0;
4062 pSMB->MaxParameterCount = 0;
4063 /* BB find exact max SMB PDU from sess structure BB */
4064 pSMB->MaxDataCount = cpu_to_le16(4000);
4065 pSMB->MaxSetupCount = 0;
4069 pSMB->Reserved2 = 0;
4070 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4071 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4072 pSMB->SetupCount = 1;
4073 pSMB->Reserved3 = 0;
4074 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4075 byte_count = params + 3 /* pad */ ;
4076 pSMB->ParameterCount = cpu_to_le16(params);
4077 pSMB->TotalParameterCount = pSMB->ParameterCount;
4078 pSMB->MaxReferralLevel = cpu_to_le16(3);
4079 pSMB->hdr.smb_buf_length += byte_count;
4080 pSMB->ByteCount = cpu_to_le16(byte_count);
4082 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4083 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4085 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4088 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4090 /* BB Also check if enough total bytes returned? */
4091 if (rc || (pSMBr->ByteCount < 17)) {
4092 rc = -EIO; /* bad smb */
4096 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4098 le16_to_cpu(pSMBr->t2.DataOffset)));
4100 /* parse returned result into more usable form */
4101 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4102 target_nodes, nls_codepage, remap,
4106 cifs_buf_release(pSMB);
4114 /* Query File System Info such as free space to old servers such as Win 9x */
4116 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4118 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4119 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4120 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4121 FILE_SYSTEM_ALLOC_INFO *response_data;
4123 int bytes_returned = 0;
4124 __u16 params, byte_count;
4126 cFYI(1, ("OldQFSInfo"));
4128 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4133 params = 2; /* level */
4134 pSMB->TotalDataCount = 0;
4135 pSMB->MaxParameterCount = cpu_to_le16(2);
4136 pSMB->MaxDataCount = cpu_to_le16(1000);
4137 pSMB->MaxSetupCount = 0;
4141 pSMB->Reserved2 = 0;
4142 byte_count = params + 1 /* pad */ ;
4143 pSMB->TotalParameterCount = cpu_to_le16(params);
4144 pSMB->ParameterCount = pSMB->TotalParameterCount;
4145 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4146 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4147 pSMB->DataCount = 0;
4148 pSMB->DataOffset = 0;
4149 pSMB->SetupCount = 1;
4150 pSMB->Reserved3 = 0;
4151 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4152 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4153 pSMB->hdr.smb_buf_length += byte_count;
4154 pSMB->ByteCount = cpu_to_le16(byte_count);
4156 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4157 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4159 cFYI(1, ("Send error in QFSInfo = %d", rc));
4160 } else { /* decode response */
4161 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4163 if (rc || (pSMBr->ByteCount < 18))
4164 rc = -EIO; /* bad smb */
4166 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4167 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4168 pSMBr->ByteCount, data_offset));
4170 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4171 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4173 le16_to_cpu(response_data->BytesPerSector) *
4174 le32_to_cpu(response_data->
4175 SectorsPerAllocationUnit);
4177 le32_to_cpu(response_data->TotalAllocationUnits);
4178 FSData->f_bfree = FSData->f_bavail =
4179 le32_to_cpu(response_data->FreeAllocationUnits);
4181 ("Blocks: %lld Free: %lld Block size %ld",
4182 (unsigned long long)FSData->f_blocks,
4183 (unsigned long long)FSData->f_bfree,
4187 cifs_buf_release(pSMB);
4190 goto oldQFSInfoRetry;
4196 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4198 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4199 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4200 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4201 FILE_SYSTEM_INFO *response_data;
4203 int bytes_returned = 0;
4204 __u16 params, byte_count;
4206 cFYI(1, ("In QFSInfo"));
4208 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4213 params = 2; /* level */
4214 pSMB->TotalDataCount = 0;
4215 pSMB->MaxParameterCount = cpu_to_le16(2);
4216 pSMB->MaxDataCount = cpu_to_le16(1000);
4217 pSMB->MaxSetupCount = 0;
4221 pSMB->Reserved2 = 0;
4222 byte_count = params + 1 /* pad */ ;
4223 pSMB->TotalParameterCount = cpu_to_le16(params);
4224 pSMB->ParameterCount = pSMB->TotalParameterCount;
4225 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4226 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4227 pSMB->DataCount = 0;
4228 pSMB->DataOffset = 0;
4229 pSMB->SetupCount = 1;
4230 pSMB->Reserved3 = 0;
4231 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4232 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4233 pSMB->hdr.smb_buf_length += byte_count;
4234 pSMB->ByteCount = cpu_to_le16(byte_count);
4236 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4237 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4239 cFYI(1, ("Send error in QFSInfo = %d", rc));
4240 } else { /* decode response */
4241 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4243 if (rc || (pSMBr->ByteCount < 24))
4244 rc = -EIO; /* bad smb */
4246 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4250 *) (((char *) &pSMBr->hdr.Protocol) +
4253 le32_to_cpu(response_data->BytesPerSector) *
4254 le32_to_cpu(response_data->
4255 SectorsPerAllocationUnit);
4257 le64_to_cpu(response_data->TotalAllocationUnits);
4258 FSData->f_bfree = FSData->f_bavail =
4259 le64_to_cpu(response_data->FreeAllocationUnits);
4261 ("Blocks: %lld Free: %lld Block size %ld",
4262 (unsigned long long)FSData->f_blocks,
4263 (unsigned long long)FSData->f_bfree,
4267 cifs_buf_release(pSMB);
4276 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4278 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4279 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4280 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4281 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4283 int bytes_returned = 0;
4284 __u16 params, byte_count;
4286 cFYI(1, ("In QFSAttributeInfo"));
4288 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4293 params = 2; /* level */
4294 pSMB->TotalDataCount = 0;
4295 pSMB->MaxParameterCount = cpu_to_le16(2);
4296 /* BB find exact max SMB PDU from sess structure BB */
4297 pSMB->MaxDataCount = cpu_to_le16(1000);
4298 pSMB->MaxSetupCount = 0;
4302 pSMB->Reserved2 = 0;
4303 byte_count = params + 1 /* pad */ ;
4304 pSMB->TotalParameterCount = cpu_to_le16(params);
4305 pSMB->ParameterCount = pSMB->TotalParameterCount;
4306 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4307 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4308 pSMB->DataCount = 0;
4309 pSMB->DataOffset = 0;
4310 pSMB->SetupCount = 1;
4311 pSMB->Reserved3 = 0;
4312 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4313 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4314 pSMB->hdr.smb_buf_length += byte_count;
4315 pSMB->ByteCount = cpu_to_le16(byte_count);
4317 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4318 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4320 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4321 } else { /* decode response */
4322 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4324 if (rc || (pSMBr->ByteCount < 13)) {
4325 /* BB also check if enough bytes returned */
4326 rc = -EIO; /* bad smb */
4328 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4330 (FILE_SYSTEM_ATTRIBUTE_INFO
4331 *) (((char *) &pSMBr->hdr.Protocol) +
4333 memcpy(&tcon->fsAttrInfo, response_data,
4334 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4337 cifs_buf_release(pSMB);
4340 goto QFSAttributeRetry;
4346 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4348 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4349 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4350 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4351 FILE_SYSTEM_DEVICE_INFO *response_data;
4353 int bytes_returned = 0;
4354 __u16 params, byte_count;
4356 cFYI(1, ("In QFSDeviceInfo"));
4358 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4363 params = 2; /* level */
4364 pSMB->TotalDataCount = 0;
4365 pSMB->MaxParameterCount = cpu_to_le16(2);
4366 /* BB find exact max SMB PDU from sess structure BB */
4367 pSMB->MaxDataCount = cpu_to_le16(1000);
4368 pSMB->MaxSetupCount = 0;
4372 pSMB->Reserved2 = 0;
4373 byte_count = params + 1 /* pad */ ;
4374 pSMB->TotalParameterCount = cpu_to_le16(params);
4375 pSMB->ParameterCount = pSMB->TotalParameterCount;
4376 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4377 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4379 pSMB->DataCount = 0;
4380 pSMB->DataOffset = 0;
4381 pSMB->SetupCount = 1;
4382 pSMB->Reserved3 = 0;
4383 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4384 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4385 pSMB->hdr.smb_buf_length += byte_count;
4386 pSMB->ByteCount = cpu_to_le16(byte_count);
4388 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4389 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4391 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4392 } else { /* decode response */
4393 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4395 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4396 rc = -EIO; /* bad smb */
4398 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4400 (FILE_SYSTEM_DEVICE_INFO *)
4401 (((char *) &pSMBr->hdr.Protocol) +
4403 memcpy(&tcon->fsDevInfo, response_data,
4404 sizeof(FILE_SYSTEM_DEVICE_INFO));
4407 cifs_buf_release(pSMB);
4410 goto QFSDeviceRetry;
4416 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4418 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4419 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4420 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4421 FILE_SYSTEM_UNIX_INFO *response_data;
4423 int bytes_returned = 0;
4424 __u16 params, byte_count;
4426 cFYI(1, ("In QFSUnixInfo"));
4428 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4433 params = 2; /* level */
4434 pSMB->TotalDataCount = 0;
4435 pSMB->DataCount = 0;
4436 pSMB->DataOffset = 0;
4437 pSMB->MaxParameterCount = cpu_to_le16(2);
4438 /* BB find exact max SMB PDU from sess structure BB */
4439 pSMB->MaxDataCount = cpu_to_le16(100);
4440 pSMB->MaxSetupCount = 0;
4444 pSMB->Reserved2 = 0;
4445 byte_count = params + 1 /* pad */ ;
4446 pSMB->ParameterCount = cpu_to_le16(params);
4447 pSMB->TotalParameterCount = pSMB->ParameterCount;
4448 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4449 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4450 pSMB->SetupCount = 1;
4451 pSMB->Reserved3 = 0;
4452 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4453 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4454 pSMB->hdr.smb_buf_length += byte_count;
4455 pSMB->ByteCount = cpu_to_le16(byte_count);
4457 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4458 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4460 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4461 } else { /* decode response */
4462 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4464 if (rc || (pSMBr->ByteCount < 13)) {
4465 rc = -EIO; /* bad smb */
4467 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4469 (FILE_SYSTEM_UNIX_INFO
4470 *) (((char *) &pSMBr->hdr.Protocol) +
4472 memcpy(&tcon->fsUnixInfo, response_data,
4473 sizeof(FILE_SYSTEM_UNIX_INFO));
4476 cifs_buf_release(pSMB);
4486 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4488 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4489 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4490 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4492 int bytes_returned = 0;
4493 __u16 params, param_offset, offset, byte_count;
4495 cFYI(1, ("In SETFSUnixInfo"));
4497 /* BB switch to small buf init to save memory */
4498 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4503 params = 4; /* 2 bytes zero followed by info level. */
4504 pSMB->MaxSetupCount = 0;
4508 pSMB->Reserved2 = 0;
4509 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4511 offset = param_offset + params;
4513 pSMB->MaxParameterCount = cpu_to_le16(4);
4514 /* BB find exact max SMB PDU from sess structure BB */
4515 pSMB->MaxDataCount = cpu_to_le16(100);
4516 pSMB->SetupCount = 1;
4517 pSMB->Reserved3 = 0;
4518 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4519 byte_count = 1 /* pad */ + params + 12;
4521 pSMB->DataCount = cpu_to_le16(12);
4522 pSMB->ParameterCount = cpu_to_le16(params);
4523 pSMB->TotalDataCount = pSMB->DataCount;
4524 pSMB->TotalParameterCount = pSMB->ParameterCount;
4525 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4526 pSMB->DataOffset = cpu_to_le16(offset);
4530 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4533 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4534 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4535 pSMB->ClientUnixCap = cpu_to_le64(cap);
4537 pSMB->hdr.smb_buf_length += byte_count;
4538 pSMB->ByteCount = cpu_to_le16(byte_count);
4540 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4541 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4543 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4544 } else { /* decode response */
4545 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4547 rc = -EIO; /* bad smb */
4549 cifs_buf_release(pSMB);
4552 goto SETFSUnixRetry;
4560 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4561 struct kstatfs *FSData)
4563 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4564 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4565 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4566 FILE_SYSTEM_POSIX_INFO *response_data;
4568 int bytes_returned = 0;
4569 __u16 params, byte_count;
4571 cFYI(1, ("In QFSPosixInfo"));
4573 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4578 params = 2; /* level */
4579 pSMB->TotalDataCount = 0;
4580 pSMB->DataCount = 0;
4581 pSMB->DataOffset = 0;
4582 pSMB->MaxParameterCount = cpu_to_le16(2);
4583 /* BB find exact max SMB PDU from sess structure BB */
4584 pSMB->MaxDataCount = cpu_to_le16(100);
4585 pSMB->MaxSetupCount = 0;
4589 pSMB->Reserved2 = 0;
4590 byte_count = params + 1 /* pad */ ;
4591 pSMB->ParameterCount = cpu_to_le16(params);
4592 pSMB->TotalParameterCount = pSMB->ParameterCount;
4593 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4594 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4595 pSMB->SetupCount = 1;
4596 pSMB->Reserved3 = 0;
4597 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4598 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4599 pSMB->hdr.smb_buf_length += byte_count;
4600 pSMB->ByteCount = cpu_to_le16(byte_count);
4602 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4603 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4605 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4606 } else { /* decode response */
4607 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4609 if (rc || (pSMBr->ByteCount < 13)) {
4610 rc = -EIO; /* bad smb */
4612 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4614 (FILE_SYSTEM_POSIX_INFO
4615 *) (((char *) &pSMBr->hdr.Protocol) +
4618 le32_to_cpu(response_data->BlockSize);
4620 le64_to_cpu(response_data->TotalBlocks);
4622 le64_to_cpu(response_data->BlocksAvail);
4623 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4624 FSData->f_bavail = FSData->f_bfree;
4627 le64_to_cpu(response_data->UserBlocksAvail);
4629 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4631 le64_to_cpu(response_data->TotalFileNodes);
4632 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4634 le64_to_cpu(response_data->FreeFileNodes);
4637 cifs_buf_release(pSMB);
4646 /* We can not use write of zero bytes trick to
4647 set file size due to need for large file support. Also note that
4648 this SetPathInfo is preferred to SetFileInfo based method in next
4649 routine which is only needed to work around a sharing violation bug
4650 in Samba which this routine can run into */
4653 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4654 __u64 size, bool SetAllocation,
4655 const struct nls_table *nls_codepage, int remap)
4657 struct smb_com_transaction2_spi_req *pSMB = NULL;
4658 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4659 struct file_end_of_file_info *parm_data;
4662 int bytes_returned = 0;
4663 __u16 params, byte_count, data_count, param_offset, offset;
4665 cFYI(1, ("In SetEOF"));
4667 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4672 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4674 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4675 PATH_MAX, nls_codepage, remap);
4676 name_len++; /* trailing null */
4678 } else { /* BB improve the check for buffer overruns BB */
4679 name_len = strnlen(fileName, PATH_MAX);
4680 name_len++; /* trailing null */
4681 strncpy(pSMB->FileName, fileName, name_len);
4683 params = 6 + name_len;
4684 data_count = sizeof(struct file_end_of_file_info);
4685 pSMB->MaxParameterCount = cpu_to_le16(2);
4686 pSMB->MaxDataCount = cpu_to_le16(4100);
4687 pSMB->MaxSetupCount = 0;
4691 pSMB->Reserved2 = 0;
4692 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4693 InformationLevel) - 4;
4694 offset = param_offset + params;
4695 if (SetAllocation) {
4696 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4697 pSMB->InformationLevel =
4698 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4700 pSMB->InformationLevel =
4701 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4702 } else /* Set File Size */ {
4703 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4704 pSMB->InformationLevel =
4705 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4707 pSMB->InformationLevel =
4708 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4712 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4714 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4715 pSMB->DataOffset = cpu_to_le16(offset);
4716 pSMB->SetupCount = 1;
4717 pSMB->Reserved3 = 0;
4718 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4719 byte_count = 3 /* pad */ + params + data_count;
4720 pSMB->DataCount = cpu_to_le16(data_count);
4721 pSMB->TotalDataCount = pSMB->DataCount;
4722 pSMB->ParameterCount = cpu_to_le16(params);
4723 pSMB->TotalParameterCount = pSMB->ParameterCount;
4724 pSMB->Reserved4 = 0;
4725 pSMB->hdr.smb_buf_length += byte_count;
4726 parm_data->FileSize = cpu_to_le64(size);
4727 pSMB->ByteCount = cpu_to_le16(byte_count);
4728 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4729 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4731 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4733 cifs_buf_release(pSMB);
4742 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4743 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4745 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4747 struct file_end_of_file_info *parm_data;
4749 __u16 params, param_offset, offset, byte_count, count;
4751 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4753 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4758 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4759 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4762 pSMB->MaxSetupCount = 0;
4766 pSMB->Reserved2 = 0;
4767 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4768 offset = param_offset + params;
4770 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4772 count = sizeof(struct file_end_of_file_info);
4773 pSMB->MaxParameterCount = cpu_to_le16(2);
4774 /* BB find exact max SMB PDU from sess structure BB */
4775 pSMB->MaxDataCount = cpu_to_le16(1000);
4776 pSMB->SetupCount = 1;
4777 pSMB->Reserved3 = 0;
4778 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4779 byte_count = 3 /* pad */ + params + count;
4780 pSMB->DataCount = cpu_to_le16(count);
4781 pSMB->ParameterCount = cpu_to_le16(params);
4782 pSMB->TotalDataCount = pSMB->DataCount;
4783 pSMB->TotalParameterCount = pSMB->ParameterCount;
4784 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4786 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4788 pSMB->DataOffset = cpu_to_le16(offset);
4789 parm_data->FileSize = cpu_to_le64(size);
4791 if (SetAllocation) {
4792 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4793 pSMB->InformationLevel =
4794 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4796 pSMB->InformationLevel =
4797 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4798 } else /* Set File Size */ {
4799 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4800 pSMB->InformationLevel =
4801 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4803 pSMB->InformationLevel =
4804 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4806 pSMB->Reserved4 = 0;
4807 pSMB->hdr.smb_buf_length += byte_count;
4808 pSMB->ByteCount = cpu_to_le16(byte_count);
4809 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4812 ("Send error in SetFileInfo (SetFileSize) = %d",
4816 /* Note: On -EAGAIN error only caller can retry on handle based calls
4817 since file handle passed in no longer valid */
4822 /* Some legacy servers such as NT4 require that the file times be set on
4823 an open handle, rather than by pathname - this is awkward due to
4824 potential access conflicts on the open, but it is unavoidable for these
4825 old servers since the only other choice is to go from 100 nanosecond DCE
4826 time and resort to the original setpathinfo level which takes the ancient
4827 DOS time format with 2 second granularity */
4829 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4830 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4832 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4835 __u16 params, param_offset, offset, byte_count, count;
4837 cFYI(1, ("Set Times (via SetFileInfo)"));
4838 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4843 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4844 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4847 pSMB->MaxSetupCount = 0;
4851 pSMB->Reserved2 = 0;
4852 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4853 offset = param_offset + params;
4855 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4857 count = sizeof(FILE_BASIC_INFO);
4858 pSMB->MaxParameterCount = cpu_to_le16(2);
4859 /* BB find max SMB PDU from sess */
4860 pSMB->MaxDataCount = cpu_to_le16(1000);
4861 pSMB->SetupCount = 1;
4862 pSMB->Reserved3 = 0;
4863 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4864 byte_count = 3 /* pad */ + params + count;
4865 pSMB->DataCount = cpu_to_le16(count);
4866 pSMB->ParameterCount = cpu_to_le16(params);
4867 pSMB->TotalDataCount = pSMB->DataCount;
4868 pSMB->TotalParameterCount = pSMB->ParameterCount;
4869 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4870 pSMB->DataOffset = cpu_to_le16(offset);
4872 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4873 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4875 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4876 pSMB->Reserved4 = 0;
4877 pSMB->hdr.smb_buf_length += byte_count;
4878 pSMB->ByteCount = cpu_to_le16(byte_count);
4879 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4880 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4882 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4884 /* Note: On -EAGAIN error only caller can retry on handle based calls
4885 since file handle passed in no longer valid */
4891 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4892 bool delete_file, __u16 fid, __u32 pid_of_opener)
4894 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4897 __u16 params, param_offset, offset, byte_count, count;
4899 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4900 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4905 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4906 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4909 pSMB->MaxSetupCount = 0;
4913 pSMB->Reserved2 = 0;
4914 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4915 offset = param_offset + params;
4917 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4920 pSMB->MaxParameterCount = cpu_to_le16(2);
4921 /* BB find max SMB PDU from sess */
4922 pSMB->MaxDataCount = cpu_to_le16(1000);
4923 pSMB->SetupCount = 1;
4924 pSMB->Reserved3 = 0;
4925 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4926 byte_count = 3 /* pad */ + params + count;
4927 pSMB->DataCount = cpu_to_le16(count);
4928 pSMB->ParameterCount = cpu_to_le16(params);
4929 pSMB->TotalDataCount = pSMB->DataCount;
4930 pSMB->TotalParameterCount = pSMB->ParameterCount;
4931 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4932 pSMB->DataOffset = cpu_to_le16(offset);
4934 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4935 pSMB->Reserved4 = 0;
4936 pSMB->hdr.smb_buf_length += byte_count;
4937 pSMB->ByteCount = cpu_to_le16(byte_count);
4938 *data_offset = delete_file ? 1 : 0;
4939 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4941 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4947 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4948 const char *fileName, const FILE_BASIC_INFO *data,
4949 const struct nls_table *nls_codepage, int remap)
4951 TRANSACTION2_SPI_REQ *pSMB = NULL;
4952 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4955 int bytes_returned = 0;
4957 __u16 params, param_offset, offset, byte_count, count;
4959 cFYI(1, ("In SetTimes"));
4962 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4967 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4969 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4970 PATH_MAX, nls_codepage, remap);
4971 name_len++; /* trailing null */
4973 } else { /* BB improve the check for buffer overruns BB */
4974 name_len = strnlen(fileName, PATH_MAX);
4975 name_len++; /* trailing null */
4976 strncpy(pSMB->FileName, fileName, name_len);
4979 params = 6 + name_len;
4980 count = sizeof(FILE_BASIC_INFO);
4981 pSMB->MaxParameterCount = cpu_to_le16(2);
4982 /* BB find max SMB PDU from sess structure BB */
4983 pSMB->MaxDataCount = cpu_to_le16(1000);
4984 pSMB->MaxSetupCount = 0;
4988 pSMB->Reserved2 = 0;
4989 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4990 InformationLevel) - 4;
4991 offset = param_offset + params;
4992 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4993 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4994 pSMB->DataOffset = cpu_to_le16(offset);
4995 pSMB->SetupCount = 1;
4996 pSMB->Reserved3 = 0;
4997 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4998 byte_count = 3 /* pad */ + params + count;
5000 pSMB->DataCount = cpu_to_le16(count);
5001 pSMB->ParameterCount = cpu_to_le16(params);
5002 pSMB->TotalDataCount = pSMB->DataCount;
5003 pSMB->TotalParameterCount = pSMB->ParameterCount;
5004 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5005 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5007 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5008 pSMB->Reserved4 = 0;
5009 pSMB->hdr.smb_buf_length += byte_count;
5010 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5011 pSMB->ByteCount = cpu_to_le16(byte_count);
5012 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5013 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5015 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5017 cifs_buf_release(pSMB);
5025 /* Can not be used to set time stamps yet (due to old DOS time format) */
5026 /* Can be used to set attributes */
5027 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5028 handling it anyway and NT4 was what we thought it would be needed for
5029 Do not delete it until we prove whether needed for Win9x though */
5031 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5032 __u16 dos_attrs, const struct nls_table *nls_codepage)
5034 SETATTR_REQ *pSMB = NULL;
5035 SETATTR_RSP *pSMBr = NULL;
5040 cFYI(1, ("In SetAttrLegacy"));
5043 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5048 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5050 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5051 PATH_MAX, nls_codepage);
5052 name_len++; /* trailing null */
5054 } else { /* BB improve the check for buffer overruns BB */
5055 name_len = strnlen(fileName, PATH_MAX);
5056 name_len++; /* trailing null */
5057 strncpy(pSMB->fileName, fileName, name_len);
5059 pSMB->attr = cpu_to_le16(dos_attrs);
5060 pSMB->BufferFormat = 0x04;
5061 pSMB->hdr.smb_buf_length += name_len + 1;
5062 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5063 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5064 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5066 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5068 cifs_buf_release(pSMB);
5071 goto SetAttrLgcyRetry;
5075 #endif /* temporarily unneeded SetAttr legacy function */
5078 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5079 const struct cifs_unix_set_info_args *args,
5080 const struct nls_table *nls_codepage, int remap)
5082 TRANSACTION2_SPI_REQ *pSMB = NULL;
5083 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5086 int bytes_returned = 0;
5087 FILE_UNIX_BASIC_INFO *data_offset;
5088 __u16 params, param_offset, offset, count, byte_count;
5089 __u64 mode = args->mode;
5091 cFYI(1, ("In SetUID/GID/Mode"));
5093 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5098 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5100 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5101 PATH_MAX, nls_codepage, remap);
5102 name_len++; /* trailing null */
5104 } else { /* BB improve the check for buffer overruns BB */
5105 name_len = strnlen(fileName, PATH_MAX);
5106 name_len++; /* trailing null */
5107 strncpy(pSMB->FileName, fileName, name_len);
5110 params = 6 + name_len;
5111 count = sizeof(FILE_UNIX_BASIC_INFO);
5112 pSMB->MaxParameterCount = cpu_to_le16(2);
5113 /* BB find max SMB PDU from sess structure BB */
5114 pSMB->MaxDataCount = cpu_to_le16(1000);
5115 pSMB->MaxSetupCount = 0;
5119 pSMB->Reserved2 = 0;
5120 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5121 InformationLevel) - 4;
5122 offset = param_offset + params;
5124 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5126 memset(data_offset, 0, count);
5127 pSMB->DataOffset = cpu_to_le16(offset);
5128 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5129 pSMB->SetupCount = 1;
5130 pSMB->Reserved3 = 0;
5131 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5132 byte_count = 3 /* pad */ + params + count;
5133 pSMB->ParameterCount = cpu_to_le16(params);
5134 pSMB->DataCount = cpu_to_le16(count);
5135 pSMB->TotalParameterCount = pSMB->ParameterCount;
5136 pSMB->TotalDataCount = pSMB->DataCount;
5137 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5138 pSMB->Reserved4 = 0;
5139 pSMB->hdr.smb_buf_length += byte_count;
5140 /* Samba server ignores set of file size to zero due to bugs in some
5141 older clients, but we should be precise - we use SetFileSize to
5142 set file size and do not want to truncate file size to zero
5143 accidently as happened on one Samba server beta by putting
5144 zero instead of -1 here */
5145 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5146 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5147 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5148 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5149 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5150 data_offset->Uid = cpu_to_le64(args->uid);
5151 data_offset->Gid = cpu_to_le64(args->gid);
5152 /* better to leave device as zero when it is */
5153 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5154 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5155 data_offset->Permissions = cpu_to_le64(mode);
5158 data_offset->Type = cpu_to_le32(UNIX_FILE);
5159 else if (S_ISDIR(mode))
5160 data_offset->Type = cpu_to_le32(UNIX_DIR);
5161 else if (S_ISLNK(mode))
5162 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5163 else if (S_ISCHR(mode))
5164 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5165 else if (S_ISBLK(mode))
5166 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5167 else if (S_ISFIFO(mode))
5168 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5169 else if (S_ISSOCK(mode))
5170 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5173 pSMB->ByteCount = cpu_to_le16(byte_count);
5174 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5175 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5177 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5179 cifs_buf_release(pSMB);
5185 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5186 const int notify_subdirs, const __u16 netfid,
5187 __u32 filter, struct file *pfile, int multishot,
5188 const struct nls_table *nls_codepage)
5191 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5192 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5193 struct dir_notify_req *dnotify_req;
5196 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5197 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5202 pSMB->TotalParameterCount = 0 ;
5203 pSMB->TotalDataCount = 0;
5204 pSMB->MaxParameterCount = cpu_to_le32(2);
5205 /* BB find exact data count max from sess structure BB */
5206 pSMB->MaxDataCount = 0; /* same in little endian or be */
5207 /* BB VERIFY verify which is correct for above BB */
5208 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5209 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5211 pSMB->MaxSetupCount = 4;
5213 pSMB->ParameterOffset = 0;
5214 pSMB->DataCount = 0;
5215 pSMB->DataOffset = 0;
5216 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5217 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5218 pSMB->ParameterCount = pSMB->TotalParameterCount;
5220 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5221 pSMB->Reserved2 = 0;
5222 pSMB->CompletionFilter = cpu_to_le32(filter);
5223 pSMB->Fid = netfid; /* file handle always le */
5224 pSMB->ByteCount = 0;
5226 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5227 (struct smb_hdr *)pSMBr, &bytes_returned,
5230 cFYI(1, ("Error in Notify = %d", rc));
5232 /* Add file to outstanding requests */
5233 /* BB change to kmem cache alloc */
5234 dnotify_req = kmalloc(
5235 sizeof(struct dir_notify_req),
5238 dnotify_req->Pid = pSMB->hdr.Pid;
5239 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5240 dnotify_req->Mid = pSMB->hdr.Mid;
5241 dnotify_req->Tid = pSMB->hdr.Tid;
5242 dnotify_req->Uid = pSMB->hdr.Uid;
5243 dnotify_req->netfid = netfid;
5244 dnotify_req->pfile = pfile;
5245 dnotify_req->filter = filter;
5246 dnotify_req->multishot = multishot;
5247 spin_lock(&GlobalMid_Lock);
5248 list_add_tail(&dnotify_req->lhead,
5249 &GlobalDnotifyReqList);
5250 spin_unlock(&GlobalMid_Lock);
5254 cifs_buf_release(pSMB);
5257 #ifdef CONFIG_CIFS_XATTR
5259 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5260 const unsigned char *searchName,
5261 char *EAData, size_t buf_size,
5262 const struct nls_table *nls_codepage, int remap)
5264 /* BB assumes one setup word */
5265 TRANSACTION2_QPI_REQ *pSMB = NULL;
5266 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5270 struct fea *temp_fea;
5272 __u16 params, byte_count;
5274 cFYI(1, ("In Query All EAs path %s", searchName));
5276 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5281 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5283 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5284 PATH_MAX, nls_codepage, remap);
5285 name_len++; /* trailing null */
5287 } else { /* BB improve the check for buffer overruns BB */
5288 name_len = strnlen(searchName, PATH_MAX);
5289 name_len++; /* trailing null */
5290 strncpy(pSMB->FileName, searchName, name_len);
5293 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5294 pSMB->TotalDataCount = 0;
5295 pSMB->MaxParameterCount = cpu_to_le16(2);
5296 /* BB find exact max SMB PDU from sess structure BB */
5297 pSMB->MaxDataCount = cpu_to_le16(4000);
5298 pSMB->MaxSetupCount = 0;
5302 pSMB->Reserved2 = 0;
5303 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5304 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5305 pSMB->DataCount = 0;
5306 pSMB->DataOffset = 0;
5307 pSMB->SetupCount = 1;
5308 pSMB->Reserved3 = 0;
5309 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5310 byte_count = params + 1 /* pad */ ;
5311 pSMB->TotalParameterCount = cpu_to_le16(params);
5312 pSMB->ParameterCount = pSMB->TotalParameterCount;
5313 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5314 pSMB->Reserved4 = 0;
5315 pSMB->hdr.smb_buf_length += byte_count;
5316 pSMB->ByteCount = cpu_to_le16(byte_count);
5318 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5319 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5321 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5322 } else { /* decode response */
5323 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5325 /* BB also check enough total bytes returned */
5326 /* BB we need to improve the validity checking
5327 of these trans2 responses */
5328 if (rc || (pSMBr->ByteCount < 4))
5329 rc = -EIO; /* bad smb */
5330 /* else if (pFindData){
5331 memcpy((char *) pFindData,
5332 (char *) &pSMBr->hdr.Protocol +
5335 /* check that length of list is not more than bcc */
5336 /* check that each entry does not go beyond length
5338 /* check that each element of each entry does not
5339 go beyond end of list */
5340 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5341 struct fealist *ea_response_data;
5343 /* validate_trans2_offsets() */
5344 /* BB check if start of smb + data_offset > &bcc+ bcc */
5345 ea_response_data = (struct fealist *)
5346 (((char *) &pSMBr->hdr.Protocol) +
5348 name_len = le32_to_cpu(ea_response_data->list_len);
5349 cFYI(1, ("ea length %d", name_len));
5350 if (name_len <= 8) {
5351 /* returned EA size zeroed at top of function */
5352 cFYI(1, ("empty EA list returned from server"));
5354 /* account for ea list len */
5356 temp_fea = ea_response_data->list;
5357 temp_ptr = (char *)temp_fea;
5358 while (name_len > 0) {
5362 rc += temp_fea->name_len;
5363 /* account for prefix user. and trailing null */
5365 if (rc < (int)buf_size) {
5366 memcpy(EAData, "user.", 5);
5368 memcpy(EAData, temp_ptr,
5369 temp_fea->name_len);
5370 EAData += temp_fea->name_len;
5371 /* null terminate name */
5373 EAData = EAData + 1;
5374 } else if (buf_size == 0) {
5375 /* skip copy - calc size only */
5377 /* stop before overrun buffer */
5381 name_len -= temp_fea->name_len;
5382 temp_ptr += temp_fea->name_len;
5383 /* account for trailing null */
5387 le16_to_cpu(temp_fea->value_len);
5388 name_len -= value_len;
5389 temp_ptr += value_len;
5390 /* BB check that temp_ptr is still
5393 /* no trailing null to account for
5395 /* go on to next EA */
5396 temp_fea = (struct fea *)temp_ptr;
5401 cifs_buf_release(pSMB);
5408 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5409 const unsigned char *searchName, const unsigned char *ea_name,
5410 unsigned char *ea_value, size_t buf_size,
5411 const struct nls_table *nls_codepage, int remap)
5413 TRANSACTION2_QPI_REQ *pSMB = NULL;
5414 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5418 struct fea *temp_fea;
5420 __u16 params, byte_count;
5422 cFYI(1, ("In Query EA path %s", searchName));
5424 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5429 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5431 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5432 PATH_MAX, nls_codepage, remap);
5433 name_len++; /* trailing null */
5435 } else { /* BB improve the check for buffer overruns BB */
5436 name_len = strnlen(searchName, PATH_MAX);
5437 name_len++; /* trailing null */
5438 strncpy(pSMB->FileName, searchName, name_len);
5441 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5442 pSMB->TotalDataCount = 0;
5443 pSMB->MaxParameterCount = cpu_to_le16(2);
5444 /* BB find exact max SMB PDU from sess structure BB */
5445 pSMB->MaxDataCount = cpu_to_le16(4000);
5446 pSMB->MaxSetupCount = 0;
5450 pSMB->Reserved2 = 0;
5451 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5452 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5453 pSMB->DataCount = 0;
5454 pSMB->DataOffset = 0;
5455 pSMB->SetupCount = 1;
5456 pSMB->Reserved3 = 0;
5457 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5458 byte_count = params + 1 /* pad */ ;
5459 pSMB->TotalParameterCount = cpu_to_le16(params);
5460 pSMB->ParameterCount = pSMB->TotalParameterCount;
5461 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5462 pSMB->Reserved4 = 0;
5463 pSMB->hdr.smb_buf_length += byte_count;
5464 pSMB->ByteCount = cpu_to_le16(byte_count);
5466 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5467 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5469 cFYI(1, ("Send error in Query EA = %d", rc));
5470 } else { /* decode response */
5471 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5473 /* BB also check enough total bytes returned */
5474 /* BB we need to improve the validity checking
5475 of these trans2 responses */
5476 if (rc || (pSMBr->ByteCount < 4))
5477 rc = -EIO; /* bad smb */
5478 /* else if (pFindData){
5479 memcpy((char *) pFindData,
5480 (char *) &pSMBr->hdr.Protocol +
5483 /* check that length of list is not more than bcc */
5484 /* check that each entry does not go beyond length
5486 /* check that each element of each entry does not
5487 go beyond end of list */
5488 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5489 struct fealist *ea_response_data;
5491 /* validate_trans2_offsets() */
5492 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5493 ea_response_data = (struct fealist *)
5494 (((char *) &pSMBr->hdr.Protocol) +
5496 name_len = le32_to_cpu(ea_response_data->list_len);
5497 cFYI(1, ("ea length %d", name_len));
5498 if (name_len <= 8) {
5499 /* returned EA size zeroed at top of function */
5500 cFYI(1, ("empty EA list returned from server"));
5502 /* account for ea list len */
5504 temp_fea = ea_response_data->list;
5505 temp_ptr = (char *)temp_fea;
5506 /* loop through checking if we have a matching
5507 name and then return the associated value */
5508 while (name_len > 0) {
5513 le16_to_cpu(temp_fea->value_len);
5514 /* BB validate that value_len falls within SMB,
5515 even though maximum for name_len is 255 */
5516 if (memcmp(temp_fea->name, ea_name,
5517 temp_fea->name_len) == 0) {
5520 /* account for prefix user. and trailing null */
5521 if (rc <= (int)buf_size) {
5523 temp_fea->name+temp_fea->name_len+1,
5525 /* ea values, unlike ea
5528 } else if (buf_size == 0) {
5529 /* skip copy - calc size only */
5531 /* stop before overrun buffer */
5536 name_len -= temp_fea->name_len;
5537 temp_ptr += temp_fea->name_len;
5538 /* account for trailing null */
5541 name_len -= value_len;
5542 temp_ptr += value_len;
5543 /* No trailing null to account for in
5544 value_len. Go on to next EA */
5545 temp_fea = (struct fea *)temp_ptr;
5550 cifs_buf_release(pSMB);
5558 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5559 const char *ea_name, const void *ea_value,
5560 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5563 struct smb_com_transaction2_spi_req *pSMB = NULL;
5564 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5565 struct fealist *parm_data;
5568 int bytes_returned = 0;
5569 __u16 params, param_offset, byte_count, offset, count;
5571 cFYI(1, ("In SetEA"));
5573 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5578 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5580 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5581 PATH_MAX, nls_codepage, remap);
5582 name_len++; /* trailing null */
5584 } else { /* BB improve the check for buffer overruns BB */
5585 name_len = strnlen(fileName, PATH_MAX);
5586 name_len++; /* trailing null */
5587 strncpy(pSMB->FileName, fileName, name_len);
5590 params = 6 + name_len;
5592 /* done calculating parms using name_len of file name,
5593 now use name_len to calculate length of ea name
5594 we are going to create in the inode xattrs */
5595 if (ea_name == NULL)
5598 name_len = strnlen(ea_name, 255);
5600 count = sizeof(*parm_data) + ea_value_len + name_len;
5601 pSMB->MaxParameterCount = cpu_to_le16(2);
5602 /* BB find max SMB PDU from sess */
5603 pSMB->MaxDataCount = cpu_to_le16(1000);
5604 pSMB->MaxSetupCount = 0;
5608 pSMB->Reserved2 = 0;
5609 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5610 InformationLevel) - 4;
5611 offset = param_offset + params;
5612 pSMB->InformationLevel =
5613 cpu_to_le16(SMB_SET_FILE_EA);
5616 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5618 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5619 pSMB->DataOffset = cpu_to_le16(offset);
5620 pSMB->SetupCount = 1;
5621 pSMB->Reserved3 = 0;
5622 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5623 byte_count = 3 /* pad */ + params + count;
5624 pSMB->DataCount = cpu_to_le16(count);
5625 parm_data->list_len = cpu_to_le32(count);
5626 parm_data->list[0].EA_flags = 0;
5627 /* we checked above that name len is less than 255 */
5628 parm_data->list[0].name_len = (__u8)name_len;
5629 /* EA names are always ASCII */
5631 strncpy(parm_data->list[0].name, ea_name, name_len);
5632 parm_data->list[0].name[name_len] = 0;
5633 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5634 /* caller ensures that ea_value_len is less than 64K but
5635 we need to ensure that it fits within the smb */
5637 /*BB add length check to see if it would fit in
5638 negotiated SMB buffer size BB */
5639 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5641 memcpy(parm_data->list[0].name+name_len+1,
5642 ea_value, ea_value_len);
5644 pSMB->TotalDataCount = pSMB->DataCount;
5645 pSMB->ParameterCount = cpu_to_le16(params);
5646 pSMB->TotalParameterCount = pSMB->ParameterCount;
5647 pSMB->Reserved4 = 0;
5648 pSMB->hdr.smb_buf_length += byte_count;
5649 pSMB->ByteCount = cpu_to_le16(byte_count);
5650 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5651 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5653 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5655 cifs_buf_release(pSMB);