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>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #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;
101 write_unlock(&GlobalSMBSeslock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
106 /* If the return code is zero, this function must fill in request_buf pointer */
108 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
109 void **request_buf /* returned */)
113 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
114 check for tcp and smb session status done differently
115 for those three - in the calling routine */
117 if (tcon->tidStatus == CifsExiting) {
118 /* only tree disconnect, open, and write,
119 (and ulogoff which does not have tcon)
120 are allowed as we start force umount */
121 if ((smb_command != SMB_COM_WRITE_ANDX) &&
122 (smb_command != SMB_COM_OPEN_ANDX) &&
123 (smb_command != SMB_COM_TREE_DISCONNECT)) {
124 cFYI(1, ("can not send cmd %d while umounting",
129 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
130 (tcon->ses->server)) {
131 struct nls_table *nls_codepage;
132 /* Give Demultiplex thread up to 10 seconds to
133 reconnect, should be greater than cifs socket
134 timeout which is 7 seconds */
135 while(tcon->ses->server->tcpStatus ==
137 wait_event_interruptible_timeout(tcon->ses->server->response_q,
138 (tcon->ses->server->tcpStatus ==
140 if (tcon->ses->server->tcpStatus ==
142 /* on "soft" mounts we wait once */
143 if ((tcon->retry == FALSE) ||
144 (tcon->ses->status == CifsExiting)) {
145 cFYI(1, ("gave up waiting on "
146 "reconnect in smb_init"));
148 } /* else "hard" mount - keep retrying
149 until process is killed or server
150 comes back on-line */
151 } else /* TCP session is reestablished now */
155 nls_codepage = load_nls_default();
156 /* need to prevent multiple threads trying to
157 simultaneously reconnect the same SMB session */
158 down(&tcon->ses->sesSem);
159 if (tcon->ses->status == CifsNeedReconnect)
160 rc = cifs_setup_session(0, tcon->ses,
162 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
163 mark_open_files_invalid(tcon);
164 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
166 up(&tcon->ses->sesSem);
167 /* tell server which Unix caps we support */
168 if (tcon->ses->capabilities & CAP_UNIX)
169 reset_cifs_unix_caps(0 /* no xid */,
171 NULL /* we do not know sb */,
172 NULL /* no vol info */);
173 /* BB FIXME add code to check if wsize needs
174 update due to negotiated smb buffer size
177 atomic_inc(&tconInfoReconnectCount);
179 cFYI(1, ("reconnect tcon rc = %d", rc));
180 /* Removed call to reopen open files here.
181 It is safer (and faster) to reopen files
182 one at a time as needed in read and write */
184 /* Check if handle based operation so we
185 know whether we can continue or not without
186 returning to caller to reset file handle */
187 switch (smb_command) {
188 case SMB_COM_READ_ANDX:
189 case SMB_COM_WRITE_ANDX:
191 case SMB_COM_FIND_CLOSE2:
192 case SMB_COM_LOCKING_ANDX: {
193 unload_nls(nls_codepage);
198 up(&tcon->ses->sesSem);
200 unload_nls(nls_codepage);
209 *request_buf = cifs_small_buf_get();
210 if (*request_buf == NULL) {
211 /* BB should we add a retry in here if not a writepage? */
215 header_assemble((struct smb_hdr *) *request_buf, smb_command,
219 cifs_stats_inc(&tcon->num_smbs_sent);
225 small_smb_init_no_tc(const int smb_command, const int wct,
226 struct cifsSesInfo *ses, void **request_buf)
229 struct smb_hdr *buffer;
231 rc = small_smb_init(smb_command, wct, NULL, request_buf);
235 buffer = (struct smb_hdr *)*request_buf;
236 buffer->Mid = GetNextMid(ses->server);
237 if (ses->capabilities & CAP_UNICODE)
238 buffer->Flags2 |= SMBFLG2_UNICODE;
239 if (ses->capabilities & CAP_STATUS32)
240 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
242 /* uid, tid can stay at zero as set in header assemble */
244 /* BB add support for turning on the signing when
245 this function is used after 1st of session setup requests */
250 /* If the return code is zero, this function must fill in request_buf pointer */
252 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
253 void **request_buf /* returned */ ,
254 void **response_buf /* returned */ )
258 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
259 check for tcp and smb session status done differently
260 for those three - in the calling routine */
262 if (tcon->tidStatus == CifsExiting) {
263 /* only tree disconnect, open, and write,
264 (and ulogoff which does not have tcon)
265 are allowed as we start force umount */
266 if ((smb_command != SMB_COM_WRITE_ANDX) &&
267 (smb_command != SMB_COM_OPEN_ANDX) &&
268 (smb_command != SMB_COM_TREE_DISCONNECT)) {
269 cFYI(1, ("can not send cmd %d while umounting",
275 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
276 (tcon->ses->server)) {
277 struct nls_table *nls_codepage;
278 /* Give Demultiplex thread up to 10 seconds to
279 reconnect, should be greater than cifs socket
280 timeout which is 7 seconds */
281 while (tcon->ses->server->tcpStatus ==
283 wait_event_interruptible_timeout(tcon->ses->server->response_q,
284 (tcon->ses->server->tcpStatus ==
286 if (tcon->ses->server->tcpStatus ==
288 /* on "soft" mounts we wait once */
289 if ((tcon->retry == FALSE) ||
290 (tcon->ses->status == CifsExiting)) {
291 cFYI(1, ("gave up waiting on "
292 "reconnect in smb_init"));
294 } /* else "hard" mount - keep retrying
295 until process is killed or server
297 } else /* TCP session is reestablished now */
300 nls_codepage = load_nls_default();
301 /* need to prevent multiple threads trying to
302 simultaneously reconnect the same SMB session */
303 down(&tcon->ses->sesSem);
304 if (tcon->ses->status == CifsNeedReconnect)
305 rc = cifs_setup_session(0, tcon->ses,
307 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
308 mark_open_files_invalid(tcon);
309 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
311 up(&tcon->ses->sesSem);
312 /* tell server which Unix caps we support */
313 if (tcon->ses->capabilities & CAP_UNIX)
314 reset_cifs_unix_caps(0 /* no xid */,
316 NULL /* do not know sb */,
317 NULL /* no vol info */);
318 /* BB FIXME add code to check if wsize needs
319 update due to negotiated smb buffer size
322 atomic_inc(&tconInfoReconnectCount);
324 cFYI(1, ("reconnect tcon rc = %d", rc));
325 /* Removed call to reopen open files here.
326 It is safer (and faster) to reopen files
327 one at a time as needed in read and write */
329 /* Check if handle based operation so we
330 know whether we can continue or not without
331 returning to caller to reset file handle */
332 switch (smb_command) {
333 case SMB_COM_READ_ANDX:
334 case SMB_COM_WRITE_ANDX:
336 case SMB_COM_FIND_CLOSE2:
337 case SMB_COM_LOCKING_ANDX: {
338 unload_nls(nls_codepage);
343 up(&tcon->ses->sesSem);
345 unload_nls(nls_codepage);
354 *request_buf = cifs_buf_get();
355 if (*request_buf == NULL) {
356 /* BB should we add a retry in here if not a writepage? */
359 /* Although the original thought was we needed the response buf for */
360 /* potential retries of smb operations it turns out we can determine */
361 /* from the mid flags when the request buffer can be resent without */
362 /* having to use a second distinct buffer for the response */
364 *response_buf = *request_buf;
366 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
370 cifs_stats_inc(&tcon->num_smbs_sent);
375 static int validate_t2(struct smb_t2_rsp *pSMB)
381 /* check for plausible wct, bcc and t2 data and parm sizes */
382 /* check for parm and data offset going beyond end of smb */
383 if (pSMB->hdr.WordCount >= 10) {
384 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
385 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
386 /* check that bcc is at least as big as parms + data */
387 /* check that bcc is less than negotiated smb buffer */
388 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
389 if (total_size < 512) {
391 le16_to_cpu(pSMB->t2_rsp.DataCount);
392 /* BCC le converted in SendReceive */
393 pBCC = (pSMB->hdr.WordCount * 2) +
394 sizeof(struct smb_hdr) +
396 if ((total_size <= (*(u16 *)pBCC)) &&
398 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
404 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
405 sizeof(struct smb_t2_rsp) + 16);
409 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
412 NEGOTIATE_RSP *pSMBr;
416 struct TCP_Server_Info *server;
418 unsigned int secFlags;
422 server = ses->server;
427 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
428 (void **) &pSMB, (void **) &pSMBr);
432 /* if any of auth flags (ie not sign or seal) are overriden use them */
433 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
434 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
435 else /* if override flags set only sign/seal OR them with global auth */
436 secFlags = extended_security | ses->overrideSecFlg;
438 cFYI(1, ("secFlags 0x%x", secFlags));
440 pSMB->hdr.Mid = GetNextMid(server);
441 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
442 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
443 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
446 for (i = 0; i < CIFS_NUM_PROT; i++) {
447 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
448 count += strlen(protocols[i].name) + 1;
449 /* null at end of source and target buffers anyway */
451 pSMB->hdr.smb_buf_length += count;
452 pSMB->ByteCount = cpu_to_le16(count);
454 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
455 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
459 dialect = le16_to_cpu(pSMBr->DialectIndex);
460 cFYI(1, ("Dialect: %d", dialect));
461 /* Check wct = 1 error case */
462 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
463 /* core returns wct = 1, but we do not ask for core - otherwise
464 small wct just comes when dialect index is -1 indicating we
465 could not negotiate a common dialect */
468 #ifdef CONFIG_CIFS_WEAK_PW_HASH
469 } else if ((pSMBr->hdr.WordCount == 13)
470 && ((dialect == LANMAN_PROT)
471 || (dialect == LANMAN2_PROT))) {
473 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
475 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
476 (secFlags & CIFSSEC_MAY_PLNTXT))
477 server->secType = LANMAN;
479 cERROR(1, ("mount failed weak security disabled"
480 " in /proc/fs/cifs/SecurityFlags"));
484 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
485 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
486 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
487 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
488 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
489 /* even though we do not use raw we might as well set this
490 accurately, in case we ever find a need for it */
491 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
492 server->maxRw = 0xFF00;
493 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
495 server->maxRw = 0;/* we do not need to use raw anyway */
496 server->capabilities = CAP_MPX_MODE;
498 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
500 /* OS/2 often does not set timezone therefore
501 * we must use server time to calc time zone.
502 * Could deviate slightly from the right zone.
503 * Smallest defined timezone difference is 15 minutes
504 * (i.e. Nepal). Rounding up/down is done to match
507 int val, seconds, remain, result;
508 struct timespec ts, utc;
510 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
511 le16_to_cpu(rsp->SrvTime.Time));
512 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
513 (int)ts.tv_sec, (int)utc.tv_sec,
514 (int)(utc.tv_sec - ts.tv_sec)));
515 val = (int)(utc.tv_sec - ts.tv_sec);
516 seconds = val < 0 ? -val : val;
517 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
518 remain = seconds % MIN_TZ_ADJ;
519 if (remain >= (MIN_TZ_ADJ / 2))
520 result += MIN_TZ_ADJ;
523 server->timeAdj = result;
525 server->timeAdj = (int)tmp;
526 server->timeAdj *= 60; /* also in seconds */
528 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
531 /* BB get server time for time conversions and add
532 code to use it and timezone since this is not UTC */
534 if (rsp->EncryptionKeyLength ==
535 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
536 memcpy(server->cryptKey, rsp->EncryptionKey,
537 CIFS_CRYPTO_KEY_SIZE);
538 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
539 rc = -EIO; /* need cryptkey unless plain text */
543 cFYI(1, ("LANMAN negotiated"));
544 /* we will not end up setting signing flags - as no signing
545 was in LANMAN and server did not return the flags on */
547 #else /* weak security disabled */
548 } else if (pSMBr->hdr.WordCount == 13) {
549 cERROR(1, ("mount failed, cifs module not built "
550 "with CIFS_WEAK_PW_HASH support"));
552 #endif /* WEAK_PW_HASH */
554 } else if (pSMBr->hdr.WordCount != 17) {
559 /* else wct == 17 NTLM */
560 server->secMode = pSMBr->SecurityMode;
561 if ((server->secMode & SECMODE_USER) == 0)
562 cFYI(1, ("share mode security"));
564 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
565 #ifdef CONFIG_CIFS_WEAK_PW_HASH
566 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
567 #endif /* CIFS_WEAK_PW_HASH */
568 cERROR(1, ("Server requests plain text password"
569 " but client support disabled"));
571 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
572 server->secType = NTLMv2;
573 else if (secFlags & CIFSSEC_MAY_NTLM)
574 server->secType = NTLM;
575 else if (secFlags & CIFSSEC_MAY_NTLMV2)
576 server->secType = NTLMv2;
577 /* else krb5 ... any others ... */
579 /* one byte, so no need to convert this or EncryptionKeyLen from
581 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
582 /* probably no need to store and check maxvcs */
583 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
584 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
585 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
586 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
587 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
588 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
589 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
590 server->timeAdj *= 60;
591 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
592 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
593 CIFS_CRYPTO_KEY_SIZE);
594 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
595 && (pSMBr->EncryptionKeyLength == 0)) {
596 /* decode security blob */
597 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
598 rc = -EIO; /* no crypt key only if plain text pwd */
602 /* BB might be helpful to save off the domain of server here */
604 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
605 (server->capabilities & CAP_EXTENDED_SECURITY)) {
606 count = pSMBr->ByteCount;
609 else if (count == 16) {
610 server->secType = RawNTLMSSP;
611 if (server->socketUseCount.counter > 1) {
612 if (memcmp(server->server_GUID,
613 pSMBr->u.extended_response.
615 cFYI(1, ("server UID changed"));
616 memcpy(server->server_GUID,
617 pSMBr->u.extended_response.GUID,
621 memcpy(server->server_GUID,
622 pSMBr->u.extended_response.GUID, 16);
624 rc = decode_negTokenInit(pSMBr->u.extended_response.
629 /* BB Need to fill struct for sessetup here */
636 server->capabilities &= ~CAP_EXTENDED_SECURITY;
638 #ifdef CONFIG_CIFS_WEAK_PW_HASH
641 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
642 /* MUST_SIGN already includes the MAY_SIGN FLAG
643 so if this is zero it means that signing is disabled */
644 cFYI(1, ("Signing disabled"));
645 if (server->secMode & SECMODE_SIGN_REQUIRED)
646 cERROR(1, ("Server requires "
647 "/proc/fs/cifs/PacketSigningEnabled "
650 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
651 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
652 /* signing required */
653 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
654 if ((server->secMode &
655 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
657 ("signing required but server lacks support"));
660 server->secMode |= SECMODE_SIGN_REQUIRED;
662 /* signing optional ie CIFSSEC_MAY_SIGN */
663 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
665 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
669 cifs_buf_release(pSMB);
671 cFYI(1, ("negprot rc %d", rc));
676 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
678 struct smb_hdr *smb_buffer;
679 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
683 cFYI(1, ("In tree disconnect"));
685 * If last user of the connection and
686 * connection alive - disconnect it
687 * If this is the last connection on the server session disconnect it
688 * (and inside session disconnect we should check if tcp socket needs
689 * to be freed and kernel thread woken up).
692 down(&tcon->tconSem);
696 atomic_dec(&tcon->useCount);
697 if (atomic_read(&tcon->useCount) > 0) {
702 /* No need to return error on this operation if tid invalidated and
703 closed on server already e.g. due to tcp session crashing */
704 if (tcon->tidStatus == CifsNeedReconnect) {
709 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
713 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
714 (void **)&smb_buffer);
719 smb_buffer_response = smb_buffer; /* BB removeme BB */
721 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
724 cFYI(1, ("Tree disconnect failed %d", rc));
727 cifs_small_buf_release(smb_buffer);
730 /* No need to return error on this operation if tid invalidated and
731 closed on server already e.g. due to tcp session crashing */
739 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
741 struct smb_hdr *smb_buffer_response;
742 LOGOFF_ANDX_REQ *pSMB;
746 cFYI(1, ("In SMBLogoff for session disconnect"));
752 atomic_dec(&ses->inUse);
753 if (atomic_read(&ses->inUse) > 0) {
757 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
763 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
766 pSMB->hdr.Mid = GetNextMid(ses->server);
768 if (ses->server->secMode &
769 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
770 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
773 pSMB->hdr.Uid = ses->Suid;
775 pSMB->AndXCommand = 0xFF;
776 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
777 smb_buffer_response, &length, 0);
779 atomic_dec(&ses->server->socketUseCount);
780 if (atomic_read(&ses->server->socketUseCount) == 0) {
781 spin_lock(&GlobalMid_Lock);
782 ses->server->tcpStatus = CifsExiting;
783 spin_unlock(&GlobalMid_Lock);
788 cifs_small_buf_release(pSMB);
790 /* if session dead then we do not need to do ulogoff,
791 since server closed smb session, no sense reporting
799 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
800 __u16 type, const struct nls_table *nls_codepage, int remap)
802 TRANSACTION2_SPI_REQ *pSMB = NULL;
803 TRANSACTION2_SPI_RSP *pSMBr = NULL;
804 struct unlink_psx_rq *pRqD;
807 int bytes_returned = 0;
808 __u16 params, param_offset, offset, byte_count;
810 cFYI(1, ("In POSIX delete"));
812 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
817 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
819 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
820 PATH_MAX, nls_codepage, remap);
821 name_len++; /* trailing null */
823 } else { /* BB add path length overrun check */
824 name_len = strnlen(fileName, PATH_MAX);
825 name_len++; /* trailing null */
826 strncpy(pSMB->FileName, fileName, name_len);
829 params = 6 + name_len;
830 pSMB->MaxParameterCount = cpu_to_le16(2);
831 pSMB->MaxDataCount = 0; /* BB double check this with jra */
832 pSMB->MaxSetupCount = 0;
837 param_offset = offsetof(struct smb_com_transaction2_spi_req,
838 InformationLevel) - 4;
839 offset = param_offset + params;
841 /* Setup pointer to Request Data (inode type) */
842 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
843 pRqD->type = cpu_to_le16(type);
844 pSMB->ParameterOffset = cpu_to_le16(param_offset);
845 pSMB->DataOffset = cpu_to_le16(offset);
846 pSMB->SetupCount = 1;
848 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
849 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
851 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
852 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
853 pSMB->ParameterCount = cpu_to_le16(params);
854 pSMB->TotalParameterCount = pSMB->ParameterCount;
855 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
857 pSMB->hdr.smb_buf_length += byte_count;
858 pSMB->ByteCount = cpu_to_le16(byte_count);
859 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
860 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
862 cFYI(1, ("Posix delete returned %d", rc));
864 cifs_buf_release(pSMB);
866 cifs_stats_inc(&tcon->num_deletes);
875 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
876 const struct nls_table *nls_codepage, int remap)
878 DELETE_FILE_REQ *pSMB = NULL;
879 DELETE_FILE_RSP *pSMBr = NULL;
885 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
890 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
892 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
893 PATH_MAX, nls_codepage, remap);
894 name_len++; /* trailing null */
896 } else { /* BB improve check for buffer overruns BB */
897 name_len = strnlen(fileName, PATH_MAX);
898 name_len++; /* trailing null */
899 strncpy(pSMB->fileName, fileName, name_len);
901 pSMB->SearchAttributes =
902 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
903 pSMB->BufferFormat = 0x04;
904 pSMB->hdr.smb_buf_length += name_len + 1;
905 pSMB->ByteCount = cpu_to_le16(name_len + 1);
906 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
907 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
908 cifs_stats_inc(&tcon->num_deletes);
910 cFYI(1, ("Error in RMFile = %d", rc));
913 cifs_buf_release(pSMB);
921 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
922 const struct nls_table *nls_codepage, int remap)
924 DELETE_DIRECTORY_REQ *pSMB = NULL;
925 DELETE_DIRECTORY_RSP *pSMBr = NULL;
930 cFYI(1, ("In CIFSSMBRmDir"));
932 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
937 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
938 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
939 PATH_MAX, nls_codepage, remap);
940 name_len++; /* trailing null */
942 } else { /* BB improve check for buffer overruns BB */
943 name_len = strnlen(dirName, PATH_MAX);
944 name_len++; /* trailing null */
945 strncpy(pSMB->DirName, dirName, name_len);
948 pSMB->BufferFormat = 0x04;
949 pSMB->hdr.smb_buf_length += name_len + 1;
950 pSMB->ByteCount = cpu_to_le16(name_len + 1);
951 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
952 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
953 cifs_stats_inc(&tcon->num_rmdirs);
955 cFYI(1, ("Error in RMDir = %d", rc));
958 cifs_buf_release(pSMB);
965 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
966 const char *name, const struct nls_table *nls_codepage, int remap)
969 CREATE_DIRECTORY_REQ *pSMB = NULL;
970 CREATE_DIRECTORY_RSP *pSMBr = NULL;
974 cFYI(1, ("In CIFSSMBMkDir"));
976 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
981 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
982 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
983 PATH_MAX, nls_codepage, remap);
984 name_len++; /* trailing null */
986 } else { /* BB improve check for buffer overruns BB */
987 name_len = strnlen(name, PATH_MAX);
988 name_len++; /* trailing null */
989 strncpy(pSMB->DirName, name, name_len);
992 pSMB->BufferFormat = 0x04;
993 pSMB->hdr.smb_buf_length += name_len + 1;
994 pSMB->ByteCount = cpu_to_le16(name_len + 1);
995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
996 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
997 cifs_stats_inc(&tcon->num_mkdirs);
999 cFYI(1, ("Error in Mkdir = %d", rc));
1002 cifs_buf_release(pSMB);
1009 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1010 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1011 __u32 *pOplock, const char *name,
1012 const struct nls_table *nls_codepage, int remap)
1014 TRANSACTION2_SPI_REQ *pSMB = NULL;
1015 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1018 int bytes_returned = 0;
1019 __u16 params, param_offset, offset, byte_count, count;
1020 OPEN_PSX_REQ * pdata;
1021 OPEN_PSX_RSP * psx_rsp;
1023 cFYI(1, ("In POSIX Create"));
1025 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1030 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1032 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1033 PATH_MAX, nls_codepage, remap);
1034 name_len++; /* trailing null */
1036 } else { /* BB improve the check for buffer overruns BB */
1037 name_len = strnlen(name, PATH_MAX);
1038 name_len++; /* trailing null */
1039 strncpy(pSMB->FileName, name, name_len);
1042 params = 6 + name_len;
1043 count = sizeof(OPEN_PSX_REQ);
1044 pSMB->MaxParameterCount = cpu_to_le16(2);
1045 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1046 pSMB->MaxSetupCount = 0;
1050 pSMB->Reserved2 = 0;
1051 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1052 InformationLevel) - 4;
1053 offset = param_offset + params;
1054 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1055 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
1056 pdata->Permissions = cpu_to_le64(mode);
1057 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1058 pdata->OpenFlags = cpu_to_le32(*pOplock);
1059 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1060 pSMB->DataOffset = cpu_to_le16(offset);
1061 pSMB->SetupCount = 1;
1062 pSMB->Reserved3 = 0;
1063 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1064 byte_count = 3 /* pad */ + params + count;
1066 pSMB->DataCount = cpu_to_le16(count);
1067 pSMB->ParameterCount = cpu_to_le16(params);
1068 pSMB->TotalDataCount = pSMB->DataCount;
1069 pSMB->TotalParameterCount = pSMB->ParameterCount;
1070 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1071 pSMB->Reserved4 = 0;
1072 pSMB->hdr.smb_buf_length += byte_count;
1073 pSMB->ByteCount = cpu_to_le16(byte_count);
1074 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1075 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1077 cFYI(1, ("Posix create returned %d", rc));
1078 goto psx_create_err;
1081 cFYI(1, ("copying inode info"));
1082 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1084 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1085 rc = -EIO; /* bad smb */
1086 goto psx_create_err;
1089 /* copy return information to pRetData */
1090 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1091 + le16_to_cpu(pSMBr->t2.DataOffset));
1093 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1095 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1096 /* Let caller know file was created so we can set the mode. */
1097 /* Do we care about the CreateAction in any other cases? */
1098 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1099 *pOplock |= CIFS_CREATE_ACTION;
1100 /* check to make sure response data is there */
1101 if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
1102 pRetData->Type = -1; /* unknown */
1103 #ifdef CONFIG_CIFS_DEBUG2
1104 cFYI(1, ("unknown type"));
1107 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1108 + sizeof(FILE_UNIX_BASIC_INFO)) {
1109 cERROR(1, ("Open response data too small"));
1110 pRetData->Type = -1;
1111 goto psx_create_err;
1113 memcpy((char *) pRetData,
1114 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1115 sizeof (FILE_UNIX_BASIC_INFO));
1119 cifs_buf_release(pSMB);
1121 cifs_stats_inc(&tcon->num_mkdirs);
1129 static __u16 convert_disposition(int disposition)
1133 switch (disposition) {
1134 case FILE_SUPERSEDE:
1135 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1138 ofun = SMBOPEN_OAPPEND;
1141 ofun = SMBOPEN_OCREATE;
1144 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1146 case FILE_OVERWRITE:
1147 ofun = SMBOPEN_OTRUNC;
1149 case FILE_OVERWRITE_IF:
1150 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1153 cFYI(1, ("unknown disposition %d", disposition));
1154 ofun = SMBOPEN_OAPPEND; /* regular open */
1160 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1161 const char *fileName, const int openDisposition,
1162 const int access_flags, const int create_options, __u16 * netfid,
1163 int *pOplock, FILE_ALL_INFO * pfile_info,
1164 const struct nls_table *nls_codepage, int remap)
1167 OPENX_REQ *pSMB = NULL;
1168 OPENX_RSP *pSMBr = NULL;
1174 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1179 pSMB->AndXCommand = 0xFF; /* none */
1181 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1182 count = 1; /* account for one byte pad to word boundary */
1184 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1185 fileName, PATH_MAX, nls_codepage, remap);
1186 name_len++; /* trailing null */
1188 } else { /* BB improve check for buffer overruns BB */
1189 count = 0; /* no pad */
1190 name_len = strnlen(fileName, PATH_MAX);
1191 name_len++; /* trailing null */
1192 strncpy(pSMB->fileName, fileName, name_len);
1194 if (*pOplock & REQ_OPLOCK)
1195 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1196 else if (*pOplock & REQ_BATCHOPLOCK) {
1197 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1199 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1200 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1206 pSMB->Mode = cpu_to_le16(2);
1207 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1208 /* set file as system file if special file such
1209 as fifo and server expecting SFU style and
1210 no Unix extensions */
1212 if (create_options & CREATE_OPTION_SPECIAL)
1213 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1215 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1217 /* if ((omode & S_IWUGO) == 0)
1218 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1219 /* Above line causes problems due to vfs splitting create into two
1220 pieces - need to set mode after file created not while it is
1224 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1225 CREATE_OPTIONS_MASK); */
1226 /* BB FIXME END BB */
1228 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1229 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1231 pSMB->hdr.smb_buf_length += count;
1233 pSMB->ByteCount = cpu_to_le16(count);
1234 /* long_op set to 1 to allow for oplock break timeouts */
1235 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1236 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1237 cifs_stats_inc(&tcon->num_opens);
1239 cFYI(1, ("Error in Open = %d", rc));
1241 /* BB verify if wct == 15 */
1243 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1245 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1246 /* Let caller know file was created so we can set the mode. */
1247 /* Do we care about the CreateAction in any other cases? */
1249 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1250 *pOplock |= CIFS_CREATE_ACTION; */
1254 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1255 pfile_info->LastAccessTime = 0; /* BB fixme */
1256 pfile_info->LastWriteTime = 0; /* BB fixme */
1257 pfile_info->ChangeTime = 0; /* BB fixme */
1258 pfile_info->Attributes =
1259 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1260 /* the file_info buf is endian converted by caller */
1261 pfile_info->AllocationSize =
1262 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1263 pfile_info->EndOfFile = pfile_info->AllocationSize;
1264 pfile_info->NumberOfLinks = cpu_to_le32(1);
1268 cifs_buf_release(pSMB);
1275 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1276 const char *fileName, const int openDisposition,
1277 const int access_flags, const int create_options, __u16 * netfid,
1278 int *pOplock, FILE_ALL_INFO * pfile_info,
1279 const struct nls_table *nls_codepage, int remap)
1282 OPEN_REQ *pSMB = NULL;
1283 OPEN_RSP *pSMBr = NULL;
1289 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1294 pSMB->AndXCommand = 0xFF; /* none */
1296 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1297 count = 1; /* account for one byte pad to word boundary */
1299 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1300 fileName, PATH_MAX, nls_codepage, remap);
1301 name_len++; /* trailing null */
1303 pSMB->NameLength = cpu_to_le16(name_len);
1304 } else { /* BB improve check for buffer overruns BB */
1305 count = 0; /* no pad */
1306 name_len = strnlen(fileName, PATH_MAX);
1307 name_len++; /* trailing null */
1308 pSMB->NameLength = cpu_to_le16(name_len);
1309 strncpy(pSMB->fileName, fileName, name_len);
1311 if (*pOplock & REQ_OPLOCK)
1312 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1313 else if (*pOplock & REQ_BATCHOPLOCK) {
1314 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1316 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1317 pSMB->AllocationSize = 0;
1318 /* set file as system file if special file such
1319 as fifo and server expecting SFU style and
1320 no Unix extensions */
1321 if (create_options & CREATE_OPTION_SPECIAL)
1322 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1324 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1325 /* XP does not handle ATTR_POSIX_SEMANTICS */
1326 /* but it helps speed up case sensitive checks for other
1327 servers such as Samba */
1328 if (tcon->ses->capabilities & CAP_UNIX)
1329 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1331 /* if ((omode & S_IWUGO) == 0)
1332 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1333 /* Above line causes problems due to vfs splitting create into two
1334 pieces - need to set mode after file created not while it is
1336 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1337 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1338 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1339 /* BB Expirement with various impersonation levels and verify */
1340 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1341 pSMB->SecurityFlags =
1342 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1345 pSMB->hdr.smb_buf_length += count;
1347 pSMB->ByteCount = cpu_to_le16(count);
1348 /* long_op set to 1 to allow for oplock break timeouts */
1349 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1350 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1351 cifs_stats_inc(&tcon->num_opens);
1353 cFYI(1, ("Error in Open = %d", rc));
1355 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1356 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1357 /* Let caller know file was created so we can set the mode. */
1358 /* Do we care about the CreateAction in any other cases? */
1359 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1360 *pOplock |= CIFS_CREATE_ACTION;
1362 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1363 36 /* CreationTime to Attributes */);
1364 /* the file_info buf is endian converted by caller */
1365 pfile_info->AllocationSize = pSMBr->AllocationSize;
1366 pfile_info->EndOfFile = pSMBr->EndOfFile;
1367 pfile_info->NumberOfLinks = cpu_to_le32(1);
1371 cifs_buf_release(pSMB);
1378 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1379 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1380 char **buf, int *pbuf_type)
1383 READ_REQ *pSMB = NULL;
1384 READ_RSP *pSMBr = NULL;
1385 char *pReadData = NULL;
1387 int resp_buf_type = 0;
1390 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1391 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1394 wct = 10; /* old style read */
1397 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1401 /* tcon and ses pointer are checked in smb_init */
1402 if (tcon->ses->server == NULL)
1403 return -ECONNABORTED;
1405 pSMB->AndXCommand = 0xFF; /* none */
1407 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1409 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1410 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1413 pSMB->Remaining = 0;
1414 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1415 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1417 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1419 /* old style read */
1420 struct smb_com_readx_req *pSMBW =
1421 (struct smb_com_readx_req *)pSMB;
1422 pSMBW->ByteCount = 0;
1425 iov[0].iov_base = (char *)pSMB;
1426 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1427 rc = SendReceive2(xid, tcon->ses, iov,
1430 cifs_stats_inc(&tcon->num_reads);
1431 pSMBr = (READ_RSP *)iov[0].iov_base;
1433 cERROR(1, ("Send error in read = %d", rc));
1435 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1436 data_length = data_length << 16;
1437 data_length += le16_to_cpu(pSMBr->DataLength);
1438 *nbytes = data_length;
1440 /*check that DataLength would not go beyond end of SMB */
1441 if ((data_length > CIFSMaxBufSize)
1442 || (data_length > count)) {
1443 cFYI(1, ("bad length %d for count %d",
1444 data_length, count));
1448 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1449 le16_to_cpu(pSMBr->DataOffset);
1450 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1451 cERROR(1,("Faulting on read rc = %d",rc));
1453 }*/ /* can not use copy_to_user when using page cache*/
1455 memcpy(*buf, pReadData, data_length);
1459 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1461 if (resp_buf_type == CIFS_SMALL_BUFFER)
1462 cifs_small_buf_release(iov[0].iov_base);
1463 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1464 cifs_buf_release(iov[0].iov_base);
1465 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1466 /* return buffer to caller to free */
1467 *buf = iov[0].iov_base;
1468 if (resp_buf_type == CIFS_SMALL_BUFFER)
1469 *pbuf_type = CIFS_SMALL_BUFFER;
1470 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1471 *pbuf_type = CIFS_LARGE_BUFFER;
1472 } /* else no valid buffer on return - leave as null */
1474 /* Note: On -EAGAIN error only caller can retry on handle based calls
1475 since file handle passed in no longer valid */
1481 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1482 const int netfid, const unsigned int count,
1483 const __u64 offset, unsigned int *nbytes, const char *buf,
1484 const char __user *ubuf, const int long_op)
1487 WRITE_REQ *pSMB = NULL;
1488 WRITE_RSP *pSMBr = NULL;
1489 int bytes_returned, wct;
1493 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1494 if (tcon->ses == NULL)
1495 return -ECONNABORTED;
1497 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1502 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1506 /* tcon and ses pointer are checked in smb_init */
1507 if (tcon->ses->server == NULL)
1508 return -ECONNABORTED;
1510 pSMB->AndXCommand = 0xFF; /* none */
1512 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1514 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1515 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1518 pSMB->Reserved = 0xFFFFFFFF;
1519 pSMB->WriteMode = 0;
1520 pSMB->Remaining = 0;
1522 /* Can increase buffer size if buffer is big enough in some cases ie we
1523 can send more if LARGE_WRITE_X capability returned by the server and if
1524 our buffer is big enough or if we convert to iovecs on socket writes
1525 and eliminate the copy to the CIFS buffer */
1526 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1527 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1529 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1533 if (bytes_sent > count)
1536 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1538 memcpy(pSMB->Data, buf, bytes_sent);
1540 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1541 cifs_buf_release(pSMB);
1544 } else if (count != 0) {
1546 cifs_buf_release(pSMB);
1548 } /* else setting file size with write of zero bytes */
1550 byte_count = bytes_sent + 1; /* pad */
1551 else /* wct == 12 */ {
1552 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1554 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1555 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1556 pSMB->hdr.smb_buf_length += byte_count;
1559 pSMB->ByteCount = cpu_to_le16(byte_count);
1560 else { /* old style write has byte count 4 bytes earlier
1562 struct smb_com_writex_req *pSMBW =
1563 (struct smb_com_writex_req *)pSMB;
1564 pSMBW->ByteCount = cpu_to_le16(byte_count);
1567 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1568 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1569 cifs_stats_inc(&tcon->num_writes);
1571 cFYI(1, ("Send error in write = %d", rc));
1574 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1575 *nbytes = (*nbytes) << 16;
1576 *nbytes += le16_to_cpu(pSMBr->Count);
1579 cifs_buf_release(pSMB);
1581 /* Note: On -EAGAIN error only caller can retry on handle based calls
1582 since file handle passed in no longer valid */
1588 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1589 const int netfid, const unsigned int count,
1590 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1591 int n_vec, const int long_op)
1594 WRITE_REQ *pSMB = NULL;
1597 int resp_buf_type = 0;
1599 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1601 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1605 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1608 /* tcon and ses pointer are checked in smb_init */
1609 if (tcon->ses->server == NULL)
1610 return -ECONNABORTED;
1612 pSMB->AndXCommand = 0xFF; /* none */
1614 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1616 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1617 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1619 pSMB->Reserved = 0xFFFFFFFF;
1620 pSMB->WriteMode = 0;
1621 pSMB->Remaining = 0;
1624 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1626 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1627 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1628 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1630 pSMB->hdr.smb_buf_length += count+1;
1631 else /* wct == 12 */
1632 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1634 pSMB->ByteCount = cpu_to_le16(count + 1);
1635 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1636 struct smb_com_writex_req *pSMBW =
1637 (struct smb_com_writex_req *)pSMB;
1638 pSMBW->ByteCount = cpu_to_le16(count + 5);
1640 iov[0].iov_base = pSMB;
1642 iov[0].iov_len = smb_hdr_len + 4;
1643 else /* wct == 12 pad bigger by four bytes */
1644 iov[0].iov_len = smb_hdr_len + 8;
1647 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1649 cifs_stats_inc(&tcon->num_writes);
1651 cFYI(1, ("Send error Write2 = %d", rc));
1653 } else if (resp_buf_type == 0) {
1654 /* presumably this can not happen, but best to be safe */
1658 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1659 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1660 *nbytes = (*nbytes) << 16;
1661 *nbytes += le16_to_cpu(pSMBr->Count);
1664 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1665 if (resp_buf_type == CIFS_SMALL_BUFFER)
1666 cifs_small_buf_release(iov[0].iov_base);
1667 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1668 cifs_buf_release(iov[0].iov_base);
1670 /* Note: On -EAGAIN error only caller can retry on handle based calls
1671 since file handle passed in no longer valid */
1678 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1679 const __u16 smb_file_id, const __u64 len,
1680 const __u64 offset, const __u32 numUnlock,
1681 const __u32 numLock, const __u8 lockType, const int waitFlag)
1684 LOCK_REQ *pSMB = NULL;
1685 LOCK_RSP *pSMBr = NULL;
1690 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1691 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1696 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1698 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1699 timeout = -1; /* no response expected */
1701 } else if (waitFlag == TRUE) {
1702 timeout = 3; /* blocking operation, no timeout */
1703 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1708 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1709 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1710 pSMB->LockType = lockType;
1711 pSMB->AndXCommand = 0xFF; /* none */
1712 pSMB->Fid = smb_file_id; /* netfid stays le */
1714 if ((numLock != 0) || (numUnlock != 0)) {
1715 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1716 /* BB where to store pid high? */
1717 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1718 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1719 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1720 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1721 count = sizeof(LOCKING_ANDX_RANGE);
1726 pSMB->hdr.smb_buf_length += count;
1727 pSMB->ByteCount = cpu_to_le16(count);
1730 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1731 (struct smb_hdr *) pSMBr, &bytes_returned);
1733 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1734 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1736 cifs_stats_inc(&tcon->num_locks);
1738 cFYI(1, ("Send error in Lock = %d", rc));
1740 cifs_small_buf_release(pSMB);
1742 /* Note: On -EAGAIN error only caller can retry on handle based calls
1743 since file handle passed in no longer valid */
1748 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1749 const __u16 smb_file_id, const int get_flag, const __u64 len,
1750 struct file_lock *pLockData, const __u16 lock_type,
1753 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1754 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1755 struct cifs_posix_lock *parm_data;
1758 int bytes_returned = 0;
1759 __u16 params, param_offset, offset, byte_count, count;
1761 cFYI(1, ("Posix Lock"));
1763 if (pLockData == NULL)
1766 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1771 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1774 pSMB->MaxSetupCount = 0;
1777 pSMB->Reserved2 = 0;
1778 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1779 offset = param_offset + params;
1781 count = sizeof(struct cifs_posix_lock);
1782 pSMB->MaxParameterCount = cpu_to_le16(2);
1783 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1784 pSMB->SetupCount = 1;
1785 pSMB->Reserved3 = 0;
1787 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1789 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1790 byte_count = 3 /* pad */ + params + count;
1791 pSMB->DataCount = cpu_to_le16(count);
1792 pSMB->ParameterCount = cpu_to_le16(params);
1793 pSMB->TotalDataCount = pSMB->DataCount;
1794 pSMB->TotalParameterCount = pSMB->ParameterCount;
1795 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1796 parm_data = (struct cifs_posix_lock *)
1797 (((char *) &pSMB->hdr.Protocol) + offset);
1799 parm_data->lock_type = cpu_to_le16(lock_type);
1801 timeout = 3; /* blocking operation, no timeout */
1802 parm_data->lock_flags = cpu_to_le16(1);
1803 pSMB->Timeout = cpu_to_le32(-1);
1807 parm_data->pid = cpu_to_le32(current->tgid);
1808 parm_data->start = cpu_to_le64(pLockData->fl_start);
1809 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1811 pSMB->DataOffset = cpu_to_le16(offset);
1812 pSMB->Fid = smb_file_id;
1813 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1814 pSMB->Reserved4 = 0;
1815 pSMB->hdr.smb_buf_length += byte_count;
1816 pSMB->ByteCount = cpu_to_le16(byte_count);
1818 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1819 (struct smb_hdr *) pSMBr, &bytes_returned);
1821 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1822 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1826 cFYI(1, ("Send error in Posix Lock = %d", rc));
1827 } else if (get_flag) {
1828 /* lock structure can be returned on get */
1831 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1833 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1834 rc = -EIO; /* bad smb */
1837 if (pLockData == NULL) {
1841 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1842 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1843 if (data_count < sizeof(struct cifs_posix_lock)) {
1847 parm_data = (struct cifs_posix_lock *)
1848 ((char *)&pSMBr->hdr.Protocol + data_offset);
1849 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1850 pLockData->fl_type = F_UNLCK;
1855 cifs_small_buf_release(pSMB);
1857 /* Note: On -EAGAIN error only caller can retry on handle based calls
1858 since file handle passed in no longer valid */
1865 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1868 CLOSE_REQ *pSMB = NULL;
1869 CLOSE_RSP *pSMBr = NULL;
1871 cFYI(1, ("In CIFSSMBClose"));
1873 /* do not retry on dead session on close */
1874 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1880 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1882 pSMB->FileID = (__u16) smb_file_id;
1883 pSMB->LastWriteTime = 0xFFFFFFFF;
1884 pSMB->ByteCount = 0;
1885 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1886 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1887 cifs_stats_inc(&tcon->num_closes);
1890 /* EINTR is expected when user ctl-c to kill app */
1891 cERROR(1, ("Send error in Close = %d", rc));
1895 cifs_small_buf_release(pSMB);
1897 /* Since session is dead, file will be closed on server already */
1905 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1906 const char *fromName, const char *toName,
1907 const struct nls_table *nls_codepage, int remap)
1910 RENAME_REQ *pSMB = NULL;
1911 RENAME_RSP *pSMBr = NULL;
1913 int name_len, name_len2;
1916 cFYI(1, ("In CIFSSMBRename"));
1918 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1923 pSMB->BufferFormat = 0x04;
1924 pSMB->SearchAttributes =
1925 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1928 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1930 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1931 PATH_MAX, nls_codepage, remap);
1932 name_len++; /* trailing null */
1934 pSMB->OldFileName[name_len] = 0x04; /* pad */
1935 /* protocol requires ASCII signature byte on Unicode string */
1936 pSMB->OldFileName[name_len + 1] = 0x00;
1938 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1939 toName, PATH_MAX, nls_codepage, remap);
1940 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1941 name_len2 *= 2; /* convert to bytes */
1942 } else { /* BB improve the check for buffer overruns BB */
1943 name_len = strnlen(fromName, PATH_MAX);
1944 name_len++; /* trailing null */
1945 strncpy(pSMB->OldFileName, fromName, name_len);
1946 name_len2 = strnlen(toName, PATH_MAX);
1947 name_len2++; /* trailing null */
1948 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1949 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1950 name_len2++; /* trailing null */
1951 name_len2++; /* signature byte */
1954 count = 1 /* 1st signature byte */ + name_len + name_len2;
1955 pSMB->hdr.smb_buf_length += count;
1956 pSMB->ByteCount = cpu_to_le16(count);
1958 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1959 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1960 cifs_stats_inc(&tcon->num_renames);
1962 cFYI(1, ("Send error in rename = %d", rc));
1965 cifs_buf_release(pSMB);
1973 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1974 int netfid, char *target_name,
1975 const struct nls_table *nls_codepage, int remap)
1977 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1978 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1979 struct set_file_rename *rename_info;
1981 char dummy_string[30];
1983 int bytes_returned = 0;
1985 __u16 params, param_offset, offset, count, byte_count;
1987 cFYI(1, ("Rename to File by handle"));
1988 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1994 pSMB->MaxSetupCount = 0;
1998 pSMB->Reserved2 = 0;
1999 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2000 offset = param_offset + params;
2002 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2003 rename_info = (struct set_file_rename *) data_offset;
2004 pSMB->MaxParameterCount = cpu_to_le16(2);
2005 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2006 pSMB->SetupCount = 1;
2007 pSMB->Reserved3 = 0;
2008 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2009 byte_count = 3 /* pad */ + params;
2010 pSMB->ParameterCount = cpu_to_le16(params);
2011 pSMB->TotalParameterCount = pSMB->ParameterCount;
2012 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2013 pSMB->DataOffset = cpu_to_le16(offset);
2014 /* construct random name ".cifs_tmp<inodenum><mid>" */
2015 rename_info->overwrite = cpu_to_le32(1);
2016 rename_info->root_fid = 0;
2017 /* unicode only call */
2018 if (target_name == NULL) {
2019 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2020 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2021 dummy_string, 24, nls_codepage, remap);
2023 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2024 target_name, PATH_MAX, nls_codepage,
2027 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2028 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2029 byte_count += count;
2030 pSMB->DataCount = cpu_to_le16(count);
2031 pSMB->TotalDataCount = pSMB->DataCount;
2033 pSMB->InformationLevel =
2034 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2035 pSMB->Reserved4 = 0;
2036 pSMB->hdr.smb_buf_length += byte_count;
2037 pSMB->ByteCount = cpu_to_le16(byte_count);
2038 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2039 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2040 cifs_stats_inc(&pTcon->num_t2renames);
2042 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2045 cifs_buf_release(pSMB);
2047 /* Note: On -EAGAIN error only caller can retry on handle based calls
2048 since file handle passed in no longer valid */
2054 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2055 const __u16 target_tid, const char *toName, const int flags,
2056 const struct nls_table *nls_codepage, int remap)
2059 COPY_REQ *pSMB = NULL;
2060 COPY_RSP *pSMBr = NULL;
2062 int name_len, name_len2;
2065 cFYI(1, ("In CIFSSMBCopy"));
2067 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2072 pSMB->BufferFormat = 0x04;
2073 pSMB->Tid2 = target_tid;
2075 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2077 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2078 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2079 fromName, PATH_MAX, nls_codepage,
2081 name_len++; /* trailing null */
2083 pSMB->OldFileName[name_len] = 0x04; /* pad */
2084 /* protocol requires ASCII signature byte on Unicode string */
2085 pSMB->OldFileName[name_len + 1] = 0x00;
2087 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2088 toName, PATH_MAX, nls_codepage, remap);
2089 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2090 name_len2 *= 2; /* convert to bytes */
2091 } else { /* BB improve the check for buffer overruns BB */
2092 name_len = strnlen(fromName, PATH_MAX);
2093 name_len++; /* trailing null */
2094 strncpy(pSMB->OldFileName, fromName, name_len);
2095 name_len2 = strnlen(toName, PATH_MAX);
2096 name_len2++; /* trailing null */
2097 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2098 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2099 name_len2++; /* trailing null */
2100 name_len2++; /* signature byte */
2103 count = 1 /* 1st signature byte */ + name_len + name_len2;
2104 pSMB->hdr.smb_buf_length += count;
2105 pSMB->ByteCount = cpu_to_le16(count);
2107 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2108 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2110 cFYI(1, ("Send error in copy = %d with %d files copied",
2111 rc, le16_to_cpu(pSMBr->CopyCount)));
2114 cifs_buf_release(pSMB);
2123 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2124 const char *fromName, const char *toName,
2125 const struct nls_table *nls_codepage)
2127 TRANSACTION2_SPI_REQ *pSMB = NULL;
2128 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2131 int name_len_target;
2133 int bytes_returned = 0;
2134 __u16 params, param_offset, offset, byte_count;
2136 cFYI(1, ("In Symlink Unix style"));
2138 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2143 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2145 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2146 /* find define for this maxpathcomponent */
2148 name_len++; /* trailing null */
2151 } else { /* BB improve the check for buffer overruns BB */
2152 name_len = strnlen(fromName, PATH_MAX);
2153 name_len++; /* trailing null */
2154 strncpy(pSMB->FileName, fromName, name_len);
2156 params = 6 + name_len;
2157 pSMB->MaxSetupCount = 0;
2161 pSMB->Reserved2 = 0;
2162 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2163 InformationLevel) - 4;
2164 offset = param_offset + params;
2166 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2167 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2169 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2170 /* find define for this maxpathcomponent */
2172 name_len_target++; /* trailing null */
2173 name_len_target *= 2;
2174 } else { /* BB improve the check for buffer overruns BB */
2175 name_len_target = strnlen(toName, PATH_MAX);
2176 name_len_target++; /* trailing null */
2177 strncpy(data_offset, toName, name_len_target);
2180 pSMB->MaxParameterCount = cpu_to_le16(2);
2181 /* BB find exact max on data count below from sess */
2182 pSMB->MaxDataCount = cpu_to_le16(1000);
2183 pSMB->SetupCount = 1;
2184 pSMB->Reserved3 = 0;
2185 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2186 byte_count = 3 /* pad */ + params + name_len_target;
2187 pSMB->DataCount = cpu_to_le16(name_len_target);
2188 pSMB->ParameterCount = cpu_to_le16(params);
2189 pSMB->TotalDataCount = pSMB->DataCount;
2190 pSMB->TotalParameterCount = pSMB->ParameterCount;
2191 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2192 pSMB->DataOffset = cpu_to_le16(offset);
2193 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2194 pSMB->Reserved4 = 0;
2195 pSMB->hdr.smb_buf_length += byte_count;
2196 pSMB->ByteCount = cpu_to_le16(byte_count);
2197 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2198 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2199 cifs_stats_inc(&tcon->num_symlinks);
2201 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2205 cifs_buf_release(pSMB);
2208 goto createSymLinkRetry;
2214 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2215 const char *fromName, const char *toName,
2216 const struct nls_table *nls_codepage, int remap)
2218 TRANSACTION2_SPI_REQ *pSMB = NULL;
2219 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2222 int name_len_target;
2224 int bytes_returned = 0;
2225 __u16 params, param_offset, offset, byte_count;
2227 cFYI(1, ("In Create Hard link Unix style"));
2228 createHardLinkRetry:
2229 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2234 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2235 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2236 PATH_MAX, nls_codepage, remap);
2237 name_len++; /* trailing null */
2240 } else { /* BB improve the check for buffer overruns BB */
2241 name_len = strnlen(toName, PATH_MAX);
2242 name_len++; /* trailing null */
2243 strncpy(pSMB->FileName, toName, name_len);
2245 params = 6 + name_len;
2246 pSMB->MaxSetupCount = 0;
2250 pSMB->Reserved2 = 0;
2251 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2252 InformationLevel) - 4;
2253 offset = param_offset + params;
2255 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2256 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2258 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2259 nls_codepage, remap);
2260 name_len_target++; /* trailing null */
2261 name_len_target *= 2;
2262 } else { /* BB improve the check for buffer overruns BB */
2263 name_len_target = strnlen(fromName, PATH_MAX);
2264 name_len_target++; /* trailing null */
2265 strncpy(data_offset, fromName, name_len_target);
2268 pSMB->MaxParameterCount = cpu_to_le16(2);
2269 /* BB find exact max on data count below from sess*/
2270 pSMB->MaxDataCount = cpu_to_le16(1000);
2271 pSMB->SetupCount = 1;
2272 pSMB->Reserved3 = 0;
2273 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2274 byte_count = 3 /* pad */ + params + name_len_target;
2275 pSMB->ParameterCount = cpu_to_le16(params);
2276 pSMB->TotalParameterCount = pSMB->ParameterCount;
2277 pSMB->DataCount = cpu_to_le16(name_len_target);
2278 pSMB->TotalDataCount = pSMB->DataCount;
2279 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2280 pSMB->DataOffset = cpu_to_le16(offset);
2281 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2282 pSMB->Reserved4 = 0;
2283 pSMB->hdr.smb_buf_length += byte_count;
2284 pSMB->ByteCount = cpu_to_le16(byte_count);
2285 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2286 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2287 cifs_stats_inc(&tcon->num_hardlinks);
2289 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2292 cifs_buf_release(pSMB);
2294 goto createHardLinkRetry;
2300 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2301 const char *fromName, const char *toName,
2302 const struct nls_table *nls_codepage, int remap)
2305 NT_RENAME_REQ *pSMB = NULL;
2306 RENAME_RSP *pSMBr = NULL;
2308 int name_len, name_len2;
2311 cFYI(1, ("In CIFSCreateHardLink"));
2312 winCreateHardLinkRetry:
2314 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2319 pSMB->SearchAttributes =
2320 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2322 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2323 pSMB->ClusterCount = 0;
2325 pSMB->BufferFormat = 0x04;
2327 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2329 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2330 PATH_MAX, nls_codepage, remap);
2331 name_len++; /* trailing null */
2333 pSMB->OldFileName[name_len] = 0; /* pad */
2334 pSMB->OldFileName[name_len + 1] = 0x04;
2336 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2337 toName, PATH_MAX, nls_codepage, remap);
2338 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2339 name_len2 *= 2; /* convert to bytes */
2340 } else { /* BB improve the check for buffer overruns BB */
2341 name_len = strnlen(fromName, PATH_MAX);
2342 name_len++; /* trailing null */
2343 strncpy(pSMB->OldFileName, fromName, name_len);
2344 name_len2 = strnlen(toName, PATH_MAX);
2345 name_len2++; /* trailing null */
2346 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2347 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2348 name_len2++; /* trailing null */
2349 name_len2++; /* signature byte */
2352 count = 1 /* string type byte */ + name_len + name_len2;
2353 pSMB->hdr.smb_buf_length += count;
2354 pSMB->ByteCount = cpu_to_le16(count);
2356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2358 cifs_stats_inc(&tcon->num_hardlinks);
2360 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2362 cifs_buf_release(pSMB);
2364 goto winCreateHardLinkRetry;
2370 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2371 const unsigned char *searchName,
2372 char *symlinkinfo, const int buflen,
2373 const struct nls_table *nls_codepage)
2375 /* SMB_QUERY_FILE_UNIX_LINK */
2376 TRANSACTION2_QPI_REQ *pSMB = NULL;
2377 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2381 __u16 params, byte_count;
2383 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2386 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2391 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2393 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2394 PATH_MAX, nls_codepage);
2395 name_len++; /* trailing null */
2397 } else { /* BB improve the check for buffer overruns BB */
2398 name_len = strnlen(searchName, PATH_MAX);
2399 name_len++; /* trailing null */
2400 strncpy(pSMB->FileName, searchName, name_len);
2403 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2404 pSMB->TotalDataCount = 0;
2405 pSMB->MaxParameterCount = cpu_to_le16(2);
2406 /* BB find exact max data count below from sess structure BB */
2407 pSMB->MaxDataCount = cpu_to_le16(4000);
2408 pSMB->MaxSetupCount = 0;
2412 pSMB->Reserved2 = 0;
2413 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2414 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2415 pSMB->DataCount = 0;
2416 pSMB->DataOffset = 0;
2417 pSMB->SetupCount = 1;
2418 pSMB->Reserved3 = 0;
2419 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2420 byte_count = params + 1 /* pad */ ;
2421 pSMB->TotalParameterCount = cpu_to_le16(params);
2422 pSMB->ParameterCount = pSMB->TotalParameterCount;
2423 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2424 pSMB->Reserved4 = 0;
2425 pSMB->hdr.smb_buf_length += byte_count;
2426 pSMB->ByteCount = cpu_to_le16(byte_count);
2428 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2429 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2431 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2433 /* decode response */
2435 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2436 if (rc || (pSMBr->ByteCount < 2))
2437 /* BB also check enough total bytes returned */
2438 rc = -EIO; /* bad smb */
2440 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2441 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2443 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2444 name_len = UniStrnlen((wchar_t *) ((char *)
2445 &pSMBr->hdr.Protocol + data_offset),
2446 min_t(const int, buflen, count) / 2);
2447 /* BB FIXME investigate remapping reserved chars here */
2448 cifs_strfromUCS_le(symlinkinfo,
2449 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2451 name_len, nls_codepage);
2453 strncpy(symlinkinfo,
2454 (char *) &pSMBr->hdr.Protocol +
2456 min_t(const int, buflen, count));
2458 symlinkinfo[buflen] = 0;
2459 /* just in case so calling code does not go off the end of buffer */
2462 cifs_buf_release(pSMB);
2464 goto querySymLinkRetry;
2468 /* Initialize NT TRANSACT SMB into small smb request buffer.
2469 This assumes that all NT TRANSACTS that we init here have
2470 total parm and data under about 400 bytes (to fit in small cifs
2471 buffer size), which is the case so far, it easily fits. NB:
2472 Setup words themselves and ByteCount
2473 MaxSetupCount (size of returned setup area) and
2474 MaxParameterCount (returned parms size) must be set by caller */
2476 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2477 const int parm_len, struct cifsTconInfo *tcon,
2482 struct smb_com_ntransact_req *pSMB;
2484 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2488 *ret_buf = (void *)pSMB;
2490 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2491 pSMB->TotalDataCount = 0;
2492 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2493 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2494 pSMB->ParameterCount = pSMB->TotalParameterCount;
2495 pSMB->DataCount = pSMB->TotalDataCount;
2496 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2497 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2498 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2499 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2500 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2501 pSMB->SubCommand = cpu_to_le16(sub_command);
2506 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2507 int *pdatalen, int *pparmlen)
2510 __u32 data_count, data_offset, parm_count, parm_offset;
2511 struct smb_com_ntransact_rsp *pSMBr;
2516 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2518 /* ByteCount was converted from little endian in SendReceive */
2519 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2520 (char *)&pSMBr->ByteCount;
2522 data_offset = le32_to_cpu(pSMBr->DataOffset);
2523 data_count = le32_to_cpu(pSMBr->DataCount);
2524 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2525 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2527 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2528 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2530 /* should we also check that parm and data areas do not overlap? */
2531 if (*ppparm > end_of_smb) {
2532 cFYI(1, ("parms start after end of smb"));
2534 } else if (parm_count + *ppparm > end_of_smb) {
2535 cFYI(1, ("parm end after end of smb"));
2537 } else if (*ppdata > end_of_smb) {
2538 cFYI(1, ("data starts after end of smb"));
2540 } else if (data_count + *ppdata > end_of_smb) {
2541 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2542 *ppdata, data_count, (data_count + *ppdata),
2543 end_of_smb, pSMBr));
2545 } else if (parm_count + data_count > pSMBr->ByteCount) {
2546 cFYI(1, ("parm count and data count larger than SMB"));
2553 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2554 const unsigned char *searchName,
2555 char *symlinkinfo, const int buflen, __u16 fid,
2556 const struct nls_table *nls_codepage)
2561 struct smb_com_transaction_ioctl_req *pSMB;
2562 struct smb_com_transaction_ioctl_rsp *pSMBr;
2564 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2565 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2570 pSMB->TotalParameterCount = 0 ;
2571 pSMB->TotalDataCount = 0;
2572 pSMB->MaxParameterCount = cpu_to_le32(2);
2573 /* BB find exact data count max from sess structure BB */
2574 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2575 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2576 pSMB->MaxSetupCount = 4;
2578 pSMB->ParameterOffset = 0;
2579 pSMB->DataCount = 0;
2580 pSMB->DataOffset = 0;
2581 pSMB->SetupCount = 4;
2582 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2583 pSMB->ParameterCount = pSMB->TotalParameterCount;
2584 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2585 pSMB->IsFsctl = 1; /* FSCTL */
2586 pSMB->IsRootFlag = 0;
2587 pSMB->Fid = fid; /* file handle always le */
2588 pSMB->ByteCount = 0;
2590 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2591 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2593 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2594 } else { /* decode response */
2595 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2596 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2597 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2598 /* BB also check enough total bytes returned */
2599 rc = -EIO; /* bad smb */
2601 if (data_count && (data_count < 2048)) {
2602 char *end_of_smb = 2 /* sizeof byte count */ +
2604 (char *)&pSMBr->ByteCount;
2606 struct reparse_data *reparse_buf =
2607 (struct reparse_data *)
2608 ((char *)&pSMBr->hdr.Protocol
2610 if ((char *)reparse_buf >= end_of_smb) {
2614 if ((reparse_buf->LinkNamesBuf +
2615 reparse_buf->TargetNameOffset +
2616 reparse_buf->TargetNameLen) >
2618 cFYI(1,("reparse buf goes beyond SMB"));
2623 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2624 name_len = UniStrnlen((wchar_t *)
2625 (reparse_buf->LinkNamesBuf +
2626 reparse_buf->TargetNameOffset),
2628 reparse_buf->TargetNameLen / 2));
2629 cifs_strfromUCS_le(symlinkinfo,
2630 (__le16 *) (reparse_buf->LinkNamesBuf +
2631 reparse_buf->TargetNameOffset),
2632 name_len, nls_codepage);
2633 } else { /* ASCII names */
2634 strncpy(symlinkinfo,
2635 reparse_buf->LinkNamesBuf +
2636 reparse_buf->TargetNameOffset,
2637 min_t(const int, buflen,
2638 reparse_buf->TargetNameLen));
2642 cFYI(1, ("Invalid return data count on "
2643 "get reparse info ioctl"));
2645 symlinkinfo[buflen] = 0; /* just in case so the caller
2646 does not go off the end of the buffer */
2647 cFYI(1, ("readlink result - %s", symlinkinfo));
2651 cifs_buf_release(pSMB);
2653 /* Note: On -EAGAIN error only caller can retry on handle based calls
2654 since file handle passed in no longer valid */
2659 #ifdef CONFIG_CIFS_POSIX
2661 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2662 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2663 struct cifs_posix_ace *cifs_ace)
2665 /* u8 cifs fields do not need le conversion */
2666 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2667 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2668 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2669 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2674 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2675 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2676 const int acl_type, const int size_of_data_area)
2681 struct cifs_posix_ace *pACE;
2682 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2683 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2685 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2688 if (acl_type & ACL_TYPE_ACCESS) {
2689 count = le16_to_cpu(cifs_acl->access_entry_count);
2690 pACE = &cifs_acl->ace_array[0];
2691 size = sizeof(struct cifs_posix_acl);
2692 size += sizeof(struct cifs_posix_ace) * count;
2693 /* check if we would go beyond end of SMB */
2694 if (size_of_data_area < size) {
2695 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2696 size_of_data_area, size));
2699 } else if (acl_type & ACL_TYPE_DEFAULT) {
2700 count = le16_to_cpu(cifs_acl->access_entry_count);
2701 size = sizeof(struct cifs_posix_acl);
2702 size += sizeof(struct cifs_posix_ace) * count;
2703 /* skip past access ACEs to get to default ACEs */
2704 pACE = &cifs_acl->ace_array[count];
2705 count = le16_to_cpu(cifs_acl->default_entry_count);
2706 size += sizeof(struct cifs_posix_ace) * count;
2707 /* check if we would go beyond end of SMB */
2708 if (size_of_data_area < size)
2715 size = posix_acl_xattr_size(count);
2716 if ((buflen == 0) || (local_acl == NULL)) {
2717 /* used to query ACL EA size */
2718 } else if (size > buflen) {
2720 } else /* buffer big enough */ {
2721 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2722 for (i = 0; i < count ; i++) {
2723 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2730 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2731 const posix_acl_xattr_entry *local_ace)
2733 __u16 rc = 0; /* 0 = ACL converted ok */
2735 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2736 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2737 /* BB is there a better way to handle the large uid? */
2738 if (local_ace->e_id == cpu_to_le32(-1)) {
2739 /* Probably no need to le convert -1 on any arch but can not hurt */
2740 cifs_ace->cifs_uid = cpu_to_le64(-1);
2742 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2743 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2747 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2748 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2749 const int buflen, const int acl_type)
2752 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2753 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2757 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2760 count = posix_acl_xattr_count((size_t)buflen);
2761 cFYI(1,("setting acl with %d entries from buf of length %d and "
2763 count, buflen, le32_to_cpu(local_acl->a_version)));
2764 if (le32_to_cpu(local_acl->a_version) != 2) {
2765 cFYI(1, ("unknown POSIX ACL version %d",
2766 le32_to_cpu(local_acl->a_version)));
2769 cifs_acl->version = cpu_to_le16(1);
2770 if (acl_type == ACL_TYPE_ACCESS)
2771 cifs_acl->access_entry_count = cpu_to_le16(count);
2772 else if (acl_type == ACL_TYPE_DEFAULT)
2773 cifs_acl->default_entry_count = cpu_to_le16(count);
2775 cFYI(1, ("unknown ACL type %d", acl_type));
2778 for (i = 0; i < count; i++) {
2779 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2780 &local_acl->a_entries[i]);
2782 /* ACE not converted */
2787 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2788 rc += sizeof(struct cifs_posix_acl);
2789 /* BB add check to make sure ACL does not overflow SMB */
2795 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2796 const unsigned char *searchName,
2797 char *acl_inf, const int buflen, const int acl_type,
2798 const struct nls_table *nls_codepage, int remap)
2800 /* SMB_QUERY_POSIX_ACL */
2801 TRANSACTION2_QPI_REQ *pSMB = NULL;
2802 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2806 __u16 params, byte_count;
2808 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2811 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2816 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2818 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2819 PATH_MAX, nls_codepage, remap);
2820 name_len++; /* trailing null */
2822 pSMB->FileName[name_len] = 0;
2823 pSMB->FileName[name_len+1] = 0;
2824 } else { /* BB improve the check for buffer overruns BB */
2825 name_len = strnlen(searchName, PATH_MAX);
2826 name_len++; /* trailing null */
2827 strncpy(pSMB->FileName, searchName, name_len);
2830 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2831 pSMB->TotalDataCount = 0;
2832 pSMB->MaxParameterCount = cpu_to_le16(2);
2833 /* BB find exact max data count below from sess structure BB */
2834 pSMB->MaxDataCount = cpu_to_le16(4000);
2835 pSMB->MaxSetupCount = 0;
2839 pSMB->Reserved2 = 0;
2840 pSMB->ParameterOffset = cpu_to_le16(
2841 offsetof(struct smb_com_transaction2_qpi_req,
2842 InformationLevel) - 4);
2843 pSMB->DataCount = 0;
2844 pSMB->DataOffset = 0;
2845 pSMB->SetupCount = 1;
2846 pSMB->Reserved3 = 0;
2847 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2848 byte_count = params + 1 /* pad */ ;
2849 pSMB->TotalParameterCount = cpu_to_le16(params);
2850 pSMB->ParameterCount = pSMB->TotalParameterCount;
2851 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2852 pSMB->Reserved4 = 0;
2853 pSMB->hdr.smb_buf_length += byte_count;
2854 pSMB->ByteCount = cpu_to_le16(byte_count);
2856 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2857 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2858 cifs_stats_inc(&tcon->num_acl_get);
2860 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2862 /* decode response */
2864 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2865 if (rc || (pSMBr->ByteCount < 2))
2866 /* BB also check enough total bytes returned */
2867 rc = -EIO; /* bad smb */
2869 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2870 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2871 rc = cifs_copy_posix_acl(acl_inf,
2872 (char *)&pSMBr->hdr.Protocol+data_offset,
2873 buflen, acl_type, count);
2876 cifs_buf_release(pSMB);
2883 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2884 const unsigned char *fileName,
2885 const char *local_acl, const int buflen,
2887 const struct nls_table *nls_codepage, int remap)
2889 struct smb_com_transaction2_spi_req *pSMB = NULL;
2890 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2894 int bytes_returned = 0;
2895 __u16 params, byte_count, data_count, param_offset, offset;
2897 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2899 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2903 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2905 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2906 PATH_MAX, nls_codepage, remap);
2907 name_len++; /* trailing null */
2909 } else { /* BB improve the check for buffer overruns BB */
2910 name_len = strnlen(fileName, PATH_MAX);
2911 name_len++; /* trailing null */
2912 strncpy(pSMB->FileName, fileName, name_len);
2914 params = 6 + name_len;
2915 pSMB->MaxParameterCount = cpu_to_le16(2);
2916 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2917 pSMB->MaxSetupCount = 0;
2921 pSMB->Reserved2 = 0;
2922 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2923 InformationLevel) - 4;
2924 offset = param_offset + params;
2925 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2926 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2928 /* convert to on the wire format for POSIX ACL */
2929 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2931 if (data_count == 0) {
2933 goto setACLerrorExit;
2935 pSMB->DataOffset = cpu_to_le16(offset);
2936 pSMB->SetupCount = 1;
2937 pSMB->Reserved3 = 0;
2938 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2939 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2940 byte_count = 3 /* pad */ + params + data_count;
2941 pSMB->DataCount = cpu_to_le16(data_count);
2942 pSMB->TotalDataCount = pSMB->DataCount;
2943 pSMB->ParameterCount = cpu_to_le16(params);
2944 pSMB->TotalParameterCount = pSMB->ParameterCount;
2945 pSMB->Reserved4 = 0;
2946 pSMB->hdr.smb_buf_length += byte_count;
2947 pSMB->ByteCount = cpu_to_le16(byte_count);
2948 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2949 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2951 cFYI(1, ("Set POSIX ACL returned %d", rc));
2955 cifs_buf_release(pSMB);
2961 /* BB fix tabs in this function FIXME BB */
2963 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2964 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2967 struct smb_t2_qfi_req *pSMB = NULL;
2968 struct smb_t2_qfi_rsp *pSMBr = NULL;
2970 __u16 params, byte_count;
2972 cFYI(1, ("In GetExtAttr"));
2977 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2982 params = 2 /* level */ +2 /* fid */;
2983 pSMB->t2.TotalDataCount = 0;
2984 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2985 /* BB find exact max data count below from sess structure BB */
2986 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2987 pSMB->t2.MaxSetupCount = 0;
2988 pSMB->t2.Reserved = 0;
2990 pSMB->t2.Timeout = 0;
2991 pSMB->t2.Reserved2 = 0;
2992 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2994 pSMB->t2.DataCount = 0;
2995 pSMB->t2.DataOffset = 0;
2996 pSMB->t2.SetupCount = 1;
2997 pSMB->t2.Reserved3 = 0;
2998 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2999 byte_count = params + 1 /* pad */ ;
3000 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3001 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3002 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3005 pSMB->hdr.smb_buf_length += byte_count;
3006 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3008 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3009 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3011 cFYI(1, ("error %d in GetExtAttr", rc));
3013 /* decode response */
3014 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3015 if (rc || (pSMBr->ByteCount < 2))
3016 /* BB also check enough total bytes returned */
3017 /* If rc should we check for EOPNOSUPP and
3018 disable the srvino flag? or in caller? */
3019 rc = -EIO; /* bad smb */
3021 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3022 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3023 struct file_chattr_info *pfinfo;
3024 /* BB Do we need a cast or hash here ? */
3026 cFYI(1, ("Illegal size ret in GetExtAttr"));
3030 pfinfo = (struct file_chattr_info *)
3031 (data_offset + (char *) &pSMBr->hdr.Protocol);
3032 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3033 *pMask = le64_to_cpu(pfinfo->mask);
3037 cifs_buf_release(pSMB);
3039 goto GetExtAttrRetry;
3043 #endif /* CONFIG_POSIX */
3046 /* security id for everyone */
3047 static const struct cifs_sid sid_everyone =
3048 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
3050 static const struct cifs_sid sid_user =
3051 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
3053 /* Convert CIFS ACL to POSIX form */
3054 static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
3059 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3061 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3062 /* BB fix up return info */ char *acl_inf, const int buflen,
3063 const int acl_type /* ACCESS/DEFAULT not sure implication */)
3067 QUERY_SEC_DESC_REQ * pSMB;
3070 cFYI(1, ("GetCifsACL"));
3072 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3073 8 /* parm len */, tcon, (void **) &pSMB);
3077 pSMB->MaxParameterCount = cpu_to_le32(4);
3078 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3079 pSMB->MaxSetupCount = 0;
3080 pSMB->Fid = fid; /* file handle always le */
3081 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3083 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3084 pSMB->hdr.smb_buf_length += 11;
3085 iov[0].iov_base = (char *)pSMB;
3086 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3088 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
3089 cifs_stats_inc(&tcon->num_acl_get);
3091 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3092 } else { /* decode response */
3093 struct cifs_sid *psec_desc;
3098 struct smb_com_ntransact_rsp *pSMBr;
3100 /* validate_nttransact */
3101 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3102 (char **)&psec_desc,
3103 &parm_len, &data_len);
3106 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3108 cERROR(1, ("smb %p parm %p data %p",
3109 pSMBr, parm, psec_desc)); /* BB removeme BB */
3111 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3112 rc = -EIO; /* bad smb */
3116 /* BB check that data area is minimum length and as big as acl_len */
3118 acl_len = le32_to_cpu(*(__le32 *)parm);
3119 /* BB check if (acl_len > bufsize) */
3121 parse_sec_desc(psec_desc, acl_len);
3124 if (buf_type == CIFS_SMALL_BUFFER)
3125 cifs_small_buf_release(iov[0].iov_base);
3126 else if (buf_type == CIFS_LARGE_BUFFER)
3127 cifs_buf_release(iov[0].iov_base);
3128 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3132 /* Legacy Query Path Information call for lookup to old servers such
3134 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3135 const unsigned char *searchName,
3136 FILE_ALL_INFO *pFinfo,
3137 const struct nls_table *nls_codepage, int remap)
3139 QUERY_INFORMATION_REQ * pSMB;
3140 QUERY_INFORMATION_RSP * pSMBr;
3145 cFYI(1, ("In SMBQPath path %s", searchName));
3147 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3152 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3154 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3155 PATH_MAX, nls_codepage, remap);
3156 name_len++; /* trailing null */
3159 name_len = strnlen(searchName, PATH_MAX);
3160 name_len++; /* trailing null */
3161 strncpy(pSMB->FileName, searchName, name_len);
3163 pSMB->BufferFormat = 0x04;
3164 name_len++; /* account for buffer type byte */
3165 pSMB->hdr.smb_buf_length += (__u16) name_len;
3166 pSMB->ByteCount = cpu_to_le16(name_len);
3168 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3169 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3171 cFYI(1, ("Send error in QueryInfo = %d", rc));
3172 } else if (pFinfo) { /* decode response */
3174 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3175 /* BB FIXME - add time zone adjustment BB */
3176 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3179 /* decode time fields */
3180 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3181 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3182 pFinfo->LastAccessTime = 0;
3183 pFinfo->AllocationSize =
3184 cpu_to_le64(le32_to_cpu(pSMBr->size));
3185 pFinfo->EndOfFile = pFinfo->AllocationSize;
3186 pFinfo->Attributes =
3187 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3189 rc = -EIO; /* bad buffer passed in */
3191 cifs_buf_release(pSMB);
3203 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3204 const unsigned char *searchName,
3205 FILE_ALL_INFO * pFindData,
3206 int legacy /* old style infolevel */,
3207 const struct nls_table *nls_codepage, int remap)
3209 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3210 TRANSACTION2_QPI_REQ *pSMB = NULL;
3211 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3215 __u16 params, byte_count;
3217 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3219 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3224 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3226 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3227 PATH_MAX, nls_codepage, remap);
3228 name_len++; /* trailing null */
3230 } else { /* BB improve the check for buffer overruns BB */
3231 name_len = strnlen(searchName, PATH_MAX);
3232 name_len++; /* trailing null */
3233 strncpy(pSMB->FileName, searchName, name_len);
3236 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3237 pSMB->TotalDataCount = 0;
3238 pSMB->MaxParameterCount = cpu_to_le16(2);
3239 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3240 pSMB->MaxSetupCount = 0;
3244 pSMB->Reserved2 = 0;
3245 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3246 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3247 pSMB->DataCount = 0;
3248 pSMB->DataOffset = 0;
3249 pSMB->SetupCount = 1;
3250 pSMB->Reserved3 = 0;
3251 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3252 byte_count = params + 1 /* pad */ ;
3253 pSMB->TotalParameterCount = cpu_to_le16(params);
3254 pSMB->ParameterCount = pSMB->TotalParameterCount;
3256 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3258 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3259 pSMB->Reserved4 = 0;
3260 pSMB->hdr.smb_buf_length += byte_count;
3261 pSMB->ByteCount = cpu_to_le16(byte_count);
3263 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3264 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3266 cFYI(1, ("Send error in QPathInfo = %d", rc));
3267 } else { /* decode response */
3268 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3270 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3272 else if (!legacy && (pSMBr->ByteCount < 40))
3273 rc = -EIO; /* bad smb */
3274 else if (legacy && (pSMBr->ByteCount < 24))
3275 rc = -EIO; /* 24 or 26 expected but we do not read
3277 else if (pFindData) {
3279 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3280 if (legacy) /* we do not read the last field, EAsize,
3281 fortunately since it varies by subdialect
3282 and on Set vs. Get, is two bytes or 4
3283 bytes depending but we don't care here */
3284 size = sizeof(FILE_INFO_STANDARD);
3286 size = sizeof(FILE_ALL_INFO);
3287 memcpy((char *) pFindData,
3288 (char *) &pSMBr->hdr.Protocol +
3293 cifs_buf_release(pSMB);
3295 goto QPathInfoRetry;
3301 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3302 const unsigned char *searchName,
3303 FILE_UNIX_BASIC_INFO * pFindData,
3304 const struct nls_table *nls_codepage, int remap)
3306 /* SMB_QUERY_FILE_UNIX_BASIC */
3307 TRANSACTION2_QPI_REQ *pSMB = NULL;
3308 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3310 int bytes_returned = 0;
3312 __u16 params, byte_count;
3314 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3316 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3321 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3323 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3324 PATH_MAX, nls_codepage, remap);
3325 name_len++; /* trailing null */
3327 } else { /* BB improve the check for buffer overruns BB */
3328 name_len = strnlen(searchName, PATH_MAX);
3329 name_len++; /* trailing null */
3330 strncpy(pSMB->FileName, searchName, name_len);
3333 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3334 pSMB->TotalDataCount = 0;
3335 pSMB->MaxParameterCount = cpu_to_le16(2);
3336 /* BB find exact max SMB PDU from sess structure BB */
3337 pSMB->MaxDataCount = cpu_to_le16(4000);
3338 pSMB->MaxSetupCount = 0;
3342 pSMB->Reserved2 = 0;
3343 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3344 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3345 pSMB->DataCount = 0;
3346 pSMB->DataOffset = 0;
3347 pSMB->SetupCount = 1;
3348 pSMB->Reserved3 = 0;
3349 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3350 byte_count = params + 1 /* pad */ ;
3351 pSMB->TotalParameterCount = cpu_to_le16(params);
3352 pSMB->ParameterCount = pSMB->TotalParameterCount;
3353 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3354 pSMB->Reserved4 = 0;
3355 pSMB->hdr.smb_buf_length += byte_count;
3356 pSMB->ByteCount = cpu_to_le16(byte_count);
3358 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3359 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3361 cFYI(1, ("Send error in QPathInfo = %d", rc));
3362 } else { /* decode response */
3363 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3365 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3366 rc = -EIO; /* bad smb */
3368 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3369 memcpy((char *) pFindData,
3370 (char *) &pSMBr->hdr.Protocol +
3372 sizeof (FILE_UNIX_BASIC_INFO));
3375 cifs_buf_release(pSMB);
3377 goto UnixQPathInfoRetry;
3382 #if 0 /* function unused at present */
3383 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3384 const char *searchName, FILE_ALL_INFO * findData,
3385 const struct nls_table *nls_codepage)
3387 /* level 257 SMB_ */
3388 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3389 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3393 __u16 params, byte_count;
3395 cFYI(1, ("In FindUnique"));
3397 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3402 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3404 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3405 PATH_MAX, nls_codepage);
3406 name_len++; /* trailing null */
3408 } else { /* BB improve the check for buffer overruns BB */
3409 name_len = strnlen(searchName, PATH_MAX);
3410 name_len++; /* trailing null */
3411 strncpy(pSMB->FileName, searchName, name_len);
3414 params = 12 + name_len /* includes null */ ;
3415 pSMB->TotalDataCount = 0; /* no EAs */
3416 pSMB->MaxParameterCount = cpu_to_le16(2);
3417 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3418 pSMB->MaxSetupCount = 0;
3422 pSMB->Reserved2 = 0;
3423 pSMB->ParameterOffset = cpu_to_le16(
3424 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3425 pSMB->DataCount = 0;
3426 pSMB->DataOffset = 0;
3427 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3428 pSMB->Reserved3 = 0;
3429 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3430 byte_count = params + 1 /* pad */ ;
3431 pSMB->TotalParameterCount = cpu_to_le16(params);
3432 pSMB->ParameterCount = pSMB->TotalParameterCount;
3433 pSMB->SearchAttributes =
3434 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3436 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3437 pSMB->SearchFlags = cpu_to_le16(1);
3438 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3439 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3440 pSMB->hdr.smb_buf_length += byte_count;
3441 pSMB->ByteCount = cpu_to_le16(byte_count);
3443 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3444 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3447 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3448 } else { /* decode response */
3449 cifs_stats_inc(&tcon->num_ffirst);
3453 cifs_buf_release(pSMB);
3455 goto findUniqueRetry;
3459 #endif /* end unused (temporarily) function */
3461 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3463 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3464 const char *searchName,
3465 const struct nls_table *nls_codepage,
3467 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3469 /* level 257 SMB_ */
3470 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3471 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3472 T2_FFIRST_RSP_PARMS * parms;
3474 int bytes_returned = 0;
3476 __u16 params, byte_count;
3478 cFYI(1, ("In FindFirst for %s", searchName));
3481 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3486 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3488 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3489 PATH_MAX, nls_codepage, remap);
3490 /* We can not add the asterik earlier in case
3491 it got remapped to 0xF03A as if it were part of the
3492 directory name instead of a wildcard */
3494 pSMB->FileName[name_len] = dirsep;
3495 pSMB->FileName[name_len+1] = 0;
3496 pSMB->FileName[name_len+2] = '*';
3497 pSMB->FileName[name_len+3] = 0;
3498 name_len += 4; /* now the trailing null */
3499 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3500 pSMB->FileName[name_len+1] = 0;
3502 } else { /* BB add check for overrun of SMB buf BB */
3503 name_len = strnlen(searchName, PATH_MAX);
3504 /* BB fix here and in unicode clause above ie
3505 if (name_len > buffersize-header)
3506 free buffer exit; BB */
3507 strncpy(pSMB->FileName, searchName, name_len);
3508 pSMB->FileName[name_len] = dirsep;
3509 pSMB->FileName[name_len+1] = '*';
3510 pSMB->FileName[name_len+2] = 0;
3514 params = 12 + name_len /* includes null */ ;
3515 pSMB->TotalDataCount = 0; /* no EAs */
3516 pSMB->MaxParameterCount = cpu_to_le16(10);
3517 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3518 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3519 pSMB->MaxSetupCount = 0;
3523 pSMB->Reserved2 = 0;
3524 byte_count = params + 1 /* pad */ ;
3525 pSMB->TotalParameterCount = cpu_to_le16(params);
3526 pSMB->ParameterCount = pSMB->TotalParameterCount;
3527 pSMB->ParameterOffset = cpu_to_le16(
3528 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3530 pSMB->DataCount = 0;
3531 pSMB->DataOffset = 0;
3532 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3533 pSMB->Reserved3 = 0;
3534 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3535 pSMB->SearchAttributes =
3536 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3538 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3539 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3540 CIFS_SEARCH_RETURN_RESUME);
3541 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3543 /* BB what should we set StorageType to? Does it matter? BB */
3544 pSMB->SearchStorageType = 0;
3545 pSMB->hdr.smb_buf_length += byte_count;
3546 pSMB->ByteCount = cpu_to_le16(byte_count);
3548 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3549 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3550 cifs_stats_inc(&tcon->num_ffirst);
3552 if (rc) {/* BB add logic to retry regular search if Unix search
3553 rejected unexpectedly by server */
3554 /* BB Add code to handle unsupported level rc */
3555 cFYI(1, ("Error in FindFirst = %d", rc));
3557 cifs_buf_release(pSMB);
3559 /* BB eventually could optimize out free and realloc of buf */
3562 goto findFirstRetry;
3563 } else { /* decode response */
3564 /* BB remember to free buffer if error BB */
3565 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3567 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3568 psrch_inf->unicode = TRUE;
3570 psrch_inf->unicode = FALSE;
3572 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3573 psrch_inf->smallBuf = 0;
3574 psrch_inf->srch_entries_start =
3575 (char *) &pSMBr->hdr.Protocol +
3576 le16_to_cpu(pSMBr->t2.DataOffset);
3577 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3578 le16_to_cpu(pSMBr->t2.ParameterOffset));
3580 if (parms->EndofSearch)
3581 psrch_inf->endOfSearch = TRUE;
3583 psrch_inf->endOfSearch = FALSE;
3585 psrch_inf->entries_in_buffer =
3586 le16_to_cpu(parms->SearchCount);
3587 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3588 psrch_inf->entries_in_buffer;
3589 *pnetfid = parms->SearchHandle;
3591 cifs_buf_release(pSMB);
3598 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3599 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3601 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3602 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3603 T2_FNEXT_RSP_PARMS * parms;
3604 char *response_data;
3606 int bytes_returned, name_len;
3607 __u16 params, byte_count;
3609 cFYI(1, ("In FindNext"));
3611 if (psrch_inf->endOfSearch == TRUE)
3614 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3619 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3621 pSMB->TotalDataCount = 0; /* no EAs */
3622 pSMB->MaxParameterCount = cpu_to_le16(8);
3623 pSMB->MaxDataCount =
3624 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3626 pSMB->MaxSetupCount = 0;
3630 pSMB->Reserved2 = 0;
3631 pSMB->ParameterOffset = cpu_to_le16(
3632 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3633 pSMB->DataCount = 0;
3634 pSMB->DataOffset = 0;
3635 pSMB->SetupCount = 1;
3636 pSMB->Reserved3 = 0;
3637 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3638 pSMB->SearchHandle = searchHandle; /* always kept as le */
3640 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3641 /* test for Unix extensions */
3642 /* if (tcon->ses->capabilities & CAP_UNIX) {
3643 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3644 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3646 pSMB->InformationLevel =
3647 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3648 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3650 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3651 pSMB->ResumeKey = psrch_inf->resume_key;
3653 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3655 name_len = psrch_inf->resume_name_len;
3657 if (name_len < PATH_MAX) {
3658 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3659 byte_count += name_len;
3660 /* 14 byte parm len above enough for 2 byte null terminator */
3661 pSMB->ResumeFileName[name_len] = 0;
3662 pSMB->ResumeFileName[name_len+1] = 0;
3665 goto FNext2_err_exit;
3667 byte_count = params + 1 /* pad */ ;
3668 pSMB->TotalParameterCount = cpu_to_le16(params);
3669 pSMB->ParameterCount = pSMB->TotalParameterCount;
3670 pSMB->hdr.smb_buf_length += byte_count;
3671 pSMB->ByteCount = cpu_to_le16(byte_count);
3673 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3674 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3675 cifs_stats_inc(&tcon->num_fnext);
3678 psrch_inf->endOfSearch = TRUE;
3679 rc = 0; /* search probably was closed at end of search*/
3681 cFYI(1, ("FindNext returned = %d", rc));
3682 } else { /* decode response */
3683 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3686 /* BB fixme add lock for file (srch_info) struct here */
3687 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3688 psrch_inf->unicode = TRUE;
3690 psrch_inf->unicode = FALSE;
3691 response_data = (char *) &pSMBr->hdr.Protocol +
3692 le16_to_cpu(pSMBr->t2.ParameterOffset);
3693 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3694 response_data = (char *)&pSMBr->hdr.Protocol +
3695 le16_to_cpu(pSMBr->t2.DataOffset);
3696 if (psrch_inf->smallBuf)
3697 cifs_small_buf_release(
3698 psrch_inf->ntwrk_buf_start);
3700 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3701 psrch_inf->srch_entries_start = response_data;
3702 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3703 psrch_inf->smallBuf = 0;
3704 if (parms->EndofSearch)
3705 psrch_inf->endOfSearch = TRUE;
3707 psrch_inf->endOfSearch = FALSE;
3708 psrch_inf->entries_in_buffer =
3709 le16_to_cpu(parms->SearchCount);
3710 psrch_inf->index_of_last_entry +=
3711 psrch_inf->entries_in_buffer;
3712 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3713 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3715 /* BB fixme add unlock here */
3720 /* BB On error, should we leave previous search buf (and count and
3721 last entry fields) intact or free the previous one? */
3723 /* Note: On -EAGAIN error only caller can retry on handle based calls
3724 since file handle passed in no longer valid */
3727 cifs_buf_release(pSMB);
3732 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3733 const __u16 searchHandle)
3736 FINDCLOSE_REQ *pSMB = NULL;
3737 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3740 cFYI(1, ("In CIFSSMBFindClose"));
3741 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3743 /* no sense returning error if session restarted
3744 as file handle has been closed */
3750 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3751 pSMB->FileID = searchHandle;
3752 pSMB->ByteCount = 0;
3753 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3754 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3756 cERROR(1, ("Send error in FindClose = %d", rc));
3758 cifs_stats_inc(&tcon->num_fclose);
3759 cifs_small_buf_release(pSMB);
3761 /* Since session is dead, search handle closed on server already */
3769 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3770 const unsigned char *searchName,
3771 __u64 * inode_number,
3772 const struct nls_table *nls_codepage, int remap)
3775 TRANSACTION2_QPI_REQ *pSMB = NULL;
3776 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3777 int name_len, bytes_returned;
3778 __u16 params, byte_count;
3780 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3784 GetInodeNumberRetry:
3785 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3790 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3792 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3793 PATH_MAX, nls_codepage, remap);
3794 name_len++; /* trailing null */
3796 } else { /* BB improve the check for buffer overruns BB */
3797 name_len = strnlen(searchName, PATH_MAX);
3798 name_len++; /* trailing null */
3799 strncpy(pSMB->FileName, searchName, name_len);
3802 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3803 pSMB->TotalDataCount = 0;
3804 pSMB->MaxParameterCount = cpu_to_le16(2);
3805 /* BB find exact max data count below from sess structure BB */
3806 pSMB->MaxDataCount = cpu_to_le16(4000);
3807 pSMB->MaxSetupCount = 0;
3811 pSMB->Reserved2 = 0;
3812 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3813 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3814 pSMB->DataCount = 0;
3815 pSMB->DataOffset = 0;
3816 pSMB->SetupCount = 1;
3817 pSMB->Reserved3 = 0;
3818 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3819 byte_count = params + 1 /* pad */ ;
3820 pSMB->TotalParameterCount = cpu_to_le16(params);
3821 pSMB->ParameterCount = pSMB->TotalParameterCount;
3822 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3823 pSMB->Reserved4 = 0;
3824 pSMB->hdr.smb_buf_length += byte_count;
3825 pSMB->ByteCount = cpu_to_le16(byte_count);
3827 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3828 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3830 cFYI(1, ("error %d in QueryInternalInfo", rc));
3832 /* decode response */
3833 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3834 if (rc || (pSMBr->ByteCount < 2))
3835 /* BB also check enough total bytes returned */
3836 /* If rc should we check for EOPNOSUPP and
3837 disable the srvino flag? or in caller? */
3838 rc = -EIO; /* bad smb */
3840 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3841 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3842 struct file_internal_info *pfinfo;
3843 /* BB Do we need a cast or hash here ? */
3845 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3847 goto GetInodeNumOut;
3849 pfinfo = (struct file_internal_info *)
3850 (data_offset + (char *) &pSMBr->hdr.Protocol);
3851 *inode_number = pfinfo->UniqueId;
3855 cifs_buf_release(pSMB);
3857 goto GetInodeNumberRetry;
3862 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3863 const unsigned char *searchName,
3864 unsigned char **targetUNCs,
3865 unsigned int *number_of_UNC_in_array,
3866 const struct nls_table *nls_codepage, int remap)
3868 /* TRANS2_GET_DFS_REFERRAL */
3869 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3870 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3871 struct dfs_referral_level_3 *referrals = NULL;
3877 __u16 params, byte_count;
3878 *number_of_UNC_in_array = 0;
3881 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3885 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3890 /* server pointer checked in called function,
3891 but should never be null here anyway */
3892 pSMB->hdr.Mid = GetNextMid(ses->server);
3893 pSMB->hdr.Tid = ses->ipc_tid;
3894 pSMB->hdr.Uid = ses->Suid;
3895 if (ses->capabilities & CAP_STATUS32) {
3896 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3898 if (ses->capabilities & CAP_DFS) {
3899 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3902 if (ses->capabilities & CAP_UNICODE) {
3903 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3905 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3906 searchName, PATH_MAX, nls_codepage, remap);
3907 name_len++; /* trailing null */
3909 } else { /* BB improve the check for buffer overruns BB */
3910 name_len = strnlen(searchName, PATH_MAX);
3911 name_len++; /* trailing null */
3912 strncpy(pSMB->RequestFileName, searchName, name_len);
3916 if (ses->server->secMode &
3917 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3918 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3921 pSMB->hdr.Uid = ses->Suid;
3923 params = 2 /* level */ + name_len /*includes null */ ;
3924 pSMB->TotalDataCount = 0;
3925 pSMB->DataCount = 0;
3926 pSMB->DataOffset = 0;
3927 pSMB->MaxParameterCount = 0;
3928 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3929 pSMB->MaxSetupCount = 0;
3933 pSMB->Reserved2 = 0;
3934 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3935 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3936 pSMB->SetupCount = 1;
3937 pSMB->Reserved3 = 0;
3938 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3939 byte_count = params + 3 /* pad */ ;
3940 pSMB->ParameterCount = cpu_to_le16(params);
3941 pSMB->TotalParameterCount = pSMB->ParameterCount;
3942 pSMB->MaxReferralLevel = cpu_to_le16(3);
3943 pSMB->hdr.smb_buf_length += byte_count;
3944 pSMB->ByteCount = cpu_to_le16(byte_count);
3946 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3947 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3949 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3950 } else { /* decode response */
3951 /* BB Add logic to parse referrals here */
3952 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3954 /* BB Also check if enough total bytes returned? */
3955 if (rc || (pSMBr->ByteCount < 17))
3956 rc = -EIO; /* bad smb */
3958 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3959 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3962 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3963 pSMBr->ByteCount, data_offset));
3965 (struct dfs_referral_level_3 *)
3966 (8 /* sizeof start of data block */ +
3968 (char *) &pSMBr->hdr.Protocol);
3969 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \n"
3970 "for referral one refer size: 0x%x srv "
3971 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3972 le16_to_cpu(pSMBr->NumberOfReferrals),
3973 le16_to_cpu(pSMBr->DFSFlags),
3974 le16_to_cpu(referrals->ReferralSize),
3975 le16_to_cpu(referrals->ServerType),
3976 le16_to_cpu(referrals->ReferralFlags),
3977 le16_to_cpu(referrals->TimeToLive)));
3978 /* BB This field is actually two bytes in from start of
3979 data block so we could do safety check that DataBlock
3980 begins at address of pSMBr->NumberOfReferrals */
3981 *number_of_UNC_in_array =
3982 le16_to_cpu(pSMBr->NumberOfReferrals);
3984 /* BB Fix below so can return more than one referral */
3985 if (*number_of_UNC_in_array > 1)
3986 *number_of_UNC_in_array = 1;
3988 /* get the length of the strings describing refs */
3990 for (i = 0; i < *number_of_UNC_in_array; i++) {
3991 /* make sure that DfsPathOffset not past end */
3993 le16_to_cpu(referrals->DfsPathOffset);
3994 if (offset > data_count) {
3995 /* if invalid referral, stop here and do
3996 not try to copy any more */
3997 *number_of_UNC_in_array = i;
4000 temp = ((char *)referrals) + offset;
4002 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4003 name_len += UniStrnlen((wchar_t *)temp,
4006 name_len += strnlen(temp, data_count);
4009 /* BB add check that referral pointer does
4010 not fall off end PDU */
4012 /* BB add check for name_len bigger than bcc */
4014 kmalloc(name_len+1+(*number_of_UNC_in_array),
4016 if (*targetUNCs == NULL) {
4020 /* copy the ref strings */
4021 referrals = (struct dfs_referral_level_3 *)
4022 (8 /* sizeof data hdr */ + data_offset +
4023 (char *) &pSMBr->hdr.Protocol);
4025 for (i = 0; i < *number_of_UNC_in_array; i++) {
4026 temp = ((char *)referrals) +
4027 le16_to_cpu(referrals->DfsPathOffset);
4028 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4029 cifs_strfromUCS_le(*targetUNCs,
4034 strncpy(*targetUNCs, temp, name_len);
4036 /* BB update target_uncs pointers */
4046 cifs_buf_release(pSMB);
4054 /* Query File System Info such as free space to old servers such as Win 9x */
4056 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4058 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4059 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4060 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4061 FILE_SYSTEM_ALLOC_INFO *response_data;
4063 int bytes_returned = 0;
4064 __u16 params, byte_count;
4066 cFYI(1, ("OldQFSInfo"));
4068 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4072 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4077 params = 2; /* level */
4078 pSMB->TotalDataCount = 0;
4079 pSMB->MaxParameterCount = cpu_to_le16(2);
4080 pSMB->MaxDataCount = cpu_to_le16(1000);
4081 pSMB->MaxSetupCount = 0;
4085 pSMB->Reserved2 = 0;
4086 byte_count = params + 1 /* pad */ ;
4087 pSMB->TotalParameterCount = cpu_to_le16(params);
4088 pSMB->ParameterCount = pSMB->TotalParameterCount;
4089 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4090 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4091 pSMB->DataCount = 0;
4092 pSMB->DataOffset = 0;
4093 pSMB->SetupCount = 1;
4094 pSMB->Reserved3 = 0;
4095 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4096 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4097 pSMB->hdr.smb_buf_length += byte_count;
4098 pSMB->ByteCount = cpu_to_le16(byte_count);
4100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4101 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4103 cFYI(1, ("Send error in QFSInfo = %d", rc));
4104 } else { /* decode response */
4105 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4107 if (rc || (pSMBr->ByteCount < 18))
4108 rc = -EIO; /* bad smb */
4110 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4111 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4112 pSMBr->ByteCount, data_offset));
4114 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4115 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4117 le16_to_cpu(response_data->BytesPerSector) *
4118 le32_to_cpu(response_data->
4119 SectorsPerAllocationUnit);
4121 le32_to_cpu(response_data->TotalAllocationUnits);
4122 FSData->f_bfree = FSData->f_bavail =
4123 le32_to_cpu(response_data->FreeAllocationUnits);
4125 ("Blocks: %lld Free: %lld Block size %ld",
4126 (unsigned long long)FSData->f_blocks,
4127 (unsigned long long)FSData->f_bfree,
4131 cifs_buf_release(pSMB);
4134 goto oldQFSInfoRetry;
4140 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4142 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4143 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4144 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4145 FILE_SYSTEM_INFO *response_data;
4147 int bytes_returned = 0;
4148 __u16 params, byte_count;
4150 cFYI(1, ("In QFSInfo"));
4152 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4157 params = 2; /* level */
4158 pSMB->TotalDataCount = 0;
4159 pSMB->MaxParameterCount = cpu_to_le16(2);
4160 pSMB->MaxDataCount = cpu_to_le16(1000);
4161 pSMB->MaxSetupCount = 0;
4165 pSMB->Reserved2 = 0;
4166 byte_count = params + 1 /* pad */ ;
4167 pSMB->TotalParameterCount = cpu_to_le16(params);
4168 pSMB->ParameterCount = pSMB->TotalParameterCount;
4169 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4170 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4171 pSMB->DataCount = 0;
4172 pSMB->DataOffset = 0;
4173 pSMB->SetupCount = 1;
4174 pSMB->Reserved3 = 0;
4175 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4176 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4177 pSMB->hdr.smb_buf_length += byte_count;
4178 pSMB->ByteCount = cpu_to_le16(byte_count);
4180 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4181 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4183 cFYI(1, ("Send error in QFSInfo = %d", rc));
4184 } else { /* decode response */
4185 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4187 if (rc || (pSMBr->ByteCount < 24))
4188 rc = -EIO; /* bad smb */
4190 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4194 *) (((char *) &pSMBr->hdr.Protocol) +
4197 le32_to_cpu(response_data->BytesPerSector) *
4198 le32_to_cpu(response_data->
4199 SectorsPerAllocationUnit);
4201 le64_to_cpu(response_data->TotalAllocationUnits);
4202 FSData->f_bfree = FSData->f_bavail =
4203 le64_to_cpu(response_data->FreeAllocationUnits);
4205 ("Blocks: %lld Free: %lld Block size %ld",
4206 (unsigned long long)FSData->f_blocks,
4207 (unsigned long long)FSData->f_bfree,
4211 cifs_buf_release(pSMB);
4220 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4222 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4223 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4224 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4225 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4227 int bytes_returned = 0;
4228 __u16 params, byte_count;
4230 cFYI(1, ("In QFSAttributeInfo"));
4232 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4237 params = 2; /* level */
4238 pSMB->TotalDataCount = 0;
4239 pSMB->MaxParameterCount = cpu_to_le16(2);
4240 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4241 pSMB->MaxSetupCount = 0;
4245 pSMB->Reserved2 = 0;
4246 byte_count = params + 1 /* pad */ ;
4247 pSMB->TotalParameterCount = cpu_to_le16(params);
4248 pSMB->ParameterCount = pSMB->TotalParameterCount;
4249 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4250 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4251 pSMB->DataCount = 0;
4252 pSMB->DataOffset = 0;
4253 pSMB->SetupCount = 1;
4254 pSMB->Reserved3 = 0;
4255 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4256 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4257 pSMB->hdr.smb_buf_length += byte_count;
4258 pSMB->ByteCount = cpu_to_le16(byte_count);
4260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4261 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4263 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4264 } else { /* decode response */
4265 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4267 if (rc || (pSMBr->ByteCount < 13)) {
4268 /* BB also check if enough bytes returned */
4269 rc = -EIO; /* bad smb */
4271 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4273 (FILE_SYSTEM_ATTRIBUTE_INFO
4274 *) (((char *) &pSMBr->hdr.Protocol) +
4276 memcpy(&tcon->fsAttrInfo, response_data,
4277 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
4280 cifs_buf_release(pSMB);
4283 goto QFSAttributeRetry;
4289 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4291 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4292 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4293 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4294 FILE_SYSTEM_DEVICE_INFO *response_data;
4296 int bytes_returned = 0;
4297 __u16 params, byte_count;
4299 cFYI(1, ("In QFSDeviceInfo"));
4301 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4306 params = 2; /* level */
4307 pSMB->TotalDataCount = 0;
4308 pSMB->MaxParameterCount = cpu_to_le16(2);
4309 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4310 pSMB->MaxSetupCount = 0;
4314 pSMB->Reserved2 = 0;
4315 byte_count = params + 1 /* pad */ ;
4316 pSMB->TotalParameterCount = cpu_to_le16(params);
4317 pSMB->ParameterCount = pSMB->TotalParameterCount;
4318 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4319 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4321 pSMB->DataCount = 0;
4322 pSMB->DataOffset = 0;
4323 pSMB->SetupCount = 1;
4324 pSMB->Reserved3 = 0;
4325 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4326 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4327 pSMB->hdr.smb_buf_length += byte_count;
4328 pSMB->ByteCount = cpu_to_le16(byte_count);
4330 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4331 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4333 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4334 } else { /* decode response */
4335 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4337 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4338 rc = -EIO; /* bad smb */
4340 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4342 (FILE_SYSTEM_DEVICE_INFO *)
4343 (((char *) &pSMBr->hdr.Protocol) +
4345 memcpy(&tcon->fsDevInfo, response_data,
4346 sizeof (FILE_SYSTEM_DEVICE_INFO));
4349 cifs_buf_release(pSMB);
4352 goto QFSDeviceRetry;
4358 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4360 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4361 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4362 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4363 FILE_SYSTEM_UNIX_INFO *response_data;
4365 int bytes_returned = 0;
4366 __u16 params, byte_count;
4368 cFYI(1, ("In QFSUnixInfo"));
4370 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4375 params = 2; /* level */
4376 pSMB->TotalDataCount = 0;
4377 pSMB->DataCount = 0;
4378 pSMB->DataOffset = 0;
4379 pSMB->MaxParameterCount = cpu_to_le16(2);
4380 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4381 pSMB->MaxSetupCount = 0;
4385 pSMB->Reserved2 = 0;
4386 byte_count = params + 1 /* pad */ ;
4387 pSMB->ParameterCount = cpu_to_le16(params);
4388 pSMB->TotalParameterCount = pSMB->ParameterCount;
4389 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4390 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4391 pSMB->SetupCount = 1;
4392 pSMB->Reserved3 = 0;
4393 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4394 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4395 pSMB->hdr.smb_buf_length += byte_count;
4396 pSMB->ByteCount = cpu_to_le16(byte_count);
4398 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4399 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4401 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4402 } else { /* decode response */
4403 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4405 if (rc || (pSMBr->ByteCount < 13)) {
4406 rc = -EIO; /* bad smb */
4408 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4410 (FILE_SYSTEM_UNIX_INFO
4411 *) (((char *) &pSMBr->hdr.Protocol) +
4413 memcpy(&tcon->fsUnixInfo, response_data,
4414 sizeof (FILE_SYSTEM_UNIX_INFO));
4417 cifs_buf_release(pSMB);
4427 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4429 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4430 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4431 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4433 int bytes_returned = 0;
4434 __u16 params, param_offset, offset, byte_count;
4436 cFYI(1, ("In SETFSUnixInfo"));
4438 /* BB switch to small buf init to save memory */
4439 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4444 params = 4; /* 2 bytes zero followed by info level. */
4445 pSMB->MaxSetupCount = 0;
4449 pSMB->Reserved2 = 0;
4450 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4452 offset = param_offset + params;
4454 pSMB->MaxParameterCount = cpu_to_le16(4);
4455 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4456 pSMB->SetupCount = 1;
4457 pSMB->Reserved3 = 0;
4458 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4459 byte_count = 1 /* pad */ + params + 12;
4461 pSMB->DataCount = cpu_to_le16(12);
4462 pSMB->ParameterCount = cpu_to_le16(params);
4463 pSMB->TotalDataCount = pSMB->DataCount;
4464 pSMB->TotalParameterCount = pSMB->ParameterCount;
4465 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4466 pSMB->DataOffset = cpu_to_le16(offset);
4470 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4473 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4474 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4475 pSMB->ClientUnixCap = cpu_to_le64(cap);
4477 pSMB->hdr.smb_buf_length += byte_count;
4478 pSMB->ByteCount = cpu_to_le16(byte_count);
4480 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4481 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4483 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4484 } else { /* decode response */
4485 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4487 rc = -EIO; /* bad smb */
4490 cifs_buf_release(pSMB);
4493 goto SETFSUnixRetry;
4501 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4502 struct kstatfs *FSData)
4504 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4505 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4506 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4507 FILE_SYSTEM_POSIX_INFO *response_data;
4509 int bytes_returned = 0;
4510 __u16 params, byte_count;
4512 cFYI(1, ("In QFSPosixInfo"));
4514 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4519 params = 2; /* level */
4520 pSMB->TotalDataCount = 0;
4521 pSMB->DataCount = 0;
4522 pSMB->DataOffset = 0;
4523 pSMB->MaxParameterCount = cpu_to_le16(2);
4524 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4525 pSMB->MaxSetupCount = 0;
4529 pSMB->Reserved2 = 0;
4530 byte_count = params + 1 /* pad */ ;
4531 pSMB->ParameterCount = cpu_to_le16(params);
4532 pSMB->TotalParameterCount = pSMB->ParameterCount;
4533 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4534 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4535 pSMB->SetupCount = 1;
4536 pSMB->Reserved3 = 0;
4537 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4538 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4539 pSMB->hdr.smb_buf_length += byte_count;
4540 pSMB->ByteCount = cpu_to_le16(byte_count);
4542 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4543 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4545 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4546 } else { /* decode response */
4547 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4549 if (rc || (pSMBr->ByteCount < 13)) {
4550 rc = -EIO; /* bad smb */
4552 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4554 (FILE_SYSTEM_POSIX_INFO
4555 *) (((char *) &pSMBr->hdr.Protocol) +
4558 le32_to_cpu(response_data->BlockSize);
4560 le64_to_cpu(response_data->TotalBlocks);
4562 le64_to_cpu(response_data->BlocksAvail);
4563 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4564 FSData->f_bavail = FSData->f_bfree;
4567 le64_to_cpu(response_data->UserBlocksAvail);
4569 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4571 le64_to_cpu(response_data->TotalFileNodes);
4572 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4574 le64_to_cpu(response_data->FreeFileNodes);
4577 cifs_buf_release(pSMB);
4586 /* We can not use write of zero bytes trick to
4587 set file size due to need for large file support. Also note that
4588 this SetPathInfo is preferred to SetFileInfo based method in next
4589 routine which is only needed to work around a sharing violation bug
4590 in Samba which this routine can run into */
4593 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4594 __u64 size, int SetAllocation,
4595 const struct nls_table *nls_codepage, int remap)
4597 struct smb_com_transaction2_spi_req *pSMB = NULL;
4598 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4599 struct file_end_of_file_info *parm_data;
4602 int bytes_returned = 0;
4603 __u16 params, byte_count, data_count, param_offset, offset;
4605 cFYI(1, ("In SetEOF"));
4607 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4612 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4614 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4615 PATH_MAX, nls_codepage, remap);
4616 name_len++; /* trailing null */
4618 } else { /* BB improve the check for buffer overruns BB */
4619 name_len = strnlen(fileName, PATH_MAX);
4620 name_len++; /* trailing null */
4621 strncpy(pSMB->FileName, fileName, name_len);
4623 params = 6 + name_len;
4624 data_count = sizeof (struct file_end_of_file_info);
4625 pSMB->MaxParameterCount = cpu_to_le16(2);
4626 pSMB->MaxDataCount = cpu_to_le16(4100);
4627 pSMB->MaxSetupCount = 0;
4631 pSMB->Reserved2 = 0;
4632 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4633 InformationLevel) - 4;
4634 offset = param_offset + params;
4635 if (SetAllocation) {
4636 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4637 pSMB->InformationLevel =
4638 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4640 pSMB->InformationLevel =
4641 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4642 } else /* Set File Size */ {
4643 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4644 pSMB->InformationLevel =
4645 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4647 pSMB->InformationLevel =
4648 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4652 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4654 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4655 pSMB->DataOffset = cpu_to_le16(offset);
4656 pSMB->SetupCount = 1;
4657 pSMB->Reserved3 = 0;
4658 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4659 byte_count = 3 /* pad */ + params + data_count;
4660 pSMB->DataCount = cpu_to_le16(data_count);
4661 pSMB->TotalDataCount = pSMB->DataCount;
4662 pSMB->ParameterCount = cpu_to_le16(params);
4663 pSMB->TotalParameterCount = pSMB->ParameterCount;
4664 pSMB->Reserved4 = 0;
4665 pSMB->hdr.smb_buf_length += byte_count;
4666 parm_data->FileSize = cpu_to_le64(size);
4667 pSMB->ByteCount = cpu_to_le16(byte_count);
4668 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4669 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4671 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4674 cifs_buf_release(pSMB);
4683 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4684 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4686 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4687 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4689 struct file_end_of_file_info *parm_data;
4691 int bytes_returned = 0;
4692 __u16 params, param_offset, offset, byte_count, count;
4694 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4696 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4701 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4703 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4704 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4707 pSMB->MaxSetupCount = 0;
4711 pSMB->Reserved2 = 0;
4712 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4713 offset = param_offset + params;
4715 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4717 count = sizeof(struct file_end_of_file_info);
4718 pSMB->MaxParameterCount = cpu_to_le16(2);
4719 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4720 pSMB->SetupCount = 1;
4721 pSMB->Reserved3 = 0;
4722 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4723 byte_count = 3 /* pad */ + params + count;
4724 pSMB->DataCount = cpu_to_le16(count);
4725 pSMB->ParameterCount = cpu_to_le16(params);
4726 pSMB->TotalDataCount = pSMB->DataCount;
4727 pSMB->TotalParameterCount = pSMB->ParameterCount;
4728 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4730 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4732 pSMB->DataOffset = cpu_to_le16(offset);
4733 parm_data->FileSize = cpu_to_le64(size);
4735 if (SetAllocation) {
4736 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4737 pSMB->InformationLevel =
4738 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4740 pSMB->InformationLevel =
4741 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4742 } else /* Set File Size */ {
4743 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4744 pSMB->InformationLevel =
4745 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4747 pSMB->InformationLevel =
4748 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4750 pSMB->Reserved4 = 0;
4751 pSMB->hdr.smb_buf_length += byte_count;
4752 pSMB->ByteCount = cpu_to_le16(byte_count);
4753 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4754 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4757 ("Send error in SetFileInfo (SetFileSize) = %d",
4762 cifs_small_buf_release(pSMB);
4764 /* Note: On -EAGAIN error only caller can retry on handle based calls
4765 since file handle passed in no longer valid */
4770 /* Some legacy servers such as NT4 require that the file times be set on
4771 an open handle, rather than by pathname - this is awkward due to
4772 potential access conflicts on the open, but it is unavoidable for these
4773 old servers since the only other choice is to go from 100 nanosecond DCE
4774 time and resort to the original setpathinfo level which takes the ancient
4775 DOS time format with 2 second granularity */
4777 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4778 const FILE_BASIC_INFO *data, __u16 fid)
4780 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4781 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4784 int bytes_returned = 0;
4785 __u16 params, param_offset, offset, byte_count, count;
4787 cFYI(1, ("Set Times (via SetFileInfo)"));
4788 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4793 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4795 /* At this point there is no need to override the current pid
4796 with the pid of the opener, but that could change if we someday
4797 use an existing handle (rather than opening one on the fly) */
4798 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4799 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4802 pSMB->MaxSetupCount = 0;
4806 pSMB->Reserved2 = 0;
4807 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4808 offset = param_offset + params;
4810 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4812 count = sizeof (FILE_BASIC_INFO);
4813 pSMB->MaxParameterCount = cpu_to_le16(2);
4814 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4815 pSMB->SetupCount = 1;
4816 pSMB->Reserved3 = 0;
4817 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4818 byte_count = 3 /* pad */ + params + count;
4819 pSMB->DataCount = cpu_to_le16(count);
4820 pSMB->ParameterCount = cpu_to_le16(params);
4821 pSMB->TotalDataCount = pSMB->DataCount;
4822 pSMB->TotalParameterCount = pSMB->ParameterCount;
4823 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4824 pSMB->DataOffset = cpu_to_le16(offset);
4826 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4827 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4829 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4830 pSMB->Reserved4 = 0;
4831 pSMB->hdr.smb_buf_length += byte_count;
4832 pSMB->ByteCount = cpu_to_le16(byte_count);
4833 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4834 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4835 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4837 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4840 cifs_small_buf_release(pSMB);
4842 /* Note: On -EAGAIN error only caller can retry on handle based calls
4843 since file handle passed in no longer valid */
4850 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4851 const FILE_BASIC_INFO *data,
4852 const struct nls_table *nls_codepage, int remap)
4854 TRANSACTION2_SPI_REQ *pSMB = NULL;
4855 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4858 int bytes_returned = 0;
4860 __u16 params, param_offset, offset, byte_count, count;
4862 cFYI(1, ("In SetTimes"));
4865 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4870 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4872 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4873 PATH_MAX, nls_codepage, remap);
4874 name_len++; /* trailing null */
4876 } else { /* BB improve the check for buffer overruns BB */
4877 name_len = strnlen(fileName, PATH_MAX);
4878 name_len++; /* trailing null */
4879 strncpy(pSMB->FileName, fileName, name_len);
4882 params = 6 + name_len;
4883 count = sizeof (FILE_BASIC_INFO);
4884 pSMB->MaxParameterCount = cpu_to_le16(2);
4885 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4886 pSMB->MaxSetupCount = 0;
4890 pSMB->Reserved2 = 0;
4891 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4892 InformationLevel) - 4;
4893 offset = param_offset + params;
4894 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4895 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4896 pSMB->DataOffset = cpu_to_le16(offset);
4897 pSMB->SetupCount = 1;
4898 pSMB->Reserved3 = 0;
4899 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4900 byte_count = 3 /* pad */ + params + count;
4902 pSMB->DataCount = cpu_to_le16(count);
4903 pSMB->ParameterCount = cpu_to_le16(params);
4904 pSMB->TotalDataCount = pSMB->DataCount;
4905 pSMB->TotalParameterCount = pSMB->ParameterCount;
4906 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4907 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4909 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4910 pSMB->Reserved4 = 0;
4911 pSMB->hdr.smb_buf_length += byte_count;
4912 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4913 pSMB->ByteCount = cpu_to_le16(byte_count);
4914 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4915 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4917 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4920 cifs_buf_release(pSMB);
4928 /* Can not be used to set time stamps yet (due to old DOS time format) */
4929 /* Can be used to set attributes */
4930 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4931 handling it anyway and NT4 was what we thought it would be needed for
4932 Do not delete it until we prove whether needed for Win9x though */
4934 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4935 __u16 dos_attrs, const struct nls_table *nls_codepage)
4937 SETATTR_REQ *pSMB = NULL;
4938 SETATTR_RSP *pSMBr = NULL;
4943 cFYI(1, ("In SetAttrLegacy"));
4946 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4951 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4953 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4954 PATH_MAX, nls_codepage);
4955 name_len++; /* trailing null */
4957 } else { /* BB improve the check for buffer overruns BB */
4958 name_len = strnlen(fileName, PATH_MAX);
4959 name_len++; /* trailing null */
4960 strncpy(pSMB->fileName, fileName, name_len);
4962 pSMB->attr = cpu_to_le16(dos_attrs);
4963 pSMB->BufferFormat = 0x04;
4964 pSMB->hdr.smb_buf_length += name_len + 1;
4965 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4966 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4967 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4969 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4972 cifs_buf_release(pSMB);
4975 goto SetAttrLgcyRetry;
4979 #endif /* temporarily unneeded SetAttr legacy function */
4982 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4983 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4984 dev_t device, const struct nls_table *nls_codepage,
4987 TRANSACTION2_SPI_REQ *pSMB = NULL;
4988 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4991 int bytes_returned = 0;
4992 FILE_UNIX_BASIC_INFO *data_offset;
4993 __u16 params, param_offset, offset, count, byte_count;
4995 cFYI(1, ("In SetUID/GID/Mode"));
4997 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5002 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5004 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5005 PATH_MAX, nls_codepage, remap);
5006 name_len++; /* trailing null */
5008 } else { /* BB improve the check for buffer overruns BB */
5009 name_len = strnlen(fileName, PATH_MAX);
5010 name_len++; /* trailing null */
5011 strncpy(pSMB->FileName, fileName, name_len);
5014 params = 6 + name_len;
5015 count = sizeof (FILE_UNIX_BASIC_INFO);
5016 pSMB->MaxParameterCount = cpu_to_le16(2);
5017 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5018 pSMB->MaxSetupCount = 0;
5022 pSMB->Reserved2 = 0;
5023 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5024 InformationLevel) - 4;
5025 offset = param_offset + params;
5027 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5029 memset(data_offset, 0, count);
5030 pSMB->DataOffset = cpu_to_le16(offset);
5031 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5032 pSMB->SetupCount = 1;
5033 pSMB->Reserved3 = 0;
5034 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5035 byte_count = 3 /* pad */ + params + count;
5036 pSMB->ParameterCount = cpu_to_le16(params);
5037 pSMB->DataCount = cpu_to_le16(count);
5038 pSMB->TotalParameterCount = pSMB->ParameterCount;
5039 pSMB->TotalDataCount = pSMB->DataCount;
5040 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5041 pSMB->Reserved4 = 0;
5042 pSMB->hdr.smb_buf_length += byte_count;
5043 /* Samba server ignores set of file size to zero due to bugs in some
5044 older clients, but we should be precise - we use SetFileSize to
5045 set file size and do not want to truncate file size to zero
5046 accidently as happened on one Samba server beta by putting
5047 zero instead of -1 here */
5048 data_offset->EndOfFile = NO_CHANGE_64;
5049 data_offset->NumOfBytes = NO_CHANGE_64;
5050 data_offset->LastStatusChange = NO_CHANGE_64;
5051 data_offset->LastAccessTime = NO_CHANGE_64;
5052 data_offset->LastModificationTime = NO_CHANGE_64;
5053 data_offset->Uid = cpu_to_le64(uid);
5054 data_offset->Gid = cpu_to_le64(gid);
5055 /* better to leave device as zero when it is */
5056 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5057 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5058 data_offset->Permissions = cpu_to_le64(mode);
5061 data_offset->Type = cpu_to_le32(UNIX_FILE);
5062 else if (S_ISDIR(mode))
5063 data_offset->Type = cpu_to_le32(UNIX_DIR);
5064 else if (S_ISLNK(mode))
5065 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5066 else if (S_ISCHR(mode))
5067 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5068 else if (S_ISBLK(mode))
5069 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5070 else if (S_ISFIFO(mode))
5071 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5072 else if (S_ISSOCK(mode))
5073 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5076 pSMB->ByteCount = cpu_to_le16(byte_count);
5077 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5078 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5080 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5084 cifs_buf_release(pSMB);
5090 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5091 const int notify_subdirs, const __u16 netfid,
5092 __u32 filter, struct file *pfile, int multishot,
5093 const struct nls_table *nls_codepage)
5096 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5097 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5098 struct dir_notify_req *dnotify_req;
5101 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5102 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5107 pSMB->TotalParameterCount = 0 ;
5108 pSMB->TotalDataCount = 0;
5109 pSMB->MaxParameterCount = cpu_to_le32(2);
5110 /* BB find exact data count max from sess structure BB */
5111 pSMB->MaxDataCount = 0; /* same in little endian or be */
5112 /* BB VERIFY verify which is correct for above BB */
5113 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5114 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5116 pSMB->MaxSetupCount = 4;
5118 pSMB->ParameterOffset = 0;
5119 pSMB->DataCount = 0;
5120 pSMB->DataOffset = 0;
5121 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5122 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5123 pSMB->ParameterCount = pSMB->TotalParameterCount;
5125 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5126 pSMB->Reserved2 = 0;
5127 pSMB->CompletionFilter = cpu_to_le32(filter);
5128 pSMB->Fid = netfid; /* file handle always le */
5129 pSMB->ByteCount = 0;
5131 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5132 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5134 cFYI(1, ("Error in Notify = %d", rc));
5136 /* Add file to outstanding requests */
5137 /* BB change to kmem cache alloc */
5138 dnotify_req = kmalloc(
5139 sizeof(struct dir_notify_req),
5142 dnotify_req->Pid = pSMB->hdr.Pid;
5143 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5144 dnotify_req->Mid = pSMB->hdr.Mid;
5145 dnotify_req->Tid = pSMB->hdr.Tid;
5146 dnotify_req->Uid = pSMB->hdr.Uid;
5147 dnotify_req->netfid = netfid;
5148 dnotify_req->pfile = pfile;
5149 dnotify_req->filter = filter;
5150 dnotify_req->multishot = multishot;
5151 spin_lock(&GlobalMid_Lock);
5152 list_add_tail(&dnotify_req->lhead,
5153 &GlobalDnotifyReqList);
5154 spin_unlock(&GlobalMid_Lock);
5158 cifs_buf_release(pSMB);
5161 #ifdef CONFIG_CIFS_XATTR
5163 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5164 const unsigned char *searchName,
5165 char *EAData, size_t buf_size,
5166 const struct nls_table *nls_codepage, int remap)
5168 /* BB assumes one setup word */
5169 TRANSACTION2_QPI_REQ *pSMB = NULL;
5170 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5174 struct fea *temp_fea;
5176 __u16 params, byte_count;
5178 cFYI(1, ("In Query All EAs path %s", searchName));
5180 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5185 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5187 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5188 PATH_MAX, nls_codepage, remap);
5189 name_len++; /* trailing null */
5191 } else { /* BB improve the check for buffer overruns BB */
5192 name_len = strnlen(searchName, PATH_MAX);
5193 name_len++; /* trailing null */
5194 strncpy(pSMB->FileName, searchName, name_len);
5197 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5198 pSMB->TotalDataCount = 0;
5199 pSMB->MaxParameterCount = cpu_to_le16(2);
5200 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5201 pSMB->MaxSetupCount = 0;
5205 pSMB->Reserved2 = 0;
5206 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5207 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5208 pSMB->DataCount = 0;
5209 pSMB->DataOffset = 0;
5210 pSMB->SetupCount = 1;
5211 pSMB->Reserved3 = 0;
5212 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5213 byte_count = params + 1 /* pad */ ;
5214 pSMB->TotalParameterCount = cpu_to_le16(params);
5215 pSMB->ParameterCount = pSMB->TotalParameterCount;
5216 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5217 pSMB->Reserved4 = 0;
5218 pSMB->hdr.smb_buf_length += byte_count;
5219 pSMB->ByteCount = cpu_to_le16(byte_count);
5221 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5222 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5224 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5225 } else { /* decode response */
5226 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5228 /* BB also check enough total bytes returned */
5229 /* BB we need to improve the validity checking
5230 of these trans2 responses */
5231 if (rc || (pSMBr->ByteCount < 4))
5232 rc = -EIO; /* bad smb */
5233 /* else if (pFindData){
5234 memcpy((char *) pFindData,
5235 (char *) &pSMBr->hdr.Protocol +
5238 /* check that length of list is not more than bcc */
5239 /* check that each entry does not go beyond length
5241 /* check that each element of each entry does not
5242 go beyond end of list */
5243 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5244 struct fealist *ea_response_data;
5246 /* validate_trans2_offsets() */
5247 /* BB check if start of smb + data_offset > &bcc+ bcc */
5248 ea_response_data = (struct fealist *)
5249 (((char *) &pSMBr->hdr.Protocol) +
5251 name_len = le32_to_cpu(ea_response_data->list_len);
5252 cFYI(1, ("ea length %d", name_len));
5253 if (name_len <= 8) {
5254 /* returned EA size zeroed at top of function */
5255 cFYI(1, ("empty EA list returned from server"));
5257 /* account for ea list len */
5259 temp_fea = ea_response_data->list;
5260 temp_ptr = (char *)temp_fea;
5261 while (name_len > 0) {
5265 rc += temp_fea->name_len;
5266 /* account for prefix user. and trailing null */
5268 if (rc < (int)buf_size) {
5269 memcpy(EAData, "user.", 5);
5271 memcpy(EAData, temp_ptr,
5272 temp_fea->name_len);
5273 EAData += temp_fea->name_len;
5274 /* null terminate name */
5276 EAData = EAData + 1;
5277 } else if (buf_size == 0) {
5278 /* skip copy - calc size only */
5280 /* stop before overrun buffer */
5284 name_len -= temp_fea->name_len;
5285 temp_ptr += temp_fea->name_len;
5286 /* account for trailing null */
5290 le16_to_cpu(temp_fea->value_len);
5291 name_len -= value_len;
5292 temp_ptr += value_len;
5293 /* BB check that temp_ptr is still
5296 /* no trailing null to account for
5298 /* go on to next EA */
5299 temp_fea = (struct fea *)temp_ptr;
5305 cifs_buf_release(pSMB);
5312 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5313 const unsigned char *searchName, const unsigned char *ea_name,
5314 unsigned char *ea_value, size_t buf_size,
5315 const struct nls_table *nls_codepage, int remap)
5317 TRANSACTION2_QPI_REQ *pSMB = NULL;
5318 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5322 struct fea *temp_fea;
5324 __u16 params, byte_count;
5326 cFYI(1, ("In Query EA path %s", searchName));
5328 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5333 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5335 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5336 PATH_MAX, nls_codepage, remap);
5337 name_len++; /* trailing null */
5339 } else { /* BB improve the check for buffer overruns BB */
5340 name_len = strnlen(searchName, PATH_MAX);
5341 name_len++; /* trailing null */
5342 strncpy(pSMB->FileName, searchName, name_len);
5345 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5346 pSMB->TotalDataCount = 0;
5347 pSMB->MaxParameterCount = cpu_to_le16(2);
5348 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5349 pSMB->MaxSetupCount = 0;
5353 pSMB->Reserved2 = 0;
5354 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5355 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5356 pSMB->DataCount = 0;
5357 pSMB->DataOffset = 0;
5358 pSMB->SetupCount = 1;
5359 pSMB->Reserved3 = 0;
5360 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5361 byte_count = params + 1 /* pad */ ;
5362 pSMB->TotalParameterCount = cpu_to_le16(params);
5363 pSMB->ParameterCount = pSMB->TotalParameterCount;
5364 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5365 pSMB->Reserved4 = 0;
5366 pSMB->hdr.smb_buf_length += byte_count;
5367 pSMB->ByteCount = cpu_to_le16(byte_count);
5369 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5370 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5372 cFYI(1, ("Send error in Query EA = %d", rc));
5373 } else { /* decode response */
5374 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5376 /* BB also check enough total bytes returned */
5377 /* BB we need to improve the validity checking
5378 of these trans2 responses */
5379 if (rc || (pSMBr->ByteCount < 4))
5380 rc = -EIO; /* bad smb */
5381 /* else if (pFindData){
5382 memcpy((char *) pFindData,
5383 (char *) &pSMBr->hdr.Protocol +
5386 /* check that length of list is not more than bcc */
5387 /* check that each entry does not go beyond length
5389 /* check that each element of each entry does not
5390 go beyond end of list */
5391 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5392 struct fealist *ea_response_data;
5394 /* validate_trans2_offsets() */
5395 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5396 ea_response_data = (struct fealist *)
5397 (((char *) &pSMBr->hdr.Protocol) +
5399 name_len = le32_to_cpu(ea_response_data->list_len);
5400 cFYI(1, ("ea length %d", name_len));
5401 if (name_len <= 8) {
5402 /* returned EA size zeroed at top of function */
5403 cFYI(1, ("empty EA list returned from server"));
5405 /* account for ea list len */
5407 temp_fea = ea_response_data->list;
5408 temp_ptr = (char *)temp_fea;
5409 /* loop through checking if we have a matching
5410 name and then return the associated value */
5411 while (name_len > 0) {
5416 le16_to_cpu(temp_fea->value_len);
5417 /* BB validate that value_len falls within SMB,
5418 even though maximum for name_len is 255 */
5419 if (memcmp(temp_fea->name, ea_name,
5420 temp_fea->name_len) == 0) {
5423 /* account for prefix user. and trailing null */
5424 if (rc <= (int)buf_size) {
5426 temp_fea->name+temp_fea->name_len+1,
5428 /* ea values, unlike ea
5431 } else if (buf_size == 0) {
5432 /* skip copy - calc size only */
5434 /* stop before overrun buffer */
5439 name_len -= temp_fea->name_len;
5440 temp_ptr += temp_fea->name_len;
5441 /* account for trailing null */
5444 name_len -= value_len;
5445 temp_ptr += value_len;
5446 /* No trailing null to account for in
5447 value_len. Go on to next EA */
5448 temp_fea = (struct fea *)temp_ptr;
5454 cifs_buf_release(pSMB);
5462 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5463 const char *ea_name, const void *ea_value,
5464 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5467 struct smb_com_transaction2_spi_req *pSMB = NULL;
5468 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5469 struct fealist *parm_data;
5472 int bytes_returned = 0;
5473 __u16 params, param_offset, byte_count, offset, count;
5475 cFYI(1, ("In SetEA"));
5477 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5482 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5484 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5485 PATH_MAX, nls_codepage, remap);
5486 name_len++; /* trailing null */
5488 } else { /* BB improve the check for buffer overruns BB */
5489 name_len = strnlen(fileName, PATH_MAX);
5490 name_len++; /* trailing null */
5491 strncpy(pSMB->FileName, fileName, name_len);
5494 params = 6 + name_len;
5496 /* done calculating parms using name_len of file name,
5497 now use name_len to calculate length of ea name
5498 we are going to create in the inode xattrs */
5499 if (ea_name == NULL)
5502 name_len = strnlen(ea_name, 255);
5504 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5505 pSMB->MaxParameterCount = cpu_to_le16(2);
5506 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5507 pSMB->MaxSetupCount = 0;
5511 pSMB->Reserved2 = 0;
5512 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5513 InformationLevel) - 4;
5514 offset = param_offset + params;
5515 pSMB->InformationLevel =
5516 cpu_to_le16(SMB_SET_FILE_EA);
5519 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5521 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5522 pSMB->DataOffset = cpu_to_le16(offset);
5523 pSMB->SetupCount = 1;
5524 pSMB->Reserved3 = 0;
5525 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5526 byte_count = 3 /* pad */ + params + count;
5527 pSMB->DataCount = cpu_to_le16(count);
5528 parm_data->list_len = cpu_to_le32(count);
5529 parm_data->list[0].EA_flags = 0;
5530 /* we checked above that name len is less than 255 */
5531 parm_data->list[0].name_len = (__u8)name_len;
5532 /* EA names are always ASCII */
5534 strncpy(parm_data->list[0].name, ea_name, name_len);
5535 parm_data->list[0].name[name_len] = 0;
5536 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5537 /* caller ensures that ea_value_len is less than 64K but
5538 we need to ensure that it fits within the smb */
5540 /*BB add length check to see if it would fit in
5541 negotiated SMB buffer size BB */
5542 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5544 memcpy(parm_data->list[0].name+name_len+1,
5545 ea_value, ea_value_len);
5547 pSMB->TotalDataCount = pSMB->DataCount;
5548 pSMB->ParameterCount = cpu_to_le16(params);
5549 pSMB->TotalParameterCount = pSMB->ParameterCount;
5550 pSMB->Reserved4 = 0;
5551 pSMB->hdr.smb_buf_length += byte_count;
5552 pSMB->ByteCount = cpu_to_le16(byte_count);
5553 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5554 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5556 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5559 cifs_buf_release(pSMB);