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.
656 server->capabilities &= ~CAP_EXTENDED_SECURITY;
658 #ifdef CONFIG_CIFS_WEAK_PW_HASH
661 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
662 /* MUST_SIGN already includes the MAY_SIGN FLAG
663 so if this is zero it means that signing is disabled */
664 cFYI(1, ("Signing disabled"));
665 if (server->secMode & SECMODE_SIGN_REQUIRED) {
666 cERROR(1, ("Server requires "
667 "packet signing to be enabled in "
668 "/proc/fs/cifs/SecurityFlags."));
672 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
673 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
674 /* signing required */
675 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
676 if ((server->secMode &
677 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
679 ("signing required but server lacks support"));
682 server->secMode |= SECMODE_SIGN_REQUIRED;
684 /* signing optional ie CIFSSEC_MAY_SIGN */
685 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
687 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
691 cifs_buf_release(pSMB);
693 cFYI(1, ("negprot rc %d", rc));
698 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
700 struct smb_hdr *smb_buffer;
701 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
705 cFYI(1, ("In tree disconnect"));
707 * If last user of the connection and
708 * connection alive - disconnect it
709 * If this is the last connection on the server session disconnect it
710 * (and inside session disconnect we should check if tcp socket needs
711 * to be freed and kernel thread woken up).
714 down(&tcon->tconSem);
718 atomic_dec(&tcon->useCount);
719 if (atomic_read(&tcon->useCount) > 0) {
724 /* No need to return error on this operation if tid invalidated and
725 closed on server already e.g. due to tcp session crashing */
726 if (tcon->tidStatus == CifsNeedReconnect) {
731 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
735 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
736 (void **)&smb_buffer);
741 smb_buffer_response = smb_buffer; /* BB removeme BB */
743 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
746 cFYI(1, ("Tree disconnect failed %d", rc));
749 cifs_small_buf_release(smb_buffer);
752 /* No need to return error on this operation if tid invalidated and
753 closed on server already e.g. due to tcp session crashing */
761 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
763 struct smb_hdr *smb_buffer_response;
764 LOGOFF_ANDX_REQ *pSMB;
768 cFYI(1, ("In SMBLogoff for session disconnect"));
774 atomic_dec(&ses->inUse);
775 if (atomic_read(&ses->inUse) > 0) {
779 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
785 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
788 pSMB->hdr.Mid = GetNextMid(ses->server);
790 if (ses->server->secMode &
791 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
792 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
795 pSMB->hdr.Uid = ses->Suid;
797 pSMB->AndXCommand = 0xFF;
798 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
799 smb_buffer_response, &length, 0);
801 atomic_dec(&ses->server->socketUseCount);
802 if (atomic_read(&ses->server->socketUseCount) == 0) {
803 spin_lock(&GlobalMid_Lock);
804 ses->server->tcpStatus = CifsExiting;
805 spin_unlock(&GlobalMid_Lock);
810 cifs_small_buf_release(pSMB);
812 /* if session dead then we do not need to do ulogoff,
813 since server closed smb session, no sense reporting
821 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
822 __u16 type, const struct nls_table *nls_codepage, int remap)
824 TRANSACTION2_SPI_REQ *pSMB = NULL;
825 TRANSACTION2_SPI_RSP *pSMBr = NULL;
826 struct unlink_psx_rq *pRqD;
829 int bytes_returned = 0;
830 __u16 params, param_offset, offset, byte_count;
832 cFYI(1, ("In POSIX delete"));
834 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
839 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
841 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
842 PATH_MAX, nls_codepage, remap);
843 name_len++; /* trailing null */
845 } else { /* BB add path length overrun check */
846 name_len = strnlen(fileName, PATH_MAX);
847 name_len++; /* trailing null */
848 strncpy(pSMB->FileName, fileName, name_len);
851 params = 6 + name_len;
852 pSMB->MaxParameterCount = cpu_to_le16(2);
853 pSMB->MaxDataCount = 0; /* BB double check this with jra */
854 pSMB->MaxSetupCount = 0;
859 param_offset = offsetof(struct smb_com_transaction2_spi_req,
860 InformationLevel) - 4;
861 offset = param_offset + params;
863 /* Setup pointer to Request Data (inode type) */
864 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
865 pRqD->type = cpu_to_le16(type);
866 pSMB->ParameterOffset = cpu_to_le16(param_offset);
867 pSMB->DataOffset = cpu_to_le16(offset);
868 pSMB->SetupCount = 1;
870 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
871 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
873 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
874 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
875 pSMB->ParameterCount = cpu_to_le16(params);
876 pSMB->TotalParameterCount = pSMB->ParameterCount;
877 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
879 pSMB->hdr.smb_buf_length += byte_count;
880 pSMB->ByteCount = cpu_to_le16(byte_count);
881 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
882 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
884 cFYI(1, ("Posix delete returned %d", rc));
886 cifs_buf_release(pSMB);
888 cifs_stats_inc(&tcon->num_deletes);
897 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
898 const struct nls_table *nls_codepage, int remap)
900 DELETE_FILE_REQ *pSMB = NULL;
901 DELETE_FILE_RSP *pSMBr = NULL;
907 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
912 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
914 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
915 PATH_MAX, nls_codepage, remap);
916 name_len++; /* trailing null */
918 } else { /* BB improve check for buffer overruns BB */
919 name_len = strnlen(fileName, PATH_MAX);
920 name_len++; /* trailing null */
921 strncpy(pSMB->fileName, fileName, name_len);
923 pSMB->SearchAttributes =
924 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
925 pSMB->BufferFormat = 0x04;
926 pSMB->hdr.smb_buf_length += name_len + 1;
927 pSMB->ByteCount = cpu_to_le16(name_len + 1);
928 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
929 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
930 cifs_stats_inc(&tcon->num_deletes);
932 cFYI(1, ("Error in RMFile = %d", rc));
935 cifs_buf_release(pSMB);
943 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
944 const struct nls_table *nls_codepage, int remap)
946 DELETE_DIRECTORY_REQ *pSMB = NULL;
947 DELETE_DIRECTORY_RSP *pSMBr = NULL;
952 cFYI(1, ("In CIFSSMBRmDir"));
954 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
959 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
960 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
961 PATH_MAX, nls_codepage, remap);
962 name_len++; /* trailing null */
964 } else { /* BB improve check for buffer overruns BB */
965 name_len = strnlen(dirName, PATH_MAX);
966 name_len++; /* trailing null */
967 strncpy(pSMB->DirName, dirName, name_len);
970 pSMB->BufferFormat = 0x04;
971 pSMB->hdr.smb_buf_length += name_len + 1;
972 pSMB->ByteCount = cpu_to_le16(name_len + 1);
973 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
975 cifs_stats_inc(&tcon->num_rmdirs);
977 cFYI(1, ("Error in RMDir = %d", rc));
980 cifs_buf_release(pSMB);
987 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
988 const char *name, const struct nls_table *nls_codepage, int remap)
991 CREATE_DIRECTORY_REQ *pSMB = NULL;
992 CREATE_DIRECTORY_RSP *pSMBr = NULL;
996 cFYI(1, ("In CIFSSMBMkDir"));
998 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1003 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1004 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1005 PATH_MAX, nls_codepage, remap);
1006 name_len++; /* trailing null */
1008 } else { /* BB improve check for buffer overruns BB */
1009 name_len = strnlen(name, PATH_MAX);
1010 name_len++; /* trailing null */
1011 strncpy(pSMB->DirName, name, name_len);
1014 pSMB->BufferFormat = 0x04;
1015 pSMB->hdr.smb_buf_length += name_len + 1;
1016 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1017 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1018 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1019 cifs_stats_inc(&tcon->num_mkdirs);
1021 cFYI(1, ("Error in Mkdir = %d", rc));
1024 cifs_buf_release(pSMB);
1031 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1032 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1033 __u32 *pOplock, const char *name,
1034 const struct nls_table *nls_codepage, int remap)
1036 TRANSACTION2_SPI_REQ *pSMB = NULL;
1037 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1040 int bytes_returned = 0;
1041 __u16 params, param_offset, offset, byte_count, count;
1042 OPEN_PSX_REQ * pdata;
1043 OPEN_PSX_RSP * psx_rsp;
1045 cFYI(1, ("In POSIX Create"));
1047 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1052 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1054 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1055 PATH_MAX, nls_codepage, remap);
1056 name_len++; /* trailing null */
1058 } else { /* BB improve the check for buffer overruns BB */
1059 name_len = strnlen(name, PATH_MAX);
1060 name_len++; /* trailing null */
1061 strncpy(pSMB->FileName, name, name_len);
1064 params = 6 + name_len;
1065 count = sizeof(OPEN_PSX_REQ);
1066 pSMB->MaxParameterCount = cpu_to_le16(2);
1067 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1068 pSMB->MaxSetupCount = 0;
1072 pSMB->Reserved2 = 0;
1073 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1074 InformationLevel) - 4;
1075 offset = param_offset + params;
1076 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1077 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1078 pdata->Permissions = cpu_to_le64(mode);
1079 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1080 pdata->OpenFlags = cpu_to_le32(*pOplock);
1081 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1082 pSMB->DataOffset = cpu_to_le16(offset);
1083 pSMB->SetupCount = 1;
1084 pSMB->Reserved3 = 0;
1085 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1086 byte_count = 3 /* pad */ + params + count;
1088 pSMB->DataCount = cpu_to_le16(count);
1089 pSMB->ParameterCount = cpu_to_le16(params);
1090 pSMB->TotalDataCount = pSMB->DataCount;
1091 pSMB->TotalParameterCount = pSMB->ParameterCount;
1092 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1093 pSMB->Reserved4 = 0;
1094 pSMB->hdr.smb_buf_length += byte_count;
1095 pSMB->ByteCount = cpu_to_le16(byte_count);
1096 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1097 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1099 cFYI(1, ("Posix create returned %d", rc));
1100 goto psx_create_err;
1103 cFYI(1, ("copying inode info"));
1104 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1106 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1107 rc = -EIO; /* bad smb */
1108 goto psx_create_err;
1111 /* copy return information to pRetData */
1112 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1113 + le16_to_cpu(pSMBr->t2.DataOffset));
1115 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1117 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1118 /* Let caller know file was created so we can set the mode. */
1119 /* Do we care about the CreateAction in any other cases? */
1120 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1121 *pOplock |= CIFS_CREATE_ACTION;
1122 /* check to make sure response data is there */
1123 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1124 pRetData->Type = cpu_to_le32(-1); /* unknown */
1125 #ifdef CONFIG_CIFS_DEBUG2
1126 cFYI(1, ("unknown type"));
1129 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1130 + sizeof(FILE_UNIX_BASIC_INFO)) {
1131 cERROR(1, ("Open response data too small"));
1132 pRetData->Type = cpu_to_le32(-1);
1133 goto psx_create_err;
1135 memcpy((char *) pRetData,
1136 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1137 sizeof(FILE_UNIX_BASIC_INFO));
1141 cifs_buf_release(pSMB);
1143 cifs_stats_inc(&tcon->num_mkdirs);
1151 static __u16 convert_disposition(int disposition)
1155 switch (disposition) {
1156 case FILE_SUPERSEDE:
1157 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1160 ofun = SMBOPEN_OAPPEND;
1163 ofun = SMBOPEN_OCREATE;
1166 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1168 case FILE_OVERWRITE:
1169 ofun = SMBOPEN_OTRUNC;
1171 case FILE_OVERWRITE_IF:
1172 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1175 cFYI(1, ("unknown disposition %d", disposition));
1176 ofun = SMBOPEN_OAPPEND; /* regular open */
1182 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1183 const char *fileName, const int openDisposition,
1184 const int access_flags, const int create_options, __u16 * netfid,
1185 int *pOplock, FILE_ALL_INFO * pfile_info,
1186 const struct nls_table *nls_codepage, int remap)
1189 OPENX_REQ *pSMB = NULL;
1190 OPENX_RSP *pSMBr = NULL;
1196 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1201 pSMB->AndXCommand = 0xFF; /* none */
1203 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1204 count = 1; /* account for one byte pad to word boundary */
1206 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1207 fileName, PATH_MAX, nls_codepage, remap);
1208 name_len++; /* trailing null */
1210 } else { /* BB improve check for buffer overruns BB */
1211 count = 0; /* no pad */
1212 name_len = strnlen(fileName, PATH_MAX);
1213 name_len++; /* trailing null */
1214 strncpy(pSMB->fileName, fileName, name_len);
1216 if (*pOplock & REQ_OPLOCK)
1217 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1218 else if (*pOplock & REQ_BATCHOPLOCK)
1219 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1221 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1222 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1228 pSMB->Mode = cpu_to_le16(2);
1229 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1230 /* set file as system file if special file such
1231 as fifo and server expecting SFU style and
1232 no Unix extensions */
1234 if (create_options & CREATE_OPTION_SPECIAL)
1235 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1237 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1239 /* if ((omode & S_IWUGO) == 0)
1240 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1241 /* Above line causes problems due to vfs splitting create into two
1242 pieces - need to set mode after file created not while it is
1246 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1247 CREATE_OPTIONS_MASK); */
1248 /* BB FIXME END BB */
1250 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1251 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1253 pSMB->hdr.smb_buf_length += count;
1255 pSMB->ByteCount = cpu_to_le16(count);
1256 /* long_op set to 1 to allow for oplock break timeouts */
1257 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1258 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1259 cifs_stats_inc(&tcon->num_opens);
1261 cFYI(1, ("Error in Open = %d", rc));
1263 /* BB verify if wct == 15 */
1265 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1267 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1268 /* Let caller know file was created so we can set the mode. */
1269 /* Do we care about the CreateAction in any other cases? */
1271 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1272 *pOplock |= CIFS_CREATE_ACTION; */
1276 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1277 pfile_info->LastAccessTime = 0; /* BB fixme */
1278 pfile_info->LastWriteTime = 0; /* BB fixme */
1279 pfile_info->ChangeTime = 0; /* BB fixme */
1280 pfile_info->Attributes =
1281 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1282 /* the file_info buf is endian converted by caller */
1283 pfile_info->AllocationSize =
1284 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1285 pfile_info->EndOfFile = pfile_info->AllocationSize;
1286 pfile_info->NumberOfLinks = cpu_to_le32(1);
1290 cifs_buf_release(pSMB);
1297 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1298 const char *fileName, const int openDisposition,
1299 const int access_flags, const int create_options, __u16 * netfid,
1300 int *pOplock, FILE_ALL_INFO * pfile_info,
1301 const struct nls_table *nls_codepage, int remap)
1304 OPEN_REQ *pSMB = NULL;
1305 OPEN_RSP *pSMBr = NULL;
1311 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1316 pSMB->AndXCommand = 0xFF; /* none */
1318 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1319 count = 1; /* account for one byte pad to word boundary */
1321 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1322 fileName, PATH_MAX, nls_codepage, remap);
1323 name_len++; /* trailing null */
1325 pSMB->NameLength = cpu_to_le16(name_len);
1326 } else { /* BB improve check for buffer overruns BB */
1327 count = 0; /* no pad */
1328 name_len = strnlen(fileName, PATH_MAX);
1329 name_len++; /* trailing null */
1330 pSMB->NameLength = cpu_to_le16(name_len);
1331 strncpy(pSMB->fileName, fileName, name_len);
1333 if (*pOplock & REQ_OPLOCK)
1334 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1335 else if (*pOplock & REQ_BATCHOPLOCK)
1336 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1337 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1338 pSMB->AllocationSize = 0;
1339 /* set file as system file if special file such
1340 as fifo and server expecting SFU style and
1341 no Unix extensions */
1342 if (create_options & CREATE_OPTION_SPECIAL)
1343 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1345 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1346 /* XP does not handle ATTR_POSIX_SEMANTICS */
1347 /* but it helps speed up case sensitive checks for other
1348 servers such as Samba */
1349 if (tcon->ses->capabilities & CAP_UNIX)
1350 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1352 /* if ((omode & S_IWUGO) == 0)
1353 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1354 /* Above line causes problems due to vfs splitting create into two
1355 pieces - need to set mode after file created not while it is
1357 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1358 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1359 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1360 /* BB Expirement with various impersonation levels and verify */
1361 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1362 pSMB->SecurityFlags =
1363 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1366 pSMB->hdr.smb_buf_length += count;
1368 pSMB->ByteCount = cpu_to_le16(count);
1369 /* long_op set to 1 to allow for oplock break timeouts */
1370 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1371 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1372 cifs_stats_inc(&tcon->num_opens);
1374 cFYI(1, ("Error in Open = %d", rc));
1376 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1377 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1378 /* Let caller know file was created so we can set the mode. */
1379 /* Do we care about the CreateAction in any other cases? */
1380 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1381 *pOplock |= CIFS_CREATE_ACTION;
1383 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1384 36 /* CreationTime to Attributes */);
1385 /* the file_info buf is endian converted by caller */
1386 pfile_info->AllocationSize = pSMBr->AllocationSize;
1387 pfile_info->EndOfFile = pSMBr->EndOfFile;
1388 pfile_info->NumberOfLinks = cpu_to_le32(1);
1392 cifs_buf_release(pSMB);
1399 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1400 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1401 char **buf, int *pbuf_type)
1404 READ_REQ *pSMB = NULL;
1405 READ_RSP *pSMBr = NULL;
1406 char *pReadData = NULL;
1408 int resp_buf_type = 0;
1411 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1412 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1415 wct = 10; /* old style read */
1418 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1422 /* tcon and ses pointer are checked in smb_init */
1423 if (tcon->ses->server == NULL)
1424 return -ECONNABORTED;
1426 pSMB->AndXCommand = 0xFF; /* none */
1428 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1430 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1431 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1434 pSMB->Remaining = 0;
1435 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1436 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1438 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1440 /* old style read */
1441 struct smb_com_readx_req *pSMBW =
1442 (struct smb_com_readx_req *)pSMB;
1443 pSMBW->ByteCount = 0;
1446 iov[0].iov_base = (char *)pSMB;
1447 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1448 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1449 &resp_buf_type, 0 /* not long op */, 1 /* log err */ );
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,
1668 long_op, 0 /* do not log STATUS code */ );
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 #ifdef CONFIG_CIFS_EXPERIMENTAL
2489 /* Initialize NT TRANSACT SMB into small smb request buffer.
2490 This assumes that all NT TRANSACTS that we init here have
2491 total parm and data under about 400 bytes (to fit in small cifs
2492 buffer size), which is the case so far, it easily fits. NB:
2493 Setup words themselves and ByteCount
2494 MaxSetupCount (size of returned setup area) and
2495 MaxParameterCount (returned parms size) must be set by caller */
2497 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2498 const int parm_len, struct cifsTconInfo *tcon,
2503 struct smb_com_ntransact_req *pSMB;
2505 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2509 *ret_buf = (void *)pSMB;
2511 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2512 pSMB->TotalDataCount = 0;
2513 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2514 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2515 pSMB->ParameterCount = pSMB->TotalParameterCount;
2516 pSMB->DataCount = pSMB->TotalDataCount;
2517 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2518 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2519 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2520 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2521 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2522 pSMB->SubCommand = cpu_to_le16(sub_command);
2527 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2528 __u32 *pparmlen, __u32 *pdatalen)
2531 __u32 data_count, data_offset, parm_count, parm_offset;
2532 struct smb_com_ntransact_rsp *pSMBr;
2540 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2542 /* ByteCount was converted from little endian in SendReceive */
2543 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2544 (char *)&pSMBr->ByteCount;
2546 data_offset = le32_to_cpu(pSMBr->DataOffset);
2547 data_count = le32_to_cpu(pSMBr->DataCount);
2548 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2549 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2551 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2552 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2554 /* should we also check that parm and data areas do not overlap? */
2555 if (*ppparm > end_of_smb) {
2556 cFYI(1, ("parms start after end of smb"));
2558 } else if (parm_count + *ppparm > end_of_smb) {
2559 cFYI(1, ("parm end after end of smb"));
2561 } else if (*ppdata > end_of_smb) {
2562 cFYI(1, ("data starts after end of smb"));
2564 } else if (data_count + *ppdata > end_of_smb) {
2565 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2566 *ppdata, data_count, (data_count + *ppdata),
2567 end_of_smb, pSMBr));
2569 } else if (parm_count + data_count > pSMBr->ByteCount) {
2570 cFYI(1, ("parm count and data count larger than SMB"));
2573 *pdatalen = data_count;
2574 *pparmlen = parm_count;
2577 #endif /* CIFS_EXPERIMENTAL */
2580 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2581 const unsigned char *searchName,
2582 char *symlinkinfo, const int buflen, __u16 fid,
2583 const struct nls_table *nls_codepage)
2588 struct smb_com_transaction_ioctl_req *pSMB;
2589 struct smb_com_transaction_ioctl_rsp *pSMBr;
2591 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2592 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2597 pSMB->TotalParameterCount = 0 ;
2598 pSMB->TotalDataCount = 0;
2599 pSMB->MaxParameterCount = cpu_to_le32(2);
2600 /* BB find exact data count max from sess structure BB */
2601 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2602 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2603 pSMB->MaxSetupCount = 4;
2605 pSMB->ParameterOffset = 0;
2606 pSMB->DataCount = 0;
2607 pSMB->DataOffset = 0;
2608 pSMB->SetupCount = 4;
2609 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2610 pSMB->ParameterCount = pSMB->TotalParameterCount;
2611 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2612 pSMB->IsFsctl = 1; /* FSCTL */
2613 pSMB->IsRootFlag = 0;
2614 pSMB->Fid = fid; /* file handle always le */
2615 pSMB->ByteCount = 0;
2617 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2618 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2621 } else { /* decode response */
2622 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2623 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2624 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2625 /* BB also check enough total bytes returned */
2626 rc = -EIO; /* bad smb */
2628 if (data_count && (data_count < 2048)) {
2629 char *end_of_smb = 2 /* sizeof byte count */ +
2631 (char *)&pSMBr->ByteCount;
2633 struct reparse_data *reparse_buf =
2634 (struct reparse_data *)
2635 ((char *)&pSMBr->hdr.Protocol
2637 if ((char *)reparse_buf >= end_of_smb) {
2641 if ((reparse_buf->LinkNamesBuf +
2642 reparse_buf->TargetNameOffset +
2643 reparse_buf->TargetNameLen) >
2645 cFYI(1, ("reparse buf beyond SMB"));
2650 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2651 name_len = UniStrnlen((wchar_t *)
2652 (reparse_buf->LinkNamesBuf +
2653 reparse_buf->TargetNameOffset),
2655 reparse_buf->TargetNameLen / 2));
2656 cifs_strfromUCS_le(symlinkinfo,
2657 (__le16 *) (reparse_buf->LinkNamesBuf +
2658 reparse_buf->TargetNameOffset),
2659 name_len, nls_codepage);
2660 } else { /* ASCII names */
2661 strncpy(symlinkinfo,
2662 reparse_buf->LinkNamesBuf +
2663 reparse_buf->TargetNameOffset,
2664 min_t(const int, buflen,
2665 reparse_buf->TargetNameLen));
2669 cFYI(1, ("Invalid return data count on "
2670 "get reparse info ioctl"));
2672 symlinkinfo[buflen] = 0; /* just in case so the caller
2673 does not go off the end of the buffer */
2674 cFYI(1, ("readlink result - %s", symlinkinfo));
2678 cifs_buf_release(pSMB);
2680 /* Note: On -EAGAIN error only caller can retry on handle based calls
2681 since file handle passed in no longer valid */
2686 #ifdef CONFIG_CIFS_POSIX
2688 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2689 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2690 struct cifs_posix_ace *cifs_ace)
2692 /* u8 cifs fields do not need le conversion */
2693 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2694 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2695 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2696 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2701 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2702 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2703 const int acl_type, const int size_of_data_area)
2708 struct cifs_posix_ace *pACE;
2709 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2710 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2712 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2715 if (acl_type & ACL_TYPE_ACCESS) {
2716 count = le16_to_cpu(cifs_acl->access_entry_count);
2717 pACE = &cifs_acl->ace_array[0];
2718 size = sizeof(struct cifs_posix_acl);
2719 size += sizeof(struct cifs_posix_ace) * count;
2720 /* check if we would go beyond end of SMB */
2721 if (size_of_data_area < size) {
2722 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2723 size_of_data_area, size));
2726 } else if (acl_type & ACL_TYPE_DEFAULT) {
2727 count = le16_to_cpu(cifs_acl->access_entry_count);
2728 size = sizeof(struct cifs_posix_acl);
2729 size += sizeof(struct cifs_posix_ace) * count;
2730 /* skip past access ACEs to get to default ACEs */
2731 pACE = &cifs_acl->ace_array[count];
2732 count = le16_to_cpu(cifs_acl->default_entry_count);
2733 size += sizeof(struct cifs_posix_ace) * count;
2734 /* check if we would go beyond end of SMB */
2735 if (size_of_data_area < size)
2742 size = posix_acl_xattr_size(count);
2743 if ((buflen == 0) || (local_acl == NULL)) {
2744 /* used to query ACL EA size */
2745 } else if (size > buflen) {
2747 } else /* buffer big enough */ {
2748 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2749 for (i = 0; i < count ; i++) {
2750 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2757 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2758 const posix_acl_xattr_entry *local_ace)
2760 __u16 rc = 0; /* 0 = ACL converted ok */
2762 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2763 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2764 /* BB is there a better way to handle the large uid? */
2765 if (local_ace->e_id == cpu_to_le32(-1)) {
2766 /* Probably no need to le convert -1 on any arch but can not hurt */
2767 cifs_ace->cifs_uid = cpu_to_le64(-1);
2769 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2770 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2774 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2775 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2776 const int buflen, const int acl_type)
2779 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2780 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2784 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2787 count = posix_acl_xattr_count((size_t)buflen);
2788 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2790 count, buflen, le32_to_cpu(local_acl->a_version)));
2791 if (le32_to_cpu(local_acl->a_version) != 2) {
2792 cFYI(1, ("unknown POSIX ACL version %d",
2793 le32_to_cpu(local_acl->a_version)));
2796 cifs_acl->version = cpu_to_le16(1);
2797 if (acl_type == ACL_TYPE_ACCESS)
2798 cifs_acl->access_entry_count = cpu_to_le16(count);
2799 else if (acl_type == ACL_TYPE_DEFAULT)
2800 cifs_acl->default_entry_count = cpu_to_le16(count);
2802 cFYI(1, ("unknown ACL type %d", acl_type));
2805 for (i = 0; i < count; i++) {
2806 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2807 &local_acl->a_entries[i]);
2809 /* ACE not converted */
2814 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2815 rc += sizeof(struct cifs_posix_acl);
2816 /* BB add check to make sure ACL does not overflow SMB */
2822 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2823 const unsigned char *searchName,
2824 char *acl_inf, const int buflen, const int acl_type,
2825 const struct nls_table *nls_codepage, int remap)
2827 /* SMB_QUERY_POSIX_ACL */
2828 TRANSACTION2_QPI_REQ *pSMB = NULL;
2829 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2833 __u16 params, byte_count;
2835 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2838 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2843 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2845 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2846 PATH_MAX, nls_codepage, remap);
2847 name_len++; /* trailing null */
2849 pSMB->FileName[name_len] = 0;
2850 pSMB->FileName[name_len+1] = 0;
2851 } else { /* BB improve the check for buffer overruns BB */
2852 name_len = strnlen(searchName, PATH_MAX);
2853 name_len++; /* trailing null */
2854 strncpy(pSMB->FileName, searchName, name_len);
2857 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2858 pSMB->TotalDataCount = 0;
2859 pSMB->MaxParameterCount = cpu_to_le16(2);
2860 /* BB find exact max data count below from sess structure BB */
2861 pSMB->MaxDataCount = cpu_to_le16(4000);
2862 pSMB->MaxSetupCount = 0;
2866 pSMB->Reserved2 = 0;
2867 pSMB->ParameterOffset = cpu_to_le16(
2868 offsetof(struct smb_com_transaction2_qpi_req,
2869 InformationLevel) - 4);
2870 pSMB->DataCount = 0;
2871 pSMB->DataOffset = 0;
2872 pSMB->SetupCount = 1;
2873 pSMB->Reserved3 = 0;
2874 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2875 byte_count = params + 1 /* pad */ ;
2876 pSMB->TotalParameterCount = cpu_to_le16(params);
2877 pSMB->ParameterCount = pSMB->TotalParameterCount;
2878 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2879 pSMB->Reserved4 = 0;
2880 pSMB->hdr.smb_buf_length += byte_count;
2881 pSMB->ByteCount = cpu_to_le16(byte_count);
2883 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2884 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2885 cifs_stats_inc(&tcon->num_acl_get);
2887 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2889 /* decode response */
2891 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2892 if (rc || (pSMBr->ByteCount < 2))
2893 /* BB also check enough total bytes returned */
2894 rc = -EIO; /* bad smb */
2896 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2897 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2898 rc = cifs_copy_posix_acl(acl_inf,
2899 (char *)&pSMBr->hdr.Protocol+data_offset,
2900 buflen, acl_type, count);
2903 cifs_buf_release(pSMB);
2910 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2911 const unsigned char *fileName,
2912 const char *local_acl, const int buflen,
2914 const struct nls_table *nls_codepage, int remap)
2916 struct smb_com_transaction2_spi_req *pSMB = NULL;
2917 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2921 int bytes_returned = 0;
2922 __u16 params, byte_count, data_count, param_offset, offset;
2924 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2926 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2930 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2932 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2933 PATH_MAX, nls_codepage, remap);
2934 name_len++; /* trailing null */
2936 } else { /* BB improve the check for buffer overruns BB */
2937 name_len = strnlen(fileName, PATH_MAX);
2938 name_len++; /* trailing null */
2939 strncpy(pSMB->FileName, fileName, name_len);
2941 params = 6 + name_len;
2942 pSMB->MaxParameterCount = cpu_to_le16(2);
2943 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2944 pSMB->MaxSetupCount = 0;
2948 pSMB->Reserved2 = 0;
2949 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2950 InformationLevel) - 4;
2951 offset = param_offset + params;
2952 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2953 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2955 /* convert to on the wire format for POSIX ACL */
2956 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2958 if (data_count == 0) {
2960 goto setACLerrorExit;
2962 pSMB->DataOffset = cpu_to_le16(offset);
2963 pSMB->SetupCount = 1;
2964 pSMB->Reserved3 = 0;
2965 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2966 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2967 byte_count = 3 /* pad */ + params + data_count;
2968 pSMB->DataCount = cpu_to_le16(data_count);
2969 pSMB->TotalDataCount = pSMB->DataCount;
2970 pSMB->ParameterCount = cpu_to_le16(params);
2971 pSMB->TotalParameterCount = pSMB->ParameterCount;
2972 pSMB->Reserved4 = 0;
2973 pSMB->hdr.smb_buf_length += byte_count;
2974 pSMB->ByteCount = cpu_to_le16(byte_count);
2975 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2976 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2978 cFYI(1, ("Set POSIX ACL returned %d", rc));
2982 cifs_buf_release(pSMB);
2988 /* BB fix tabs in this function FIXME BB */
2990 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2991 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2994 struct smb_t2_qfi_req *pSMB = NULL;
2995 struct smb_t2_qfi_rsp *pSMBr = NULL;
2997 __u16 params, byte_count;
2999 cFYI(1, ("In GetExtAttr"));
3004 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3009 params = 2 /* level */ +2 /* fid */;
3010 pSMB->t2.TotalDataCount = 0;
3011 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3012 /* BB find exact max data count below from sess structure BB */
3013 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3014 pSMB->t2.MaxSetupCount = 0;
3015 pSMB->t2.Reserved = 0;
3017 pSMB->t2.Timeout = 0;
3018 pSMB->t2.Reserved2 = 0;
3019 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3021 pSMB->t2.DataCount = 0;
3022 pSMB->t2.DataOffset = 0;
3023 pSMB->t2.SetupCount = 1;
3024 pSMB->t2.Reserved3 = 0;
3025 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3026 byte_count = params + 1 /* pad */ ;
3027 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3028 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3029 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3032 pSMB->hdr.smb_buf_length += byte_count;
3033 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3035 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3036 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3038 cFYI(1, ("error %d in GetExtAttr", rc));
3040 /* decode response */
3041 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3042 if (rc || (pSMBr->ByteCount < 2))
3043 /* BB also check enough total bytes returned */
3044 /* If rc should we check for EOPNOSUPP and
3045 disable the srvino flag? or in caller? */
3046 rc = -EIO; /* bad smb */
3048 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3049 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3050 struct file_chattr_info *pfinfo;
3051 /* BB Do we need a cast or hash here ? */
3053 cFYI(1, ("Illegal size ret in GetExtAttr"));
3057 pfinfo = (struct file_chattr_info *)
3058 (data_offset + (char *) &pSMBr->hdr.Protocol);
3059 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3060 *pMask = le64_to_cpu(pfinfo->mask);
3064 cifs_buf_release(pSMB);
3066 goto GetExtAttrRetry;
3070 #endif /* CONFIG_POSIX */
3072 #ifdef CONFIG_CIFS_EXPERIMENTAL
3073 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3075 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3076 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3080 QUERY_SEC_DESC_REQ * pSMB;
3083 cFYI(1, ("GetCifsACL"));
3088 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3089 8 /* parm len */, tcon, (void **) &pSMB);
3093 pSMB->MaxParameterCount = cpu_to_le32(4);
3094 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3095 pSMB->MaxSetupCount = 0;
3096 pSMB->Fid = fid; /* file handle always le */
3097 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3099 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3100 pSMB->hdr.smb_buf_length += 11;
3101 iov[0].iov_base = (char *)pSMB;
3102 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3104 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3105 0 /* not long op */, 0 /* do not log STATUS codes */ );
3106 cifs_stats_inc(&tcon->num_acl_get);
3108 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3109 } else { /* decode response */
3113 struct smb_com_ntransact_rsp *pSMBr;
3116 /* validate_nttransact */
3117 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3118 &pdata, &parm_len, pbuflen);
3121 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3123 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3125 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3126 rc = -EIO; /* bad smb */
3131 /* BB check that data area is minimum length and as big as acl_len */
3133 acl_len = le32_to_cpu(*parm);
3134 if (acl_len != *pbuflen) {
3135 cERROR(1, ("acl length %d does not match %d",
3136 acl_len, *pbuflen));
3137 if (*pbuflen > acl_len)
3141 /* check if buffer is big enough for the acl
3142 header followed by the smallest SID */
3143 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3144 (*pbuflen >= 64 * 1024)) {
3145 cERROR(1, ("bad acl length %d", *pbuflen));
3149 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3150 if (*acl_inf == NULL) {
3154 memcpy(*acl_inf, pdata, *pbuflen);
3158 if (buf_type == CIFS_SMALL_BUFFER)
3159 cifs_small_buf_release(iov[0].iov_base);
3160 else if (buf_type == CIFS_LARGE_BUFFER)
3161 cifs_buf_release(iov[0].iov_base);
3162 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3165 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3167 /* Legacy Query Path Information call for lookup to old servers such
3169 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3170 const unsigned char *searchName,
3171 FILE_ALL_INFO *pFinfo,
3172 const struct nls_table *nls_codepage, int remap)
3174 QUERY_INFORMATION_REQ * pSMB;
3175 QUERY_INFORMATION_RSP * pSMBr;
3180 cFYI(1, ("In SMBQPath path %s", searchName));
3182 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3187 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3189 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3190 PATH_MAX, nls_codepage, remap);
3191 name_len++; /* trailing null */
3194 name_len = strnlen(searchName, PATH_MAX);
3195 name_len++; /* trailing null */
3196 strncpy(pSMB->FileName, searchName, name_len);
3198 pSMB->BufferFormat = 0x04;
3199 name_len++; /* account for buffer type byte */
3200 pSMB->hdr.smb_buf_length += (__u16) name_len;
3201 pSMB->ByteCount = cpu_to_le16(name_len);
3203 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3204 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3206 cFYI(1, ("Send error in QueryInfo = %d", rc));
3207 } else if (pFinfo) { /* decode response */
3209 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3210 /* BB FIXME - add time zone adjustment BB */
3211 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3214 /* decode time fields */
3215 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3216 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3217 pFinfo->LastAccessTime = 0;
3218 pFinfo->AllocationSize =
3219 cpu_to_le64(le32_to_cpu(pSMBr->size));
3220 pFinfo->EndOfFile = pFinfo->AllocationSize;
3221 pFinfo->Attributes =
3222 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3224 rc = -EIO; /* bad buffer passed in */
3226 cifs_buf_release(pSMB);
3238 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3239 const unsigned char *searchName,
3240 FILE_ALL_INFO * pFindData,
3241 int legacy /* old style infolevel */,
3242 const struct nls_table *nls_codepage, int remap)
3244 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3245 TRANSACTION2_QPI_REQ *pSMB = NULL;
3246 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3250 __u16 params, byte_count;
3252 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3254 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3259 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3261 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3262 PATH_MAX, nls_codepage, remap);
3263 name_len++; /* trailing null */
3265 } else { /* BB improve the check for buffer overruns BB */
3266 name_len = strnlen(searchName, PATH_MAX);
3267 name_len++; /* trailing null */
3268 strncpy(pSMB->FileName, searchName, name_len);
3271 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3272 pSMB->TotalDataCount = 0;
3273 pSMB->MaxParameterCount = cpu_to_le16(2);
3274 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3275 pSMB->MaxSetupCount = 0;
3279 pSMB->Reserved2 = 0;
3280 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3281 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3282 pSMB->DataCount = 0;
3283 pSMB->DataOffset = 0;
3284 pSMB->SetupCount = 1;
3285 pSMB->Reserved3 = 0;
3286 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3287 byte_count = params + 1 /* pad */ ;
3288 pSMB->TotalParameterCount = cpu_to_le16(params);
3289 pSMB->ParameterCount = pSMB->TotalParameterCount;
3291 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3293 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3294 pSMB->Reserved4 = 0;
3295 pSMB->hdr.smb_buf_length += byte_count;
3296 pSMB->ByteCount = cpu_to_le16(byte_count);
3298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3301 cFYI(1, ("Send error in QPathInfo = %d", rc));
3302 } else { /* decode response */
3303 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3305 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3307 else if (!legacy && (pSMBr->ByteCount < 40))
3308 rc = -EIO; /* bad smb */
3309 else if (legacy && (pSMBr->ByteCount < 24))
3310 rc = -EIO; /* 24 or 26 expected but we do not read
3312 else if (pFindData) {
3314 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3315 if (legacy) /* we do not read the last field, EAsize,
3316 fortunately since it varies by subdialect
3317 and on Set vs. Get, is two bytes or 4
3318 bytes depending but we don't care here */
3319 size = sizeof(FILE_INFO_STANDARD);
3321 size = sizeof(FILE_ALL_INFO);
3322 memcpy((char *) pFindData,
3323 (char *) &pSMBr->hdr.Protocol +
3328 cifs_buf_release(pSMB);
3330 goto QPathInfoRetry;
3336 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3337 const unsigned char *searchName,
3338 FILE_UNIX_BASIC_INFO * pFindData,
3339 const struct nls_table *nls_codepage, int remap)
3341 /* SMB_QUERY_FILE_UNIX_BASIC */
3342 TRANSACTION2_QPI_REQ *pSMB = NULL;
3343 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3345 int bytes_returned = 0;
3347 __u16 params, byte_count;
3349 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3351 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3356 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3358 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3359 PATH_MAX, nls_codepage, remap);
3360 name_len++; /* trailing null */
3362 } else { /* BB improve the check for buffer overruns BB */
3363 name_len = strnlen(searchName, PATH_MAX);
3364 name_len++; /* trailing null */
3365 strncpy(pSMB->FileName, searchName, name_len);
3368 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3369 pSMB->TotalDataCount = 0;
3370 pSMB->MaxParameterCount = cpu_to_le16(2);
3371 /* BB find exact max SMB PDU from sess structure BB */
3372 pSMB->MaxDataCount = cpu_to_le16(4000);
3373 pSMB->MaxSetupCount = 0;
3377 pSMB->Reserved2 = 0;
3378 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3379 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3380 pSMB->DataCount = 0;
3381 pSMB->DataOffset = 0;
3382 pSMB->SetupCount = 1;
3383 pSMB->Reserved3 = 0;
3384 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3385 byte_count = params + 1 /* pad */ ;
3386 pSMB->TotalParameterCount = cpu_to_le16(params);
3387 pSMB->ParameterCount = pSMB->TotalParameterCount;
3388 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3389 pSMB->Reserved4 = 0;
3390 pSMB->hdr.smb_buf_length += byte_count;
3391 pSMB->ByteCount = cpu_to_le16(byte_count);
3393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3396 cFYI(1, ("Send error in QPathInfo = %d", rc));
3397 } else { /* decode response */
3398 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3400 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3401 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3402 "Unix Extensions can be disabled on mount "
3403 "by specifying the nosfu mount option."));
3404 rc = -EIO; /* bad smb */
3406 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3407 memcpy((char *) pFindData,
3408 (char *) &pSMBr->hdr.Protocol +
3410 sizeof(FILE_UNIX_BASIC_INFO));
3413 cifs_buf_release(pSMB);
3415 goto UnixQPathInfoRetry;
3420 #if 0 /* function unused at present */
3421 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3422 const char *searchName, FILE_ALL_INFO * findData,
3423 const struct nls_table *nls_codepage)
3425 /* level 257 SMB_ */
3426 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3427 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3431 __u16 params, byte_count;
3433 cFYI(1, ("In FindUnique"));
3435 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3440 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3442 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3443 PATH_MAX, nls_codepage);
3444 name_len++; /* trailing null */
3446 } else { /* BB improve the check for buffer overruns BB */
3447 name_len = strnlen(searchName, PATH_MAX);
3448 name_len++; /* trailing null */
3449 strncpy(pSMB->FileName, searchName, name_len);
3452 params = 12 + name_len /* includes null */ ;
3453 pSMB->TotalDataCount = 0; /* no EAs */
3454 pSMB->MaxParameterCount = cpu_to_le16(2);
3455 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3456 pSMB->MaxSetupCount = 0;
3460 pSMB->Reserved2 = 0;
3461 pSMB->ParameterOffset = cpu_to_le16(
3462 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3463 pSMB->DataCount = 0;
3464 pSMB->DataOffset = 0;
3465 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3466 pSMB->Reserved3 = 0;
3467 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3468 byte_count = params + 1 /* pad */ ;
3469 pSMB->TotalParameterCount = cpu_to_le16(params);
3470 pSMB->ParameterCount = pSMB->TotalParameterCount;
3471 pSMB->SearchAttributes =
3472 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3474 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3475 pSMB->SearchFlags = cpu_to_le16(1);
3476 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3477 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3478 pSMB->hdr.smb_buf_length += byte_count;
3479 pSMB->ByteCount = cpu_to_le16(byte_count);
3481 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3482 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3485 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3486 } else { /* decode response */
3487 cifs_stats_inc(&tcon->num_ffirst);
3491 cifs_buf_release(pSMB);
3493 goto findUniqueRetry;
3497 #endif /* end unused (temporarily) function */
3499 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3501 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3502 const char *searchName,
3503 const struct nls_table *nls_codepage,
3505 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3507 /* level 257 SMB_ */
3508 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3509 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3510 T2_FFIRST_RSP_PARMS * parms;
3512 int bytes_returned = 0;
3514 __u16 params, byte_count;
3516 cFYI(1, ("In FindFirst for %s", searchName));
3519 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3524 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3526 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3527 PATH_MAX, nls_codepage, remap);
3528 /* We can not add the asterik earlier in case
3529 it got remapped to 0xF03A as if it were part of the
3530 directory name instead of a wildcard */
3532 pSMB->FileName[name_len] = dirsep;
3533 pSMB->FileName[name_len+1] = 0;
3534 pSMB->FileName[name_len+2] = '*';
3535 pSMB->FileName[name_len+3] = 0;
3536 name_len += 4; /* now the trailing null */
3537 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3538 pSMB->FileName[name_len+1] = 0;
3540 } else { /* BB add check for overrun of SMB buf BB */
3541 name_len = strnlen(searchName, PATH_MAX);
3542 /* BB fix here and in unicode clause above ie
3543 if (name_len > buffersize-header)
3544 free buffer exit; BB */
3545 strncpy(pSMB->FileName, searchName, name_len);
3546 pSMB->FileName[name_len] = dirsep;
3547 pSMB->FileName[name_len+1] = '*';
3548 pSMB->FileName[name_len+2] = 0;
3552 params = 12 + name_len /* includes null */ ;
3553 pSMB->TotalDataCount = 0; /* no EAs */
3554 pSMB->MaxParameterCount = cpu_to_le16(10);
3555 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3556 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3557 pSMB->MaxSetupCount = 0;
3561 pSMB->Reserved2 = 0;
3562 byte_count = params + 1 /* pad */ ;
3563 pSMB->TotalParameterCount = cpu_to_le16(params);
3564 pSMB->ParameterCount = pSMB->TotalParameterCount;
3565 pSMB->ParameterOffset = cpu_to_le16(
3566 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3568 pSMB->DataCount = 0;
3569 pSMB->DataOffset = 0;
3570 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3571 pSMB->Reserved3 = 0;
3572 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3573 pSMB->SearchAttributes =
3574 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3576 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3577 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3578 CIFS_SEARCH_RETURN_RESUME);
3579 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3581 /* BB what should we set StorageType to? Does it matter? BB */
3582 pSMB->SearchStorageType = 0;
3583 pSMB->hdr.smb_buf_length += byte_count;
3584 pSMB->ByteCount = cpu_to_le16(byte_count);
3586 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3587 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3588 cifs_stats_inc(&tcon->num_ffirst);
3590 if (rc) {/* BB add logic to retry regular search if Unix search
3591 rejected unexpectedly by server */
3592 /* BB Add code to handle unsupported level rc */
3593 cFYI(1, ("Error in FindFirst = %d", rc));
3595 cifs_buf_release(pSMB);
3597 /* BB eventually could optimize out free and realloc of buf */
3600 goto findFirstRetry;
3601 } else { /* decode response */
3602 /* BB remember to free buffer if error BB */
3603 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3605 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3606 psrch_inf->unicode = TRUE;
3608 psrch_inf->unicode = FALSE;
3610 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3611 psrch_inf->smallBuf = 0;
3612 psrch_inf->srch_entries_start =
3613 (char *) &pSMBr->hdr.Protocol +
3614 le16_to_cpu(pSMBr->t2.DataOffset);
3615 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3616 le16_to_cpu(pSMBr->t2.ParameterOffset));
3618 if (parms->EndofSearch)
3619 psrch_inf->endOfSearch = TRUE;
3621 psrch_inf->endOfSearch = FALSE;
3623 psrch_inf->entries_in_buffer =
3624 le16_to_cpu(parms->SearchCount);
3625 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3626 psrch_inf->entries_in_buffer;
3627 *pnetfid = parms->SearchHandle;
3629 cifs_buf_release(pSMB);
3636 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3637 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3639 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3640 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3641 T2_FNEXT_RSP_PARMS * parms;
3642 char *response_data;
3644 int bytes_returned, name_len;
3645 __u16 params, byte_count;
3647 cFYI(1, ("In FindNext"));
3649 if (psrch_inf->endOfSearch == TRUE)
3652 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3657 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3659 pSMB->TotalDataCount = 0; /* no EAs */
3660 pSMB->MaxParameterCount = cpu_to_le16(8);
3661 pSMB->MaxDataCount =
3662 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3664 pSMB->MaxSetupCount = 0;
3668 pSMB->Reserved2 = 0;
3669 pSMB->ParameterOffset = cpu_to_le16(
3670 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3671 pSMB->DataCount = 0;
3672 pSMB->DataOffset = 0;
3673 pSMB->SetupCount = 1;
3674 pSMB->Reserved3 = 0;
3675 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3676 pSMB->SearchHandle = searchHandle; /* always kept as le */
3678 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3679 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3680 pSMB->ResumeKey = psrch_inf->resume_key;
3682 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3684 name_len = psrch_inf->resume_name_len;
3686 if (name_len < PATH_MAX) {
3687 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3688 byte_count += name_len;
3689 /* 14 byte parm len above enough for 2 byte null terminator */
3690 pSMB->ResumeFileName[name_len] = 0;
3691 pSMB->ResumeFileName[name_len+1] = 0;
3694 goto FNext2_err_exit;
3696 byte_count = params + 1 /* pad */ ;
3697 pSMB->TotalParameterCount = cpu_to_le16(params);
3698 pSMB->ParameterCount = pSMB->TotalParameterCount;
3699 pSMB->hdr.smb_buf_length += byte_count;
3700 pSMB->ByteCount = cpu_to_le16(byte_count);
3702 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3703 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3704 cifs_stats_inc(&tcon->num_fnext);
3707 psrch_inf->endOfSearch = TRUE;
3708 rc = 0; /* search probably was closed at end of search*/
3710 cFYI(1, ("FindNext returned = %d", rc));
3711 } else { /* decode response */
3712 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3715 /* BB fixme add lock for file (srch_info) struct here */
3716 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3717 psrch_inf->unicode = TRUE;
3719 psrch_inf->unicode = FALSE;
3720 response_data = (char *) &pSMBr->hdr.Protocol +
3721 le16_to_cpu(pSMBr->t2.ParameterOffset);
3722 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3723 response_data = (char *)&pSMBr->hdr.Protocol +
3724 le16_to_cpu(pSMBr->t2.DataOffset);
3725 if (psrch_inf->smallBuf)
3726 cifs_small_buf_release(
3727 psrch_inf->ntwrk_buf_start);
3729 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3730 psrch_inf->srch_entries_start = response_data;
3731 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3732 psrch_inf->smallBuf = 0;
3733 if (parms->EndofSearch)
3734 psrch_inf->endOfSearch = TRUE;
3736 psrch_inf->endOfSearch = FALSE;
3737 psrch_inf->entries_in_buffer =
3738 le16_to_cpu(parms->SearchCount);
3739 psrch_inf->index_of_last_entry +=
3740 psrch_inf->entries_in_buffer;
3741 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3742 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3744 /* BB fixme add unlock here */
3749 /* BB On error, should we leave previous search buf (and count and
3750 last entry fields) intact or free the previous one? */
3752 /* Note: On -EAGAIN error only caller can retry on handle based calls
3753 since file handle passed in no longer valid */
3756 cifs_buf_release(pSMB);
3761 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3762 const __u16 searchHandle)
3765 FINDCLOSE_REQ *pSMB = NULL;
3766 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3769 cFYI(1, ("In CIFSSMBFindClose"));
3770 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3772 /* no sense returning error if session restarted
3773 as file handle has been closed */
3779 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3780 pSMB->FileID = searchHandle;
3781 pSMB->ByteCount = 0;
3782 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3783 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3785 cERROR(1, ("Send error in FindClose = %d", rc));
3787 cifs_stats_inc(&tcon->num_fclose);
3788 cifs_small_buf_release(pSMB);
3790 /* Since session is dead, search handle closed on server already */
3798 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3799 const unsigned char *searchName,
3800 __u64 * inode_number,
3801 const struct nls_table *nls_codepage, int remap)
3804 TRANSACTION2_QPI_REQ *pSMB = NULL;
3805 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3806 int name_len, bytes_returned;
3807 __u16 params, byte_count;
3809 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3813 GetInodeNumberRetry:
3814 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3819 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3821 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3822 PATH_MAX, nls_codepage, remap);
3823 name_len++; /* trailing null */
3825 } else { /* BB improve the check for buffer overruns BB */
3826 name_len = strnlen(searchName, PATH_MAX);
3827 name_len++; /* trailing null */
3828 strncpy(pSMB->FileName, searchName, name_len);
3831 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3832 pSMB->TotalDataCount = 0;
3833 pSMB->MaxParameterCount = cpu_to_le16(2);
3834 /* BB find exact max data count below from sess structure BB */
3835 pSMB->MaxDataCount = cpu_to_le16(4000);
3836 pSMB->MaxSetupCount = 0;
3840 pSMB->Reserved2 = 0;
3841 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3842 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3843 pSMB->DataCount = 0;
3844 pSMB->DataOffset = 0;
3845 pSMB->SetupCount = 1;
3846 pSMB->Reserved3 = 0;
3847 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3848 byte_count = params + 1 /* pad */ ;
3849 pSMB->TotalParameterCount = cpu_to_le16(params);
3850 pSMB->ParameterCount = pSMB->TotalParameterCount;
3851 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3852 pSMB->Reserved4 = 0;
3853 pSMB->hdr.smb_buf_length += byte_count;
3854 pSMB->ByteCount = cpu_to_le16(byte_count);
3856 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3857 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3859 cFYI(1, ("error %d in QueryInternalInfo", rc));
3861 /* decode response */
3862 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3863 if (rc || (pSMBr->ByteCount < 2))
3864 /* BB also check enough total bytes returned */
3865 /* If rc should we check for EOPNOSUPP and
3866 disable the srvino flag? or in caller? */
3867 rc = -EIO; /* bad smb */
3869 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3870 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3871 struct file_internal_info *pfinfo;
3872 /* BB Do we need a cast or hash here ? */
3874 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3876 goto GetInodeNumOut;
3878 pfinfo = (struct file_internal_info *)
3879 (data_offset + (char *) &pSMBr->hdr.Protocol);
3880 *inode_number = pfinfo->UniqueId;
3884 cifs_buf_release(pSMB);
3886 goto GetInodeNumberRetry;
3891 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3892 const unsigned char *searchName,
3893 unsigned char **targetUNCs,
3894 unsigned int *number_of_UNC_in_array,
3895 const struct nls_table *nls_codepage, int remap)
3897 /* TRANS2_GET_DFS_REFERRAL */
3898 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3899 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3900 struct dfs_referral_level_3 *referrals = NULL;
3906 __u16 params, byte_count;
3907 *number_of_UNC_in_array = 0;
3910 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3914 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3919 /* server pointer checked in called function,
3920 but should never be null here anyway */
3921 pSMB->hdr.Mid = GetNextMid(ses->server);
3922 pSMB->hdr.Tid = ses->ipc_tid;
3923 pSMB->hdr.Uid = ses->Suid;
3924 if (ses->capabilities & CAP_STATUS32)
3925 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3926 if (ses->capabilities & CAP_DFS)
3927 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3929 if (ses->capabilities & CAP_UNICODE) {
3930 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3932 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3933 searchName, PATH_MAX, nls_codepage, remap);
3934 name_len++; /* trailing null */
3936 } else { /* BB improve the check for buffer overruns BB */
3937 name_len = strnlen(searchName, PATH_MAX);
3938 name_len++; /* trailing null */
3939 strncpy(pSMB->RequestFileName, searchName, name_len);
3943 if (ses->server->secMode &
3944 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3945 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3948 pSMB->hdr.Uid = ses->Suid;
3950 params = 2 /* level */ + name_len /*includes null */ ;
3951 pSMB->TotalDataCount = 0;
3952 pSMB->DataCount = 0;
3953 pSMB->DataOffset = 0;
3954 pSMB->MaxParameterCount = 0;
3955 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3956 pSMB->MaxSetupCount = 0;
3960 pSMB->Reserved2 = 0;
3961 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3962 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3963 pSMB->SetupCount = 1;
3964 pSMB->Reserved3 = 0;
3965 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3966 byte_count = params + 3 /* pad */ ;
3967 pSMB->ParameterCount = cpu_to_le16(params);
3968 pSMB->TotalParameterCount = pSMB->ParameterCount;
3969 pSMB->MaxReferralLevel = cpu_to_le16(3);
3970 pSMB->hdr.smb_buf_length += byte_count;
3971 pSMB->ByteCount = cpu_to_le16(byte_count);
3973 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3976 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3977 } else { /* decode response */
3978 /* BB Add logic to parse referrals here */
3979 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3981 /* BB Also check if enough total bytes returned? */
3982 if (rc || (pSMBr->ByteCount < 17))
3983 rc = -EIO; /* bad smb */
3985 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3986 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3989 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3990 pSMBr->ByteCount, data_offset));
3992 (struct dfs_referral_level_3 *)
3993 (8 /* sizeof start of data block */ +
3995 (char *) &pSMBr->hdr.Protocol);
3996 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3997 "for referral one refer size: 0x%x srv "
3998 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3999 le16_to_cpu(pSMBr->NumberOfReferrals),
4000 le16_to_cpu(pSMBr->DFSFlags),
4001 le16_to_cpu(referrals->ReferralSize),
4002 le16_to_cpu(referrals->ServerType),
4003 le16_to_cpu(referrals->ReferralFlags),
4004 le16_to_cpu(referrals->TimeToLive)));
4005 /* BB This field is actually two bytes in from start of
4006 data block so we could do safety check that DataBlock
4007 begins at address of pSMBr->NumberOfReferrals */
4008 *number_of_UNC_in_array =
4009 le16_to_cpu(pSMBr->NumberOfReferrals);
4011 /* BB Fix below so can return more than one referral */
4012 if (*number_of_UNC_in_array > 1)
4013 *number_of_UNC_in_array = 1;
4015 /* get the length of the strings describing refs */
4017 for (i = 0; i < *number_of_UNC_in_array; i++) {
4018 /* make sure that DfsPathOffset not past end */
4020 le16_to_cpu(referrals->DfsPathOffset);
4021 if (offset > data_count) {
4022 /* if invalid referral, stop here and do
4023 not try to copy any more */
4024 *number_of_UNC_in_array = i;
4027 temp = ((char *)referrals) + offset;
4029 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4030 name_len += UniStrnlen((wchar_t *)temp,
4033 name_len += strnlen(temp, data_count);
4036 /* BB add check that referral pointer does
4037 not fall off end PDU */
4039 /* BB add check for name_len bigger than bcc */
4041 kmalloc(name_len+1+(*number_of_UNC_in_array),
4043 if (*targetUNCs == NULL) {
4047 /* copy the ref strings */
4048 referrals = (struct dfs_referral_level_3 *)
4049 (8 /* sizeof data hdr */ + data_offset +
4050 (char *) &pSMBr->hdr.Protocol);
4052 for (i = 0; i < *number_of_UNC_in_array; i++) {
4053 temp = ((char *)referrals) +
4054 le16_to_cpu(referrals->DfsPathOffset);
4055 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4056 cifs_strfromUCS_le(*targetUNCs,
4061 strncpy(*targetUNCs, temp, name_len);
4063 /* BB update target_uncs pointers */
4073 cifs_buf_release(pSMB);
4081 /* Query File System Info such as free space to old servers such as Win 9x */
4083 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4085 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4086 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4087 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4088 FILE_SYSTEM_ALLOC_INFO *response_data;
4090 int bytes_returned = 0;
4091 __u16 params, byte_count;
4093 cFYI(1, ("OldQFSInfo"));
4095 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4100 params = 2; /* level */
4101 pSMB->TotalDataCount = 0;
4102 pSMB->MaxParameterCount = cpu_to_le16(2);
4103 pSMB->MaxDataCount = cpu_to_le16(1000);
4104 pSMB->MaxSetupCount = 0;
4108 pSMB->Reserved2 = 0;
4109 byte_count = params + 1 /* pad */ ;
4110 pSMB->TotalParameterCount = cpu_to_le16(params);
4111 pSMB->ParameterCount = pSMB->TotalParameterCount;
4112 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4113 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4114 pSMB->DataCount = 0;
4115 pSMB->DataOffset = 0;
4116 pSMB->SetupCount = 1;
4117 pSMB->Reserved3 = 0;
4118 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4119 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4120 pSMB->hdr.smb_buf_length += byte_count;
4121 pSMB->ByteCount = cpu_to_le16(byte_count);
4123 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4124 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4126 cFYI(1, ("Send error in QFSInfo = %d", rc));
4127 } else { /* decode response */
4128 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4130 if (rc || (pSMBr->ByteCount < 18))
4131 rc = -EIO; /* bad smb */
4133 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4134 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4135 pSMBr->ByteCount, data_offset));
4137 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4138 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4140 le16_to_cpu(response_data->BytesPerSector) *
4141 le32_to_cpu(response_data->
4142 SectorsPerAllocationUnit);
4144 le32_to_cpu(response_data->TotalAllocationUnits);
4145 FSData->f_bfree = FSData->f_bavail =
4146 le32_to_cpu(response_data->FreeAllocationUnits);
4148 ("Blocks: %lld Free: %lld Block size %ld",
4149 (unsigned long long)FSData->f_blocks,
4150 (unsigned long long)FSData->f_bfree,
4154 cifs_buf_release(pSMB);
4157 goto oldQFSInfoRetry;
4163 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4165 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4166 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4167 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4168 FILE_SYSTEM_INFO *response_data;
4170 int bytes_returned = 0;
4171 __u16 params, byte_count;
4173 cFYI(1, ("In QFSInfo"));
4175 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4180 params = 2; /* level */
4181 pSMB->TotalDataCount = 0;
4182 pSMB->MaxParameterCount = cpu_to_le16(2);
4183 pSMB->MaxDataCount = cpu_to_le16(1000);
4184 pSMB->MaxSetupCount = 0;
4188 pSMB->Reserved2 = 0;
4189 byte_count = params + 1 /* pad */ ;
4190 pSMB->TotalParameterCount = cpu_to_le16(params);
4191 pSMB->ParameterCount = pSMB->TotalParameterCount;
4192 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4193 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4194 pSMB->DataCount = 0;
4195 pSMB->DataOffset = 0;
4196 pSMB->SetupCount = 1;
4197 pSMB->Reserved3 = 0;
4198 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4199 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4200 pSMB->hdr.smb_buf_length += byte_count;
4201 pSMB->ByteCount = cpu_to_le16(byte_count);
4203 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4204 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4206 cFYI(1, ("Send error in QFSInfo = %d", rc));
4207 } else { /* decode response */
4208 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4210 if (rc || (pSMBr->ByteCount < 24))
4211 rc = -EIO; /* bad smb */
4213 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4217 *) (((char *) &pSMBr->hdr.Protocol) +
4220 le32_to_cpu(response_data->BytesPerSector) *
4221 le32_to_cpu(response_data->
4222 SectorsPerAllocationUnit);
4224 le64_to_cpu(response_data->TotalAllocationUnits);
4225 FSData->f_bfree = FSData->f_bavail =
4226 le64_to_cpu(response_data->FreeAllocationUnits);
4228 ("Blocks: %lld Free: %lld Block size %ld",
4229 (unsigned long long)FSData->f_blocks,
4230 (unsigned long long)FSData->f_bfree,
4234 cifs_buf_release(pSMB);
4243 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4245 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4246 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4247 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4248 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4250 int bytes_returned = 0;
4251 __u16 params, byte_count;
4253 cFYI(1, ("In QFSAttributeInfo"));
4255 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4260 params = 2; /* level */
4261 pSMB->TotalDataCount = 0;
4262 pSMB->MaxParameterCount = cpu_to_le16(2);
4263 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4264 pSMB->MaxSetupCount = 0;
4268 pSMB->Reserved2 = 0;
4269 byte_count = params + 1 /* pad */ ;
4270 pSMB->TotalParameterCount = cpu_to_le16(params);
4271 pSMB->ParameterCount = pSMB->TotalParameterCount;
4272 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4273 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4274 pSMB->DataCount = 0;
4275 pSMB->DataOffset = 0;
4276 pSMB->SetupCount = 1;
4277 pSMB->Reserved3 = 0;
4278 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4279 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4280 pSMB->hdr.smb_buf_length += byte_count;
4281 pSMB->ByteCount = cpu_to_le16(byte_count);
4283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4284 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4286 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4287 } else { /* decode response */
4288 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4290 if (rc || (pSMBr->ByteCount < 13)) {
4291 /* BB also check if enough bytes returned */
4292 rc = -EIO; /* bad smb */
4294 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4296 (FILE_SYSTEM_ATTRIBUTE_INFO
4297 *) (((char *) &pSMBr->hdr.Protocol) +
4299 memcpy(&tcon->fsAttrInfo, response_data,
4300 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4303 cifs_buf_release(pSMB);
4306 goto QFSAttributeRetry;
4312 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4314 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4315 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4316 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4317 FILE_SYSTEM_DEVICE_INFO *response_data;
4319 int bytes_returned = 0;
4320 __u16 params, byte_count;
4322 cFYI(1, ("In QFSDeviceInfo"));
4324 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4329 params = 2; /* level */
4330 pSMB->TotalDataCount = 0;
4331 pSMB->MaxParameterCount = cpu_to_le16(2);
4332 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4333 pSMB->MaxSetupCount = 0;
4337 pSMB->Reserved2 = 0;
4338 byte_count = params + 1 /* pad */ ;
4339 pSMB->TotalParameterCount = cpu_to_le16(params);
4340 pSMB->ParameterCount = pSMB->TotalParameterCount;
4341 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4342 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4344 pSMB->DataCount = 0;
4345 pSMB->DataOffset = 0;
4346 pSMB->SetupCount = 1;
4347 pSMB->Reserved3 = 0;
4348 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4349 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4350 pSMB->hdr.smb_buf_length += byte_count;
4351 pSMB->ByteCount = cpu_to_le16(byte_count);
4353 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4354 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4356 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4357 } else { /* decode response */
4358 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4360 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4361 rc = -EIO; /* bad smb */
4363 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4365 (FILE_SYSTEM_DEVICE_INFO *)
4366 (((char *) &pSMBr->hdr.Protocol) +
4368 memcpy(&tcon->fsDevInfo, response_data,
4369 sizeof(FILE_SYSTEM_DEVICE_INFO));
4372 cifs_buf_release(pSMB);
4375 goto QFSDeviceRetry;
4381 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4383 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4384 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4385 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4386 FILE_SYSTEM_UNIX_INFO *response_data;
4388 int bytes_returned = 0;
4389 __u16 params, byte_count;
4391 cFYI(1, ("In QFSUnixInfo"));
4393 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4398 params = 2; /* level */
4399 pSMB->TotalDataCount = 0;
4400 pSMB->DataCount = 0;
4401 pSMB->DataOffset = 0;
4402 pSMB->MaxParameterCount = cpu_to_le16(2);
4403 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4404 pSMB->MaxSetupCount = 0;
4408 pSMB->Reserved2 = 0;
4409 byte_count = params + 1 /* pad */ ;
4410 pSMB->ParameterCount = cpu_to_le16(params);
4411 pSMB->TotalParameterCount = pSMB->ParameterCount;
4412 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4413 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4414 pSMB->SetupCount = 1;
4415 pSMB->Reserved3 = 0;
4416 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4417 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4418 pSMB->hdr.smb_buf_length += byte_count;
4419 pSMB->ByteCount = cpu_to_le16(byte_count);
4421 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4422 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4424 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4425 } else { /* decode response */
4426 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4428 if (rc || (pSMBr->ByteCount < 13)) {
4429 rc = -EIO; /* bad smb */
4431 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4433 (FILE_SYSTEM_UNIX_INFO
4434 *) (((char *) &pSMBr->hdr.Protocol) +
4436 memcpy(&tcon->fsUnixInfo, response_data,
4437 sizeof(FILE_SYSTEM_UNIX_INFO));
4440 cifs_buf_release(pSMB);
4450 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4452 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4453 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4454 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4456 int bytes_returned = 0;
4457 __u16 params, param_offset, offset, byte_count;
4459 cFYI(1, ("In SETFSUnixInfo"));
4461 /* BB switch to small buf init to save memory */
4462 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4467 params = 4; /* 2 bytes zero followed by info level. */
4468 pSMB->MaxSetupCount = 0;
4472 pSMB->Reserved2 = 0;
4473 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4475 offset = param_offset + params;
4477 pSMB->MaxParameterCount = cpu_to_le16(4);
4478 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4479 pSMB->SetupCount = 1;
4480 pSMB->Reserved3 = 0;
4481 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4482 byte_count = 1 /* pad */ + params + 12;
4484 pSMB->DataCount = cpu_to_le16(12);
4485 pSMB->ParameterCount = cpu_to_le16(params);
4486 pSMB->TotalDataCount = pSMB->DataCount;
4487 pSMB->TotalParameterCount = pSMB->ParameterCount;
4488 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4489 pSMB->DataOffset = cpu_to_le16(offset);
4493 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4496 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4497 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4498 pSMB->ClientUnixCap = cpu_to_le64(cap);
4500 pSMB->hdr.smb_buf_length += byte_count;
4501 pSMB->ByteCount = cpu_to_le16(byte_count);
4503 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4504 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4506 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4507 } else { /* decode response */
4508 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4510 rc = -EIO; /* bad smb */
4513 cifs_buf_release(pSMB);
4516 goto SETFSUnixRetry;
4524 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4525 struct kstatfs *FSData)
4527 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4528 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4529 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4530 FILE_SYSTEM_POSIX_INFO *response_data;
4532 int bytes_returned = 0;
4533 __u16 params, byte_count;
4535 cFYI(1, ("In QFSPosixInfo"));
4537 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4542 params = 2; /* level */
4543 pSMB->TotalDataCount = 0;
4544 pSMB->DataCount = 0;
4545 pSMB->DataOffset = 0;
4546 pSMB->MaxParameterCount = cpu_to_le16(2);
4547 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4548 pSMB->MaxSetupCount = 0;
4552 pSMB->Reserved2 = 0;
4553 byte_count = params + 1 /* pad */ ;
4554 pSMB->ParameterCount = cpu_to_le16(params);
4555 pSMB->TotalParameterCount = pSMB->ParameterCount;
4556 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4557 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4558 pSMB->SetupCount = 1;
4559 pSMB->Reserved3 = 0;
4560 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4561 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4562 pSMB->hdr.smb_buf_length += byte_count;
4563 pSMB->ByteCount = cpu_to_le16(byte_count);
4565 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4566 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4568 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4569 } else { /* decode response */
4570 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4572 if (rc || (pSMBr->ByteCount < 13)) {
4573 rc = -EIO; /* bad smb */
4575 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4577 (FILE_SYSTEM_POSIX_INFO
4578 *) (((char *) &pSMBr->hdr.Protocol) +
4581 le32_to_cpu(response_data->BlockSize);
4583 le64_to_cpu(response_data->TotalBlocks);
4585 le64_to_cpu(response_data->BlocksAvail);
4586 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4587 FSData->f_bavail = FSData->f_bfree;
4590 le64_to_cpu(response_data->UserBlocksAvail);
4592 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4594 le64_to_cpu(response_data->TotalFileNodes);
4595 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4597 le64_to_cpu(response_data->FreeFileNodes);
4600 cifs_buf_release(pSMB);
4609 /* We can not use write of zero bytes trick to
4610 set file size due to need for large file support. Also note that
4611 this SetPathInfo is preferred to SetFileInfo based method in next
4612 routine which is only needed to work around a sharing violation bug
4613 in Samba which this routine can run into */
4616 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4617 __u64 size, int SetAllocation,
4618 const struct nls_table *nls_codepage, int remap)
4620 struct smb_com_transaction2_spi_req *pSMB = NULL;
4621 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4622 struct file_end_of_file_info *parm_data;
4625 int bytes_returned = 0;
4626 __u16 params, byte_count, data_count, param_offset, offset;
4628 cFYI(1, ("In SetEOF"));
4630 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4635 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4637 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4638 PATH_MAX, nls_codepage, remap);
4639 name_len++; /* trailing null */
4641 } else { /* BB improve the check for buffer overruns BB */
4642 name_len = strnlen(fileName, PATH_MAX);
4643 name_len++; /* trailing null */
4644 strncpy(pSMB->FileName, fileName, name_len);
4646 params = 6 + name_len;
4647 data_count = sizeof(struct file_end_of_file_info);
4648 pSMB->MaxParameterCount = cpu_to_le16(2);
4649 pSMB->MaxDataCount = cpu_to_le16(4100);
4650 pSMB->MaxSetupCount = 0;
4654 pSMB->Reserved2 = 0;
4655 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4656 InformationLevel) - 4;
4657 offset = param_offset + params;
4658 if (SetAllocation) {
4659 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4660 pSMB->InformationLevel =
4661 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4663 pSMB->InformationLevel =
4664 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4665 } else /* Set File Size */ {
4666 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4667 pSMB->InformationLevel =
4668 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4670 pSMB->InformationLevel =
4671 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4675 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4677 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4678 pSMB->DataOffset = cpu_to_le16(offset);
4679 pSMB->SetupCount = 1;
4680 pSMB->Reserved3 = 0;
4681 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4682 byte_count = 3 /* pad */ + params + data_count;
4683 pSMB->DataCount = cpu_to_le16(data_count);
4684 pSMB->TotalDataCount = pSMB->DataCount;
4685 pSMB->ParameterCount = cpu_to_le16(params);
4686 pSMB->TotalParameterCount = pSMB->ParameterCount;
4687 pSMB->Reserved4 = 0;
4688 pSMB->hdr.smb_buf_length += byte_count;
4689 parm_data->FileSize = cpu_to_le64(size);
4690 pSMB->ByteCount = cpu_to_le16(byte_count);
4691 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4692 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4694 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4697 cifs_buf_release(pSMB);
4706 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4707 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4709 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4710 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4712 struct file_end_of_file_info *parm_data;
4714 int bytes_returned = 0;
4715 __u16 params, param_offset, offset, byte_count, count;
4717 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4719 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4724 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4726 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4727 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4730 pSMB->MaxSetupCount = 0;
4734 pSMB->Reserved2 = 0;
4735 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4736 offset = param_offset + params;
4738 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4740 count = sizeof(struct file_end_of_file_info);
4741 pSMB->MaxParameterCount = cpu_to_le16(2);
4742 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4743 pSMB->SetupCount = 1;
4744 pSMB->Reserved3 = 0;
4745 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4746 byte_count = 3 /* pad */ + params + count;
4747 pSMB->DataCount = cpu_to_le16(count);
4748 pSMB->ParameterCount = cpu_to_le16(params);
4749 pSMB->TotalDataCount = pSMB->DataCount;
4750 pSMB->TotalParameterCount = pSMB->ParameterCount;
4751 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4753 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4755 pSMB->DataOffset = cpu_to_le16(offset);
4756 parm_data->FileSize = cpu_to_le64(size);
4758 if (SetAllocation) {
4759 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4760 pSMB->InformationLevel =
4761 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4763 pSMB->InformationLevel =
4764 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4765 } else /* Set File Size */ {
4766 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4767 pSMB->InformationLevel =
4768 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4770 pSMB->InformationLevel =
4771 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4773 pSMB->Reserved4 = 0;
4774 pSMB->hdr.smb_buf_length += byte_count;
4775 pSMB->ByteCount = cpu_to_le16(byte_count);
4776 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4777 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4780 ("Send error in SetFileInfo (SetFileSize) = %d",
4785 cifs_small_buf_release(pSMB);
4787 /* Note: On -EAGAIN error only caller can retry on handle based calls
4788 since file handle passed in no longer valid */
4793 /* Some legacy servers such as NT4 require that the file times be set on
4794 an open handle, rather than by pathname - this is awkward due to
4795 potential access conflicts on the open, but it is unavoidable for these
4796 old servers since the only other choice is to go from 100 nanosecond DCE
4797 time and resort to the original setpathinfo level which takes the ancient
4798 DOS time format with 2 second granularity */
4800 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4801 const FILE_BASIC_INFO *data, __u16 fid)
4803 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4804 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4807 int bytes_returned = 0;
4808 __u16 params, param_offset, offset, byte_count, count;
4810 cFYI(1, ("Set Times (via SetFileInfo)"));
4811 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4816 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4818 /* At this point there is no need to override the current pid
4819 with the pid of the opener, but that could change if we someday
4820 use an existing handle (rather than opening one on the fly) */
4821 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4822 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4825 pSMB->MaxSetupCount = 0;
4829 pSMB->Reserved2 = 0;
4830 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4831 offset = param_offset + params;
4833 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4835 count = sizeof(FILE_BASIC_INFO);
4836 pSMB->MaxParameterCount = cpu_to_le16(2);
4837 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4838 pSMB->SetupCount = 1;
4839 pSMB->Reserved3 = 0;
4840 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4841 byte_count = 3 /* pad */ + params + count;
4842 pSMB->DataCount = cpu_to_le16(count);
4843 pSMB->ParameterCount = cpu_to_le16(params);
4844 pSMB->TotalDataCount = pSMB->DataCount;
4845 pSMB->TotalParameterCount = pSMB->ParameterCount;
4846 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4847 pSMB->DataOffset = cpu_to_le16(offset);
4849 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4850 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4852 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4853 pSMB->Reserved4 = 0;
4854 pSMB->hdr.smb_buf_length += byte_count;
4855 pSMB->ByteCount = cpu_to_le16(byte_count);
4856 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4857 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4858 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4860 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4863 cifs_small_buf_release(pSMB);
4865 /* Note: On -EAGAIN error only caller can retry on handle based calls
4866 since file handle passed in no longer valid */
4873 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4874 const FILE_BASIC_INFO *data,
4875 const struct nls_table *nls_codepage, int remap)
4877 TRANSACTION2_SPI_REQ *pSMB = NULL;
4878 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4881 int bytes_returned = 0;
4883 __u16 params, param_offset, offset, byte_count, count;
4885 cFYI(1, ("In SetTimes"));
4888 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4893 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4895 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4896 PATH_MAX, nls_codepage, remap);
4897 name_len++; /* trailing null */
4899 } else { /* BB improve the check for buffer overruns BB */
4900 name_len = strnlen(fileName, PATH_MAX);
4901 name_len++; /* trailing null */
4902 strncpy(pSMB->FileName, fileName, name_len);
4905 params = 6 + name_len;
4906 count = sizeof(FILE_BASIC_INFO);
4907 pSMB->MaxParameterCount = cpu_to_le16(2);
4908 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4909 pSMB->MaxSetupCount = 0;
4913 pSMB->Reserved2 = 0;
4914 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4915 InformationLevel) - 4;
4916 offset = param_offset + params;
4917 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4918 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4919 pSMB->DataOffset = cpu_to_le16(offset);
4920 pSMB->SetupCount = 1;
4921 pSMB->Reserved3 = 0;
4922 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4923 byte_count = 3 /* pad */ + params + count;
4925 pSMB->DataCount = cpu_to_le16(count);
4926 pSMB->ParameterCount = cpu_to_le16(params);
4927 pSMB->TotalDataCount = pSMB->DataCount;
4928 pSMB->TotalParameterCount = pSMB->ParameterCount;
4929 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4930 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4932 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4933 pSMB->Reserved4 = 0;
4934 pSMB->hdr.smb_buf_length += byte_count;
4935 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4936 pSMB->ByteCount = cpu_to_le16(byte_count);
4937 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4940 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4943 cifs_buf_release(pSMB);
4951 /* Can not be used to set time stamps yet (due to old DOS time format) */
4952 /* Can be used to set attributes */
4953 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4954 handling it anyway and NT4 was what we thought it would be needed for
4955 Do not delete it until we prove whether needed for Win9x though */
4957 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4958 __u16 dos_attrs, const struct nls_table *nls_codepage)
4960 SETATTR_REQ *pSMB = NULL;
4961 SETATTR_RSP *pSMBr = NULL;
4966 cFYI(1, ("In SetAttrLegacy"));
4969 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4974 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4976 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4977 PATH_MAX, nls_codepage);
4978 name_len++; /* trailing null */
4980 } else { /* BB improve the check for buffer overruns BB */
4981 name_len = strnlen(fileName, PATH_MAX);
4982 name_len++; /* trailing null */
4983 strncpy(pSMB->fileName, fileName, name_len);
4985 pSMB->attr = cpu_to_le16(dos_attrs);
4986 pSMB->BufferFormat = 0x04;
4987 pSMB->hdr.smb_buf_length += name_len + 1;
4988 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4989 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4990 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4992 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4995 cifs_buf_release(pSMB);
4998 goto SetAttrLgcyRetry;
5002 #endif /* temporarily unneeded SetAttr legacy function */
5005 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
5006 char *fileName, __u64 mode, __u64 uid, __u64 gid,
5007 dev_t device, const struct nls_table *nls_codepage,
5010 TRANSACTION2_SPI_REQ *pSMB = NULL;
5011 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5014 int bytes_returned = 0;
5015 FILE_UNIX_BASIC_INFO *data_offset;
5016 __u16 params, param_offset, offset, count, byte_count;
5018 cFYI(1, ("In SetUID/GID/Mode"));
5020 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5027 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5028 PATH_MAX, nls_codepage, remap);
5029 name_len++; /* trailing null */
5031 } else { /* BB improve the check for buffer overruns BB */
5032 name_len = strnlen(fileName, PATH_MAX);
5033 name_len++; /* trailing null */
5034 strncpy(pSMB->FileName, fileName, name_len);
5037 params = 6 + name_len;
5038 count = sizeof(FILE_UNIX_BASIC_INFO);
5039 pSMB->MaxParameterCount = cpu_to_le16(2);
5040 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5041 pSMB->MaxSetupCount = 0;
5045 pSMB->Reserved2 = 0;
5046 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5047 InformationLevel) - 4;
5048 offset = param_offset + params;
5050 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5052 memset(data_offset, 0, count);
5053 pSMB->DataOffset = cpu_to_le16(offset);
5054 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5055 pSMB->SetupCount = 1;
5056 pSMB->Reserved3 = 0;
5057 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5058 byte_count = 3 /* pad */ + params + count;
5059 pSMB->ParameterCount = cpu_to_le16(params);
5060 pSMB->DataCount = cpu_to_le16(count);
5061 pSMB->TotalParameterCount = pSMB->ParameterCount;
5062 pSMB->TotalDataCount = pSMB->DataCount;
5063 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5064 pSMB->Reserved4 = 0;
5065 pSMB->hdr.smb_buf_length += byte_count;
5066 /* Samba server ignores set of file size to zero due to bugs in some
5067 older clients, but we should be precise - we use SetFileSize to
5068 set file size and do not want to truncate file size to zero
5069 accidently as happened on one Samba server beta by putting
5070 zero instead of -1 here */
5071 data_offset->EndOfFile = NO_CHANGE_64;
5072 data_offset->NumOfBytes = NO_CHANGE_64;
5073 data_offset->LastStatusChange = NO_CHANGE_64;
5074 data_offset->LastAccessTime = NO_CHANGE_64;
5075 data_offset->LastModificationTime = NO_CHANGE_64;
5076 data_offset->Uid = cpu_to_le64(uid);
5077 data_offset->Gid = cpu_to_le64(gid);
5078 /* better to leave device as zero when it is */
5079 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5080 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5081 data_offset->Permissions = cpu_to_le64(mode);
5084 data_offset->Type = cpu_to_le32(UNIX_FILE);
5085 else if (S_ISDIR(mode))
5086 data_offset->Type = cpu_to_le32(UNIX_DIR);
5087 else if (S_ISLNK(mode))
5088 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5089 else if (S_ISCHR(mode))
5090 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5091 else if (S_ISBLK(mode))
5092 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5093 else if (S_ISFIFO(mode))
5094 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5095 else if (S_ISSOCK(mode))
5096 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5099 pSMB->ByteCount = cpu_to_le16(byte_count);
5100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5101 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5103 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5107 cifs_buf_release(pSMB);
5113 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5114 const int notify_subdirs, const __u16 netfid,
5115 __u32 filter, struct file *pfile, int multishot,
5116 const struct nls_table *nls_codepage)
5119 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5120 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5121 struct dir_notify_req *dnotify_req;
5124 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5125 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5130 pSMB->TotalParameterCount = 0 ;
5131 pSMB->TotalDataCount = 0;
5132 pSMB->MaxParameterCount = cpu_to_le32(2);
5133 /* BB find exact data count max from sess structure BB */
5134 pSMB->MaxDataCount = 0; /* same in little endian or be */
5135 /* BB VERIFY verify which is correct for above BB */
5136 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5137 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5139 pSMB->MaxSetupCount = 4;
5141 pSMB->ParameterOffset = 0;
5142 pSMB->DataCount = 0;
5143 pSMB->DataOffset = 0;
5144 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5145 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5146 pSMB->ParameterCount = pSMB->TotalParameterCount;
5148 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5149 pSMB->Reserved2 = 0;
5150 pSMB->CompletionFilter = cpu_to_le32(filter);
5151 pSMB->Fid = netfid; /* file handle always le */
5152 pSMB->ByteCount = 0;
5154 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5155 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5157 cFYI(1, ("Error in Notify = %d", rc));
5159 /* Add file to outstanding requests */
5160 /* BB change to kmem cache alloc */
5161 dnotify_req = kmalloc(
5162 sizeof(struct dir_notify_req),
5165 dnotify_req->Pid = pSMB->hdr.Pid;
5166 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5167 dnotify_req->Mid = pSMB->hdr.Mid;
5168 dnotify_req->Tid = pSMB->hdr.Tid;
5169 dnotify_req->Uid = pSMB->hdr.Uid;
5170 dnotify_req->netfid = netfid;
5171 dnotify_req->pfile = pfile;
5172 dnotify_req->filter = filter;
5173 dnotify_req->multishot = multishot;
5174 spin_lock(&GlobalMid_Lock);
5175 list_add_tail(&dnotify_req->lhead,
5176 &GlobalDnotifyReqList);
5177 spin_unlock(&GlobalMid_Lock);
5181 cifs_buf_release(pSMB);
5184 #ifdef CONFIG_CIFS_XATTR
5186 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5187 const unsigned char *searchName,
5188 char *EAData, size_t buf_size,
5189 const struct nls_table *nls_codepage, int remap)
5191 /* BB assumes one setup word */
5192 TRANSACTION2_QPI_REQ *pSMB = NULL;
5193 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5197 struct fea *temp_fea;
5199 __u16 params, byte_count;
5201 cFYI(1, ("In Query All EAs path %s", searchName));
5203 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5208 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5210 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5211 PATH_MAX, nls_codepage, remap);
5212 name_len++; /* trailing null */
5214 } else { /* BB improve the check for buffer overruns BB */
5215 name_len = strnlen(searchName, PATH_MAX);
5216 name_len++; /* trailing null */
5217 strncpy(pSMB->FileName, searchName, name_len);
5220 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5221 pSMB->TotalDataCount = 0;
5222 pSMB->MaxParameterCount = cpu_to_le16(2);
5223 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5224 pSMB->MaxSetupCount = 0;
5228 pSMB->Reserved2 = 0;
5229 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5230 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5231 pSMB->DataCount = 0;
5232 pSMB->DataOffset = 0;
5233 pSMB->SetupCount = 1;
5234 pSMB->Reserved3 = 0;
5235 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5236 byte_count = params + 1 /* pad */ ;
5237 pSMB->TotalParameterCount = cpu_to_le16(params);
5238 pSMB->ParameterCount = pSMB->TotalParameterCount;
5239 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5240 pSMB->Reserved4 = 0;
5241 pSMB->hdr.smb_buf_length += byte_count;
5242 pSMB->ByteCount = cpu_to_le16(byte_count);
5244 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5245 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5247 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5248 } else { /* decode response */
5249 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5251 /* BB also check enough total bytes returned */
5252 /* BB we need to improve the validity checking
5253 of these trans2 responses */
5254 if (rc || (pSMBr->ByteCount < 4))
5255 rc = -EIO; /* bad smb */
5256 /* else if (pFindData){
5257 memcpy((char *) pFindData,
5258 (char *) &pSMBr->hdr.Protocol +
5261 /* check that length of list is not more than bcc */
5262 /* check that each entry does not go beyond length
5264 /* check that each element of each entry does not
5265 go beyond end of list */
5266 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5267 struct fealist *ea_response_data;
5269 /* validate_trans2_offsets() */
5270 /* BB check if start of smb + data_offset > &bcc+ bcc */
5271 ea_response_data = (struct fealist *)
5272 (((char *) &pSMBr->hdr.Protocol) +
5274 name_len = le32_to_cpu(ea_response_data->list_len);
5275 cFYI(1, ("ea length %d", name_len));
5276 if (name_len <= 8) {
5277 /* returned EA size zeroed at top of function */
5278 cFYI(1, ("empty EA list returned from server"));
5280 /* account for ea list len */
5282 temp_fea = ea_response_data->list;
5283 temp_ptr = (char *)temp_fea;
5284 while (name_len > 0) {
5288 rc += temp_fea->name_len;
5289 /* account for prefix user. and trailing null */
5291 if (rc < (int)buf_size) {
5292 memcpy(EAData, "user.", 5);
5294 memcpy(EAData, temp_ptr,
5295 temp_fea->name_len);
5296 EAData += temp_fea->name_len;
5297 /* null terminate name */
5299 EAData = EAData + 1;
5300 } else if (buf_size == 0) {
5301 /* skip copy - calc size only */
5303 /* stop before overrun buffer */
5307 name_len -= temp_fea->name_len;
5308 temp_ptr += temp_fea->name_len;
5309 /* account for trailing null */
5313 le16_to_cpu(temp_fea->value_len);
5314 name_len -= value_len;
5315 temp_ptr += value_len;
5316 /* BB check that temp_ptr is still
5319 /* no trailing null to account for
5321 /* go on to next EA */
5322 temp_fea = (struct fea *)temp_ptr;
5328 cifs_buf_release(pSMB);
5335 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5336 const unsigned char *searchName, const unsigned char *ea_name,
5337 unsigned char *ea_value, size_t buf_size,
5338 const struct nls_table *nls_codepage, int remap)
5340 TRANSACTION2_QPI_REQ *pSMB = NULL;
5341 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5345 struct fea *temp_fea;
5347 __u16 params, byte_count;
5349 cFYI(1, ("In Query EA path %s", searchName));
5351 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5356 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5358 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5359 PATH_MAX, nls_codepage, remap);
5360 name_len++; /* trailing null */
5362 } else { /* BB improve the check for buffer overruns BB */
5363 name_len = strnlen(searchName, PATH_MAX);
5364 name_len++; /* trailing null */
5365 strncpy(pSMB->FileName, searchName, name_len);
5368 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5369 pSMB->TotalDataCount = 0;
5370 pSMB->MaxParameterCount = cpu_to_le16(2);
5371 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5372 pSMB->MaxSetupCount = 0;
5376 pSMB->Reserved2 = 0;
5377 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5378 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5379 pSMB->DataCount = 0;
5380 pSMB->DataOffset = 0;
5381 pSMB->SetupCount = 1;
5382 pSMB->Reserved3 = 0;
5383 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5384 byte_count = params + 1 /* pad */ ;
5385 pSMB->TotalParameterCount = cpu_to_le16(params);
5386 pSMB->ParameterCount = pSMB->TotalParameterCount;
5387 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5388 pSMB->Reserved4 = 0;
5389 pSMB->hdr.smb_buf_length += byte_count;
5390 pSMB->ByteCount = cpu_to_le16(byte_count);
5392 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5393 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5395 cFYI(1, ("Send error in Query EA = %d", rc));
5396 } else { /* decode response */
5397 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5399 /* BB also check enough total bytes returned */
5400 /* BB we need to improve the validity checking
5401 of these trans2 responses */
5402 if (rc || (pSMBr->ByteCount < 4))
5403 rc = -EIO; /* bad smb */
5404 /* else if (pFindData){
5405 memcpy((char *) pFindData,
5406 (char *) &pSMBr->hdr.Protocol +
5409 /* check that length of list is not more than bcc */
5410 /* check that each entry does not go beyond length
5412 /* check that each element of each entry does not
5413 go beyond end of list */
5414 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5415 struct fealist *ea_response_data;
5417 /* validate_trans2_offsets() */
5418 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5419 ea_response_data = (struct fealist *)
5420 (((char *) &pSMBr->hdr.Protocol) +
5422 name_len = le32_to_cpu(ea_response_data->list_len);
5423 cFYI(1, ("ea length %d", name_len));
5424 if (name_len <= 8) {
5425 /* returned EA size zeroed at top of function */
5426 cFYI(1, ("empty EA list returned from server"));
5428 /* account for ea list len */
5430 temp_fea = ea_response_data->list;
5431 temp_ptr = (char *)temp_fea;
5432 /* loop through checking if we have a matching
5433 name and then return the associated value */
5434 while (name_len > 0) {
5439 le16_to_cpu(temp_fea->value_len);
5440 /* BB validate that value_len falls within SMB,
5441 even though maximum for name_len is 255 */
5442 if (memcmp(temp_fea->name, ea_name,
5443 temp_fea->name_len) == 0) {
5446 /* account for prefix user. and trailing null */
5447 if (rc <= (int)buf_size) {
5449 temp_fea->name+temp_fea->name_len+1,
5451 /* ea values, unlike ea
5454 } else if (buf_size == 0) {
5455 /* skip copy - calc size only */
5457 /* stop before overrun buffer */
5462 name_len -= temp_fea->name_len;
5463 temp_ptr += temp_fea->name_len;
5464 /* account for trailing null */
5467 name_len -= value_len;
5468 temp_ptr += value_len;
5469 /* No trailing null to account for in
5470 value_len. Go on to next EA */
5471 temp_fea = (struct fea *)temp_ptr;
5477 cifs_buf_release(pSMB);
5485 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5486 const char *ea_name, const void *ea_value,
5487 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5490 struct smb_com_transaction2_spi_req *pSMB = NULL;
5491 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5492 struct fealist *parm_data;
5495 int bytes_returned = 0;
5496 __u16 params, param_offset, byte_count, offset, count;
5498 cFYI(1, ("In SetEA"));
5500 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5505 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5507 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5508 PATH_MAX, nls_codepage, remap);
5509 name_len++; /* trailing null */
5511 } else { /* BB improve the check for buffer overruns BB */
5512 name_len = strnlen(fileName, PATH_MAX);
5513 name_len++; /* trailing null */
5514 strncpy(pSMB->FileName, fileName, name_len);
5517 params = 6 + name_len;
5519 /* done calculating parms using name_len of file name,
5520 now use name_len to calculate length of ea name
5521 we are going to create in the inode xattrs */
5522 if (ea_name == NULL)
5525 name_len = strnlen(ea_name, 255);
5527 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5528 pSMB->MaxParameterCount = cpu_to_le16(2);
5529 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5530 pSMB->MaxSetupCount = 0;
5534 pSMB->Reserved2 = 0;
5535 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5536 InformationLevel) - 4;
5537 offset = param_offset + params;
5538 pSMB->InformationLevel =
5539 cpu_to_le16(SMB_SET_FILE_EA);
5542 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5544 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5545 pSMB->DataOffset = cpu_to_le16(offset);
5546 pSMB->SetupCount = 1;
5547 pSMB->Reserved3 = 0;
5548 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5549 byte_count = 3 /* pad */ + params + count;
5550 pSMB->DataCount = cpu_to_le16(count);
5551 parm_data->list_len = cpu_to_le32(count);
5552 parm_data->list[0].EA_flags = 0;
5553 /* we checked above that name len is less than 255 */
5554 parm_data->list[0].name_len = (__u8)name_len;
5555 /* EA names are always ASCII */
5557 strncpy(parm_data->list[0].name, ea_name, name_len);
5558 parm_data->list[0].name[name_len] = 0;
5559 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5560 /* caller ensures that ea_value_len is less than 64K but
5561 we need to ensure that it fits within the smb */
5563 /*BB add length check to see if it would fit in
5564 negotiated SMB buffer size BB */
5565 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5567 memcpy(parm_data->list[0].name+name_len+1,
5568 ea_value, ea_value_len);
5570 pSMB->TotalDataCount = pSMB->DataCount;
5571 pSMB->ParameterCount = cpu_to_le16(params);
5572 pSMB->TotalParameterCount = pSMB->ParameterCount;
5573 pSMB->Reserved4 = 0;
5574 pSMB->hdr.smb_buf_length += byte_count;
5575 pSMB->ByteCount = cpu_to_le16(byte_count);
5576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5577 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5579 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5582 cifs_buf_release(pSMB);