4 * Copyright (C) International Business Machines Corp., 2002,2007
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 */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head *tmp;
91 struct list_head *tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
98 open_file->invalidHandle = TRUE;
100 write_unlock(&GlobalSMBSeslock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* If the return code is zero, this function must fill in request_buf pointer */
107 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
108 void **request_buf /* returned */)
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 */
142 if ((tcon->retry == FALSE) ||
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->status == CifsNeedReconnect)
159 rc = cifs_setup_session(0, tcon->ses,
161 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
162 mark_open_files_invalid(tcon);
163 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
165 up(&tcon->ses->sesSem);
166 /* tell server which Unix caps we support */
167 if (tcon->ses->capabilities & CAP_UNIX)
168 reset_cifs_unix_caps(0 /* no xid */,
170 NULL /* we do not know sb */,
171 NULL /* no vol info */);
172 /* BB FIXME add code to check if wsize needs
173 update due to negotiated smb buffer size
176 atomic_inc(&tconInfoReconnectCount);
178 cFYI(1, ("reconnect tcon rc = %d", rc));
179 /* Removed call to reopen open files here.
180 It is safer (and faster) to reopen files
181 one at a time as needed in read and write */
183 /* Check if handle based operation so we
184 know whether we can continue or not without
185 returning to caller to reset file handle */
186 switch (smb_command) {
187 case SMB_COM_READ_ANDX:
188 case SMB_COM_WRITE_ANDX:
190 case SMB_COM_FIND_CLOSE2:
191 case SMB_COM_LOCKING_ANDX: {
192 unload_nls(nls_codepage);
197 up(&tcon->ses->sesSem);
199 unload_nls(nls_codepage);
208 *request_buf = cifs_small_buf_get();
209 if (*request_buf == NULL) {
210 /* BB should we add a retry in here if not a writepage? */
214 header_assemble((struct smb_hdr *) *request_buf, smb_command,
218 cifs_stats_inc(&tcon->num_smbs_sent);
224 small_smb_init_no_tc(const int smb_command, const int wct,
225 struct cifsSesInfo *ses, void **request_buf)
228 struct smb_hdr *buffer;
230 rc = small_smb_init(smb_command, wct, NULL, request_buf);
234 buffer = (struct smb_hdr *)*request_buf;
235 buffer->Mid = GetNextMid(ses->server);
236 if (ses->capabilities & CAP_UNICODE)
237 buffer->Flags2 |= SMBFLG2_UNICODE;
238 if (ses->capabilities & CAP_STATUS32)
239 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
241 /* uid, tid can stay at zero as set in header assemble */
243 /* BB add support for turning on the signing when
244 this function is used after 1st of session setup requests */
249 /* If the return code is zero, this function must fill in request_buf pointer */
251 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
252 void **request_buf /* returned */ ,
253 void **response_buf /* returned */ )
257 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
258 check for tcp and smb session status done differently
259 for those three - in the calling routine */
261 if (tcon->tidStatus == CifsExiting) {
262 /* only tree disconnect, open, and write,
263 (and ulogoff which does not have tcon)
264 are allowed as we start force umount */
265 if ((smb_command != SMB_COM_WRITE_ANDX) &&
266 (smb_command != SMB_COM_OPEN_ANDX) &&
267 (smb_command != SMB_COM_TREE_DISCONNECT)) {
268 cFYI(1, ("can not send cmd %d while umounting",
274 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
275 (tcon->ses->server)) {
276 struct nls_table *nls_codepage;
277 /* Give Demultiplex thread up to 10 seconds to
278 reconnect, should be greater than cifs socket
279 timeout which is 7 seconds */
280 while (tcon->ses->server->tcpStatus ==
282 wait_event_interruptible_timeout(tcon->ses->server->response_q,
283 (tcon->ses->server->tcpStatus ==
285 if (tcon->ses->server->tcpStatus ==
287 /* on "soft" mounts we wait once */
288 if ((tcon->retry == FALSE) ||
289 (tcon->ses->status == CifsExiting)) {
290 cFYI(1, ("gave up waiting on "
291 "reconnect in smb_init"));
293 } /* else "hard" mount - keep retrying
294 until process is killed or server
296 } else /* TCP session is reestablished now */
299 nls_codepage = load_nls_default();
300 /* need to prevent multiple threads trying to
301 simultaneously reconnect the same SMB session */
302 down(&tcon->ses->sesSem);
303 if (tcon->ses->status == CifsNeedReconnect)
304 rc = cifs_setup_session(0, tcon->ses,
306 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
307 mark_open_files_invalid(tcon);
308 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
310 up(&tcon->ses->sesSem);
311 /* tell server which Unix caps we support */
312 if (tcon->ses->capabilities & CAP_UNIX)
313 reset_cifs_unix_caps(0 /* no xid */,
315 NULL /* do not know sb */,
316 NULL /* no vol info */);
317 /* BB FIXME add code to check if wsize needs
318 update due to negotiated smb buffer size
321 atomic_inc(&tconInfoReconnectCount);
323 cFYI(1, ("reconnect tcon rc = %d", rc));
324 /* Removed call to reopen open files here.
325 It is safer (and faster) to reopen files
326 one at a time as needed in read and write */
328 /* Check if handle based operation so we
329 know whether we can continue or not without
330 returning to caller to reset file handle */
331 switch (smb_command) {
332 case SMB_COM_READ_ANDX:
333 case SMB_COM_WRITE_ANDX:
335 case SMB_COM_FIND_CLOSE2:
336 case SMB_COM_LOCKING_ANDX: {
337 unload_nls(nls_codepage);
342 up(&tcon->ses->sesSem);
344 unload_nls(nls_codepage);
353 *request_buf = cifs_buf_get();
354 if (*request_buf == NULL) {
355 /* BB should we add a retry in here if not a writepage? */
358 /* Although the original thought was we needed the response buf for */
359 /* potential retries of smb operations it turns out we can determine */
360 /* from the mid flags when the request buffer can be resent without */
361 /* having to use a second distinct buffer for the response */
363 *response_buf = *request_buf;
365 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
369 cifs_stats_inc(&tcon->num_smbs_sent);
374 static int validate_t2(struct smb_t2_rsp *pSMB)
380 /* check for plausible wct, bcc and t2 data and parm sizes */
381 /* check for parm and data offset going beyond end of smb */
382 if (pSMB->hdr.WordCount >= 10) {
383 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
384 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
385 /* check that bcc is at least as big as parms + data */
386 /* check that bcc is less than negotiated smb buffer */
387 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
388 if (total_size < 512) {
390 le16_to_cpu(pSMB->t2_rsp.DataCount);
391 /* BCC le converted in SendReceive */
392 pBCC = (pSMB->hdr.WordCount * 2) +
393 sizeof(struct smb_hdr) +
395 if ((total_size <= (*(u16 *)pBCC)) &&
397 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
403 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
404 sizeof(struct smb_t2_rsp) + 16);
408 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
411 NEGOTIATE_RSP *pSMBr;
415 struct TCP_Server_Info *server;
417 unsigned int secFlags;
421 server = ses->server;
426 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
427 (void **) &pSMB, (void **) &pSMBr);
431 /* if any of auth flags (ie not sign or seal) are overriden use them */
432 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
433 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
434 else /* if override flags set only sign/seal OR them with global auth */
435 secFlags = extended_security | ses->overrideSecFlg;
437 cFYI(1, ("secFlags 0x%x", secFlags));
439 pSMB->hdr.Mid = GetNextMid(server);
440 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
442 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
443 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
444 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
445 cFYI(1, ("Kerberos only mechanism, enable extended security"));
446 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
450 for (i = 0; i < CIFS_NUM_PROT; i++) {
451 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
452 count += strlen(protocols[i].name) + 1;
453 /* null at end of source and target buffers anyway */
455 pSMB->hdr.smb_buf_length += count;
456 pSMB->ByteCount = cpu_to_le16(count);
458 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
459 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
463 dialect = le16_to_cpu(pSMBr->DialectIndex);
464 cFYI(1, ("Dialect: %d", dialect));
465 /* Check wct = 1 error case */
466 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
467 /* core returns wct = 1, but we do not ask for core - otherwise
468 small wct just comes when dialect index is -1 indicating we
469 could not negotiate a common dialect */
472 #ifdef CONFIG_CIFS_WEAK_PW_HASH
473 } else if ((pSMBr->hdr.WordCount == 13)
474 && ((dialect == LANMAN_PROT)
475 || (dialect == LANMAN2_PROT))) {
477 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
479 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
480 (secFlags & CIFSSEC_MAY_PLNTXT))
481 server->secType = LANMAN;
483 cERROR(1, ("mount failed weak security disabled"
484 " in /proc/fs/cifs/SecurityFlags"));
488 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
489 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
490 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
491 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
492 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
493 /* even though we do not use raw we might as well set this
494 accurately, in case we ever find a need for it */
495 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
496 server->maxRw = 0xFF00;
497 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
499 server->maxRw = 0;/* we do not need to use raw anyway */
500 server->capabilities = CAP_MPX_MODE;
502 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
504 /* OS/2 often does not set timezone therefore
505 * we must use server time to calc time zone.
506 * Could deviate slightly from the right zone.
507 * Smallest defined timezone difference is 15 minutes
508 * (i.e. Nepal). Rounding up/down is done to match
511 int val, seconds, remain, result;
512 struct timespec ts, utc;
514 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
515 le16_to_cpu(rsp->SrvTime.Time));
516 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
517 (int)ts.tv_sec, (int)utc.tv_sec,
518 (int)(utc.tv_sec - ts.tv_sec)));
519 val = (int)(utc.tv_sec - ts.tv_sec);
521 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
522 remain = seconds % MIN_TZ_ADJ;
523 if (remain >= (MIN_TZ_ADJ / 2))
524 result += MIN_TZ_ADJ;
527 server->timeAdj = result;
529 server->timeAdj = (int)tmp;
530 server->timeAdj *= 60; /* also in seconds */
532 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
535 /* BB get server time for time conversions and add
536 code to use it and timezone since this is not UTC */
538 if (rsp->EncryptionKeyLength ==
539 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
540 memcpy(server->cryptKey, rsp->EncryptionKey,
541 CIFS_CRYPTO_KEY_SIZE);
542 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
543 rc = -EIO; /* need cryptkey unless plain text */
547 cFYI(1, ("LANMAN negotiated"));
548 /* we will not end up setting signing flags - as no signing
549 was in LANMAN and server did not return the flags on */
551 #else /* weak security disabled */
552 } else if (pSMBr->hdr.WordCount == 13) {
553 cERROR(1, ("mount failed, cifs module not built "
554 "with CIFS_WEAK_PW_HASH support"));
556 #endif /* WEAK_PW_HASH */
558 } else if (pSMBr->hdr.WordCount != 17) {
563 /* else wct == 17 NTLM */
564 server->secMode = pSMBr->SecurityMode;
565 if ((server->secMode & SECMODE_USER) == 0)
566 cFYI(1, ("share mode security"));
568 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
569 #ifdef CONFIG_CIFS_WEAK_PW_HASH
570 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
571 #endif /* CIFS_WEAK_PW_HASH */
572 cERROR(1, ("Server requests plain text password"
573 " but client support disabled"));
575 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
576 server->secType = NTLMv2;
577 else if (secFlags & CIFSSEC_MAY_NTLM)
578 server->secType = NTLM;
579 else if (secFlags & CIFSSEC_MAY_NTLMV2)
580 server->secType = NTLMv2;
581 else if (secFlags & CIFSSEC_MAY_KRB5)
582 server->secType = Kerberos;
583 else if (secFlags & CIFSSEC_MAY_LANMAN)
584 server->secType = LANMAN;
585 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
586 else if (secFlags & CIFSSEC_MAY_PLNTXT)
591 cERROR(1, ("Invalid security type"));
594 /* else ... any others ...? */
596 /* one byte, so no need to convert this or EncryptionKeyLen from
598 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
599 /* probably no need to store and check maxvcs */
600 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
601 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
602 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
603 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
604 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
605 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
606 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
607 server->timeAdj *= 60;
608 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
609 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
610 CIFS_CRYPTO_KEY_SIZE);
611 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
612 && (pSMBr->EncryptionKeyLength == 0)) {
613 /* decode security blob */
614 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
615 rc = -EIO; /* no crypt key only if plain text pwd */
619 /* BB might be helpful to save off the domain of server here */
621 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
622 (server->capabilities & CAP_EXTENDED_SECURITY)) {
623 count = pSMBr->ByteCount;
629 if (server->socketUseCount.counter > 1) {
630 if (memcmp(server->server_GUID,
631 pSMBr->u.extended_response.
633 cFYI(1, ("server UID changed"));
634 memcpy(server->server_GUID,
635 pSMBr->u.extended_response.GUID,
639 memcpy(server->server_GUID,
640 pSMBr->u.extended_response.GUID, 16);
643 server->secType = RawNTLMSSP;
645 rc = decode_negTokenInit(pSMBr->u.extended_response.
650 /* BB Need to fill struct for sessetup here */
657 server->capabilities &= ~CAP_EXTENDED_SECURITY;
659 #ifdef CONFIG_CIFS_WEAK_PW_HASH
662 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
663 /* MUST_SIGN already includes the MAY_SIGN FLAG
664 so if this is zero it means that signing is disabled */
665 cFYI(1, ("Signing disabled"));
666 if (server->secMode & SECMODE_SIGN_REQUIRED) {
667 cERROR(1, ("Server requires "
668 "packet signing to be enabled in "
669 "/proc/fs/cifs/SecurityFlags."));
673 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
674 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
675 /* signing required */
676 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
677 if ((server->secMode &
678 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
680 ("signing required but server lacks support"));
683 server->secMode |= SECMODE_SIGN_REQUIRED;
685 /* signing optional ie CIFSSEC_MAY_SIGN */
686 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
688 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
692 cifs_buf_release(pSMB);
694 cFYI(1, ("negprot rc %d", rc));
699 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
701 struct smb_hdr *smb_buffer;
702 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
706 cFYI(1, ("In tree disconnect"));
708 * If last user of the connection and
709 * connection alive - disconnect it
710 * If this is the last connection on the server session disconnect it
711 * (and inside session disconnect we should check if tcp socket needs
712 * to be freed and kernel thread woken up).
715 down(&tcon->tconSem);
719 atomic_dec(&tcon->useCount);
720 if (atomic_read(&tcon->useCount) > 0) {
725 /* No need to return error on this operation if tid invalidated and
726 closed on server already e.g. due to tcp session crashing */
727 if (tcon->tidStatus == CifsNeedReconnect) {
732 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
736 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
737 (void **)&smb_buffer);
742 smb_buffer_response = smb_buffer; /* BB removeme BB */
744 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
747 cFYI(1, ("Tree disconnect failed %d", rc));
750 cifs_small_buf_release(smb_buffer);
753 /* No need to return error on this operation if tid invalidated and
754 closed on server already e.g. due to tcp session crashing */
762 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
764 struct smb_hdr *smb_buffer_response;
765 LOGOFF_ANDX_REQ *pSMB;
769 cFYI(1, ("In SMBLogoff for session disconnect"));
775 atomic_dec(&ses->inUse);
776 if (atomic_read(&ses->inUse) > 0) {
780 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
786 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
789 pSMB->hdr.Mid = GetNextMid(ses->server);
791 if (ses->server->secMode &
792 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
793 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
796 pSMB->hdr.Uid = ses->Suid;
798 pSMB->AndXCommand = 0xFF;
799 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
800 smb_buffer_response, &length, 0);
802 atomic_dec(&ses->server->socketUseCount);
803 if (atomic_read(&ses->server->socketUseCount) == 0) {
804 spin_lock(&GlobalMid_Lock);
805 ses->server->tcpStatus = CifsExiting;
806 spin_unlock(&GlobalMid_Lock);
811 cifs_small_buf_release(pSMB);
813 /* if session dead then we do not need to do ulogoff,
814 since server closed smb session, no sense reporting
822 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
823 __u16 type, const struct nls_table *nls_codepage, int remap)
825 TRANSACTION2_SPI_REQ *pSMB = NULL;
826 TRANSACTION2_SPI_RSP *pSMBr = NULL;
827 struct unlink_psx_rq *pRqD;
830 int bytes_returned = 0;
831 __u16 params, param_offset, offset, byte_count;
833 cFYI(1, ("In POSIX delete"));
835 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
840 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
842 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
843 PATH_MAX, nls_codepage, remap);
844 name_len++; /* trailing null */
846 } else { /* BB add path length overrun check */
847 name_len = strnlen(fileName, PATH_MAX);
848 name_len++; /* trailing null */
849 strncpy(pSMB->FileName, fileName, name_len);
852 params = 6 + name_len;
853 pSMB->MaxParameterCount = cpu_to_le16(2);
854 pSMB->MaxDataCount = 0; /* BB double check this with jra */
855 pSMB->MaxSetupCount = 0;
860 param_offset = offsetof(struct smb_com_transaction2_spi_req,
861 InformationLevel) - 4;
862 offset = param_offset + params;
864 /* Setup pointer to Request Data (inode type) */
865 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
866 pRqD->type = cpu_to_le16(type);
867 pSMB->ParameterOffset = cpu_to_le16(param_offset);
868 pSMB->DataOffset = cpu_to_le16(offset);
869 pSMB->SetupCount = 1;
871 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
872 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
874 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
875 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
876 pSMB->ParameterCount = cpu_to_le16(params);
877 pSMB->TotalParameterCount = pSMB->ParameterCount;
878 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
880 pSMB->hdr.smb_buf_length += byte_count;
881 pSMB->ByteCount = cpu_to_le16(byte_count);
882 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
883 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
885 cFYI(1, ("Posix delete returned %d", rc));
887 cifs_buf_release(pSMB);
889 cifs_stats_inc(&tcon->num_deletes);
898 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
899 const struct nls_table *nls_codepage, int remap)
901 DELETE_FILE_REQ *pSMB = NULL;
902 DELETE_FILE_RSP *pSMBr = NULL;
908 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
913 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
915 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
916 PATH_MAX, nls_codepage, remap);
917 name_len++; /* trailing null */
919 } else { /* BB improve check for buffer overruns BB */
920 name_len = strnlen(fileName, PATH_MAX);
921 name_len++; /* trailing null */
922 strncpy(pSMB->fileName, fileName, name_len);
924 pSMB->SearchAttributes =
925 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
926 pSMB->BufferFormat = 0x04;
927 pSMB->hdr.smb_buf_length += name_len + 1;
928 pSMB->ByteCount = cpu_to_le16(name_len + 1);
929 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
930 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
931 cifs_stats_inc(&tcon->num_deletes);
933 cFYI(1, ("Error in RMFile = %d", rc));
936 cifs_buf_release(pSMB);
944 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
945 const struct nls_table *nls_codepage, int remap)
947 DELETE_DIRECTORY_REQ *pSMB = NULL;
948 DELETE_DIRECTORY_RSP *pSMBr = NULL;
953 cFYI(1, ("In CIFSSMBRmDir"));
955 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
961 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
962 PATH_MAX, nls_codepage, remap);
963 name_len++; /* trailing null */
965 } else { /* BB improve check for buffer overruns BB */
966 name_len = strnlen(dirName, PATH_MAX);
967 name_len++; /* trailing null */
968 strncpy(pSMB->DirName, dirName, name_len);
971 pSMB->BufferFormat = 0x04;
972 pSMB->hdr.smb_buf_length += name_len + 1;
973 pSMB->ByteCount = cpu_to_le16(name_len + 1);
974 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
976 cifs_stats_inc(&tcon->num_rmdirs);
978 cFYI(1, ("Error in RMDir = %d", rc));
981 cifs_buf_release(pSMB);
988 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
989 const char *name, const struct nls_table *nls_codepage, int remap)
992 CREATE_DIRECTORY_REQ *pSMB = NULL;
993 CREATE_DIRECTORY_RSP *pSMBr = NULL;
997 cFYI(1, ("In CIFSSMBMkDir"));
999 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1004 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1005 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1006 PATH_MAX, nls_codepage, remap);
1007 name_len++; /* trailing null */
1009 } else { /* BB improve check for buffer overruns BB */
1010 name_len = strnlen(name, PATH_MAX);
1011 name_len++; /* trailing null */
1012 strncpy(pSMB->DirName, name, name_len);
1015 pSMB->BufferFormat = 0x04;
1016 pSMB->hdr.smb_buf_length += name_len + 1;
1017 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1018 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1019 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1020 cifs_stats_inc(&tcon->num_mkdirs);
1022 cFYI(1, ("Error in Mkdir = %d", rc));
1025 cifs_buf_release(pSMB);
1032 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1033 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1034 __u32 *pOplock, const char *name,
1035 const struct nls_table *nls_codepage, int remap)
1037 TRANSACTION2_SPI_REQ *pSMB = NULL;
1038 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1041 int bytes_returned = 0;
1042 __u16 params, param_offset, offset, byte_count, count;
1043 OPEN_PSX_REQ * pdata;
1044 OPEN_PSX_RSP * psx_rsp;
1046 cFYI(1, ("In POSIX Create"));
1048 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1053 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1055 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1056 PATH_MAX, nls_codepage, remap);
1057 name_len++; /* trailing null */
1059 } else { /* BB improve the check for buffer overruns BB */
1060 name_len = strnlen(name, PATH_MAX);
1061 name_len++; /* trailing null */
1062 strncpy(pSMB->FileName, name, name_len);
1065 params = 6 + name_len;
1066 count = sizeof(OPEN_PSX_REQ);
1067 pSMB->MaxParameterCount = cpu_to_le16(2);
1068 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1069 pSMB->MaxSetupCount = 0;
1073 pSMB->Reserved2 = 0;
1074 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1075 InformationLevel) - 4;
1076 offset = param_offset + params;
1077 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1078 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1079 pdata->Permissions = cpu_to_le64(mode);
1080 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1081 pdata->OpenFlags = cpu_to_le32(*pOplock);
1082 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1083 pSMB->DataOffset = cpu_to_le16(offset);
1084 pSMB->SetupCount = 1;
1085 pSMB->Reserved3 = 0;
1086 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1087 byte_count = 3 /* pad */ + params + count;
1089 pSMB->DataCount = cpu_to_le16(count);
1090 pSMB->ParameterCount = cpu_to_le16(params);
1091 pSMB->TotalDataCount = pSMB->DataCount;
1092 pSMB->TotalParameterCount = pSMB->ParameterCount;
1093 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1094 pSMB->Reserved4 = 0;
1095 pSMB->hdr.smb_buf_length += byte_count;
1096 pSMB->ByteCount = cpu_to_le16(byte_count);
1097 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1098 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1100 cFYI(1, ("Posix create returned %d", rc));
1101 goto psx_create_err;
1104 cFYI(1, ("copying inode info"));
1105 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1107 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1108 rc = -EIO; /* bad smb */
1109 goto psx_create_err;
1112 /* copy return information to pRetData */
1113 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1114 + le16_to_cpu(pSMBr->t2.DataOffset));
1116 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1118 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1119 /* Let caller know file was created so we can set the mode. */
1120 /* Do we care about the CreateAction in any other cases? */
1121 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1122 *pOplock |= CIFS_CREATE_ACTION;
1123 /* check to make sure response data is there */
1124 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1125 pRetData->Type = cpu_to_le32(-1); /* unknown */
1126 #ifdef CONFIG_CIFS_DEBUG2
1127 cFYI(1, ("unknown type"));
1130 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1131 + sizeof(FILE_UNIX_BASIC_INFO)) {
1132 cERROR(1, ("Open response data too small"));
1133 pRetData->Type = cpu_to_le32(-1);
1134 goto psx_create_err;
1136 memcpy((char *) pRetData,
1137 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1138 sizeof(FILE_UNIX_BASIC_INFO));
1142 cifs_buf_release(pSMB);
1144 cifs_stats_inc(&tcon->num_mkdirs);
1152 static __u16 convert_disposition(int disposition)
1156 switch (disposition) {
1157 case FILE_SUPERSEDE:
1158 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1161 ofun = SMBOPEN_OAPPEND;
1164 ofun = SMBOPEN_OCREATE;
1167 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1169 case FILE_OVERWRITE:
1170 ofun = SMBOPEN_OTRUNC;
1172 case FILE_OVERWRITE_IF:
1173 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1176 cFYI(1, ("unknown disposition %d", disposition));
1177 ofun = SMBOPEN_OAPPEND; /* regular open */
1183 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1184 const char *fileName, const int openDisposition,
1185 const int access_flags, const int create_options, __u16 * netfid,
1186 int *pOplock, FILE_ALL_INFO * pfile_info,
1187 const struct nls_table *nls_codepage, int remap)
1190 OPENX_REQ *pSMB = NULL;
1191 OPENX_RSP *pSMBr = NULL;
1197 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1202 pSMB->AndXCommand = 0xFF; /* none */
1204 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1205 count = 1; /* account for one byte pad to word boundary */
1207 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1208 fileName, PATH_MAX, nls_codepage, remap);
1209 name_len++; /* trailing null */
1211 } else { /* BB improve check for buffer overruns BB */
1212 count = 0; /* no pad */
1213 name_len = strnlen(fileName, PATH_MAX);
1214 name_len++; /* trailing null */
1215 strncpy(pSMB->fileName, fileName, name_len);
1217 if (*pOplock & REQ_OPLOCK)
1218 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1219 else if (*pOplock & REQ_BATCHOPLOCK)
1220 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1222 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1223 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1229 pSMB->Mode = cpu_to_le16(2);
1230 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1231 /* set file as system file if special file such
1232 as fifo and server expecting SFU style and
1233 no Unix extensions */
1235 if (create_options & CREATE_OPTION_SPECIAL)
1236 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1238 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1240 /* if ((omode & S_IWUGO) == 0)
1241 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1242 /* Above line causes problems due to vfs splitting create into two
1243 pieces - need to set mode after file created not while it is
1247 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1248 CREATE_OPTIONS_MASK); */
1249 /* BB FIXME END BB */
1251 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1252 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1254 pSMB->hdr.smb_buf_length += count;
1256 pSMB->ByteCount = cpu_to_le16(count);
1257 /* long_op set to 1 to allow for oplock break timeouts */
1258 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1259 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1260 cifs_stats_inc(&tcon->num_opens);
1262 cFYI(1, ("Error in Open = %d", rc));
1264 /* BB verify if wct == 15 */
1266 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1268 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1269 /* Let caller know file was created so we can set the mode. */
1270 /* Do we care about the CreateAction in any other cases? */
1272 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1273 *pOplock |= CIFS_CREATE_ACTION; */
1277 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1278 pfile_info->LastAccessTime = 0; /* BB fixme */
1279 pfile_info->LastWriteTime = 0; /* BB fixme */
1280 pfile_info->ChangeTime = 0; /* BB fixme */
1281 pfile_info->Attributes =
1282 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1283 /* the file_info buf is endian converted by caller */
1284 pfile_info->AllocationSize =
1285 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1286 pfile_info->EndOfFile = pfile_info->AllocationSize;
1287 pfile_info->NumberOfLinks = cpu_to_le32(1);
1291 cifs_buf_release(pSMB);
1298 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1299 const char *fileName, const int openDisposition,
1300 const int access_flags, const int create_options, __u16 * netfid,
1301 int *pOplock, FILE_ALL_INFO * pfile_info,
1302 const struct nls_table *nls_codepage, int remap)
1305 OPEN_REQ *pSMB = NULL;
1306 OPEN_RSP *pSMBr = NULL;
1312 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1317 pSMB->AndXCommand = 0xFF; /* none */
1319 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1320 count = 1; /* account for one byte pad to word boundary */
1322 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1323 fileName, PATH_MAX, nls_codepage, remap);
1324 name_len++; /* trailing null */
1326 pSMB->NameLength = cpu_to_le16(name_len);
1327 } else { /* BB improve check for buffer overruns BB */
1328 count = 0; /* no pad */
1329 name_len = strnlen(fileName, PATH_MAX);
1330 name_len++; /* trailing null */
1331 pSMB->NameLength = cpu_to_le16(name_len);
1332 strncpy(pSMB->fileName, fileName, name_len);
1334 if (*pOplock & REQ_OPLOCK)
1335 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1336 else if (*pOplock & REQ_BATCHOPLOCK)
1337 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1338 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1339 pSMB->AllocationSize = 0;
1340 /* set file as system file if special file such
1341 as fifo and server expecting SFU style and
1342 no Unix extensions */
1343 if (create_options & CREATE_OPTION_SPECIAL)
1344 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1346 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1347 /* XP does not handle ATTR_POSIX_SEMANTICS */
1348 /* but it helps speed up case sensitive checks for other
1349 servers such as Samba */
1350 if (tcon->ses->capabilities & CAP_UNIX)
1351 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1353 /* if ((omode & S_IWUGO) == 0)
1354 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1355 /* Above line causes problems due to vfs splitting create into two
1356 pieces - need to set mode after file created not while it is
1358 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1359 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1360 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1361 /* BB Expirement with various impersonation levels and verify */
1362 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1363 pSMB->SecurityFlags =
1364 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1367 pSMB->hdr.smb_buf_length += count;
1369 pSMB->ByteCount = cpu_to_le16(count);
1370 /* long_op set to 1 to allow for oplock break timeouts */
1371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1372 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1373 cifs_stats_inc(&tcon->num_opens);
1375 cFYI(1, ("Error in Open = %d", rc));
1377 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1378 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1379 /* Let caller know file was created so we can set the mode. */
1380 /* Do we care about the CreateAction in any other cases? */
1381 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1382 *pOplock |= CIFS_CREATE_ACTION;
1384 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1385 36 /* CreationTime to Attributes */);
1386 /* the file_info buf is endian converted by caller */
1387 pfile_info->AllocationSize = pSMBr->AllocationSize;
1388 pfile_info->EndOfFile = pSMBr->EndOfFile;
1389 pfile_info->NumberOfLinks = cpu_to_le32(1);
1393 cifs_buf_release(pSMB);
1400 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1401 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1402 char **buf, int *pbuf_type)
1405 READ_REQ *pSMB = NULL;
1406 READ_RSP *pSMBr = NULL;
1407 char *pReadData = NULL;
1409 int resp_buf_type = 0;
1412 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1413 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1416 wct = 10; /* old style read */
1419 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1423 /* tcon and ses pointer are checked in smb_init */
1424 if (tcon->ses->server == NULL)
1425 return -ECONNABORTED;
1427 pSMB->AndXCommand = 0xFF; /* none */
1429 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1431 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1432 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1435 pSMB->Remaining = 0;
1436 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1437 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1439 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1441 /* old style read */
1442 struct smb_com_readx_req *pSMBW =
1443 (struct smb_com_readx_req *)pSMB;
1444 pSMBW->ByteCount = 0;
1447 iov[0].iov_base = (char *)pSMB;
1448 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1449 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1450 &resp_buf_type, 0 /* not long op */, 1 /* log err */ );
1451 cifs_stats_inc(&tcon->num_reads);
1452 pSMBr = (READ_RSP *)iov[0].iov_base;
1454 cERROR(1, ("Send error in read = %d", rc));
1456 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1457 data_length = data_length << 16;
1458 data_length += le16_to_cpu(pSMBr->DataLength);
1459 *nbytes = data_length;
1461 /*check that DataLength would not go beyond end of SMB */
1462 if ((data_length > CIFSMaxBufSize)
1463 || (data_length > count)) {
1464 cFYI(1, ("bad length %d for count %d",
1465 data_length, count));
1469 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1470 le16_to_cpu(pSMBr->DataOffset);
1471 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1472 cERROR(1,("Faulting on read rc = %d",rc));
1474 }*/ /* can not use copy_to_user when using page cache*/
1476 memcpy(*buf, pReadData, data_length);
1480 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1482 if (resp_buf_type == CIFS_SMALL_BUFFER)
1483 cifs_small_buf_release(iov[0].iov_base);
1484 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1485 cifs_buf_release(iov[0].iov_base);
1486 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1487 /* return buffer to caller to free */
1488 *buf = iov[0].iov_base;
1489 if (resp_buf_type == CIFS_SMALL_BUFFER)
1490 *pbuf_type = CIFS_SMALL_BUFFER;
1491 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1492 *pbuf_type = CIFS_LARGE_BUFFER;
1493 } /* else no valid buffer on return - leave as null */
1495 /* Note: On -EAGAIN error only caller can retry on handle based calls
1496 since file handle passed in no longer valid */
1502 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1503 const int netfid, const unsigned int count,
1504 const __u64 offset, unsigned int *nbytes, const char *buf,
1505 const char __user *ubuf, const int long_op)
1508 WRITE_REQ *pSMB = NULL;
1509 WRITE_RSP *pSMBr = NULL;
1510 int bytes_returned, wct;
1514 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1515 if (tcon->ses == NULL)
1516 return -ECONNABORTED;
1518 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1523 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1527 /* tcon and ses pointer are checked in smb_init */
1528 if (tcon->ses->server == NULL)
1529 return -ECONNABORTED;
1531 pSMB->AndXCommand = 0xFF; /* none */
1533 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1535 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1536 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1539 pSMB->Reserved = 0xFFFFFFFF;
1540 pSMB->WriteMode = 0;
1541 pSMB->Remaining = 0;
1543 /* Can increase buffer size if buffer is big enough in some cases ie we
1544 can send more if LARGE_WRITE_X capability returned by the server and if
1545 our buffer is big enough or if we convert to iovecs on socket writes
1546 and eliminate the copy to the CIFS buffer */
1547 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1548 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1550 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1554 if (bytes_sent > count)
1557 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1559 memcpy(pSMB->Data, buf, bytes_sent);
1561 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1562 cifs_buf_release(pSMB);
1565 } else if (count != 0) {
1567 cifs_buf_release(pSMB);
1569 } /* else setting file size with write of zero bytes */
1571 byte_count = bytes_sent + 1; /* pad */
1572 else /* wct == 12 */ {
1573 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1575 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1576 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1577 pSMB->hdr.smb_buf_length += byte_count;
1580 pSMB->ByteCount = cpu_to_le16(byte_count);
1581 else { /* old style write has byte count 4 bytes earlier
1583 struct smb_com_writex_req *pSMBW =
1584 (struct smb_com_writex_req *)pSMB;
1585 pSMBW->ByteCount = cpu_to_le16(byte_count);
1588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1589 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1590 cifs_stats_inc(&tcon->num_writes);
1592 cFYI(1, ("Send error in write = %d", rc));
1595 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1596 *nbytes = (*nbytes) << 16;
1597 *nbytes += le16_to_cpu(pSMBr->Count);
1600 cifs_buf_release(pSMB);
1602 /* Note: On -EAGAIN error only caller can retry on handle based calls
1603 since file handle passed in no longer valid */
1609 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1610 const int netfid, const unsigned int count,
1611 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1612 int n_vec, const int long_op)
1615 WRITE_REQ *pSMB = NULL;
1618 int resp_buf_type = 0;
1620 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1622 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1626 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1629 /* tcon and ses pointer are checked in smb_init */
1630 if (tcon->ses->server == NULL)
1631 return -ECONNABORTED;
1633 pSMB->AndXCommand = 0xFF; /* none */
1635 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1637 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1638 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1640 pSMB->Reserved = 0xFFFFFFFF;
1641 pSMB->WriteMode = 0;
1642 pSMB->Remaining = 0;
1645 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1647 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1648 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1649 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1651 pSMB->hdr.smb_buf_length += count+1;
1652 else /* wct == 12 */
1653 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1655 pSMB->ByteCount = cpu_to_le16(count + 1);
1656 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1657 struct smb_com_writex_req *pSMBW =
1658 (struct smb_com_writex_req *)pSMB;
1659 pSMBW->ByteCount = cpu_to_le16(count + 5);
1661 iov[0].iov_base = pSMB;
1663 iov[0].iov_len = smb_hdr_len + 4;
1664 else /* wct == 12 pad bigger by four bytes */
1665 iov[0].iov_len = smb_hdr_len + 8;
1668 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1669 long_op, 0 /* do not log STATUS code */ );
1670 cifs_stats_inc(&tcon->num_writes);
1672 cFYI(1, ("Send error Write2 = %d", rc));
1674 } else if (resp_buf_type == 0) {
1675 /* presumably this can not happen, but best to be safe */
1679 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1680 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1681 *nbytes = (*nbytes) << 16;
1682 *nbytes += le16_to_cpu(pSMBr->Count);
1685 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1686 if (resp_buf_type == CIFS_SMALL_BUFFER)
1687 cifs_small_buf_release(iov[0].iov_base);
1688 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1689 cifs_buf_release(iov[0].iov_base);
1691 /* Note: On -EAGAIN error only caller can retry on handle based calls
1692 since file handle passed in no longer valid */
1699 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1700 const __u16 smb_file_id, const __u64 len,
1701 const __u64 offset, const __u32 numUnlock,
1702 const __u32 numLock, const __u8 lockType, const int waitFlag)
1705 LOCK_REQ *pSMB = NULL;
1706 LOCK_RSP *pSMBr = NULL;
1711 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1712 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1717 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1719 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1720 timeout = -1; /* no response expected */
1722 } else if (waitFlag == TRUE) {
1723 timeout = 3; /* blocking operation, no timeout */
1724 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1729 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1730 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1731 pSMB->LockType = lockType;
1732 pSMB->AndXCommand = 0xFF; /* none */
1733 pSMB->Fid = smb_file_id; /* netfid stays le */
1735 if ((numLock != 0) || (numUnlock != 0)) {
1736 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1737 /* BB where to store pid high? */
1738 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1739 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1740 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1741 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1742 count = sizeof(LOCKING_ANDX_RANGE);
1747 pSMB->hdr.smb_buf_length += count;
1748 pSMB->ByteCount = cpu_to_le16(count);
1751 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1752 (struct smb_hdr *) pSMBr, &bytes_returned);
1754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1755 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1757 cifs_stats_inc(&tcon->num_locks);
1759 cFYI(1, ("Send error in Lock = %d", rc));
1761 cifs_small_buf_release(pSMB);
1763 /* Note: On -EAGAIN error only caller can retry on handle based calls
1764 since file handle passed in no longer valid */
1769 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1770 const __u16 smb_file_id, const int get_flag, const __u64 len,
1771 struct file_lock *pLockData, const __u16 lock_type,
1774 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1775 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1776 struct cifs_posix_lock *parm_data;
1779 int bytes_returned = 0;
1780 __u16 params, param_offset, offset, byte_count, count;
1782 cFYI(1, ("Posix Lock"));
1784 if (pLockData == NULL)
1787 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1792 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1795 pSMB->MaxSetupCount = 0;
1798 pSMB->Reserved2 = 0;
1799 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1800 offset = param_offset + params;
1802 count = sizeof(struct cifs_posix_lock);
1803 pSMB->MaxParameterCount = cpu_to_le16(2);
1804 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1805 pSMB->SetupCount = 1;
1806 pSMB->Reserved3 = 0;
1808 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1810 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1811 byte_count = 3 /* pad */ + params + count;
1812 pSMB->DataCount = cpu_to_le16(count);
1813 pSMB->ParameterCount = cpu_to_le16(params);
1814 pSMB->TotalDataCount = pSMB->DataCount;
1815 pSMB->TotalParameterCount = pSMB->ParameterCount;
1816 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1817 parm_data = (struct cifs_posix_lock *)
1818 (((char *) &pSMB->hdr.Protocol) + offset);
1820 parm_data->lock_type = cpu_to_le16(lock_type);
1822 timeout = 3; /* blocking operation, no timeout */
1823 parm_data->lock_flags = cpu_to_le16(1);
1824 pSMB->Timeout = cpu_to_le32(-1);
1828 parm_data->pid = cpu_to_le32(current->tgid);
1829 parm_data->start = cpu_to_le64(pLockData->fl_start);
1830 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1832 pSMB->DataOffset = cpu_to_le16(offset);
1833 pSMB->Fid = smb_file_id;
1834 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1835 pSMB->Reserved4 = 0;
1836 pSMB->hdr.smb_buf_length += byte_count;
1837 pSMB->ByteCount = cpu_to_le16(byte_count);
1839 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1840 (struct smb_hdr *) pSMBr, &bytes_returned);
1842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1843 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1847 cFYI(1, ("Send error in Posix Lock = %d", rc));
1848 } else if (get_flag) {
1849 /* lock structure can be returned on get */
1852 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1854 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1855 rc = -EIO; /* bad smb */
1858 if (pLockData == NULL) {
1862 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1863 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1864 if (data_count < sizeof(struct cifs_posix_lock)) {
1868 parm_data = (struct cifs_posix_lock *)
1869 ((char *)&pSMBr->hdr.Protocol + data_offset);
1870 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1871 pLockData->fl_type = F_UNLCK;
1876 cifs_small_buf_release(pSMB);
1878 /* Note: On -EAGAIN error only caller can retry on handle based calls
1879 since file handle passed in no longer valid */
1886 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1889 CLOSE_REQ *pSMB = NULL;
1890 CLOSE_RSP *pSMBr = NULL;
1892 cFYI(1, ("In CIFSSMBClose"));
1894 /* do not retry on dead session on close */
1895 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1901 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1903 pSMB->FileID = (__u16) smb_file_id;
1904 pSMB->LastWriteTime = 0xFFFFFFFF;
1905 pSMB->ByteCount = 0;
1906 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1907 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1908 cifs_stats_inc(&tcon->num_closes);
1911 /* EINTR is expected when user ctl-c to kill app */
1912 cERROR(1, ("Send error in Close = %d", rc));
1916 cifs_small_buf_release(pSMB);
1918 /* Since session is dead, file will be closed on server already */
1926 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1927 const char *fromName, const char *toName,
1928 const struct nls_table *nls_codepage, int remap)
1931 RENAME_REQ *pSMB = NULL;
1932 RENAME_RSP *pSMBr = NULL;
1934 int name_len, name_len2;
1937 cFYI(1, ("In CIFSSMBRename"));
1939 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1944 pSMB->BufferFormat = 0x04;
1945 pSMB->SearchAttributes =
1946 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1949 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1951 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1952 PATH_MAX, nls_codepage, remap);
1953 name_len++; /* trailing null */
1955 pSMB->OldFileName[name_len] = 0x04; /* pad */
1956 /* protocol requires ASCII signature byte on Unicode string */
1957 pSMB->OldFileName[name_len + 1] = 0x00;
1959 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1960 toName, PATH_MAX, nls_codepage, remap);
1961 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1962 name_len2 *= 2; /* convert to bytes */
1963 } else { /* BB improve the check for buffer overruns BB */
1964 name_len = strnlen(fromName, PATH_MAX);
1965 name_len++; /* trailing null */
1966 strncpy(pSMB->OldFileName, fromName, name_len);
1967 name_len2 = strnlen(toName, PATH_MAX);
1968 name_len2++; /* trailing null */
1969 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1970 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1971 name_len2++; /* trailing null */
1972 name_len2++; /* signature byte */
1975 count = 1 /* 1st signature byte */ + name_len + name_len2;
1976 pSMB->hdr.smb_buf_length += count;
1977 pSMB->ByteCount = cpu_to_le16(count);
1979 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1980 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1981 cifs_stats_inc(&tcon->num_renames);
1983 cFYI(1, ("Send error in rename = %d", rc));
1986 cifs_buf_release(pSMB);
1994 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1995 int netfid, char *target_name,
1996 const struct nls_table *nls_codepage, int remap)
1998 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1999 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2000 struct set_file_rename *rename_info;
2002 char dummy_string[30];
2004 int bytes_returned = 0;
2006 __u16 params, param_offset, offset, count, byte_count;
2008 cFYI(1, ("Rename to File by handle"));
2009 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2015 pSMB->MaxSetupCount = 0;
2019 pSMB->Reserved2 = 0;
2020 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2021 offset = param_offset + params;
2023 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2024 rename_info = (struct set_file_rename *) data_offset;
2025 pSMB->MaxParameterCount = cpu_to_le16(2);
2026 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2027 pSMB->SetupCount = 1;
2028 pSMB->Reserved3 = 0;
2029 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2030 byte_count = 3 /* pad */ + params;
2031 pSMB->ParameterCount = cpu_to_le16(params);
2032 pSMB->TotalParameterCount = pSMB->ParameterCount;
2033 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2034 pSMB->DataOffset = cpu_to_le16(offset);
2035 /* construct random name ".cifs_tmp<inodenum><mid>" */
2036 rename_info->overwrite = cpu_to_le32(1);
2037 rename_info->root_fid = 0;
2038 /* unicode only call */
2039 if (target_name == NULL) {
2040 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2041 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2042 dummy_string, 24, nls_codepage, remap);
2044 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2045 target_name, PATH_MAX, nls_codepage,
2048 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2049 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2050 byte_count += count;
2051 pSMB->DataCount = cpu_to_le16(count);
2052 pSMB->TotalDataCount = pSMB->DataCount;
2054 pSMB->InformationLevel =
2055 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2056 pSMB->Reserved4 = 0;
2057 pSMB->hdr.smb_buf_length += byte_count;
2058 pSMB->ByteCount = cpu_to_le16(byte_count);
2059 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2060 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2061 cifs_stats_inc(&pTcon->num_t2renames);
2063 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2066 cifs_buf_release(pSMB);
2068 /* Note: On -EAGAIN error only caller can retry on handle based calls
2069 since file handle passed in no longer valid */
2075 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2076 const __u16 target_tid, const char *toName, const int flags,
2077 const struct nls_table *nls_codepage, int remap)
2080 COPY_REQ *pSMB = NULL;
2081 COPY_RSP *pSMBr = NULL;
2083 int name_len, name_len2;
2086 cFYI(1, ("In CIFSSMBCopy"));
2088 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2093 pSMB->BufferFormat = 0x04;
2094 pSMB->Tid2 = target_tid;
2096 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2098 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2099 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2100 fromName, PATH_MAX, nls_codepage,
2102 name_len++; /* trailing null */
2104 pSMB->OldFileName[name_len] = 0x04; /* pad */
2105 /* protocol requires ASCII signature byte on Unicode string */
2106 pSMB->OldFileName[name_len + 1] = 0x00;
2108 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2109 toName, PATH_MAX, nls_codepage, remap);
2110 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2111 name_len2 *= 2; /* convert to bytes */
2112 } else { /* BB improve the check for buffer overruns BB */
2113 name_len = strnlen(fromName, PATH_MAX);
2114 name_len++; /* trailing null */
2115 strncpy(pSMB->OldFileName, fromName, name_len);
2116 name_len2 = strnlen(toName, PATH_MAX);
2117 name_len2++; /* trailing null */
2118 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2119 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2120 name_len2++; /* trailing null */
2121 name_len2++; /* signature byte */
2124 count = 1 /* 1st signature byte */ + name_len + name_len2;
2125 pSMB->hdr.smb_buf_length += count;
2126 pSMB->ByteCount = cpu_to_le16(count);
2128 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2129 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2131 cFYI(1, ("Send error in copy = %d with %d files copied",
2132 rc, le16_to_cpu(pSMBr->CopyCount)));
2135 cifs_buf_release(pSMB);
2144 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2145 const char *fromName, const char *toName,
2146 const struct nls_table *nls_codepage)
2148 TRANSACTION2_SPI_REQ *pSMB = NULL;
2149 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2152 int name_len_target;
2154 int bytes_returned = 0;
2155 __u16 params, param_offset, offset, byte_count;
2157 cFYI(1, ("In Symlink Unix style"));
2159 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2164 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2166 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2167 /* find define for this maxpathcomponent */
2169 name_len++; /* trailing null */
2172 } else { /* BB improve the check for buffer overruns BB */
2173 name_len = strnlen(fromName, PATH_MAX);
2174 name_len++; /* trailing null */
2175 strncpy(pSMB->FileName, fromName, name_len);
2177 params = 6 + name_len;
2178 pSMB->MaxSetupCount = 0;
2182 pSMB->Reserved2 = 0;
2183 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2184 InformationLevel) - 4;
2185 offset = param_offset + params;
2187 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2188 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2190 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2191 /* find define for this maxpathcomponent */
2193 name_len_target++; /* trailing null */
2194 name_len_target *= 2;
2195 } else { /* BB improve the check for buffer overruns BB */
2196 name_len_target = strnlen(toName, PATH_MAX);
2197 name_len_target++; /* trailing null */
2198 strncpy(data_offset, toName, name_len_target);
2201 pSMB->MaxParameterCount = cpu_to_le16(2);
2202 /* BB find exact max on data count below from sess */
2203 pSMB->MaxDataCount = cpu_to_le16(1000);
2204 pSMB->SetupCount = 1;
2205 pSMB->Reserved3 = 0;
2206 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2207 byte_count = 3 /* pad */ + params + name_len_target;
2208 pSMB->DataCount = cpu_to_le16(name_len_target);
2209 pSMB->ParameterCount = cpu_to_le16(params);
2210 pSMB->TotalDataCount = pSMB->DataCount;
2211 pSMB->TotalParameterCount = pSMB->ParameterCount;
2212 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2213 pSMB->DataOffset = cpu_to_le16(offset);
2214 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2215 pSMB->Reserved4 = 0;
2216 pSMB->hdr.smb_buf_length += byte_count;
2217 pSMB->ByteCount = cpu_to_le16(byte_count);
2218 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2219 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2220 cifs_stats_inc(&tcon->num_symlinks);
2222 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2226 cifs_buf_release(pSMB);
2229 goto createSymLinkRetry;
2235 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2236 const char *fromName, const char *toName,
2237 const struct nls_table *nls_codepage, int remap)
2239 TRANSACTION2_SPI_REQ *pSMB = NULL;
2240 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2243 int name_len_target;
2245 int bytes_returned = 0;
2246 __u16 params, param_offset, offset, byte_count;
2248 cFYI(1, ("In Create Hard link Unix style"));
2249 createHardLinkRetry:
2250 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2255 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2256 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2257 PATH_MAX, nls_codepage, remap);
2258 name_len++; /* trailing null */
2261 } else { /* BB improve the check for buffer overruns BB */
2262 name_len = strnlen(toName, PATH_MAX);
2263 name_len++; /* trailing null */
2264 strncpy(pSMB->FileName, toName, name_len);
2266 params = 6 + name_len;
2267 pSMB->MaxSetupCount = 0;
2271 pSMB->Reserved2 = 0;
2272 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2273 InformationLevel) - 4;
2274 offset = param_offset + params;
2276 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2279 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2280 nls_codepage, remap);
2281 name_len_target++; /* trailing null */
2282 name_len_target *= 2;
2283 } else { /* BB improve the check for buffer overruns BB */
2284 name_len_target = strnlen(fromName, PATH_MAX);
2285 name_len_target++; /* trailing null */
2286 strncpy(data_offset, fromName, name_len_target);
2289 pSMB->MaxParameterCount = cpu_to_le16(2);
2290 /* BB find exact max on data count below from sess*/
2291 pSMB->MaxDataCount = cpu_to_le16(1000);
2292 pSMB->SetupCount = 1;
2293 pSMB->Reserved3 = 0;
2294 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2295 byte_count = 3 /* pad */ + params + name_len_target;
2296 pSMB->ParameterCount = cpu_to_le16(params);
2297 pSMB->TotalParameterCount = pSMB->ParameterCount;
2298 pSMB->DataCount = cpu_to_le16(name_len_target);
2299 pSMB->TotalDataCount = pSMB->DataCount;
2300 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2301 pSMB->DataOffset = cpu_to_le16(offset);
2302 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2303 pSMB->Reserved4 = 0;
2304 pSMB->hdr.smb_buf_length += byte_count;
2305 pSMB->ByteCount = cpu_to_le16(byte_count);
2306 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2307 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2308 cifs_stats_inc(&tcon->num_hardlinks);
2310 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2313 cifs_buf_release(pSMB);
2315 goto createHardLinkRetry;
2321 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2322 const char *fromName, const char *toName,
2323 const struct nls_table *nls_codepage, int remap)
2326 NT_RENAME_REQ *pSMB = NULL;
2327 RENAME_RSP *pSMBr = NULL;
2329 int name_len, name_len2;
2332 cFYI(1, ("In CIFSCreateHardLink"));
2333 winCreateHardLinkRetry:
2335 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2340 pSMB->SearchAttributes =
2341 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2343 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2344 pSMB->ClusterCount = 0;
2346 pSMB->BufferFormat = 0x04;
2348 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2350 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2351 PATH_MAX, nls_codepage, remap);
2352 name_len++; /* trailing null */
2354 pSMB->OldFileName[name_len] = 0; /* pad */
2355 pSMB->OldFileName[name_len + 1] = 0x04;
2357 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2358 toName, PATH_MAX, nls_codepage, remap);
2359 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2360 name_len2 *= 2; /* convert to bytes */
2361 } else { /* BB improve the check for buffer overruns BB */
2362 name_len = strnlen(fromName, PATH_MAX);
2363 name_len++; /* trailing null */
2364 strncpy(pSMB->OldFileName, fromName, name_len);
2365 name_len2 = strnlen(toName, PATH_MAX);
2366 name_len2++; /* trailing null */
2367 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2368 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2369 name_len2++; /* trailing null */
2370 name_len2++; /* signature byte */
2373 count = 1 /* string type byte */ + name_len + name_len2;
2374 pSMB->hdr.smb_buf_length += count;
2375 pSMB->ByteCount = cpu_to_le16(count);
2377 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2378 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2379 cifs_stats_inc(&tcon->num_hardlinks);
2381 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2383 cifs_buf_release(pSMB);
2385 goto winCreateHardLinkRetry;
2391 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2392 const unsigned char *searchName,
2393 char *symlinkinfo, const int buflen,
2394 const struct nls_table *nls_codepage)
2396 /* SMB_QUERY_FILE_UNIX_LINK */
2397 TRANSACTION2_QPI_REQ *pSMB = NULL;
2398 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2402 __u16 params, byte_count;
2404 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2407 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2412 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2414 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2415 PATH_MAX, nls_codepage);
2416 name_len++; /* trailing null */
2418 } else { /* BB improve the check for buffer overruns BB */
2419 name_len = strnlen(searchName, PATH_MAX);
2420 name_len++; /* trailing null */
2421 strncpy(pSMB->FileName, searchName, name_len);
2424 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2425 pSMB->TotalDataCount = 0;
2426 pSMB->MaxParameterCount = cpu_to_le16(2);
2427 /* BB find exact max data count below from sess structure BB */
2428 pSMB->MaxDataCount = cpu_to_le16(4000);
2429 pSMB->MaxSetupCount = 0;
2433 pSMB->Reserved2 = 0;
2434 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2435 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2436 pSMB->DataCount = 0;
2437 pSMB->DataOffset = 0;
2438 pSMB->SetupCount = 1;
2439 pSMB->Reserved3 = 0;
2440 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2441 byte_count = params + 1 /* pad */ ;
2442 pSMB->TotalParameterCount = cpu_to_le16(params);
2443 pSMB->ParameterCount = pSMB->TotalParameterCount;
2444 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2445 pSMB->Reserved4 = 0;
2446 pSMB->hdr.smb_buf_length += byte_count;
2447 pSMB->ByteCount = cpu_to_le16(byte_count);
2449 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2450 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2452 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2454 /* decode response */
2456 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2457 if (rc || (pSMBr->ByteCount < 2))
2458 /* BB also check enough total bytes returned */
2459 rc = -EIO; /* bad smb */
2461 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2462 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2464 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2465 name_len = UniStrnlen((wchar_t *) ((char *)
2466 &pSMBr->hdr.Protocol + data_offset),
2467 min_t(const int, buflen, count) / 2);
2468 /* BB FIXME investigate remapping reserved chars here */
2469 cifs_strfromUCS_le(symlinkinfo,
2470 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2472 name_len, nls_codepage);
2474 strncpy(symlinkinfo,
2475 (char *) &pSMBr->hdr.Protocol +
2477 min_t(const int, buflen, count));
2479 symlinkinfo[buflen] = 0;
2480 /* just in case so calling code does not go off the end of buffer */
2483 cifs_buf_release(pSMB);
2485 goto querySymLinkRetry;
2489 #ifdef CONFIG_CIFS_EXPERIMENTAL
2490 /* Initialize NT TRANSACT SMB into small smb request buffer.
2491 This assumes that all NT TRANSACTS that we init here have
2492 total parm and data under about 400 bytes (to fit in small cifs
2493 buffer size), which is the case so far, it easily fits. NB:
2494 Setup words themselves and ByteCount
2495 MaxSetupCount (size of returned setup area) and
2496 MaxParameterCount (returned parms size) must be set by caller */
2498 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2499 const int parm_len, struct cifsTconInfo *tcon,
2504 struct smb_com_ntransact_req *pSMB;
2506 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2510 *ret_buf = (void *)pSMB;
2512 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2513 pSMB->TotalDataCount = 0;
2514 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2515 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2516 pSMB->ParameterCount = pSMB->TotalParameterCount;
2517 pSMB->DataCount = pSMB->TotalDataCount;
2518 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2519 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2520 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2521 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2522 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2523 pSMB->SubCommand = cpu_to_le16(sub_command);
2528 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2529 __u32 *pdatalen, __u32 *pparmlen)
2532 __u32 data_count, data_offset, parm_count, parm_offset;
2533 struct smb_com_ntransact_rsp *pSMBr;
2541 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2543 /* ByteCount was converted from little endian in SendReceive */
2544 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2545 (char *)&pSMBr->ByteCount;
2547 data_offset = le32_to_cpu(pSMBr->DataOffset);
2548 data_count = le32_to_cpu(pSMBr->DataCount);
2549 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2550 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2552 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2553 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2555 /* should we also check that parm and data areas do not overlap? */
2556 if (*ppparm > end_of_smb) {
2557 cFYI(1, ("parms start after end of smb"));
2559 } else if (parm_count + *ppparm > end_of_smb) {
2560 cFYI(1, ("parm end after end of smb"));
2562 } else if (*ppdata > end_of_smb) {
2563 cFYI(1, ("data starts after end of smb"));
2565 } else if (data_count + *ppdata > end_of_smb) {
2566 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2567 *ppdata, data_count, (data_count + *ppdata),
2568 end_of_smb, pSMBr));
2570 } else if (parm_count + data_count > pSMBr->ByteCount) {
2571 cFYI(1, ("parm count and data count larger than SMB"));
2574 *pdatalen = data_count;
2575 *pparmlen = parm_count;
2578 #endif /* CIFS_EXPERIMENTAL */
2581 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2582 const unsigned char *searchName,
2583 char *symlinkinfo, const int buflen, __u16 fid,
2584 const struct nls_table *nls_codepage)
2589 struct smb_com_transaction_ioctl_req *pSMB;
2590 struct smb_com_transaction_ioctl_rsp *pSMBr;
2592 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2593 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2598 pSMB->TotalParameterCount = 0 ;
2599 pSMB->TotalDataCount = 0;
2600 pSMB->MaxParameterCount = cpu_to_le32(2);
2601 /* BB find exact data count max from sess structure BB */
2602 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2603 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2604 pSMB->MaxSetupCount = 4;
2606 pSMB->ParameterOffset = 0;
2607 pSMB->DataCount = 0;
2608 pSMB->DataOffset = 0;
2609 pSMB->SetupCount = 4;
2610 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2611 pSMB->ParameterCount = pSMB->TotalParameterCount;
2612 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2613 pSMB->IsFsctl = 1; /* FSCTL */
2614 pSMB->IsRootFlag = 0;
2615 pSMB->Fid = fid; /* file handle always le */
2616 pSMB->ByteCount = 0;
2618 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2619 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2621 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2622 } else { /* decode response */
2623 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2624 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2625 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2626 /* BB also check enough total bytes returned */
2627 rc = -EIO; /* bad smb */
2629 if (data_count && (data_count < 2048)) {
2630 char *end_of_smb = 2 /* sizeof byte count */ +
2632 (char *)&pSMBr->ByteCount;
2634 struct reparse_data *reparse_buf =
2635 (struct reparse_data *)
2636 ((char *)&pSMBr->hdr.Protocol
2638 if ((char *)reparse_buf >= end_of_smb) {
2642 if ((reparse_buf->LinkNamesBuf +
2643 reparse_buf->TargetNameOffset +
2644 reparse_buf->TargetNameLen) >
2646 cFYI(1, ("reparse buf beyond SMB"));
2651 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2652 name_len = UniStrnlen((wchar_t *)
2653 (reparse_buf->LinkNamesBuf +
2654 reparse_buf->TargetNameOffset),
2656 reparse_buf->TargetNameLen / 2));
2657 cifs_strfromUCS_le(symlinkinfo,
2658 (__le16 *) (reparse_buf->LinkNamesBuf +
2659 reparse_buf->TargetNameOffset),
2660 name_len, nls_codepage);
2661 } else { /* ASCII names */
2662 strncpy(symlinkinfo,
2663 reparse_buf->LinkNamesBuf +
2664 reparse_buf->TargetNameOffset,
2665 min_t(const int, buflen,
2666 reparse_buf->TargetNameLen));
2670 cFYI(1, ("Invalid return data count on "
2671 "get reparse info ioctl"));
2673 symlinkinfo[buflen] = 0; /* just in case so the caller
2674 does not go off the end of the buffer */
2675 cFYI(1, ("readlink result - %s", symlinkinfo));
2679 cifs_buf_release(pSMB);
2681 /* Note: On -EAGAIN error only caller can retry on handle based calls
2682 since file handle passed in no longer valid */
2687 #ifdef CONFIG_CIFS_POSIX
2689 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2690 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2691 struct cifs_posix_ace *cifs_ace)
2693 /* u8 cifs fields do not need le conversion */
2694 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2695 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2696 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2697 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2702 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2703 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2704 const int acl_type, const int size_of_data_area)
2709 struct cifs_posix_ace *pACE;
2710 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2711 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2713 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2716 if (acl_type & ACL_TYPE_ACCESS) {
2717 count = le16_to_cpu(cifs_acl->access_entry_count);
2718 pACE = &cifs_acl->ace_array[0];
2719 size = sizeof(struct cifs_posix_acl);
2720 size += sizeof(struct cifs_posix_ace) * count;
2721 /* check if we would go beyond end of SMB */
2722 if (size_of_data_area < size) {
2723 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2724 size_of_data_area, size));
2727 } else if (acl_type & ACL_TYPE_DEFAULT) {
2728 count = le16_to_cpu(cifs_acl->access_entry_count);
2729 size = sizeof(struct cifs_posix_acl);
2730 size += sizeof(struct cifs_posix_ace) * count;
2731 /* skip past access ACEs to get to default ACEs */
2732 pACE = &cifs_acl->ace_array[count];
2733 count = le16_to_cpu(cifs_acl->default_entry_count);
2734 size += sizeof(struct cifs_posix_ace) * count;
2735 /* check if we would go beyond end of SMB */
2736 if (size_of_data_area < size)
2743 size = posix_acl_xattr_size(count);
2744 if ((buflen == 0) || (local_acl == NULL)) {
2745 /* used to query ACL EA size */
2746 } else if (size > buflen) {
2748 } else /* buffer big enough */ {
2749 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2750 for (i = 0; i < count ; i++) {
2751 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2758 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2759 const posix_acl_xattr_entry *local_ace)
2761 __u16 rc = 0; /* 0 = ACL converted ok */
2763 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2764 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2765 /* BB is there a better way to handle the large uid? */
2766 if (local_ace->e_id == cpu_to_le32(-1)) {
2767 /* Probably no need to le convert -1 on any arch but can not hurt */
2768 cifs_ace->cifs_uid = cpu_to_le64(-1);
2770 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2771 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2775 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2776 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2777 const int buflen, const int acl_type)
2780 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2781 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2785 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2788 count = posix_acl_xattr_count((size_t)buflen);
2789 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2791 count, buflen, le32_to_cpu(local_acl->a_version)));
2792 if (le32_to_cpu(local_acl->a_version) != 2) {
2793 cFYI(1, ("unknown POSIX ACL version %d",
2794 le32_to_cpu(local_acl->a_version)));
2797 cifs_acl->version = cpu_to_le16(1);
2798 if (acl_type == ACL_TYPE_ACCESS)
2799 cifs_acl->access_entry_count = cpu_to_le16(count);
2800 else if (acl_type == ACL_TYPE_DEFAULT)
2801 cifs_acl->default_entry_count = cpu_to_le16(count);
2803 cFYI(1, ("unknown ACL type %d", acl_type));
2806 for (i = 0; i < count; i++) {
2807 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2808 &local_acl->a_entries[i]);
2810 /* ACE not converted */
2815 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2816 rc += sizeof(struct cifs_posix_acl);
2817 /* BB add check to make sure ACL does not overflow SMB */
2823 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2824 const unsigned char *searchName,
2825 char *acl_inf, const int buflen, const int acl_type,
2826 const struct nls_table *nls_codepage, int remap)
2828 /* SMB_QUERY_POSIX_ACL */
2829 TRANSACTION2_QPI_REQ *pSMB = NULL;
2830 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2834 __u16 params, byte_count;
2836 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2839 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2844 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2846 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2847 PATH_MAX, nls_codepage, remap);
2848 name_len++; /* trailing null */
2850 pSMB->FileName[name_len] = 0;
2851 pSMB->FileName[name_len+1] = 0;
2852 } else { /* BB improve the check for buffer overruns BB */
2853 name_len = strnlen(searchName, PATH_MAX);
2854 name_len++; /* trailing null */
2855 strncpy(pSMB->FileName, searchName, name_len);
2858 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2859 pSMB->TotalDataCount = 0;
2860 pSMB->MaxParameterCount = cpu_to_le16(2);
2861 /* BB find exact max data count below from sess structure BB */
2862 pSMB->MaxDataCount = cpu_to_le16(4000);
2863 pSMB->MaxSetupCount = 0;
2867 pSMB->Reserved2 = 0;
2868 pSMB->ParameterOffset = cpu_to_le16(
2869 offsetof(struct smb_com_transaction2_qpi_req,
2870 InformationLevel) - 4);
2871 pSMB->DataCount = 0;
2872 pSMB->DataOffset = 0;
2873 pSMB->SetupCount = 1;
2874 pSMB->Reserved3 = 0;
2875 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2876 byte_count = params + 1 /* pad */ ;
2877 pSMB->TotalParameterCount = cpu_to_le16(params);
2878 pSMB->ParameterCount = pSMB->TotalParameterCount;
2879 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2880 pSMB->Reserved4 = 0;
2881 pSMB->hdr.smb_buf_length += byte_count;
2882 pSMB->ByteCount = cpu_to_le16(byte_count);
2884 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2885 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2886 cifs_stats_inc(&tcon->num_acl_get);
2888 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2890 /* decode response */
2892 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2893 if (rc || (pSMBr->ByteCount < 2))
2894 /* BB also check enough total bytes returned */
2895 rc = -EIO; /* bad smb */
2897 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2898 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2899 rc = cifs_copy_posix_acl(acl_inf,
2900 (char *)&pSMBr->hdr.Protocol+data_offset,
2901 buflen, acl_type, count);
2904 cifs_buf_release(pSMB);
2911 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2912 const unsigned char *fileName,
2913 const char *local_acl, const int buflen,
2915 const struct nls_table *nls_codepage, int remap)
2917 struct smb_com_transaction2_spi_req *pSMB = NULL;
2918 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2922 int bytes_returned = 0;
2923 __u16 params, byte_count, data_count, param_offset, offset;
2925 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2927 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2931 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2933 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2934 PATH_MAX, nls_codepage, remap);
2935 name_len++; /* trailing null */
2937 } else { /* BB improve the check for buffer overruns BB */
2938 name_len = strnlen(fileName, PATH_MAX);
2939 name_len++; /* trailing null */
2940 strncpy(pSMB->FileName, fileName, name_len);
2942 params = 6 + name_len;
2943 pSMB->MaxParameterCount = cpu_to_le16(2);
2944 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2945 pSMB->MaxSetupCount = 0;
2949 pSMB->Reserved2 = 0;
2950 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2951 InformationLevel) - 4;
2952 offset = param_offset + params;
2953 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2954 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2956 /* convert to on the wire format for POSIX ACL */
2957 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2959 if (data_count == 0) {
2961 goto setACLerrorExit;
2963 pSMB->DataOffset = cpu_to_le16(offset);
2964 pSMB->SetupCount = 1;
2965 pSMB->Reserved3 = 0;
2966 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2967 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2968 byte_count = 3 /* pad */ + params + data_count;
2969 pSMB->DataCount = cpu_to_le16(data_count);
2970 pSMB->TotalDataCount = pSMB->DataCount;
2971 pSMB->ParameterCount = cpu_to_le16(params);
2972 pSMB->TotalParameterCount = pSMB->ParameterCount;
2973 pSMB->Reserved4 = 0;
2974 pSMB->hdr.smb_buf_length += byte_count;
2975 pSMB->ByteCount = cpu_to_le16(byte_count);
2976 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2979 cFYI(1, ("Set POSIX ACL returned %d", rc));
2983 cifs_buf_release(pSMB);
2989 /* BB fix tabs in this function FIXME BB */
2991 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2992 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2995 struct smb_t2_qfi_req *pSMB = NULL;
2996 struct smb_t2_qfi_rsp *pSMBr = NULL;
2998 __u16 params, byte_count;
3000 cFYI(1, ("In GetExtAttr"));
3005 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3010 params = 2 /* level */ +2 /* fid */;
3011 pSMB->t2.TotalDataCount = 0;
3012 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3013 /* BB find exact max data count below from sess structure BB */
3014 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3015 pSMB->t2.MaxSetupCount = 0;
3016 pSMB->t2.Reserved = 0;
3018 pSMB->t2.Timeout = 0;
3019 pSMB->t2.Reserved2 = 0;
3020 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3022 pSMB->t2.DataCount = 0;
3023 pSMB->t2.DataOffset = 0;
3024 pSMB->t2.SetupCount = 1;
3025 pSMB->t2.Reserved3 = 0;
3026 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3027 byte_count = params + 1 /* pad */ ;
3028 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3029 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3030 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3033 pSMB->hdr.smb_buf_length += byte_count;
3034 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3036 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3037 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3039 cFYI(1, ("error %d in GetExtAttr", rc));
3041 /* decode response */
3042 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3043 if (rc || (pSMBr->ByteCount < 2))
3044 /* BB also check enough total bytes returned */
3045 /* If rc should we check for EOPNOSUPP and
3046 disable the srvino flag? or in caller? */
3047 rc = -EIO; /* bad smb */
3049 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3050 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3051 struct file_chattr_info *pfinfo;
3052 /* BB Do we need a cast or hash here ? */
3054 cFYI(1, ("Illegal size ret in GetExtAttr"));
3058 pfinfo = (struct file_chattr_info *)
3059 (data_offset + (char *) &pSMBr->hdr.Protocol);
3060 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3061 *pMask = le64_to_cpu(pfinfo->mask);
3065 cifs_buf_release(pSMB);
3067 goto GetExtAttrRetry;
3071 #endif /* CONFIG_POSIX */
3073 #ifdef CONFIG_CIFS_EXPERIMENTAL
3074 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3076 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3077 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3081 QUERY_SEC_DESC_REQ * pSMB;
3084 cFYI(1, ("GetCifsACL"));
3089 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3090 8 /* parm len */, tcon, (void **) &pSMB);
3094 pSMB->MaxParameterCount = cpu_to_le32(4);
3095 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3096 pSMB->MaxSetupCount = 0;
3097 pSMB->Fid = fid; /* file handle always le */
3098 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3100 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3101 pSMB->hdr.smb_buf_length += 11;
3102 iov[0].iov_base = (char *)pSMB;
3103 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3105 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3106 0 /* not long op */, 0 /* do not log STATUS codes */ );
3107 cifs_stats_inc(&tcon->num_acl_get);
3109 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3110 } else { /* decode response */
3114 struct smb_com_ntransact_rsp *pSMBr;
3117 /* validate_nttransact */
3118 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3119 &pdata, &parm_len, pbuflen);
3122 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3124 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3126 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3127 rc = -EIO; /* bad smb */
3132 /* BB check that data area is minimum length and as big as acl_len */
3134 acl_len = le32_to_cpu(*parm);
3135 if (acl_len != *pbuflen) {
3136 cERROR(1, ("acl length %d does not match %d",
3137 acl_len, *pbuflen));
3138 if (*pbuflen > acl_len)
3142 /* check if buffer is big enough for the acl
3143 header followed by the smallest SID */
3144 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3145 (*pbuflen >= 64 * 1024)) {
3146 cERROR(1, ("bad acl length %d", *pbuflen));
3150 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3151 if (*acl_inf == NULL) {
3155 memcpy(*acl_inf, pdata, *pbuflen);
3159 if (buf_type == CIFS_SMALL_BUFFER)
3160 cifs_small_buf_release(iov[0].iov_base);
3161 else if (buf_type == CIFS_LARGE_BUFFER)
3162 cifs_buf_release(iov[0].iov_base);
3163 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3166 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3168 /* Legacy Query Path Information call for lookup to old servers such
3170 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3171 const unsigned char *searchName,
3172 FILE_ALL_INFO *pFinfo,
3173 const struct nls_table *nls_codepage, int remap)
3175 QUERY_INFORMATION_REQ * pSMB;
3176 QUERY_INFORMATION_RSP * pSMBr;
3181 cFYI(1, ("In SMBQPath path %s", searchName));
3183 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3188 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3190 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3191 PATH_MAX, nls_codepage, remap);
3192 name_len++; /* trailing null */
3195 name_len = strnlen(searchName, PATH_MAX);
3196 name_len++; /* trailing null */
3197 strncpy(pSMB->FileName, searchName, name_len);
3199 pSMB->BufferFormat = 0x04;
3200 name_len++; /* account for buffer type byte */
3201 pSMB->hdr.smb_buf_length += (__u16) name_len;
3202 pSMB->ByteCount = cpu_to_le16(name_len);
3204 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3205 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3207 cFYI(1, ("Send error in QueryInfo = %d", rc));
3208 } else if (pFinfo) { /* decode response */
3210 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3211 /* BB FIXME - add time zone adjustment BB */
3212 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3215 /* decode time fields */
3216 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3217 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3218 pFinfo->LastAccessTime = 0;
3219 pFinfo->AllocationSize =
3220 cpu_to_le64(le32_to_cpu(pSMBr->size));
3221 pFinfo->EndOfFile = pFinfo->AllocationSize;
3222 pFinfo->Attributes =
3223 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3225 rc = -EIO; /* bad buffer passed in */
3227 cifs_buf_release(pSMB);
3239 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3240 const unsigned char *searchName,
3241 FILE_ALL_INFO * pFindData,
3242 int legacy /* old style infolevel */,
3243 const struct nls_table *nls_codepage, int remap)
3245 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3246 TRANSACTION2_QPI_REQ *pSMB = NULL;
3247 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3251 __u16 params, byte_count;
3253 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3255 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3260 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3262 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3263 PATH_MAX, nls_codepage, remap);
3264 name_len++; /* trailing null */
3266 } else { /* BB improve the check for buffer overruns BB */
3267 name_len = strnlen(searchName, PATH_MAX);
3268 name_len++; /* trailing null */
3269 strncpy(pSMB->FileName, searchName, name_len);
3272 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3273 pSMB->TotalDataCount = 0;
3274 pSMB->MaxParameterCount = cpu_to_le16(2);
3275 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3276 pSMB->MaxSetupCount = 0;
3280 pSMB->Reserved2 = 0;
3281 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3282 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3283 pSMB->DataCount = 0;
3284 pSMB->DataOffset = 0;
3285 pSMB->SetupCount = 1;
3286 pSMB->Reserved3 = 0;
3287 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3288 byte_count = params + 1 /* pad */ ;
3289 pSMB->TotalParameterCount = cpu_to_le16(params);
3290 pSMB->ParameterCount = pSMB->TotalParameterCount;
3292 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3294 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3295 pSMB->Reserved4 = 0;
3296 pSMB->hdr.smb_buf_length += byte_count;
3297 pSMB->ByteCount = cpu_to_le16(byte_count);
3299 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3300 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3302 cFYI(1, ("Send error in QPathInfo = %d", rc));
3303 } else { /* decode response */
3304 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3306 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3308 else if (!legacy && (pSMBr->ByteCount < 40))
3309 rc = -EIO; /* bad smb */
3310 else if (legacy && (pSMBr->ByteCount < 24))
3311 rc = -EIO; /* 24 or 26 expected but we do not read
3313 else if (pFindData) {
3315 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3316 if (legacy) /* we do not read the last field, EAsize,
3317 fortunately since it varies by subdialect
3318 and on Set vs. Get, is two bytes or 4
3319 bytes depending but we don't care here */
3320 size = sizeof(FILE_INFO_STANDARD);
3322 size = sizeof(FILE_ALL_INFO);
3323 memcpy((char *) pFindData,
3324 (char *) &pSMBr->hdr.Protocol +
3329 cifs_buf_release(pSMB);
3331 goto QPathInfoRetry;
3337 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3338 const unsigned char *searchName,
3339 FILE_UNIX_BASIC_INFO * pFindData,
3340 const struct nls_table *nls_codepage, int remap)
3342 /* SMB_QUERY_FILE_UNIX_BASIC */
3343 TRANSACTION2_QPI_REQ *pSMB = NULL;
3344 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3346 int bytes_returned = 0;
3348 __u16 params, byte_count;
3350 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3352 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3357 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3359 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3360 PATH_MAX, nls_codepage, remap);
3361 name_len++; /* trailing null */
3363 } else { /* BB improve the check for buffer overruns BB */
3364 name_len = strnlen(searchName, PATH_MAX);
3365 name_len++; /* trailing null */
3366 strncpy(pSMB->FileName, searchName, name_len);
3369 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3370 pSMB->TotalDataCount = 0;
3371 pSMB->MaxParameterCount = cpu_to_le16(2);
3372 /* BB find exact max SMB PDU from sess structure BB */
3373 pSMB->MaxDataCount = cpu_to_le16(4000);
3374 pSMB->MaxSetupCount = 0;
3378 pSMB->Reserved2 = 0;
3379 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3380 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3381 pSMB->DataCount = 0;
3382 pSMB->DataOffset = 0;
3383 pSMB->SetupCount = 1;
3384 pSMB->Reserved3 = 0;
3385 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3386 byte_count = params + 1 /* pad */ ;
3387 pSMB->TotalParameterCount = cpu_to_le16(params);
3388 pSMB->ParameterCount = pSMB->TotalParameterCount;
3389 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3390 pSMB->Reserved4 = 0;
3391 pSMB->hdr.smb_buf_length += byte_count;
3392 pSMB->ByteCount = cpu_to_le16(byte_count);
3394 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3395 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3397 cFYI(1, ("Send error in QPathInfo = %d", rc));
3398 } else { /* decode response */
3399 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3401 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3402 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3403 "Unix Extensions can be disabled on mount "
3404 "by specifying the nosfu mount option."));
3405 rc = -EIO; /* bad smb */
3407 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3408 memcpy((char *) pFindData,
3409 (char *) &pSMBr->hdr.Protocol +
3411 sizeof(FILE_UNIX_BASIC_INFO));
3414 cifs_buf_release(pSMB);
3416 goto UnixQPathInfoRetry;
3421 #if 0 /* function unused at present */
3422 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3423 const char *searchName, FILE_ALL_INFO * findData,
3424 const struct nls_table *nls_codepage)
3426 /* level 257 SMB_ */
3427 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3428 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3432 __u16 params, byte_count;
3434 cFYI(1, ("In FindUnique"));
3436 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3441 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3443 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3444 PATH_MAX, nls_codepage);
3445 name_len++; /* trailing null */
3447 } else { /* BB improve the check for buffer overruns BB */
3448 name_len = strnlen(searchName, PATH_MAX);
3449 name_len++; /* trailing null */
3450 strncpy(pSMB->FileName, searchName, name_len);
3453 params = 12 + name_len /* includes null */ ;
3454 pSMB->TotalDataCount = 0; /* no EAs */
3455 pSMB->MaxParameterCount = cpu_to_le16(2);
3456 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3457 pSMB->MaxSetupCount = 0;
3461 pSMB->Reserved2 = 0;
3462 pSMB->ParameterOffset = cpu_to_le16(
3463 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3464 pSMB->DataCount = 0;
3465 pSMB->DataOffset = 0;
3466 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3467 pSMB->Reserved3 = 0;
3468 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3469 byte_count = params + 1 /* pad */ ;
3470 pSMB->TotalParameterCount = cpu_to_le16(params);
3471 pSMB->ParameterCount = pSMB->TotalParameterCount;
3472 pSMB->SearchAttributes =
3473 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3475 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3476 pSMB->SearchFlags = cpu_to_le16(1);
3477 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3478 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3479 pSMB->hdr.smb_buf_length += byte_count;
3480 pSMB->ByteCount = cpu_to_le16(byte_count);
3482 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3483 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3486 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3487 } else { /* decode response */
3488 cifs_stats_inc(&tcon->num_ffirst);
3492 cifs_buf_release(pSMB);
3494 goto findUniqueRetry;
3498 #endif /* end unused (temporarily) function */
3500 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3502 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3503 const char *searchName,
3504 const struct nls_table *nls_codepage,
3506 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3508 /* level 257 SMB_ */
3509 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3510 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3511 T2_FFIRST_RSP_PARMS * parms;
3513 int bytes_returned = 0;
3515 __u16 params, byte_count;
3517 cFYI(1, ("In FindFirst for %s", searchName));
3520 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3525 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3527 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3528 PATH_MAX, nls_codepage, remap);
3529 /* We can not add the asterik earlier in case
3530 it got remapped to 0xF03A as if it were part of the
3531 directory name instead of a wildcard */
3533 pSMB->FileName[name_len] = dirsep;
3534 pSMB->FileName[name_len+1] = 0;
3535 pSMB->FileName[name_len+2] = '*';
3536 pSMB->FileName[name_len+3] = 0;
3537 name_len += 4; /* now the trailing null */
3538 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3539 pSMB->FileName[name_len+1] = 0;
3541 } else { /* BB add check for overrun of SMB buf BB */
3542 name_len = strnlen(searchName, PATH_MAX);
3543 /* BB fix here and in unicode clause above ie
3544 if (name_len > buffersize-header)
3545 free buffer exit; BB */
3546 strncpy(pSMB->FileName, searchName, name_len);
3547 pSMB->FileName[name_len] = dirsep;
3548 pSMB->FileName[name_len+1] = '*';
3549 pSMB->FileName[name_len+2] = 0;
3553 params = 12 + name_len /* includes null */ ;
3554 pSMB->TotalDataCount = 0; /* no EAs */
3555 pSMB->MaxParameterCount = cpu_to_le16(10);
3556 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3557 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3558 pSMB->MaxSetupCount = 0;
3562 pSMB->Reserved2 = 0;
3563 byte_count = params + 1 /* pad */ ;
3564 pSMB->TotalParameterCount = cpu_to_le16(params);
3565 pSMB->ParameterCount = pSMB->TotalParameterCount;
3566 pSMB->ParameterOffset = cpu_to_le16(
3567 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3569 pSMB->DataCount = 0;
3570 pSMB->DataOffset = 0;
3571 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3572 pSMB->Reserved3 = 0;
3573 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3574 pSMB->SearchAttributes =
3575 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3577 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3578 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3579 CIFS_SEARCH_RETURN_RESUME);
3580 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3582 /* BB what should we set StorageType to? Does it matter? BB */
3583 pSMB->SearchStorageType = 0;
3584 pSMB->hdr.smb_buf_length += byte_count;
3585 pSMB->ByteCount = cpu_to_le16(byte_count);
3587 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3588 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3589 cifs_stats_inc(&tcon->num_ffirst);
3591 if (rc) {/* BB add logic to retry regular search if Unix search
3592 rejected unexpectedly by server */
3593 /* BB Add code to handle unsupported level rc */
3594 cFYI(1, ("Error in FindFirst = %d", rc));
3596 cifs_buf_release(pSMB);
3598 /* BB eventually could optimize out free and realloc of buf */
3601 goto findFirstRetry;
3602 } else { /* decode response */
3603 /* BB remember to free buffer if error BB */
3604 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3606 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3607 psrch_inf->unicode = TRUE;
3609 psrch_inf->unicode = FALSE;
3611 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3612 psrch_inf->smallBuf = 0;
3613 psrch_inf->srch_entries_start =
3614 (char *) &pSMBr->hdr.Protocol +
3615 le16_to_cpu(pSMBr->t2.DataOffset);
3616 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3617 le16_to_cpu(pSMBr->t2.ParameterOffset));
3619 if (parms->EndofSearch)
3620 psrch_inf->endOfSearch = TRUE;
3622 psrch_inf->endOfSearch = FALSE;
3624 psrch_inf->entries_in_buffer =
3625 le16_to_cpu(parms->SearchCount);
3626 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3627 psrch_inf->entries_in_buffer;
3628 *pnetfid = parms->SearchHandle;
3630 cifs_buf_release(pSMB);
3637 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3638 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3640 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3641 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3642 T2_FNEXT_RSP_PARMS * parms;
3643 char *response_data;
3645 int bytes_returned, name_len;
3646 __u16 params, byte_count;
3648 cFYI(1, ("In FindNext"));
3650 if (psrch_inf->endOfSearch == TRUE)
3653 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3658 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3660 pSMB->TotalDataCount = 0; /* no EAs */
3661 pSMB->MaxParameterCount = cpu_to_le16(8);
3662 pSMB->MaxDataCount =
3663 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3665 pSMB->MaxSetupCount = 0;
3669 pSMB->Reserved2 = 0;
3670 pSMB->ParameterOffset = cpu_to_le16(
3671 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3672 pSMB->DataCount = 0;
3673 pSMB->DataOffset = 0;
3674 pSMB->SetupCount = 1;
3675 pSMB->Reserved3 = 0;
3676 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3677 pSMB->SearchHandle = searchHandle; /* always kept as le */
3679 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3680 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3681 pSMB->ResumeKey = psrch_inf->resume_key;
3683 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3685 name_len = psrch_inf->resume_name_len;
3687 if (name_len < PATH_MAX) {
3688 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3689 byte_count += name_len;
3690 /* 14 byte parm len above enough for 2 byte null terminator */
3691 pSMB->ResumeFileName[name_len] = 0;
3692 pSMB->ResumeFileName[name_len+1] = 0;
3695 goto FNext2_err_exit;
3697 byte_count = params + 1 /* pad */ ;
3698 pSMB->TotalParameterCount = cpu_to_le16(params);
3699 pSMB->ParameterCount = pSMB->TotalParameterCount;
3700 pSMB->hdr.smb_buf_length += byte_count;
3701 pSMB->ByteCount = cpu_to_le16(byte_count);
3703 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3704 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3705 cifs_stats_inc(&tcon->num_fnext);
3708 psrch_inf->endOfSearch = TRUE;
3709 rc = 0; /* search probably was closed at end of search*/
3711 cFYI(1, ("FindNext returned = %d", rc));
3712 } else { /* decode response */
3713 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3716 /* BB fixme add lock for file (srch_info) struct here */
3717 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3718 psrch_inf->unicode = TRUE;
3720 psrch_inf->unicode = FALSE;
3721 response_data = (char *) &pSMBr->hdr.Protocol +
3722 le16_to_cpu(pSMBr->t2.ParameterOffset);
3723 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3724 response_data = (char *)&pSMBr->hdr.Protocol +
3725 le16_to_cpu(pSMBr->t2.DataOffset);
3726 if (psrch_inf->smallBuf)
3727 cifs_small_buf_release(
3728 psrch_inf->ntwrk_buf_start);
3730 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3731 psrch_inf->srch_entries_start = response_data;
3732 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3733 psrch_inf->smallBuf = 0;
3734 if (parms->EndofSearch)
3735 psrch_inf->endOfSearch = TRUE;
3737 psrch_inf->endOfSearch = FALSE;
3738 psrch_inf->entries_in_buffer =
3739 le16_to_cpu(parms->SearchCount);
3740 psrch_inf->index_of_last_entry +=
3741 psrch_inf->entries_in_buffer;
3742 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3743 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3745 /* BB fixme add unlock here */
3750 /* BB On error, should we leave previous search buf (and count and
3751 last entry fields) intact or free the previous one? */
3753 /* Note: On -EAGAIN error only caller can retry on handle based calls
3754 since file handle passed in no longer valid */
3757 cifs_buf_release(pSMB);
3762 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3763 const __u16 searchHandle)
3766 FINDCLOSE_REQ *pSMB = NULL;
3767 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3770 cFYI(1, ("In CIFSSMBFindClose"));
3771 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3773 /* no sense returning error if session restarted
3774 as file handle has been closed */
3780 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3781 pSMB->FileID = searchHandle;
3782 pSMB->ByteCount = 0;
3783 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3784 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3786 cERROR(1, ("Send error in FindClose = %d", rc));
3788 cifs_stats_inc(&tcon->num_fclose);
3789 cifs_small_buf_release(pSMB);
3791 /* Since session is dead, search handle closed on server already */
3799 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3800 const unsigned char *searchName,
3801 __u64 * inode_number,
3802 const struct nls_table *nls_codepage, int remap)
3805 TRANSACTION2_QPI_REQ *pSMB = NULL;
3806 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3807 int name_len, bytes_returned;
3808 __u16 params, byte_count;
3810 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3814 GetInodeNumberRetry:
3815 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3820 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3822 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3823 PATH_MAX, nls_codepage, remap);
3824 name_len++; /* trailing null */
3826 } else { /* BB improve the check for buffer overruns BB */
3827 name_len = strnlen(searchName, PATH_MAX);
3828 name_len++; /* trailing null */
3829 strncpy(pSMB->FileName, searchName, name_len);
3832 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3833 pSMB->TotalDataCount = 0;
3834 pSMB->MaxParameterCount = cpu_to_le16(2);
3835 /* BB find exact max data count below from sess structure BB */
3836 pSMB->MaxDataCount = cpu_to_le16(4000);
3837 pSMB->MaxSetupCount = 0;
3841 pSMB->Reserved2 = 0;
3842 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3843 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3844 pSMB->DataCount = 0;
3845 pSMB->DataOffset = 0;
3846 pSMB->SetupCount = 1;
3847 pSMB->Reserved3 = 0;
3848 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3849 byte_count = params + 1 /* pad */ ;
3850 pSMB->TotalParameterCount = cpu_to_le16(params);
3851 pSMB->ParameterCount = pSMB->TotalParameterCount;
3852 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3853 pSMB->Reserved4 = 0;
3854 pSMB->hdr.smb_buf_length += byte_count;
3855 pSMB->ByteCount = cpu_to_le16(byte_count);
3857 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3858 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3860 cFYI(1, ("error %d in QueryInternalInfo", rc));
3862 /* decode response */
3863 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3864 if (rc || (pSMBr->ByteCount < 2))
3865 /* BB also check enough total bytes returned */
3866 /* If rc should we check for EOPNOSUPP and
3867 disable the srvino flag? or in caller? */
3868 rc = -EIO; /* bad smb */
3870 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3871 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3872 struct file_internal_info *pfinfo;
3873 /* BB Do we need a cast or hash here ? */
3875 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3877 goto GetInodeNumOut;
3879 pfinfo = (struct file_internal_info *)
3880 (data_offset + (char *) &pSMBr->hdr.Protocol);
3881 *inode_number = pfinfo->UniqueId;
3885 cifs_buf_release(pSMB);
3887 goto GetInodeNumberRetry;
3892 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3893 const unsigned char *searchName,
3894 unsigned char **targetUNCs,
3895 unsigned int *number_of_UNC_in_array,
3896 const struct nls_table *nls_codepage, int remap)
3898 /* TRANS2_GET_DFS_REFERRAL */
3899 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3900 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3901 struct dfs_referral_level_3 *referrals = NULL;
3907 __u16 params, byte_count;
3908 *number_of_UNC_in_array = 0;
3911 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3915 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3920 /* server pointer checked in called function,
3921 but should never be null here anyway */
3922 pSMB->hdr.Mid = GetNextMid(ses->server);
3923 pSMB->hdr.Tid = ses->ipc_tid;
3924 pSMB->hdr.Uid = ses->Suid;
3925 if (ses->capabilities & CAP_STATUS32)
3926 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3927 if (ses->capabilities & CAP_DFS)
3928 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3930 if (ses->capabilities & CAP_UNICODE) {
3931 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3933 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3934 searchName, PATH_MAX, nls_codepage, remap);
3935 name_len++; /* trailing null */
3937 } else { /* BB improve the check for buffer overruns BB */
3938 name_len = strnlen(searchName, PATH_MAX);
3939 name_len++; /* trailing null */
3940 strncpy(pSMB->RequestFileName, searchName, name_len);
3944 if (ses->server->secMode &
3945 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3946 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3949 pSMB->hdr.Uid = ses->Suid;
3951 params = 2 /* level */ + name_len /*includes null */ ;
3952 pSMB->TotalDataCount = 0;
3953 pSMB->DataCount = 0;
3954 pSMB->DataOffset = 0;
3955 pSMB->MaxParameterCount = 0;
3956 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3957 pSMB->MaxSetupCount = 0;
3961 pSMB->Reserved2 = 0;
3962 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3963 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3964 pSMB->SetupCount = 1;
3965 pSMB->Reserved3 = 0;
3966 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3967 byte_count = params + 3 /* pad */ ;
3968 pSMB->ParameterCount = cpu_to_le16(params);
3969 pSMB->TotalParameterCount = pSMB->ParameterCount;
3970 pSMB->MaxReferralLevel = cpu_to_le16(3);
3971 pSMB->hdr.smb_buf_length += byte_count;
3972 pSMB->ByteCount = cpu_to_le16(byte_count);
3974 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3977 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3978 } else { /* decode response */
3979 /* BB Add logic to parse referrals here */
3980 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3982 /* BB Also check if enough total bytes returned? */
3983 if (rc || (pSMBr->ByteCount < 17))
3984 rc = -EIO; /* bad smb */
3986 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3987 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3990 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3991 pSMBr->ByteCount, data_offset));
3993 (struct dfs_referral_level_3 *)
3994 (8 /* sizeof start of data block */ +
3996 (char *) &pSMBr->hdr.Protocol);
3997 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3998 "for referral one refer size: 0x%x srv "
3999 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
4000 le16_to_cpu(pSMBr->NumberOfReferrals),
4001 le16_to_cpu(pSMBr->DFSFlags),
4002 le16_to_cpu(referrals->ReferralSize),
4003 le16_to_cpu(referrals->ServerType),
4004 le16_to_cpu(referrals->ReferralFlags),
4005 le16_to_cpu(referrals->TimeToLive)));
4006 /* BB This field is actually two bytes in from start of
4007 data block so we could do safety check that DataBlock
4008 begins at address of pSMBr->NumberOfReferrals */
4009 *number_of_UNC_in_array =
4010 le16_to_cpu(pSMBr->NumberOfReferrals);
4012 /* BB Fix below so can return more than one referral */
4013 if (*number_of_UNC_in_array > 1)
4014 *number_of_UNC_in_array = 1;
4016 /* get the length of the strings describing refs */
4018 for (i = 0; i < *number_of_UNC_in_array; i++) {
4019 /* make sure that DfsPathOffset not past end */
4021 le16_to_cpu(referrals->DfsPathOffset);
4022 if (offset > data_count) {
4023 /* if invalid referral, stop here and do
4024 not try to copy any more */
4025 *number_of_UNC_in_array = i;
4028 temp = ((char *)referrals) + offset;
4030 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4031 name_len += UniStrnlen((wchar_t *)temp,
4034 name_len += strnlen(temp, data_count);
4037 /* BB add check that referral pointer does
4038 not fall off end PDU */
4040 /* BB add check for name_len bigger than bcc */
4042 kmalloc(name_len+1+(*number_of_UNC_in_array),
4044 if (*targetUNCs == NULL) {
4048 /* copy the ref strings */
4049 referrals = (struct dfs_referral_level_3 *)
4050 (8 /* sizeof data hdr */ + data_offset +
4051 (char *) &pSMBr->hdr.Protocol);
4053 for (i = 0; i < *number_of_UNC_in_array; i++) {
4054 temp = ((char *)referrals) +
4055 le16_to_cpu(referrals->DfsPathOffset);
4056 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4057 cifs_strfromUCS_le(*targetUNCs,
4062 strncpy(*targetUNCs, temp, name_len);
4064 /* BB update target_uncs pointers */
4074 cifs_buf_release(pSMB);
4082 /* Query File System Info such as free space to old servers such as Win 9x */
4084 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4086 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4087 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4088 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4089 FILE_SYSTEM_ALLOC_INFO *response_data;
4091 int bytes_returned = 0;
4092 __u16 params, byte_count;
4094 cFYI(1, ("OldQFSInfo"));
4096 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4101 params = 2; /* level */
4102 pSMB->TotalDataCount = 0;
4103 pSMB->MaxParameterCount = cpu_to_le16(2);
4104 pSMB->MaxDataCount = cpu_to_le16(1000);
4105 pSMB->MaxSetupCount = 0;
4109 pSMB->Reserved2 = 0;
4110 byte_count = params + 1 /* pad */ ;
4111 pSMB->TotalParameterCount = cpu_to_le16(params);
4112 pSMB->ParameterCount = pSMB->TotalParameterCount;
4113 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4114 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4115 pSMB->DataCount = 0;
4116 pSMB->DataOffset = 0;
4117 pSMB->SetupCount = 1;
4118 pSMB->Reserved3 = 0;
4119 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4120 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4121 pSMB->hdr.smb_buf_length += byte_count;
4122 pSMB->ByteCount = cpu_to_le16(byte_count);
4124 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4125 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4127 cFYI(1, ("Send error in QFSInfo = %d", rc));
4128 } else { /* decode response */
4129 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4131 if (rc || (pSMBr->ByteCount < 18))
4132 rc = -EIO; /* bad smb */
4134 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4135 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4136 pSMBr->ByteCount, data_offset));
4138 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4139 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4141 le16_to_cpu(response_data->BytesPerSector) *
4142 le32_to_cpu(response_data->
4143 SectorsPerAllocationUnit);
4145 le32_to_cpu(response_data->TotalAllocationUnits);
4146 FSData->f_bfree = FSData->f_bavail =
4147 le32_to_cpu(response_data->FreeAllocationUnits);
4149 ("Blocks: %lld Free: %lld Block size %ld",
4150 (unsigned long long)FSData->f_blocks,
4151 (unsigned long long)FSData->f_bfree,
4155 cifs_buf_release(pSMB);
4158 goto oldQFSInfoRetry;
4164 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4166 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4167 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4168 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4169 FILE_SYSTEM_INFO *response_data;
4171 int bytes_returned = 0;
4172 __u16 params, byte_count;
4174 cFYI(1, ("In QFSInfo"));
4176 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4181 params = 2; /* level */
4182 pSMB->TotalDataCount = 0;
4183 pSMB->MaxParameterCount = cpu_to_le16(2);
4184 pSMB->MaxDataCount = cpu_to_le16(1000);
4185 pSMB->MaxSetupCount = 0;
4189 pSMB->Reserved2 = 0;
4190 byte_count = params + 1 /* pad */ ;
4191 pSMB->TotalParameterCount = cpu_to_le16(params);
4192 pSMB->ParameterCount = pSMB->TotalParameterCount;
4193 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4194 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4195 pSMB->DataCount = 0;
4196 pSMB->DataOffset = 0;
4197 pSMB->SetupCount = 1;
4198 pSMB->Reserved3 = 0;
4199 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4200 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4201 pSMB->hdr.smb_buf_length += byte_count;
4202 pSMB->ByteCount = cpu_to_le16(byte_count);
4204 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4205 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4207 cFYI(1, ("Send error in QFSInfo = %d", rc));
4208 } else { /* decode response */
4209 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4211 if (rc || (pSMBr->ByteCount < 24))
4212 rc = -EIO; /* bad smb */
4214 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4218 *) (((char *) &pSMBr->hdr.Protocol) +
4221 le32_to_cpu(response_data->BytesPerSector) *
4222 le32_to_cpu(response_data->
4223 SectorsPerAllocationUnit);
4225 le64_to_cpu(response_data->TotalAllocationUnits);
4226 FSData->f_bfree = FSData->f_bavail =
4227 le64_to_cpu(response_data->FreeAllocationUnits);
4229 ("Blocks: %lld Free: %lld Block size %ld",
4230 (unsigned long long)FSData->f_blocks,
4231 (unsigned long long)FSData->f_bfree,
4235 cifs_buf_release(pSMB);
4244 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4246 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4247 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4248 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4249 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4251 int bytes_returned = 0;
4252 __u16 params, byte_count;
4254 cFYI(1, ("In QFSAttributeInfo"));
4256 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4261 params = 2; /* level */
4262 pSMB->TotalDataCount = 0;
4263 pSMB->MaxParameterCount = cpu_to_le16(2);
4264 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4265 pSMB->MaxSetupCount = 0;
4269 pSMB->Reserved2 = 0;
4270 byte_count = params + 1 /* pad */ ;
4271 pSMB->TotalParameterCount = cpu_to_le16(params);
4272 pSMB->ParameterCount = pSMB->TotalParameterCount;
4273 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4274 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4275 pSMB->DataCount = 0;
4276 pSMB->DataOffset = 0;
4277 pSMB->SetupCount = 1;
4278 pSMB->Reserved3 = 0;
4279 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4280 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4281 pSMB->hdr.smb_buf_length += byte_count;
4282 pSMB->ByteCount = cpu_to_le16(byte_count);
4284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4287 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4288 } else { /* decode response */
4289 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4291 if (rc || (pSMBr->ByteCount < 13)) {
4292 /* BB also check if enough bytes returned */
4293 rc = -EIO; /* bad smb */
4295 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4297 (FILE_SYSTEM_ATTRIBUTE_INFO
4298 *) (((char *) &pSMBr->hdr.Protocol) +
4300 memcpy(&tcon->fsAttrInfo, response_data,
4301 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4304 cifs_buf_release(pSMB);
4307 goto QFSAttributeRetry;
4313 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4315 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4316 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4317 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4318 FILE_SYSTEM_DEVICE_INFO *response_data;
4320 int bytes_returned = 0;
4321 __u16 params, byte_count;
4323 cFYI(1, ("In QFSDeviceInfo"));
4325 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4330 params = 2; /* level */
4331 pSMB->TotalDataCount = 0;
4332 pSMB->MaxParameterCount = cpu_to_le16(2);
4333 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4334 pSMB->MaxSetupCount = 0;
4338 pSMB->Reserved2 = 0;
4339 byte_count = params + 1 /* pad */ ;
4340 pSMB->TotalParameterCount = cpu_to_le16(params);
4341 pSMB->ParameterCount = pSMB->TotalParameterCount;
4342 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4343 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4345 pSMB->DataCount = 0;
4346 pSMB->DataOffset = 0;
4347 pSMB->SetupCount = 1;
4348 pSMB->Reserved3 = 0;
4349 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4350 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4351 pSMB->hdr.smb_buf_length += byte_count;
4352 pSMB->ByteCount = cpu_to_le16(byte_count);
4354 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4355 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4357 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4358 } else { /* decode response */
4359 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4361 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4362 rc = -EIO; /* bad smb */
4364 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4366 (FILE_SYSTEM_DEVICE_INFO *)
4367 (((char *) &pSMBr->hdr.Protocol) +
4369 memcpy(&tcon->fsDevInfo, response_data,
4370 sizeof(FILE_SYSTEM_DEVICE_INFO));
4373 cifs_buf_release(pSMB);
4376 goto QFSDeviceRetry;
4382 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4384 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4385 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4386 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4387 FILE_SYSTEM_UNIX_INFO *response_data;
4389 int bytes_returned = 0;
4390 __u16 params, byte_count;
4392 cFYI(1, ("In QFSUnixInfo"));
4394 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4399 params = 2; /* level */
4400 pSMB->TotalDataCount = 0;
4401 pSMB->DataCount = 0;
4402 pSMB->DataOffset = 0;
4403 pSMB->MaxParameterCount = cpu_to_le16(2);
4404 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4405 pSMB->MaxSetupCount = 0;
4409 pSMB->Reserved2 = 0;
4410 byte_count = params + 1 /* pad */ ;
4411 pSMB->ParameterCount = cpu_to_le16(params);
4412 pSMB->TotalParameterCount = pSMB->ParameterCount;
4413 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4414 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4415 pSMB->SetupCount = 1;
4416 pSMB->Reserved3 = 0;
4417 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4418 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4419 pSMB->hdr.smb_buf_length += byte_count;
4420 pSMB->ByteCount = cpu_to_le16(byte_count);
4422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4425 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4426 } else { /* decode response */
4427 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4429 if (rc || (pSMBr->ByteCount < 13)) {
4430 rc = -EIO; /* bad smb */
4432 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4434 (FILE_SYSTEM_UNIX_INFO
4435 *) (((char *) &pSMBr->hdr.Protocol) +
4437 memcpy(&tcon->fsUnixInfo, response_data,
4438 sizeof(FILE_SYSTEM_UNIX_INFO));
4441 cifs_buf_release(pSMB);
4451 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4453 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4454 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4455 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4457 int bytes_returned = 0;
4458 __u16 params, param_offset, offset, byte_count;
4460 cFYI(1, ("In SETFSUnixInfo"));
4462 /* BB switch to small buf init to save memory */
4463 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4468 params = 4; /* 2 bytes zero followed by info level. */
4469 pSMB->MaxSetupCount = 0;
4473 pSMB->Reserved2 = 0;
4474 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4476 offset = param_offset + params;
4478 pSMB->MaxParameterCount = cpu_to_le16(4);
4479 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4480 pSMB->SetupCount = 1;
4481 pSMB->Reserved3 = 0;
4482 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4483 byte_count = 1 /* pad */ + params + 12;
4485 pSMB->DataCount = cpu_to_le16(12);
4486 pSMB->ParameterCount = cpu_to_le16(params);
4487 pSMB->TotalDataCount = pSMB->DataCount;
4488 pSMB->TotalParameterCount = pSMB->ParameterCount;
4489 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4490 pSMB->DataOffset = cpu_to_le16(offset);
4494 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4497 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4498 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4499 pSMB->ClientUnixCap = cpu_to_le64(cap);
4501 pSMB->hdr.smb_buf_length += byte_count;
4502 pSMB->ByteCount = cpu_to_le16(byte_count);
4504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4505 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4507 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4508 } else { /* decode response */
4509 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4511 rc = -EIO; /* bad smb */
4514 cifs_buf_release(pSMB);
4517 goto SETFSUnixRetry;
4525 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4526 struct kstatfs *FSData)
4528 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4529 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4530 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4531 FILE_SYSTEM_POSIX_INFO *response_data;
4533 int bytes_returned = 0;
4534 __u16 params, byte_count;
4536 cFYI(1, ("In QFSPosixInfo"));
4538 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4543 params = 2; /* level */
4544 pSMB->TotalDataCount = 0;
4545 pSMB->DataCount = 0;
4546 pSMB->DataOffset = 0;
4547 pSMB->MaxParameterCount = cpu_to_le16(2);
4548 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4549 pSMB->MaxSetupCount = 0;
4553 pSMB->Reserved2 = 0;
4554 byte_count = params + 1 /* pad */ ;
4555 pSMB->ParameterCount = cpu_to_le16(params);
4556 pSMB->TotalParameterCount = pSMB->ParameterCount;
4557 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4558 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4559 pSMB->SetupCount = 1;
4560 pSMB->Reserved3 = 0;
4561 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4562 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4563 pSMB->hdr.smb_buf_length += byte_count;
4564 pSMB->ByteCount = cpu_to_le16(byte_count);
4566 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4567 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4569 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4570 } else { /* decode response */
4571 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4573 if (rc || (pSMBr->ByteCount < 13)) {
4574 rc = -EIO; /* bad smb */
4576 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4578 (FILE_SYSTEM_POSIX_INFO
4579 *) (((char *) &pSMBr->hdr.Protocol) +
4582 le32_to_cpu(response_data->BlockSize);
4584 le64_to_cpu(response_data->TotalBlocks);
4586 le64_to_cpu(response_data->BlocksAvail);
4587 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4588 FSData->f_bavail = FSData->f_bfree;
4591 le64_to_cpu(response_data->UserBlocksAvail);
4593 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4595 le64_to_cpu(response_data->TotalFileNodes);
4596 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4598 le64_to_cpu(response_data->FreeFileNodes);
4601 cifs_buf_release(pSMB);
4610 /* We can not use write of zero bytes trick to
4611 set file size due to need for large file support. Also note that
4612 this SetPathInfo is preferred to SetFileInfo based method in next
4613 routine which is only needed to work around a sharing violation bug
4614 in Samba which this routine can run into */
4617 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4618 __u64 size, int SetAllocation,
4619 const struct nls_table *nls_codepage, int remap)
4621 struct smb_com_transaction2_spi_req *pSMB = NULL;
4622 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4623 struct file_end_of_file_info *parm_data;
4626 int bytes_returned = 0;
4627 __u16 params, byte_count, data_count, param_offset, offset;
4629 cFYI(1, ("In SetEOF"));
4631 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4636 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4638 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4639 PATH_MAX, nls_codepage, remap);
4640 name_len++; /* trailing null */
4642 } else { /* BB improve the check for buffer overruns BB */
4643 name_len = strnlen(fileName, PATH_MAX);
4644 name_len++; /* trailing null */
4645 strncpy(pSMB->FileName, fileName, name_len);
4647 params = 6 + name_len;
4648 data_count = sizeof(struct file_end_of_file_info);
4649 pSMB->MaxParameterCount = cpu_to_le16(2);
4650 pSMB->MaxDataCount = cpu_to_le16(4100);
4651 pSMB->MaxSetupCount = 0;
4655 pSMB->Reserved2 = 0;
4656 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4657 InformationLevel) - 4;
4658 offset = param_offset + params;
4659 if (SetAllocation) {
4660 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4661 pSMB->InformationLevel =
4662 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4664 pSMB->InformationLevel =
4665 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4666 } else /* Set File Size */ {
4667 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4668 pSMB->InformationLevel =
4669 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4671 pSMB->InformationLevel =
4672 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4676 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4678 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4679 pSMB->DataOffset = cpu_to_le16(offset);
4680 pSMB->SetupCount = 1;
4681 pSMB->Reserved3 = 0;
4682 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4683 byte_count = 3 /* pad */ + params + data_count;
4684 pSMB->DataCount = cpu_to_le16(data_count);
4685 pSMB->TotalDataCount = pSMB->DataCount;
4686 pSMB->ParameterCount = cpu_to_le16(params);
4687 pSMB->TotalParameterCount = pSMB->ParameterCount;
4688 pSMB->Reserved4 = 0;
4689 pSMB->hdr.smb_buf_length += byte_count;
4690 parm_data->FileSize = cpu_to_le64(size);
4691 pSMB->ByteCount = cpu_to_le16(byte_count);
4692 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4693 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4695 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4698 cifs_buf_release(pSMB);
4707 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4708 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4710 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4711 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4713 struct file_end_of_file_info *parm_data;
4715 int bytes_returned = 0;
4716 __u16 params, param_offset, offset, byte_count, count;
4718 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4720 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4725 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4727 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4728 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4731 pSMB->MaxSetupCount = 0;
4735 pSMB->Reserved2 = 0;
4736 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4737 offset = param_offset + params;
4739 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4741 count = sizeof(struct file_end_of_file_info);
4742 pSMB->MaxParameterCount = cpu_to_le16(2);
4743 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4744 pSMB->SetupCount = 1;
4745 pSMB->Reserved3 = 0;
4746 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4747 byte_count = 3 /* pad */ + params + count;
4748 pSMB->DataCount = cpu_to_le16(count);
4749 pSMB->ParameterCount = cpu_to_le16(params);
4750 pSMB->TotalDataCount = pSMB->DataCount;
4751 pSMB->TotalParameterCount = pSMB->ParameterCount;
4752 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4754 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4756 pSMB->DataOffset = cpu_to_le16(offset);
4757 parm_data->FileSize = cpu_to_le64(size);
4759 if (SetAllocation) {
4760 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4761 pSMB->InformationLevel =
4762 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4764 pSMB->InformationLevel =
4765 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4766 } else /* Set File Size */ {
4767 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4768 pSMB->InformationLevel =
4769 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4771 pSMB->InformationLevel =
4772 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4774 pSMB->Reserved4 = 0;
4775 pSMB->hdr.smb_buf_length += byte_count;
4776 pSMB->ByteCount = cpu_to_le16(byte_count);
4777 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4778 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4781 ("Send error in SetFileInfo (SetFileSize) = %d",
4786 cifs_small_buf_release(pSMB);
4788 /* Note: On -EAGAIN error only caller can retry on handle based calls
4789 since file handle passed in no longer valid */
4794 /* Some legacy servers such as NT4 require that the file times be set on
4795 an open handle, rather than by pathname - this is awkward due to
4796 potential access conflicts on the open, but it is unavoidable for these
4797 old servers since the only other choice is to go from 100 nanosecond DCE
4798 time and resort to the original setpathinfo level which takes the ancient
4799 DOS time format with 2 second granularity */
4801 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4802 const FILE_BASIC_INFO *data, __u16 fid)
4804 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4805 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4808 int bytes_returned = 0;
4809 __u16 params, param_offset, offset, byte_count, count;
4811 cFYI(1, ("Set Times (via SetFileInfo)"));
4812 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4817 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4819 /* At this point there is no need to override the current pid
4820 with the pid of the opener, but that could change if we someday
4821 use an existing handle (rather than opening one on the fly) */
4822 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4823 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4826 pSMB->MaxSetupCount = 0;
4830 pSMB->Reserved2 = 0;
4831 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4832 offset = param_offset + params;
4834 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4836 count = sizeof(FILE_BASIC_INFO);
4837 pSMB->MaxParameterCount = cpu_to_le16(2);
4838 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4839 pSMB->SetupCount = 1;
4840 pSMB->Reserved3 = 0;
4841 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4842 byte_count = 3 /* pad */ + params + count;
4843 pSMB->DataCount = cpu_to_le16(count);
4844 pSMB->ParameterCount = cpu_to_le16(params);
4845 pSMB->TotalDataCount = pSMB->DataCount;
4846 pSMB->TotalParameterCount = pSMB->ParameterCount;
4847 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4848 pSMB->DataOffset = cpu_to_le16(offset);
4850 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4851 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4853 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4854 pSMB->Reserved4 = 0;
4855 pSMB->hdr.smb_buf_length += byte_count;
4856 pSMB->ByteCount = cpu_to_le16(byte_count);
4857 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4858 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4859 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4861 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4864 cifs_small_buf_release(pSMB);
4866 /* Note: On -EAGAIN error only caller can retry on handle based calls
4867 since file handle passed in no longer valid */
4874 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4875 const FILE_BASIC_INFO *data,
4876 const struct nls_table *nls_codepage, int remap)
4878 TRANSACTION2_SPI_REQ *pSMB = NULL;
4879 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4882 int bytes_returned = 0;
4884 __u16 params, param_offset, offset, byte_count, count;
4886 cFYI(1, ("In SetTimes"));
4889 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4894 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4896 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4897 PATH_MAX, nls_codepage, remap);
4898 name_len++; /* trailing null */
4900 } else { /* BB improve the check for buffer overruns BB */
4901 name_len = strnlen(fileName, PATH_MAX);
4902 name_len++; /* trailing null */
4903 strncpy(pSMB->FileName, fileName, name_len);
4906 params = 6 + name_len;
4907 count = sizeof(FILE_BASIC_INFO);
4908 pSMB->MaxParameterCount = cpu_to_le16(2);
4909 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4910 pSMB->MaxSetupCount = 0;
4914 pSMB->Reserved2 = 0;
4915 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4916 InformationLevel) - 4;
4917 offset = param_offset + params;
4918 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4919 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4920 pSMB->DataOffset = cpu_to_le16(offset);
4921 pSMB->SetupCount = 1;
4922 pSMB->Reserved3 = 0;
4923 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4924 byte_count = 3 /* pad */ + params + count;
4926 pSMB->DataCount = cpu_to_le16(count);
4927 pSMB->ParameterCount = cpu_to_le16(params);
4928 pSMB->TotalDataCount = pSMB->DataCount;
4929 pSMB->TotalParameterCount = pSMB->ParameterCount;
4930 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4931 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4933 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4934 pSMB->Reserved4 = 0;
4935 pSMB->hdr.smb_buf_length += byte_count;
4936 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4937 pSMB->ByteCount = cpu_to_le16(byte_count);
4938 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4939 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4941 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4944 cifs_buf_release(pSMB);
4952 /* Can not be used to set time stamps yet (due to old DOS time format) */
4953 /* Can be used to set attributes */
4954 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4955 handling it anyway and NT4 was what we thought it would be needed for
4956 Do not delete it until we prove whether needed for Win9x though */
4958 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4959 __u16 dos_attrs, const struct nls_table *nls_codepage)
4961 SETATTR_REQ *pSMB = NULL;
4962 SETATTR_RSP *pSMBr = NULL;
4967 cFYI(1, ("In SetAttrLegacy"));
4970 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4975 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4977 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4978 PATH_MAX, nls_codepage);
4979 name_len++; /* trailing null */
4981 } else { /* BB improve the check for buffer overruns BB */
4982 name_len = strnlen(fileName, PATH_MAX);
4983 name_len++; /* trailing null */
4984 strncpy(pSMB->fileName, fileName, name_len);
4986 pSMB->attr = cpu_to_le16(dos_attrs);
4987 pSMB->BufferFormat = 0x04;
4988 pSMB->hdr.smb_buf_length += name_len + 1;
4989 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4990 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4991 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4993 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4996 cifs_buf_release(pSMB);
4999 goto SetAttrLgcyRetry;
5003 #endif /* temporarily unneeded SetAttr legacy function */
5006 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
5007 char *fileName, __u64 mode, __u64 uid, __u64 gid,
5008 dev_t device, const struct nls_table *nls_codepage,
5011 TRANSACTION2_SPI_REQ *pSMB = NULL;
5012 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5015 int bytes_returned = 0;
5016 FILE_UNIX_BASIC_INFO *data_offset;
5017 __u16 params, param_offset, offset, count, byte_count;
5019 cFYI(1, ("In SetUID/GID/Mode"));
5021 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5026 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5028 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5029 PATH_MAX, nls_codepage, remap);
5030 name_len++; /* trailing null */
5032 } else { /* BB improve the check for buffer overruns BB */
5033 name_len = strnlen(fileName, PATH_MAX);
5034 name_len++; /* trailing null */
5035 strncpy(pSMB->FileName, fileName, name_len);
5038 params = 6 + name_len;
5039 count = sizeof(FILE_UNIX_BASIC_INFO);
5040 pSMB->MaxParameterCount = cpu_to_le16(2);
5041 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5042 pSMB->MaxSetupCount = 0;
5046 pSMB->Reserved2 = 0;
5047 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5048 InformationLevel) - 4;
5049 offset = param_offset + params;
5051 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5053 memset(data_offset, 0, count);
5054 pSMB->DataOffset = cpu_to_le16(offset);
5055 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5056 pSMB->SetupCount = 1;
5057 pSMB->Reserved3 = 0;
5058 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5059 byte_count = 3 /* pad */ + params + count;
5060 pSMB->ParameterCount = cpu_to_le16(params);
5061 pSMB->DataCount = cpu_to_le16(count);
5062 pSMB->TotalParameterCount = pSMB->ParameterCount;
5063 pSMB->TotalDataCount = pSMB->DataCount;
5064 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5065 pSMB->Reserved4 = 0;
5066 pSMB->hdr.smb_buf_length += byte_count;
5067 /* Samba server ignores set of file size to zero due to bugs in some
5068 older clients, but we should be precise - we use SetFileSize to
5069 set file size and do not want to truncate file size to zero
5070 accidently as happened on one Samba server beta by putting
5071 zero instead of -1 here */
5072 data_offset->EndOfFile = NO_CHANGE_64;
5073 data_offset->NumOfBytes = NO_CHANGE_64;
5074 data_offset->LastStatusChange = NO_CHANGE_64;
5075 data_offset->LastAccessTime = NO_CHANGE_64;
5076 data_offset->LastModificationTime = NO_CHANGE_64;
5077 data_offset->Uid = cpu_to_le64(uid);
5078 data_offset->Gid = cpu_to_le64(gid);
5079 /* better to leave device as zero when it is */
5080 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5081 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5082 data_offset->Permissions = cpu_to_le64(mode);
5085 data_offset->Type = cpu_to_le32(UNIX_FILE);
5086 else if (S_ISDIR(mode))
5087 data_offset->Type = cpu_to_le32(UNIX_DIR);
5088 else if (S_ISLNK(mode))
5089 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5090 else if (S_ISCHR(mode))
5091 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5092 else if (S_ISBLK(mode))
5093 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5094 else if (S_ISFIFO(mode))
5095 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5096 else if (S_ISSOCK(mode))
5097 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5100 pSMB->ByteCount = cpu_to_le16(byte_count);
5101 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5102 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5104 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5108 cifs_buf_release(pSMB);
5114 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5115 const int notify_subdirs, const __u16 netfid,
5116 __u32 filter, struct file *pfile, int multishot,
5117 const struct nls_table *nls_codepage)
5120 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5121 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5122 struct dir_notify_req *dnotify_req;
5125 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5126 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5131 pSMB->TotalParameterCount = 0 ;
5132 pSMB->TotalDataCount = 0;
5133 pSMB->MaxParameterCount = cpu_to_le32(2);
5134 /* BB find exact data count max from sess structure BB */
5135 pSMB->MaxDataCount = 0; /* same in little endian or be */
5136 /* BB VERIFY verify which is correct for above BB */
5137 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5138 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5140 pSMB->MaxSetupCount = 4;
5142 pSMB->ParameterOffset = 0;
5143 pSMB->DataCount = 0;
5144 pSMB->DataOffset = 0;
5145 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5146 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5147 pSMB->ParameterCount = pSMB->TotalParameterCount;
5149 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5150 pSMB->Reserved2 = 0;
5151 pSMB->CompletionFilter = cpu_to_le32(filter);
5152 pSMB->Fid = netfid; /* file handle always le */
5153 pSMB->ByteCount = 0;
5155 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5156 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5158 cFYI(1, ("Error in Notify = %d", rc));
5160 /* Add file to outstanding requests */
5161 /* BB change to kmem cache alloc */
5162 dnotify_req = kmalloc(
5163 sizeof(struct dir_notify_req),
5166 dnotify_req->Pid = pSMB->hdr.Pid;
5167 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5168 dnotify_req->Mid = pSMB->hdr.Mid;
5169 dnotify_req->Tid = pSMB->hdr.Tid;
5170 dnotify_req->Uid = pSMB->hdr.Uid;
5171 dnotify_req->netfid = netfid;
5172 dnotify_req->pfile = pfile;
5173 dnotify_req->filter = filter;
5174 dnotify_req->multishot = multishot;
5175 spin_lock(&GlobalMid_Lock);
5176 list_add_tail(&dnotify_req->lhead,
5177 &GlobalDnotifyReqList);
5178 spin_unlock(&GlobalMid_Lock);
5182 cifs_buf_release(pSMB);
5185 #ifdef CONFIG_CIFS_XATTR
5187 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5188 const unsigned char *searchName,
5189 char *EAData, size_t buf_size,
5190 const struct nls_table *nls_codepage, int remap)
5192 /* BB assumes one setup word */
5193 TRANSACTION2_QPI_REQ *pSMB = NULL;
5194 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5198 struct fea *temp_fea;
5200 __u16 params, byte_count;
5202 cFYI(1, ("In Query All EAs path %s", searchName));
5204 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5209 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5211 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5212 PATH_MAX, nls_codepage, remap);
5213 name_len++; /* trailing null */
5215 } else { /* BB improve the check for buffer overruns BB */
5216 name_len = strnlen(searchName, PATH_MAX);
5217 name_len++; /* trailing null */
5218 strncpy(pSMB->FileName, searchName, name_len);
5221 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5222 pSMB->TotalDataCount = 0;
5223 pSMB->MaxParameterCount = cpu_to_le16(2);
5224 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5225 pSMB->MaxSetupCount = 0;
5229 pSMB->Reserved2 = 0;
5230 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5231 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5232 pSMB->DataCount = 0;
5233 pSMB->DataOffset = 0;
5234 pSMB->SetupCount = 1;
5235 pSMB->Reserved3 = 0;
5236 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5237 byte_count = params + 1 /* pad */ ;
5238 pSMB->TotalParameterCount = cpu_to_le16(params);
5239 pSMB->ParameterCount = pSMB->TotalParameterCount;
5240 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5241 pSMB->Reserved4 = 0;
5242 pSMB->hdr.smb_buf_length += byte_count;
5243 pSMB->ByteCount = cpu_to_le16(byte_count);
5245 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5246 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5248 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5249 } else { /* decode response */
5250 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5252 /* BB also check enough total bytes returned */
5253 /* BB we need to improve the validity checking
5254 of these trans2 responses */
5255 if (rc || (pSMBr->ByteCount < 4))
5256 rc = -EIO; /* bad smb */
5257 /* else if (pFindData){
5258 memcpy((char *) pFindData,
5259 (char *) &pSMBr->hdr.Protocol +
5262 /* check that length of list is not more than bcc */
5263 /* check that each entry does not go beyond length
5265 /* check that each element of each entry does not
5266 go beyond end of list */
5267 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5268 struct fealist *ea_response_data;
5270 /* validate_trans2_offsets() */
5271 /* BB check if start of smb + data_offset > &bcc+ bcc */
5272 ea_response_data = (struct fealist *)
5273 (((char *) &pSMBr->hdr.Protocol) +
5275 name_len = le32_to_cpu(ea_response_data->list_len);
5276 cFYI(1, ("ea length %d", name_len));
5277 if (name_len <= 8) {
5278 /* returned EA size zeroed at top of function */
5279 cFYI(1, ("empty EA list returned from server"));
5281 /* account for ea list len */
5283 temp_fea = ea_response_data->list;
5284 temp_ptr = (char *)temp_fea;
5285 while (name_len > 0) {
5289 rc += temp_fea->name_len;
5290 /* account for prefix user. and trailing null */
5292 if (rc < (int)buf_size) {
5293 memcpy(EAData, "user.", 5);
5295 memcpy(EAData, temp_ptr,
5296 temp_fea->name_len);
5297 EAData += temp_fea->name_len;
5298 /* null terminate name */
5300 EAData = EAData + 1;
5301 } else if (buf_size == 0) {
5302 /* skip copy - calc size only */
5304 /* stop before overrun buffer */
5308 name_len -= temp_fea->name_len;
5309 temp_ptr += temp_fea->name_len;
5310 /* account for trailing null */
5314 le16_to_cpu(temp_fea->value_len);
5315 name_len -= value_len;
5316 temp_ptr += value_len;
5317 /* BB check that temp_ptr is still
5320 /* no trailing null to account for
5322 /* go on to next EA */
5323 temp_fea = (struct fea *)temp_ptr;
5329 cifs_buf_release(pSMB);
5336 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5337 const unsigned char *searchName, const unsigned char *ea_name,
5338 unsigned char *ea_value, size_t buf_size,
5339 const struct nls_table *nls_codepage, int remap)
5341 TRANSACTION2_QPI_REQ *pSMB = NULL;
5342 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5346 struct fea *temp_fea;
5348 __u16 params, byte_count;
5350 cFYI(1, ("In Query EA path %s", searchName));
5352 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5357 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5359 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5360 PATH_MAX, nls_codepage, remap);
5361 name_len++; /* trailing null */
5363 } else { /* BB improve the check for buffer overruns BB */
5364 name_len = strnlen(searchName, PATH_MAX);
5365 name_len++; /* trailing null */
5366 strncpy(pSMB->FileName, searchName, name_len);
5369 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5370 pSMB->TotalDataCount = 0;
5371 pSMB->MaxParameterCount = cpu_to_le16(2);
5372 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5373 pSMB->MaxSetupCount = 0;
5377 pSMB->Reserved2 = 0;
5378 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5379 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5380 pSMB->DataCount = 0;
5381 pSMB->DataOffset = 0;
5382 pSMB->SetupCount = 1;
5383 pSMB->Reserved3 = 0;
5384 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5385 byte_count = params + 1 /* pad */ ;
5386 pSMB->TotalParameterCount = cpu_to_le16(params);
5387 pSMB->ParameterCount = pSMB->TotalParameterCount;
5388 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5389 pSMB->Reserved4 = 0;
5390 pSMB->hdr.smb_buf_length += byte_count;
5391 pSMB->ByteCount = cpu_to_le16(byte_count);
5393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5396 cFYI(1, ("Send error in Query EA = %d", rc));
5397 } else { /* decode response */
5398 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5400 /* BB also check enough total bytes returned */
5401 /* BB we need to improve the validity checking
5402 of these trans2 responses */
5403 if (rc || (pSMBr->ByteCount < 4))
5404 rc = -EIO; /* bad smb */
5405 /* else if (pFindData){
5406 memcpy((char *) pFindData,
5407 (char *) &pSMBr->hdr.Protocol +
5410 /* check that length of list is not more than bcc */
5411 /* check that each entry does not go beyond length
5413 /* check that each element of each entry does not
5414 go beyond end of list */
5415 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5416 struct fealist *ea_response_data;
5418 /* validate_trans2_offsets() */
5419 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5420 ea_response_data = (struct fealist *)
5421 (((char *) &pSMBr->hdr.Protocol) +
5423 name_len = le32_to_cpu(ea_response_data->list_len);
5424 cFYI(1, ("ea length %d", name_len));
5425 if (name_len <= 8) {
5426 /* returned EA size zeroed at top of function */
5427 cFYI(1, ("empty EA list returned from server"));
5429 /* account for ea list len */
5431 temp_fea = ea_response_data->list;
5432 temp_ptr = (char *)temp_fea;
5433 /* loop through checking if we have a matching
5434 name and then return the associated value */
5435 while (name_len > 0) {
5440 le16_to_cpu(temp_fea->value_len);
5441 /* BB validate that value_len falls within SMB,
5442 even though maximum for name_len is 255 */
5443 if (memcmp(temp_fea->name, ea_name,
5444 temp_fea->name_len) == 0) {
5447 /* account for prefix user. and trailing null */
5448 if (rc <= (int)buf_size) {
5450 temp_fea->name+temp_fea->name_len+1,
5452 /* ea values, unlike ea
5455 } else if (buf_size == 0) {
5456 /* skip copy - calc size only */
5458 /* stop before overrun buffer */
5463 name_len -= temp_fea->name_len;
5464 temp_ptr += temp_fea->name_len;
5465 /* account for trailing null */
5468 name_len -= value_len;
5469 temp_ptr += value_len;
5470 /* No trailing null to account for in
5471 value_len. Go on to next EA */
5472 temp_fea = (struct fea *)temp_ptr;
5478 cifs_buf_release(pSMB);
5486 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5487 const char *ea_name, const void *ea_value,
5488 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5491 struct smb_com_transaction2_spi_req *pSMB = NULL;
5492 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5493 struct fealist *parm_data;
5496 int bytes_returned = 0;
5497 __u16 params, param_offset, byte_count, offset, count;
5499 cFYI(1, ("In SetEA"));
5501 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5506 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5508 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5509 PATH_MAX, nls_codepage, remap);
5510 name_len++; /* trailing null */
5512 } else { /* BB improve the check for buffer overruns BB */
5513 name_len = strnlen(fileName, PATH_MAX);
5514 name_len++; /* trailing null */
5515 strncpy(pSMB->FileName, fileName, name_len);
5518 params = 6 + name_len;
5520 /* done calculating parms using name_len of file name,
5521 now use name_len to calculate length of ea name
5522 we are going to create in the inode xattrs */
5523 if (ea_name == NULL)
5526 name_len = strnlen(ea_name, 255);
5528 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5529 pSMB->MaxParameterCount = cpu_to_le16(2);
5530 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5531 pSMB->MaxSetupCount = 0;
5535 pSMB->Reserved2 = 0;
5536 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5537 InformationLevel) - 4;
5538 offset = param_offset + params;
5539 pSMB->InformationLevel =
5540 cpu_to_le16(SMB_SET_FILE_EA);
5543 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5545 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5546 pSMB->DataOffset = cpu_to_le16(offset);
5547 pSMB->SetupCount = 1;
5548 pSMB->Reserved3 = 0;
5549 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5550 byte_count = 3 /* pad */ + params + count;
5551 pSMB->DataCount = cpu_to_le16(count);
5552 parm_data->list_len = cpu_to_le32(count);
5553 parm_data->list[0].EA_flags = 0;
5554 /* we checked above that name len is less than 255 */
5555 parm_data->list[0].name_len = (__u8)name_len;
5556 /* EA names are always ASCII */
5558 strncpy(parm_data->list[0].name, ea_name, name_len);
5559 parm_data->list[0].name[name_len] = 0;
5560 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5561 /* caller ensures that ea_value_len is less than 64K but
5562 we need to ensure that it fits within the smb */
5564 /*BB add length check to see if it would fit in
5565 negotiated SMB buffer size BB */
5566 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5568 memcpy(parm_data->list[0].name+name_len+1,
5569 ea_value, ea_value_len);
5571 pSMB->TotalDataCount = pSMB->DataCount;
5572 pSMB->ParameterCount = cpu_to_le16(params);
5573 pSMB->TotalParameterCount = pSMB->ParameterCount;
5574 pSMB->Reserved4 = 0;
5575 pSMB->hdr.smb_buf_length += byte_count;
5576 pSMB->ByteCount = cpu_to_le16(byte_count);
5577 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5578 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5580 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5583 cifs_buf_release(pSMB);