4 * Copyright (C) International Business Machines Corp., 2002,2007
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head *tmp;
91 struct list_head *tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
98 open_file->invalidHandle = TRUE;
100 write_unlock(&GlobalSMBSeslock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* If the return code is zero, this function must fill in request_buf pointer */
107 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
108 void **request_buf /* returned */)
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
113 check for tcp and smb session status done differently
114 for those three - in the calling routine */
116 if (tcon->tidStatus == CifsExiting) {
117 /* only tree disconnect, open, and write,
118 (and ulogoff which does not have tcon)
119 are allowed as we start force umount */
120 if ((smb_command != SMB_COM_WRITE_ANDX) &&
121 (smb_command != SMB_COM_OPEN_ANDX) &&
122 (smb_command != SMB_COM_TREE_DISCONNECT)) {
123 cFYI(1, ("can not send cmd %d while umounting",
128 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
129 (tcon->ses->server)) {
130 struct nls_table *nls_codepage;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while (tcon->ses->server->tcpStatus ==
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus ==
139 if (tcon->ses->server->tcpStatus ==
141 /* on "soft" mounts we wait once */
142 if ((tcon->retry == FALSE) ||
143 (tcon->ses->status == CifsExiting)) {
144 cFYI(1, ("gave up waiting on "
145 "reconnect in smb_init"));
147 } /* else "hard" mount - keep retrying
148 until process is killed or server
149 comes back on-line */
150 } else /* TCP session is reestablished now */
154 nls_codepage = load_nls_default();
155 /* need to prevent multiple threads trying to
156 simultaneously reconnect the same SMB session */
157 down(&tcon->ses->sesSem);
158 if (tcon->ses->status == CifsNeedReconnect)
159 rc = cifs_setup_session(0, tcon->ses,
161 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
162 mark_open_files_invalid(tcon);
163 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
165 up(&tcon->ses->sesSem);
166 /* tell server which Unix caps we support */
167 if (tcon->ses->capabilities & CAP_UNIX)
168 reset_cifs_unix_caps(0 /* no xid */,
170 NULL /* we do not know sb */,
171 NULL /* no vol info */);
172 /* BB FIXME add code to check if wsize needs
173 update due to negotiated smb buffer size
176 atomic_inc(&tconInfoReconnectCount);
178 cFYI(1, ("reconnect tcon rc = %d", rc));
179 /* Removed call to reopen open files here.
180 It is safer (and faster) to reopen files
181 one at a time as needed in read and write */
183 /* Check if handle based operation so we
184 know whether we can continue or not without
185 returning to caller to reset file handle */
186 switch (smb_command) {
187 case SMB_COM_READ_ANDX:
188 case SMB_COM_WRITE_ANDX:
190 case SMB_COM_FIND_CLOSE2:
191 case SMB_COM_LOCKING_ANDX: {
192 unload_nls(nls_codepage);
197 up(&tcon->ses->sesSem);
199 unload_nls(nls_codepage);
208 *request_buf = cifs_small_buf_get();
209 if (*request_buf == NULL) {
210 /* BB should we add a retry in here if not a writepage? */
214 header_assemble((struct smb_hdr *) *request_buf, smb_command,
218 cifs_stats_inc(&tcon->num_smbs_sent);
224 small_smb_init_no_tc(const int smb_command, const int wct,
225 struct cifsSesInfo *ses, void **request_buf)
228 struct smb_hdr *buffer;
230 rc = small_smb_init(smb_command, wct, NULL, request_buf);
234 buffer = (struct smb_hdr *)*request_buf;
235 buffer->Mid = GetNextMid(ses->server);
236 if (ses->capabilities & CAP_UNICODE)
237 buffer->Flags2 |= SMBFLG2_UNICODE;
238 if (ses->capabilities & CAP_STATUS32)
239 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
241 /* uid, tid can stay at zero as set in header assemble */
243 /* BB add support for turning on the signing when
244 this function is used after 1st of session setup requests */
249 /* If the return code is zero, this function must fill in request_buf pointer */
251 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
252 void **request_buf /* returned */ ,
253 void **response_buf /* returned */ )
257 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
258 check for tcp and smb session status done differently
259 for those three - in the calling routine */
261 if (tcon->tidStatus == CifsExiting) {
262 /* only tree disconnect, open, and write,
263 (and ulogoff which does not have tcon)
264 are allowed as we start force umount */
265 if ((smb_command != SMB_COM_WRITE_ANDX) &&
266 (smb_command != SMB_COM_OPEN_ANDX) &&
267 (smb_command != SMB_COM_TREE_DISCONNECT)) {
268 cFYI(1, ("can not send cmd %d while umounting",
274 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
275 (tcon->ses->server)) {
276 struct nls_table *nls_codepage;
277 /* Give Demultiplex thread up to 10 seconds to
278 reconnect, should be greater than cifs socket
279 timeout which is 7 seconds */
280 while (tcon->ses->server->tcpStatus ==
282 wait_event_interruptible_timeout(tcon->ses->server->response_q,
283 (tcon->ses->server->tcpStatus ==
285 if (tcon->ses->server->tcpStatus ==
287 /* on "soft" mounts we wait once */
288 if ((tcon->retry == FALSE) ||
289 (tcon->ses->status == CifsExiting)) {
290 cFYI(1, ("gave up waiting on "
291 "reconnect in smb_init"));
293 } /* else "hard" mount - keep retrying
294 until process is killed or server
296 } else /* TCP session is reestablished now */
299 nls_codepage = load_nls_default();
300 /* need to prevent multiple threads trying to
301 simultaneously reconnect the same SMB session */
302 down(&tcon->ses->sesSem);
303 if (tcon->ses->status == CifsNeedReconnect)
304 rc = cifs_setup_session(0, tcon->ses,
306 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
307 mark_open_files_invalid(tcon);
308 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
310 up(&tcon->ses->sesSem);
311 /* tell server which Unix caps we support */
312 if (tcon->ses->capabilities & CAP_UNIX)
313 reset_cifs_unix_caps(0 /* no xid */,
315 NULL /* do not know sb */,
316 NULL /* no vol info */);
317 /* BB FIXME add code to check if wsize needs
318 update due to negotiated smb buffer size
321 atomic_inc(&tconInfoReconnectCount);
323 cFYI(1, ("reconnect tcon rc = %d", rc));
324 /* Removed call to reopen open files here.
325 It is safer (and faster) to reopen files
326 one at a time as needed in read and write */
328 /* Check if handle based operation so we
329 know whether we can continue or not without
330 returning to caller to reset file handle */
331 switch (smb_command) {
332 case SMB_COM_READ_ANDX:
333 case SMB_COM_WRITE_ANDX:
335 case SMB_COM_FIND_CLOSE2:
336 case SMB_COM_LOCKING_ANDX: {
337 unload_nls(nls_codepage);
342 up(&tcon->ses->sesSem);
344 unload_nls(nls_codepage);
353 *request_buf = cifs_buf_get();
354 if (*request_buf == NULL) {
355 /* BB should we add a retry in here if not a writepage? */
358 /* Although the original thought was we needed the response buf for */
359 /* potential retries of smb operations it turns out we can determine */
360 /* from the mid flags when the request buffer can be resent without */
361 /* having to use a second distinct buffer for the response */
363 *response_buf = *request_buf;
365 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
369 cifs_stats_inc(&tcon->num_smbs_sent);
374 static int validate_t2(struct smb_t2_rsp *pSMB)
380 /* check for plausible wct, bcc and t2 data and parm sizes */
381 /* check for parm and data offset going beyond end of smb */
382 if (pSMB->hdr.WordCount >= 10) {
383 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
384 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
385 /* check that bcc is at least as big as parms + data */
386 /* check that bcc is less than negotiated smb buffer */
387 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
388 if (total_size < 512) {
390 le16_to_cpu(pSMB->t2_rsp.DataCount);
391 /* BCC le converted in SendReceive */
392 pBCC = (pSMB->hdr.WordCount * 2) +
393 sizeof(struct smb_hdr) +
395 if ((total_size <= (*(u16 *)pBCC)) &&
397 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
403 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
404 sizeof(struct smb_t2_rsp) + 16);
408 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
411 NEGOTIATE_RSP *pSMBr;
415 struct TCP_Server_Info *server;
417 unsigned int secFlags;
421 server = ses->server;
426 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
427 (void **) &pSMB, (void **) &pSMBr);
431 /* if any of auth flags (ie not sign or seal) are overriden use them */
432 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
433 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
434 else /* if override flags set only sign/seal OR them with global auth */
435 secFlags = extended_security | ses->overrideSecFlg;
437 cFYI(1, ("secFlags 0x%x", secFlags));
439 pSMB->hdr.Mid = GetNextMid(server);
440 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
442 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
443 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
444 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
445 cFYI(1, ("Kerberos only mechanism, enable extended security"));
446 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
450 for (i = 0; i < CIFS_NUM_PROT; i++) {
451 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
452 count += strlen(protocols[i].name) + 1;
453 /* null at end of source and target buffers anyway */
455 pSMB->hdr.smb_buf_length += count;
456 pSMB->ByteCount = cpu_to_le16(count);
458 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
459 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
463 dialect = le16_to_cpu(pSMBr->DialectIndex);
464 cFYI(1, ("Dialect: %d", dialect));
465 /* Check wct = 1 error case */
466 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
467 /* core returns wct = 1, but we do not ask for core - otherwise
468 small wct just comes when dialect index is -1 indicating we
469 could not negotiate a common dialect */
472 #ifdef CONFIG_CIFS_WEAK_PW_HASH
473 } else if ((pSMBr->hdr.WordCount == 13)
474 && ((dialect == LANMAN_PROT)
475 || (dialect == LANMAN2_PROT))) {
477 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
479 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
480 (secFlags & CIFSSEC_MAY_PLNTXT))
481 server->secType = LANMAN;
483 cERROR(1, ("mount failed weak security disabled"
484 " in /proc/fs/cifs/SecurityFlags"));
488 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
489 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
490 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
491 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
492 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
493 /* even though we do not use raw we might as well set this
494 accurately, in case we ever find a need for it */
495 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
496 server->maxRw = 0xFF00;
497 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
499 server->maxRw = 0;/* we do not need to use raw anyway */
500 server->capabilities = CAP_MPX_MODE;
502 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
504 /* OS/2 often does not set timezone therefore
505 * we must use server time to calc time zone.
506 * Could deviate slightly from the right zone.
507 * Smallest defined timezone difference is 15 minutes
508 * (i.e. Nepal). Rounding up/down is done to match
511 int val, seconds, remain, result;
512 struct timespec ts, utc;
514 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
515 le16_to_cpu(rsp->SrvTime.Time));
516 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
517 (int)ts.tv_sec, (int)utc.tv_sec,
518 (int)(utc.tv_sec - ts.tv_sec)));
519 val = (int)(utc.tv_sec - ts.tv_sec);
521 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
522 remain = seconds % MIN_TZ_ADJ;
523 if (remain >= (MIN_TZ_ADJ / 2))
524 result += MIN_TZ_ADJ;
527 server->timeAdj = result;
529 server->timeAdj = (int)tmp;
530 server->timeAdj *= 60; /* also in seconds */
532 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
535 /* BB get server time for time conversions and add
536 code to use it and timezone since this is not UTC */
538 if (rsp->EncryptionKeyLength ==
539 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
540 memcpy(server->cryptKey, rsp->EncryptionKey,
541 CIFS_CRYPTO_KEY_SIZE);
542 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
543 rc = -EIO; /* need cryptkey unless plain text */
547 cFYI(1, ("LANMAN negotiated"));
548 /* we will not end up setting signing flags - as no signing
549 was in LANMAN and server did not return the flags on */
551 #else /* weak security disabled */
552 } else if (pSMBr->hdr.WordCount == 13) {
553 cERROR(1, ("mount failed, cifs module not built "
554 "with CIFS_WEAK_PW_HASH support"));
556 #endif /* WEAK_PW_HASH */
558 } else if (pSMBr->hdr.WordCount != 17) {
563 /* else wct == 17 NTLM */
564 server->secMode = pSMBr->SecurityMode;
565 if ((server->secMode & SECMODE_USER) == 0)
566 cFYI(1, ("share mode security"));
568 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
569 #ifdef CONFIG_CIFS_WEAK_PW_HASH
570 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
571 #endif /* CIFS_WEAK_PW_HASH */
572 cERROR(1, ("Server requests plain text password"
573 " but client support disabled"));
575 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
576 server->secType = NTLMv2;
577 else if (secFlags & CIFSSEC_MAY_NTLM)
578 server->secType = NTLM;
579 else if (secFlags & CIFSSEC_MAY_NTLMV2)
580 server->secType = NTLMv2;
581 else if (secFlags & CIFSSEC_MAY_KRB5)
582 server->secType = Kerberos;
583 else if (secFlags & CIFSSEC_MAY_LANMAN)
584 server->secType = LANMAN;
585 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
586 else if (secFlags & CIFSSEC_MAY_PLNTXT)
591 cERROR(1, ("Invalid security type"));
594 /* else ... any others ...? */
596 /* one byte, so no need to convert this or EncryptionKeyLen from
598 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
599 /* probably no need to store and check maxvcs */
600 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
601 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
602 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
603 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
604 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
605 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
606 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
607 server->timeAdj *= 60;
608 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
609 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
610 CIFS_CRYPTO_KEY_SIZE);
611 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
612 && (pSMBr->EncryptionKeyLength == 0)) {
613 /* decode security blob */
614 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
615 rc = -EIO; /* no crypt key only if plain text pwd */
619 /* BB might be helpful to save off the domain of server here */
621 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
622 (server->capabilities & CAP_EXTENDED_SECURITY)) {
623 count = pSMBr->ByteCount;
629 if (server->socketUseCount.counter > 1) {
630 if (memcmp(server->server_GUID,
631 pSMBr->u.extended_response.
633 cFYI(1, ("server UID changed"));
634 memcpy(server->server_GUID,
635 pSMBr->u.extended_response.GUID,
639 memcpy(server->server_GUID,
640 pSMBr->u.extended_response.GUID, 16);
643 server->secType = RawNTLMSSP;
645 rc = decode_negTokenInit(pSMBr->u.extended_response.
650 /* BB Need to fill struct for sessetup here */
657 server->capabilities &= ~CAP_EXTENDED_SECURITY;
659 #ifdef CONFIG_CIFS_WEAK_PW_HASH
662 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
663 /* MUST_SIGN already includes the MAY_SIGN FLAG
664 so if this is zero it means that signing is disabled */
665 cFYI(1, ("Signing disabled"));
666 if (server->secMode & SECMODE_SIGN_REQUIRED)
667 cERROR(1, ("Server requires "
668 "packet signing to be enabled in "
669 "/proc/fs/cifs/SecurityFlags."));
671 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
672 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
673 /* signing required */
674 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
675 if ((server->secMode &
676 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
678 ("signing required but server lacks support"));
681 server->secMode |= SECMODE_SIGN_REQUIRED;
683 /* signing optional ie CIFSSEC_MAY_SIGN */
684 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
686 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
690 cifs_buf_release(pSMB);
692 cFYI(1, ("negprot rc %d", rc));
697 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
699 struct smb_hdr *smb_buffer;
700 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
704 cFYI(1, ("In tree disconnect"));
706 * If last user of the connection and
707 * connection alive - disconnect it
708 * If this is the last connection on the server session disconnect it
709 * (and inside session disconnect we should check if tcp socket needs
710 * to be freed and kernel thread woken up).
713 down(&tcon->tconSem);
717 atomic_dec(&tcon->useCount);
718 if (atomic_read(&tcon->useCount) > 0) {
723 /* No need to return error on this operation if tid invalidated and
724 closed on server already e.g. due to tcp session crashing */
725 if (tcon->tidStatus == CifsNeedReconnect) {
730 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
734 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
735 (void **)&smb_buffer);
740 smb_buffer_response = smb_buffer; /* BB removeme BB */
742 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
745 cFYI(1, ("Tree disconnect failed %d", rc));
748 cifs_small_buf_release(smb_buffer);
751 /* No need to return error on this operation if tid invalidated and
752 closed on server already e.g. due to tcp session crashing */
760 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
762 struct smb_hdr *smb_buffer_response;
763 LOGOFF_ANDX_REQ *pSMB;
767 cFYI(1, ("In SMBLogoff for session disconnect"));
773 atomic_dec(&ses->inUse);
774 if (atomic_read(&ses->inUse) > 0) {
778 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
784 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
787 pSMB->hdr.Mid = GetNextMid(ses->server);
789 if (ses->server->secMode &
790 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
791 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
794 pSMB->hdr.Uid = ses->Suid;
796 pSMB->AndXCommand = 0xFF;
797 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
798 smb_buffer_response, &length, 0);
800 atomic_dec(&ses->server->socketUseCount);
801 if (atomic_read(&ses->server->socketUseCount) == 0) {
802 spin_lock(&GlobalMid_Lock);
803 ses->server->tcpStatus = CifsExiting;
804 spin_unlock(&GlobalMid_Lock);
809 cifs_small_buf_release(pSMB);
811 /* if session dead then we do not need to do ulogoff,
812 since server closed smb session, no sense reporting
820 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
821 __u16 type, const struct nls_table *nls_codepage, int remap)
823 TRANSACTION2_SPI_REQ *pSMB = NULL;
824 TRANSACTION2_SPI_RSP *pSMBr = NULL;
825 struct unlink_psx_rq *pRqD;
828 int bytes_returned = 0;
829 __u16 params, param_offset, offset, byte_count;
831 cFYI(1, ("In POSIX delete"));
833 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
838 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
840 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
841 PATH_MAX, nls_codepage, remap);
842 name_len++; /* trailing null */
844 } else { /* BB add path length overrun check */
845 name_len = strnlen(fileName, PATH_MAX);
846 name_len++; /* trailing null */
847 strncpy(pSMB->FileName, fileName, name_len);
850 params = 6 + name_len;
851 pSMB->MaxParameterCount = cpu_to_le16(2);
852 pSMB->MaxDataCount = 0; /* BB double check this with jra */
853 pSMB->MaxSetupCount = 0;
858 param_offset = offsetof(struct smb_com_transaction2_spi_req,
859 InformationLevel) - 4;
860 offset = param_offset + params;
862 /* Setup pointer to Request Data (inode type) */
863 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
864 pRqD->type = cpu_to_le16(type);
865 pSMB->ParameterOffset = cpu_to_le16(param_offset);
866 pSMB->DataOffset = cpu_to_le16(offset);
867 pSMB->SetupCount = 1;
869 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
870 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
872 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
873 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
874 pSMB->ParameterCount = cpu_to_le16(params);
875 pSMB->TotalParameterCount = pSMB->ParameterCount;
876 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
878 pSMB->hdr.smb_buf_length += byte_count;
879 pSMB->ByteCount = cpu_to_le16(byte_count);
880 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
881 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
883 cFYI(1, ("Posix delete returned %d", rc));
885 cifs_buf_release(pSMB);
887 cifs_stats_inc(&tcon->num_deletes);
896 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
897 const struct nls_table *nls_codepage, int remap)
899 DELETE_FILE_REQ *pSMB = NULL;
900 DELETE_FILE_RSP *pSMBr = NULL;
906 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
911 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
913 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
914 PATH_MAX, nls_codepage, remap);
915 name_len++; /* trailing null */
917 } else { /* BB improve check for buffer overruns BB */
918 name_len = strnlen(fileName, PATH_MAX);
919 name_len++; /* trailing null */
920 strncpy(pSMB->fileName, fileName, name_len);
922 pSMB->SearchAttributes =
923 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
924 pSMB->BufferFormat = 0x04;
925 pSMB->hdr.smb_buf_length += name_len + 1;
926 pSMB->ByteCount = cpu_to_le16(name_len + 1);
927 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
928 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
929 cifs_stats_inc(&tcon->num_deletes);
931 cFYI(1, ("Error in RMFile = %d", rc));
934 cifs_buf_release(pSMB);
942 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
943 const struct nls_table *nls_codepage, int remap)
945 DELETE_DIRECTORY_REQ *pSMB = NULL;
946 DELETE_DIRECTORY_RSP *pSMBr = NULL;
951 cFYI(1, ("In CIFSSMBRmDir"));
953 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
958 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
959 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
960 PATH_MAX, nls_codepage, remap);
961 name_len++; /* trailing null */
963 } else { /* BB improve check for buffer overruns BB */
964 name_len = strnlen(dirName, PATH_MAX);
965 name_len++; /* trailing null */
966 strncpy(pSMB->DirName, dirName, name_len);
969 pSMB->BufferFormat = 0x04;
970 pSMB->hdr.smb_buf_length += name_len + 1;
971 pSMB->ByteCount = cpu_to_le16(name_len + 1);
972 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
973 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
974 cifs_stats_inc(&tcon->num_rmdirs);
976 cFYI(1, ("Error in RMDir = %d", rc));
979 cifs_buf_release(pSMB);
986 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
987 const char *name, const struct nls_table *nls_codepage, int remap)
990 CREATE_DIRECTORY_REQ *pSMB = NULL;
991 CREATE_DIRECTORY_RSP *pSMBr = NULL;
995 cFYI(1, ("In CIFSSMBMkDir"));
997 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1002 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1003 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1004 PATH_MAX, nls_codepage, remap);
1005 name_len++; /* trailing null */
1007 } else { /* BB improve check for buffer overruns BB */
1008 name_len = strnlen(name, PATH_MAX);
1009 name_len++; /* trailing null */
1010 strncpy(pSMB->DirName, name, name_len);
1013 pSMB->BufferFormat = 0x04;
1014 pSMB->hdr.smb_buf_length += name_len + 1;
1015 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1016 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1017 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1018 cifs_stats_inc(&tcon->num_mkdirs);
1020 cFYI(1, ("Error in Mkdir = %d", rc));
1023 cifs_buf_release(pSMB);
1030 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1031 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1032 __u32 *pOplock, const char *name,
1033 const struct nls_table *nls_codepage, int remap)
1035 TRANSACTION2_SPI_REQ *pSMB = NULL;
1036 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1039 int bytes_returned = 0;
1040 __u16 params, param_offset, offset, byte_count, count;
1041 OPEN_PSX_REQ * pdata;
1042 OPEN_PSX_RSP * psx_rsp;
1044 cFYI(1, ("In POSIX Create"));
1046 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1051 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1053 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1054 PATH_MAX, nls_codepage, remap);
1055 name_len++; /* trailing null */
1057 } else { /* BB improve the check for buffer overruns BB */
1058 name_len = strnlen(name, PATH_MAX);
1059 name_len++; /* trailing null */
1060 strncpy(pSMB->FileName, name, name_len);
1063 params = 6 + name_len;
1064 count = sizeof(OPEN_PSX_REQ);
1065 pSMB->MaxParameterCount = cpu_to_le16(2);
1066 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1067 pSMB->MaxSetupCount = 0;
1071 pSMB->Reserved2 = 0;
1072 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1073 InformationLevel) - 4;
1074 offset = param_offset + params;
1075 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1076 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1077 pdata->Permissions = cpu_to_le64(mode);
1078 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1079 pdata->OpenFlags = cpu_to_le32(*pOplock);
1080 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1081 pSMB->DataOffset = cpu_to_le16(offset);
1082 pSMB->SetupCount = 1;
1083 pSMB->Reserved3 = 0;
1084 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1085 byte_count = 3 /* pad */ + params + count;
1087 pSMB->DataCount = cpu_to_le16(count);
1088 pSMB->ParameterCount = cpu_to_le16(params);
1089 pSMB->TotalDataCount = pSMB->DataCount;
1090 pSMB->TotalParameterCount = pSMB->ParameterCount;
1091 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1092 pSMB->Reserved4 = 0;
1093 pSMB->hdr.smb_buf_length += byte_count;
1094 pSMB->ByteCount = cpu_to_le16(byte_count);
1095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1098 cFYI(1, ("Posix create returned %d", rc));
1099 goto psx_create_err;
1102 cFYI(1, ("copying inode info"));
1103 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1105 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1106 rc = -EIO; /* bad smb */
1107 goto psx_create_err;
1110 /* copy return information to pRetData */
1111 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1112 + le16_to_cpu(pSMBr->t2.DataOffset));
1114 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1116 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1117 /* Let caller know file was created so we can set the mode. */
1118 /* Do we care about the CreateAction in any other cases? */
1119 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1120 *pOplock |= CIFS_CREATE_ACTION;
1121 /* check to make sure response data is there */
1122 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1123 pRetData->Type = cpu_to_le32(-1); /* unknown */
1124 #ifdef CONFIG_CIFS_DEBUG2
1125 cFYI(1, ("unknown type"));
1128 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1129 + sizeof(FILE_UNIX_BASIC_INFO)) {
1130 cERROR(1, ("Open response data too small"));
1131 pRetData->Type = cpu_to_le32(-1);
1132 goto psx_create_err;
1134 memcpy((char *) pRetData,
1135 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1136 sizeof(FILE_UNIX_BASIC_INFO));
1140 cifs_buf_release(pSMB);
1142 cifs_stats_inc(&tcon->num_mkdirs);
1150 static __u16 convert_disposition(int disposition)
1154 switch (disposition) {
1155 case FILE_SUPERSEDE:
1156 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1159 ofun = SMBOPEN_OAPPEND;
1162 ofun = SMBOPEN_OCREATE;
1165 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1167 case FILE_OVERWRITE:
1168 ofun = SMBOPEN_OTRUNC;
1170 case FILE_OVERWRITE_IF:
1171 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1174 cFYI(1, ("unknown disposition %d", disposition));
1175 ofun = SMBOPEN_OAPPEND; /* regular open */
1181 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1182 const char *fileName, const int openDisposition,
1183 const int access_flags, const int create_options, __u16 * netfid,
1184 int *pOplock, FILE_ALL_INFO * pfile_info,
1185 const struct nls_table *nls_codepage, int remap)
1188 OPENX_REQ *pSMB = NULL;
1189 OPENX_RSP *pSMBr = NULL;
1195 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1200 pSMB->AndXCommand = 0xFF; /* none */
1202 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1203 count = 1; /* account for one byte pad to word boundary */
1205 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1206 fileName, PATH_MAX, nls_codepage, remap);
1207 name_len++; /* trailing null */
1209 } else { /* BB improve check for buffer overruns BB */
1210 count = 0; /* no pad */
1211 name_len = strnlen(fileName, PATH_MAX);
1212 name_len++; /* trailing null */
1213 strncpy(pSMB->fileName, fileName, name_len);
1215 if (*pOplock & REQ_OPLOCK)
1216 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1217 else if (*pOplock & REQ_BATCHOPLOCK)
1218 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1220 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1221 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1227 pSMB->Mode = cpu_to_le16(2);
1228 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1229 /* set file as system file if special file such
1230 as fifo and server expecting SFU style and
1231 no Unix extensions */
1233 if (create_options & CREATE_OPTION_SPECIAL)
1234 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1236 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1238 /* if ((omode & S_IWUGO) == 0)
1239 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1240 /* Above line causes problems due to vfs splitting create into two
1241 pieces - need to set mode after file created not while it is
1245 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1246 CREATE_OPTIONS_MASK); */
1247 /* BB FIXME END BB */
1249 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1250 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1252 pSMB->hdr.smb_buf_length += count;
1254 pSMB->ByteCount = cpu_to_le16(count);
1255 /* long_op set to 1 to allow for oplock break timeouts */
1256 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1258 cifs_stats_inc(&tcon->num_opens);
1260 cFYI(1, ("Error in Open = %d", rc));
1262 /* BB verify if wct == 15 */
1264 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1266 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1267 /* Let caller know file was created so we can set the mode. */
1268 /* Do we care about the CreateAction in any other cases? */
1270 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1271 *pOplock |= CIFS_CREATE_ACTION; */
1275 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1276 pfile_info->LastAccessTime = 0; /* BB fixme */
1277 pfile_info->LastWriteTime = 0; /* BB fixme */
1278 pfile_info->ChangeTime = 0; /* BB fixme */
1279 pfile_info->Attributes =
1280 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1281 /* the file_info buf is endian converted by caller */
1282 pfile_info->AllocationSize =
1283 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1284 pfile_info->EndOfFile = pfile_info->AllocationSize;
1285 pfile_info->NumberOfLinks = cpu_to_le32(1);
1289 cifs_buf_release(pSMB);
1296 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1297 const char *fileName, const int openDisposition,
1298 const int access_flags, const int create_options, __u16 * netfid,
1299 int *pOplock, FILE_ALL_INFO * pfile_info,
1300 const struct nls_table *nls_codepage, int remap)
1303 OPEN_REQ *pSMB = NULL;
1304 OPEN_RSP *pSMBr = NULL;
1310 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1315 pSMB->AndXCommand = 0xFF; /* none */
1317 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1318 count = 1; /* account for one byte pad to word boundary */
1320 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1321 fileName, PATH_MAX, nls_codepage, remap);
1322 name_len++; /* trailing null */
1324 pSMB->NameLength = cpu_to_le16(name_len);
1325 } else { /* BB improve check for buffer overruns BB */
1326 count = 0; /* no pad */
1327 name_len = strnlen(fileName, PATH_MAX);
1328 name_len++; /* trailing null */
1329 pSMB->NameLength = cpu_to_le16(name_len);
1330 strncpy(pSMB->fileName, fileName, name_len);
1332 if (*pOplock & REQ_OPLOCK)
1333 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1334 else if (*pOplock & REQ_BATCHOPLOCK)
1335 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1336 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1337 pSMB->AllocationSize = 0;
1338 /* set file as system file if special file such
1339 as fifo and server expecting SFU style and
1340 no Unix extensions */
1341 if (create_options & CREATE_OPTION_SPECIAL)
1342 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1344 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1345 /* XP does not handle ATTR_POSIX_SEMANTICS */
1346 /* but it helps speed up case sensitive checks for other
1347 servers such as Samba */
1348 if (tcon->ses->capabilities & CAP_UNIX)
1349 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1351 /* if ((omode & S_IWUGO) == 0)
1352 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1353 /* Above line causes problems due to vfs splitting create into two
1354 pieces - need to set mode after file created not while it is
1356 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1357 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1358 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1359 /* BB Expirement with various impersonation levels and verify */
1360 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1361 pSMB->SecurityFlags =
1362 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1365 pSMB->hdr.smb_buf_length += count;
1367 pSMB->ByteCount = cpu_to_le16(count);
1368 /* long_op set to 1 to allow for oplock break timeouts */
1369 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1370 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1371 cifs_stats_inc(&tcon->num_opens);
1373 cFYI(1, ("Error in Open = %d", rc));
1375 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1376 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1377 /* Let caller know file was created so we can set the mode. */
1378 /* Do we care about the CreateAction in any other cases? */
1379 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1380 *pOplock |= CIFS_CREATE_ACTION;
1382 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1383 36 /* CreationTime to Attributes */);
1384 /* the file_info buf is endian converted by caller */
1385 pfile_info->AllocationSize = pSMBr->AllocationSize;
1386 pfile_info->EndOfFile = pSMBr->EndOfFile;
1387 pfile_info->NumberOfLinks = cpu_to_le32(1);
1391 cifs_buf_release(pSMB);
1398 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1399 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1400 char **buf, int *pbuf_type)
1403 READ_REQ *pSMB = NULL;
1404 READ_RSP *pSMBr = NULL;
1405 char *pReadData = NULL;
1407 int resp_buf_type = 0;
1410 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1411 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1414 wct = 10; /* old style read */
1417 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1421 /* tcon and ses pointer are checked in smb_init */
1422 if (tcon->ses->server == NULL)
1423 return -ECONNABORTED;
1425 pSMB->AndXCommand = 0xFF; /* none */
1427 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1429 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1430 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1433 pSMB->Remaining = 0;
1434 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1435 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1437 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1439 /* old style read */
1440 struct smb_com_readx_req *pSMBW =
1441 (struct smb_com_readx_req *)pSMB;
1442 pSMBW->ByteCount = 0;
1445 iov[0].iov_base = (char *)pSMB;
1446 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1447 rc = SendReceive2(xid, tcon->ses, iov,
1450 cifs_stats_inc(&tcon->num_reads);
1451 pSMBr = (READ_RSP *)iov[0].iov_base;
1453 cERROR(1, ("Send error in read = %d", rc));
1455 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1456 data_length = data_length << 16;
1457 data_length += le16_to_cpu(pSMBr->DataLength);
1458 *nbytes = data_length;
1460 /*check that DataLength would not go beyond end of SMB */
1461 if ((data_length > CIFSMaxBufSize)
1462 || (data_length > count)) {
1463 cFYI(1, ("bad length %d for count %d",
1464 data_length, count));
1468 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1469 le16_to_cpu(pSMBr->DataOffset);
1470 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1471 cERROR(1,("Faulting on read rc = %d",rc));
1473 }*/ /* can not use copy_to_user when using page cache*/
1475 memcpy(*buf, pReadData, data_length);
1479 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1481 if (resp_buf_type == CIFS_SMALL_BUFFER)
1482 cifs_small_buf_release(iov[0].iov_base);
1483 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1484 cifs_buf_release(iov[0].iov_base);
1485 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1486 /* return buffer to caller to free */
1487 *buf = iov[0].iov_base;
1488 if (resp_buf_type == CIFS_SMALL_BUFFER)
1489 *pbuf_type = CIFS_SMALL_BUFFER;
1490 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1491 *pbuf_type = CIFS_LARGE_BUFFER;
1492 } /* else no valid buffer on return - leave as null */
1494 /* Note: On -EAGAIN error only caller can retry on handle based calls
1495 since file handle passed in no longer valid */
1501 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1502 const int netfid, const unsigned int count,
1503 const __u64 offset, unsigned int *nbytes, const char *buf,
1504 const char __user *ubuf, const int long_op)
1507 WRITE_REQ *pSMB = NULL;
1508 WRITE_RSP *pSMBr = NULL;
1509 int bytes_returned, wct;
1513 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1514 if (tcon->ses == NULL)
1515 return -ECONNABORTED;
1517 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1522 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1526 /* tcon and ses pointer are checked in smb_init */
1527 if (tcon->ses->server == NULL)
1528 return -ECONNABORTED;
1530 pSMB->AndXCommand = 0xFF; /* none */
1532 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1534 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1535 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1538 pSMB->Reserved = 0xFFFFFFFF;
1539 pSMB->WriteMode = 0;
1540 pSMB->Remaining = 0;
1542 /* Can increase buffer size if buffer is big enough in some cases ie we
1543 can send more if LARGE_WRITE_X capability returned by the server and if
1544 our buffer is big enough or if we convert to iovecs on socket writes
1545 and eliminate the copy to the CIFS buffer */
1546 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1547 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1549 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1553 if (bytes_sent > count)
1556 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1558 memcpy(pSMB->Data, buf, bytes_sent);
1560 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1561 cifs_buf_release(pSMB);
1564 } else if (count != 0) {
1566 cifs_buf_release(pSMB);
1568 } /* else setting file size with write of zero bytes */
1570 byte_count = bytes_sent + 1; /* pad */
1571 else /* wct == 12 */ {
1572 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1574 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1575 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1576 pSMB->hdr.smb_buf_length += byte_count;
1579 pSMB->ByteCount = cpu_to_le16(byte_count);
1580 else { /* old style write has byte count 4 bytes earlier
1582 struct smb_com_writex_req *pSMBW =
1583 (struct smb_com_writex_req *)pSMB;
1584 pSMBW->ByteCount = cpu_to_le16(byte_count);
1587 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1588 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1589 cifs_stats_inc(&tcon->num_writes);
1591 cFYI(1, ("Send error in write = %d", rc));
1594 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1595 *nbytes = (*nbytes) << 16;
1596 *nbytes += le16_to_cpu(pSMBr->Count);
1599 cifs_buf_release(pSMB);
1601 /* Note: On -EAGAIN error only caller can retry on handle based calls
1602 since file handle passed in no longer valid */
1608 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1609 const int netfid, const unsigned int count,
1610 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1611 int n_vec, const int long_op)
1614 WRITE_REQ *pSMB = NULL;
1617 int resp_buf_type = 0;
1619 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1621 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1625 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1628 /* tcon and ses pointer are checked in smb_init */
1629 if (tcon->ses->server == NULL)
1630 return -ECONNABORTED;
1632 pSMB->AndXCommand = 0xFF; /* none */
1634 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1636 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1637 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1639 pSMB->Reserved = 0xFFFFFFFF;
1640 pSMB->WriteMode = 0;
1641 pSMB->Remaining = 0;
1644 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1646 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1647 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1648 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1650 pSMB->hdr.smb_buf_length += count+1;
1651 else /* wct == 12 */
1652 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1654 pSMB->ByteCount = cpu_to_le16(count + 1);
1655 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1656 struct smb_com_writex_req *pSMBW =
1657 (struct smb_com_writex_req *)pSMB;
1658 pSMBW->ByteCount = cpu_to_le16(count + 5);
1660 iov[0].iov_base = pSMB;
1662 iov[0].iov_len = smb_hdr_len + 4;
1663 else /* wct == 12 pad bigger by four bytes */
1664 iov[0].iov_len = smb_hdr_len + 8;
1667 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1669 cifs_stats_inc(&tcon->num_writes);
1671 cFYI(1, ("Send error Write2 = %d", rc));
1673 } else if (resp_buf_type == 0) {
1674 /* presumably this can not happen, but best to be safe */
1678 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1679 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1680 *nbytes = (*nbytes) << 16;
1681 *nbytes += le16_to_cpu(pSMBr->Count);
1684 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1685 if (resp_buf_type == CIFS_SMALL_BUFFER)
1686 cifs_small_buf_release(iov[0].iov_base);
1687 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1688 cifs_buf_release(iov[0].iov_base);
1690 /* Note: On -EAGAIN error only caller can retry on handle based calls
1691 since file handle passed in no longer valid */
1698 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1699 const __u16 smb_file_id, const __u64 len,
1700 const __u64 offset, const __u32 numUnlock,
1701 const __u32 numLock, const __u8 lockType, const int waitFlag)
1704 LOCK_REQ *pSMB = NULL;
1705 LOCK_RSP *pSMBr = NULL;
1710 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1711 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1716 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1718 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1719 timeout = -1; /* no response expected */
1721 } else if (waitFlag == TRUE) {
1722 timeout = 3; /* blocking operation, no timeout */
1723 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1728 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1729 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1730 pSMB->LockType = lockType;
1731 pSMB->AndXCommand = 0xFF; /* none */
1732 pSMB->Fid = smb_file_id; /* netfid stays le */
1734 if ((numLock != 0) || (numUnlock != 0)) {
1735 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1736 /* BB where to store pid high? */
1737 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1738 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1739 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1740 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1741 count = sizeof(LOCKING_ANDX_RANGE);
1746 pSMB->hdr.smb_buf_length += count;
1747 pSMB->ByteCount = cpu_to_le16(count);
1750 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1751 (struct smb_hdr *) pSMBr, &bytes_returned);
1753 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1754 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1756 cifs_stats_inc(&tcon->num_locks);
1758 cFYI(1, ("Send error in Lock = %d", rc));
1760 cifs_small_buf_release(pSMB);
1762 /* Note: On -EAGAIN error only caller can retry on handle based calls
1763 since file handle passed in no longer valid */
1768 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1769 const __u16 smb_file_id, const int get_flag, const __u64 len,
1770 struct file_lock *pLockData, const __u16 lock_type,
1773 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1774 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1775 struct cifs_posix_lock *parm_data;
1778 int bytes_returned = 0;
1779 __u16 params, param_offset, offset, byte_count, count;
1781 cFYI(1, ("Posix Lock"));
1783 if (pLockData == NULL)
1786 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1791 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1794 pSMB->MaxSetupCount = 0;
1797 pSMB->Reserved2 = 0;
1798 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1799 offset = param_offset + params;
1801 count = sizeof(struct cifs_posix_lock);
1802 pSMB->MaxParameterCount = cpu_to_le16(2);
1803 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1804 pSMB->SetupCount = 1;
1805 pSMB->Reserved3 = 0;
1807 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1809 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1810 byte_count = 3 /* pad */ + params + count;
1811 pSMB->DataCount = cpu_to_le16(count);
1812 pSMB->ParameterCount = cpu_to_le16(params);
1813 pSMB->TotalDataCount = pSMB->DataCount;
1814 pSMB->TotalParameterCount = pSMB->ParameterCount;
1815 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1816 parm_data = (struct cifs_posix_lock *)
1817 (((char *) &pSMB->hdr.Protocol) + offset);
1819 parm_data->lock_type = cpu_to_le16(lock_type);
1821 timeout = 3; /* blocking operation, no timeout */
1822 parm_data->lock_flags = cpu_to_le16(1);
1823 pSMB->Timeout = cpu_to_le32(-1);
1827 parm_data->pid = cpu_to_le32(current->tgid);
1828 parm_data->start = cpu_to_le64(pLockData->fl_start);
1829 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1831 pSMB->DataOffset = cpu_to_le16(offset);
1832 pSMB->Fid = smb_file_id;
1833 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1834 pSMB->Reserved4 = 0;
1835 pSMB->hdr.smb_buf_length += byte_count;
1836 pSMB->ByteCount = cpu_to_le16(byte_count);
1838 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1839 (struct smb_hdr *) pSMBr, &bytes_returned);
1841 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1842 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1846 cFYI(1, ("Send error in Posix Lock = %d", rc));
1847 } else if (get_flag) {
1848 /* lock structure can be returned on get */
1851 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1853 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1854 rc = -EIO; /* bad smb */
1857 if (pLockData == NULL) {
1861 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1862 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1863 if (data_count < sizeof(struct cifs_posix_lock)) {
1867 parm_data = (struct cifs_posix_lock *)
1868 ((char *)&pSMBr->hdr.Protocol + data_offset);
1869 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1870 pLockData->fl_type = F_UNLCK;
1875 cifs_small_buf_release(pSMB);
1877 /* Note: On -EAGAIN error only caller can retry on handle based calls
1878 since file handle passed in no longer valid */
1885 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1888 CLOSE_REQ *pSMB = NULL;
1889 CLOSE_RSP *pSMBr = NULL;
1891 cFYI(1, ("In CIFSSMBClose"));
1893 /* do not retry on dead session on close */
1894 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1900 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1902 pSMB->FileID = (__u16) smb_file_id;
1903 pSMB->LastWriteTime = 0xFFFFFFFF;
1904 pSMB->ByteCount = 0;
1905 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1906 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1907 cifs_stats_inc(&tcon->num_closes);
1910 /* EINTR is expected when user ctl-c to kill app */
1911 cERROR(1, ("Send error in Close = %d", rc));
1915 cifs_small_buf_release(pSMB);
1917 /* Since session is dead, file will be closed on server already */
1925 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1926 const char *fromName, const char *toName,
1927 const struct nls_table *nls_codepage, int remap)
1930 RENAME_REQ *pSMB = NULL;
1931 RENAME_RSP *pSMBr = NULL;
1933 int name_len, name_len2;
1936 cFYI(1, ("In CIFSSMBRename"));
1938 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1943 pSMB->BufferFormat = 0x04;
1944 pSMB->SearchAttributes =
1945 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1948 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1950 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1951 PATH_MAX, nls_codepage, remap);
1952 name_len++; /* trailing null */
1954 pSMB->OldFileName[name_len] = 0x04; /* pad */
1955 /* protocol requires ASCII signature byte on Unicode string */
1956 pSMB->OldFileName[name_len + 1] = 0x00;
1958 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1959 toName, PATH_MAX, nls_codepage, remap);
1960 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1961 name_len2 *= 2; /* convert to bytes */
1962 } else { /* BB improve the check for buffer overruns BB */
1963 name_len = strnlen(fromName, PATH_MAX);
1964 name_len++; /* trailing null */
1965 strncpy(pSMB->OldFileName, fromName, name_len);
1966 name_len2 = strnlen(toName, PATH_MAX);
1967 name_len2++; /* trailing null */
1968 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1969 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1970 name_len2++; /* trailing null */
1971 name_len2++; /* signature byte */
1974 count = 1 /* 1st signature byte */ + name_len + name_len2;
1975 pSMB->hdr.smb_buf_length += count;
1976 pSMB->ByteCount = cpu_to_le16(count);
1978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1980 cifs_stats_inc(&tcon->num_renames);
1982 cFYI(1, ("Send error in rename = %d", rc));
1985 cifs_buf_release(pSMB);
1993 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1994 int netfid, char *target_name,
1995 const struct nls_table *nls_codepage, int remap)
1997 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1998 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1999 struct set_file_rename *rename_info;
2001 char dummy_string[30];
2003 int bytes_returned = 0;
2005 __u16 params, param_offset, offset, count, byte_count;
2007 cFYI(1, ("Rename to File by handle"));
2008 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2014 pSMB->MaxSetupCount = 0;
2018 pSMB->Reserved2 = 0;
2019 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2020 offset = param_offset + params;
2022 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2023 rename_info = (struct set_file_rename *) data_offset;
2024 pSMB->MaxParameterCount = cpu_to_le16(2);
2025 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2026 pSMB->SetupCount = 1;
2027 pSMB->Reserved3 = 0;
2028 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2029 byte_count = 3 /* pad */ + params;
2030 pSMB->ParameterCount = cpu_to_le16(params);
2031 pSMB->TotalParameterCount = pSMB->ParameterCount;
2032 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2033 pSMB->DataOffset = cpu_to_le16(offset);
2034 /* construct random name ".cifs_tmp<inodenum><mid>" */
2035 rename_info->overwrite = cpu_to_le32(1);
2036 rename_info->root_fid = 0;
2037 /* unicode only call */
2038 if (target_name == NULL) {
2039 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2040 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2041 dummy_string, 24, nls_codepage, remap);
2043 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2044 target_name, PATH_MAX, nls_codepage,
2047 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2048 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2049 byte_count += count;
2050 pSMB->DataCount = cpu_to_le16(count);
2051 pSMB->TotalDataCount = pSMB->DataCount;
2053 pSMB->InformationLevel =
2054 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2055 pSMB->Reserved4 = 0;
2056 pSMB->hdr.smb_buf_length += byte_count;
2057 pSMB->ByteCount = cpu_to_le16(byte_count);
2058 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2059 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2060 cifs_stats_inc(&pTcon->num_t2renames);
2062 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2065 cifs_buf_release(pSMB);
2067 /* Note: On -EAGAIN error only caller can retry on handle based calls
2068 since file handle passed in no longer valid */
2074 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2075 const __u16 target_tid, const char *toName, const int flags,
2076 const struct nls_table *nls_codepage, int remap)
2079 COPY_REQ *pSMB = NULL;
2080 COPY_RSP *pSMBr = NULL;
2082 int name_len, name_len2;
2085 cFYI(1, ("In CIFSSMBCopy"));
2087 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2092 pSMB->BufferFormat = 0x04;
2093 pSMB->Tid2 = target_tid;
2095 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2097 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2098 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2099 fromName, PATH_MAX, nls_codepage,
2101 name_len++; /* trailing null */
2103 pSMB->OldFileName[name_len] = 0x04; /* pad */
2104 /* protocol requires ASCII signature byte on Unicode string */
2105 pSMB->OldFileName[name_len + 1] = 0x00;
2107 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2108 toName, PATH_MAX, nls_codepage, remap);
2109 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2110 name_len2 *= 2; /* convert to bytes */
2111 } else { /* BB improve the check for buffer overruns BB */
2112 name_len = strnlen(fromName, PATH_MAX);
2113 name_len++; /* trailing null */
2114 strncpy(pSMB->OldFileName, fromName, name_len);
2115 name_len2 = strnlen(toName, PATH_MAX);
2116 name_len2++; /* trailing null */
2117 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2118 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2119 name_len2++; /* trailing null */
2120 name_len2++; /* signature byte */
2123 count = 1 /* 1st signature byte */ + name_len + name_len2;
2124 pSMB->hdr.smb_buf_length += count;
2125 pSMB->ByteCount = cpu_to_le16(count);
2127 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2128 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2130 cFYI(1, ("Send error in copy = %d with %d files copied",
2131 rc, le16_to_cpu(pSMBr->CopyCount)));
2134 cifs_buf_release(pSMB);
2143 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2144 const char *fromName, const char *toName,
2145 const struct nls_table *nls_codepage)
2147 TRANSACTION2_SPI_REQ *pSMB = NULL;
2148 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2151 int name_len_target;
2153 int bytes_returned = 0;
2154 __u16 params, param_offset, offset, byte_count;
2156 cFYI(1, ("In Symlink Unix style"));
2158 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2163 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2165 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2166 /* find define for this maxpathcomponent */
2168 name_len++; /* trailing null */
2171 } else { /* BB improve the check for buffer overruns BB */
2172 name_len = strnlen(fromName, PATH_MAX);
2173 name_len++; /* trailing null */
2174 strncpy(pSMB->FileName, fromName, name_len);
2176 params = 6 + name_len;
2177 pSMB->MaxSetupCount = 0;
2181 pSMB->Reserved2 = 0;
2182 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2183 InformationLevel) - 4;
2184 offset = param_offset + params;
2186 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2187 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2189 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2190 /* find define for this maxpathcomponent */
2192 name_len_target++; /* trailing null */
2193 name_len_target *= 2;
2194 } else { /* BB improve the check for buffer overruns BB */
2195 name_len_target = strnlen(toName, PATH_MAX);
2196 name_len_target++; /* trailing null */
2197 strncpy(data_offset, toName, name_len_target);
2200 pSMB->MaxParameterCount = cpu_to_le16(2);
2201 /* BB find exact max on data count below from sess */
2202 pSMB->MaxDataCount = cpu_to_le16(1000);
2203 pSMB->SetupCount = 1;
2204 pSMB->Reserved3 = 0;
2205 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2206 byte_count = 3 /* pad */ + params + name_len_target;
2207 pSMB->DataCount = cpu_to_le16(name_len_target);
2208 pSMB->ParameterCount = cpu_to_le16(params);
2209 pSMB->TotalDataCount = pSMB->DataCount;
2210 pSMB->TotalParameterCount = pSMB->ParameterCount;
2211 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2212 pSMB->DataOffset = cpu_to_le16(offset);
2213 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2214 pSMB->Reserved4 = 0;
2215 pSMB->hdr.smb_buf_length += byte_count;
2216 pSMB->ByteCount = cpu_to_le16(byte_count);
2217 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2218 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2219 cifs_stats_inc(&tcon->num_symlinks);
2221 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2225 cifs_buf_release(pSMB);
2228 goto createSymLinkRetry;
2234 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2235 const char *fromName, const char *toName,
2236 const struct nls_table *nls_codepage, int remap)
2238 TRANSACTION2_SPI_REQ *pSMB = NULL;
2239 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2242 int name_len_target;
2244 int bytes_returned = 0;
2245 __u16 params, param_offset, offset, byte_count;
2247 cFYI(1, ("In Create Hard link Unix style"));
2248 createHardLinkRetry:
2249 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2254 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2255 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2256 PATH_MAX, nls_codepage, remap);
2257 name_len++; /* trailing null */
2260 } else { /* BB improve the check for buffer overruns BB */
2261 name_len = strnlen(toName, PATH_MAX);
2262 name_len++; /* trailing null */
2263 strncpy(pSMB->FileName, toName, name_len);
2265 params = 6 + name_len;
2266 pSMB->MaxSetupCount = 0;
2270 pSMB->Reserved2 = 0;
2271 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2272 InformationLevel) - 4;
2273 offset = param_offset + params;
2275 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2276 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2278 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2279 nls_codepage, remap);
2280 name_len_target++; /* trailing null */
2281 name_len_target *= 2;
2282 } else { /* BB improve the check for buffer overruns BB */
2283 name_len_target = strnlen(fromName, PATH_MAX);
2284 name_len_target++; /* trailing null */
2285 strncpy(data_offset, fromName, name_len_target);
2288 pSMB->MaxParameterCount = cpu_to_le16(2);
2289 /* BB find exact max on data count below from sess*/
2290 pSMB->MaxDataCount = cpu_to_le16(1000);
2291 pSMB->SetupCount = 1;
2292 pSMB->Reserved3 = 0;
2293 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2294 byte_count = 3 /* pad */ + params + name_len_target;
2295 pSMB->ParameterCount = cpu_to_le16(params);
2296 pSMB->TotalParameterCount = pSMB->ParameterCount;
2297 pSMB->DataCount = cpu_to_le16(name_len_target);
2298 pSMB->TotalDataCount = pSMB->DataCount;
2299 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2300 pSMB->DataOffset = cpu_to_le16(offset);
2301 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2302 pSMB->Reserved4 = 0;
2303 pSMB->hdr.smb_buf_length += byte_count;
2304 pSMB->ByteCount = cpu_to_le16(byte_count);
2305 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2306 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2307 cifs_stats_inc(&tcon->num_hardlinks);
2309 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2312 cifs_buf_release(pSMB);
2314 goto createHardLinkRetry;
2320 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2321 const char *fromName, const char *toName,
2322 const struct nls_table *nls_codepage, int remap)
2325 NT_RENAME_REQ *pSMB = NULL;
2326 RENAME_RSP *pSMBr = NULL;
2328 int name_len, name_len2;
2331 cFYI(1, ("In CIFSCreateHardLink"));
2332 winCreateHardLinkRetry:
2334 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2339 pSMB->SearchAttributes =
2340 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2342 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2343 pSMB->ClusterCount = 0;
2345 pSMB->BufferFormat = 0x04;
2347 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2349 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2350 PATH_MAX, nls_codepage, remap);
2351 name_len++; /* trailing null */
2353 pSMB->OldFileName[name_len] = 0; /* pad */
2354 pSMB->OldFileName[name_len + 1] = 0x04;
2356 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2357 toName, PATH_MAX, nls_codepage, remap);
2358 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2359 name_len2 *= 2; /* convert to bytes */
2360 } else { /* BB improve the check for buffer overruns BB */
2361 name_len = strnlen(fromName, PATH_MAX);
2362 name_len++; /* trailing null */
2363 strncpy(pSMB->OldFileName, fromName, name_len);
2364 name_len2 = strnlen(toName, PATH_MAX);
2365 name_len2++; /* trailing null */
2366 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2367 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2368 name_len2++; /* trailing null */
2369 name_len2++; /* signature byte */
2372 count = 1 /* string type byte */ + name_len + name_len2;
2373 pSMB->hdr.smb_buf_length += count;
2374 pSMB->ByteCount = cpu_to_le16(count);
2376 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2377 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2378 cifs_stats_inc(&tcon->num_hardlinks);
2380 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2382 cifs_buf_release(pSMB);
2384 goto winCreateHardLinkRetry;
2390 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2391 const unsigned char *searchName,
2392 char *symlinkinfo, const int buflen,
2393 const struct nls_table *nls_codepage)
2395 /* SMB_QUERY_FILE_UNIX_LINK */
2396 TRANSACTION2_QPI_REQ *pSMB = NULL;
2397 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2401 __u16 params, byte_count;
2403 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2406 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2411 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2413 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2414 PATH_MAX, nls_codepage);
2415 name_len++; /* trailing null */
2417 } else { /* BB improve the check for buffer overruns BB */
2418 name_len = strnlen(searchName, PATH_MAX);
2419 name_len++; /* trailing null */
2420 strncpy(pSMB->FileName, searchName, name_len);
2423 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2424 pSMB->TotalDataCount = 0;
2425 pSMB->MaxParameterCount = cpu_to_le16(2);
2426 /* BB find exact max data count below from sess structure BB */
2427 pSMB->MaxDataCount = cpu_to_le16(4000);
2428 pSMB->MaxSetupCount = 0;
2432 pSMB->Reserved2 = 0;
2433 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2434 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2435 pSMB->DataCount = 0;
2436 pSMB->DataOffset = 0;
2437 pSMB->SetupCount = 1;
2438 pSMB->Reserved3 = 0;
2439 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2440 byte_count = params + 1 /* pad */ ;
2441 pSMB->TotalParameterCount = cpu_to_le16(params);
2442 pSMB->ParameterCount = pSMB->TotalParameterCount;
2443 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2444 pSMB->Reserved4 = 0;
2445 pSMB->hdr.smb_buf_length += byte_count;
2446 pSMB->ByteCount = cpu_to_le16(byte_count);
2448 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2449 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2451 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2453 /* decode response */
2455 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2456 if (rc || (pSMBr->ByteCount < 2))
2457 /* BB also check enough total bytes returned */
2458 rc = -EIO; /* bad smb */
2460 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2461 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2463 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2464 name_len = UniStrnlen((wchar_t *) ((char *)
2465 &pSMBr->hdr.Protocol + data_offset),
2466 min_t(const int, buflen, count) / 2);
2467 /* BB FIXME investigate remapping reserved chars here */
2468 cifs_strfromUCS_le(symlinkinfo,
2469 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2471 name_len, nls_codepage);
2473 strncpy(symlinkinfo,
2474 (char *) &pSMBr->hdr.Protocol +
2476 min_t(const int, buflen, count));
2478 symlinkinfo[buflen] = 0;
2479 /* just in case so calling code does not go off the end of buffer */
2482 cifs_buf_release(pSMB);
2484 goto querySymLinkRetry;
2488 /* Initialize NT TRANSACT SMB into small smb request buffer.
2489 This assumes that all NT TRANSACTS that we init here have
2490 total parm and data under about 400 bytes (to fit in small cifs
2491 buffer size), which is the case so far, it easily fits. NB:
2492 Setup words themselves and ByteCount
2493 MaxSetupCount (size of returned setup area) and
2494 MaxParameterCount (returned parms size) must be set by caller */
2496 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2497 const int parm_len, struct cifsTconInfo *tcon,
2502 struct smb_com_ntransact_req *pSMB;
2504 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2508 *ret_buf = (void *)pSMB;
2510 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2511 pSMB->TotalDataCount = 0;
2512 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2513 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2514 pSMB->ParameterCount = pSMB->TotalParameterCount;
2515 pSMB->DataCount = pSMB->TotalDataCount;
2516 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2517 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2518 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2519 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2520 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2521 pSMB->SubCommand = cpu_to_le16(sub_command);
2526 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2527 int *pdatalen, int *pparmlen)
2530 __u32 data_count, data_offset, parm_count, parm_offset;
2531 struct smb_com_ntransact_rsp *pSMBr;
2536 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2538 /* ByteCount was converted from little endian in SendReceive */
2539 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2540 (char *)&pSMBr->ByteCount;
2542 data_offset = le32_to_cpu(pSMBr->DataOffset);
2543 data_count = le32_to_cpu(pSMBr->DataCount);
2544 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2545 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2547 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2548 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2550 /* should we also check that parm and data areas do not overlap? */
2551 if (*ppparm > end_of_smb) {
2552 cFYI(1, ("parms start after end of smb"));
2554 } else if (parm_count + *ppparm > end_of_smb) {
2555 cFYI(1, ("parm end after end of smb"));
2557 } else if (*ppdata > end_of_smb) {
2558 cFYI(1, ("data starts after end of smb"));
2560 } else if (data_count + *ppdata > end_of_smb) {
2561 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2562 *ppdata, data_count, (data_count + *ppdata),
2563 end_of_smb, pSMBr));
2565 } else if (parm_count + data_count > pSMBr->ByteCount) {
2566 cFYI(1, ("parm count and data count larger than SMB"));
2573 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2574 const unsigned char *searchName,
2575 char *symlinkinfo, const int buflen, __u16 fid,
2576 const struct nls_table *nls_codepage)
2581 struct smb_com_transaction_ioctl_req *pSMB;
2582 struct smb_com_transaction_ioctl_rsp *pSMBr;
2584 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2585 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2590 pSMB->TotalParameterCount = 0 ;
2591 pSMB->TotalDataCount = 0;
2592 pSMB->MaxParameterCount = cpu_to_le32(2);
2593 /* BB find exact data count max from sess structure BB */
2594 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2595 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2596 pSMB->MaxSetupCount = 4;
2598 pSMB->ParameterOffset = 0;
2599 pSMB->DataCount = 0;
2600 pSMB->DataOffset = 0;
2601 pSMB->SetupCount = 4;
2602 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2603 pSMB->ParameterCount = pSMB->TotalParameterCount;
2604 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2605 pSMB->IsFsctl = 1; /* FSCTL */
2606 pSMB->IsRootFlag = 0;
2607 pSMB->Fid = fid; /* file handle always le */
2608 pSMB->ByteCount = 0;
2610 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2611 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2613 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2614 } else { /* decode response */
2615 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2616 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2617 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2618 /* BB also check enough total bytes returned */
2619 rc = -EIO; /* bad smb */
2621 if (data_count && (data_count < 2048)) {
2622 char *end_of_smb = 2 /* sizeof byte count */ +
2624 (char *)&pSMBr->ByteCount;
2626 struct reparse_data *reparse_buf =
2627 (struct reparse_data *)
2628 ((char *)&pSMBr->hdr.Protocol
2630 if ((char *)reparse_buf >= end_of_smb) {
2634 if ((reparse_buf->LinkNamesBuf +
2635 reparse_buf->TargetNameOffset +
2636 reparse_buf->TargetNameLen) >
2638 cFYI(1, ("reparse buf beyond SMB"));
2643 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2644 name_len = UniStrnlen((wchar_t *)
2645 (reparse_buf->LinkNamesBuf +
2646 reparse_buf->TargetNameOffset),
2648 reparse_buf->TargetNameLen / 2));
2649 cifs_strfromUCS_le(symlinkinfo,
2650 (__le16 *) (reparse_buf->LinkNamesBuf +
2651 reparse_buf->TargetNameOffset),
2652 name_len, nls_codepage);
2653 } else { /* ASCII names */
2654 strncpy(symlinkinfo,
2655 reparse_buf->LinkNamesBuf +
2656 reparse_buf->TargetNameOffset,
2657 min_t(const int, buflen,
2658 reparse_buf->TargetNameLen));
2662 cFYI(1, ("Invalid return data count on "
2663 "get reparse info ioctl"));
2665 symlinkinfo[buflen] = 0; /* just in case so the caller
2666 does not go off the end of the buffer */
2667 cFYI(1, ("readlink result - %s", symlinkinfo));
2671 cifs_buf_release(pSMB);
2673 /* Note: On -EAGAIN error only caller can retry on handle based calls
2674 since file handle passed in no longer valid */
2679 #ifdef CONFIG_CIFS_POSIX
2681 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2682 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2683 struct cifs_posix_ace *cifs_ace)
2685 /* u8 cifs fields do not need le conversion */
2686 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2687 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2688 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2689 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2694 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2695 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2696 const int acl_type, const int size_of_data_area)
2701 struct cifs_posix_ace *pACE;
2702 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2703 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2705 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2708 if (acl_type & ACL_TYPE_ACCESS) {
2709 count = le16_to_cpu(cifs_acl->access_entry_count);
2710 pACE = &cifs_acl->ace_array[0];
2711 size = sizeof(struct cifs_posix_acl);
2712 size += sizeof(struct cifs_posix_ace) * count;
2713 /* check if we would go beyond end of SMB */
2714 if (size_of_data_area < size) {
2715 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2716 size_of_data_area, size));
2719 } else if (acl_type & ACL_TYPE_DEFAULT) {
2720 count = le16_to_cpu(cifs_acl->access_entry_count);
2721 size = sizeof(struct cifs_posix_acl);
2722 size += sizeof(struct cifs_posix_ace) * count;
2723 /* skip past access ACEs to get to default ACEs */
2724 pACE = &cifs_acl->ace_array[count];
2725 count = le16_to_cpu(cifs_acl->default_entry_count);
2726 size += sizeof(struct cifs_posix_ace) * count;
2727 /* check if we would go beyond end of SMB */
2728 if (size_of_data_area < size)
2735 size = posix_acl_xattr_size(count);
2736 if ((buflen == 0) || (local_acl == NULL)) {
2737 /* used to query ACL EA size */
2738 } else if (size > buflen) {
2740 } else /* buffer big enough */ {
2741 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2742 for (i = 0; i < count ; i++) {
2743 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2750 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2751 const posix_acl_xattr_entry *local_ace)
2753 __u16 rc = 0; /* 0 = ACL converted ok */
2755 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2756 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2757 /* BB is there a better way to handle the large uid? */
2758 if (local_ace->e_id == cpu_to_le32(-1)) {
2759 /* Probably no need to le convert -1 on any arch but can not hurt */
2760 cifs_ace->cifs_uid = cpu_to_le64(-1);
2762 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2763 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2767 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2768 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2769 const int buflen, const int acl_type)
2772 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2773 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2777 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2780 count = posix_acl_xattr_count((size_t)buflen);
2781 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2783 count, buflen, le32_to_cpu(local_acl->a_version)));
2784 if (le32_to_cpu(local_acl->a_version) != 2) {
2785 cFYI(1, ("unknown POSIX ACL version %d",
2786 le32_to_cpu(local_acl->a_version)));
2789 cifs_acl->version = cpu_to_le16(1);
2790 if (acl_type == ACL_TYPE_ACCESS)
2791 cifs_acl->access_entry_count = cpu_to_le16(count);
2792 else if (acl_type == ACL_TYPE_DEFAULT)
2793 cifs_acl->default_entry_count = cpu_to_le16(count);
2795 cFYI(1, ("unknown ACL type %d", acl_type));
2798 for (i = 0; i < count; i++) {
2799 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2800 &local_acl->a_entries[i]);
2802 /* ACE not converted */
2807 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2808 rc += sizeof(struct cifs_posix_acl);
2809 /* BB add check to make sure ACL does not overflow SMB */
2815 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2816 const unsigned char *searchName,
2817 char *acl_inf, const int buflen, const int acl_type,
2818 const struct nls_table *nls_codepage, int remap)
2820 /* SMB_QUERY_POSIX_ACL */
2821 TRANSACTION2_QPI_REQ *pSMB = NULL;
2822 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2826 __u16 params, byte_count;
2828 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2831 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2836 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2838 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2839 PATH_MAX, nls_codepage, remap);
2840 name_len++; /* trailing null */
2842 pSMB->FileName[name_len] = 0;
2843 pSMB->FileName[name_len+1] = 0;
2844 } else { /* BB improve the check for buffer overruns BB */
2845 name_len = strnlen(searchName, PATH_MAX);
2846 name_len++; /* trailing null */
2847 strncpy(pSMB->FileName, searchName, name_len);
2850 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2851 pSMB->TotalDataCount = 0;
2852 pSMB->MaxParameterCount = cpu_to_le16(2);
2853 /* BB find exact max data count below from sess structure BB */
2854 pSMB->MaxDataCount = cpu_to_le16(4000);
2855 pSMB->MaxSetupCount = 0;
2859 pSMB->Reserved2 = 0;
2860 pSMB->ParameterOffset = cpu_to_le16(
2861 offsetof(struct smb_com_transaction2_qpi_req,
2862 InformationLevel) - 4);
2863 pSMB->DataCount = 0;
2864 pSMB->DataOffset = 0;
2865 pSMB->SetupCount = 1;
2866 pSMB->Reserved3 = 0;
2867 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2868 byte_count = params + 1 /* pad */ ;
2869 pSMB->TotalParameterCount = cpu_to_le16(params);
2870 pSMB->ParameterCount = pSMB->TotalParameterCount;
2871 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2872 pSMB->Reserved4 = 0;
2873 pSMB->hdr.smb_buf_length += byte_count;
2874 pSMB->ByteCount = cpu_to_le16(byte_count);
2876 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2877 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2878 cifs_stats_inc(&tcon->num_acl_get);
2880 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2882 /* decode response */
2884 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2885 if (rc || (pSMBr->ByteCount < 2))
2886 /* BB also check enough total bytes returned */
2887 rc = -EIO; /* bad smb */
2889 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2890 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2891 rc = cifs_copy_posix_acl(acl_inf,
2892 (char *)&pSMBr->hdr.Protocol+data_offset,
2893 buflen, acl_type, count);
2896 cifs_buf_release(pSMB);
2903 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2904 const unsigned char *fileName,
2905 const char *local_acl, const int buflen,
2907 const struct nls_table *nls_codepage, int remap)
2909 struct smb_com_transaction2_spi_req *pSMB = NULL;
2910 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2914 int bytes_returned = 0;
2915 __u16 params, byte_count, data_count, param_offset, offset;
2917 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2919 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2923 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2925 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2926 PATH_MAX, nls_codepage, remap);
2927 name_len++; /* trailing null */
2929 } else { /* BB improve the check for buffer overruns BB */
2930 name_len = strnlen(fileName, PATH_MAX);
2931 name_len++; /* trailing null */
2932 strncpy(pSMB->FileName, fileName, name_len);
2934 params = 6 + name_len;
2935 pSMB->MaxParameterCount = cpu_to_le16(2);
2936 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2937 pSMB->MaxSetupCount = 0;
2941 pSMB->Reserved2 = 0;
2942 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2943 InformationLevel) - 4;
2944 offset = param_offset + params;
2945 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2946 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2948 /* convert to on the wire format for POSIX ACL */
2949 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2951 if (data_count == 0) {
2953 goto setACLerrorExit;
2955 pSMB->DataOffset = cpu_to_le16(offset);
2956 pSMB->SetupCount = 1;
2957 pSMB->Reserved3 = 0;
2958 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2959 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2960 byte_count = 3 /* pad */ + params + data_count;
2961 pSMB->DataCount = cpu_to_le16(data_count);
2962 pSMB->TotalDataCount = pSMB->DataCount;
2963 pSMB->ParameterCount = cpu_to_le16(params);
2964 pSMB->TotalParameterCount = pSMB->ParameterCount;
2965 pSMB->Reserved4 = 0;
2966 pSMB->hdr.smb_buf_length += byte_count;
2967 pSMB->ByteCount = cpu_to_le16(byte_count);
2968 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2969 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2971 cFYI(1, ("Set POSIX ACL returned %d", rc));
2975 cifs_buf_release(pSMB);
2981 /* BB fix tabs in this function FIXME BB */
2983 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2984 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2987 struct smb_t2_qfi_req *pSMB = NULL;
2988 struct smb_t2_qfi_rsp *pSMBr = NULL;
2990 __u16 params, byte_count;
2992 cFYI(1, ("In GetExtAttr"));
2997 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3002 params = 2 /* level */ +2 /* fid */;
3003 pSMB->t2.TotalDataCount = 0;
3004 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3005 /* BB find exact max data count below from sess structure BB */
3006 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3007 pSMB->t2.MaxSetupCount = 0;
3008 pSMB->t2.Reserved = 0;
3010 pSMB->t2.Timeout = 0;
3011 pSMB->t2.Reserved2 = 0;
3012 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3014 pSMB->t2.DataCount = 0;
3015 pSMB->t2.DataOffset = 0;
3016 pSMB->t2.SetupCount = 1;
3017 pSMB->t2.Reserved3 = 0;
3018 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3019 byte_count = params + 1 /* pad */ ;
3020 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3021 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3022 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3025 pSMB->hdr.smb_buf_length += byte_count;
3026 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3028 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3029 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3031 cFYI(1, ("error %d in GetExtAttr", rc));
3033 /* decode response */
3034 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3035 if (rc || (pSMBr->ByteCount < 2))
3036 /* BB also check enough total bytes returned */
3037 /* If rc should we check for EOPNOSUPP and
3038 disable the srvino flag? or in caller? */
3039 rc = -EIO; /* bad smb */
3041 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3042 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3043 struct file_chattr_info *pfinfo;
3044 /* BB Do we need a cast or hash here ? */
3046 cFYI(1, ("Illegal size ret in GetExtAttr"));
3050 pfinfo = (struct file_chattr_info *)
3051 (data_offset + (char *) &pSMBr->hdr.Protocol);
3052 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3053 *pMask = le64_to_cpu(pfinfo->mask);
3057 cifs_buf_release(pSMB);
3059 goto GetExtAttrRetry;
3063 #endif /* CONFIG_POSIX */
3065 #ifdef CONFIG_CIFS_EXPERIMENTAL
3066 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3068 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3069 /* BB fix up return info */ char *acl_inf, const int buflen,
3074 QUERY_SEC_DESC_REQ * pSMB;
3077 cFYI(1, ("GetCifsACL"));
3079 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3080 8 /* parm len */, tcon, (void **) &pSMB);
3084 pSMB->MaxParameterCount = cpu_to_le32(4);
3085 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3086 pSMB->MaxSetupCount = 0;
3087 pSMB->Fid = fid; /* file handle always le */
3088 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3090 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3091 pSMB->hdr.smb_buf_length += 11;
3092 iov[0].iov_base = (char *)pSMB;
3093 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3095 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
3096 cifs_stats_inc(&tcon->num_acl_get);
3098 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3099 } else { /* decode response */
3100 struct cifs_ntsd *psec_desc;
3105 struct smb_com_ntransact_rsp *pSMBr;
3107 /* validate_nttransact */
3108 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3109 (char **)&psec_desc,
3110 &parm_len, &data_len);
3113 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3115 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
3117 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3118 rc = -EIO; /* bad smb */
3122 /* BB check that data area is minimum length and as big as acl_len */
3124 acl_len = le32_to_cpu(*parm);
3125 /* BB check if (acl_len > bufsize) */
3127 parse_sec_desc(psec_desc, acl_len);
3130 if (buf_type == CIFS_SMALL_BUFFER)
3131 cifs_small_buf_release(iov[0].iov_base);
3132 else if (buf_type == CIFS_LARGE_BUFFER)
3133 cifs_buf_release(iov[0].iov_base);
3134 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3137 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3139 /* Legacy Query Path Information call for lookup to old servers such
3141 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3142 const unsigned char *searchName,
3143 FILE_ALL_INFO *pFinfo,
3144 const struct nls_table *nls_codepage, int remap)
3146 QUERY_INFORMATION_REQ * pSMB;
3147 QUERY_INFORMATION_RSP * pSMBr;
3152 cFYI(1, ("In SMBQPath path %s", searchName));
3154 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3159 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3161 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3162 PATH_MAX, nls_codepage, remap);
3163 name_len++; /* trailing null */
3166 name_len = strnlen(searchName, PATH_MAX);
3167 name_len++; /* trailing null */
3168 strncpy(pSMB->FileName, searchName, name_len);
3170 pSMB->BufferFormat = 0x04;
3171 name_len++; /* account for buffer type byte */
3172 pSMB->hdr.smb_buf_length += (__u16) name_len;
3173 pSMB->ByteCount = cpu_to_le16(name_len);
3175 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3176 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3178 cFYI(1, ("Send error in QueryInfo = %d", rc));
3179 } else if (pFinfo) { /* decode response */
3181 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3182 /* BB FIXME - add time zone adjustment BB */
3183 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3186 /* decode time fields */
3187 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3188 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3189 pFinfo->LastAccessTime = 0;
3190 pFinfo->AllocationSize =
3191 cpu_to_le64(le32_to_cpu(pSMBr->size));
3192 pFinfo->EndOfFile = pFinfo->AllocationSize;
3193 pFinfo->Attributes =
3194 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3196 rc = -EIO; /* bad buffer passed in */
3198 cifs_buf_release(pSMB);
3210 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3211 const unsigned char *searchName,
3212 FILE_ALL_INFO * pFindData,
3213 int legacy /* old style infolevel */,
3214 const struct nls_table *nls_codepage, int remap)
3216 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3217 TRANSACTION2_QPI_REQ *pSMB = NULL;
3218 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3222 __u16 params, byte_count;
3224 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3226 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3231 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3233 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3234 PATH_MAX, nls_codepage, remap);
3235 name_len++; /* trailing null */
3237 } else { /* BB improve the check for buffer overruns BB */
3238 name_len = strnlen(searchName, PATH_MAX);
3239 name_len++; /* trailing null */
3240 strncpy(pSMB->FileName, searchName, name_len);
3243 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3244 pSMB->TotalDataCount = 0;
3245 pSMB->MaxParameterCount = cpu_to_le16(2);
3246 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3247 pSMB->MaxSetupCount = 0;
3251 pSMB->Reserved2 = 0;
3252 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3253 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3254 pSMB->DataCount = 0;
3255 pSMB->DataOffset = 0;
3256 pSMB->SetupCount = 1;
3257 pSMB->Reserved3 = 0;
3258 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3259 byte_count = params + 1 /* pad */ ;
3260 pSMB->TotalParameterCount = cpu_to_le16(params);
3261 pSMB->ParameterCount = pSMB->TotalParameterCount;
3263 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3265 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3266 pSMB->Reserved4 = 0;
3267 pSMB->hdr.smb_buf_length += byte_count;
3268 pSMB->ByteCount = cpu_to_le16(byte_count);
3270 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3271 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3273 cFYI(1, ("Send error in QPathInfo = %d", rc));
3274 } else { /* decode response */
3275 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3277 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3279 else if (!legacy && (pSMBr->ByteCount < 40))
3280 rc = -EIO; /* bad smb */
3281 else if (legacy && (pSMBr->ByteCount < 24))
3282 rc = -EIO; /* 24 or 26 expected but we do not read
3284 else if (pFindData) {
3286 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3287 if (legacy) /* we do not read the last field, EAsize,
3288 fortunately since it varies by subdialect
3289 and on Set vs. Get, is two bytes or 4
3290 bytes depending but we don't care here */
3291 size = sizeof(FILE_INFO_STANDARD);
3293 size = sizeof(FILE_ALL_INFO);
3294 memcpy((char *) pFindData,
3295 (char *) &pSMBr->hdr.Protocol +
3300 cifs_buf_release(pSMB);
3302 goto QPathInfoRetry;
3308 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3309 const unsigned char *searchName,
3310 FILE_UNIX_BASIC_INFO * pFindData,
3311 const struct nls_table *nls_codepage, int remap)
3313 /* SMB_QUERY_FILE_UNIX_BASIC */
3314 TRANSACTION2_QPI_REQ *pSMB = NULL;
3315 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3317 int bytes_returned = 0;
3319 __u16 params, byte_count;
3321 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3323 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3328 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3330 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3331 PATH_MAX, nls_codepage, remap);
3332 name_len++; /* trailing null */
3334 } else { /* BB improve the check for buffer overruns BB */
3335 name_len = strnlen(searchName, PATH_MAX);
3336 name_len++; /* trailing null */
3337 strncpy(pSMB->FileName, searchName, name_len);
3340 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3341 pSMB->TotalDataCount = 0;
3342 pSMB->MaxParameterCount = cpu_to_le16(2);
3343 /* BB find exact max SMB PDU from sess structure BB */
3344 pSMB->MaxDataCount = cpu_to_le16(4000);
3345 pSMB->MaxSetupCount = 0;
3349 pSMB->Reserved2 = 0;
3350 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3351 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3352 pSMB->DataCount = 0;
3353 pSMB->DataOffset = 0;
3354 pSMB->SetupCount = 1;
3355 pSMB->Reserved3 = 0;
3356 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3357 byte_count = params + 1 /* pad */ ;
3358 pSMB->TotalParameterCount = cpu_to_le16(params);
3359 pSMB->ParameterCount = pSMB->TotalParameterCount;
3360 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3361 pSMB->Reserved4 = 0;
3362 pSMB->hdr.smb_buf_length += byte_count;
3363 pSMB->ByteCount = cpu_to_le16(byte_count);
3365 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3366 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3368 cFYI(1, ("Send error in QPathInfo = %d", rc));
3369 } else { /* decode response */
3370 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3372 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3373 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3374 "Unix Extensions can be disabled on mount "
3375 "by specifying the nosfu mount option."));
3376 rc = -EIO; /* bad smb */
3378 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3379 memcpy((char *) pFindData,
3380 (char *) &pSMBr->hdr.Protocol +
3382 sizeof (FILE_UNIX_BASIC_INFO));
3385 cifs_buf_release(pSMB);
3387 goto UnixQPathInfoRetry;
3392 #if 0 /* function unused at present */
3393 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3394 const char *searchName, FILE_ALL_INFO * findData,
3395 const struct nls_table *nls_codepage)
3397 /* level 257 SMB_ */
3398 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3399 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3403 __u16 params, byte_count;
3405 cFYI(1, ("In FindUnique"));
3407 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3412 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3414 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3415 PATH_MAX, nls_codepage);
3416 name_len++; /* trailing null */
3418 } else { /* BB improve the check for buffer overruns BB */
3419 name_len = strnlen(searchName, PATH_MAX);
3420 name_len++; /* trailing null */
3421 strncpy(pSMB->FileName, searchName, name_len);
3424 params = 12 + name_len /* includes null */ ;
3425 pSMB->TotalDataCount = 0; /* no EAs */
3426 pSMB->MaxParameterCount = cpu_to_le16(2);
3427 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3428 pSMB->MaxSetupCount = 0;
3432 pSMB->Reserved2 = 0;
3433 pSMB->ParameterOffset = cpu_to_le16(
3434 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3435 pSMB->DataCount = 0;
3436 pSMB->DataOffset = 0;
3437 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3438 pSMB->Reserved3 = 0;
3439 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3440 byte_count = params + 1 /* pad */ ;
3441 pSMB->TotalParameterCount = cpu_to_le16(params);
3442 pSMB->ParameterCount = pSMB->TotalParameterCount;
3443 pSMB->SearchAttributes =
3444 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3446 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3447 pSMB->SearchFlags = cpu_to_le16(1);
3448 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3449 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3450 pSMB->hdr.smb_buf_length += byte_count;
3451 pSMB->ByteCount = cpu_to_le16(byte_count);
3453 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3454 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3457 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3458 } else { /* decode response */
3459 cifs_stats_inc(&tcon->num_ffirst);
3463 cifs_buf_release(pSMB);
3465 goto findUniqueRetry;
3469 #endif /* end unused (temporarily) function */
3471 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3473 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3474 const char *searchName,
3475 const struct nls_table *nls_codepage,
3477 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3479 /* level 257 SMB_ */
3480 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3481 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3482 T2_FFIRST_RSP_PARMS * parms;
3484 int bytes_returned = 0;
3486 __u16 params, byte_count;
3488 cFYI(1, ("In FindFirst for %s", searchName));
3491 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3496 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3498 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3499 PATH_MAX, nls_codepage, remap);
3500 /* We can not add the asterik earlier in case
3501 it got remapped to 0xF03A as if it were part of the
3502 directory name instead of a wildcard */
3504 pSMB->FileName[name_len] = dirsep;
3505 pSMB->FileName[name_len+1] = 0;
3506 pSMB->FileName[name_len+2] = '*';
3507 pSMB->FileName[name_len+3] = 0;
3508 name_len += 4; /* now the trailing null */
3509 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3510 pSMB->FileName[name_len+1] = 0;
3512 } else { /* BB add check for overrun of SMB buf BB */
3513 name_len = strnlen(searchName, PATH_MAX);
3514 /* BB fix here and in unicode clause above ie
3515 if (name_len > buffersize-header)
3516 free buffer exit; BB */
3517 strncpy(pSMB->FileName, searchName, name_len);
3518 pSMB->FileName[name_len] = dirsep;
3519 pSMB->FileName[name_len+1] = '*';
3520 pSMB->FileName[name_len+2] = 0;
3524 params = 12 + name_len /* includes null */ ;
3525 pSMB->TotalDataCount = 0; /* no EAs */
3526 pSMB->MaxParameterCount = cpu_to_le16(10);
3527 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3528 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3529 pSMB->MaxSetupCount = 0;
3533 pSMB->Reserved2 = 0;
3534 byte_count = params + 1 /* pad */ ;
3535 pSMB->TotalParameterCount = cpu_to_le16(params);
3536 pSMB->ParameterCount = pSMB->TotalParameterCount;
3537 pSMB->ParameterOffset = cpu_to_le16(
3538 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3540 pSMB->DataCount = 0;
3541 pSMB->DataOffset = 0;
3542 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3543 pSMB->Reserved3 = 0;
3544 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3545 pSMB->SearchAttributes =
3546 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3548 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3549 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3550 CIFS_SEARCH_RETURN_RESUME);
3551 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3553 /* BB what should we set StorageType to? Does it matter? BB */
3554 pSMB->SearchStorageType = 0;
3555 pSMB->hdr.smb_buf_length += byte_count;
3556 pSMB->ByteCount = cpu_to_le16(byte_count);
3558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3559 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3560 cifs_stats_inc(&tcon->num_ffirst);
3562 if (rc) {/* BB add logic to retry regular search if Unix search
3563 rejected unexpectedly by server */
3564 /* BB Add code to handle unsupported level rc */
3565 cFYI(1, ("Error in FindFirst = %d", rc));
3567 cifs_buf_release(pSMB);
3569 /* BB eventually could optimize out free and realloc of buf */
3572 goto findFirstRetry;
3573 } else { /* decode response */
3574 /* BB remember to free buffer if error BB */
3575 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3577 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3578 psrch_inf->unicode = TRUE;
3580 psrch_inf->unicode = FALSE;
3582 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3583 psrch_inf->smallBuf = 0;
3584 psrch_inf->srch_entries_start =
3585 (char *) &pSMBr->hdr.Protocol +
3586 le16_to_cpu(pSMBr->t2.DataOffset);
3587 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3588 le16_to_cpu(pSMBr->t2.ParameterOffset));
3590 if (parms->EndofSearch)
3591 psrch_inf->endOfSearch = TRUE;
3593 psrch_inf->endOfSearch = FALSE;
3595 psrch_inf->entries_in_buffer =
3596 le16_to_cpu(parms->SearchCount);
3597 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3598 psrch_inf->entries_in_buffer;
3599 *pnetfid = parms->SearchHandle;
3601 cifs_buf_release(pSMB);
3608 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3609 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3611 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3612 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3613 T2_FNEXT_RSP_PARMS * parms;
3614 char *response_data;
3616 int bytes_returned, name_len;
3617 __u16 params, byte_count;
3619 cFYI(1, ("In FindNext"));
3621 if (psrch_inf->endOfSearch == TRUE)
3624 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3629 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3631 pSMB->TotalDataCount = 0; /* no EAs */
3632 pSMB->MaxParameterCount = cpu_to_le16(8);
3633 pSMB->MaxDataCount =
3634 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3636 pSMB->MaxSetupCount = 0;
3640 pSMB->Reserved2 = 0;
3641 pSMB->ParameterOffset = cpu_to_le16(
3642 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3643 pSMB->DataCount = 0;
3644 pSMB->DataOffset = 0;
3645 pSMB->SetupCount = 1;
3646 pSMB->Reserved3 = 0;
3647 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3648 pSMB->SearchHandle = searchHandle; /* always kept as le */
3650 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3651 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3652 pSMB->ResumeKey = psrch_inf->resume_key;
3654 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3656 name_len = psrch_inf->resume_name_len;
3658 if (name_len < PATH_MAX) {
3659 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3660 byte_count += name_len;
3661 /* 14 byte parm len above enough for 2 byte null terminator */
3662 pSMB->ResumeFileName[name_len] = 0;
3663 pSMB->ResumeFileName[name_len+1] = 0;
3666 goto FNext2_err_exit;
3668 byte_count = params + 1 /* pad */ ;
3669 pSMB->TotalParameterCount = cpu_to_le16(params);
3670 pSMB->ParameterCount = pSMB->TotalParameterCount;
3671 pSMB->hdr.smb_buf_length += byte_count;
3672 pSMB->ByteCount = cpu_to_le16(byte_count);
3674 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3675 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3676 cifs_stats_inc(&tcon->num_fnext);
3679 psrch_inf->endOfSearch = TRUE;
3680 rc = 0; /* search probably was closed at end of search*/
3682 cFYI(1, ("FindNext returned = %d", rc));
3683 } else { /* decode response */
3684 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3687 /* BB fixme add lock for file (srch_info) struct here */
3688 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3689 psrch_inf->unicode = TRUE;
3691 psrch_inf->unicode = FALSE;
3692 response_data = (char *) &pSMBr->hdr.Protocol +
3693 le16_to_cpu(pSMBr->t2.ParameterOffset);
3694 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3695 response_data = (char *)&pSMBr->hdr.Protocol +
3696 le16_to_cpu(pSMBr->t2.DataOffset);
3697 if (psrch_inf->smallBuf)
3698 cifs_small_buf_release(
3699 psrch_inf->ntwrk_buf_start);
3701 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3702 psrch_inf->srch_entries_start = response_data;
3703 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3704 psrch_inf->smallBuf = 0;
3705 if (parms->EndofSearch)
3706 psrch_inf->endOfSearch = TRUE;
3708 psrch_inf->endOfSearch = FALSE;
3709 psrch_inf->entries_in_buffer =
3710 le16_to_cpu(parms->SearchCount);
3711 psrch_inf->index_of_last_entry +=
3712 psrch_inf->entries_in_buffer;
3713 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3714 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3716 /* BB fixme add unlock here */
3721 /* BB On error, should we leave previous search buf (and count and
3722 last entry fields) intact or free the previous one? */
3724 /* Note: On -EAGAIN error only caller can retry on handle based calls
3725 since file handle passed in no longer valid */
3728 cifs_buf_release(pSMB);
3733 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3734 const __u16 searchHandle)
3737 FINDCLOSE_REQ *pSMB = NULL;
3738 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3741 cFYI(1, ("In CIFSSMBFindClose"));
3742 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3744 /* no sense returning error if session restarted
3745 as file handle has been closed */
3751 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3752 pSMB->FileID = searchHandle;
3753 pSMB->ByteCount = 0;
3754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3757 cERROR(1, ("Send error in FindClose = %d", rc));
3759 cifs_stats_inc(&tcon->num_fclose);
3760 cifs_small_buf_release(pSMB);
3762 /* Since session is dead, search handle closed on server already */
3770 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3771 const unsigned char *searchName,
3772 __u64 * inode_number,
3773 const struct nls_table *nls_codepage, int remap)
3776 TRANSACTION2_QPI_REQ *pSMB = NULL;
3777 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3778 int name_len, bytes_returned;
3779 __u16 params, byte_count;
3781 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3785 GetInodeNumberRetry:
3786 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3791 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3793 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3794 PATH_MAX, nls_codepage, remap);
3795 name_len++; /* trailing null */
3797 } else { /* BB improve the check for buffer overruns BB */
3798 name_len = strnlen(searchName, PATH_MAX);
3799 name_len++; /* trailing null */
3800 strncpy(pSMB->FileName, searchName, name_len);
3803 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3804 pSMB->TotalDataCount = 0;
3805 pSMB->MaxParameterCount = cpu_to_le16(2);
3806 /* BB find exact max data count below from sess structure BB */
3807 pSMB->MaxDataCount = cpu_to_le16(4000);
3808 pSMB->MaxSetupCount = 0;
3812 pSMB->Reserved2 = 0;
3813 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3814 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3815 pSMB->DataCount = 0;
3816 pSMB->DataOffset = 0;
3817 pSMB->SetupCount = 1;
3818 pSMB->Reserved3 = 0;
3819 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3820 byte_count = params + 1 /* pad */ ;
3821 pSMB->TotalParameterCount = cpu_to_le16(params);
3822 pSMB->ParameterCount = pSMB->TotalParameterCount;
3823 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3824 pSMB->Reserved4 = 0;
3825 pSMB->hdr.smb_buf_length += byte_count;
3826 pSMB->ByteCount = cpu_to_le16(byte_count);
3828 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3829 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3831 cFYI(1, ("error %d in QueryInternalInfo", rc));
3833 /* decode response */
3834 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3835 if (rc || (pSMBr->ByteCount < 2))
3836 /* BB also check enough total bytes returned */
3837 /* If rc should we check for EOPNOSUPP and
3838 disable the srvino flag? or in caller? */
3839 rc = -EIO; /* bad smb */
3841 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3842 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3843 struct file_internal_info *pfinfo;
3844 /* BB Do we need a cast or hash here ? */
3846 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3848 goto GetInodeNumOut;
3850 pfinfo = (struct file_internal_info *)
3851 (data_offset + (char *) &pSMBr->hdr.Protocol);
3852 *inode_number = pfinfo->UniqueId;
3856 cifs_buf_release(pSMB);
3858 goto GetInodeNumberRetry;
3863 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3864 const unsigned char *searchName,
3865 unsigned char **targetUNCs,
3866 unsigned int *number_of_UNC_in_array,
3867 const struct nls_table *nls_codepage, int remap)
3869 /* TRANS2_GET_DFS_REFERRAL */
3870 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3871 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3872 struct dfs_referral_level_3 *referrals = NULL;
3878 __u16 params, byte_count;
3879 *number_of_UNC_in_array = 0;
3882 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3886 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3891 /* server pointer checked in called function,
3892 but should never be null here anyway */
3893 pSMB->hdr.Mid = GetNextMid(ses->server);
3894 pSMB->hdr.Tid = ses->ipc_tid;
3895 pSMB->hdr.Uid = ses->Suid;
3896 if (ses->capabilities & CAP_STATUS32)
3897 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3898 if (ses->capabilities & CAP_DFS)
3899 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3901 if (ses->capabilities & CAP_UNICODE) {
3902 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3904 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3905 searchName, PATH_MAX, nls_codepage, remap);
3906 name_len++; /* trailing null */
3908 } else { /* BB improve the check for buffer overruns BB */
3909 name_len = strnlen(searchName, PATH_MAX);
3910 name_len++; /* trailing null */
3911 strncpy(pSMB->RequestFileName, searchName, name_len);
3915 if (ses->server->secMode &
3916 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3917 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3920 pSMB->hdr.Uid = ses->Suid;
3922 params = 2 /* level */ + name_len /*includes null */ ;
3923 pSMB->TotalDataCount = 0;
3924 pSMB->DataCount = 0;
3925 pSMB->DataOffset = 0;
3926 pSMB->MaxParameterCount = 0;
3927 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3928 pSMB->MaxSetupCount = 0;
3932 pSMB->Reserved2 = 0;
3933 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3934 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3935 pSMB->SetupCount = 1;
3936 pSMB->Reserved3 = 0;
3937 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3938 byte_count = params + 3 /* pad */ ;
3939 pSMB->ParameterCount = cpu_to_le16(params);
3940 pSMB->TotalParameterCount = pSMB->ParameterCount;
3941 pSMB->MaxReferralLevel = cpu_to_le16(3);
3942 pSMB->hdr.smb_buf_length += byte_count;
3943 pSMB->ByteCount = cpu_to_le16(byte_count);
3945 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3946 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3948 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3949 } else { /* decode response */
3950 /* BB Add logic to parse referrals here */
3951 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3953 /* BB Also check if enough total bytes returned? */
3954 if (rc || (pSMBr->ByteCount < 17))
3955 rc = -EIO; /* bad smb */
3957 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3958 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3961 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3962 pSMBr->ByteCount, data_offset));
3964 (struct dfs_referral_level_3 *)
3965 (8 /* sizeof start of data block */ +
3967 (char *) &pSMBr->hdr.Protocol);
3968 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3969 "for referral one refer size: 0x%x srv "
3970 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3971 le16_to_cpu(pSMBr->NumberOfReferrals),
3972 le16_to_cpu(pSMBr->DFSFlags),
3973 le16_to_cpu(referrals->ReferralSize),
3974 le16_to_cpu(referrals->ServerType),
3975 le16_to_cpu(referrals->ReferralFlags),
3976 le16_to_cpu(referrals->TimeToLive)));
3977 /* BB This field is actually two bytes in from start of
3978 data block so we could do safety check that DataBlock
3979 begins at address of pSMBr->NumberOfReferrals */
3980 *number_of_UNC_in_array =
3981 le16_to_cpu(pSMBr->NumberOfReferrals);
3983 /* BB Fix below so can return more than one referral */
3984 if (*number_of_UNC_in_array > 1)
3985 *number_of_UNC_in_array = 1;
3987 /* get the length of the strings describing refs */
3989 for (i = 0; i < *number_of_UNC_in_array; i++) {
3990 /* make sure that DfsPathOffset not past end */
3992 le16_to_cpu(referrals->DfsPathOffset);
3993 if (offset > data_count) {
3994 /* if invalid referral, stop here and do
3995 not try to copy any more */
3996 *number_of_UNC_in_array = i;
3999 temp = ((char *)referrals) + offset;
4001 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4002 name_len += UniStrnlen((wchar_t *)temp,
4005 name_len += strnlen(temp, data_count);
4008 /* BB add check that referral pointer does
4009 not fall off end PDU */
4011 /* BB add check for name_len bigger than bcc */
4013 kmalloc(name_len+1+(*number_of_UNC_in_array),
4015 if (*targetUNCs == NULL) {
4019 /* copy the ref strings */
4020 referrals = (struct dfs_referral_level_3 *)
4021 (8 /* sizeof data hdr */ + data_offset +
4022 (char *) &pSMBr->hdr.Protocol);
4024 for (i = 0; i < *number_of_UNC_in_array; i++) {
4025 temp = ((char *)referrals) +
4026 le16_to_cpu(referrals->DfsPathOffset);
4027 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4028 cifs_strfromUCS_le(*targetUNCs,
4033 strncpy(*targetUNCs, temp, name_len);
4035 /* BB update target_uncs pointers */
4045 cifs_buf_release(pSMB);
4053 /* Query File System Info such as free space to old servers such as Win 9x */
4055 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4057 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4058 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4059 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4060 FILE_SYSTEM_ALLOC_INFO *response_data;
4062 int bytes_returned = 0;
4063 __u16 params, byte_count;
4065 cFYI(1, ("OldQFSInfo"));
4067 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4072 params = 2; /* level */
4073 pSMB->TotalDataCount = 0;
4074 pSMB->MaxParameterCount = cpu_to_le16(2);
4075 pSMB->MaxDataCount = cpu_to_le16(1000);
4076 pSMB->MaxSetupCount = 0;
4080 pSMB->Reserved2 = 0;
4081 byte_count = params + 1 /* pad */ ;
4082 pSMB->TotalParameterCount = cpu_to_le16(params);
4083 pSMB->ParameterCount = pSMB->TotalParameterCount;
4084 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4085 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4086 pSMB->DataCount = 0;
4087 pSMB->DataOffset = 0;
4088 pSMB->SetupCount = 1;
4089 pSMB->Reserved3 = 0;
4090 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4091 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4092 pSMB->hdr.smb_buf_length += byte_count;
4093 pSMB->ByteCount = cpu_to_le16(byte_count);
4095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4098 cFYI(1, ("Send error in QFSInfo = %d", rc));
4099 } else { /* decode response */
4100 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4102 if (rc || (pSMBr->ByteCount < 18))
4103 rc = -EIO; /* bad smb */
4105 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4106 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4107 pSMBr->ByteCount, data_offset));
4109 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4110 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4112 le16_to_cpu(response_data->BytesPerSector) *
4113 le32_to_cpu(response_data->
4114 SectorsPerAllocationUnit);
4116 le32_to_cpu(response_data->TotalAllocationUnits);
4117 FSData->f_bfree = FSData->f_bavail =
4118 le32_to_cpu(response_data->FreeAllocationUnits);
4120 ("Blocks: %lld Free: %lld Block size %ld",
4121 (unsigned long long)FSData->f_blocks,
4122 (unsigned long long)FSData->f_bfree,
4126 cifs_buf_release(pSMB);
4129 goto oldQFSInfoRetry;
4135 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4137 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4138 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4139 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4140 FILE_SYSTEM_INFO *response_data;
4142 int bytes_returned = 0;
4143 __u16 params, byte_count;
4145 cFYI(1, ("In QFSInfo"));
4147 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4152 params = 2; /* level */
4153 pSMB->TotalDataCount = 0;
4154 pSMB->MaxParameterCount = cpu_to_le16(2);
4155 pSMB->MaxDataCount = cpu_to_le16(1000);
4156 pSMB->MaxSetupCount = 0;
4160 pSMB->Reserved2 = 0;
4161 byte_count = params + 1 /* pad */ ;
4162 pSMB->TotalParameterCount = cpu_to_le16(params);
4163 pSMB->ParameterCount = pSMB->TotalParameterCount;
4164 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4165 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4166 pSMB->DataCount = 0;
4167 pSMB->DataOffset = 0;
4168 pSMB->SetupCount = 1;
4169 pSMB->Reserved3 = 0;
4170 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4171 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4172 pSMB->hdr.smb_buf_length += byte_count;
4173 pSMB->ByteCount = cpu_to_le16(byte_count);
4175 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4176 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4178 cFYI(1, ("Send error in QFSInfo = %d", rc));
4179 } else { /* decode response */
4180 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4182 if (rc || (pSMBr->ByteCount < 24))
4183 rc = -EIO; /* bad smb */
4185 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4189 *) (((char *) &pSMBr->hdr.Protocol) +
4192 le32_to_cpu(response_data->BytesPerSector) *
4193 le32_to_cpu(response_data->
4194 SectorsPerAllocationUnit);
4196 le64_to_cpu(response_data->TotalAllocationUnits);
4197 FSData->f_bfree = FSData->f_bavail =
4198 le64_to_cpu(response_data->FreeAllocationUnits);
4200 ("Blocks: %lld Free: %lld Block size %ld",
4201 (unsigned long long)FSData->f_blocks,
4202 (unsigned long long)FSData->f_bfree,
4206 cifs_buf_release(pSMB);
4215 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4217 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4218 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4219 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4220 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4222 int bytes_returned = 0;
4223 __u16 params, byte_count;
4225 cFYI(1, ("In QFSAttributeInfo"));
4227 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4232 params = 2; /* level */
4233 pSMB->TotalDataCount = 0;
4234 pSMB->MaxParameterCount = cpu_to_le16(2);
4235 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4236 pSMB->MaxSetupCount = 0;
4240 pSMB->Reserved2 = 0;
4241 byte_count = params + 1 /* pad */ ;
4242 pSMB->TotalParameterCount = cpu_to_le16(params);
4243 pSMB->ParameterCount = pSMB->TotalParameterCount;
4244 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4245 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4246 pSMB->DataCount = 0;
4247 pSMB->DataOffset = 0;
4248 pSMB->SetupCount = 1;
4249 pSMB->Reserved3 = 0;
4250 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4251 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4252 pSMB->hdr.smb_buf_length += byte_count;
4253 pSMB->ByteCount = cpu_to_le16(byte_count);
4255 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4256 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4258 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4259 } else { /* decode response */
4260 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4262 if (rc || (pSMBr->ByteCount < 13)) {
4263 /* BB also check if enough bytes returned */
4264 rc = -EIO; /* bad smb */
4266 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4268 (FILE_SYSTEM_ATTRIBUTE_INFO
4269 *) (((char *) &pSMBr->hdr.Protocol) +
4271 memcpy(&tcon->fsAttrInfo, response_data,
4272 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4275 cifs_buf_release(pSMB);
4278 goto QFSAttributeRetry;
4284 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4286 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4287 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4288 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4289 FILE_SYSTEM_DEVICE_INFO *response_data;
4291 int bytes_returned = 0;
4292 __u16 params, byte_count;
4294 cFYI(1, ("In QFSDeviceInfo"));
4296 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4301 params = 2; /* level */
4302 pSMB->TotalDataCount = 0;
4303 pSMB->MaxParameterCount = cpu_to_le16(2);
4304 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4305 pSMB->MaxSetupCount = 0;
4309 pSMB->Reserved2 = 0;
4310 byte_count = params + 1 /* pad */ ;
4311 pSMB->TotalParameterCount = cpu_to_le16(params);
4312 pSMB->ParameterCount = pSMB->TotalParameterCount;
4313 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4314 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4316 pSMB->DataCount = 0;
4317 pSMB->DataOffset = 0;
4318 pSMB->SetupCount = 1;
4319 pSMB->Reserved3 = 0;
4320 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4321 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4322 pSMB->hdr.smb_buf_length += byte_count;
4323 pSMB->ByteCount = cpu_to_le16(byte_count);
4325 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4326 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4328 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4329 } else { /* decode response */
4330 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4332 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4333 rc = -EIO; /* bad smb */
4335 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4337 (FILE_SYSTEM_DEVICE_INFO *)
4338 (((char *) &pSMBr->hdr.Protocol) +
4340 memcpy(&tcon->fsDevInfo, response_data,
4341 sizeof(FILE_SYSTEM_DEVICE_INFO));
4344 cifs_buf_release(pSMB);
4347 goto QFSDeviceRetry;
4353 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4355 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4356 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4357 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4358 FILE_SYSTEM_UNIX_INFO *response_data;
4360 int bytes_returned = 0;
4361 __u16 params, byte_count;
4363 cFYI(1, ("In QFSUnixInfo"));
4365 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4370 params = 2; /* level */
4371 pSMB->TotalDataCount = 0;
4372 pSMB->DataCount = 0;
4373 pSMB->DataOffset = 0;
4374 pSMB->MaxParameterCount = cpu_to_le16(2);
4375 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4376 pSMB->MaxSetupCount = 0;
4380 pSMB->Reserved2 = 0;
4381 byte_count = params + 1 /* pad */ ;
4382 pSMB->ParameterCount = cpu_to_le16(params);
4383 pSMB->TotalParameterCount = pSMB->ParameterCount;
4384 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4385 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4386 pSMB->SetupCount = 1;
4387 pSMB->Reserved3 = 0;
4388 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4389 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4390 pSMB->hdr.smb_buf_length += byte_count;
4391 pSMB->ByteCount = cpu_to_le16(byte_count);
4393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4396 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4397 } else { /* decode response */
4398 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4400 if (rc || (pSMBr->ByteCount < 13)) {
4401 rc = -EIO; /* bad smb */
4403 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4405 (FILE_SYSTEM_UNIX_INFO
4406 *) (((char *) &pSMBr->hdr.Protocol) +
4408 memcpy(&tcon->fsUnixInfo, response_data,
4409 sizeof(FILE_SYSTEM_UNIX_INFO));
4412 cifs_buf_release(pSMB);
4422 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4424 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4425 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4426 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4428 int bytes_returned = 0;
4429 __u16 params, param_offset, offset, byte_count;
4431 cFYI(1, ("In SETFSUnixInfo"));
4433 /* BB switch to small buf init to save memory */
4434 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4439 params = 4; /* 2 bytes zero followed by info level. */
4440 pSMB->MaxSetupCount = 0;
4444 pSMB->Reserved2 = 0;
4445 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4447 offset = param_offset + params;
4449 pSMB->MaxParameterCount = cpu_to_le16(4);
4450 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4451 pSMB->SetupCount = 1;
4452 pSMB->Reserved3 = 0;
4453 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4454 byte_count = 1 /* pad */ + params + 12;
4456 pSMB->DataCount = cpu_to_le16(12);
4457 pSMB->ParameterCount = cpu_to_le16(params);
4458 pSMB->TotalDataCount = pSMB->DataCount;
4459 pSMB->TotalParameterCount = pSMB->ParameterCount;
4460 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4461 pSMB->DataOffset = cpu_to_le16(offset);
4465 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4468 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4469 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4470 pSMB->ClientUnixCap = cpu_to_le64(cap);
4472 pSMB->hdr.smb_buf_length += byte_count;
4473 pSMB->ByteCount = cpu_to_le16(byte_count);
4475 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4478 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4479 } else { /* decode response */
4480 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4482 rc = -EIO; /* bad smb */
4485 cifs_buf_release(pSMB);
4488 goto SETFSUnixRetry;
4496 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4497 struct kstatfs *FSData)
4499 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4500 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4501 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4502 FILE_SYSTEM_POSIX_INFO *response_data;
4504 int bytes_returned = 0;
4505 __u16 params, byte_count;
4507 cFYI(1, ("In QFSPosixInfo"));
4509 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4514 params = 2; /* level */
4515 pSMB->TotalDataCount = 0;
4516 pSMB->DataCount = 0;
4517 pSMB->DataOffset = 0;
4518 pSMB->MaxParameterCount = cpu_to_le16(2);
4519 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4520 pSMB->MaxSetupCount = 0;
4524 pSMB->Reserved2 = 0;
4525 byte_count = params + 1 /* pad */ ;
4526 pSMB->ParameterCount = cpu_to_le16(params);
4527 pSMB->TotalParameterCount = pSMB->ParameterCount;
4528 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4529 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4530 pSMB->SetupCount = 1;
4531 pSMB->Reserved3 = 0;
4532 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4533 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4534 pSMB->hdr.smb_buf_length += byte_count;
4535 pSMB->ByteCount = cpu_to_le16(byte_count);
4537 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4538 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4540 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4541 } else { /* decode response */
4542 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4544 if (rc || (pSMBr->ByteCount < 13)) {
4545 rc = -EIO; /* bad smb */
4547 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4549 (FILE_SYSTEM_POSIX_INFO
4550 *) (((char *) &pSMBr->hdr.Protocol) +
4553 le32_to_cpu(response_data->BlockSize);
4555 le64_to_cpu(response_data->TotalBlocks);
4557 le64_to_cpu(response_data->BlocksAvail);
4558 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4559 FSData->f_bavail = FSData->f_bfree;
4562 le64_to_cpu(response_data->UserBlocksAvail);
4564 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4566 le64_to_cpu(response_data->TotalFileNodes);
4567 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4569 le64_to_cpu(response_data->FreeFileNodes);
4572 cifs_buf_release(pSMB);
4581 /* We can not use write of zero bytes trick to
4582 set file size due to need for large file support. Also note that
4583 this SetPathInfo is preferred to SetFileInfo based method in next
4584 routine which is only needed to work around a sharing violation bug
4585 in Samba which this routine can run into */
4588 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4589 __u64 size, int SetAllocation,
4590 const struct nls_table *nls_codepage, int remap)
4592 struct smb_com_transaction2_spi_req *pSMB = NULL;
4593 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4594 struct file_end_of_file_info *parm_data;
4597 int bytes_returned = 0;
4598 __u16 params, byte_count, data_count, param_offset, offset;
4600 cFYI(1, ("In SetEOF"));
4602 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4607 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4609 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4610 PATH_MAX, nls_codepage, remap);
4611 name_len++; /* trailing null */
4613 } else { /* BB improve the check for buffer overruns BB */
4614 name_len = strnlen(fileName, PATH_MAX);
4615 name_len++; /* trailing null */
4616 strncpy(pSMB->FileName, fileName, name_len);
4618 params = 6 + name_len;
4619 data_count = sizeof(struct file_end_of_file_info);
4620 pSMB->MaxParameterCount = cpu_to_le16(2);
4621 pSMB->MaxDataCount = cpu_to_le16(4100);
4622 pSMB->MaxSetupCount = 0;
4626 pSMB->Reserved2 = 0;
4627 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4628 InformationLevel) - 4;
4629 offset = param_offset + params;
4630 if (SetAllocation) {
4631 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4632 pSMB->InformationLevel =
4633 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4635 pSMB->InformationLevel =
4636 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4637 } else /* Set File Size */ {
4638 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4639 pSMB->InformationLevel =
4640 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4642 pSMB->InformationLevel =
4643 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4647 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4649 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4650 pSMB->DataOffset = cpu_to_le16(offset);
4651 pSMB->SetupCount = 1;
4652 pSMB->Reserved3 = 0;
4653 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4654 byte_count = 3 /* pad */ + params + data_count;
4655 pSMB->DataCount = cpu_to_le16(data_count);
4656 pSMB->TotalDataCount = pSMB->DataCount;
4657 pSMB->ParameterCount = cpu_to_le16(params);
4658 pSMB->TotalParameterCount = pSMB->ParameterCount;
4659 pSMB->Reserved4 = 0;
4660 pSMB->hdr.smb_buf_length += byte_count;
4661 parm_data->FileSize = cpu_to_le64(size);
4662 pSMB->ByteCount = cpu_to_le16(byte_count);
4663 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4664 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4666 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4669 cifs_buf_release(pSMB);
4678 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4679 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4681 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4682 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4684 struct file_end_of_file_info *parm_data;
4686 int bytes_returned = 0;
4687 __u16 params, param_offset, offset, byte_count, count;
4689 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4691 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4696 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4698 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4699 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4702 pSMB->MaxSetupCount = 0;
4706 pSMB->Reserved2 = 0;
4707 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4708 offset = param_offset + params;
4710 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4712 count = sizeof(struct file_end_of_file_info);
4713 pSMB->MaxParameterCount = cpu_to_le16(2);
4714 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4715 pSMB->SetupCount = 1;
4716 pSMB->Reserved3 = 0;
4717 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4718 byte_count = 3 /* pad */ + params + count;
4719 pSMB->DataCount = cpu_to_le16(count);
4720 pSMB->ParameterCount = cpu_to_le16(params);
4721 pSMB->TotalDataCount = pSMB->DataCount;
4722 pSMB->TotalParameterCount = pSMB->ParameterCount;
4723 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4725 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4727 pSMB->DataOffset = cpu_to_le16(offset);
4728 parm_data->FileSize = cpu_to_le64(size);
4730 if (SetAllocation) {
4731 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4732 pSMB->InformationLevel =
4733 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4735 pSMB->InformationLevel =
4736 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4737 } else /* Set File Size */ {
4738 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4739 pSMB->InformationLevel =
4740 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4742 pSMB->InformationLevel =
4743 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4745 pSMB->Reserved4 = 0;
4746 pSMB->hdr.smb_buf_length += byte_count;
4747 pSMB->ByteCount = cpu_to_le16(byte_count);
4748 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4749 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4752 ("Send error in SetFileInfo (SetFileSize) = %d",
4757 cifs_small_buf_release(pSMB);
4759 /* Note: On -EAGAIN error only caller can retry on handle based calls
4760 since file handle passed in no longer valid */
4765 /* Some legacy servers such as NT4 require that the file times be set on
4766 an open handle, rather than by pathname - this is awkward due to
4767 potential access conflicts on the open, but it is unavoidable for these
4768 old servers since the only other choice is to go from 100 nanosecond DCE
4769 time and resort to the original setpathinfo level which takes the ancient
4770 DOS time format with 2 second granularity */
4772 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4773 const FILE_BASIC_INFO *data, __u16 fid)
4775 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4776 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4779 int bytes_returned = 0;
4780 __u16 params, param_offset, offset, byte_count, count;
4782 cFYI(1, ("Set Times (via SetFileInfo)"));
4783 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4788 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4790 /* At this point there is no need to override the current pid
4791 with the pid of the opener, but that could change if we someday
4792 use an existing handle (rather than opening one on the fly) */
4793 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4794 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4797 pSMB->MaxSetupCount = 0;
4801 pSMB->Reserved2 = 0;
4802 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4803 offset = param_offset + params;
4805 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4807 count = sizeof(FILE_BASIC_INFO);
4808 pSMB->MaxParameterCount = cpu_to_le16(2);
4809 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4810 pSMB->SetupCount = 1;
4811 pSMB->Reserved3 = 0;
4812 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4813 byte_count = 3 /* pad */ + params + count;
4814 pSMB->DataCount = cpu_to_le16(count);
4815 pSMB->ParameterCount = cpu_to_le16(params);
4816 pSMB->TotalDataCount = pSMB->DataCount;
4817 pSMB->TotalParameterCount = pSMB->ParameterCount;
4818 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4819 pSMB->DataOffset = cpu_to_le16(offset);
4821 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4822 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4824 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4825 pSMB->Reserved4 = 0;
4826 pSMB->hdr.smb_buf_length += byte_count;
4827 pSMB->ByteCount = cpu_to_le16(byte_count);
4828 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4829 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4830 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4832 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4835 cifs_small_buf_release(pSMB);
4837 /* Note: On -EAGAIN error only caller can retry on handle based calls
4838 since file handle passed in no longer valid */
4845 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4846 const FILE_BASIC_INFO *data,
4847 const struct nls_table *nls_codepage, int remap)
4849 TRANSACTION2_SPI_REQ *pSMB = NULL;
4850 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4853 int bytes_returned = 0;
4855 __u16 params, param_offset, offset, byte_count, count;
4857 cFYI(1, ("In SetTimes"));
4860 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4865 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4867 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4868 PATH_MAX, nls_codepage, remap);
4869 name_len++; /* trailing null */
4871 } else { /* BB improve the check for buffer overruns BB */
4872 name_len = strnlen(fileName, PATH_MAX);
4873 name_len++; /* trailing null */
4874 strncpy(pSMB->FileName, fileName, name_len);
4877 params = 6 + name_len;
4878 count = sizeof(FILE_BASIC_INFO);
4879 pSMB->MaxParameterCount = cpu_to_le16(2);
4880 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4881 pSMB->MaxSetupCount = 0;
4885 pSMB->Reserved2 = 0;
4886 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4887 InformationLevel) - 4;
4888 offset = param_offset + params;
4889 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4890 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4891 pSMB->DataOffset = cpu_to_le16(offset);
4892 pSMB->SetupCount = 1;
4893 pSMB->Reserved3 = 0;
4894 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4895 byte_count = 3 /* pad */ + params + count;
4897 pSMB->DataCount = cpu_to_le16(count);
4898 pSMB->ParameterCount = cpu_to_le16(params);
4899 pSMB->TotalDataCount = pSMB->DataCount;
4900 pSMB->TotalParameterCount = pSMB->ParameterCount;
4901 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4902 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4904 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4905 pSMB->Reserved4 = 0;
4906 pSMB->hdr.smb_buf_length += byte_count;
4907 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4908 pSMB->ByteCount = cpu_to_le16(byte_count);
4909 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4910 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4912 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4915 cifs_buf_release(pSMB);
4923 /* Can not be used to set time stamps yet (due to old DOS time format) */
4924 /* Can be used to set attributes */
4925 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4926 handling it anyway and NT4 was what we thought it would be needed for
4927 Do not delete it until we prove whether needed for Win9x though */
4929 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4930 __u16 dos_attrs, const struct nls_table *nls_codepage)
4932 SETATTR_REQ *pSMB = NULL;
4933 SETATTR_RSP *pSMBr = NULL;
4938 cFYI(1, ("In SetAttrLegacy"));
4941 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4946 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4948 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4949 PATH_MAX, nls_codepage);
4950 name_len++; /* trailing null */
4952 } else { /* BB improve the check for buffer overruns BB */
4953 name_len = strnlen(fileName, PATH_MAX);
4954 name_len++; /* trailing null */
4955 strncpy(pSMB->fileName, fileName, name_len);
4957 pSMB->attr = cpu_to_le16(dos_attrs);
4958 pSMB->BufferFormat = 0x04;
4959 pSMB->hdr.smb_buf_length += name_len + 1;
4960 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4961 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4962 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4964 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4967 cifs_buf_release(pSMB);
4970 goto SetAttrLgcyRetry;
4974 #endif /* temporarily unneeded SetAttr legacy function */
4977 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4978 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4979 dev_t device, const struct nls_table *nls_codepage,
4982 TRANSACTION2_SPI_REQ *pSMB = NULL;
4983 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4986 int bytes_returned = 0;
4987 FILE_UNIX_BASIC_INFO *data_offset;
4988 __u16 params, param_offset, offset, count, byte_count;
4990 cFYI(1, ("In SetUID/GID/Mode"));
4992 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4997 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4999 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5000 PATH_MAX, nls_codepage, remap);
5001 name_len++; /* trailing null */
5003 } else { /* BB improve the check for buffer overruns BB */
5004 name_len = strnlen(fileName, PATH_MAX);
5005 name_len++; /* trailing null */
5006 strncpy(pSMB->FileName, fileName, name_len);
5009 params = 6 + name_len;
5010 count = sizeof(FILE_UNIX_BASIC_INFO);
5011 pSMB->MaxParameterCount = cpu_to_le16(2);
5012 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5013 pSMB->MaxSetupCount = 0;
5017 pSMB->Reserved2 = 0;
5018 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5019 InformationLevel) - 4;
5020 offset = param_offset + params;
5022 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5024 memset(data_offset, 0, count);
5025 pSMB->DataOffset = cpu_to_le16(offset);
5026 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5027 pSMB->SetupCount = 1;
5028 pSMB->Reserved3 = 0;
5029 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5030 byte_count = 3 /* pad */ + params + count;
5031 pSMB->ParameterCount = cpu_to_le16(params);
5032 pSMB->DataCount = cpu_to_le16(count);
5033 pSMB->TotalParameterCount = pSMB->ParameterCount;
5034 pSMB->TotalDataCount = pSMB->DataCount;
5035 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5036 pSMB->Reserved4 = 0;
5037 pSMB->hdr.smb_buf_length += byte_count;
5038 /* Samba server ignores set of file size to zero due to bugs in some
5039 older clients, but we should be precise - we use SetFileSize to
5040 set file size and do not want to truncate file size to zero
5041 accidently as happened on one Samba server beta by putting
5042 zero instead of -1 here */
5043 data_offset->EndOfFile = NO_CHANGE_64;
5044 data_offset->NumOfBytes = NO_CHANGE_64;
5045 data_offset->LastStatusChange = NO_CHANGE_64;
5046 data_offset->LastAccessTime = NO_CHANGE_64;
5047 data_offset->LastModificationTime = NO_CHANGE_64;
5048 data_offset->Uid = cpu_to_le64(uid);
5049 data_offset->Gid = cpu_to_le64(gid);
5050 /* better to leave device as zero when it is */
5051 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5052 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5053 data_offset->Permissions = cpu_to_le64(mode);
5056 data_offset->Type = cpu_to_le32(UNIX_FILE);
5057 else if (S_ISDIR(mode))
5058 data_offset->Type = cpu_to_le32(UNIX_DIR);
5059 else if (S_ISLNK(mode))
5060 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5061 else if (S_ISCHR(mode))
5062 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5063 else if (S_ISBLK(mode))
5064 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5065 else if (S_ISFIFO(mode))
5066 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5067 else if (S_ISSOCK(mode))
5068 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5071 pSMB->ByteCount = cpu_to_le16(byte_count);
5072 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5073 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5075 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5079 cifs_buf_release(pSMB);
5085 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5086 const int notify_subdirs, const __u16 netfid,
5087 __u32 filter, struct file *pfile, int multishot,
5088 const struct nls_table *nls_codepage)
5091 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5092 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5093 struct dir_notify_req *dnotify_req;
5096 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5097 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5102 pSMB->TotalParameterCount = 0 ;
5103 pSMB->TotalDataCount = 0;
5104 pSMB->MaxParameterCount = cpu_to_le32(2);
5105 /* BB find exact data count max from sess structure BB */
5106 pSMB->MaxDataCount = 0; /* same in little endian or be */
5107 /* BB VERIFY verify which is correct for above BB */
5108 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5109 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5111 pSMB->MaxSetupCount = 4;
5113 pSMB->ParameterOffset = 0;
5114 pSMB->DataCount = 0;
5115 pSMB->DataOffset = 0;
5116 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5117 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5118 pSMB->ParameterCount = pSMB->TotalParameterCount;
5120 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5121 pSMB->Reserved2 = 0;
5122 pSMB->CompletionFilter = cpu_to_le32(filter);
5123 pSMB->Fid = netfid; /* file handle always le */
5124 pSMB->ByteCount = 0;
5126 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5127 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5129 cFYI(1, ("Error in Notify = %d", rc));
5131 /* Add file to outstanding requests */
5132 /* BB change to kmem cache alloc */
5133 dnotify_req = kmalloc(
5134 sizeof(struct dir_notify_req),
5137 dnotify_req->Pid = pSMB->hdr.Pid;
5138 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5139 dnotify_req->Mid = pSMB->hdr.Mid;
5140 dnotify_req->Tid = pSMB->hdr.Tid;
5141 dnotify_req->Uid = pSMB->hdr.Uid;
5142 dnotify_req->netfid = netfid;
5143 dnotify_req->pfile = pfile;
5144 dnotify_req->filter = filter;
5145 dnotify_req->multishot = multishot;
5146 spin_lock(&GlobalMid_Lock);
5147 list_add_tail(&dnotify_req->lhead,
5148 &GlobalDnotifyReqList);
5149 spin_unlock(&GlobalMid_Lock);
5153 cifs_buf_release(pSMB);
5156 #ifdef CONFIG_CIFS_XATTR
5158 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5159 const unsigned char *searchName,
5160 char *EAData, size_t buf_size,
5161 const struct nls_table *nls_codepage, int remap)
5163 /* BB assumes one setup word */
5164 TRANSACTION2_QPI_REQ *pSMB = NULL;
5165 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5169 struct fea *temp_fea;
5171 __u16 params, byte_count;
5173 cFYI(1, ("In Query All EAs path %s", searchName));
5175 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5182 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5183 PATH_MAX, nls_codepage, remap);
5184 name_len++; /* trailing null */
5186 } else { /* BB improve the check for buffer overruns BB */
5187 name_len = strnlen(searchName, PATH_MAX);
5188 name_len++; /* trailing null */
5189 strncpy(pSMB->FileName, searchName, name_len);
5192 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5193 pSMB->TotalDataCount = 0;
5194 pSMB->MaxParameterCount = cpu_to_le16(2);
5195 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5196 pSMB->MaxSetupCount = 0;
5200 pSMB->Reserved2 = 0;
5201 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5202 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5203 pSMB->DataCount = 0;
5204 pSMB->DataOffset = 0;
5205 pSMB->SetupCount = 1;
5206 pSMB->Reserved3 = 0;
5207 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5208 byte_count = params + 1 /* pad */ ;
5209 pSMB->TotalParameterCount = cpu_to_le16(params);
5210 pSMB->ParameterCount = pSMB->TotalParameterCount;
5211 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5212 pSMB->Reserved4 = 0;
5213 pSMB->hdr.smb_buf_length += byte_count;
5214 pSMB->ByteCount = cpu_to_le16(byte_count);
5216 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5217 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5219 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5220 } else { /* decode response */
5221 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5223 /* BB also check enough total bytes returned */
5224 /* BB we need to improve the validity checking
5225 of these trans2 responses */
5226 if (rc || (pSMBr->ByteCount < 4))
5227 rc = -EIO; /* bad smb */
5228 /* else if (pFindData){
5229 memcpy((char *) pFindData,
5230 (char *) &pSMBr->hdr.Protocol +
5233 /* check that length of list is not more than bcc */
5234 /* check that each entry does not go beyond length
5236 /* check that each element of each entry does not
5237 go beyond end of list */
5238 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5239 struct fealist *ea_response_data;
5241 /* validate_trans2_offsets() */
5242 /* BB check if start of smb + data_offset > &bcc+ bcc */
5243 ea_response_data = (struct fealist *)
5244 (((char *) &pSMBr->hdr.Protocol) +
5246 name_len = le32_to_cpu(ea_response_data->list_len);
5247 cFYI(1, ("ea length %d", name_len));
5248 if (name_len <= 8) {
5249 /* returned EA size zeroed at top of function */
5250 cFYI(1, ("empty EA list returned from server"));
5252 /* account for ea list len */
5254 temp_fea = ea_response_data->list;
5255 temp_ptr = (char *)temp_fea;
5256 while (name_len > 0) {
5260 rc += temp_fea->name_len;
5261 /* account for prefix user. and trailing null */
5263 if (rc < (int)buf_size) {
5264 memcpy(EAData, "user.", 5);
5266 memcpy(EAData, temp_ptr,
5267 temp_fea->name_len);
5268 EAData += temp_fea->name_len;
5269 /* null terminate name */
5271 EAData = EAData + 1;
5272 } else if (buf_size == 0) {
5273 /* skip copy - calc size only */
5275 /* stop before overrun buffer */
5279 name_len -= temp_fea->name_len;
5280 temp_ptr += temp_fea->name_len;
5281 /* account for trailing null */
5285 le16_to_cpu(temp_fea->value_len);
5286 name_len -= value_len;
5287 temp_ptr += value_len;
5288 /* BB check that temp_ptr is still
5291 /* no trailing null to account for
5293 /* go on to next EA */
5294 temp_fea = (struct fea *)temp_ptr;
5300 cifs_buf_release(pSMB);
5307 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5308 const unsigned char *searchName, const unsigned char *ea_name,
5309 unsigned char *ea_value, size_t buf_size,
5310 const struct nls_table *nls_codepage, int remap)
5312 TRANSACTION2_QPI_REQ *pSMB = NULL;
5313 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5317 struct fea *temp_fea;
5319 __u16 params, byte_count;
5321 cFYI(1, ("In Query EA path %s", searchName));
5323 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5328 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5330 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5331 PATH_MAX, nls_codepage, remap);
5332 name_len++; /* trailing null */
5334 } else { /* BB improve the check for buffer overruns BB */
5335 name_len = strnlen(searchName, PATH_MAX);
5336 name_len++; /* trailing null */
5337 strncpy(pSMB->FileName, searchName, name_len);
5340 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5341 pSMB->TotalDataCount = 0;
5342 pSMB->MaxParameterCount = cpu_to_le16(2);
5343 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5344 pSMB->MaxSetupCount = 0;
5348 pSMB->Reserved2 = 0;
5349 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5350 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5351 pSMB->DataCount = 0;
5352 pSMB->DataOffset = 0;
5353 pSMB->SetupCount = 1;
5354 pSMB->Reserved3 = 0;
5355 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5356 byte_count = params + 1 /* pad */ ;
5357 pSMB->TotalParameterCount = cpu_to_le16(params);
5358 pSMB->ParameterCount = pSMB->TotalParameterCount;
5359 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5360 pSMB->Reserved4 = 0;
5361 pSMB->hdr.smb_buf_length += byte_count;
5362 pSMB->ByteCount = cpu_to_le16(byte_count);
5364 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5365 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5367 cFYI(1, ("Send error in Query EA = %d", rc));
5368 } else { /* decode response */
5369 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5371 /* BB also check enough total bytes returned */
5372 /* BB we need to improve the validity checking
5373 of these trans2 responses */
5374 if (rc || (pSMBr->ByteCount < 4))
5375 rc = -EIO; /* bad smb */
5376 /* else if (pFindData){
5377 memcpy((char *) pFindData,
5378 (char *) &pSMBr->hdr.Protocol +
5381 /* check that length of list is not more than bcc */
5382 /* check that each entry does not go beyond length
5384 /* check that each element of each entry does not
5385 go beyond end of list */
5386 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5387 struct fealist *ea_response_data;
5389 /* validate_trans2_offsets() */
5390 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5391 ea_response_data = (struct fealist *)
5392 (((char *) &pSMBr->hdr.Protocol) +
5394 name_len = le32_to_cpu(ea_response_data->list_len);
5395 cFYI(1, ("ea length %d", name_len));
5396 if (name_len <= 8) {
5397 /* returned EA size zeroed at top of function */
5398 cFYI(1, ("empty EA list returned from server"));
5400 /* account for ea list len */
5402 temp_fea = ea_response_data->list;
5403 temp_ptr = (char *)temp_fea;
5404 /* loop through checking if we have a matching
5405 name and then return the associated value */
5406 while (name_len > 0) {
5411 le16_to_cpu(temp_fea->value_len);
5412 /* BB validate that value_len falls within SMB,
5413 even though maximum for name_len is 255 */
5414 if (memcmp(temp_fea->name, ea_name,
5415 temp_fea->name_len) == 0) {
5418 /* account for prefix user. and trailing null */
5419 if (rc <= (int)buf_size) {
5421 temp_fea->name+temp_fea->name_len+1,
5423 /* ea values, unlike ea
5426 } else if (buf_size == 0) {
5427 /* skip copy - calc size only */
5429 /* stop before overrun buffer */
5434 name_len -= temp_fea->name_len;
5435 temp_ptr += temp_fea->name_len;
5436 /* account for trailing null */
5439 name_len -= value_len;
5440 temp_ptr += value_len;
5441 /* No trailing null to account for in
5442 value_len. Go on to next EA */
5443 temp_fea = (struct fea *)temp_ptr;
5449 cifs_buf_release(pSMB);
5457 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5458 const char *ea_name, const void *ea_value,
5459 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5462 struct smb_com_transaction2_spi_req *pSMB = NULL;
5463 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5464 struct fealist *parm_data;
5467 int bytes_returned = 0;
5468 __u16 params, param_offset, byte_count, offset, count;
5470 cFYI(1, ("In SetEA"));
5472 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5477 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5479 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5480 PATH_MAX, nls_codepage, remap);
5481 name_len++; /* trailing null */
5483 } else { /* BB improve the check for buffer overruns BB */
5484 name_len = strnlen(fileName, PATH_MAX);
5485 name_len++; /* trailing null */
5486 strncpy(pSMB->FileName, fileName, name_len);
5489 params = 6 + name_len;
5491 /* done calculating parms using name_len of file name,
5492 now use name_len to calculate length of ea name
5493 we are going to create in the inode xattrs */
5494 if (ea_name == NULL)
5497 name_len = strnlen(ea_name, 255);
5499 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5500 pSMB->MaxParameterCount = cpu_to_le16(2);
5501 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5502 pSMB->MaxSetupCount = 0;
5506 pSMB->Reserved2 = 0;
5507 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5508 InformationLevel) - 4;
5509 offset = param_offset + params;
5510 pSMB->InformationLevel =
5511 cpu_to_le16(SMB_SET_FILE_EA);
5514 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5516 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5517 pSMB->DataOffset = cpu_to_le16(offset);
5518 pSMB->SetupCount = 1;
5519 pSMB->Reserved3 = 0;
5520 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5521 byte_count = 3 /* pad */ + params + count;
5522 pSMB->DataCount = cpu_to_le16(count);
5523 parm_data->list_len = cpu_to_le32(count);
5524 parm_data->list[0].EA_flags = 0;
5525 /* we checked above that name len is less than 255 */
5526 parm_data->list[0].name_len = (__u8)name_len;
5527 /* EA names are always ASCII */
5529 strncpy(parm_data->list[0].name, ea_name, name_len);
5530 parm_data->list[0].name[name_len] = 0;
5531 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5532 /* caller ensures that ea_value_len is less than 64K but
5533 we need to ensure that it fits within the smb */
5535 /*BB add length check to see if it would fit in
5536 negotiated SMB buffer size BB */
5537 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5539 memcpy(parm_data->list[0].name+name_len+1,
5540 ea_value, ea_value_len);
5542 pSMB->TotalDataCount = pSMB->DataCount;
5543 pSMB->ParameterCount = cpu_to_le16(params);
5544 pSMB->TotalParameterCount = pSMB->ParameterCount;
5545 pSMB->Reserved4 = 0;
5546 pSMB->hdr.smb_buf_length += byte_count;
5547 pSMB->ByteCount = cpu_to_le16(byte_count);
5548 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5549 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5551 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5554 cifs_buf_release(pSMB);