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;
100 write_unlock(&GlobalSMBSeslock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* If the return code is zero, this function must fill in request_buf pointer */
107 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
108 void **request_buf /* returned */)
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
113 check for tcp and smb session status done differently
114 for those three - in the calling routine */
116 if (tcon->tidStatus == CifsExiting) {
117 /* only tree disconnect, open, and write,
118 (and ulogoff which does not have tcon)
119 are allowed as we start force umount */
120 if ((smb_command != SMB_COM_WRITE_ANDX) &&
121 (smb_command != SMB_COM_OPEN_ANDX) &&
122 (smb_command != SMB_COM_TREE_DISCONNECT)) {
123 cFYI(1, ("can not send cmd %d while umounting",
128 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
129 (tcon->ses->server)) {
130 struct nls_table *nls_codepage;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while (tcon->ses->server->tcpStatus ==
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus ==
139 if (tcon->ses->server->tcpStatus ==
141 /* on "soft" mounts we wait once */
142 if ((tcon->retry == FALSE) ||
143 (tcon->ses->status == CifsExiting)) {
144 cFYI(1, ("gave up waiting on "
145 "reconnect in smb_init"));
147 } /* else "hard" mount - keep retrying
148 until process is killed or server
149 comes back on-line */
150 } else /* TCP session is reestablished now */
154 nls_codepage = load_nls_default();
155 /* need to prevent multiple threads trying to
156 simultaneously reconnect the same SMB session */
157 down(&tcon->ses->sesSem);
158 if (tcon->ses->status == CifsNeedReconnect)
159 rc = cifs_setup_session(0, tcon->ses,
161 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
162 mark_open_files_invalid(tcon);
163 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
165 up(&tcon->ses->sesSem);
166 /* tell server which Unix caps we support */
167 if (tcon->ses->capabilities & CAP_UNIX)
168 reset_cifs_unix_caps(0 /* no xid */,
170 NULL /* we do not know sb */,
171 NULL /* no vol info */);
172 /* BB FIXME add code to check if wsize needs
173 update due to negotiated smb buffer size
176 atomic_inc(&tconInfoReconnectCount);
178 cFYI(1, ("reconnect tcon rc = %d", rc));
179 /* Removed call to reopen open files here.
180 It is safer (and faster) to reopen files
181 one at a time as needed in read and write */
183 /* Check if handle based operation so we
184 know whether we can continue or not without
185 returning to caller to reset file handle */
186 switch (smb_command) {
187 case SMB_COM_READ_ANDX:
188 case SMB_COM_WRITE_ANDX:
190 case SMB_COM_FIND_CLOSE2:
191 case SMB_COM_LOCKING_ANDX: {
192 unload_nls(nls_codepage);
197 up(&tcon->ses->sesSem);
199 unload_nls(nls_codepage);
208 *request_buf = cifs_small_buf_get();
209 if (*request_buf == NULL) {
210 /* BB should we add a retry in here if not a writepage? */
214 header_assemble((struct smb_hdr *) *request_buf, smb_command,
218 cifs_stats_inc(&tcon->num_smbs_sent);
224 small_smb_init_no_tc(const int smb_command, const int wct,
225 struct cifsSesInfo *ses, void **request_buf)
228 struct smb_hdr *buffer;
230 rc = small_smb_init(smb_command, wct, NULL, request_buf);
234 buffer = (struct smb_hdr *)*request_buf;
235 buffer->Mid = GetNextMid(ses->server);
236 if (ses->capabilities & CAP_UNICODE)
237 buffer->Flags2 |= SMBFLG2_UNICODE;
238 if (ses->capabilities & CAP_STATUS32)
239 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
241 /* uid, tid can stay at zero as set in header assemble */
243 /* BB add support for turning on the signing when
244 this function is used after 1st of session setup requests */
249 /* If the return code is zero, this function must fill in request_buf pointer */
251 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
252 void **request_buf /* returned */ ,
253 void **response_buf /* returned */ )
257 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
258 check for tcp and smb session status done differently
259 for those three - in the calling routine */
261 if (tcon->tidStatus == CifsExiting) {
262 /* only tree disconnect, open, and write,
263 (and ulogoff which does not have tcon)
264 are allowed as we start force umount */
265 if ((smb_command != SMB_COM_WRITE_ANDX) &&
266 (smb_command != SMB_COM_OPEN_ANDX) &&
267 (smb_command != SMB_COM_TREE_DISCONNECT)) {
268 cFYI(1, ("can not send cmd %d while umounting",
274 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
275 (tcon->ses->server)) {
276 struct nls_table *nls_codepage;
277 /* Give Demultiplex thread up to 10 seconds to
278 reconnect, should be greater than cifs socket
279 timeout which is 7 seconds */
280 while (tcon->ses->server->tcpStatus ==
282 wait_event_interruptible_timeout(tcon->ses->server->response_q,
283 (tcon->ses->server->tcpStatus ==
285 if (tcon->ses->server->tcpStatus ==
287 /* on "soft" mounts we wait once */
288 if ((tcon->retry == FALSE) ||
289 (tcon->ses->status == CifsExiting)) {
290 cFYI(1, ("gave up waiting on "
291 "reconnect in smb_init"));
293 } /* else "hard" mount - keep retrying
294 until process is killed or server
296 } else /* TCP session is reestablished now */
299 nls_codepage = load_nls_default();
300 /* need to prevent multiple threads trying to
301 simultaneously reconnect the same SMB session */
302 down(&tcon->ses->sesSem);
303 if (tcon->ses->status == CifsNeedReconnect)
304 rc = cifs_setup_session(0, tcon->ses,
306 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
307 mark_open_files_invalid(tcon);
308 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
310 up(&tcon->ses->sesSem);
311 /* tell server which Unix caps we support */
312 if (tcon->ses->capabilities & CAP_UNIX)
313 reset_cifs_unix_caps(0 /* no xid */,
315 NULL /* do not know sb */,
316 NULL /* no vol info */);
317 /* BB FIXME add code to check if wsize needs
318 update due to negotiated smb buffer size
321 atomic_inc(&tconInfoReconnectCount);
323 cFYI(1, ("reconnect tcon rc = %d", rc));
324 /* Removed call to reopen open files here.
325 It is safer (and faster) to reopen files
326 one at a time as needed in read and write */
328 /* Check if handle based operation so we
329 know whether we can continue or not without
330 returning to caller to reset file handle */
331 switch (smb_command) {
332 case SMB_COM_READ_ANDX:
333 case SMB_COM_WRITE_ANDX:
335 case SMB_COM_FIND_CLOSE2:
336 case SMB_COM_LOCKING_ANDX: {
337 unload_nls(nls_codepage);
342 up(&tcon->ses->sesSem);
344 unload_nls(nls_codepage);
353 *request_buf = cifs_buf_get();
354 if (*request_buf == NULL) {
355 /* BB should we add a retry in here if not a writepage? */
358 /* Although the original thought was we needed the response buf for */
359 /* potential retries of smb operations it turns out we can determine */
360 /* from the mid flags when the request buffer can be resent without */
361 /* having to use a second distinct buffer for the response */
363 *response_buf = *request_buf;
365 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
369 cifs_stats_inc(&tcon->num_smbs_sent);
374 static int validate_t2(struct smb_t2_rsp *pSMB)
380 /* check for plausible wct, bcc and t2 data and parm sizes */
381 /* check for parm and data offset going beyond end of smb */
382 if (pSMB->hdr.WordCount >= 10) {
383 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
384 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
385 /* check that bcc is at least as big as parms + data */
386 /* check that bcc is less than negotiated smb buffer */
387 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
388 if (total_size < 512) {
390 le16_to_cpu(pSMB->t2_rsp.DataCount);
391 /* BCC le converted in SendReceive */
392 pBCC = (pSMB->hdr.WordCount * 2) +
393 sizeof(struct smb_hdr) +
395 if ((total_size <= (*(u16 *)pBCC)) &&
397 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
403 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
404 sizeof(struct smb_t2_rsp) + 16);
408 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
411 NEGOTIATE_RSP *pSMBr;
415 struct TCP_Server_Info *server;
417 unsigned int secFlags;
421 server = ses->server;
426 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
427 (void **) &pSMB, (void **) &pSMBr);
431 /* if any of auth flags (ie not sign or seal) are overriden use them */
432 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
433 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
434 else /* if override flags set only sign/seal OR them with global auth */
435 secFlags = extended_security | ses->overrideSecFlg;
437 cFYI(1, ("secFlags 0x%x", secFlags));
439 pSMB->hdr.Mid = GetNextMid(server);
440 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
441 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
442 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
445 for (i = 0; i < CIFS_NUM_PROT; i++) {
446 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
447 count += strlen(protocols[i].name) + 1;
448 /* null at end of source and target buffers anyway */
450 pSMB->hdr.smb_buf_length += count;
451 pSMB->ByteCount = cpu_to_le16(count);
453 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
454 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
458 dialect = le16_to_cpu(pSMBr->DialectIndex);
459 cFYI(1, ("Dialect: %d", dialect));
460 /* Check wct = 1 error case */
461 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
462 /* core returns wct = 1, but we do not ask for core - otherwise
463 small wct just comes when dialect index is -1 indicating we
464 could not negotiate a common dialect */
467 #ifdef CONFIG_CIFS_WEAK_PW_HASH
468 } else if ((pSMBr->hdr.WordCount == 13)
469 && ((dialect == LANMAN_PROT)
470 || (dialect == LANMAN2_PROT))) {
472 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
474 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
475 (secFlags & CIFSSEC_MAY_PLNTXT))
476 server->secType = LANMAN;
478 cERROR(1, ("mount failed weak security disabled"
479 " in /proc/fs/cifs/SecurityFlags"));
483 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
484 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
485 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
486 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
487 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
488 /* even though we do not use raw we might as well set this
489 accurately, in case we ever find a need for it */
490 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
491 server->maxRw = 0xFF00;
492 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
494 server->maxRw = 0;/* we do not need to use raw anyway */
495 server->capabilities = CAP_MPX_MODE;
497 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
499 /* OS/2 often does not set timezone therefore
500 * we must use server time to calc time zone.
501 * Could deviate slightly from the right zone.
502 * Smallest defined timezone difference is 15 minutes
503 * (i.e. Nepal). Rounding up/down is done to match
506 int val, seconds, remain, result;
507 struct timespec ts, utc;
509 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
510 le16_to_cpu(rsp->SrvTime.Time));
511 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
512 (int)ts.tv_sec, (int)utc.tv_sec,
513 (int)(utc.tv_sec - ts.tv_sec)));
514 val = (int)(utc.tv_sec - ts.tv_sec);
516 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
517 remain = seconds % MIN_TZ_ADJ;
518 if (remain >= (MIN_TZ_ADJ / 2))
519 result += MIN_TZ_ADJ;
522 server->timeAdj = result;
524 server->timeAdj = (int)tmp;
525 server->timeAdj *= 60; /* also in seconds */
527 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
530 /* BB get server time for time conversions and add
531 code to use it and timezone since this is not UTC */
533 if (rsp->EncryptionKeyLength ==
534 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
535 memcpy(server->cryptKey, rsp->EncryptionKey,
536 CIFS_CRYPTO_KEY_SIZE);
537 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
538 rc = -EIO; /* need cryptkey unless plain text */
542 cFYI(1, ("LANMAN negotiated"));
543 /* we will not end up setting signing flags - as no signing
544 was in LANMAN and server did not return the flags on */
546 #else /* weak security disabled */
547 } else if (pSMBr->hdr.WordCount == 13) {
548 cERROR(1, ("mount failed, cifs module not built "
549 "with CIFS_WEAK_PW_HASH support"));
551 #endif /* WEAK_PW_HASH */
553 } else if (pSMBr->hdr.WordCount != 17) {
558 /* else wct == 17 NTLM */
559 server->secMode = pSMBr->SecurityMode;
560 if ((server->secMode & SECMODE_USER) == 0)
561 cFYI(1, ("share mode security"));
563 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
564 #ifdef CONFIG_CIFS_WEAK_PW_HASH
565 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
566 #endif /* CIFS_WEAK_PW_HASH */
567 cERROR(1, ("Server requests plain text password"
568 " but client support disabled"));
570 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
571 server->secType = NTLMv2;
572 else if (secFlags & CIFSSEC_MAY_NTLM)
573 server->secType = NTLM;
574 else if (secFlags & CIFSSEC_MAY_NTLMV2)
575 server->secType = NTLMv2;
576 /* else krb5 ... any others ... */
578 /* one byte, so no need to convert this or EncryptionKeyLen from
580 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
581 /* probably no need to store and check maxvcs */
582 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
583 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
584 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
585 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
586 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
587 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
588 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
589 server->timeAdj *= 60;
590 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
591 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
592 CIFS_CRYPTO_KEY_SIZE);
593 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
594 && (pSMBr->EncryptionKeyLength == 0)) {
595 /* decode security blob */
596 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
597 rc = -EIO; /* no crypt key only if plain text pwd */
601 /* BB might be helpful to save off the domain of server here */
603 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
604 (server->capabilities & CAP_EXTENDED_SECURITY)) {
605 count = pSMBr->ByteCount;
608 else if (count == 16) {
609 server->secType = RawNTLMSSP;
610 if (server->socketUseCount.counter > 1) {
611 if (memcmp(server->server_GUID,
612 pSMBr->u.extended_response.
614 cFYI(1, ("server UID changed"));
615 memcpy(server->server_GUID,
616 pSMBr->u.extended_response.GUID,
620 memcpy(server->server_GUID,
621 pSMBr->u.extended_response.GUID, 16);
623 rc = decode_negTokenInit(pSMBr->u.extended_response.
628 /* BB Need to fill struct for sessetup here */
635 server->capabilities &= ~CAP_EXTENDED_SECURITY;
637 #ifdef CONFIG_CIFS_WEAK_PW_HASH
640 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
641 /* MUST_SIGN already includes the MAY_SIGN FLAG
642 so if this is zero it means that signing is disabled */
643 cFYI(1, ("Signing disabled"));
644 if (server->secMode & SECMODE_SIGN_REQUIRED)
645 cERROR(1, ("Server requires "
646 "/proc/fs/cifs/PacketSigningEnabled "
649 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
650 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
651 /* signing required */
652 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
653 if ((server->secMode &
654 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
656 ("signing required but server lacks support"));
659 server->secMode |= SECMODE_SIGN_REQUIRED;
661 /* signing optional ie CIFSSEC_MAY_SIGN */
662 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
664 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
668 cifs_buf_release(pSMB);
670 cFYI(1, ("negprot rc %d", rc));
675 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
677 struct smb_hdr *smb_buffer;
678 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
682 cFYI(1, ("In tree disconnect"));
684 * If last user of the connection and
685 * connection alive - disconnect it
686 * If this is the last connection on the server session disconnect it
687 * (and inside session disconnect we should check if tcp socket needs
688 * to be freed and kernel thread woken up).
691 down(&tcon->tconSem);
695 atomic_dec(&tcon->useCount);
696 if (atomic_read(&tcon->useCount) > 0) {
701 /* No need to return error on this operation if tid invalidated and
702 closed on server already e.g. due to tcp session crashing */
703 if (tcon->tidStatus == CifsNeedReconnect) {
708 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
712 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
713 (void **)&smb_buffer);
718 smb_buffer_response = smb_buffer; /* BB removeme BB */
720 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
723 cFYI(1, ("Tree disconnect failed %d", rc));
726 cifs_small_buf_release(smb_buffer);
729 /* No need to return error on this operation if tid invalidated and
730 closed on server already e.g. due to tcp session crashing */
738 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
740 struct smb_hdr *smb_buffer_response;
741 LOGOFF_ANDX_REQ *pSMB;
745 cFYI(1, ("In SMBLogoff for session disconnect"));
751 atomic_dec(&ses->inUse);
752 if (atomic_read(&ses->inUse) > 0) {
756 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
762 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
765 pSMB->hdr.Mid = GetNextMid(ses->server);
767 if (ses->server->secMode &
768 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
769 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
772 pSMB->hdr.Uid = ses->Suid;
774 pSMB->AndXCommand = 0xFF;
775 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
776 smb_buffer_response, &length, 0);
778 atomic_dec(&ses->server->socketUseCount);
779 if (atomic_read(&ses->server->socketUseCount) == 0) {
780 spin_lock(&GlobalMid_Lock);
781 ses->server->tcpStatus = CifsExiting;
782 spin_unlock(&GlobalMid_Lock);
787 cifs_small_buf_release(pSMB);
789 /* if session dead then we do not need to do ulogoff,
790 since server closed smb session, no sense reporting
798 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
799 __u16 type, const struct nls_table *nls_codepage, int remap)
801 TRANSACTION2_SPI_REQ *pSMB = NULL;
802 TRANSACTION2_SPI_RSP *pSMBr = NULL;
803 struct unlink_psx_rq *pRqD;
806 int bytes_returned = 0;
807 __u16 params, param_offset, offset, byte_count;
809 cFYI(1, ("In POSIX delete"));
811 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
816 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
818 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
819 PATH_MAX, nls_codepage, remap);
820 name_len++; /* trailing null */
822 } else { /* BB add path length overrun check */
823 name_len = strnlen(fileName, PATH_MAX);
824 name_len++; /* trailing null */
825 strncpy(pSMB->FileName, fileName, name_len);
828 params = 6 + name_len;
829 pSMB->MaxParameterCount = cpu_to_le16(2);
830 pSMB->MaxDataCount = 0; /* BB double check this with jra */
831 pSMB->MaxSetupCount = 0;
836 param_offset = offsetof(struct smb_com_transaction2_spi_req,
837 InformationLevel) - 4;
838 offset = param_offset + params;
840 /* Setup pointer to Request Data (inode type) */
841 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
842 pRqD->type = cpu_to_le16(type);
843 pSMB->ParameterOffset = cpu_to_le16(param_offset);
844 pSMB->DataOffset = cpu_to_le16(offset);
845 pSMB->SetupCount = 1;
847 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
848 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
850 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
851 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
852 pSMB->ParameterCount = cpu_to_le16(params);
853 pSMB->TotalParameterCount = pSMB->ParameterCount;
854 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
856 pSMB->hdr.smb_buf_length += byte_count;
857 pSMB->ByteCount = cpu_to_le16(byte_count);
858 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
859 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
861 cFYI(1, ("Posix delete returned %d", rc));
863 cifs_buf_release(pSMB);
865 cifs_stats_inc(&tcon->num_deletes);
874 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
875 const struct nls_table *nls_codepage, int remap)
877 DELETE_FILE_REQ *pSMB = NULL;
878 DELETE_FILE_RSP *pSMBr = NULL;
884 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
889 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
891 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
892 PATH_MAX, nls_codepage, remap);
893 name_len++; /* trailing null */
895 } else { /* BB improve check for buffer overruns BB */
896 name_len = strnlen(fileName, PATH_MAX);
897 name_len++; /* trailing null */
898 strncpy(pSMB->fileName, fileName, name_len);
900 pSMB->SearchAttributes =
901 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
902 pSMB->BufferFormat = 0x04;
903 pSMB->hdr.smb_buf_length += name_len + 1;
904 pSMB->ByteCount = cpu_to_le16(name_len + 1);
905 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
906 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
907 cifs_stats_inc(&tcon->num_deletes);
909 cFYI(1, ("Error in RMFile = %d", rc));
912 cifs_buf_release(pSMB);
920 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
921 const struct nls_table *nls_codepage, int remap)
923 DELETE_DIRECTORY_REQ *pSMB = NULL;
924 DELETE_DIRECTORY_RSP *pSMBr = NULL;
929 cFYI(1, ("In CIFSSMBRmDir"));
931 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
937 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
938 PATH_MAX, nls_codepage, remap);
939 name_len++; /* trailing null */
941 } else { /* BB improve check for buffer overruns BB */
942 name_len = strnlen(dirName, PATH_MAX);
943 name_len++; /* trailing null */
944 strncpy(pSMB->DirName, dirName, name_len);
947 pSMB->BufferFormat = 0x04;
948 pSMB->hdr.smb_buf_length += name_len + 1;
949 pSMB->ByteCount = cpu_to_le16(name_len + 1);
950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
952 cifs_stats_inc(&tcon->num_rmdirs);
954 cFYI(1, ("Error in RMDir = %d", rc));
957 cifs_buf_release(pSMB);
964 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
965 const char *name, const struct nls_table *nls_codepage, int remap)
968 CREATE_DIRECTORY_REQ *pSMB = NULL;
969 CREATE_DIRECTORY_RSP *pSMBr = NULL;
973 cFYI(1, ("In CIFSSMBMkDir"));
975 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
980 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
981 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
982 PATH_MAX, nls_codepage, remap);
983 name_len++; /* trailing null */
985 } else { /* BB improve check for buffer overruns BB */
986 name_len = strnlen(name, PATH_MAX);
987 name_len++; /* trailing null */
988 strncpy(pSMB->DirName, name, name_len);
991 pSMB->BufferFormat = 0x04;
992 pSMB->hdr.smb_buf_length += name_len + 1;
993 pSMB->ByteCount = cpu_to_le16(name_len + 1);
994 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
995 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
996 cifs_stats_inc(&tcon->num_mkdirs);
998 cFYI(1, ("Error in Mkdir = %d", rc));
1001 cifs_buf_release(pSMB);
1008 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1009 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1010 __u32 *pOplock, const char *name,
1011 const struct nls_table *nls_codepage, int remap)
1013 TRANSACTION2_SPI_REQ *pSMB = NULL;
1014 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1017 int bytes_returned = 0;
1018 __u16 params, param_offset, offset, byte_count, count;
1019 OPEN_PSX_REQ * pdata;
1020 OPEN_PSX_RSP * psx_rsp;
1022 cFYI(1, ("In POSIX Create"));
1024 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1029 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1031 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1032 PATH_MAX, nls_codepage, remap);
1033 name_len++; /* trailing null */
1035 } else { /* BB improve the check for buffer overruns BB */
1036 name_len = strnlen(name, PATH_MAX);
1037 name_len++; /* trailing null */
1038 strncpy(pSMB->FileName, name, name_len);
1041 params = 6 + name_len;
1042 count = sizeof(OPEN_PSX_REQ);
1043 pSMB->MaxParameterCount = cpu_to_le16(2);
1044 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1045 pSMB->MaxSetupCount = 0;
1049 pSMB->Reserved2 = 0;
1050 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1051 InformationLevel) - 4;
1052 offset = param_offset + params;
1053 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1054 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
1055 pdata->Permissions = cpu_to_le64(mode);
1056 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1057 pdata->OpenFlags = cpu_to_le32(*pOplock);
1058 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1059 pSMB->DataOffset = cpu_to_le16(offset);
1060 pSMB->SetupCount = 1;
1061 pSMB->Reserved3 = 0;
1062 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1063 byte_count = 3 /* pad */ + params + count;
1065 pSMB->DataCount = cpu_to_le16(count);
1066 pSMB->ParameterCount = cpu_to_le16(params);
1067 pSMB->TotalDataCount = pSMB->DataCount;
1068 pSMB->TotalParameterCount = pSMB->ParameterCount;
1069 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1070 pSMB->Reserved4 = 0;
1071 pSMB->hdr.smb_buf_length += byte_count;
1072 pSMB->ByteCount = cpu_to_le16(byte_count);
1073 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1074 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1076 cFYI(1, ("Posix create returned %d", rc));
1077 goto psx_create_err;
1080 cFYI(1, ("copying inode info"));
1081 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1083 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1084 rc = -EIO; /* bad smb */
1085 goto psx_create_err;
1088 /* copy return information to pRetData */
1089 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1090 + le16_to_cpu(pSMBr->t2.DataOffset));
1092 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1094 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1095 /* Let caller know file was created so we can set the mode. */
1096 /* Do we care about the CreateAction in any other cases? */
1097 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1098 *pOplock |= CIFS_CREATE_ACTION;
1099 /* check to make sure response data is there */
1100 if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
1101 pRetData->Type = -1; /* unknown */
1102 #ifdef CONFIG_CIFS_DEBUG2
1103 cFYI(1, ("unknown type"));
1106 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1107 + sizeof(FILE_UNIX_BASIC_INFO)) {
1108 cERROR(1, ("Open response data too small"));
1109 pRetData->Type = -1;
1110 goto psx_create_err;
1112 memcpy((char *) pRetData,
1113 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1114 sizeof(FILE_UNIX_BASIC_INFO));
1118 cifs_buf_release(pSMB);
1120 cifs_stats_inc(&tcon->num_mkdirs);
1128 static __u16 convert_disposition(int disposition)
1132 switch (disposition) {
1133 case FILE_SUPERSEDE:
1134 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1137 ofun = SMBOPEN_OAPPEND;
1140 ofun = SMBOPEN_OCREATE;
1143 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1145 case FILE_OVERWRITE:
1146 ofun = SMBOPEN_OTRUNC;
1148 case FILE_OVERWRITE_IF:
1149 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1152 cFYI(1, ("unknown disposition %d", disposition));
1153 ofun = SMBOPEN_OAPPEND; /* regular open */
1159 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1160 const char *fileName, const int openDisposition,
1161 const int access_flags, const int create_options, __u16 * netfid,
1162 int *pOplock, FILE_ALL_INFO * pfile_info,
1163 const struct nls_table *nls_codepage, int remap)
1166 OPENX_REQ *pSMB = NULL;
1167 OPENX_RSP *pSMBr = NULL;
1173 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1178 pSMB->AndXCommand = 0xFF; /* none */
1180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1181 count = 1; /* account for one byte pad to word boundary */
1183 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1184 fileName, PATH_MAX, nls_codepage, remap);
1185 name_len++; /* trailing null */
1187 } else { /* BB improve check for buffer overruns BB */
1188 count = 0; /* no pad */
1189 name_len = strnlen(fileName, PATH_MAX);
1190 name_len++; /* trailing null */
1191 strncpy(pSMB->fileName, fileName, name_len);
1193 if (*pOplock & REQ_OPLOCK)
1194 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1195 else if (*pOplock & REQ_BATCHOPLOCK)
1196 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1198 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1199 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1205 pSMB->Mode = cpu_to_le16(2);
1206 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1207 /* set file as system file if special file such
1208 as fifo and server expecting SFU style and
1209 no Unix extensions */
1211 if (create_options & CREATE_OPTION_SPECIAL)
1212 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1214 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1216 /* if ((omode & S_IWUGO) == 0)
1217 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1218 /* Above line causes problems due to vfs splitting create into two
1219 pieces - need to set mode after file created not while it is
1223 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1224 CREATE_OPTIONS_MASK); */
1225 /* BB FIXME END BB */
1227 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1228 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1230 pSMB->hdr.smb_buf_length += count;
1232 pSMB->ByteCount = cpu_to_le16(count);
1233 /* long_op set to 1 to allow for oplock break timeouts */
1234 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1235 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1236 cifs_stats_inc(&tcon->num_opens);
1238 cFYI(1, ("Error in Open = %d", rc));
1240 /* BB verify if wct == 15 */
1242 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1244 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1245 /* Let caller know file was created so we can set the mode. */
1246 /* Do we care about the CreateAction in any other cases? */
1248 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1249 *pOplock |= CIFS_CREATE_ACTION; */
1253 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1254 pfile_info->LastAccessTime = 0; /* BB fixme */
1255 pfile_info->LastWriteTime = 0; /* BB fixme */
1256 pfile_info->ChangeTime = 0; /* BB fixme */
1257 pfile_info->Attributes =
1258 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1259 /* the file_info buf is endian converted by caller */
1260 pfile_info->AllocationSize =
1261 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1262 pfile_info->EndOfFile = pfile_info->AllocationSize;
1263 pfile_info->NumberOfLinks = cpu_to_le32(1);
1267 cifs_buf_release(pSMB);
1274 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1275 const char *fileName, const int openDisposition,
1276 const int access_flags, const int create_options, __u16 * netfid,
1277 int *pOplock, FILE_ALL_INFO * pfile_info,
1278 const struct nls_table *nls_codepage, int remap)
1281 OPEN_REQ *pSMB = NULL;
1282 OPEN_RSP *pSMBr = NULL;
1288 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1293 pSMB->AndXCommand = 0xFF; /* none */
1295 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1296 count = 1; /* account for one byte pad to word boundary */
1298 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1299 fileName, PATH_MAX, nls_codepage, remap);
1300 name_len++; /* trailing null */
1302 pSMB->NameLength = cpu_to_le16(name_len);
1303 } else { /* BB improve check for buffer overruns BB */
1304 count = 0; /* no pad */
1305 name_len = strnlen(fileName, PATH_MAX);
1306 name_len++; /* trailing null */
1307 pSMB->NameLength = cpu_to_le16(name_len);
1308 strncpy(pSMB->fileName, fileName, name_len);
1310 if (*pOplock & REQ_OPLOCK)
1311 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1312 else if (*pOplock & REQ_BATCHOPLOCK)
1313 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1314 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1315 pSMB->AllocationSize = 0;
1316 /* set file as system file if special file such
1317 as fifo and server expecting SFU style and
1318 no Unix extensions */
1319 if (create_options & CREATE_OPTION_SPECIAL)
1320 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1322 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1323 /* XP does not handle ATTR_POSIX_SEMANTICS */
1324 /* but it helps speed up case sensitive checks for other
1325 servers such as Samba */
1326 if (tcon->ses->capabilities & CAP_UNIX)
1327 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1329 /* if ((omode & S_IWUGO) == 0)
1330 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1331 /* Above line causes problems due to vfs splitting create into two
1332 pieces - need to set mode after file created not while it is
1334 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1335 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1336 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1337 /* BB Expirement with various impersonation levels and verify */
1338 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1339 pSMB->SecurityFlags =
1340 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1343 pSMB->hdr.smb_buf_length += count;
1345 pSMB->ByteCount = cpu_to_le16(count);
1346 /* long_op set to 1 to allow for oplock break timeouts */
1347 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1348 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1349 cifs_stats_inc(&tcon->num_opens);
1351 cFYI(1, ("Error in Open = %d", rc));
1353 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1354 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1355 /* Let caller know file was created so we can set the mode. */
1356 /* Do we care about the CreateAction in any other cases? */
1357 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1358 *pOplock |= CIFS_CREATE_ACTION;
1360 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1361 36 /* CreationTime to Attributes */);
1362 /* the file_info buf is endian converted by caller */
1363 pfile_info->AllocationSize = pSMBr->AllocationSize;
1364 pfile_info->EndOfFile = pSMBr->EndOfFile;
1365 pfile_info->NumberOfLinks = cpu_to_le32(1);
1369 cifs_buf_release(pSMB);
1376 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1377 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1378 char **buf, int *pbuf_type)
1381 READ_REQ *pSMB = NULL;
1382 READ_RSP *pSMBr = NULL;
1383 char *pReadData = NULL;
1385 int resp_buf_type = 0;
1388 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1389 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1392 wct = 10; /* old style read */
1395 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1399 /* tcon and ses pointer are checked in smb_init */
1400 if (tcon->ses->server == NULL)
1401 return -ECONNABORTED;
1403 pSMB->AndXCommand = 0xFF; /* none */
1405 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1407 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1408 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1411 pSMB->Remaining = 0;
1412 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1413 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1415 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1417 /* old style read */
1418 struct smb_com_readx_req *pSMBW =
1419 (struct smb_com_readx_req *)pSMB;
1420 pSMBW->ByteCount = 0;
1423 iov[0].iov_base = (char *)pSMB;
1424 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1425 rc = SendReceive2(xid, tcon->ses, iov,
1428 cifs_stats_inc(&tcon->num_reads);
1429 pSMBr = (READ_RSP *)iov[0].iov_base;
1431 cERROR(1, ("Send error in read = %d", rc));
1433 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1434 data_length = data_length << 16;
1435 data_length += le16_to_cpu(pSMBr->DataLength);
1436 *nbytes = data_length;
1438 /*check that DataLength would not go beyond end of SMB */
1439 if ((data_length > CIFSMaxBufSize)
1440 || (data_length > count)) {
1441 cFYI(1, ("bad length %d for count %d",
1442 data_length, count));
1446 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1447 le16_to_cpu(pSMBr->DataOffset);
1448 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1449 cERROR(1,("Faulting on read rc = %d",rc));
1451 }*/ /* can not use copy_to_user when using page cache*/
1453 memcpy(*buf, pReadData, data_length);
1457 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1459 if (resp_buf_type == CIFS_SMALL_BUFFER)
1460 cifs_small_buf_release(iov[0].iov_base);
1461 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1462 cifs_buf_release(iov[0].iov_base);
1463 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1464 /* return buffer to caller to free */
1465 *buf = iov[0].iov_base;
1466 if (resp_buf_type == CIFS_SMALL_BUFFER)
1467 *pbuf_type = CIFS_SMALL_BUFFER;
1468 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1469 *pbuf_type = CIFS_LARGE_BUFFER;
1470 } /* else no valid buffer on return - leave as null */
1472 /* Note: On -EAGAIN error only caller can retry on handle based calls
1473 since file handle passed in no longer valid */
1479 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1480 const int netfid, const unsigned int count,
1481 const __u64 offset, unsigned int *nbytes, const char *buf,
1482 const char __user *ubuf, const int long_op)
1485 WRITE_REQ *pSMB = NULL;
1486 WRITE_RSP *pSMBr = NULL;
1487 int bytes_returned, wct;
1491 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1492 if (tcon->ses == NULL)
1493 return -ECONNABORTED;
1495 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1500 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1504 /* tcon and ses pointer are checked in smb_init */
1505 if (tcon->ses->server == NULL)
1506 return -ECONNABORTED;
1508 pSMB->AndXCommand = 0xFF; /* none */
1510 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1512 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1513 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1516 pSMB->Reserved = 0xFFFFFFFF;
1517 pSMB->WriteMode = 0;
1518 pSMB->Remaining = 0;
1520 /* Can increase buffer size if buffer is big enough in some cases ie we
1521 can send more if LARGE_WRITE_X capability returned by the server and if
1522 our buffer is big enough or if we convert to iovecs on socket writes
1523 and eliminate the copy to the CIFS buffer */
1524 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1525 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1527 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1531 if (bytes_sent > count)
1534 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1536 memcpy(pSMB->Data, buf, bytes_sent);
1538 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1539 cifs_buf_release(pSMB);
1542 } else if (count != 0) {
1544 cifs_buf_release(pSMB);
1546 } /* else setting file size with write of zero bytes */
1548 byte_count = bytes_sent + 1; /* pad */
1549 else /* wct == 12 */ {
1550 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1552 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1553 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1554 pSMB->hdr.smb_buf_length += byte_count;
1557 pSMB->ByteCount = cpu_to_le16(byte_count);
1558 else { /* old style write has byte count 4 bytes earlier
1560 struct smb_com_writex_req *pSMBW =
1561 (struct smb_com_writex_req *)pSMB;
1562 pSMBW->ByteCount = cpu_to_le16(byte_count);
1565 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1566 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1567 cifs_stats_inc(&tcon->num_writes);
1569 cFYI(1, ("Send error in write = %d", rc));
1572 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1573 *nbytes = (*nbytes) << 16;
1574 *nbytes += le16_to_cpu(pSMBr->Count);
1577 cifs_buf_release(pSMB);
1579 /* Note: On -EAGAIN error only caller can retry on handle based calls
1580 since file handle passed in no longer valid */
1586 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1587 const int netfid, const unsigned int count,
1588 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1589 int n_vec, const int long_op)
1592 WRITE_REQ *pSMB = NULL;
1595 int resp_buf_type = 0;
1597 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1599 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1603 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1606 /* tcon and ses pointer are checked in smb_init */
1607 if (tcon->ses->server == NULL)
1608 return -ECONNABORTED;
1610 pSMB->AndXCommand = 0xFF; /* none */
1612 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1614 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1615 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1617 pSMB->Reserved = 0xFFFFFFFF;
1618 pSMB->WriteMode = 0;
1619 pSMB->Remaining = 0;
1622 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1624 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1625 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1626 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1628 pSMB->hdr.smb_buf_length += count+1;
1629 else /* wct == 12 */
1630 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1632 pSMB->ByteCount = cpu_to_le16(count + 1);
1633 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1634 struct smb_com_writex_req *pSMBW =
1635 (struct smb_com_writex_req *)pSMB;
1636 pSMBW->ByteCount = cpu_to_le16(count + 5);
1638 iov[0].iov_base = pSMB;
1640 iov[0].iov_len = smb_hdr_len + 4;
1641 else /* wct == 12 pad bigger by four bytes */
1642 iov[0].iov_len = smb_hdr_len + 8;
1645 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1647 cifs_stats_inc(&tcon->num_writes);
1649 cFYI(1, ("Send error Write2 = %d", rc));
1651 } else if (resp_buf_type == 0) {
1652 /* presumably this can not happen, but best to be safe */
1656 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1657 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1658 *nbytes = (*nbytes) << 16;
1659 *nbytes += le16_to_cpu(pSMBr->Count);
1662 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1663 if (resp_buf_type == CIFS_SMALL_BUFFER)
1664 cifs_small_buf_release(iov[0].iov_base);
1665 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1666 cifs_buf_release(iov[0].iov_base);
1668 /* Note: On -EAGAIN error only caller can retry on handle based calls
1669 since file handle passed in no longer valid */
1676 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1677 const __u16 smb_file_id, const __u64 len,
1678 const __u64 offset, const __u32 numUnlock,
1679 const __u32 numLock, const __u8 lockType, const int waitFlag)
1682 LOCK_REQ *pSMB = NULL;
1683 LOCK_RSP *pSMBr = NULL;
1688 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1689 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1694 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1696 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1697 timeout = -1; /* no response expected */
1699 } else if (waitFlag == TRUE) {
1700 timeout = 3; /* blocking operation, no timeout */
1701 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1706 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1707 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1708 pSMB->LockType = lockType;
1709 pSMB->AndXCommand = 0xFF; /* none */
1710 pSMB->Fid = smb_file_id; /* netfid stays le */
1712 if ((numLock != 0) || (numUnlock != 0)) {
1713 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1714 /* BB where to store pid high? */
1715 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1716 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1717 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1718 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1719 count = sizeof(LOCKING_ANDX_RANGE);
1724 pSMB->hdr.smb_buf_length += count;
1725 pSMB->ByteCount = cpu_to_le16(count);
1728 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1729 (struct smb_hdr *) pSMBr, &bytes_returned);
1731 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1732 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1734 cifs_stats_inc(&tcon->num_locks);
1736 cFYI(1, ("Send error in Lock = %d", rc));
1738 cifs_small_buf_release(pSMB);
1740 /* Note: On -EAGAIN error only caller can retry on handle based calls
1741 since file handle passed in no longer valid */
1746 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1747 const __u16 smb_file_id, const int get_flag, const __u64 len,
1748 struct file_lock *pLockData, const __u16 lock_type,
1751 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1752 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1753 struct cifs_posix_lock *parm_data;
1756 int bytes_returned = 0;
1757 __u16 params, param_offset, offset, byte_count, count;
1759 cFYI(1, ("Posix Lock"));
1761 if (pLockData == NULL)
1764 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1769 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1772 pSMB->MaxSetupCount = 0;
1775 pSMB->Reserved2 = 0;
1776 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1777 offset = param_offset + params;
1779 count = sizeof(struct cifs_posix_lock);
1780 pSMB->MaxParameterCount = cpu_to_le16(2);
1781 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1782 pSMB->SetupCount = 1;
1783 pSMB->Reserved3 = 0;
1785 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1787 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1788 byte_count = 3 /* pad */ + params + count;
1789 pSMB->DataCount = cpu_to_le16(count);
1790 pSMB->ParameterCount = cpu_to_le16(params);
1791 pSMB->TotalDataCount = pSMB->DataCount;
1792 pSMB->TotalParameterCount = pSMB->ParameterCount;
1793 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1794 parm_data = (struct cifs_posix_lock *)
1795 (((char *) &pSMB->hdr.Protocol) + offset);
1797 parm_data->lock_type = cpu_to_le16(lock_type);
1799 timeout = 3; /* blocking operation, no timeout */
1800 parm_data->lock_flags = cpu_to_le16(1);
1801 pSMB->Timeout = cpu_to_le32(-1);
1805 parm_data->pid = cpu_to_le32(current->tgid);
1806 parm_data->start = cpu_to_le64(pLockData->fl_start);
1807 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1809 pSMB->DataOffset = cpu_to_le16(offset);
1810 pSMB->Fid = smb_file_id;
1811 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1812 pSMB->Reserved4 = 0;
1813 pSMB->hdr.smb_buf_length += byte_count;
1814 pSMB->ByteCount = cpu_to_le16(byte_count);
1816 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1817 (struct smb_hdr *) pSMBr, &bytes_returned);
1819 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1820 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1824 cFYI(1, ("Send error in Posix Lock = %d", rc));
1825 } else if (get_flag) {
1826 /* lock structure can be returned on get */
1829 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1831 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1832 rc = -EIO; /* bad smb */
1835 if (pLockData == NULL) {
1839 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1840 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1841 if (data_count < sizeof(struct cifs_posix_lock)) {
1845 parm_data = (struct cifs_posix_lock *)
1846 ((char *)&pSMBr->hdr.Protocol + data_offset);
1847 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1848 pLockData->fl_type = F_UNLCK;
1853 cifs_small_buf_release(pSMB);
1855 /* Note: On -EAGAIN error only caller can retry on handle based calls
1856 since file handle passed in no longer valid */
1863 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1866 CLOSE_REQ *pSMB = NULL;
1867 CLOSE_RSP *pSMBr = NULL;
1869 cFYI(1, ("In CIFSSMBClose"));
1871 /* do not retry on dead session on close */
1872 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1878 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1880 pSMB->FileID = (__u16) smb_file_id;
1881 pSMB->LastWriteTime = 0xFFFFFFFF;
1882 pSMB->ByteCount = 0;
1883 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1884 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1885 cifs_stats_inc(&tcon->num_closes);
1888 /* EINTR is expected when user ctl-c to kill app */
1889 cERROR(1, ("Send error in Close = %d", rc));
1893 cifs_small_buf_release(pSMB);
1895 /* Since session is dead, file will be closed on server already */
1903 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1904 const char *fromName, const char *toName,
1905 const struct nls_table *nls_codepage, int remap)
1908 RENAME_REQ *pSMB = NULL;
1909 RENAME_RSP *pSMBr = NULL;
1911 int name_len, name_len2;
1914 cFYI(1, ("In CIFSSMBRename"));
1916 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1921 pSMB->BufferFormat = 0x04;
1922 pSMB->SearchAttributes =
1923 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1926 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1928 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1929 PATH_MAX, nls_codepage, remap);
1930 name_len++; /* trailing null */
1932 pSMB->OldFileName[name_len] = 0x04; /* pad */
1933 /* protocol requires ASCII signature byte on Unicode string */
1934 pSMB->OldFileName[name_len + 1] = 0x00;
1936 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1937 toName, PATH_MAX, nls_codepage, remap);
1938 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1939 name_len2 *= 2; /* convert to bytes */
1940 } else { /* BB improve the check for buffer overruns BB */
1941 name_len = strnlen(fromName, PATH_MAX);
1942 name_len++; /* trailing null */
1943 strncpy(pSMB->OldFileName, fromName, name_len);
1944 name_len2 = strnlen(toName, PATH_MAX);
1945 name_len2++; /* trailing null */
1946 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1947 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1948 name_len2++; /* trailing null */
1949 name_len2++; /* signature byte */
1952 count = 1 /* 1st signature byte */ + name_len + name_len2;
1953 pSMB->hdr.smb_buf_length += count;
1954 pSMB->ByteCount = cpu_to_le16(count);
1956 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1957 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1958 cifs_stats_inc(&tcon->num_renames);
1960 cFYI(1, ("Send error in rename = %d", rc));
1963 cifs_buf_release(pSMB);
1971 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1972 int netfid, char *target_name,
1973 const struct nls_table *nls_codepage, int remap)
1975 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1976 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1977 struct set_file_rename *rename_info;
1979 char dummy_string[30];
1981 int bytes_returned = 0;
1983 __u16 params, param_offset, offset, count, byte_count;
1985 cFYI(1, ("Rename to File by handle"));
1986 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1992 pSMB->MaxSetupCount = 0;
1996 pSMB->Reserved2 = 0;
1997 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1998 offset = param_offset + params;
2000 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2001 rename_info = (struct set_file_rename *) data_offset;
2002 pSMB->MaxParameterCount = cpu_to_le16(2);
2003 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2004 pSMB->SetupCount = 1;
2005 pSMB->Reserved3 = 0;
2006 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2007 byte_count = 3 /* pad */ + params;
2008 pSMB->ParameterCount = cpu_to_le16(params);
2009 pSMB->TotalParameterCount = pSMB->ParameterCount;
2010 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2011 pSMB->DataOffset = cpu_to_le16(offset);
2012 /* construct random name ".cifs_tmp<inodenum><mid>" */
2013 rename_info->overwrite = cpu_to_le32(1);
2014 rename_info->root_fid = 0;
2015 /* unicode only call */
2016 if (target_name == NULL) {
2017 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2018 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2019 dummy_string, 24, nls_codepage, remap);
2021 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2022 target_name, PATH_MAX, nls_codepage,
2025 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2026 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2027 byte_count += count;
2028 pSMB->DataCount = cpu_to_le16(count);
2029 pSMB->TotalDataCount = pSMB->DataCount;
2031 pSMB->InformationLevel =
2032 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2033 pSMB->Reserved4 = 0;
2034 pSMB->hdr.smb_buf_length += byte_count;
2035 pSMB->ByteCount = cpu_to_le16(byte_count);
2036 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2037 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2038 cifs_stats_inc(&pTcon->num_t2renames);
2040 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2043 cifs_buf_release(pSMB);
2045 /* Note: On -EAGAIN error only caller can retry on handle based calls
2046 since file handle passed in no longer valid */
2052 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2053 const __u16 target_tid, const char *toName, const int flags,
2054 const struct nls_table *nls_codepage, int remap)
2057 COPY_REQ *pSMB = NULL;
2058 COPY_RSP *pSMBr = NULL;
2060 int name_len, name_len2;
2063 cFYI(1, ("In CIFSSMBCopy"));
2065 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2070 pSMB->BufferFormat = 0x04;
2071 pSMB->Tid2 = target_tid;
2073 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2075 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2076 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2077 fromName, PATH_MAX, nls_codepage,
2079 name_len++; /* trailing null */
2081 pSMB->OldFileName[name_len] = 0x04; /* pad */
2082 /* protocol requires ASCII signature byte on Unicode string */
2083 pSMB->OldFileName[name_len + 1] = 0x00;
2085 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2086 toName, PATH_MAX, nls_codepage, remap);
2087 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2088 name_len2 *= 2; /* convert to bytes */
2089 } else { /* BB improve the check for buffer overruns BB */
2090 name_len = strnlen(fromName, PATH_MAX);
2091 name_len++; /* trailing null */
2092 strncpy(pSMB->OldFileName, fromName, name_len);
2093 name_len2 = strnlen(toName, PATH_MAX);
2094 name_len2++; /* trailing null */
2095 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2096 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2097 name_len2++; /* trailing null */
2098 name_len2++; /* signature byte */
2101 count = 1 /* 1st signature byte */ + name_len + name_len2;
2102 pSMB->hdr.smb_buf_length += count;
2103 pSMB->ByteCount = cpu_to_le16(count);
2105 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2106 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2108 cFYI(1, ("Send error in copy = %d with %d files copied",
2109 rc, le16_to_cpu(pSMBr->CopyCount)));
2112 cifs_buf_release(pSMB);
2121 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2122 const char *fromName, const char *toName,
2123 const struct nls_table *nls_codepage)
2125 TRANSACTION2_SPI_REQ *pSMB = NULL;
2126 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2129 int name_len_target;
2131 int bytes_returned = 0;
2132 __u16 params, param_offset, offset, byte_count;
2134 cFYI(1, ("In Symlink Unix style"));
2136 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2141 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2143 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2144 /* find define for this maxpathcomponent */
2146 name_len++; /* trailing null */
2149 } else { /* BB improve the check for buffer overruns BB */
2150 name_len = strnlen(fromName, PATH_MAX);
2151 name_len++; /* trailing null */
2152 strncpy(pSMB->FileName, fromName, name_len);
2154 params = 6 + name_len;
2155 pSMB->MaxSetupCount = 0;
2159 pSMB->Reserved2 = 0;
2160 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2161 InformationLevel) - 4;
2162 offset = param_offset + params;
2164 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2165 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2167 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2168 /* find define for this maxpathcomponent */
2170 name_len_target++; /* trailing null */
2171 name_len_target *= 2;
2172 } else { /* BB improve the check for buffer overruns BB */
2173 name_len_target = strnlen(toName, PATH_MAX);
2174 name_len_target++; /* trailing null */
2175 strncpy(data_offset, toName, name_len_target);
2178 pSMB->MaxParameterCount = cpu_to_le16(2);
2179 /* BB find exact max on data count below from sess */
2180 pSMB->MaxDataCount = cpu_to_le16(1000);
2181 pSMB->SetupCount = 1;
2182 pSMB->Reserved3 = 0;
2183 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2184 byte_count = 3 /* pad */ + params + name_len_target;
2185 pSMB->DataCount = cpu_to_le16(name_len_target);
2186 pSMB->ParameterCount = cpu_to_le16(params);
2187 pSMB->TotalDataCount = pSMB->DataCount;
2188 pSMB->TotalParameterCount = pSMB->ParameterCount;
2189 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2190 pSMB->DataOffset = cpu_to_le16(offset);
2191 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2192 pSMB->Reserved4 = 0;
2193 pSMB->hdr.smb_buf_length += byte_count;
2194 pSMB->ByteCount = cpu_to_le16(byte_count);
2195 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2196 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2197 cifs_stats_inc(&tcon->num_symlinks);
2199 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2203 cifs_buf_release(pSMB);
2206 goto createSymLinkRetry;
2212 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2213 const char *fromName, const char *toName,
2214 const struct nls_table *nls_codepage, int remap)
2216 TRANSACTION2_SPI_REQ *pSMB = NULL;
2217 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2220 int name_len_target;
2222 int bytes_returned = 0;
2223 __u16 params, param_offset, offset, byte_count;
2225 cFYI(1, ("In Create Hard link Unix style"));
2226 createHardLinkRetry:
2227 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2232 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2233 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2234 PATH_MAX, nls_codepage, remap);
2235 name_len++; /* trailing null */
2238 } else { /* BB improve the check for buffer overruns BB */
2239 name_len = strnlen(toName, PATH_MAX);
2240 name_len++; /* trailing null */
2241 strncpy(pSMB->FileName, toName, name_len);
2243 params = 6 + name_len;
2244 pSMB->MaxSetupCount = 0;
2248 pSMB->Reserved2 = 0;
2249 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2250 InformationLevel) - 4;
2251 offset = param_offset + params;
2253 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2254 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2256 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2257 nls_codepage, remap);
2258 name_len_target++; /* trailing null */
2259 name_len_target *= 2;
2260 } else { /* BB improve the check for buffer overruns BB */
2261 name_len_target = strnlen(fromName, PATH_MAX);
2262 name_len_target++; /* trailing null */
2263 strncpy(data_offset, fromName, name_len_target);
2266 pSMB->MaxParameterCount = cpu_to_le16(2);
2267 /* BB find exact max on data count below from sess*/
2268 pSMB->MaxDataCount = cpu_to_le16(1000);
2269 pSMB->SetupCount = 1;
2270 pSMB->Reserved3 = 0;
2271 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2272 byte_count = 3 /* pad */ + params + name_len_target;
2273 pSMB->ParameterCount = cpu_to_le16(params);
2274 pSMB->TotalParameterCount = pSMB->ParameterCount;
2275 pSMB->DataCount = cpu_to_le16(name_len_target);
2276 pSMB->TotalDataCount = pSMB->DataCount;
2277 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2278 pSMB->DataOffset = cpu_to_le16(offset);
2279 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2280 pSMB->Reserved4 = 0;
2281 pSMB->hdr.smb_buf_length += byte_count;
2282 pSMB->ByteCount = cpu_to_le16(byte_count);
2283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2284 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2285 cifs_stats_inc(&tcon->num_hardlinks);
2287 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2290 cifs_buf_release(pSMB);
2292 goto createHardLinkRetry;
2298 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2299 const char *fromName, const char *toName,
2300 const struct nls_table *nls_codepage, int remap)
2303 NT_RENAME_REQ *pSMB = NULL;
2304 RENAME_RSP *pSMBr = NULL;
2306 int name_len, name_len2;
2309 cFYI(1, ("In CIFSCreateHardLink"));
2310 winCreateHardLinkRetry:
2312 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2317 pSMB->SearchAttributes =
2318 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2320 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2321 pSMB->ClusterCount = 0;
2323 pSMB->BufferFormat = 0x04;
2325 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2327 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2328 PATH_MAX, nls_codepage, remap);
2329 name_len++; /* trailing null */
2331 pSMB->OldFileName[name_len] = 0; /* pad */
2332 pSMB->OldFileName[name_len + 1] = 0x04;
2334 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2335 toName, PATH_MAX, nls_codepage, remap);
2336 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2337 name_len2 *= 2; /* convert to bytes */
2338 } else { /* BB improve the check for buffer overruns BB */
2339 name_len = strnlen(fromName, PATH_MAX);
2340 name_len++; /* trailing null */
2341 strncpy(pSMB->OldFileName, fromName, name_len);
2342 name_len2 = strnlen(toName, PATH_MAX);
2343 name_len2++; /* trailing null */
2344 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2345 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2346 name_len2++; /* trailing null */
2347 name_len2++; /* signature byte */
2350 count = 1 /* string type byte */ + name_len + name_len2;
2351 pSMB->hdr.smb_buf_length += count;
2352 pSMB->ByteCount = cpu_to_le16(count);
2354 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2355 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2356 cifs_stats_inc(&tcon->num_hardlinks);
2358 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2360 cifs_buf_release(pSMB);
2362 goto winCreateHardLinkRetry;
2368 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2369 const unsigned char *searchName,
2370 char *symlinkinfo, const int buflen,
2371 const struct nls_table *nls_codepage)
2373 /* SMB_QUERY_FILE_UNIX_LINK */
2374 TRANSACTION2_QPI_REQ *pSMB = NULL;
2375 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2379 __u16 params, byte_count;
2381 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2384 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2389 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2391 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2392 PATH_MAX, nls_codepage);
2393 name_len++; /* trailing null */
2395 } else { /* BB improve the check for buffer overruns BB */
2396 name_len = strnlen(searchName, PATH_MAX);
2397 name_len++; /* trailing null */
2398 strncpy(pSMB->FileName, searchName, name_len);
2401 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2402 pSMB->TotalDataCount = 0;
2403 pSMB->MaxParameterCount = cpu_to_le16(2);
2404 /* BB find exact max data count below from sess structure BB */
2405 pSMB->MaxDataCount = cpu_to_le16(4000);
2406 pSMB->MaxSetupCount = 0;
2410 pSMB->Reserved2 = 0;
2411 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2412 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2413 pSMB->DataCount = 0;
2414 pSMB->DataOffset = 0;
2415 pSMB->SetupCount = 1;
2416 pSMB->Reserved3 = 0;
2417 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2418 byte_count = params + 1 /* pad */ ;
2419 pSMB->TotalParameterCount = cpu_to_le16(params);
2420 pSMB->ParameterCount = pSMB->TotalParameterCount;
2421 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2422 pSMB->Reserved4 = 0;
2423 pSMB->hdr.smb_buf_length += byte_count;
2424 pSMB->ByteCount = cpu_to_le16(byte_count);
2426 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2427 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2429 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2431 /* decode response */
2433 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2434 if (rc || (pSMBr->ByteCount < 2))
2435 /* BB also check enough total bytes returned */
2436 rc = -EIO; /* bad smb */
2438 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2439 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2441 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2442 name_len = UniStrnlen((wchar_t *) ((char *)
2443 &pSMBr->hdr.Protocol + data_offset),
2444 min_t(const int, buflen, count) / 2);
2445 /* BB FIXME investigate remapping reserved chars here */
2446 cifs_strfromUCS_le(symlinkinfo,
2447 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2449 name_len, nls_codepage);
2451 strncpy(symlinkinfo,
2452 (char *) &pSMBr->hdr.Protocol +
2454 min_t(const int, buflen, count));
2456 symlinkinfo[buflen] = 0;
2457 /* just in case so calling code does not go off the end of buffer */
2460 cifs_buf_release(pSMB);
2462 goto querySymLinkRetry;
2466 /* Initialize NT TRANSACT SMB into small smb request buffer.
2467 This assumes that all NT TRANSACTS that we init here have
2468 total parm and data under about 400 bytes (to fit in small cifs
2469 buffer size), which is the case so far, it easily fits. NB:
2470 Setup words themselves and ByteCount
2471 MaxSetupCount (size of returned setup area) and
2472 MaxParameterCount (returned parms size) must be set by caller */
2474 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2475 const int parm_len, struct cifsTconInfo *tcon,
2480 struct smb_com_ntransact_req *pSMB;
2482 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2486 *ret_buf = (void *)pSMB;
2488 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2489 pSMB->TotalDataCount = 0;
2490 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2491 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2492 pSMB->ParameterCount = pSMB->TotalParameterCount;
2493 pSMB->DataCount = pSMB->TotalDataCount;
2494 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2495 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2496 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2497 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2498 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2499 pSMB->SubCommand = cpu_to_le16(sub_command);
2504 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2505 int *pdatalen, int *pparmlen)
2508 __u32 data_count, data_offset, parm_count, parm_offset;
2509 struct smb_com_ntransact_rsp *pSMBr;
2514 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2516 /* ByteCount was converted from little endian in SendReceive */
2517 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2518 (char *)&pSMBr->ByteCount;
2520 data_offset = le32_to_cpu(pSMBr->DataOffset);
2521 data_count = le32_to_cpu(pSMBr->DataCount);
2522 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2523 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2525 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2526 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2528 /* should we also check that parm and data areas do not overlap? */
2529 if (*ppparm > end_of_smb) {
2530 cFYI(1, ("parms start after end of smb"));
2532 } else if (parm_count + *ppparm > end_of_smb) {
2533 cFYI(1, ("parm end after end of smb"));
2535 } else if (*ppdata > end_of_smb) {
2536 cFYI(1, ("data starts after end of smb"));
2538 } else if (data_count + *ppdata > end_of_smb) {
2539 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2540 *ppdata, data_count, (data_count + *ppdata),
2541 end_of_smb, pSMBr));
2543 } else if (parm_count + data_count > pSMBr->ByteCount) {
2544 cFYI(1, ("parm count and data count larger than SMB"));
2551 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2552 const unsigned char *searchName,
2553 char *symlinkinfo, const int buflen, __u16 fid,
2554 const struct nls_table *nls_codepage)
2559 struct smb_com_transaction_ioctl_req *pSMB;
2560 struct smb_com_transaction_ioctl_rsp *pSMBr;
2562 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2563 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2568 pSMB->TotalParameterCount = 0 ;
2569 pSMB->TotalDataCount = 0;
2570 pSMB->MaxParameterCount = cpu_to_le32(2);
2571 /* BB find exact data count max from sess structure BB */
2572 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2573 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2574 pSMB->MaxSetupCount = 4;
2576 pSMB->ParameterOffset = 0;
2577 pSMB->DataCount = 0;
2578 pSMB->DataOffset = 0;
2579 pSMB->SetupCount = 4;
2580 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2581 pSMB->ParameterCount = pSMB->TotalParameterCount;
2582 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2583 pSMB->IsFsctl = 1; /* FSCTL */
2584 pSMB->IsRootFlag = 0;
2585 pSMB->Fid = fid; /* file handle always le */
2586 pSMB->ByteCount = 0;
2588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2589 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2591 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2592 } else { /* decode response */
2593 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2594 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2595 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2596 /* BB also check enough total bytes returned */
2597 rc = -EIO; /* bad smb */
2599 if (data_count && (data_count < 2048)) {
2600 char *end_of_smb = 2 /* sizeof byte count */ +
2602 (char *)&pSMBr->ByteCount;
2604 struct reparse_data *reparse_buf =
2605 (struct reparse_data *)
2606 ((char *)&pSMBr->hdr.Protocol
2608 if ((char *)reparse_buf >= end_of_smb) {
2612 if ((reparse_buf->LinkNamesBuf +
2613 reparse_buf->TargetNameOffset +
2614 reparse_buf->TargetNameLen) >
2616 cFYI(1, ("reparse buf beyond SMB"));
2621 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2622 name_len = UniStrnlen((wchar_t *)
2623 (reparse_buf->LinkNamesBuf +
2624 reparse_buf->TargetNameOffset),
2626 reparse_buf->TargetNameLen / 2));
2627 cifs_strfromUCS_le(symlinkinfo,
2628 (__le16 *) (reparse_buf->LinkNamesBuf +
2629 reparse_buf->TargetNameOffset),
2630 name_len, nls_codepage);
2631 } else { /* ASCII names */
2632 strncpy(symlinkinfo,
2633 reparse_buf->LinkNamesBuf +
2634 reparse_buf->TargetNameOffset,
2635 min_t(const int, buflen,
2636 reparse_buf->TargetNameLen));
2640 cFYI(1, ("Invalid return data count on "
2641 "get reparse info ioctl"));
2643 symlinkinfo[buflen] = 0; /* just in case so the caller
2644 does not go off the end of the buffer */
2645 cFYI(1, ("readlink result - %s", symlinkinfo));
2649 cifs_buf_release(pSMB);
2651 /* Note: On -EAGAIN error only caller can retry on handle based calls
2652 since file handle passed in no longer valid */
2657 #ifdef CONFIG_CIFS_POSIX
2659 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2660 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2661 struct cifs_posix_ace *cifs_ace)
2663 /* u8 cifs fields do not need le conversion */
2664 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2665 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2666 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2667 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2672 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2673 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2674 const int acl_type, const int size_of_data_area)
2679 struct cifs_posix_ace *pACE;
2680 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2681 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2683 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2686 if (acl_type & ACL_TYPE_ACCESS) {
2687 count = le16_to_cpu(cifs_acl->access_entry_count);
2688 pACE = &cifs_acl->ace_array[0];
2689 size = sizeof(struct cifs_posix_acl);
2690 size += sizeof(struct cifs_posix_ace) * count;
2691 /* check if we would go beyond end of SMB */
2692 if (size_of_data_area < size) {
2693 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2694 size_of_data_area, size));
2697 } else if (acl_type & ACL_TYPE_DEFAULT) {
2698 count = le16_to_cpu(cifs_acl->access_entry_count);
2699 size = sizeof(struct cifs_posix_acl);
2700 size += sizeof(struct cifs_posix_ace) * count;
2701 /* skip past access ACEs to get to default ACEs */
2702 pACE = &cifs_acl->ace_array[count];
2703 count = le16_to_cpu(cifs_acl->default_entry_count);
2704 size += sizeof(struct cifs_posix_ace) * count;
2705 /* check if we would go beyond end of SMB */
2706 if (size_of_data_area < size)
2713 size = posix_acl_xattr_size(count);
2714 if ((buflen == 0) || (local_acl == NULL)) {
2715 /* used to query ACL EA size */
2716 } else if (size > buflen) {
2718 } else /* buffer big enough */ {
2719 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2720 for (i = 0; i < count ; i++) {
2721 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2728 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2729 const posix_acl_xattr_entry *local_ace)
2731 __u16 rc = 0; /* 0 = ACL converted ok */
2733 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2734 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2735 /* BB is there a better way to handle the large uid? */
2736 if (local_ace->e_id == cpu_to_le32(-1)) {
2737 /* Probably no need to le convert -1 on any arch but can not hurt */
2738 cifs_ace->cifs_uid = cpu_to_le64(-1);
2740 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2741 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2745 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2746 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2747 const int buflen, const int acl_type)
2750 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2751 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2755 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2758 count = posix_acl_xattr_count((size_t)buflen);
2759 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2761 count, buflen, le32_to_cpu(local_acl->a_version)));
2762 if (le32_to_cpu(local_acl->a_version) != 2) {
2763 cFYI(1, ("unknown POSIX ACL version %d",
2764 le32_to_cpu(local_acl->a_version)));
2767 cifs_acl->version = cpu_to_le16(1);
2768 if (acl_type == ACL_TYPE_ACCESS)
2769 cifs_acl->access_entry_count = cpu_to_le16(count);
2770 else if (acl_type == ACL_TYPE_DEFAULT)
2771 cifs_acl->default_entry_count = cpu_to_le16(count);
2773 cFYI(1, ("unknown ACL type %d", acl_type));
2776 for (i = 0; i < count; i++) {
2777 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2778 &local_acl->a_entries[i]);
2780 /* ACE not converted */
2785 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2786 rc += sizeof(struct cifs_posix_acl);
2787 /* BB add check to make sure ACL does not overflow SMB */
2793 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2794 const unsigned char *searchName,
2795 char *acl_inf, const int buflen, const int acl_type,
2796 const struct nls_table *nls_codepage, int remap)
2798 /* SMB_QUERY_POSIX_ACL */
2799 TRANSACTION2_QPI_REQ *pSMB = NULL;
2800 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2804 __u16 params, byte_count;
2806 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2809 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2814 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2816 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2817 PATH_MAX, nls_codepage, remap);
2818 name_len++; /* trailing null */
2820 pSMB->FileName[name_len] = 0;
2821 pSMB->FileName[name_len+1] = 0;
2822 } else { /* BB improve the check for buffer overruns BB */
2823 name_len = strnlen(searchName, PATH_MAX);
2824 name_len++; /* trailing null */
2825 strncpy(pSMB->FileName, searchName, name_len);
2828 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2829 pSMB->TotalDataCount = 0;
2830 pSMB->MaxParameterCount = cpu_to_le16(2);
2831 /* BB find exact max data count below from sess structure BB */
2832 pSMB->MaxDataCount = cpu_to_le16(4000);
2833 pSMB->MaxSetupCount = 0;
2837 pSMB->Reserved2 = 0;
2838 pSMB->ParameterOffset = cpu_to_le16(
2839 offsetof(struct smb_com_transaction2_qpi_req,
2840 InformationLevel) - 4);
2841 pSMB->DataCount = 0;
2842 pSMB->DataOffset = 0;
2843 pSMB->SetupCount = 1;
2844 pSMB->Reserved3 = 0;
2845 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2846 byte_count = params + 1 /* pad */ ;
2847 pSMB->TotalParameterCount = cpu_to_le16(params);
2848 pSMB->ParameterCount = pSMB->TotalParameterCount;
2849 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2850 pSMB->Reserved4 = 0;
2851 pSMB->hdr.smb_buf_length += byte_count;
2852 pSMB->ByteCount = cpu_to_le16(byte_count);
2854 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2855 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2856 cifs_stats_inc(&tcon->num_acl_get);
2858 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2860 /* decode response */
2862 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2863 if (rc || (pSMBr->ByteCount < 2))
2864 /* BB also check enough total bytes returned */
2865 rc = -EIO; /* bad smb */
2867 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2868 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2869 rc = cifs_copy_posix_acl(acl_inf,
2870 (char *)&pSMBr->hdr.Protocol+data_offset,
2871 buflen, acl_type, count);
2874 cifs_buf_release(pSMB);
2881 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2882 const unsigned char *fileName,
2883 const char *local_acl, const int buflen,
2885 const struct nls_table *nls_codepage, int remap)
2887 struct smb_com_transaction2_spi_req *pSMB = NULL;
2888 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2892 int bytes_returned = 0;
2893 __u16 params, byte_count, data_count, param_offset, offset;
2895 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2897 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2901 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2903 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2904 PATH_MAX, nls_codepage, remap);
2905 name_len++; /* trailing null */
2907 } else { /* BB improve the check for buffer overruns BB */
2908 name_len = strnlen(fileName, PATH_MAX);
2909 name_len++; /* trailing null */
2910 strncpy(pSMB->FileName, fileName, name_len);
2912 params = 6 + name_len;
2913 pSMB->MaxParameterCount = cpu_to_le16(2);
2914 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2915 pSMB->MaxSetupCount = 0;
2919 pSMB->Reserved2 = 0;
2920 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2921 InformationLevel) - 4;
2922 offset = param_offset + params;
2923 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2924 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2926 /* convert to on the wire format for POSIX ACL */
2927 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2929 if (data_count == 0) {
2931 goto setACLerrorExit;
2933 pSMB->DataOffset = cpu_to_le16(offset);
2934 pSMB->SetupCount = 1;
2935 pSMB->Reserved3 = 0;
2936 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2937 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2938 byte_count = 3 /* pad */ + params + data_count;
2939 pSMB->DataCount = cpu_to_le16(data_count);
2940 pSMB->TotalDataCount = pSMB->DataCount;
2941 pSMB->ParameterCount = cpu_to_le16(params);
2942 pSMB->TotalParameterCount = pSMB->ParameterCount;
2943 pSMB->Reserved4 = 0;
2944 pSMB->hdr.smb_buf_length += byte_count;
2945 pSMB->ByteCount = cpu_to_le16(byte_count);
2946 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2947 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2949 cFYI(1, ("Set POSIX ACL returned %d", rc));
2953 cifs_buf_release(pSMB);
2959 /* BB fix tabs in this function FIXME BB */
2961 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2962 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2965 struct smb_t2_qfi_req *pSMB = NULL;
2966 struct smb_t2_qfi_rsp *pSMBr = NULL;
2968 __u16 params, byte_count;
2970 cFYI(1, ("In GetExtAttr"));
2975 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2980 params = 2 /* level */ +2 /* fid */;
2981 pSMB->t2.TotalDataCount = 0;
2982 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2983 /* BB find exact max data count below from sess structure BB */
2984 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2985 pSMB->t2.MaxSetupCount = 0;
2986 pSMB->t2.Reserved = 0;
2988 pSMB->t2.Timeout = 0;
2989 pSMB->t2.Reserved2 = 0;
2990 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2992 pSMB->t2.DataCount = 0;
2993 pSMB->t2.DataOffset = 0;
2994 pSMB->t2.SetupCount = 1;
2995 pSMB->t2.Reserved3 = 0;
2996 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2997 byte_count = params + 1 /* pad */ ;
2998 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2999 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3000 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3003 pSMB->hdr.smb_buf_length += byte_count;
3004 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3009 cFYI(1, ("error %d in GetExtAttr", rc));
3011 /* decode response */
3012 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3013 if (rc || (pSMBr->ByteCount < 2))
3014 /* BB also check enough total bytes returned */
3015 /* If rc should we check for EOPNOSUPP and
3016 disable the srvino flag? or in caller? */
3017 rc = -EIO; /* bad smb */
3019 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3020 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3021 struct file_chattr_info *pfinfo;
3022 /* BB Do we need a cast or hash here ? */
3024 cFYI(1, ("Illegal size ret in GetExtAttr"));
3028 pfinfo = (struct file_chattr_info *)
3029 (data_offset + (char *) &pSMBr->hdr.Protocol);
3030 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3031 *pMask = le64_to_cpu(pfinfo->mask);
3035 cifs_buf_release(pSMB);
3037 goto GetExtAttrRetry;
3041 #endif /* CONFIG_POSIX */
3043 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3045 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3046 /* BB fix up return info */ char *acl_inf, const int buflen,
3051 QUERY_SEC_DESC_REQ * pSMB;
3054 cFYI(1, ("GetCifsACL"));
3056 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3057 8 /* parm len */, tcon, (void **) &pSMB);
3061 pSMB->MaxParameterCount = cpu_to_le32(4);
3062 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3063 pSMB->MaxSetupCount = 0;
3064 pSMB->Fid = fid; /* file handle always le */
3065 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3067 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3068 pSMB->hdr.smb_buf_length += 11;
3069 iov[0].iov_base = (char *)pSMB;
3070 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3072 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
3073 cifs_stats_inc(&tcon->num_acl_get);
3075 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3076 } else { /* decode response */
3077 struct cifs_ntsd *psec_desc;
3082 struct smb_com_ntransact_rsp *pSMBr;
3084 /* validate_nttransact */
3085 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3086 (char **)&psec_desc,
3087 &parm_len, &data_len);
3090 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3092 cERROR(1, ("smb %p parm %p data %p",
3093 pSMBr, parm, psec_desc)); /* BB removeme BB */
3095 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3096 rc = -EIO; /* bad smb */
3100 /* BB check that data area is minimum length and as big as acl_len */
3102 acl_len = le32_to_cpu(*(__le32 *)parm);
3103 /* BB check if (acl_len > bufsize) */
3105 parse_sec_desc(psec_desc, acl_len);
3108 if (buf_type == CIFS_SMALL_BUFFER)
3109 cifs_small_buf_release(iov[0].iov_base);
3110 else if (buf_type == CIFS_LARGE_BUFFER)
3111 cifs_buf_release(iov[0].iov_base);
3112 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3116 /* Legacy Query Path Information call for lookup to old servers such
3118 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3119 const unsigned char *searchName,
3120 FILE_ALL_INFO *pFinfo,
3121 const struct nls_table *nls_codepage, int remap)
3123 QUERY_INFORMATION_REQ * pSMB;
3124 QUERY_INFORMATION_RSP * pSMBr;
3129 cFYI(1, ("In SMBQPath path %s", searchName));
3131 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3136 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3138 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3139 PATH_MAX, nls_codepage, remap);
3140 name_len++; /* trailing null */
3143 name_len = strnlen(searchName, PATH_MAX);
3144 name_len++; /* trailing null */
3145 strncpy(pSMB->FileName, searchName, name_len);
3147 pSMB->BufferFormat = 0x04;
3148 name_len++; /* account for buffer type byte */
3149 pSMB->hdr.smb_buf_length += (__u16) name_len;
3150 pSMB->ByteCount = cpu_to_le16(name_len);
3152 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3153 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3155 cFYI(1, ("Send error in QueryInfo = %d", rc));
3156 } else if (pFinfo) { /* decode response */
3158 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3159 /* BB FIXME - add time zone adjustment BB */
3160 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3163 /* decode time fields */
3164 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3165 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3166 pFinfo->LastAccessTime = 0;
3167 pFinfo->AllocationSize =
3168 cpu_to_le64(le32_to_cpu(pSMBr->size));
3169 pFinfo->EndOfFile = pFinfo->AllocationSize;
3170 pFinfo->Attributes =
3171 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3173 rc = -EIO; /* bad buffer passed in */
3175 cifs_buf_release(pSMB);
3187 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3188 const unsigned char *searchName,
3189 FILE_ALL_INFO * pFindData,
3190 int legacy /* old style infolevel */,
3191 const struct nls_table *nls_codepage, int remap)
3193 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3194 TRANSACTION2_QPI_REQ *pSMB = NULL;
3195 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3199 __u16 params, byte_count;
3201 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3203 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3208 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3210 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3211 PATH_MAX, nls_codepage, remap);
3212 name_len++; /* trailing null */
3214 } else { /* BB improve the check for buffer overruns BB */
3215 name_len = strnlen(searchName, PATH_MAX);
3216 name_len++; /* trailing null */
3217 strncpy(pSMB->FileName, searchName, name_len);
3220 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3221 pSMB->TotalDataCount = 0;
3222 pSMB->MaxParameterCount = cpu_to_le16(2);
3223 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3224 pSMB->MaxSetupCount = 0;
3228 pSMB->Reserved2 = 0;
3229 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3230 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3231 pSMB->DataCount = 0;
3232 pSMB->DataOffset = 0;
3233 pSMB->SetupCount = 1;
3234 pSMB->Reserved3 = 0;
3235 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3236 byte_count = params + 1 /* pad */ ;
3237 pSMB->TotalParameterCount = cpu_to_le16(params);
3238 pSMB->ParameterCount = pSMB->TotalParameterCount;
3240 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3242 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3243 pSMB->Reserved4 = 0;
3244 pSMB->hdr.smb_buf_length += byte_count;
3245 pSMB->ByteCount = cpu_to_le16(byte_count);
3247 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3248 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3250 cFYI(1, ("Send error in QPathInfo = %d", rc));
3251 } else { /* decode response */
3252 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3254 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3256 else if (!legacy && (pSMBr->ByteCount < 40))
3257 rc = -EIO; /* bad smb */
3258 else if (legacy && (pSMBr->ByteCount < 24))
3259 rc = -EIO; /* 24 or 26 expected but we do not read
3261 else if (pFindData) {
3263 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3264 if (legacy) /* we do not read the last field, EAsize,
3265 fortunately since it varies by subdialect
3266 and on Set vs. Get, is two bytes or 4
3267 bytes depending but we don't care here */
3268 size = sizeof(FILE_INFO_STANDARD);
3270 size = sizeof(FILE_ALL_INFO);
3271 memcpy((char *) pFindData,
3272 (char *) &pSMBr->hdr.Protocol +
3277 cifs_buf_release(pSMB);
3279 goto QPathInfoRetry;
3285 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3286 const unsigned char *searchName,
3287 FILE_UNIX_BASIC_INFO * pFindData,
3288 const struct nls_table *nls_codepage, int remap)
3290 /* SMB_QUERY_FILE_UNIX_BASIC */
3291 TRANSACTION2_QPI_REQ *pSMB = NULL;
3292 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3294 int bytes_returned = 0;
3296 __u16 params, byte_count;
3298 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3300 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3305 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3307 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3308 PATH_MAX, nls_codepage, remap);
3309 name_len++; /* trailing null */
3311 } else { /* BB improve the check for buffer overruns BB */
3312 name_len = strnlen(searchName, PATH_MAX);
3313 name_len++; /* trailing null */
3314 strncpy(pSMB->FileName, searchName, name_len);
3317 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3318 pSMB->TotalDataCount = 0;
3319 pSMB->MaxParameterCount = cpu_to_le16(2);
3320 /* BB find exact max SMB PDU from sess structure BB */
3321 pSMB->MaxDataCount = cpu_to_le16(4000);
3322 pSMB->MaxSetupCount = 0;
3326 pSMB->Reserved2 = 0;
3327 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3328 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3329 pSMB->DataCount = 0;
3330 pSMB->DataOffset = 0;
3331 pSMB->SetupCount = 1;
3332 pSMB->Reserved3 = 0;
3333 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3334 byte_count = params + 1 /* pad */ ;
3335 pSMB->TotalParameterCount = cpu_to_le16(params);
3336 pSMB->ParameterCount = pSMB->TotalParameterCount;
3337 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3338 pSMB->Reserved4 = 0;
3339 pSMB->hdr.smb_buf_length += byte_count;
3340 pSMB->ByteCount = cpu_to_le16(byte_count);
3342 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3343 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3345 cFYI(1, ("Send error in QPathInfo = %d", rc));
3346 } else { /* decode response */
3347 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3349 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3350 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3351 "Unix Extensions can be disabled on mount "
3352 "by specifying the nosfu mount option."));
3353 rc = -EIO; /* bad smb */
3355 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3356 memcpy((char *) pFindData,
3357 (char *) &pSMBr->hdr.Protocol +
3359 sizeof (FILE_UNIX_BASIC_INFO));
3362 cifs_buf_release(pSMB);
3364 goto UnixQPathInfoRetry;
3369 #if 0 /* function unused at present */
3370 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3371 const char *searchName, FILE_ALL_INFO * findData,
3372 const struct nls_table *nls_codepage)
3374 /* level 257 SMB_ */
3375 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3376 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3380 __u16 params, byte_count;
3382 cFYI(1, ("In FindUnique"));
3384 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3389 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3391 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3392 PATH_MAX, nls_codepage);
3393 name_len++; /* trailing null */
3395 } else { /* BB improve the check for buffer overruns BB */
3396 name_len = strnlen(searchName, PATH_MAX);
3397 name_len++; /* trailing null */
3398 strncpy(pSMB->FileName, searchName, name_len);
3401 params = 12 + name_len /* includes null */ ;
3402 pSMB->TotalDataCount = 0; /* no EAs */
3403 pSMB->MaxParameterCount = cpu_to_le16(2);
3404 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3405 pSMB->MaxSetupCount = 0;
3409 pSMB->Reserved2 = 0;
3410 pSMB->ParameterOffset = cpu_to_le16(
3411 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3412 pSMB->DataCount = 0;
3413 pSMB->DataOffset = 0;
3414 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3415 pSMB->Reserved3 = 0;
3416 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3417 byte_count = params + 1 /* pad */ ;
3418 pSMB->TotalParameterCount = cpu_to_le16(params);
3419 pSMB->ParameterCount = pSMB->TotalParameterCount;
3420 pSMB->SearchAttributes =
3421 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3423 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3424 pSMB->SearchFlags = cpu_to_le16(1);
3425 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3426 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3427 pSMB->hdr.smb_buf_length += byte_count;
3428 pSMB->ByteCount = cpu_to_le16(byte_count);
3430 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3431 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3434 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3435 } else { /* decode response */
3436 cifs_stats_inc(&tcon->num_ffirst);
3440 cifs_buf_release(pSMB);
3442 goto findUniqueRetry;
3446 #endif /* end unused (temporarily) function */
3448 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3450 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3451 const char *searchName,
3452 const struct nls_table *nls_codepage,
3454 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3456 /* level 257 SMB_ */
3457 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3458 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3459 T2_FFIRST_RSP_PARMS * parms;
3461 int bytes_returned = 0;
3463 __u16 params, byte_count;
3465 cFYI(1, ("In FindFirst for %s", searchName));
3468 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3473 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3475 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3476 PATH_MAX, nls_codepage, remap);
3477 /* We can not add the asterik earlier in case
3478 it got remapped to 0xF03A as if it were part of the
3479 directory name instead of a wildcard */
3481 pSMB->FileName[name_len] = dirsep;
3482 pSMB->FileName[name_len+1] = 0;
3483 pSMB->FileName[name_len+2] = '*';
3484 pSMB->FileName[name_len+3] = 0;
3485 name_len += 4; /* now the trailing null */
3486 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3487 pSMB->FileName[name_len+1] = 0;
3489 } else { /* BB add check for overrun of SMB buf BB */
3490 name_len = strnlen(searchName, PATH_MAX);
3491 /* BB fix here and in unicode clause above ie
3492 if (name_len > buffersize-header)
3493 free buffer exit; BB */
3494 strncpy(pSMB->FileName, searchName, name_len);
3495 pSMB->FileName[name_len] = dirsep;
3496 pSMB->FileName[name_len+1] = '*';
3497 pSMB->FileName[name_len+2] = 0;
3501 params = 12 + name_len /* includes null */ ;
3502 pSMB->TotalDataCount = 0; /* no EAs */
3503 pSMB->MaxParameterCount = cpu_to_le16(10);
3504 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3505 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3506 pSMB->MaxSetupCount = 0;
3510 pSMB->Reserved2 = 0;
3511 byte_count = params + 1 /* pad */ ;
3512 pSMB->TotalParameterCount = cpu_to_le16(params);
3513 pSMB->ParameterCount = pSMB->TotalParameterCount;
3514 pSMB->ParameterOffset = cpu_to_le16(
3515 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3517 pSMB->DataCount = 0;
3518 pSMB->DataOffset = 0;
3519 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3520 pSMB->Reserved3 = 0;
3521 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3522 pSMB->SearchAttributes =
3523 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3525 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3526 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3527 CIFS_SEARCH_RETURN_RESUME);
3528 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3530 /* BB what should we set StorageType to? Does it matter? BB */
3531 pSMB->SearchStorageType = 0;
3532 pSMB->hdr.smb_buf_length += byte_count;
3533 pSMB->ByteCount = cpu_to_le16(byte_count);
3535 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3536 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3537 cifs_stats_inc(&tcon->num_ffirst);
3539 if (rc) {/* BB add logic to retry regular search if Unix search
3540 rejected unexpectedly by server */
3541 /* BB Add code to handle unsupported level rc */
3542 cFYI(1, ("Error in FindFirst = %d", rc));
3544 cifs_buf_release(pSMB);
3546 /* BB eventually could optimize out free and realloc of buf */
3549 goto findFirstRetry;
3550 } else { /* decode response */
3551 /* BB remember to free buffer if error BB */
3552 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3554 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3555 psrch_inf->unicode = TRUE;
3557 psrch_inf->unicode = FALSE;
3559 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3560 psrch_inf->smallBuf = 0;
3561 psrch_inf->srch_entries_start =
3562 (char *) &pSMBr->hdr.Protocol +
3563 le16_to_cpu(pSMBr->t2.DataOffset);
3564 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3565 le16_to_cpu(pSMBr->t2.ParameterOffset));
3567 if (parms->EndofSearch)
3568 psrch_inf->endOfSearch = TRUE;
3570 psrch_inf->endOfSearch = FALSE;
3572 psrch_inf->entries_in_buffer =
3573 le16_to_cpu(parms->SearchCount);
3574 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3575 psrch_inf->entries_in_buffer;
3576 *pnetfid = parms->SearchHandle;
3578 cifs_buf_release(pSMB);
3585 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3586 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3588 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3589 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3590 T2_FNEXT_RSP_PARMS * parms;
3591 char *response_data;
3593 int bytes_returned, name_len;
3594 __u16 params, byte_count;
3596 cFYI(1, ("In FindNext"));
3598 if (psrch_inf->endOfSearch == TRUE)
3601 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3606 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3608 pSMB->TotalDataCount = 0; /* no EAs */
3609 pSMB->MaxParameterCount = cpu_to_le16(8);
3610 pSMB->MaxDataCount =
3611 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3613 pSMB->MaxSetupCount = 0;
3617 pSMB->Reserved2 = 0;
3618 pSMB->ParameterOffset = cpu_to_le16(
3619 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3620 pSMB->DataCount = 0;
3621 pSMB->DataOffset = 0;
3622 pSMB->SetupCount = 1;
3623 pSMB->Reserved3 = 0;
3624 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3625 pSMB->SearchHandle = searchHandle; /* always kept as le */
3627 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3628 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3629 pSMB->ResumeKey = psrch_inf->resume_key;
3631 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3633 name_len = psrch_inf->resume_name_len;
3635 if (name_len < PATH_MAX) {
3636 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3637 byte_count += name_len;
3638 /* 14 byte parm len above enough for 2 byte null terminator */
3639 pSMB->ResumeFileName[name_len] = 0;
3640 pSMB->ResumeFileName[name_len+1] = 0;
3643 goto FNext2_err_exit;
3645 byte_count = params + 1 /* pad */ ;
3646 pSMB->TotalParameterCount = cpu_to_le16(params);
3647 pSMB->ParameterCount = pSMB->TotalParameterCount;
3648 pSMB->hdr.smb_buf_length += byte_count;
3649 pSMB->ByteCount = cpu_to_le16(byte_count);
3651 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3652 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3653 cifs_stats_inc(&tcon->num_fnext);
3656 psrch_inf->endOfSearch = TRUE;
3657 rc = 0; /* search probably was closed at end of search*/
3659 cFYI(1, ("FindNext returned = %d", rc));
3660 } else { /* decode response */
3661 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3664 /* BB fixme add lock for file (srch_info) struct here */
3665 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3666 psrch_inf->unicode = TRUE;
3668 psrch_inf->unicode = FALSE;
3669 response_data = (char *) &pSMBr->hdr.Protocol +
3670 le16_to_cpu(pSMBr->t2.ParameterOffset);
3671 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3672 response_data = (char *)&pSMBr->hdr.Protocol +
3673 le16_to_cpu(pSMBr->t2.DataOffset);
3674 if (psrch_inf->smallBuf)
3675 cifs_small_buf_release(
3676 psrch_inf->ntwrk_buf_start);
3678 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3679 psrch_inf->srch_entries_start = response_data;
3680 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3681 psrch_inf->smallBuf = 0;
3682 if (parms->EndofSearch)
3683 psrch_inf->endOfSearch = TRUE;
3685 psrch_inf->endOfSearch = FALSE;
3686 psrch_inf->entries_in_buffer =
3687 le16_to_cpu(parms->SearchCount);
3688 psrch_inf->index_of_last_entry +=
3689 psrch_inf->entries_in_buffer;
3690 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3691 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3693 /* BB fixme add unlock here */
3698 /* BB On error, should we leave previous search buf (and count and
3699 last entry fields) intact or free the previous one? */
3701 /* Note: On -EAGAIN error only caller can retry on handle based calls
3702 since file handle passed in no longer valid */
3705 cifs_buf_release(pSMB);
3710 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3711 const __u16 searchHandle)
3714 FINDCLOSE_REQ *pSMB = NULL;
3715 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3718 cFYI(1, ("In CIFSSMBFindClose"));
3719 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3721 /* no sense returning error if session restarted
3722 as file handle has been closed */
3728 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3729 pSMB->FileID = searchHandle;
3730 pSMB->ByteCount = 0;
3731 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3732 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3734 cERROR(1, ("Send error in FindClose = %d", rc));
3736 cifs_stats_inc(&tcon->num_fclose);
3737 cifs_small_buf_release(pSMB);
3739 /* Since session is dead, search handle closed on server already */
3747 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3748 const unsigned char *searchName,
3749 __u64 * inode_number,
3750 const struct nls_table *nls_codepage, int remap)
3753 TRANSACTION2_QPI_REQ *pSMB = NULL;
3754 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3755 int name_len, bytes_returned;
3756 __u16 params, byte_count;
3758 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3762 GetInodeNumberRetry:
3763 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3768 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3770 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3771 PATH_MAX, nls_codepage, remap);
3772 name_len++; /* trailing null */
3774 } else { /* BB improve the check for buffer overruns BB */
3775 name_len = strnlen(searchName, PATH_MAX);
3776 name_len++; /* trailing null */
3777 strncpy(pSMB->FileName, searchName, name_len);
3780 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3781 pSMB->TotalDataCount = 0;
3782 pSMB->MaxParameterCount = cpu_to_le16(2);
3783 /* BB find exact max data count below from sess structure BB */
3784 pSMB->MaxDataCount = cpu_to_le16(4000);
3785 pSMB->MaxSetupCount = 0;
3789 pSMB->Reserved2 = 0;
3790 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3791 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3792 pSMB->DataCount = 0;
3793 pSMB->DataOffset = 0;
3794 pSMB->SetupCount = 1;
3795 pSMB->Reserved3 = 0;
3796 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3797 byte_count = params + 1 /* pad */ ;
3798 pSMB->TotalParameterCount = cpu_to_le16(params);
3799 pSMB->ParameterCount = pSMB->TotalParameterCount;
3800 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3801 pSMB->Reserved4 = 0;
3802 pSMB->hdr.smb_buf_length += byte_count;
3803 pSMB->ByteCount = cpu_to_le16(byte_count);
3805 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3806 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3808 cFYI(1, ("error %d in QueryInternalInfo", rc));
3810 /* decode response */
3811 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3812 if (rc || (pSMBr->ByteCount < 2))
3813 /* BB also check enough total bytes returned */
3814 /* If rc should we check for EOPNOSUPP and
3815 disable the srvino flag? or in caller? */
3816 rc = -EIO; /* bad smb */
3818 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3819 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3820 struct file_internal_info *pfinfo;
3821 /* BB Do we need a cast or hash here ? */
3823 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3825 goto GetInodeNumOut;
3827 pfinfo = (struct file_internal_info *)
3828 (data_offset + (char *) &pSMBr->hdr.Protocol);
3829 *inode_number = pfinfo->UniqueId;
3833 cifs_buf_release(pSMB);
3835 goto GetInodeNumberRetry;
3840 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3841 const unsigned char *searchName,
3842 unsigned char **targetUNCs,
3843 unsigned int *number_of_UNC_in_array,
3844 const struct nls_table *nls_codepage, int remap)
3846 /* TRANS2_GET_DFS_REFERRAL */
3847 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3848 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3849 struct dfs_referral_level_3 *referrals = NULL;
3855 __u16 params, byte_count;
3856 *number_of_UNC_in_array = 0;
3859 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3863 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3868 /* server pointer checked in called function,
3869 but should never be null here anyway */
3870 pSMB->hdr.Mid = GetNextMid(ses->server);
3871 pSMB->hdr.Tid = ses->ipc_tid;
3872 pSMB->hdr.Uid = ses->Suid;
3873 if (ses->capabilities & CAP_STATUS32)
3874 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3875 if (ses->capabilities & CAP_DFS)
3876 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3878 if (ses->capabilities & CAP_UNICODE) {
3879 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3881 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3882 searchName, PATH_MAX, nls_codepage, remap);
3883 name_len++; /* trailing null */
3885 } else { /* BB improve the check for buffer overruns BB */
3886 name_len = strnlen(searchName, PATH_MAX);
3887 name_len++; /* trailing null */
3888 strncpy(pSMB->RequestFileName, searchName, name_len);
3892 if (ses->server->secMode &
3893 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3894 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3897 pSMB->hdr.Uid = ses->Suid;
3899 params = 2 /* level */ + name_len /*includes null */ ;
3900 pSMB->TotalDataCount = 0;
3901 pSMB->DataCount = 0;
3902 pSMB->DataOffset = 0;
3903 pSMB->MaxParameterCount = 0;
3904 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3905 pSMB->MaxSetupCount = 0;
3909 pSMB->Reserved2 = 0;
3910 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3911 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3912 pSMB->SetupCount = 1;
3913 pSMB->Reserved3 = 0;
3914 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3915 byte_count = params + 3 /* pad */ ;
3916 pSMB->ParameterCount = cpu_to_le16(params);
3917 pSMB->TotalParameterCount = pSMB->ParameterCount;
3918 pSMB->MaxReferralLevel = cpu_to_le16(3);
3919 pSMB->hdr.smb_buf_length += byte_count;
3920 pSMB->ByteCount = cpu_to_le16(byte_count);
3922 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3923 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3925 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3926 } else { /* decode response */
3927 /* BB Add logic to parse referrals here */
3928 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3930 /* BB Also check if enough total bytes returned? */
3931 if (rc || (pSMBr->ByteCount < 17))
3932 rc = -EIO; /* bad smb */
3934 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3935 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3938 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3939 pSMBr->ByteCount, data_offset));
3941 (struct dfs_referral_level_3 *)
3942 (8 /* sizeof start of data block */ +
3944 (char *) &pSMBr->hdr.Protocol);
3945 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3946 "for referral one refer size: 0x%x srv "
3947 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3948 le16_to_cpu(pSMBr->NumberOfReferrals),
3949 le16_to_cpu(pSMBr->DFSFlags),
3950 le16_to_cpu(referrals->ReferralSize),
3951 le16_to_cpu(referrals->ServerType),
3952 le16_to_cpu(referrals->ReferralFlags),
3953 le16_to_cpu(referrals->TimeToLive)));
3954 /* BB This field is actually two bytes in from start of
3955 data block so we could do safety check that DataBlock
3956 begins at address of pSMBr->NumberOfReferrals */
3957 *number_of_UNC_in_array =
3958 le16_to_cpu(pSMBr->NumberOfReferrals);
3960 /* BB Fix below so can return more than one referral */
3961 if (*number_of_UNC_in_array > 1)
3962 *number_of_UNC_in_array = 1;
3964 /* get the length of the strings describing refs */
3966 for (i = 0; i < *number_of_UNC_in_array; i++) {
3967 /* make sure that DfsPathOffset not past end */
3969 le16_to_cpu(referrals->DfsPathOffset);
3970 if (offset > data_count) {
3971 /* if invalid referral, stop here and do
3972 not try to copy any more */
3973 *number_of_UNC_in_array = i;
3976 temp = ((char *)referrals) + offset;
3978 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3979 name_len += UniStrnlen((wchar_t *)temp,
3982 name_len += strnlen(temp, data_count);
3985 /* BB add check that referral pointer does
3986 not fall off end PDU */
3988 /* BB add check for name_len bigger than bcc */
3990 kmalloc(name_len+1+(*number_of_UNC_in_array),
3992 if (*targetUNCs == NULL) {
3996 /* copy the ref strings */
3997 referrals = (struct dfs_referral_level_3 *)
3998 (8 /* sizeof data hdr */ + data_offset +
3999 (char *) &pSMBr->hdr.Protocol);
4001 for (i = 0; i < *number_of_UNC_in_array; i++) {
4002 temp = ((char *)referrals) +
4003 le16_to_cpu(referrals->DfsPathOffset);
4004 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4005 cifs_strfromUCS_le(*targetUNCs,
4010 strncpy(*targetUNCs, temp, name_len);
4012 /* BB update target_uncs pointers */
4022 cifs_buf_release(pSMB);
4030 /* Query File System Info such as free space to old servers such as Win 9x */
4032 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4034 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4035 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4036 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4037 FILE_SYSTEM_ALLOC_INFO *response_data;
4039 int bytes_returned = 0;
4040 __u16 params, byte_count;
4042 cFYI(1, ("OldQFSInfo"));
4044 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4049 params = 2; /* level */
4050 pSMB->TotalDataCount = 0;
4051 pSMB->MaxParameterCount = cpu_to_le16(2);
4052 pSMB->MaxDataCount = cpu_to_le16(1000);
4053 pSMB->MaxSetupCount = 0;
4057 pSMB->Reserved2 = 0;
4058 byte_count = params + 1 /* pad */ ;
4059 pSMB->TotalParameterCount = cpu_to_le16(params);
4060 pSMB->ParameterCount = pSMB->TotalParameterCount;
4061 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4062 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4063 pSMB->DataCount = 0;
4064 pSMB->DataOffset = 0;
4065 pSMB->SetupCount = 1;
4066 pSMB->Reserved3 = 0;
4067 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4068 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4069 pSMB->hdr.smb_buf_length += byte_count;
4070 pSMB->ByteCount = cpu_to_le16(byte_count);
4072 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4073 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4075 cFYI(1, ("Send error in QFSInfo = %d", rc));
4076 } else { /* decode response */
4077 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4079 if (rc || (pSMBr->ByteCount < 18))
4080 rc = -EIO; /* bad smb */
4082 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4083 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4084 pSMBr->ByteCount, data_offset));
4086 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4087 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4089 le16_to_cpu(response_data->BytesPerSector) *
4090 le32_to_cpu(response_data->
4091 SectorsPerAllocationUnit);
4093 le32_to_cpu(response_data->TotalAllocationUnits);
4094 FSData->f_bfree = FSData->f_bavail =
4095 le32_to_cpu(response_data->FreeAllocationUnits);
4097 ("Blocks: %lld Free: %lld Block size %ld",
4098 (unsigned long long)FSData->f_blocks,
4099 (unsigned long long)FSData->f_bfree,
4103 cifs_buf_release(pSMB);
4106 goto oldQFSInfoRetry;
4112 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4114 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4115 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4116 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4117 FILE_SYSTEM_INFO *response_data;
4119 int bytes_returned = 0;
4120 __u16 params, byte_count;
4122 cFYI(1, ("In QFSInfo"));
4124 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4129 params = 2; /* level */
4130 pSMB->TotalDataCount = 0;
4131 pSMB->MaxParameterCount = cpu_to_le16(2);
4132 pSMB->MaxDataCount = cpu_to_le16(1000);
4133 pSMB->MaxSetupCount = 0;
4137 pSMB->Reserved2 = 0;
4138 byte_count = params + 1 /* pad */ ;
4139 pSMB->TotalParameterCount = cpu_to_le16(params);
4140 pSMB->ParameterCount = pSMB->TotalParameterCount;
4141 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4142 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4143 pSMB->DataCount = 0;
4144 pSMB->DataOffset = 0;
4145 pSMB->SetupCount = 1;
4146 pSMB->Reserved3 = 0;
4147 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4148 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4149 pSMB->hdr.smb_buf_length += byte_count;
4150 pSMB->ByteCount = cpu_to_le16(byte_count);
4152 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4153 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4155 cFYI(1, ("Send error in QFSInfo = %d", rc));
4156 } else { /* decode response */
4157 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4159 if (rc || (pSMBr->ByteCount < 24))
4160 rc = -EIO; /* bad smb */
4162 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4166 *) (((char *) &pSMBr->hdr.Protocol) +
4169 le32_to_cpu(response_data->BytesPerSector) *
4170 le32_to_cpu(response_data->
4171 SectorsPerAllocationUnit);
4173 le64_to_cpu(response_data->TotalAllocationUnits);
4174 FSData->f_bfree = FSData->f_bavail =
4175 le64_to_cpu(response_data->FreeAllocationUnits);
4177 ("Blocks: %lld Free: %lld Block size %ld",
4178 (unsigned long long)FSData->f_blocks,
4179 (unsigned long long)FSData->f_bfree,
4183 cifs_buf_release(pSMB);
4192 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4194 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4195 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4196 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4197 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4199 int bytes_returned = 0;
4200 __u16 params, byte_count;
4202 cFYI(1, ("In QFSAttributeInfo"));
4204 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4209 params = 2; /* level */
4210 pSMB->TotalDataCount = 0;
4211 pSMB->MaxParameterCount = cpu_to_le16(2);
4212 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4213 pSMB->MaxSetupCount = 0;
4217 pSMB->Reserved2 = 0;
4218 byte_count = params + 1 /* pad */ ;
4219 pSMB->TotalParameterCount = cpu_to_le16(params);
4220 pSMB->ParameterCount = pSMB->TotalParameterCount;
4221 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4222 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4223 pSMB->DataCount = 0;
4224 pSMB->DataOffset = 0;
4225 pSMB->SetupCount = 1;
4226 pSMB->Reserved3 = 0;
4227 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4228 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4229 pSMB->hdr.smb_buf_length += byte_count;
4230 pSMB->ByteCount = cpu_to_le16(byte_count);
4232 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4233 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4235 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4236 } else { /* decode response */
4237 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4239 if (rc || (pSMBr->ByteCount < 13)) {
4240 /* BB also check if enough bytes returned */
4241 rc = -EIO; /* bad smb */
4243 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4245 (FILE_SYSTEM_ATTRIBUTE_INFO
4246 *) (((char *) &pSMBr->hdr.Protocol) +
4248 memcpy(&tcon->fsAttrInfo, response_data,
4249 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4252 cifs_buf_release(pSMB);
4255 goto QFSAttributeRetry;
4261 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4263 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4264 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4265 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4266 FILE_SYSTEM_DEVICE_INFO *response_data;
4268 int bytes_returned = 0;
4269 __u16 params, byte_count;
4271 cFYI(1, ("In QFSDeviceInfo"));
4273 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4278 params = 2; /* level */
4279 pSMB->TotalDataCount = 0;
4280 pSMB->MaxParameterCount = cpu_to_le16(2);
4281 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4282 pSMB->MaxSetupCount = 0;
4286 pSMB->Reserved2 = 0;
4287 byte_count = params + 1 /* pad */ ;
4288 pSMB->TotalParameterCount = cpu_to_le16(params);
4289 pSMB->ParameterCount = pSMB->TotalParameterCount;
4290 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4291 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4293 pSMB->DataCount = 0;
4294 pSMB->DataOffset = 0;
4295 pSMB->SetupCount = 1;
4296 pSMB->Reserved3 = 0;
4297 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4298 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4299 pSMB->hdr.smb_buf_length += byte_count;
4300 pSMB->ByteCount = cpu_to_le16(byte_count);
4302 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4303 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4305 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4306 } else { /* decode response */
4307 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4309 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4310 rc = -EIO; /* bad smb */
4312 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4314 (FILE_SYSTEM_DEVICE_INFO *)
4315 (((char *) &pSMBr->hdr.Protocol) +
4317 memcpy(&tcon->fsDevInfo, response_data,
4318 sizeof(FILE_SYSTEM_DEVICE_INFO));
4321 cifs_buf_release(pSMB);
4324 goto QFSDeviceRetry;
4330 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4332 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4333 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4334 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4335 FILE_SYSTEM_UNIX_INFO *response_data;
4337 int bytes_returned = 0;
4338 __u16 params, byte_count;
4340 cFYI(1, ("In QFSUnixInfo"));
4342 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4347 params = 2; /* level */
4348 pSMB->TotalDataCount = 0;
4349 pSMB->DataCount = 0;
4350 pSMB->DataOffset = 0;
4351 pSMB->MaxParameterCount = cpu_to_le16(2);
4352 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4353 pSMB->MaxSetupCount = 0;
4357 pSMB->Reserved2 = 0;
4358 byte_count = params + 1 /* pad */ ;
4359 pSMB->ParameterCount = cpu_to_le16(params);
4360 pSMB->TotalParameterCount = pSMB->ParameterCount;
4361 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4362 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4363 pSMB->SetupCount = 1;
4364 pSMB->Reserved3 = 0;
4365 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4366 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4367 pSMB->hdr.smb_buf_length += byte_count;
4368 pSMB->ByteCount = cpu_to_le16(byte_count);
4370 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4371 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4373 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4374 } else { /* decode response */
4375 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4377 if (rc || (pSMBr->ByteCount < 13)) {
4378 rc = -EIO; /* bad smb */
4380 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4382 (FILE_SYSTEM_UNIX_INFO
4383 *) (((char *) &pSMBr->hdr.Protocol) +
4385 memcpy(&tcon->fsUnixInfo, response_data,
4386 sizeof(FILE_SYSTEM_UNIX_INFO));
4389 cifs_buf_release(pSMB);
4399 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4401 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4402 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4403 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4405 int bytes_returned = 0;
4406 __u16 params, param_offset, offset, byte_count;
4408 cFYI(1, ("In SETFSUnixInfo"));
4410 /* BB switch to small buf init to save memory */
4411 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4416 params = 4; /* 2 bytes zero followed by info level. */
4417 pSMB->MaxSetupCount = 0;
4421 pSMB->Reserved2 = 0;
4422 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4424 offset = param_offset + params;
4426 pSMB->MaxParameterCount = cpu_to_le16(4);
4427 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4428 pSMB->SetupCount = 1;
4429 pSMB->Reserved3 = 0;
4430 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4431 byte_count = 1 /* pad */ + params + 12;
4433 pSMB->DataCount = cpu_to_le16(12);
4434 pSMB->ParameterCount = cpu_to_le16(params);
4435 pSMB->TotalDataCount = pSMB->DataCount;
4436 pSMB->TotalParameterCount = pSMB->ParameterCount;
4437 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4438 pSMB->DataOffset = cpu_to_le16(offset);
4442 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4445 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4446 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4447 pSMB->ClientUnixCap = cpu_to_le64(cap);
4449 pSMB->hdr.smb_buf_length += byte_count;
4450 pSMB->ByteCount = cpu_to_le16(byte_count);
4452 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4453 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4455 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4456 } else { /* decode response */
4457 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4459 rc = -EIO; /* bad smb */
4462 cifs_buf_release(pSMB);
4465 goto SETFSUnixRetry;
4473 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4474 struct kstatfs *FSData)
4476 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4477 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4478 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4479 FILE_SYSTEM_POSIX_INFO *response_data;
4481 int bytes_returned = 0;
4482 __u16 params, byte_count;
4484 cFYI(1, ("In QFSPosixInfo"));
4486 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4491 params = 2; /* level */
4492 pSMB->TotalDataCount = 0;
4493 pSMB->DataCount = 0;
4494 pSMB->DataOffset = 0;
4495 pSMB->MaxParameterCount = cpu_to_le16(2);
4496 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4497 pSMB->MaxSetupCount = 0;
4501 pSMB->Reserved2 = 0;
4502 byte_count = params + 1 /* pad */ ;
4503 pSMB->ParameterCount = cpu_to_le16(params);
4504 pSMB->TotalParameterCount = pSMB->ParameterCount;
4505 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4506 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4507 pSMB->SetupCount = 1;
4508 pSMB->Reserved3 = 0;
4509 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4510 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4511 pSMB->hdr.smb_buf_length += byte_count;
4512 pSMB->ByteCount = cpu_to_le16(byte_count);
4514 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4515 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4517 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4518 } else { /* decode response */
4519 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4521 if (rc || (pSMBr->ByteCount < 13)) {
4522 rc = -EIO; /* bad smb */
4524 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4526 (FILE_SYSTEM_POSIX_INFO
4527 *) (((char *) &pSMBr->hdr.Protocol) +
4530 le32_to_cpu(response_data->BlockSize);
4532 le64_to_cpu(response_data->TotalBlocks);
4534 le64_to_cpu(response_data->BlocksAvail);
4535 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4536 FSData->f_bavail = FSData->f_bfree;
4539 le64_to_cpu(response_data->UserBlocksAvail);
4541 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4543 le64_to_cpu(response_data->TotalFileNodes);
4544 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4546 le64_to_cpu(response_data->FreeFileNodes);
4549 cifs_buf_release(pSMB);
4558 /* We can not use write of zero bytes trick to
4559 set file size due to need for large file support. Also note that
4560 this SetPathInfo is preferred to SetFileInfo based method in next
4561 routine which is only needed to work around a sharing violation bug
4562 in Samba which this routine can run into */
4565 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4566 __u64 size, int SetAllocation,
4567 const struct nls_table *nls_codepage, int remap)
4569 struct smb_com_transaction2_spi_req *pSMB = NULL;
4570 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4571 struct file_end_of_file_info *parm_data;
4574 int bytes_returned = 0;
4575 __u16 params, byte_count, data_count, param_offset, offset;
4577 cFYI(1, ("In SetEOF"));
4579 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4584 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4586 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4587 PATH_MAX, nls_codepage, remap);
4588 name_len++; /* trailing null */
4590 } else { /* BB improve the check for buffer overruns BB */
4591 name_len = strnlen(fileName, PATH_MAX);
4592 name_len++; /* trailing null */
4593 strncpy(pSMB->FileName, fileName, name_len);
4595 params = 6 + name_len;
4596 data_count = sizeof(struct file_end_of_file_info);
4597 pSMB->MaxParameterCount = cpu_to_le16(2);
4598 pSMB->MaxDataCount = cpu_to_le16(4100);
4599 pSMB->MaxSetupCount = 0;
4603 pSMB->Reserved2 = 0;
4604 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4605 InformationLevel) - 4;
4606 offset = param_offset + params;
4607 if (SetAllocation) {
4608 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4609 pSMB->InformationLevel =
4610 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4612 pSMB->InformationLevel =
4613 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4614 } else /* Set File Size */ {
4615 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4616 pSMB->InformationLevel =
4617 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4619 pSMB->InformationLevel =
4620 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4624 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4626 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4627 pSMB->DataOffset = cpu_to_le16(offset);
4628 pSMB->SetupCount = 1;
4629 pSMB->Reserved3 = 0;
4630 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4631 byte_count = 3 /* pad */ + params + data_count;
4632 pSMB->DataCount = cpu_to_le16(data_count);
4633 pSMB->TotalDataCount = pSMB->DataCount;
4634 pSMB->ParameterCount = cpu_to_le16(params);
4635 pSMB->TotalParameterCount = pSMB->ParameterCount;
4636 pSMB->Reserved4 = 0;
4637 pSMB->hdr.smb_buf_length += byte_count;
4638 parm_data->FileSize = cpu_to_le64(size);
4639 pSMB->ByteCount = cpu_to_le16(byte_count);
4640 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4641 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4643 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4646 cifs_buf_release(pSMB);
4655 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4656 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4658 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4659 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4661 struct file_end_of_file_info *parm_data;
4663 int bytes_returned = 0;
4664 __u16 params, param_offset, offset, byte_count, count;
4666 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4668 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4673 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4675 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4676 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4679 pSMB->MaxSetupCount = 0;
4683 pSMB->Reserved2 = 0;
4684 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4685 offset = param_offset + params;
4687 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4689 count = sizeof(struct file_end_of_file_info);
4690 pSMB->MaxParameterCount = cpu_to_le16(2);
4691 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4692 pSMB->SetupCount = 1;
4693 pSMB->Reserved3 = 0;
4694 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4695 byte_count = 3 /* pad */ + params + count;
4696 pSMB->DataCount = cpu_to_le16(count);
4697 pSMB->ParameterCount = cpu_to_le16(params);
4698 pSMB->TotalDataCount = pSMB->DataCount;
4699 pSMB->TotalParameterCount = pSMB->ParameterCount;
4700 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4702 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4704 pSMB->DataOffset = cpu_to_le16(offset);
4705 parm_data->FileSize = cpu_to_le64(size);
4707 if (SetAllocation) {
4708 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4709 pSMB->InformationLevel =
4710 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4712 pSMB->InformationLevel =
4713 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4714 } else /* Set File Size */ {
4715 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4716 pSMB->InformationLevel =
4717 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4719 pSMB->InformationLevel =
4720 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4722 pSMB->Reserved4 = 0;
4723 pSMB->hdr.smb_buf_length += byte_count;
4724 pSMB->ByteCount = cpu_to_le16(byte_count);
4725 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4726 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4729 ("Send error in SetFileInfo (SetFileSize) = %d",
4734 cifs_small_buf_release(pSMB);
4736 /* Note: On -EAGAIN error only caller can retry on handle based calls
4737 since file handle passed in no longer valid */
4742 /* Some legacy servers such as NT4 require that the file times be set on
4743 an open handle, rather than by pathname - this is awkward due to
4744 potential access conflicts on the open, but it is unavoidable for these
4745 old servers since the only other choice is to go from 100 nanosecond DCE
4746 time and resort to the original setpathinfo level which takes the ancient
4747 DOS time format with 2 second granularity */
4749 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4750 const FILE_BASIC_INFO *data, __u16 fid)
4752 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4753 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4756 int bytes_returned = 0;
4757 __u16 params, param_offset, offset, byte_count, count;
4759 cFYI(1, ("Set Times (via SetFileInfo)"));
4760 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4765 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4767 /* At this point there is no need to override the current pid
4768 with the pid of the opener, but that could change if we someday
4769 use an existing handle (rather than opening one on the fly) */
4770 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4771 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4774 pSMB->MaxSetupCount = 0;
4778 pSMB->Reserved2 = 0;
4779 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4780 offset = param_offset + params;
4782 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4784 count = sizeof(FILE_BASIC_INFO);
4785 pSMB->MaxParameterCount = cpu_to_le16(2);
4786 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4787 pSMB->SetupCount = 1;
4788 pSMB->Reserved3 = 0;
4789 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4790 byte_count = 3 /* pad */ + params + count;
4791 pSMB->DataCount = cpu_to_le16(count);
4792 pSMB->ParameterCount = cpu_to_le16(params);
4793 pSMB->TotalDataCount = pSMB->DataCount;
4794 pSMB->TotalParameterCount = pSMB->ParameterCount;
4795 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4796 pSMB->DataOffset = cpu_to_le16(offset);
4798 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4799 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4801 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4802 pSMB->Reserved4 = 0;
4803 pSMB->hdr.smb_buf_length += byte_count;
4804 pSMB->ByteCount = cpu_to_le16(byte_count);
4805 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4806 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4807 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4809 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4812 cifs_small_buf_release(pSMB);
4814 /* Note: On -EAGAIN error only caller can retry on handle based calls
4815 since file handle passed in no longer valid */
4822 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4823 const FILE_BASIC_INFO *data,
4824 const struct nls_table *nls_codepage, int remap)
4826 TRANSACTION2_SPI_REQ *pSMB = NULL;
4827 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4830 int bytes_returned = 0;
4832 __u16 params, param_offset, offset, byte_count, count;
4834 cFYI(1, ("In SetTimes"));
4837 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4842 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4844 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4845 PATH_MAX, nls_codepage, remap);
4846 name_len++; /* trailing null */
4848 } else { /* BB improve the check for buffer overruns BB */
4849 name_len = strnlen(fileName, PATH_MAX);
4850 name_len++; /* trailing null */
4851 strncpy(pSMB->FileName, fileName, name_len);
4854 params = 6 + name_len;
4855 count = sizeof(FILE_BASIC_INFO);
4856 pSMB->MaxParameterCount = cpu_to_le16(2);
4857 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4858 pSMB->MaxSetupCount = 0;
4862 pSMB->Reserved2 = 0;
4863 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4864 InformationLevel) - 4;
4865 offset = param_offset + params;
4866 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4867 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4868 pSMB->DataOffset = cpu_to_le16(offset);
4869 pSMB->SetupCount = 1;
4870 pSMB->Reserved3 = 0;
4871 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4872 byte_count = 3 /* pad */ + params + count;
4874 pSMB->DataCount = cpu_to_le16(count);
4875 pSMB->ParameterCount = cpu_to_le16(params);
4876 pSMB->TotalDataCount = pSMB->DataCount;
4877 pSMB->TotalParameterCount = pSMB->ParameterCount;
4878 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4879 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4881 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4882 pSMB->Reserved4 = 0;
4883 pSMB->hdr.smb_buf_length += byte_count;
4884 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4885 pSMB->ByteCount = cpu_to_le16(byte_count);
4886 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4887 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4889 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4892 cifs_buf_release(pSMB);
4900 /* Can not be used to set time stamps yet (due to old DOS time format) */
4901 /* Can be used to set attributes */
4902 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4903 handling it anyway and NT4 was what we thought it would be needed for
4904 Do not delete it until we prove whether needed for Win9x though */
4906 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4907 __u16 dos_attrs, const struct nls_table *nls_codepage)
4909 SETATTR_REQ *pSMB = NULL;
4910 SETATTR_RSP *pSMBr = NULL;
4915 cFYI(1, ("In SetAttrLegacy"));
4918 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4923 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4925 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4926 PATH_MAX, nls_codepage);
4927 name_len++; /* trailing null */
4929 } else { /* BB improve the check for buffer overruns BB */
4930 name_len = strnlen(fileName, PATH_MAX);
4931 name_len++; /* trailing null */
4932 strncpy(pSMB->fileName, fileName, name_len);
4934 pSMB->attr = cpu_to_le16(dos_attrs);
4935 pSMB->BufferFormat = 0x04;
4936 pSMB->hdr.smb_buf_length += name_len + 1;
4937 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4938 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4939 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4941 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4944 cifs_buf_release(pSMB);
4947 goto SetAttrLgcyRetry;
4951 #endif /* temporarily unneeded SetAttr legacy function */
4954 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4955 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4956 dev_t device, const struct nls_table *nls_codepage,
4959 TRANSACTION2_SPI_REQ *pSMB = NULL;
4960 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4963 int bytes_returned = 0;
4964 FILE_UNIX_BASIC_INFO *data_offset;
4965 __u16 params, param_offset, offset, count, byte_count;
4967 cFYI(1, ("In SetUID/GID/Mode"));
4969 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4974 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4976 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4977 PATH_MAX, nls_codepage, remap);
4978 name_len++; /* trailing null */
4980 } else { /* BB improve the check for buffer overruns BB */
4981 name_len = strnlen(fileName, PATH_MAX);
4982 name_len++; /* trailing null */
4983 strncpy(pSMB->FileName, fileName, name_len);
4986 params = 6 + name_len;
4987 count = sizeof(FILE_UNIX_BASIC_INFO);
4988 pSMB->MaxParameterCount = cpu_to_le16(2);
4989 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4990 pSMB->MaxSetupCount = 0;
4994 pSMB->Reserved2 = 0;
4995 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4996 InformationLevel) - 4;
4997 offset = param_offset + params;
4999 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5001 memset(data_offset, 0, count);
5002 pSMB->DataOffset = cpu_to_le16(offset);
5003 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5004 pSMB->SetupCount = 1;
5005 pSMB->Reserved3 = 0;
5006 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5007 byte_count = 3 /* pad */ + params + count;
5008 pSMB->ParameterCount = cpu_to_le16(params);
5009 pSMB->DataCount = cpu_to_le16(count);
5010 pSMB->TotalParameterCount = pSMB->ParameterCount;
5011 pSMB->TotalDataCount = pSMB->DataCount;
5012 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5013 pSMB->Reserved4 = 0;
5014 pSMB->hdr.smb_buf_length += byte_count;
5015 /* Samba server ignores set of file size to zero due to bugs in some
5016 older clients, but we should be precise - we use SetFileSize to
5017 set file size and do not want to truncate file size to zero
5018 accidently as happened on one Samba server beta by putting
5019 zero instead of -1 here */
5020 data_offset->EndOfFile = NO_CHANGE_64;
5021 data_offset->NumOfBytes = NO_CHANGE_64;
5022 data_offset->LastStatusChange = NO_CHANGE_64;
5023 data_offset->LastAccessTime = NO_CHANGE_64;
5024 data_offset->LastModificationTime = NO_CHANGE_64;
5025 data_offset->Uid = cpu_to_le64(uid);
5026 data_offset->Gid = cpu_to_le64(gid);
5027 /* better to leave device as zero when it is */
5028 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5029 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5030 data_offset->Permissions = cpu_to_le64(mode);
5033 data_offset->Type = cpu_to_le32(UNIX_FILE);
5034 else if (S_ISDIR(mode))
5035 data_offset->Type = cpu_to_le32(UNIX_DIR);
5036 else if (S_ISLNK(mode))
5037 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5038 else if (S_ISCHR(mode))
5039 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5040 else if (S_ISBLK(mode))
5041 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5042 else if (S_ISFIFO(mode))
5043 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5044 else if (S_ISSOCK(mode))
5045 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5048 pSMB->ByteCount = cpu_to_le16(byte_count);
5049 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5050 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5052 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5056 cifs_buf_release(pSMB);
5062 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5063 const int notify_subdirs, const __u16 netfid,
5064 __u32 filter, struct file *pfile, int multishot,
5065 const struct nls_table *nls_codepage)
5068 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5069 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5070 struct dir_notify_req *dnotify_req;
5073 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5074 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5079 pSMB->TotalParameterCount = 0 ;
5080 pSMB->TotalDataCount = 0;
5081 pSMB->MaxParameterCount = cpu_to_le32(2);
5082 /* BB find exact data count max from sess structure BB */
5083 pSMB->MaxDataCount = 0; /* same in little endian or be */
5084 /* BB VERIFY verify which is correct for above BB */
5085 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5086 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5088 pSMB->MaxSetupCount = 4;
5090 pSMB->ParameterOffset = 0;
5091 pSMB->DataCount = 0;
5092 pSMB->DataOffset = 0;
5093 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5094 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5095 pSMB->ParameterCount = pSMB->TotalParameterCount;
5097 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5098 pSMB->Reserved2 = 0;
5099 pSMB->CompletionFilter = cpu_to_le32(filter);
5100 pSMB->Fid = netfid; /* file handle always le */
5101 pSMB->ByteCount = 0;
5103 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5104 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5106 cFYI(1, ("Error in Notify = %d", rc));
5108 /* Add file to outstanding requests */
5109 /* BB change to kmem cache alloc */
5110 dnotify_req = kmalloc(
5111 sizeof(struct dir_notify_req),
5114 dnotify_req->Pid = pSMB->hdr.Pid;
5115 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5116 dnotify_req->Mid = pSMB->hdr.Mid;
5117 dnotify_req->Tid = pSMB->hdr.Tid;
5118 dnotify_req->Uid = pSMB->hdr.Uid;
5119 dnotify_req->netfid = netfid;
5120 dnotify_req->pfile = pfile;
5121 dnotify_req->filter = filter;
5122 dnotify_req->multishot = multishot;
5123 spin_lock(&GlobalMid_Lock);
5124 list_add_tail(&dnotify_req->lhead,
5125 &GlobalDnotifyReqList);
5126 spin_unlock(&GlobalMid_Lock);
5130 cifs_buf_release(pSMB);
5133 #ifdef CONFIG_CIFS_XATTR
5135 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5136 const unsigned char *searchName,
5137 char *EAData, size_t buf_size,
5138 const struct nls_table *nls_codepage, int remap)
5140 /* BB assumes one setup word */
5141 TRANSACTION2_QPI_REQ *pSMB = NULL;
5142 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5146 struct fea *temp_fea;
5148 __u16 params, byte_count;
5150 cFYI(1, ("In Query All EAs path %s", searchName));
5152 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5157 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5159 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5160 PATH_MAX, nls_codepage, remap);
5161 name_len++; /* trailing null */
5163 } else { /* BB improve the check for buffer overruns BB */
5164 name_len = strnlen(searchName, PATH_MAX);
5165 name_len++; /* trailing null */
5166 strncpy(pSMB->FileName, searchName, name_len);
5169 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5170 pSMB->TotalDataCount = 0;
5171 pSMB->MaxParameterCount = cpu_to_le16(2);
5172 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5173 pSMB->MaxSetupCount = 0;
5177 pSMB->Reserved2 = 0;
5178 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5179 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5180 pSMB->DataCount = 0;
5181 pSMB->DataOffset = 0;
5182 pSMB->SetupCount = 1;
5183 pSMB->Reserved3 = 0;
5184 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5185 byte_count = params + 1 /* pad */ ;
5186 pSMB->TotalParameterCount = cpu_to_le16(params);
5187 pSMB->ParameterCount = pSMB->TotalParameterCount;
5188 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5189 pSMB->Reserved4 = 0;
5190 pSMB->hdr.smb_buf_length += byte_count;
5191 pSMB->ByteCount = cpu_to_le16(byte_count);
5193 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5194 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5196 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5197 } else { /* decode response */
5198 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5200 /* BB also check enough total bytes returned */
5201 /* BB we need to improve the validity checking
5202 of these trans2 responses */
5203 if (rc || (pSMBr->ByteCount < 4))
5204 rc = -EIO; /* bad smb */
5205 /* else if (pFindData){
5206 memcpy((char *) pFindData,
5207 (char *) &pSMBr->hdr.Protocol +
5210 /* check that length of list is not more than bcc */
5211 /* check that each entry does not go beyond length
5213 /* check that each element of each entry does not
5214 go beyond end of list */
5215 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5216 struct fealist *ea_response_data;
5218 /* validate_trans2_offsets() */
5219 /* BB check if start of smb + data_offset > &bcc+ bcc */
5220 ea_response_data = (struct fealist *)
5221 (((char *) &pSMBr->hdr.Protocol) +
5223 name_len = le32_to_cpu(ea_response_data->list_len);
5224 cFYI(1, ("ea length %d", name_len));
5225 if (name_len <= 8) {
5226 /* returned EA size zeroed at top of function */
5227 cFYI(1, ("empty EA list returned from server"));
5229 /* account for ea list len */
5231 temp_fea = ea_response_data->list;
5232 temp_ptr = (char *)temp_fea;
5233 while (name_len > 0) {
5237 rc += temp_fea->name_len;
5238 /* account for prefix user. and trailing null */
5240 if (rc < (int)buf_size) {
5241 memcpy(EAData, "user.", 5);
5243 memcpy(EAData, temp_ptr,
5244 temp_fea->name_len);
5245 EAData += temp_fea->name_len;
5246 /* null terminate name */
5248 EAData = EAData + 1;
5249 } else if (buf_size == 0) {
5250 /* skip copy - calc size only */
5252 /* stop before overrun buffer */
5256 name_len -= temp_fea->name_len;
5257 temp_ptr += temp_fea->name_len;
5258 /* account for trailing null */
5262 le16_to_cpu(temp_fea->value_len);
5263 name_len -= value_len;
5264 temp_ptr += value_len;
5265 /* BB check that temp_ptr is still
5268 /* no trailing null to account for
5270 /* go on to next EA */
5271 temp_fea = (struct fea *)temp_ptr;
5277 cifs_buf_release(pSMB);
5284 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5285 const unsigned char *searchName, const unsigned char *ea_name,
5286 unsigned char *ea_value, size_t buf_size,
5287 const struct nls_table *nls_codepage, int remap)
5289 TRANSACTION2_QPI_REQ *pSMB = NULL;
5290 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5294 struct fea *temp_fea;
5296 __u16 params, byte_count;
5298 cFYI(1, ("In Query EA path %s", searchName));
5300 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5305 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5307 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5308 PATH_MAX, nls_codepage, remap);
5309 name_len++; /* trailing null */
5311 } else { /* BB improve the check for buffer overruns BB */
5312 name_len = strnlen(searchName, PATH_MAX);
5313 name_len++; /* trailing null */
5314 strncpy(pSMB->FileName, searchName, name_len);
5317 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5318 pSMB->TotalDataCount = 0;
5319 pSMB->MaxParameterCount = cpu_to_le16(2);
5320 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5321 pSMB->MaxSetupCount = 0;
5325 pSMB->Reserved2 = 0;
5326 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5327 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5328 pSMB->DataCount = 0;
5329 pSMB->DataOffset = 0;
5330 pSMB->SetupCount = 1;
5331 pSMB->Reserved3 = 0;
5332 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5333 byte_count = params + 1 /* pad */ ;
5334 pSMB->TotalParameterCount = cpu_to_le16(params);
5335 pSMB->ParameterCount = pSMB->TotalParameterCount;
5336 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5337 pSMB->Reserved4 = 0;
5338 pSMB->hdr.smb_buf_length += byte_count;
5339 pSMB->ByteCount = cpu_to_le16(byte_count);
5341 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5342 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5344 cFYI(1, ("Send error in Query EA = %d", rc));
5345 } else { /* decode response */
5346 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5348 /* BB also check enough total bytes returned */
5349 /* BB we need to improve the validity checking
5350 of these trans2 responses */
5351 if (rc || (pSMBr->ByteCount < 4))
5352 rc = -EIO; /* bad smb */
5353 /* else if (pFindData){
5354 memcpy((char *) pFindData,
5355 (char *) &pSMBr->hdr.Protocol +
5358 /* check that length of list is not more than bcc */
5359 /* check that each entry does not go beyond length
5361 /* check that each element of each entry does not
5362 go beyond end of list */
5363 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5364 struct fealist *ea_response_data;
5366 /* validate_trans2_offsets() */
5367 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5368 ea_response_data = (struct fealist *)
5369 (((char *) &pSMBr->hdr.Protocol) +
5371 name_len = le32_to_cpu(ea_response_data->list_len);
5372 cFYI(1, ("ea length %d", name_len));
5373 if (name_len <= 8) {
5374 /* returned EA size zeroed at top of function */
5375 cFYI(1, ("empty EA list returned from server"));
5377 /* account for ea list len */
5379 temp_fea = ea_response_data->list;
5380 temp_ptr = (char *)temp_fea;
5381 /* loop through checking if we have a matching
5382 name and then return the associated value */
5383 while (name_len > 0) {
5388 le16_to_cpu(temp_fea->value_len);
5389 /* BB validate that value_len falls within SMB,
5390 even though maximum for name_len is 255 */
5391 if (memcmp(temp_fea->name, ea_name,
5392 temp_fea->name_len) == 0) {
5395 /* account for prefix user. and trailing null */
5396 if (rc <= (int)buf_size) {
5398 temp_fea->name+temp_fea->name_len+1,
5400 /* ea values, unlike ea
5403 } else if (buf_size == 0) {
5404 /* skip copy - calc size only */
5406 /* stop before overrun buffer */
5411 name_len -= temp_fea->name_len;
5412 temp_ptr += temp_fea->name_len;
5413 /* account for trailing null */
5416 name_len -= value_len;
5417 temp_ptr += value_len;
5418 /* No trailing null to account for in
5419 value_len. Go on to next EA */
5420 temp_fea = (struct fea *)temp_ptr;
5426 cifs_buf_release(pSMB);
5434 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5435 const char *ea_name, const void *ea_value,
5436 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5439 struct smb_com_transaction2_spi_req *pSMB = NULL;
5440 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5441 struct fealist *parm_data;
5444 int bytes_returned = 0;
5445 __u16 params, param_offset, byte_count, offset, count;
5447 cFYI(1, ("In SetEA"));
5449 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5454 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5456 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5457 PATH_MAX, nls_codepage, remap);
5458 name_len++; /* trailing null */
5460 } else { /* BB improve the check for buffer overruns BB */
5461 name_len = strnlen(fileName, PATH_MAX);
5462 name_len++; /* trailing null */
5463 strncpy(pSMB->FileName, fileName, name_len);
5466 params = 6 + name_len;
5468 /* done calculating parms using name_len of file name,
5469 now use name_len to calculate length of ea name
5470 we are going to create in the inode xattrs */
5471 if (ea_name == NULL)
5474 name_len = strnlen(ea_name, 255);
5476 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5477 pSMB->MaxParameterCount = cpu_to_le16(2);
5478 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5479 pSMB->MaxSetupCount = 0;
5483 pSMB->Reserved2 = 0;
5484 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5485 InformationLevel) - 4;
5486 offset = param_offset + params;
5487 pSMB->InformationLevel =
5488 cpu_to_le16(SMB_SET_FILE_EA);
5491 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5493 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5494 pSMB->DataOffset = cpu_to_le16(offset);
5495 pSMB->SetupCount = 1;
5496 pSMB->Reserved3 = 0;
5497 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5498 byte_count = 3 /* pad */ + params + count;
5499 pSMB->DataCount = cpu_to_le16(count);
5500 parm_data->list_len = cpu_to_le32(count);
5501 parm_data->list[0].EA_flags = 0;
5502 /* we checked above that name len is less than 255 */
5503 parm_data->list[0].name_len = (__u8)name_len;
5504 /* EA names are always ASCII */
5506 strncpy(parm_data->list[0].name, ea_name, name_len);
5507 parm_data->list[0].name[name_len] = 0;
5508 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5509 /* caller ensures that ea_value_len is less than 64K but
5510 we need to ensure that it fits within the smb */
5512 /*BB add length check to see if it would fit in
5513 negotiated SMB buffer size BB */
5514 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5516 memcpy(parm_data->list[0].name+name_len+1,
5517 ea_value, ea_value_len);
5519 pSMB->TotalDataCount = pSMB->DataCount;
5520 pSMB->ParameterCount = cpu_to_le16(params);
5521 pSMB->TotalParameterCount = pSMB->ParameterCount;
5522 pSMB->Reserved4 = 0;
5523 pSMB->hdr.smb_buf_length += byte_count;
5524 pSMB->ByteCount = cpu_to_le16(byte_count);
5525 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5526 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5528 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5531 cifs_buf_release(pSMB);