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;
626 else if (count == 16) {
627 server->secType = RawNTLMSSP;
628 if (server->socketUseCount.counter > 1) {
629 if (memcmp(server->server_GUID,
630 pSMBr->u.extended_response.
632 cFYI(1, ("server UID changed"));
633 memcpy(server->server_GUID,
634 pSMBr->u.extended_response.GUID,
638 memcpy(server->server_GUID,
639 pSMBr->u.extended_response.GUID, 16);
641 rc = decode_negTokenInit(pSMBr->u.extended_response.
646 /* BB Need to fill struct for sessetup here */
653 server->capabilities &= ~CAP_EXTENDED_SECURITY;
655 #ifdef CONFIG_CIFS_WEAK_PW_HASH
658 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
659 /* MUST_SIGN already includes the MAY_SIGN FLAG
660 so if this is zero it means that signing is disabled */
661 cFYI(1, ("Signing disabled"));
662 if (server->secMode & SECMODE_SIGN_REQUIRED)
663 cERROR(1, ("Server requires "
664 "/proc/fs/cifs/PacketSigningEnabled "
667 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
668 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
669 /* signing required */
670 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
671 if ((server->secMode &
672 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
674 ("signing required but server lacks support"));
677 server->secMode |= SECMODE_SIGN_REQUIRED;
679 /* signing optional ie CIFSSEC_MAY_SIGN */
680 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
682 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
686 cifs_buf_release(pSMB);
688 cFYI(1, ("negprot rc %d", rc));
693 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
695 struct smb_hdr *smb_buffer;
696 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
700 cFYI(1, ("In tree disconnect"));
702 * If last user of the connection and
703 * connection alive - disconnect it
704 * If this is the last connection on the server session disconnect it
705 * (and inside session disconnect we should check if tcp socket needs
706 * to be freed and kernel thread woken up).
709 down(&tcon->tconSem);
713 atomic_dec(&tcon->useCount);
714 if (atomic_read(&tcon->useCount) > 0) {
719 /* No need to return error on this operation if tid invalidated and
720 closed on server already e.g. due to tcp session crashing */
721 if (tcon->tidStatus == CifsNeedReconnect) {
726 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
730 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
731 (void **)&smb_buffer);
736 smb_buffer_response = smb_buffer; /* BB removeme BB */
738 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
741 cFYI(1, ("Tree disconnect failed %d", rc));
744 cifs_small_buf_release(smb_buffer);
747 /* No need to return error on this operation if tid invalidated and
748 closed on server already e.g. due to tcp session crashing */
756 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
758 struct smb_hdr *smb_buffer_response;
759 LOGOFF_ANDX_REQ *pSMB;
763 cFYI(1, ("In SMBLogoff for session disconnect"));
769 atomic_dec(&ses->inUse);
770 if (atomic_read(&ses->inUse) > 0) {
774 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
780 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
783 pSMB->hdr.Mid = GetNextMid(ses->server);
785 if (ses->server->secMode &
786 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
787 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
790 pSMB->hdr.Uid = ses->Suid;
792 pSMB->AndXCommand = 0xFF;
793 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
794 smb_buffer_response, &length, 0);
796 atomic_dec(&ses->server->socketUseCount);
797 if (atomic_read(&ses->server->socketUseCount) == 0) {
798 spin_lock(&GlobalMid_Lock);
799 ses->server->tcpStatus = CifsExiting;
800 spin_unlock(&GlobalMid_Lock);
805 cifs_small_buf_release(pSMB);
807 /* if session dead then we do not need to do ulogoff,
808 since server closed smb session, no sense reporting
816 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
817 __u16 type, const struct nls_table *nls_codepage, int remap)
819 TRANSACTION2_SPI_REQ *pSMB = NULL;
820 TRANSACTION2_SPI_RSP *pSMBr = NULL;
821 struct unlink_psx_rq *pRqD;
824 int bytes_returned = 0;
825 __u16 params, param_offset, offset, byte_count;
827 cFYI(1, ("In POSIX delete"));
829 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
834 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
836 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
837 PATH_MAX, nls_codepage, remap);
838 name_len++; /* trailing null */
840 } else { /* BB add path length overrun check */
841 name_len = strnlen(fileName, PATH_MAX);
842 name_len++; /* trailing null */
843 strncpy(pSMB->FileName, fileName, name_len);
846 params = 6 + name_len;
847 pSMB->MaxParameterCount = cpu_to_le16(2);
848 pSMB->MaxDataCount = 0; /* BB double check this with jra */
849 pSMB->MaxSetupCount = 0;
854 param_offset = offsetof(struct smb_com_transaction2_spi_req,
855 InformationLevel) - 4;
856 offset = param_offset + params;
858 /* Setup pointer to Request Data (inode type) */
859 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
860 pRqD->type = cpu_to_le16(type);
861 pSMB->ParameterOffset = cpu_to_le16(param_offset);
862 pSMB->DataOffset = cpu_to_le16(offset);
863 pSMB->SetupCount = 1;
865 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
866 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
868 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
869 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
870 pSMB->ParameterCount = cpu_to_le16(params);
871 pSMB->TotalParameterCount = pSMB->ParameterCount;
872 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
874 pSMB->hdr.smb_buf_length += byte_count;
875 pSMB->ByteCount = cpu_to_le16(byte_count);
876 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
877 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
879 cFYI(1, ("Posix delete returned %d", rc));
881 cifs_buf_release(pSMB);
883 cifs_stats_inc(&tcon->num_deletes);
892 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
893 const struct nls_table *nls_codepage, int remap)
895 DELETE_FILE_REQ *pSMB = NULL;
896 DELETE_FILE_RSP *pSMBr = NULL;
902 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
907 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
909 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
910 PATH_MAX, nls_codepage, remap);
911 name_len++; /* trailing null */
913 } else { /* BB improve check for buffer overruns BB */
914 name_len = strnlen(fileName, PATH_MAX);
915 name_len++; /* trailing null */
916 strncpy(pSMB->fileName, fileName, name_len);
918 pSMB->SearchAttributes =
919 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
920 pSMB->BufferFormat = 0x04;
921 pSMB->hdr.smb_buf_length += name_len + 1;
922 pSMB->ByteCount = cpu_to_le16(name_len + 1);
923 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
924 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
925 cifs_stats_inc(&tcon->num_deletes);
927 cFYI(1, ("Error in RMFile = %d", rc));
930 cifs_buf_release(pSMB);
938 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
939 const struct nls_table *nls_codepage, int remap)
941 DELETE_DIRECTORY_REQ *pSMB = NULL;
942 DELETE_DIRECTORY_RSP *pSMBr = NULL;
947 cFYI(1, ("In CIFSSMBRmDir"));
949 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
955 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
956 PATH_MAX, nls_codepage, remap);
957 name_len++; /* trailing null */
959 } else { /* BB improve check for buffer overruns BB */
960 name_len = strnlen(dirName, PATH_MAX);
961 name_len++; /* trailing null */
962 strncpy(pSMB->DirName, dirName, name_len);
965 pSMB->BufferFormat = 0x04;
966 pSMB->hdr.smb_buf_length += name_len + 1;
967 pSMB->ByteCount = cpu_to_le16(name_len + 1);
968 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
969 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
970 cifs_stats_inc(&tcon->num_rmdirs);
972 cFYI(1, ("Error in RMDir = %d", rc));
975 cifs_buf_release(pSMB);
982 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
983 const char *name, const struct nls_table *nls_codepage, int remap)
986 CREATE_DIRECTORY_REQ *pSMB = NULL;
987 CREATE_DIRECTORY_RSP *pSMBr = NULL;
991 cFYI(1, ("In CIFSSMBMkDir"));
993 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
998 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
999 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1000 PATH_MAX, nls_codepage, remap);
1001 name_len++; /* trailing null */
1003 } else { /* BB improve check for buffer overruns BB */
1004 name_len = strnlen(name, PATH_MAX);
1005 name_len++; /* trailing null */
1006 strncpy(pSMB->DirName, name, name_len);
1009 pSMB->BufferFormat = 0x04;
1010 pSMB->hdr.smb_buf_length += name_len + 1;
1011 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1012 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1013 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1014 cifs_stats_inc(&tcon->num_mkdirs);
1016 cFYI(1, ("Error in Mkdir = %d", rc));
1019 cifs_buf_release(pSMB);
1026 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1027 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1028 __u32 *pOplock, const char *name,
1029 const struct nls_table *nls_codepage, int remap)
1031 TRANSACTION2_SPI_REQ *pSMB = NULL;
1032 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1035 int bytes_returned = 0;
1036 __u16 params, param_offset, offset, byte_count, count;
1037 OPEN_PSX_REQ * pdata;
1038 OPEN_PSX_RSP * psx_rsp;
1040 cFYI(1, ("In POSIX Create"));
1042 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1047 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1049 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1050 PATH_MAX, nls_codepage, remap);
1051 name_len++; /* trailing null */
1053 } else { /* BB improve the check for buffer overruns BB */
1054 name_len = strnlen(name, PATH_MAX);
1055 name_len++; /* trailing null */
1056 strncpy(pSMB->FileName, name, name_len);
1059 params = 6 + name_len;
1060 count = sizeof(OPEN_PSX_REQ);
1061 pSMB->MaxParameterCount = cpu_to_le16(2);
1062 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1063 pSMB->MaxSetupCount = 0;
1067 pSMB->Reserved2 = 0;
1068 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1069 InformationLevel) - 4;
1070 offset = param_offset + params;
1071 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1072 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
1073 pdata->Permissions = cpu_to_le64(mode);
1074 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1075 pdata->OpenFlags = cpu_to_le32(*pOplock);
1076 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1077 pSMB->DataOffset = cpu_to_le16(offset);
1078 pSMB->SetupCount = 1;
1079 pSMB->Reserved3 = 0;
1080 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1081 byte_count = 3 /* pad */ + params + count;
1083 pSMB->DataCount = cpu_to_le16(count);
1084 pSMB->ParameterCount = cpu_to_le16(params);
1085 pSMB->TotalDataCount = pSMB->DataCount;
1086 pSMB->TotalParameterCount = pSMB->ParameterCount;
1087 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1088 pSMB->Reserved4 = 0;
1089 pSMB->hdr.smb_buf_length += byte_count;
1090 pSMB->ByteCount = cpu_to_le16(byte_count);
1091 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1092 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1094 cFYI(1, ("Posix create returned %d", rc));
1095 goto psx_create_err;
1098 cFYI(1, ("copying inode info"));
1099 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1101 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1102 rc = -EIO; /* bad smb */
1103 goto psx_create_err;
1106 /* copy return information to pRetData */
1107 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1108 + le16_to_cpu(pSMBr->t2.DataOffset));
1110 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1112 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1113 /* Let caller know file was created so we can set the mode. */
1114 /* Do we care about the CreateAction in any other cases? */
1115 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1116 *pOplock |= CIFS_CREATE_ACTION;
1117 /* check to make sure response data is there */
1118 if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
1119 pRetData->Type = -1; /* unknown */
1120 #ifdef CONFIG_CIFS_DEBUG2
1121 cFYI(1, ("unknown type"));
1124 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1125 + sizeof(FILE_UNIX_BASIC_INFO)) {
1126 cERROR(1, ("Open response data too small"));
1127 pRetData->Type = -1;
1128 goto psx_create_err;
1130 memcpy((char *) pRetData,
1131 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1132 sizeof(FILE_UNIX_BASIC_INFO));
1136 cifs_buf_release(pSMB);
1138 cifs_stats_inc(&tcon->num_mkdirs);
1146 static __u16 convert_disposition(int disposition)
1150 switch (disposition) {
1151 case FILE_SUPERSEDE:
1152 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1155 ofun = SMBOPEN_OAPPEND;
1158 ofun = SMBOPEN_OCREATE;
1161 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1163 case FILE_OVERWRITE:
1164 ofun = SMBOPEN_OTRUNC;
1166 case FILE_OVERWRITE_IF:
1167 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1170 cFYI(1, ("unknown disposition %d", disposition));
1171 ofun = SMBOPEN_OAPPEND; /* regular open */
1177 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1178 const char *fileName, const int openDisposition,
1179 const int access_flags, const int create_options, __u16 * netfid,
1180 int *pOplock, FILE_ALL_INFO * pfile_info,
1181 const struct nls_table *nls_codepage, int remap)
1184 OPENX_REQ *pSMB = NULL;
1185 OPENX_RSP *pSMBr = NULL;
1191 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1196 pSMB->AndXCommand = 0xFF; /* none */
1198 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1199 count = 1; /* account for one byte pad to word boundary */
1201 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1202 fileName, PATH_MAX, nls_codepage, remap);
1203 name_len++; /* trailing null */
1205 } else { /* BB improve check for buffer overruns BB */
1206 count = 0; /* no pad */
1207 name_len = strnlen(fileName, PATH_MAX);
1208 name_len++; /* trailing null */
1209 strncpy(pSMB->fileName, fileName, name_len);
1211 if (*pOplock & REQ_OPLOCK)
1212 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1213 else if (*pOplock & REQ_BATCHOPLOCK)
1214 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1216 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1217 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1223 pSMB->Mode = cpu_to_le16(2);
1224 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1225 /* set file as system file if special file such
1226 as fifo and server expecting SFU style and
1227 no Unix extensions */
1229 if (create_options & CREATE_OPTION_SPECIAL)
1230 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1232 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1234 /* if ((omode & S_IWUGO) == 0)
1235 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1236 /* Above line causes problems due to vfs splitting create into two
1237 pieces - need to set mode after file created not while it is
1241 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1242 CREATE_OPTIONS_MASK); */
1243 /* BB FIXME END BB */
1245 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1246 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1248 pSMB->hdr.smb_buf_length += count;
1250 pSMB->ByteCount = cpu_to_le16(count);
1251 /* long_op set to 1 to allow for oplock break timeouts */
1252 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1253 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1254 cifs_stats_inc(&tcon->num_opens);
1256 cFYI(1, ("Error in Open = %d", rc));
1258 /* BB verify if wct == 15 */
1260 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1262 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1263 /* Let caller know file was created so we can set the mode. */
1264 /* Do we care about the CreateAction in any other cases? */
1266 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1267 *pOplock |= CIFS_CREATE_ACTION; */
1271 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1272 pfile_info->LastAccessTime = 0; /* BB fixme */
1273 pfile_info->LastWriteTime = 0; /* BB fixme */
1274 pfile_info->ChangeTime = 0; /* BB fixme */
1275 pfile_info->Attributes =
1276 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1277 /* the file_info buf is endian converted by caller */
1278 pfile_info->AllocationSize =
1279 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1280 pfile_info->EndOfFile = pfile_info->AllocationSize;
1281 pfile_info->NumberOfLinks = cpu_to_le32(1);
1285 cifs_buf_release(pSMB);
1292 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1293 const char *fileName, const int openDisposition,
1294 const int access_flags, const int create_options, __u16 * netfid,
1295 int *pOplock, FILE_ALL_INFO * pfile_info,
1296 const struct nls_table *nls_codepage, int remap)
1299 OPEN_REQ *pSMB = NULL;
1300 OPEN_RSP *pSMBr = NULL;
1306 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1311 pSMB->AndXCommand = 0xFF; /* none */
1313 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1314 count = 1; /* account for one byte pad to word boundary */
1316 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1317 fileName, PATH_MAX, nls_codepage, remap);
1318 name_len++; /* trailing null */
1320 pSMB->NameLength = cpu_to_le16(name_len);
1321 } else { /* BB improve check for buffer overruns BB */
1322 count = 0; /* no pad */
1323 name_len = strnlen(fileName, PATH_MAX);
1324 name_len++; /* trailing null */
1325 pSMB->NameLength = cpu_to_le16(name_len);
1326 strncpy(pSMB->fileName, fileName, name_len);
1328 if (*pOplock & REQ_OPLOCK)
1329 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1330 else if (*pOplock & REQ_BATCHOPLOCK)
1331 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1332 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1333 pSMB->AllocationSize = 0;
1334 /* set file as system file if special file such
1335 as fifo and server expecting SFU style and
1336 no Unix extensions */
1337 if (create_options & CREATE_OPTION_SPECIAL)
1338 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1340 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1341 /* XP does not handle ATTR_POSIX_SEMANTICS */
1342 /* but it helps speed up case sensitive checks for other
1343 servers such as Samba */
1344 if (tcon->ses->capabilities & CAP_UNIX)
1345 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1347 /* if ((omode & S_IWUGO) == 0)
1348 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1349 /* Above line causes problems due to vfs splitting create into two
1350 pieces - need to set mode after file created not while it is
1352 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1353 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1354 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1355 /* BB Expirement with various impersonation levels and verify */
1356 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1357 pSMB->SecurityFlags =
1358 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1361 pSMB->hdr.smb_buf_length += count;
1363 pSMB->ByteCount = cpu_to_le16(count);
1364 /* long_op set to 1 to allow for oplock break timeouts */
1365 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1366 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1367 cifs_stats_inc(&tcon->num_opens);
1369 cFYI(1, ("Error in Open = %d", rc));
1371 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1372 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1373 /* Let caller know file was created so we can set the mode. */
1374 /* Do we care about the CreateAction in any other cases? */
1375 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1376 *pOplock |= CIFS_CREATE_ACTION;
1378 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1379 36 /* CreationTime to Attributes */);
1380 /* the file_info buf is endian converted by caller */
1381 pfile_info->AllocationSize = pSMBr->AllocationSize;
1382 pfile_info->EndOfFile = pSMBr->EndOfFile;
1383 pfile_info->NumberOfLinks = cpu_to_le32(1);
1387 cifs_buf_release(pSMB);
1394 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1395 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1396 char **buf, int *pbuf_type)
1399 READ_REQ *pSMB = NULL;
1400 READ_RSP *pSMBr = NULL;
1401 char *pReadData = NULL;
1403 int resp_buf_type = 0;
1406 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1407 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1410 wct = 10; /* old style read */
1413 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1417 /* tcon and ses pointer are checked in smb_init */
1418 if (tcon->ses->server == NULL)
1419 return -ECONNABORTED;
1421 pSMB->AndXCommand = 0xFF; /* none */
1423 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1425 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1426 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1429 pSMB->Remaining = 0;
1430 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1431 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1433 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1435 /* old style read */
1436 struct smb_com_readx_req *pSMBW =
1437 (struct smb_com_readx_req *)pSMB;
1438 pSMBW->ByteCount = 0;
1441 iov[0].iov_base = (char *)pSMB;
1442 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1443 rc = SendReceive2(xid, tcon->ses, iov,
1446 cifs_stats_inc(&tcon->num_reads);
1447 pSMBr = (READ_RSP *)iov[0].iov_base;
1449 cERROR(1, ("Send error in read = %d", rc));
1451 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1452 data_length = data_length << 16;
1453 data_length += le16_to_cpu(pSMBr->DataLength);
1454 *nbytes = data_length;
1456 /*check that DataLength would not go beyond end of SMB */
1457 if ((data_length > CIFSMaxBufSize)
1458 || (data_length > count)) {
1459 cFYI(1, ("bad length %d for count %d",
1460 data_length, count));
1464 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1465 le16_to_cpu(pSMBr->DataOffset);
1466 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1467 cERROR(1,("Faulting on read rc = %d",rc));
1469 }*/ /* can not use copy_to_user when using page cache*/
1471 memcpy(*buf, pReadData, data_length);
1475 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1477 if (resp_buf_type == CIFS_SMALL_BUFFER)
1478 cifs_small_buf_release(iov[0].iov_base);
1479 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1480 cifs_buf_release(iov[0].iov_base);
1481 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1482 /* return buffer to caller to free */
1483 *buf = iov[0].iov_base;
1484 if (resp_buf_type == CIFS_SMALL_BUFFER)
1485 *pbuf_type = CIFS_SMALL_BUFFER;
1486 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1487 *pbuf_type = CIFS_LARGE_BUFFER;
1488 } /* else no valid buffer on return - leave as null */
1490 /* Note: On -EAGAIN error only caller can retry on handle based calls
1491 since file handle passed in no longer valid */
1497 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1498 const int netfid, const unsigned int count,
1499 const __u64 offset, unsigned int *nbytes, const char *buf,
1500 const char __user *ubuf, const int long_op)
1503 WRITE_REQ *pSMB = NULL;
1504 WRITE_RSP *pSMBr = NULL;
1505 int bytes_returned, wct;
1509 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1510 if (tcon->ses == NULL)
1511 return -ECONNABORTED;
1513 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1518 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1522 /* tcon and ses pointer are checked in smb_init */
1523 if (tcon->ses->server == NULL)
1524 return -ECONNABORTED;
1526 pSMB->AndXCommand = 0xFF; /* none */
1528 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1530 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1531 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1534 pSMB->Reserved = 0xFFFFFFFF;
1535 pSMB->WriteMode = 0;
1536 pSMB->Remaining = 0;
1538 /* Can increase buffer size if buffer is big enough in some cases ie we
1539 can send more if LARGE_WRITE_X capability returned by the server and if
1540 our buffer is big enough or if we convert to iovecs on socket writes
1541 and eliminate the copy to the CIFS buffer */
1542 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1543 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1545 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1549 if (bytes_sent > count)
1552 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1554 memcpy(pSMB->Data, buf, bytes_sent);
1556 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1557 cifs_buf_release(pSMB);
1560 } else if (count != 0) {
1562 cifs_buf_release(pSMB);
1564 } /* else setting file size with write of zero bytes */
1566 byte_count = bytes_sent + 1; /* pad */
1567 else /* wct == 12 */ {
1568 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1570 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1571 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1572 pSMB->hdr.smb_buf_length += byte_count;
1575 pSMB->ByteCount = cpu_to_le16(byte_count);
1576 else { /* old style write has byte count 4 bytes earlier
1578 struct smb_com_writex_req *pSMBW =
1579 (struct smb_com_writex_req *)pSMB;
1580 pSMBW->ByteCount = cpu_to_le16(byte_count);
1583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1584 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1585 cifs_stats_inc(&tcon->num_writes);
1587 cFYI(1, ("Send error in write = %d", rc));
1590 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1591 *nbytes = (*nbytes) << 16;
1592 *nbytes += le16_to_cpu(pSMBr->Count);
1595 cifs_buf_release(pSMB);
1597 /* Note: On -EAGAIN error only caller can retry on handle based calls
1598 since file handle passed in no longer valid */
1604 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1605 const int netfid, const unsigned int count,
1606 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1607 int n_vec, const int long_op)
1610 WRITE_REQ *pSMB = NULL;
1613 int resp_buf_type = 0;
1615 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1617 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1621 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1624 /* tcon and ses pointer are checked in smb_init */
1625 if (tcon->ses->server == NULL)
1626 return -ECONNABORTED;
1628 pSMB->AndXCommand = 0xFF; /* none */
1630 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1632 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1633 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1635 pSMB->Reserved = 0xFFFFFFFF;
1636 pSMB->WriteMode = 0;
1637 pSMB->Remaining = 0;
1640 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1642 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1643 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1644 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1646 pSMB->hdr.smb_buf_length += count+1;
1647 else /* wct == 12 */
1648 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1650 pSMB->ByteCount = cpu_to_le16(count + 1);
1651 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1652 struct smb_com_writex_req *pSMBW =
1653 (struct smb_com_writex_req *)pSMB;
1654 pSMBW->ByteCount = cpu_to_le16(count + 5);
1656 iov[0].iov_base = pSMB;
1658 iov[0].iov_len = smb_hdr_len + 4;
1659 else /* wct == 12 pad bigger by four bytes */
1660 iov[0].iov_len = smb_hdr_len + 8;
1663 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1665 cifs_stats_inc(&tcon->num_writes);
1667 cFYI(1, ("Send error Write2 = %d", rc));
1669 } else if (resp_buf_type == 0) {
1670 /* presumably this can not happen, but best to be safe */
1674 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1675 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1676 *nbytes = (*nbytes) << 16;
1677 *nbytes += le16_to_cpu(pSMBr->Count);
1680 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1681 if (resp_buf_type == CIFS_SMALL_BUFFER)
1682 cifs_small_buf_release(iov[0].iov_base);
1683 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1684 cifs_buf_release(iov[0].iov_base);
1686 /* Note: On -EAGAIN error only caller can retry on handle based calls
1687 since file handle passed in no longer valid */
1694 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1695 const __u16 smb_file_id, const __u64 len,
1696 const __u64 offset, const __u32 numUnlock,
1697 const __u32 numLock, const __u8 lockType, const int waitFlag)
1700 LOCK_REQ *pSMB = NULL;
1701 LOCK_RSP *pSMBr = NULL;
1706 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1707 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1712 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1714 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1715 timeout = -1; /* no response expected */
1717 } else if (waitFlag == TRUE) {
1718 timeout = 3; /* blocking operation, no timeout */
1719 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1724 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1725 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1726 pSMB->LockType = lockType;
1727 pSMB->AndXCommand = 0xFF; /* none */
1728 pSMB->Fid = smb_file_id; /* netfid stays le */
1730 if ((numLock != 0) || (numUnlock != 0)) {
1731 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1732 /* BB where to store pid high? */
1733 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1734 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1735 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1736 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1737 count = sizeof(LOCKING_ANDX_RANGE);
1742 pSMB->hdr.smb_buf_length += count;
1743 pSMB->ByteCount = cpu_to_le16(count);
1746 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1747 (struct smb_hdr *) pSMBr, &bytes_returned);
1749 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1750 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1752 cifs_stats_inc(&tcon->num_locks);
1754 cFYI(1, ("Send error in Lock = %d", rc));
1756 cifs_small_buf_release(pSMB);
1758 /* Note: On -EAGAIN error only caller can retry on handle based calls
1759 since file handle passed in no longer valid */
1764 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1765 const __u16 smb_file_id, const int get_flag, const __u64 len,
1766 struct file_lock *pLockData, const __u16 lock_type,
1769 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1770 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1771 struct cifs_posix_lock *parm_data;
1774 int bytes_returned = 0;
1775 __u16 params, param_offset, offset, byte_count, count;
1777 cFYI(1, ("Posix Lock"));
1779 if (pLockData == NULL)
1782 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1787 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1790 pSMB->MaxSetupCount = 0;
1793 pSMB->Reserved2 = 0;
1794 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1795 offset = param_offset + params;
1797 count = sizeof(struct cifs_posix_lock);
1798 pSMB->MaxParameterCount = cpu_to_le16(2);
1799 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1800 pSMB->SetupCount = 1;
1801 pSMB->Reserved3 = 0;
1803 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1805 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1806 byte_count = 3 /* pad */ + params + count;
1807 pSMB->DataCount = cpu_to_le16(count);
1808 pSMB->ParameterCount = cpu_to_le16(params);
1809 pSMB->TotalDataCount = pSMB->DataCount;
1810 pSMB->TotalParameterCount = pSMB->ParameterCount;
1811 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1812 parm_data = (struct cifs_posix_lock *)
1813 (((char *) &pSMB->hdr.Protocol) + offset);
1815 parm_data->lock_type = cpu_to_le16(lock_type);
1817 timeout = 3; /* blocking operation, no timeout */
1818 parm_data->lock_flags = cpu_to_le16(1);
1819 pSMB->Timeout = cpu_to_le32(-1);
1823 parm_data->pid = cpu_to_le32(current->tgid);
1824 parm_data->start = cpu_to_le64(pLockData->fl_start);
1825 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1827 pSMB->DataOffset = cpu_to_le16(offset);
1828 pSMB->Fid = smb_file_id;
1829 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1830 pSMB->Reserved4 = 0;
1831 pSMB->hdr.smb_buf_length += byte_count;
1832 pSMB->ByteCount = cpu_to_le16(byte_count);
1834 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1835 (struct smb_hdr *) pSMBr, &bytes_returned);
1837 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1838 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1842 cFYI(1, ("Send error in Posix Lock = %d", rc));
1843 } else if (get_flag) {
1844 /* lock structure can be returned on get */
1847 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1849 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1850 rc = -EIO; /* bad smb */
1853 if (pLockData == NULL) {
1857 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1858 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1859 if (data_count < sizeof(struct cifs_posix_lock)) {
1863 parm_data = (struct cifs_posix_lock *)
1864 ((char *)&pSMBr->hdr.Protocol + data_offset);
1865 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1866 pLockData->fl_type = F_UNLCK;
1871 cifs_small_buf_release(pSMB);
1873 /* Note: On -EAGAIN error only caller can retry on handle based calls
1874 since file handle passed in no longer valid */
1881 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1884 CLOSE_REQ *pSMB = NULL;
1885 CLOSE_RSP *pSMBr = NULL;
1887 cFYI(1, ("In CIFSSMBClose"));
1889 /* do not retry on dead session on close */
1890 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1896 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1898 pSMB->FileID = (__u16) smb_file_id;
1899 pSMB->LastWriteTime = 0xFFFFFFFF;
1900 pSMB->ByteCount = 0;
1901 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1902 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1903 cifs_stats_inc(&tcon->num_closes);
1906 /* EINTR is expected when user ctl-c to kill app */
1907 cERROR(1, ("Send error in Close = %d", rc));
1911 cifs_small_buf_release(pSMB);
1913 /* Since session is dead, file will be closed on server already */
1921 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1922 const char *fromName, const char *toName,
1923 const struct nls_table *nls_codepage, int remap)
1926 RENAME_REQ *pSMB = NULL;
1927 RENAME_RSP *pSMBr = NULL;
1929 int name_len, name_len2;
1932 cFYI(1, ("In CIFSSMBRename"));
1934 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1939 pSMB->BufferFormat = 0x04;
1940 pSMB->SearchAttributes =
1941 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1944 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1946 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1947 PATH_MAX, nls_codepage, remap);
1948 name_len++; /* trailing null */
1950 pSMB->OldFileName[name_len] = 0x04; /* pad */
1951 /* protocol requires ASCII signature byte on Unicode string */
1952 pSMB->OldFileName[name_len + 1] = 0x00;
1954 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1955 toName, PATH_MAX, nls_codepage, remap);
1956 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1957 name_len2 *= 2; /* convert to bytes */
1958 } else { /* BB improve the check for buffer overruns BB */
1959 name_len = strnlen(fromName, PATH_MAX);
1960 name_len++; /* trailing null */
1961 strncpy(pSMB->OldFileName, fromName, name_len);
1962 name_len2 = strnlen(toName, PATH_MAX);
1963 name_len2++; /* trailing null */
1964 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1965 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1966 name_len2++; /* trailing null */
1967 name_len2++; /* signature byte */
1970 count = 1 /* 1st signature byte */ + name_len + name_len2;
1971 pSMB->hdr.smb_buf_length += count;
1972 pSMB->ByteCount = cpu_to_le16(count);
1974 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1976 cifs_stats_inc(&tcon->num_renames);
1978 cFYI(1, ("Send error in rename = %d", rc));
1981 cifs_buf_release(pSMB);
1989 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1990 int netfid, char *target_name,
1991 const struct nls_table *nls_codepage, int remap)
1993 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1994 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1995 struct set_file_rename *rename_info;
1997 char dummy_string[30];
1999 int bytes_returned = 0;
2001 __u16 params, param_offset, offset, count, byte_count;
2003 cFYI(1, ("Rename to File by handle"));
2004 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2010 pSMB->MaxSetupCount = 0;
2014 pSMB->Reserved2 = 0;
2015 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2016 offset = param_offset + params;
2018 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2019 rename_info = (struct set_file_rename *) data_offset;
2020 pSMB->MaxParameterCount = cpu_to_le16(2);
2021 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2022 pSMB->SetupCount = 1;
2023 pSMB->Reserved3 = 0;
2024 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2025 byte_count = 3 /* pad */ + params;
2026 pSMB->ParameterCount = cpu_to_le16(params);
2027 pSMB->TotalParameterCount = pSMB->ParameterCount;
2028 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2029 pSMB->DataOffset = cpu_to_le16(offset);
2030 /* construct random name ".cifs_tmp<inodenum><mid>" */
2031 rename_info->overwrite = cpu_to_le32(1);
2032 rename_info->root_fid = 0;
2033 /* unicode only call */
2034 if (target_name == NULL) {
2035 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2036 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2037 dummy_string, 24, nls_codepage, remap);
2039 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2040 target_name, PATH_MAX, nls_codepage,
2043 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2044 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2045 byte_count += count;
2046 pSMB->DataCount = cpu_to_le16(count);
2047 pSMB->TotalDataCount = pSMB->DataCount;
2049 pSMB->InformationLevel =
2050 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2051 pSMB->Reserved4 = 0;
2052 pSMB->hdr.smb_buf_length += byte_count;
2053 pSMB->ByteCount = cpu_to_le16(byte_count);
2054 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2055 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2056 cifs_stats_inc(&pTcon->num_t2renames);
2058 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2061 cifs_buf_release(pSMB);
2063 /* Note: On -EAGAIN error only caller can retry on handle based calls
2064 since file handle passed in no longer valid */
2070 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2071 const __u16 target_tid, const char *toName, const int flags,
2072 const struct nls_table *nls_codepage, int remap)
2075 COPY_REQ *pSMB = NULL;
2076 COPY_RSP *pSMBr = NULL;
2078 int name_len, name_len2;
2081 cFYI(1, ("In CIFSSMBCopy"));
2083 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2088 pSMB->BufferFormat = 0x04;
2089 pSMB->Tid2 = target_tid;
2091 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2093 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2094 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2095 fromName, PATH_MAX, nls_codepage,
2097 name_len++; /* trailing null */
2099 pSMB->OldFileName[name_len] = 0x04; /* pad */
2100 /* protocol requires ASCII signature byte on Unicode string */
2101 pSMB->OldFileName[name_len + 1] = 0x00;
2103 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2104 toName, PATH_MAX, nls_codepage, remap);
2105 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2106 name_len2 *= 2; /* convert to bytes */
2107 } else { /* BB improve the check for buffer overruns BB */
2108 name_len = strnlen(fromName, PATH_MAX);
2109 name_len++; /* trailing null */
2110 strncpy(pSMB->OldFileName, fromName, name_len);
2111 name_len2 = strnlen(toName, PATH_MAX);
2112 name_len2++; /* trailing null */
2113 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2114 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2115 name_len2++; /* trailing null */
2116 name_len2++; /* signature byte */
2119 count = 1 /* 1st signature byte */ + name_len + name_len2;
2120 pSMB->hdr.smb_buf_length += count;
2121 pSMB->ByteCount = cpu_to_le16(count);
2123 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2124 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2126 cFYI(1, ("Send error in copy = %d with %d files copied",
2127 rc, le16_to_cpu(pSMBr->CopyCount)));
2130 cifs_buf_release(pSMB);
2139 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2140 const char *fromName, const char *toName,
2141 const struct nls_table *nls_codepage)
2143 TRANSACTION2_SPI_REQ *pSMB = NULL;
2144 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2147 int name_len_target;
2149 int bytes_returned = 0;
2150 __u16 params, param_offset, offset, byte_count;
2152 cFYI(1, ("In Symlink Unix style"));
2154 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2159 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2161 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2162 /* find define for this maxpathcomponent */
2164 name_len++; /* trailing null */
2167 } else { /* BB improve the check for buffer overruns BB */
2168 name_len = strnlen(fromName, PATH_MAX);
2169 name_len++; /* trailing null */
2170 strncpy(pSMB->FileName, fromName, name_len);
2172 params = 6 + name_len;
2173 pSMB->MaxSetupCount = 0;
2177 pSMB->Reserved2 = 0;
2178 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2179 InformationLevel) - 4;
2180 offset = param_offset + params;
2182 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2183 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2185 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2186 /* find define for this maxpathcomponent */
2188 name_len_target++; /* trailing null */
2189 name_len_target *= 2;
2190 } else { /* BB improve the check for buffer overruns BB */
2191 name_len_target = strnlen(toName, PATH_MAX);
2192 name_len_target++; /* trailing null */
2193 strncpy(data_offset, toName, name_len_target);
2196 pSMB->MaxParameterCount = cpu_to_le16(2);
2197 /* BB find exact max on data count below from sess */
2198 pSMB->MaxDataCount = cpu_to_le16(1000);
2199 pSMB->SetupCount = 1;
2200 pSMB->Reserved3 = 0;
2201 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2202 byte_count = 3 /* pad */ + params + name_len_target;
2203 pSMB->DataCount = cpu_to_le16(name_len_target);
2204 pSMB->ParameterCount = cpu_to_le16(params);
2205 pSMB->TotalDataCount = pSMB->DataCount;
2206 pSMB->TotalParameterCount = pSMB->ParameterCount;
2207 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2208 pSMB->DataOffset = cpu_to_le16(offset);
2209 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2210 pSMB->Reserved4 = 0;
2211 pSMB->hdr.smb_buf_length += byte_count;
2212 pSMB->ByteCount = cpu_to_le16(byte_count);
2213 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2214 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2215 cifs_stats_inc(&tcon->num_symlinks);
2217 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2221 cifs_buf_release(pSMB);
2224 goto createSymLinkRetry;
2230 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2231 const char *fromName, const char *toName,
2232 const struct nls_table *nls_codepage, int remap)
2234 TRANSACTION2_SPI_REQ *pSMB = NULL;
2235 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2238 int name_len_target;
2240 int bytes_returned = 0;
2241 __u16 params, param_offset, offset, byte_count;
2243 cFYI(1, ("In Create Hard link Unix style"));
2244 createHardLinkRetry:
2245 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2250 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2251 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2252 PATH_MAX, nls_codepage, remap);
2253 name_len++; /* trailing null */
2256 } else { /* BB improve the check for buffer overruns BB */
2257 name_len = strnlen(toName, PATH_MAX);
2258 name_len++; /* trailing null */
2259 strncpy(pSMB->FileName, toName, name_len);
2261 params = 6 + name_len;
2262 pSMB->MaxSetupCount = 0;
2266 pSMB->Reserved2 = 0;
2267 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2268 InformationLevel) - 4;
2269 offset = param_offset + params;
2271 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2272 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2274 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2275 nls_codepage, remap);
2276 name_len_target++; /* trailing null */
2277 name_len_target *= 2;
2278 } else { /* BB improve the check for buffer overruns BB */
2279 name_len_target = strnlen(fromName, PATH_MAX);
2280 name_len_target++; /* trailing null */
2281 strncpy(data_offset, fromName, name_len_target);
2284 pSMB->MaxParameterCount = cpu_to_le16(2);
2285 /* BB find exact max on data count below from sess*/
2286 pSMB->MaxDataCount = cpu_to_le16(1000);
2287 pSMB->SetupCount = 1;
2288 pSMB->Reserved3 = 0;
2289 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2290 byte_count = 3 /* pad */ + params + name_len_target;
2291 pSMB->ParameterCount = cpu_to_le16(params);
2292 pSMB->TotalParameterCount = pSMB->ParameterCount;
2293 pSMB->DataCount = cpu_to_le16(name_len_target);
2294 pSMB->TotalDataCount = pSMB->DataCount;
2295 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2296 pSMB->DataOffset = cpu_to_le16(offset);
2297 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2298 pSMB->Reserved4 = 0;
2299 pSMB->hdr.smb_buf_length += byte_count;
2300 pSMB->ByteCount = cpu_to_le16(byte_count);
2301 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2302 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2303 cifs_stats_inc(&tcon->num_hardlinks);
2305 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2308 cifs_buf_release(pSMB);
2310 goto createHardLinkRetry;
2316 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2317 const char *fromName, const char *toName,
2318 const struct nls_table *nls_codepage, int remap)
2321 NT_RENAME_REQ *pSMB = NULL;
2322 RENAME_RSP *pSMBr = NULL;
2324 int name_len, name_len2;
2327 cFYI(1, ("In CIFSCreateHardLink"));
2328 winCreateHardLinkRetry:
2330 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2335 pSMB->SearchAttributes =
2336 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2338 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2339 pSMB->ClusterCount = 0;
2341 pSMB->BufferFormat = 0x04;
2343 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2345 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2346 PATH_MAX, nls_codepage, remap);
2347 name_len++; /* trailing null */
2349 pSMB->OldFileName[name_len] = 0; /* pad */
2350 pSMB->OldFileName[name_len + 1] = 0x04;
2352 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2353 toName, PATH_MAX, nls_codepage, remap);
2354 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2355 name_len2 *= 2; /* convert to bytes */
2356 } else { /* BB improve the check for buffer overruns BB */
2357 name_len = strnlen(fromName, PATH_MAX);
2358 name_len++; /* trailing null */
2359 strncpy(pSMB->OldFileName, fromName, name_len);
2360 name_len2 = strnlen(toName, PATH_MAX);
2361 name_len2++; /* trailing null */
2362 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2363 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2364 name_len2++; /* trailing null */
2365 name_len2++; /* signature byte */
2368 count = 1 /* string type byte */ + name_len + name_len2;
2369 pSMB->hdr.smb_buf_length += count;
2370 pSMB->ByteCount = cpu_to_le16(count);
2372 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2373 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2374 cifs_stats_inc(&tcon->num_hardlinks);
2376 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2378 cifs_buf_release(pSMB);
2380 goto winCreateHardLinkRetry;
2386 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2387 const unsigned char *searchName,
2388 char *symlinkinfo, const int buflen,
2389 const struct nls_table *nls_codepage)
2391 /* SMB_QUERY_FILE_UNIX_LINK */
2392 TRANSACTION2_QPI_REQ *pSMB = NULL;
2393 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2397 __u16 params, byte_count;
2399 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2402 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2407 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2409 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2410 PATH_MAX, nls_codepage);
2411 name_len++; /* trailing null */
2413 } else { /* BB improve the check for buffer overruns BB */
2414 name_len = strnlen(searchName, PATH_MAX);
2415 name_len++; /* trailing null */
2416 strncpy(pSMB->FileName, searchName, name_len);
2419 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2420 pSMB->TotalDataCount = 0;
2421 pSMB->MaxParameterCount = cpu_to_le16(2);
2422 /* BB find exact max data count below from sess structure BB */
2423 pSMB->MaxDataCount = cpu_to_le16(4000);
2424 pSMB->MaxSetupCount = 0;
2428 pSMB->Reserved2 = 0;
2429 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2430 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2431 pSMB->DataCount = 0;
2432 pSMB->DataOffset = 0;
2433 pSMB->SetupCount = 1;
2434 pSMB->Reserved3 = 0;
2435 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2436 byte_count = params + 1 /* pad */ ;
2437 pSMB->TotalParameterCount = cpu_to_le16(params);
2438 pSMB->ParameterCount = pSMB->TotalParameterCount;
2439 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2440 pSMB->Reserved4 = 0;
2441 pSMB->hdr.smb_buf_length += byte_count;
2442 pSMB->ByteCount = cpu_to_le16(byte_count);
2444 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2445 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2447 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2449 /* decode response */
2451 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2452 if (rc || (pSMBr->ByteCount < 2))
2453 /* BB also check enough total bytes returned */
2454 rc = -EIO; /* bad smb */
2456 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2457 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2459 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2460 name_len = UniStrnlen((wchar_t *) ((char *)
2461 &pSMBr->hdr.Protocol + data_offset),
2462 min_t(const int, buflen, count) / 2);
2463 /* BB FIXME investigate remapping reserved chars here */
2464 cifs_strfromUCS_le(symlinkinfo,
2465 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2467 name_len, nls_codepage);
2469 strncpy(symlinkinfo,
2470 (char *) &pSMBr->hdr.Protocol +
2472 min_t(const int, buflen, count));
2474 symlinkinfo[buflen] = 0;
2475 /* just in case so calling code does not go off the end of buffer */
2478 cifs_buf_release(pSMB);
2480 goto querySymLinkRetry;
2484 /* Initialize NT TRANSACT SMB into small smb request buffer.
2485 This assumes that all NT TRANSACTS that we init here have
2486 total parm and data under about 400 bytes (to fit in small cifs
2487 buffer size), which is the case so far, it easily fits. NB:
2488 Setup words themselves and ByteCount
2489 MaxSetupCount (size of returned setup area) and
2490 MaxParameterCount (returned parms size) must be set by caller */
2492 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2493 const int parm_len, struct cifsTconInfo *tcon,
2498 struct smb_com_ntransact_req *pSMB;
2500 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2504 *ret_buf = (void *)pSMB;
2506 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2507 pSMB->TotalDataCount = 0;
2508 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2509 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2510 pSMB->ParameterCount = pSMB->TotalParameterCount;
2511 pSMB->DataCount = pSMB->TotalDataCount;
2512 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2513 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2514 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2515 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2516 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2517 pSMB->SubCommand = cpu_to_le16(sub_command);
2522 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2523 int *pdatalen, int *pparmlen)
2526 __u32 data_count, data_offset, parm_count, parm_offset;
2527 struct smb_com_ntransact_rsp *pSMBr;
2532 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2534 /* ByteCount was converted from little endian in SendReceive */
2535 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2536 (char *)&pSMBr->ByteCount;
2538 data_offset = le32_to_cpu(pSMBr->DataOffset);
2539 data_count = le32_to_cpu(pSMBr->DataCount);
2540 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2541 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2543 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2544 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2546 /* should we also check that parm and data areas do not overlap? */
2547 if (*ppparm > end_of_smb) {
2548 cFYI(1, ("parms start after end of smb"));
2550 } else if (parm_count + *ppparm > end_of_smb) {
2551 cFYI(1, ("parm end after end of smb"));
2553 } else if (*ppdata > end_of_smb) {
2554 cFYI(1, ("data starts after end of smb"));
2556 } else if (data_count + *ppdata > end_of_smb) {
2557 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2558 *ppdata, data_count, (data_count + *ppdata),
2559 end_of_smb, pSMBr));
2561 } else if (parm_count + data_count > pSMBr->ByteCount) {
2562 cFYI(1, ("parm count and data count larger than SMB"));
2569 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2570 const unsigned char *searchName,
2571 char *symlinkinfo, const int buflen, __u16 fid,
2572 const struct nls_table *nls_codepage)
2577 struct smb_com_transaction_ioctl_req *pSMB;
2578 struct smb_com_transaction_ioctl_rsp *pSMBr;
2580 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2581 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2586 pSMB->TotalParameterCount = 0 ;
2587 pSMB->TotalDataCount = 0;
2588 pSMB->MaxParameterCount = cpu_to_le32(2);
2589 /* BB find exact data count max from sess structure BB */
2590 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2591 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2592 pSMB->MaxSetupCount = 4;
2594 pSMB->ParameterOffset = 0;
2595 pSMB->DataCount = 0;
2596 pSMB->DataOffset = 0;
2597 pSMB->SetupCount = 4;
2598 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2599 pSMB->ParameterCount = pSMB->TotalParameterCount;
2600 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2601 pSMB->IsFsctl = 1; /* FSCTL */
2602 pSMB->IsRootFlag = 0;
2603 pSMB->Fid = fid; /* file handle always le */
2604 pSMB->ByteCount = 0;
2606 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2607 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2609 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2610 } else { /* decode response */
2611 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2612 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2613 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2614 /* BB also check enough total bytes returned */
2615 rc = -EIO; /* bad smb */
2617 if (data_count && (data_count < 2048)) {
2618 char *end_of_smb = 2 /* sizeof byte count */ +
2620 (char *)&pSMBr->ByteCount;
2622 struct reparse_data *reparse_buf =
2623 (struct reparse_data *)
2624 ((char *)&pSMBr->hdr.Protocol
2626 if ((char *)reparse_buf >= end_of_smb) {
2630 if ((reparse_buf->LinkNamesBuf +
2631 reparse_buf->TargetNameOffset +
2632 reparse_buf->TargetNameLen) >
2634 cFYI(1, ("reparse buf beyond SMB"));
2639 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2640 name_len = UniStrnlen((wchar_t *)
2641 (reparse_buf->LinkNamesBuf +
2642 reparse_buf->TargetNameOffset),
2644 reparse_buf->TargetNameLen / 2));
2645 cifs_strfromUCS_le(symlinkinfo,
2646 (__le16 *) (reparse_buf->LinkNamesBuf +
2647 reparse_buf->TargetNameOffset),
2648 name_len, nls_codepage);
2649 } else { /* ASCII names */
2650 strncpy(symlinkinfo,
2651 reparse_buf->LinkNamesBuf +
2652 reparse_buf->TargetNameOffset,
2653 min_t(const int, buflen,
2654 reparse_buf->TargetNameLen));
2658 cFYI(1, ("Invalid return data count on "
2659 "get reparse info ioctl"));
2661 symlinkinfo[buflen] = 0; /* just in case so the caller
2662 does not go off the end of the buffer */
2663 cFYI(1, ("readlink result - %s", symlinkinfo));
2667 cifs_buf_release(pSMB);
2669 /* Note: On -EAGAIN error only caller can retry on handle based calls
2670 since file handle passed in no longer valid */
2675 #ifdef CONFIG_CIFS_POSIX
2677 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2678 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2679 struct cifs_posix_ace *cifs_ace)
2681 /* u8 cifs fields do not need le conversion */
2682 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2683 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2684 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2685 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2690 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2691 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2692 const int acl_type, const int size_of_data_area)
2697 struct cifs_posix_ace *pACE;
2698 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2699 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2701 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2704 if (acl_type & ACL_TYPE_ACCESS) {
2705 count = le16_to_cpu(cifs_acl->access_entry_count);
2706 pACE = &cifs_acl->ace_array[0];
2707 size = sizeof(struct cifs_posix_acl);
2708 size += sizeof(struct cifs_posix_ace) * count;
2709 /* check if we would go beyond end of SMB */
2710 if (size_of_data_area < size) {
2711 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2712 size_of_data_area, size));
2715 } else if (acl_type & ACL_TYPE_DEFAULT) {
2716 count = le16_to_cpu(cifs_acl->access_entry_count);
2717 size = sizeof(struct cifs_posix_acl);
2718 size += sizeof(struct cifs_posix_ace) * count;
2719 /* skip past access ACEs to get to default ACEs */
2720 pACE = &cifs_acl->ace_array[count];
2721 count = le16_to_cpu(cifs_acl->default_entry_count);
2722 size += sizeof(struct cifs_posix_ace) * count;
2723 /* check if we would go beyond end of SMB */
2724 if (size_of_data_area < size)
2731 size = posix_acl_xattr_size(count);
2732 if ((buflen == 0) || (local_acl == NULL)) {
2733 /* used to query ACL EA size */
2734 } else if (size > buflen) {
2736 } else /* buffer big enough */ {
2737 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2738 for (i = 0; i < count ; i++) {
2739 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2746 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2747 const posix_acl_xattr_entry *local_ace)
2749 __u16 rc = 0; /* 0 = ACL converted ok */
2751 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2752 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2753 /* BB is there a better way to handle the large uid? */
2754 if (local_ace->e_id == cpu_to_le32(-1)) {
2755 /* Probably no need to le convert -1 on any arch but can not hurt */
2756 cifs_ace->cifs_uid = cpu_to_le64(-1);
2758 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2759 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2763 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2764 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2765 const int buflen, const int acl_type)
2768 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2769 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2773 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2776 count = posix_acl_xattr_count((size_t)buflen);
2777 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2779 count, buflen, le32_to_cpu(local_acl->a_version)));
2780 if (le32_to_cpu(local_acl->a_version) != 2) {
2781 cFYI(1, ("unknown POSIX ACL version %d",
2782 le32_to_cpu(local_acl->a_version)));
2785 cifs_acl->version = cpu_to_le16(1);
2786 if (acl_type == ACL_TYPE_ACCESS)
2787 cifs_acl->access_entry_count = cpu_to_le16(count);
2788 else if (acl_type == ACL_TYPE_DEFAULT)
2789 cifs_acl->default_entry_count = cpu_to_le16(count);
2791 cFYI(1, ("unknown ACL type %d", acl_type));
2794 for (i = 0; i < count; i++) {
2795 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2796 &local_acl->a_entries[i]);
2798 /* ACE not converted */
2803 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2804 rc += sizeof(struct cifs_posix_acl);
2805 /* BB add check to make sure ACL does not overflow SMB */
2811 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2812 const unsigned char *searchName,
2813 char *acl_inf, const int buflen, const int acl_type,
2814 const struct nls_table *nls_codepage, int remap)
2816 /* SMB_QUERY_POSIX_ACL */
2817 TRANSACTION2_QPI_REQ *pSMB = NULL;
2818 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2822 __u16 params, byte_count;
2824 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2827 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2832 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2834 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2835 PATH_MAX, nls_codepage, remap);
2836 name_len++; /* trailing null */
2838 pSMB->FileName[name_len] = 0;
2839 pSMB->FileName[name_len+1] = 0;
2840 } else { /* BB improve the check for buffer overruns BB */
2841 name_len = strnlen(searchName, PATH_MAX);
2842 name_len++; /* trailing null */
2843 strncpy(pSMB->FileName, searchName, name_len);
2846 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2847 pSMB->TotalDataCount = 0;
2848 pSMB->MaxParameterCount = cpu_to_le16(2);
2849 /* BB find exact max data count below from sess structure BB */
2850 pSMB->MaxDataCount = cpu_to_le16(4000);
2851 pSMB->MaxSetupCount = 0;
2855 pSMB->Reserved2 = 0;
2856 pSMB->ParameterOffset = cpu_to_le16(
2857 offsetof(struct smb_com_transaction2_qpi_req,
2858 InformationLevel) - 4);
2859 pSMB->DataCount = 0;
2860 pSMB->DataOffset = 0;
2861 pSMB->SetupCount = 1;
2862 pSMB->Reserved3 = 0;
2863 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2864 byte_count = params + 1 /* pad */ ;
2865 pSMB->TotalParameterCount = cpu_to_le16(params);
2866 pSMB->ParameterCount = pSMB->TotalParameterCount;
2867 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2868 pSMB->Reserved4 = 0;
2869 pSMB->hdr.smb_buf_length += byte_count;
2870 pSMB->ByteCount = cpu_to_le16(byte_count);
2872 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2873 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2874 cifs_stats_inc(&tcon->num_acl_get);
2876 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2878 /* decode response */
2880 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2881 if (rc || (pSMBr->ByteCount < 2))
2882 /* BB also check enough total bytes returned */
2883 rc = -EIO; /* bad smb */
2885 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2886 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2887 rc = cifs_copy_posix_acl(acl_inf,
2888 (char *)&pSMBr->hdr.Protocol+data_offset,
2889 buflen, acl_type, count);
2892 cifs_buf_release(pSMB);
2899 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2900 const unsigned char *fileName,
2901 const char *local_acl, const int buflen,
2903 const struct nls_table *nls_codepage, int remap)
2905 struct smb_com_transaction2_spi_req *pSMB = NULL;
2906 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2910 int bytes_returned = 0;
2911 __u16 params, byte_count, data_count, param_offset, offset;
2913 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2915 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2919 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2921 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2922 PATH_MAX, nls_codepage, remap);
2923 name_len++; /* trailing null */
2925 } else { /* BB improve the check for buffer overruns BB */
2926 name_len = strnlen(fileName, PATH_MAX);
2927 name_len++; /* trailing null */
2928 strncpy(pSMB->FileName, fileName, name_len);
2930 params = 6 + name_len;
2931 pSMB->MaxParameterCount = cpu_to_le16(2);
2932 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2933 pSMB->MaxSetupCount = 0;
2937 pSMB->Reserved2 = 0;
2938 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2939 InformationLevel) - 4;
2940 offset = param_offset + params;
2941 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2942 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2944 /* convert to on the wire format for POSIX ACL */
2945 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2947 if (data_count == 0) {
2949 goto setACLerrorExit;
2951 pSMB->DataOffset = cpu_to_le16(offset);
2952 pSMB->SetupCount = 1;
2953 pSMB->Reserved3 = 0;
2954 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2955 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2956 byte_count = 3 /* pad */ + params + data_count;
2957 pSMB->DataCount = cpu_to_le16(data_count);
2958 pSMB->TotalDataCount = pSMB->DataCount;
2959 pSMB->ParameterCount = cpu_to_le16(params);
2960 pSMB->TotalParameterCount = pSMB->ParameterCount;
2961 pSMB->Reserved4 = 0;
2962 pSMB->hdr.smb_buf_length += byte_count;
2963 pSMB->ByteCount = cpu_to_le16(byte_count);
2964 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2965 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2967 cFYI(1, ("Set POSIX ACL returned %d", rc));
2971 cifs_buf_release(pSMB);
2977 /* BB fix tabs in this function FIXME BB */
2979 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2980 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2983 struct smb_t2_qfi_req *pSMB = NULL;
2984 struct smb_t2_qfi_rsp *pSMBr = NULL;
2986 __u16 params, byte_count;
2988 cFYI(1, ("In GetExtAttr"));
2993 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2998 params = 2 /* level */ +2 /* fid */;
2999 pSMB->t2.TotalDataCount = 0;
3000 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3001 /* BB find exact max data count below from sess structure BB */
3002 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3003 pSMB->t2.MaxSetupCount = 0;
3004 pSMB->t2.Reserved = 0;
3006 pSMB->t2.Timeout = 0;
3007 pSMB->t2.Reserved2 = 0;
3008 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3010 pSMB->t2.DataCount = 0;
3011 pSMB->t2.DataOffset = 0;
3012 pSMB->t2.SetupCount = 1;
3013 pSMB->t2.Reserved3 = 0;
3014 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3015 byte_count = params + 1 /* pad */ ;
3016 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3017 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3018 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3021 pSMB->hdr.smb_buf_length += byte_count;
3022 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3024 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3025 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3027 cFYI(1, ("error %d in GetExtAttr", rc));
3029 /* decode response */
3030 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3031 if (rc || (pSMBr->ByteCount < 2))
3032 /* BB also check enough total bytes returned */
3033 /* If rc should we check for EOPNOSUPP and
3034 disable the srvino flag? or in caller? */
3035 rc = -EIO; /* bad smb */
3037 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3038 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3039 struct file_chattr_info *pfinfo;
3040 /* BB Do we need a cast or hash here ? */
3042 cFYI(1, ("Illegal size ret in GetExtAttr"));
3046 pfinfo = (struct file_chattr_info *)
3047 (data_offset + (char *) &pSMBr->hdr.Protocol);
3048 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3049 *pMask = le64_to_cpu(pfinfo->mask);
3053 cifs_buf_release(pSMB);
3055 goto GetExtAttrRetry;
3059 #endif /* CONFIG_POSIX */
3061 #ifdef CONFIG_CIFS_EXPERIMENTAL
3062 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3064 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3065 /* BB fix up return info */ char *acl_inf, const int buflen,
3070 QUERY_SEC_DESC_REQ * pSMB;
3073 cFYI(1, ("GetCifsACL"));
3075 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3076 8 /* parm len */, tcon, (void **) &pSMB);
3080 pSMB->MaxParameterCount = cpu_to_le32(4);
3081 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3082 pSMB->MaxSetupCount = 0;
3083 pSMB->Fid = fid; /* file handle always le */
3084 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3086 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3087 pSMB->hdr.smb_buf_length += 11;
3088 iov[0].iov_base = (char *)pSMB;
3089 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3091 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
3092 cifs_stats_inc(&tcon->num_acl_get);
3094 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3095 } else { /* decode response */
3096 struct cifs_ntsd *psec_desc;
3101 struct smb_com_ntransact_rsp *pSMBr;
3103 /* validate_nttransact */
3104 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3105 (char **)&psec_desc,
3106 &parm_len, &data_len);
3109 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3111 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
3113 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3114 rc = -EIO; /* bad smb */
3118 /* BB check that data area is minimum length and as big as acl_len */
3120 acl_len = le32_to_cpu(*(__le32 *)parm);
3121 /* BB check if (acl_len > bufsize) */
3123 parse_sec_desc(psec_desc, acl_len);
3126 if (buf_type == CIFS_SMALL_BUFFER)
3127 cifs_small_buf_release(iov[0].iov_base);
3128 else if (buf_type == CIFS_LARGE_BUFFER)
3129 cifs_buf_release(iov[0].iov_base);
3130 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3133 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3135 /* Legacy Query Path Information call for lookup to old servers such
3137 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3138 const unsigned char *searchName,
3139 FILE_ALL_INFO *pFinfo,
3140 const struct nls_table *nls_codepage, int remap)
3142 QUERY_INFORMATION_REQ * pSMB;
3143 QUERY_INFORMATION_RSP * pSMBr;
3148 cFYI(1, ("In SMBQPath path %s", searchName));
3150 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3155 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3157 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3158 PATH_MAX, nls_codepage, remap);
3159 name_len++; /* trailing null */
3162 name_len = strnlen(searchName, PATH_MAX);
3163 name_len++; /* trailing null */
3164 strncpy(pSMB->FileName, searchName, name_len);
3166 pSMB->BufferFormat = 0x04;
3167 name_len++; /* account for buffer type byte */
3168 pSMB->hdr.smb_buf_length += (__u16) name_len;
3169 pSMB->ByteCount = cpu_to_le16(name_len);
3171 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3172 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3174 cFYI(1, ("Send error in QueryInfo = %d", rc));
3175 } else if (pFinfo) { /* decode response */
3177 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3178 /* BB FIXME - add time zone adjustment BB */
3179 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3182 /* decode time fields */
3183 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3184 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3185 pFinfo->LastAccessTime = 0;
3186 pFinfo->AllocationSize =
3187 cpu_to_le64(le32_to_cpu(pSMBr->size));
3188 pFinfo->EndOfFile = pFinfo->AllocationSize;
3189 pFinfo->Attributes =
3190 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3192 rc = -EIO; /* bad buffer passed in */
3194 cifs_buf_release(pSMB);
3206 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3207 const unsigned char *searchName,
3208 FILE_ALL_INFO * pFindData,
3209 int legacy /* old style infolevel */,
3210 const struct nls_table *nls_codepage, int remap)
3212 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3213 TRANSACTION2_QPI_REQ *pSMB = NULL;
3214 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3218 __u16 params, byte_count;
3220 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3222 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3227 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3229 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3230 PATH_MAX, nls_codepage, remap);
3231 name_len++; /* trailing null */
3233 } else { /* BB improve the check for buffer overruns BB */
3234 name_len = strnlen(searchName, PATH_MAX);
3235 name_len++; /* trailing null */
3236 strncpy(pSMB->FileName, searchName, name_len);
3239 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3240 pSMB->TotalDataCount = 0;
3241 pSMB->MaxParameterCount = cpu_to_le16(2);
3242 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3243 pSMB->MaxSetupCount = 0;
3247 pSMB->Reserved2 = 0;
3248 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3249 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3250 pSMB->DataCount = 0;
3251 pSMB->DataOffset = 0;
3252 pSMB->SetupCount = 1;
3253 pSMB->Reserved3 = 0;
3254 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3255 byte_count = params + 1 /* pad */ ;
3256 pSMB->TotalParameterCount = cpu_to_le16(params);
3257 pSMB->ParameterCount = pSMB->TotalParameterCount;
3259 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3261 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3262 pSMB->Reserved4 = 0;
3263 pSMB->hdr.smb_buf_length += byte_count;
3264 pSMB->ByteCount = cpu_to_le16(byte_count);
3266 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3267 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3269 cFYI(1, ("Send error in QPathInfo = %d", rc));
3270 } else { /* decode response */
3271 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3273 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3275 else if (!legacy && (pSMBr->ByteCount < 40))
3276 rc = -EIO; /* bad smb */
3277 else if (legacy && (pSMBr->ByteCount < 24))
3278 rc = -EIO; /* 24 or 26 expected but we do not read
3280 else if (pFindData) {
3282 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3283 if (legacy) /* we do not read the last field, EAsize,
3284 fortunately since it varies by subdialect
3285 and on Set vs. Get, is two bytes or 4
3286 bytes depending but we don't care here */
3287 size = sizeof(FILE_INFO_STANDARD);
3289 size = sizeof(FILE_ALL_INFO);
3290 memcpy((char *) pFindData,
3291 (char *) &pSMBr->hdr.Protocol +
3296 cifs_buf_release(pSMB);
3298 goto QPathInfoRetry;
3304 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3305 const unsigned char *searchName,
3306 FILE_UNIX_BASIC_INFO * pFindData,
3307 const struct nls_table *nls_codepage, int remap)
3309 /* SMB_QUERY_FILE_UNIX_BASIC */
3310 TRANSACTION2_QPI_REQ *pSMB = NULL;
3311 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3313 int bytes_returned = 0;
3315 __u16 params, byte_count;
3317 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3319 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3324 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3326 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3327 PATH_MAX, nls_codepage, remap);
3328 name_len++; /* trailing null */
3330 } else { /* BB improve the check for buffer overruns BB */
3331 name_len = strnlen(searchName, PATH_MAX);
3332 name_len++; /* trailing null */
3333 strncpy(pSMB->FileName, searchName, name_len);
3336 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3337 pSMB->TotalDataCount = 0;
3338 pSMB->MaxParameterCount = cpu_to_le16(2);
3339 /* BB find exact max SMB PDU from sess structure BB */
3340 pSMB->MaxDataCount = cpu_to_le16(4000);
3341 pSMB->MaxSetupCount = 0;
3345 pSMB->Reserved2 = 0;
3346 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3347 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3348 pSMB->DataCount = 0;
3349 pSMB->DataOffset = 0;
3350 pSMB->SetupCount = 1;
3351 pSMB->Reserved3 = 0;
3352 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3353 byte_count = params + 1 /* pad */ ;
3354 pSMB->TotalParameterCount = cpu_to_le16(params);
3355 pSMB->ParameterCount = pSMB->TotalParameterCount;
3356 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3357 pSMB->Reserved4 = 0;
3358 pSMB->hdr.smb_buf_length += byte_count;
3359 pSMB->ByteCount = cpu_to_le16(byte_count);
3361 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3362 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3364 cFYI(1, ("Send error in QPathInfo = %d", rc));
3365 } else { /* decode response */
3366 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3368 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3369 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3370 "Unix Extensions can be disabled on mount "
3371 "by specifying the nosfu mount option."));
3372 rc = -EIO; /* bad smb */
3374 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3375 memcpy((char *) pFindData,
3376 (char *) &pSMBr->hdr.Protocol +
3378 sizeof (FILE_UNIX_BASIC_INFO));
3381 cifs_buf_release(pSMB);
3383 goto UnixQPathInfoRetry;
3388 #if 0 /* function unused at present */
3389 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3390 const char *searchName, FILE_ALL_INFO * findData,
3391 const struct nls_table *nls_codepage)
3393 /* level 257 SMB_ */
3394 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3395 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3399 __u16 params, byte_count;
3401 cFYI(1, ("In FindUnique"));
3403 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3408 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3410 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3411 PATH_MAX, nls_codepage);
3412 name_len++; /* trailing null */
3414 } else { /* BB improve the check for buffer overruns BB */
3415 name_len = strnlen(searchName, PATH_MAX);
3416 name_len++; /* trailing null */
3417 strncpy(pSMB->FileName, searchName, name_len);
3420 params = 12 + name_len /* includes null */ ;
3421 pSMB->TotalDataCount = 0; /* no EAs */
3422 pSMB->MaxParameterCount = cpu_to_le16(2);
3423 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3424 pSMB->MaxSetupCount = 0;
3428 pSMB->Reserved2 = 0;
3429 pSMB->ParameterOffset = cpu_to_le16(
3430 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3431 pSMB->DataCount = 0;
3432 pSMB->DataOffset = 0;
3433 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3434 pSMB->Reserved3 = 0;
3435 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3436 byte_count = params + 1 /* pad */ ;
3437 pSMB->TotalParameterCount = cpu_to_le16(params);
3438 pSMB->ParameterCount = pSMB->TotalParameterCount;
3439 pSMB->SearchAttributes =
3440 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3442 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3443 pSMB->SearchFlags = cpu_to_le16(1);
3444 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3445 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3446 pSMB->hdr.smb_buf_length += byte_count;
3447 pSMB->ByteCount = cpu_to_le16(byte_count);
3449 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3450 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3453 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3454 } else { /* decode response */
3455 cifs_stats_inc(&tcon->num_ffirst);
3459 cifs_buf_release(pSMB);
3461 goto findUniqueRetry;
3465 #endif /* end unused (temporarily) function */
3467 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3469 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3470 const char *searchName,
3471 const struct nls_table *nls_codepage,
3473 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3475 /* level 257 SMB_ */
3476 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3477 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3478 T2_FFIRST_RSP_PARMS * parms;
3480 int bytes_returned = 0;
3482 __u16 params, byte_count;
3484 cFYI(1, ("In FindFirst for %s", searchName));
3487 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3492 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3494 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3495 PATH_MAX, nls_codepage, remap);
3496 /* We can not add the asterik earlier in case
3497 it got remapped to 0xF03A as if it were part of the
3498 directory name instead of a wildcard */
3500 pSMB->FileName[name_len] = dirsep;
3501 pSMB->FileName[name_len+1] = 0;
3502 pSMB->FileName[name_len+2] = '*';
3503 pSMB->FileName[name_len+3] = 0;
3504 name_len += 4; /* now the trailing null */
3505 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3506 pSMB->FileName[name_len+1] = 0;
3508 } else { /* BB add check for overrun of SMB buf BB */
3509 name_len = strnlen(searchName, PATH_MAX);
3510 /* BB fix here and in unicode clause above ie
3511 if (name_len > buffersize-header)
3512 free buffer exit; BB */
3513 strncpy(pSMB->FileName, searchName, name_len);
3514 pSMB->FileName[name_len] = dirsep;
3515 pSMB->FileName[name_len+1] = '*';
3516 pSMB->FileName[name_len+2] = 0;
3520 params = 12 + name_len /* includes null */ ;
3521 pSMB->TotalDataCount = 0; /* no EAs */
3522 pSMB->MaxParameterCount = cpu_to_le16(10);
3523 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3524 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3525 pSMB->MaxSetupCount = 0;
3529 pSMB->Reserved2 = 0;
3530 byte_count = params + 1 /* pad */ ;
3531 pSMB->TotalParameterCount = cpu_to_le16(params);
3532 pSMB->ParameterCount = pSMB->TotalParameterCount;
3533 pSMB->ParameterOffset = cpu_to_le16(
3534 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3536 pSMB->DataCount = 0;
3537 pSMB->DataOffset = 0;
3538 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3539 pSMB->Reserved3 = 0;
3540 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3541 pSMB->SearchAttributes =
3542 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3544 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3545 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3546 CIFS_SEARCH_RETURN_RESUME);
3547 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3549 /* BB what should we set StorageType to? Does it matter? BB */
3550 pSMB->SearchStorageType = 0;
3551 pSMB->hdr.smb_buf_length += byte_count;
3552 pSMB->ByteCount = cpu_to_le16(byte_count);
3554 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3555 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3556 cifs_stats_inc(&tcon->num_ffirst);
3558 if (rc) {/* BB add logic to retry regular search if Unix search
3559 rejected unexpectedly by server */
3560 /* BB Add code to handle unsupported level rc */
3561 cFYI(1, ("Error in FindFirst = %d", rc));
3563 cifs_buf_release(pSMB);
3565 /* BB eventually could optimize out free and realloc of buf */
3568 goto findFirstRetry;
3569 } else { /* decode response */
3570 /* BB remember to free buffer if error BB */
3571 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3573 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3574 psrch_inf->unicode = TRUE;
3576 psrch_inf->unicode = FALSE;
3578 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3579 psrch_inf->smallBuf = 0;
3580 psrch_inf->srch_entries_start =
3581 (char *) &pSMBr->hdr.Protocol +
3582 le16_to_cpu(pSMBr->t2.DataOffset);
3583 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3584 le16_to_cpu(pSMBr->t2.ParameterOffset));
3586 if (parms->EndofSearch)
3587 psrch_inf->endOfSearch = TRUE;
3589 psrch_inf->endOfSearch = FALSE;
3591 psrch_inf->entries_in_buffer =
3592 le16_to_cpu(parms->SearchCount);
3593 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3594 psrch_inf->entries_in_buffer;
3595 *pnetfid = parms->SearchHandle;
3597 cifs_buf_release(pSMB);
3604 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3605 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3607 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3608 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3609 T2_FNEXT_RSP_PARMS * parms;
3610 char *response_data;
3612 int bytes_returned, name_len;
3613 __u16 params, byte_count;
3615 cFYI(1, ("In FindNext"));
3617 if (psrch_inf->endOfSearch == TRUE)
3620 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3625 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3627 pSMB->TotalDataCount = 0; /* no EAs */
3628 pSMB->MaxParameterCount = cpu_to_le16(8);
3629 pSMB->MaxDataCount =
3630 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3632 pSMB->MaxSetupCount = 0;
3636 pSMB->Reserved2 = 0;
3637 pSMB->ParameterOffset = cpu_to_le16(
3638 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3639 pSMB->DataCount = 0;
3640 pSMB->DataOffset = 0;
3641 pSMB->SetupCount = 1;
3642 pSMB->Reserved3 = 0;
3643 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3644 pSMB->SearchHandle = searchHandle; /* always kept as le */
3646 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3647 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3648 pSMB->ResumeKey = psrch_inf->resume_key;
3650 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3652 name_len = psrch_inf->resume_name_len;
3654 if (name_len < PATH_MAX) {
3655 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3656 byte_count += name_len;
3657 /* 14 byte parm len above enough for 2 byte null terminator */
3658 pSMB->ResumeFileName[name_len] = 0;
3659 pSMB->ResumeFileName[name_len+1] = 0;
3662 goto FNext2_err_exit;
3664 byte_count = params + 1 /* pad */ ;
3665 pSMB->TotalParameterCount = cpu_to_le16(params);
3666 pSMB->ParameterCount = pSMB->TotalParameterCount;
3667 pSMB->hdr.smb_buf_length += byte_count;
3668 pSMB->ByteCount = cpu_to_le16(byte_count);
3670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3672 cifs_stats_inc(&tcon->num_fnext);
3675 psrch_inf->endOfSearch = TRUE;
3676 rc = 0; /* search probably was closed at end of search*/
3678 cFYI(1, ("FindNext returned = %d", rc));
3679 } else { /* decode response */
3680 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3683 /* BB fixme add lock for file (srch_info) struct here */
3684 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3685 psrch_inf->unicode = TRUE;
3687 psrch_inf->unicode = FALSE;
3688 response_data = (char *) &pSMBr->hdr.Protocol +
3689 le16_to_cpu(pSMBr->t2.ParameterOffset);
3690 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3691 response_data = (char *)&pSMBr->hdr.Protocol +
3692 le16_to_cpu(pSMBr->t2.DataOffset);
3693 if (psrch_inf->smallBuf)
3694 cifs_small_buf_release(
3695 psrch_inf->ntwrk_buf_start);
3697 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3698 psrch_inf->srch_entries_start = response_data;
3699 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3700 psrch_inf->smallBuf = 0;
3701 if (parms->EndofSearch)
3702 psrch_inf->endOfSearch = TRUE;
3704 psrch_inf->endOfSearch = FALSE;
3705 psrch_inf->entries_in_buffer =
3706 le16_to_cpu(parms->SearchCount);
3707 psrch_inf->index_of_last_entry +=
3708 psrch_inf->entries_in_buffer;
3709 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3710 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3712 /* BB fixme add unlock here */
3717 /* BB On error, should we leave previous search buf (and count and
3718 last entry fields) intact or free the previous one? */
3720 /* Note: On -EAGAIN error only caller can retry on handle based calls
3721 since file handle passed in no longer valid */
3724 cifs_buf_release(pSMB);
3729 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3730 const __u16 searchHandle)
3733 FINDCLOSE_REQ *pSMB = NULL;
3734 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3737 cFYI(1, ("In CIFSSMBFindClose"));
3738 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3740 /* no sense returning error if session restarted
3741 as file handle has been closed */
3747 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3748 pSMB->FileID = searchHandle;
3749 pSMB->ByteCount = 0;
3750 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3751 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3753 cERROR(1, ("Send error in FindClose = %d", rc));
3755 cifs_stats_inc(&tcon->num_fclose);
3756 cifs_small_buf_release(pSMB);
3758 /* Since session is dead, search handle closed on server already */
3766 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3767 const unsigned char *searchName,
3768 __u64 * inode_number,
3769 const struct nls_table *nls_codepage, int remap)
3772 TRANSACTION2_QPI_REQ *pSMB = NULL;
3773 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3774 int name_len, bytes_returned;
3775 __u16 params, byte_count;
3777 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3781 GetInodeNumberRetry:
3782 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3787 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3789 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3790 PATH_MAX, nls_codepage, remap);
3791 name_len++; /* trailing null */
3793 } else { /* BB improve the check for buffer overruns BB */
3794 name_len = strnlen(searchName, PATH_MAX);
3795 name_len++; /* trailing null */
3796 strncpy(pSMB->FileName, searchName, name_len);
3799 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3800 pSMB->TotalDataCount = 0;
3801 pSMB->MaxParameterCount = cpu_to_le16(2);
3802 /* BB find exact max data count below from sess structure BB */
3803 pSMB->MaxDataCount = cpu_to_le16(4000);
3804 pSMB->MaxSetupCount = 0;
3808 pSMB->Reserved2 = 0;
3809 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3810 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3811 pSMB->DataCount = 0;
3812 pSMB->DataOffset = 0;
3813 pSMB->SetupCount = 1;
3814 pSMB->Reserved3 = 0;
3815 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3816 byte_count = params + 1 /* pad */ ;
3817 pSMB->TotalParameterCount = cpu_to_le16(params);
3818 pSMB->ParameterCount = pSMB->TotalParameterCount;
3819 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3820 pSMB->Reserved4 = 0;
3821 pSMB->hdr.smb_buf_length += byte_count;
3822 pSMB->ByteCount = cpu_to_le16(byte_count);
3824 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3825 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3827 cFYI(1, ("error %d in QueryInternalInfo", rc));
3829 /* decode response */
3830 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3831 if (rc || (pSMBr->ByteCount < 2))
3832 /* BB also check enough total bytes returned */
3833 /* If rc should we check for EOPNOSUPP and
3834 disable the srvino flag? or in caller? */
3835 rc = -EIO; /* bad smb */
3837 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3838 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3839 struct file_internal_info *pfinfo;
3840 /* BB Do we need a cast or hash here ? */
3842 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3844 goto GetInodeNumOut;
3846 pfinfo = (struct file_internal_info *)
3847 (data_offset + (char *) &pSMBr->hdr.Protocol);
3848 *inode_number = pfinfo->UniqueId;
3852 cifs_buf_release(pSMB);
3854 goto GetInodeNumberRetry;
3859 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3860 const unsigned char *searchName,
3861 unsigned char **targetUNCs,
3862 unsigned int *number_of_UNC_in_array,
3863 const struct nls_table *nls_codepage, int remap)
3865 /* TRANS2_GET_DFS_REFERRAL */
3866 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3867 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3868 struct dfs_referral_level_3 *referrals = NULL;
3874 __u16 params, byte_count;
3875 *number_of_UNC_in_array = 0;
3878 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3882 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3887 /* server pointer checked in called function,
3888 but should never be null here anyway */
3889 pSMB->hdr.Mid = GetNextMid(ses->server);
3890 pSMB->hdr.Tid = ses->ipc_tid;
3891 pSMB->hdr.Uid = ses->Suid;
3892 if (ses->capabilities & CAP_STATUS32)
3893 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3894 if (ses->capabilities & CAP_DFS)
3895 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3897 if (ses->capabilities & CAP_UNICODE) {
3898 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3900 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3901 searchName, PATH_MAX, nls_codepage, remap);
3902 name_len++; /* trailing null */
3904 } else { /* BB improve the check for buffer overruns BB */
3905 name_len = strnlen(searchName, PATH_MAX);
3906 name_len++; /* trailing null */
3907 strncpy(pSMB->RequestFileName, searchName, name_len);
3911 if (ses->server->secMode &
3912 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3913 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3916 pSMB->hdr.Uid = ses->Suid;
3918 params = 2 /* level */ + name_len /*includes null */ ;
3919 pSMB->TotalDataCount = 0;
3920 pSMB->DataCount = 0;
3921 pSMB->DataOffset = 0;
3922 pSMB->MaxParameterCount = 0;
3923 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3924 pSMB->MaxSetupCount = 0;
3928 pSMB->Reserved2 = 0;
3929 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3930 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3931 pSMB->SetupCount = 1;
3932 pSMB->Reserved3 = 0;
3933 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3934 byte_count = params + 3 /* pad */ ;
3935 pSMB->ParameterCount = cpu_to_le16(params);
3936 pSMB->TotalParameterCount = pSMB->ParameterCount;
3937 pSMB->MaxReferralLevel = cpu_to_le16(3);
3938 pSMB->hdr.smb_buf_length += byte_count;
3939 pSMB->ByteCount = cpu_to_le16(byte_count);
3941 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3942 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3944 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3945 } else { /* decode response */
3946 /* BB Add logic to parse referrals here */
3947 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3949 /* BB Also check if enough total bytes returned? */
3950 if (rc || (pSMBr->ByteCount < 17))
3951 rc = -EIO; /* bad smb */
3953 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3954 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3957 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3958 pSMBr->ByteCount, data_offset));
3960 (struct dfs_referral_level_3 *)
3961 (8 /* sizeof start of data block */ +
3963 (char *) &pSMBr->hdr.Protocol);
3964 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3965 "for referral one refer size: 0x%x srv "
3966 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3967 le16_to_cpu(pSMBr->NumberOfReferrals),
3968 le16_to_cpu(pSMBr->DFSFlags),
3969 le16_to_cpu(referrals->ReferralSize),
3970 le16_to_cpu(referrals->ServerType),
3971 le16_to_cpu(referrals->ReferralFlags),
3972 le16_to_cpu(referrals->TimeToLive)));
3973 /* BB This field is actually two bytes in from start of
3974 data block so we could do safety check that DataBlock
3975 begins at address of pSMBr->NumberOfReferrals */
3976 *number_of_UNC_in_array =
3977 le16_to_cpu(pSMBr->NumberOfReferrals);
3979 /* BB Fix below so can return more than one referral */
3980 if (*number_of_UNC_in_array > 1)
3981 *number_of_UNC_in_array = 1;
3983 /* get the length of the strings describing refs */
3985 for (i = 0; i < *number_of_UNC_in_array; i++) {
3986 /* make sure that DfsPathOffset not past end */
3988 le16_to_cpu(referrals->DfsPathOffset);
3989 if (offset > data_count) {
3990 /* if invalid referral, stop here and do
3991 not try to copy any more */
3992 *number_of_UNC_in_array = i;
3995 temp = ((char *)referrals) + offset;
3997 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3998 name_len += UniStrnlen((wchar_t *)temp,
4001 name_len += strnlen(temp, data_count);
4004 /* BB add check that referral pointer does
4005 not fall off end PDU */
4007 /* BB add check for name_len bigger than bcc */
4009 kmalloc(name_len+1+(*number_of_UNC_in_array),
4011 if (*targetUNCs == NULL) {
4015 /* copy the ref strings */
4016 referrals = (struct dfs_referral_level_3 *)
4017 (8 /* sizeof data hdr */ + data_offset +
4018 (char *) &pSMBr->hdr.Protocol);
4020 for (i = 0; i < *number_of_UNC_in_array; i++) {
4021 temp = ((char *)referrals) +
4022 le16_to_cpu(referrals->DfsPathOffset);
4023 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4024 cifs_strfromUCS_le(*targetUNCs,
4029 strncpy(*targetUNCs, temp, name_len);
4031 /* BB update target_uncs pointers */
4041 cifs_buf_release(pSMB);
4049 /* Query File System Info such as free space to old servers such as Win 9x */
4051 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4053 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4054 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4055 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4056 FILE_SYSTEM_ALLOC_INFO *response_data;
4058 int bytes_returned = 0;
4059 __u16 params, byte_count;
4061 cFYI(1, ("OldQFSInfo"));
4063 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4068 params = 2; /* level */
4069 pSMB->TotalDataCount = 0;
4070 pSMB->MaxParameterCount = cpu_to_le16(2);
4071 pSMB->MaxDataCount = cpu_to_le16(1000);
4072 pSMB->MaxSetupCount = 0;
4076 pSMB->Reserved2 = 0;
4077 byte_count = params + 1 /* pad */ ;
4078 pSMB->TotalParameterCount = cpu_to_le16(params);
4079 pSMB->ParameterCount = pSMB->TotalParameterCount;
4080 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4081 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4082 pSMB->DataCount = 0;
4083 pSMB->DataOffset = 0;
4084 pSMB->SetupCount = 1;
4085 pSMB->Reserved3 = 0;
4086 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4087 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4088 pSMB->hdr.smb_buf_length += byte_count;
4089 pSMB->ByteCount = cpu_to_le16(byte_count);
4091 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4092 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4094 cFYI(1, ("Send error in QFSInfo = %d", rc));
4095 } else { /* decode response */
4096 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4098 if (rc || (pSMBr->ByteCount < 18))
4099 rc = -EIO; /* bad smb */
4101 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4102 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4103 pSMBr->ByteCount, data_offset));
4105 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4106 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4108 le16_to_cpu(response_data->BytesPerSector) *
4109 le32_to_cpu(response_data->
4110 SectorsPerAllocationUnit);
4112 le32_to_cpu(response_data->TotalAllocationUnits);
4113 FSData->f_bfree = FSData->f_bavail =
4114 le32_to_cpu(response_data->FreeAllocationUnits);
4116 ("Blocks: %lld Free: %lld Block size %ld",
4117 (unsigned long long)FSData->f_blocks,
4118 (unsigned long long)FSData->f_bfree,
4122 cifs_buf_release(pSMB);
4125 goto oldQFSInfoRetry;
4131 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4133 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4134 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4135 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4136 FILE_SYSTEM_INFO *response_data;
4138 int bytes_returned = 0;
4139 __u16 params, byte_count;
4141 cFYI(1, ("In QFSInfo"));
4143 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4148 params = 2; /* level */
4149 pSMB->TotalDataCount = 0;
4150 pSMB->MaxParameterCount = cpu_to_le16(2);
4151 pSMB->MaxDataCount = cpu_to_le16(1000);
4152 pSMB->MaxSetupCount = 0;
4156 pSMB->Reserved2 = 0;
4157 byte_count = params + 1 /* pad */ ;
4158 pSMB->TotalParameterCount = cpu_to_le16(params);
4159 pSMB->ParameterCount = pSMB->TotalParameterCount;
4160 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4161 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4162 pSMB->DataCount = 0;
4163 pSMB->DataOffset = 0;
4164 pSMB->SetupCount = 1;
4165 pSMB->Reserved3 = 0;
4166 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4167 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4168 pSMB->hdr.smb_buf_length += byte_count;
4169 pSMB->ByteCount = cpu_to_le16(byte_count);
4171 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4172 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4174 cFYI(1, ("Send error in QFSInfo = %d", rc));
4175 } else { /* decode response */
4176 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4178 if (rc || (pSMBr->ByteCount < 24))
4179 rc = -EIO; /* bad smb */
4181 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4185 *) (((char *) &pSMBr->hdr.Protocol) +
4188 le32_to_cpu(response_data->BytesPerSector) *
4189 le32_to_cpu(response_data->
4190 SectorsPerAllocationUnit);
4192 le64_to_cpu(response_data->TotalAllocationUnits);
4193 FSData->f_bfree = FSData->f_bavail =
4194 le64_to_cpu(response_data->FreeAllocationUnits);
4196 ("Blocks: %lld Free: %lld Block size %ld",
4197 (unsigned long long)FSData->f_blocks,
4198 (unsigned long long)FSData->f_bfree,
4202 cifs_buf_release(pSMB);
4211 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4213 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4214 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4215 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4216 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4218 int bytes_returned = 0;
4219 __u16 params, byte_count;
4221 cFYI(1, ("In QFSAttributeInfo"));
4223 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4228 params = 2; /* level */
4229 pSMB->TotalDataCount = 0;
4230 pSMB->MaxParameterCount = cpu_to_le16(2);
4231 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4232 pSMB->MaxSetupCount = 0;
4236 pSMB->Reserved2 = 0;
4237 byte_count = params + 1 /* pad */ ;
4238 pSMB->TotalParameterCount = cpu_to_le16(params);
4239 pSMB->ParameterCount = pSMB->TotalParameterCount;
4240 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4241 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4242 pSMB->DataCount = 0;
4243 pSMB->DataOffset = 0;
4244 pSMB->SetupCount = 1;
4245 pSMB->Reserved3 = 0;
4246 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4247 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4248 pSMB->hdr.smb_buf_length += byte_count;
4249 pSMB->ByteCount = cpu_to_le16(byte_count);
4251 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4252 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4254 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4255 } else { /* decode response */
4256 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4258 if (rc || (pSMBr->ByteCount < 13)) {
4259 /* BB also check if enough bytes returned */
4260 rc = -EIO; /* bad smb */
4262 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4264 (FILE_SYSTEM_ATTRIBUTE_INFO
4265 *) (((char *) &pSMBr->hdr.Protocol) +
4267 memcpy(&tcon->fsAttrInfo, response_data,
4268 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4271 cifs_buf_release(pSMB);
4274 goto QFSAttributeRetry;
4280 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4282 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4283 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4284 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4285 FILE_SYSTEM_DEVICE_INFO *response_data;
4287 int bytes_returned = 0;
4288 __u16 params, byte_count;
4290 cFYI(1, ("In QFSDeviceInfo"));
4292 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4297 params = 2; /* level */
4298 pSMB->TotalDataCount = 0;
4299 pSMB->MaxParameterCount = cpu_to_le16(2);
4300 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4301 pSMB->MaxSetupCount = 0;
4305 pSMB->Reserved2 = 0;
4306 byte_count = params + 1 /* pad */ ;
4307 pSMB->TotalParameterCount = cpu_to_le16(params);
4308 pSMB->ParameterCount = pSMB->TotalParameterCount;
4309 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4310 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4312 pSMB->DataCount = 0;
4313 pSMB->DataOffset = 0;
4314 pSMB->SetupCount = 1;
4315 pSMB->Reserved3 = 0;
4316 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4317 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4318 pSMB->hdr.smb_buf_length += byte_count;
4319 pSMB->ByteCount = cpu_to_le16(byte_count);
4321 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4322 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4324 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4325 } else { /* decode response */
4326 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4328 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4329 rc = -EIO; /* bad smb */
4331 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4333 (FILE_SYSTEM_DEVICE_INFO *)
4334 (((char *) &pSMBr->hdr.Protocol) +
4336 memcpy(&tcon->fsDevInfo, response_data,
4337 sizeof(FILE_SYSTEM_DEVICE_INFO));
4340 cifs_buf_release(pSMB);
4343 goto QFSDeviceRetry;
4349 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4351 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4352 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4353 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4354 FILE_SYSTEM_UNIX_INFO *response_data;
4356 int bytes_returned = 0;
4357 __u16 params, byte_count;
4359 cFYI(1, ("In QFSUnixInfo"));
4361 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4366 params = 2; /* level */
4367 pSMB->TotalDataCount = 0;
4368 pSMB->DataCount = 0;
4369 pSMB->DataOffset = 0;
4370 pSMB->MaxParameterCount = cpu_to_le16(2);
4371 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4372 pSMB->MaxSetupCount = 0;
4376 pSMB->Reserved2 = 0;
4377 byte_count = params + 1 /* pad */ ;
4378 pSMB->ParameterCount = cpu_to_le16(params);
4379 pSMB->TotalParameterCount = pSMB->ParameterCount;
4380 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4381 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4382 pSMB->SetupCount = 1;
4383 pSMB->Reserved3 = 0;
4384 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4385 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4386 pSMB->hdr.smb_buf_length += byte_count;
4387 pSMB->ByteCount = cpu_to_le16(byte_count);
4389 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4390 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4392 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4393 } else { /* decode response */
4394 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4396 if (rc || (pSMBr->ByteCount < 13)) {
4397 rc = -EIO; /* bad smb */
4399 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4401 (FILE_SYSTEM_UNIX_INFO
4402 *) (((char *) &pSMBr->hdr.Protocol) +
4404 memcpy(&tcon->fsUnixInfo, response_data,
4405 sizeof(FILE_SYSTEM_UNIX_INFO));
4408 cifs_buf_release(pSMB);
4418 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4420 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4421 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4422 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4424 int bytes_returned = 0;
4425 __u16 params, param_offset, offset, byte_count;
4427 cFYI(1, ("In SETFSUnixInfo"));
4429 /* BB switch to small buf init to save memory */
4430 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4435 params = 4; /* 2 bytes zero followed by info level. */
4436 pSMB->MaxSetupCount = 0;
4440 pSMB->Reserved2 = 0;
4441 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4443 offset = param_offset + params;
4445 pSMB->MaxParameterCount = cpu_to_le16(4);
4446 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4447 pSMB->SetupCount = 1;
4448 pSMB->Reserved3 = 0;
4449 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4450 byte_count = 1 /* pad */ + params + 12;
4452 pSMB->DataCount = cpu_to_le16(12);
4453 pSMB->ParameterCount = cpu_to_le16(params);
4454 pSMB->TotalDataCount = pSMB->DataCount;
4455 pSMB->TotalParameterCount = pSMB->ParameterCount;
4456 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4457 pSMB->DataOffset = cpu_to_le16(offset);
4461 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4464 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4465 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4466 pSMB->ClientUnixCap = cpu_to_le64(cap);
4468 pSMB->hdr.smb_buf_length += byte_count;
4469 pSMB->ByteCount = cpu_to_le16(byte_count);
4471 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4472 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4474 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4475 } else { /* decode response */
4476 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4478 rc = -EIO; /* bad smb */
4481 cifs_buf_release(pSMB);
4484 goto SETFSUnixRetry;
4492 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4493 struct kstatfs *FSData)
4495 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4496 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4497 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4498 FILE_SYSTEM_POSIX_INFO *response_data;
4500 int bytes_returned = 0;
4501 __u16 params, byte_count;
4503 cFYI(1, ("In QFSPosixInfo"));
4505 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4510 params = 2; /* level */
4511 pSMB->TotalDataCount = 0;
4512 pSMB->DataCount = 0;
4513 pSMB->DataOffset = 0;
4514 pSMB->MaxParameterCount = cpu_to_le16(2);
4515 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4516 pSMB->MaxSetupCount = 0;
4520 pSMB->Reserved2 = 0;
4521 byte_count = params + 1 /* pad */ ;
4522 pSMB->ParameterCount = cpu_to_le16(params);
4523 pSMB->TotalParameterCount = pSMB->ParameterCount;
4524 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4525 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4526 pSMB->SetupCount = 1;
4527 pSMB->Reserved3 = 0;
4528 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4529 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4530 pSMB->hdr.smb_buf_length += byte_count;
4531 pSMB->ByteCount = cpu_to_le16(byte_count);
4533 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4534 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4536 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4537 } else { /* decode response */
4538 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4540 if (rc || (pSMBr->ByteCount < 13)) {
4541 rc = -EIO; /* bad smb */
4543 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4545 (FILE_SYSTEM_POSIX_INFO
4546 *) (((char *) &pSMBr->hdr.Protocol) +
4549 le32_to_cpu(response_data->BlockSize);
4551 le64_to_cpu(response_data->TotalBlocks);
4553 le64_to_cpu(response_data->BlocksAvail);
4554 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4555 FSData->f_bavail = FSData->f_bfree;
4558 le64_to_cpu(response_data->UserBlocksAvail);
4560 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4562 le64_to_cpu(response_data->TotalFileNodes);
4563 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4565 le64_to_cpu(response_data->FreeFileNodes);
4568 cifs_buf_release(pSMB);
4577 /* We can not use write of zero bytes trick to
4578 set file size due to need for large file support. Also note that
4579 this SetPathInfo is preferred to SetFileInfo based method in next
4580 routine which is only needed to work around a sharing violation bug
4581 in Samba which this routine can run into */
4584 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4585 __u64 size, int SetAllocation,
4586 const struct nls_table *nls_codepage, int remap)
4588 struct smb_com_transaction2_spi_req *pSMB = NULL;
4589 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4590 struct file_end_of_file_info *parm_data;
4593 int bytes_returned = 0;
4594 __u16 params, byte_count, data_count, param_offset, offset;
4596 cFYI(1, ("In SetEOF"));
4598 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4603 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4605 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4606 PATH_MAX, nls_codepage, remap);
4607 name_len++; /* trailing null */
4609 } else { /* BB improve the check for buffer overruns BB */
4610 name_len = strnlen(fileName, PATH_MAX);
4611 name_len++; /* trailing null */
4612 strncpy(pSMB->FileName, fileName, name_len);
4614 params = 6 + name_len;
4615 data_count = sizeof(struct file_end_of_file_info);
4616 pSMB->MaxParameterCount = cpu_to_le16(2);
4617 pSMB->MaxDataCount = cpu_to_le16(4100);
4618 pSMB->MaxSetupCount = 0;
4622 pSMB->Reserved2 = 0;
4623 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4624 InformationLevel) - 4;
4625 offset = param_offset + params;
4626 if (SetAllocation) {
4627 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4628 pSMB->InformationLevel =
4629 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4631 pSMB->InformationLevel =
4632 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4633 } else /* Set File Size */ {
4634 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4635 pSMB->InformationLevel =
4636 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4638 pSMB->InformationLevel =
4639 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4643 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4645 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4646 pSMB->DataOffset = cpu_to_le16(offset);
4647 pSMB->SetupCount = 1;
4648 pSMB->Reserved3 = 0;
4649 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4650 byte_count = 3 /* pad */ + params + data_count;
4651 pSMB->DataCount = cpu_to_le16(data_count);
4652 pSMB->TotalDataCount = pSMB->DataCount;
4653 pSMB->ParameterCount = cpu_to_le16(params);
4654 pSMB->TotalParameterCount = pSMB->ParameterCount;
4655 pSMB->Reserved4 = 0;
4656 pSMB->hdr.smb_buf_length += byte_count;
4657 parm_data->FileSize = cpu_to_le64(size);
4658 pSMB->ByteCount = cpu_to_le16(byte_count);
4659 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4660 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4662 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4665 cifs_buf_release(pSMB);
4674 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4675 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4677 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4678 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4680 struct file_end_of_file_info *parm_data;
4682 int bytes_returned = 0;
4683 __u16 params, param_offset, offset, byte_count, count;
4685 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4687 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4692 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4694 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4695 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4698 pSMB->MaxSetupCount = 0;
4702 pSMB->Reserved2 = 0;
4703 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4704 offset = param_offset + params;
4706 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4708 count = sizeof(struct file_end_of_file_info);
4709 pSMB->MaxParameterCount = cpu_to_le16(2);
4710 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4711 pSMB->SetupCount = 1;
4712 pSMB->Reserved3 = 0;
4713 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4714 byte_count = 3 /* pad */ + params + count;
4715 pSMB->DataCount = cpu_to_le16(count);
4716 pSMB->ParameterCount = cpu_to_le16(params);
4717 pSMB->TotalDataCount = pSMB->DataCount;
4718 pSMB->TotalParameterCount = pSMB->ParameterCount;
4719 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4721 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4723 pSMB->DataOffset = cpu_to_le16(offset);
4724 parm_data->FileSize = cpu_to_le64(size);
4726 if (SetAllocation) {
4727 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4728 pSMB->InformationLevel =
4729 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4731 pSMB->InformationLevel =
4732 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4733 } else /* Set File Size */ {
4734 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4735 pSMB->InformationLevel =
4736 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4738 pSMB->InformationLevel =
4739 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4741 pSMB->Reserved4 = 0;
4742 pSMB->hdr.smb_buf_length += byte_count;
4743 pSMB->ByteCount = cpu_to_le16(byte_count);
4744 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4745 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4748 ("Send error in SetFileInfo (SetFileSize) = %d",
4753 cifs_small_buf_release(pSMB);
4755 /* Note: On -EAGAIN error only caller can retry on handle based calls
4756 since file handle passed in no longer valid */
4761 /* Some legacy servers such as NT4 require that the file times be set on
4762 an open handle, rather than by pathname - this is awkward due to
4763 potential access conflicts on the open, but it is unavoidable for these
4764 old servers since the only other choice is to go from 100 nanosecond DCE
4765 time and resort to the original setpathinfo level which takes the ancient
4766 DOS time format with 2 second granularity */
4768 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4769 const FILE_BASIC_INFO *data, __u16 fid)
4771 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4772 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4775 int bytes_returned = 0;
4776 __u16 params, param_offset, offset, byte_count, count;
4778 cFYI(1, ("Set Times (via SetFileInfo)"));
4779 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4784 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4786 /* At this point there is no need to override the current pid
4787 with the pid of the opener, but that could change if we someday
4788 use an existing handle (rather than opening one on the fly) */
4789 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4790 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4793 pSMB->MaxSetupCount = 0;
4797 pSMB->Reserved2 = 0;
4798 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4799 offset = param_offset + params;
4801 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4803 count = sizeof(FILE_BASIC_INFO);
4804 pSMB->MaxParameterCount = cpu_to_le16(2);
4805 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4806 pSMB->SetupCount = 1;
4807 pSMB->Reserved3 = 0;
4808 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4809 byte_count = 3 /* pad */ + params + count;
4810 pSMB->DataCount = cpu_to_le16(count);
4811 pSMB->ParameterCount = cpu_to_le16(params);
4812 pSMB->TotalDataCount = pSMB->DataCount;
4813 pSMB->TotalParameterCount = pSMB->ParameterCount;
4814 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4815 pSMB->DataOffset = cpu_to_le16(offset);
4817 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4818 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4820 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4821 pSMB->Reserved4 = 0;
4822 pSMB->hdr.smb_buf_length += byte_count;
4823 pSMB->ByteCount = cpu_to_le16(byte_count);
4824 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4825 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4826 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4828 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4831 cifs_small_buf_release(pSMB);
4833 /* Note: On -EAGAIN error only caller can retry on handle based calls
4834 since file handle passed in no longer valid */
4841 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4842 const FILE_BASIC_INFO *data,
4843 const struct nls_table *nls_codepage, int remap)
4845 TRANSACTION2_SPI_REQ *pSMB = NULL;
4846 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4849 int bytes_returned = 0;
4851 __u16 params, param_offset, offset, byte_count, count;
4853 cFYI(1, ("In SetTimes"));
4856 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4861 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4863 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4864 PATH_MAX, nls_codepage, remap);
4865 name_len++; /* trailing null */
4867 } else { /* BB improve the check for buffer overruns BB */
4868 name_len = strnlen(fileName, PATH_MAX);
4869 name_len++; /* trailing null */
4870 strncpy(pSMB->FileName, fileName, name_len);
4873 params = 6 + name_len;
4874 count = sizeof(FILE_BASIC_INFO);
4875 pSMB->MaxParameterCount = cpu_to_le16(2);
4876 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4877 pSMB->MaxSetupCount = 0;
4881 pSMB->Reserved2 = 0;
4882 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4883 InformationLevel) - 4;
4884 offset = param_offset + params;
4885 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4886 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4887 pSMB->DataOffset = cpu_to_le16(offset);
4888 pSMB->SetupCount = 1;
4889 pSMB->Reserved3 = 0;
4890 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4891 byte_count = 3 /* pad */ + params + count;
4893 pSMB->DataCount = cpu_to_le16(count);
4894 pSMB->ParameterCount = cpu_to_le16(params);
4895 pSMB->TotalDataCount = pSMB->DataCount;
4896 pSMB->TotalParameterCount = pSMB->ParameterCount;
4897 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4898 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4900 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4901 pSMB->Reserved4 = 0;
4902 pSMB->hdr.smb_buf_length += byte_count;
4903 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4904 pSMB->ByteCount = cpu_to_le16(byte_count);
4905 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4906 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4908 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4911 cifs_buf_release(pSMB);
4919 /* Can not be used to set time stamps yet (due to old DOS time format) */
4920 /* Can be used to set attributes */
4921 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4922 handling it anyway and NT4 was what we thought it would be needed for
4923 Do not delete it until we prove whether needed for Win9x though */
4925 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4926 __u16 dos_attrs, const struct nls_table *nls_codepage)
4928 SETATTR_REQ *pSMB = NULL;
4929 SETATTR_RSP *pSMBr = NULL;
4934 cFYI(1, ("In SetAttrLegacy"));
4937 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4942 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4944 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4945 PATH_MAX, nls_codepage);
4946 name_len++; /* trailing null */
4948 } else { /* BB improve the check for buffer overruns BB */
4949 name_len = strnlen(fileName, PATH_MAX);
4950 name_len++; /* trailing null */
4951 strncpy(pSMB->fileName, fileName, name_len);
4953 pSMB->attr = cpu_to_le16(dos_attrs);
4954 pSMB->BufferFormat = 0x04;
4955 pSMB->hdr.smb_buf_length += name_len + 1;
4956 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4957 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4958 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4960 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4963 cifs_buf_release(pSMB);
4966 goto SetAttrLgcyRetry;
4970 #endif /* temporarily unneeded SetAttr legacy function */
4973 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4974 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4975 dev_t device, const struct nls_table *nls_codepage,
4978 TRANSACTION2_SPI_REQ *pSMB = NULL;
4979 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4982 int bytes_returned = 0;
4983 FILE_UNIX_BASIC_INFO *data_offset;
4984 __u16 params, param_offset, offset, count, byte_count;
4986 cFYI(1, ("In SetUID/GID/Mode"));
4988 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4993 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4995 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4996 PATH_MAX, nls_codepage, remap);
4997 name_len++; /* trailing null */
4999 } else { /* BB improve the check for buffer overruns BB */
5000 name_len = strnlen(fileName, PATH_MAX);
5001 name_len++; /* trailing null */
5002 strncpy(pSMB->FileName, fileName, name_len);
5005 params = 6 + name_len;
5006 count = sizeof(FILE_UNIX_BASIC_INFO);
5007 pSMB->MaxParameterCount = cpu_to_le16(2);
5008 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5009 pSMB->MaxSetupCount = 0;
5013 pSMB->Reserved2 = 0;
5014 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5015 InformationLevel) - 4;
5016 offset = param_offset + params;
5018 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5020 memset(data_offset, 0, count);
5021 pSMB->DataOffset = cpu_to_le16(offset);
5022 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5023 pSMB->SetupCount = 1;
5024 pSMB->Reserved3 = 0;
5025 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5026 byte_count = 3 /* pad */ + params + count;
5027 pSMB->ParameterCount = cpu_to_le16(params);
5028 pSMB->DataCount = cpu_to_le16(count);
5029 pSMB->TotalParameterCount = pSMB->ParameterCount;
5030 pSMB->TotalDataCount = pSMB->DataCount;
5031 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5032 pSMB->Reserved4 = 0;
5033 pSMB->hdr.smb_buf_length += byte_count;
5034 /* Samba server ignores set of file size to zero due to bugs in some
5035 older clients, but we should be precise - we use SetFileSize to
5036 set file size and do not want to truncate file size to zero
5037 accidently as happened on one Samba server beta by putting
5038 zero instead of -1 here */
5039 data_offset->EndOfFile = NO_CHANGE_64;
5040 data_offset->NumOfBytes = NO_CHANGE_64;
5041 data_offset->LastStatusChange = NO_CHANGE_64;
5042 data_offset->LastAccessTime = NO_CHANGE_64;
5043 data_offset->LastModificationTime = NO_CHANGE_64;
5044 data_offset->Uid = cpu_to_le64(uid);
5045 data_offset->Gid = cpu_to_le64(gid);
5046 /* better to leave device as zero when it is */
5047 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5048 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5049 data_offset->Permissions = cpu_to_le64(mode);
5052 data_offset->Type = cpu_to_le32(UNIX_FILE);
5053 else if (S_ISDIR(mode))
5054 data_offset->Type = cpu_to_le32(UNIX_DIR);
5055 else if (S_ISLNK(mode))
5056 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5057 else if (S_ISCHR(mode))
5058 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5059 else if (S_ISBLK(mode))
5060 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5061 else if (S_ISFIFO(mode))
5062 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5063 else if (S_ISSOCK(mode))
5064 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5067 pSMB->ByteCount = cpu_to_le16(byte_count);
5068 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5071 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5075 cifs_buf_release(pSMB);
5081 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5082 const int notify_subdirs, const __u16 netfid,
5083 __u32 filter, struct file *pfile, int multishot,
5084 const struct nls_table *nls_codepage)
5087 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5088 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5089 struct dir_notify_req *dnotify_req;
5092 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5093 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5098 pSMB->TotalParameterCount = 0 ;
5099 pSMB->TotalDataCount = 0;
5100 pSMB->MaxParameterCount = cpu_to_le32(2);
5101 /* BB find exact data count max from sess structure BB */
5102 pSMB->MaxDataCount = 0; /* same in little endian or be */
5103 /* BB VERIFY verify which is correct for above BB */
5104 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5105 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5107 pSMB->MaxSetupCount = 4;
5109 pSMB->ParameterOffset = 0;
5110 pSMB->DataCount = 0;
5111 pSMB->DataOffset = 0;
5112 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5113 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5114 pSMB->ParameterCount = pSMB->TotalParameterCount;
5116 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5117 pSMB->Reserved2 = 0;
5118 pSMB->CompletionFilter = cpu_to_le32(filter);
5119 pSMB->Fid = netfid; /* file handle always le */
5120 pSMB->ByteCount = 0;
5122 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5123 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5125 cFYI(1, ("Error in Notify = %d", rc));
5127 /* Add file to outstanding requests */
5128 /* BB change to kmem cache alloc */
5129 dnotify_req = kmalloc(
5130 sizeof(struct dir_notify_req),
5133 dnotify_req->Pid = pSMB->hdr.Pid;
5134 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5135 dnotify_req->Mid = pSMB->hdr.Mid;
5136 dnotify_req->Tid = pSMB->hdr.Tid;
5137 dnotify_req->Uid = pSMB->hdr.Uid;
5138 dnotify_req->netfid = netfid;
5139 dnotify_req->pfile = pfile;
5140 dnotify_req->filter = filter;
5141 dnotify_req->multishot = multishot;
5142 spin_lock(&GlobalMid_Lock);
5143 list_add_tail(&dnotify_req->lhead,
5144 &GlobalDnotifyReqList);
5145 spin_unlock(&GlobalMid_Lock);
5149 cifs_buf_release(pSMB);
5152 #ifdef CONFIG_CIFS_XATTR
5154 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5155 const unsigned char *searchName,
5156 char *EAData, size_t buf_size,
5157 const struct nls_table *nls_codepage, int remap)
5159 /* BB assumes one setup word */
5160 TRANSACTION2_QPI_REQ *pSMB = NULL;
5161 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5165 struct fea *temp_fea;
5167 __u16 params, byte_count;
5169 cFYI(1, ("In Query All EAs path %s", searchName));
5171 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5176 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5178 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5179 PATH_MAX, nls_codepage, remap);
5180 name_len++; /* trailing null */
5182 } else { /* BB improve the check for buffer overruns BB */
5183 name_len = strnlen(searchName, PATH_MAX);
5184 name_len++; /* trailing null */
5185 strncpy(pSMB->FileName, searchName, name_len);
5188 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5189 pSMB->TotalDataCount = 0;
5190 pSMB->MaxParameterCount = cpu_to_le16(2);
5191 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5192 pSMB->MaxSetupCount = 0;
5196 pSMB->Reserved2 = 0;
5197 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5198 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5199 pSMB->DataCount = 0;
5200 pSMB->DataOffset = 0;
5201 pSMB->SetupCount = 1;
5202 pSMB->Reserved3 = 0;
5203 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5204 byte_count = params + 1 /* pad */ ;
5205 pSMB->TotalParameterCount = cpu_to_le16(params);
5206 pSMB->ParameterCount = pSMB->TotalParameterCount;
5207 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5208 pSMB->Reserved4 = 0;
5209 pSMB->hdr.smb_buf_length += byte_count;
5210 pSMB->ByteCount = cpu_to_le16(byte_count);
5212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5215 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5216 } else { /* decode response */
5217 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5219 /* BB also check enough total bytes returned */
5220 /* BB we need to improve the validity checking
5221 of these trans2 responses */
5222 if (rc || (pSMBr->ByteCount < 4))
5223 rc = -EIO; /* bad smb */
5224 /* else if (pFindData){
5225 memcpy((char *) pFindData,
5226 (char *) &pSMBr->hdr.Protocol +
5229 /* check that length of list is not more than bcc */
5230 /* check that each entry does not go beyond length
5232 /* check that each element of each entry does not
5233 go beyond end of list */
5234 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5235 struct fealist *ea_response_data;
5237 /* validate_trans2_offsets() */
5238 /* BB check if start of smb + data_offset > &bcc+ bcc */
5239 ea_response_data = (struct fealist *)
5240 (((char *) &pSMBr->hdr.Protocol) +
5242 name_len = le32_to_cpu(ea_response_data->list_len);
5243 cFYI(1, ("ea length %d", name_len));
5244 if (name_len <= 8) {
5245 /* returned EA size zeroed at top of function */
5246 cFYI(1, ("empty EA list returned from server"));
5248 /* account for ea list len */
5250 temp_fea = ea_response_data->list;
5251 temp_ptr = (char *)temp_fea;
5252 while (name_len > 0) {
5256 rc += temp_fea->name_len;
5257 /* account for prefix user. and trailing null */
5259 if (rc < (int)buf_size) {
5260 memcpy(EAData, "user.", 5);
5262 memcpy(EAData, temp_ptr,
5263 temp_fea->name_len);
5264 EAData += temp_fea->name_len;
5265 /* null terminate name */
5267 EAData = EAData + 1;
5268 } else if (buf_size == 0) {
5269 /* skip copy - calc size only */
5271 /* stop before overrun buffer */
5275 name_len -= temp_fea->name_len;
5276 temp_ptr += temp_fea->name_len;
5277 /* account for trailing null */
5281 le16_to_cpu(temp_fea->value_len);
5282 name_len -= value_len;
5283 temp_ptr += value_len;
5284 /* BB check that temp_ptr is still
5287 /* no trailing null to account for
5289 /* go on to next EA */
5290 temp_fea = (struct fea *)temp_ptr;
5296 cifs_buf_release(pSMB);
5303 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5304 const unsigned char *searchName, const unsigned char *ea_name,
5305 unsigned char *ea_value, size_t buf_size,
5306 const struct nls_table *nls_codepage, int remap)
5308 TRANSACTION2_QPI_REQ *pSMB = NULL;
5309 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5313 struct fea *temp_fea;
5315 __u16 params, byte_count;
5317 cFYI(1, ("In Query EA path %s", searchName));
5319 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5324 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5326 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5327 PATH_MAX, nls_codepage, remap);
5328 name_len++; /* trailing null */
5330 } else { /* BB improve the check for buffer overruns BB */
5331 name_len = strnlen(searchName, PATH_MAX);
5332 name_len++; /* trailing null */
5333 strncpy(pSMB->FileName, searchName, name_len);
5336 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5337 pSMB->TotalDataCount = 0;
5338 pSMB->MaxParameterCount = cpu_to_le16(2);
5339 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5340 pSMB->MaxSetupCount = 0;
5344 pSMB->Reserved2 = 0;
5345 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5346 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5347 pSMB->DataCount = 0;
5348 pSMB->DataOffset = 0;
5349 pSMB->SetupCount = 1;
5350 pSMB->Reserved3 = 0;
5351 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5352 byte_count = params + 1 /* pad */ ;
5353 pSMB->TotalParameterCount = cpu_to_le16(params);
5354 pSMB->ParameterCount = pSMB->TotalParameterCount;
5355 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5356 pSMB->Reserved4 = 0;
5357 pSMB->hdr.smb_buf_length += byte_count;
5358 pSMB->ByteCount = cpu_to_le16(byte_count);
5360 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5361 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5363 cFYI(1, ("Send error in Query EA = %d", rc));
5364 } else { /* decode response */
5365 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5367 /* BB also check enough total bytes returned */
5368 /* BB we need to improve the validity checking
5369 of these trans2 responses */
5370 if (rc || (pSMBr->ByteCount < 4))
5371 rc = -EIO; /* bad smb */
5372 /* else if (pFindData){
5373 memcpy((char *) pFindData,
5374 (char *) &pSMBr->hdr.Protocol +
5377 /* check that length of list is not more than bcc */
5378 /* check that each entry does not go beyond length
5380 /* check that each element of each entry does not
5381 go beyond end of list */
5382 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5383 struct fealist *ea_response_data;
5385 /* validate_trans2_offsets() */
5386 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5387 ea_response_data = (struct fealist *)
5388 (((char *) &pSMBr->hdr.Protocol) +
5390 name_len = le32_to_cpu(ea_response_data->list_len);
5391 cFYI(1, ("ea length %d", name_len));
5392 if (name_len <= 8) {
5393 /* returned EA size zeroed at top of function */
5394 cFYI(1, ("empty EA list returned from server"));
5396 /* account for ea list len */
5398 temp_fea = ea_response_data->list;
5399 temp_ptr = (char *)temp_fea;
5400 /* loop through checking if we have a matching
5401 name and then return the associated value */
5402 while (name_len > 0) {
5407 le16_to_cpu(temp_fea->value_len);
5408 /* BB validate that value_len falls within SMB,
5409 even though maximum for name_len is 255 */
5410 if (memcmp(temp_fea->name, ea_name,
5411 temp_fea->name_len) == 0) {
5414 /* account for prefix user. and trailing null */
5415 if (rc <= (int)buf_size) {
5417 temp_fea->name+temp_fea->name_len+1,
5419 /* ea values, unlike ea
5422 } else if (buf_size == 0) {
5423 /* skip copy - calc size only */
5425 /* stop before overrun buffer */
5430 name_len -= temp_fea->name_len;
5431 temp_ptr += temp_fea->name_len;
5432 /* account for trailing null */
5435 name_len -= value_len;
5436 temp_ptr += value_len;
5437 /* No trailing null to account for in
5438 value_len. Go on to next EA */
5439 temp_fea = (struct fea *)temp_ptr;
5445 cifs_buf_release(pSMB);
5453 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5454 const char *ea_name, const void *ea_value,
5455 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5458 struct smb_com_transaction2_spi_req *pSMB = NULL;
5459 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5460 struct fealist *parm_data;
5463 int bytes_returned = 0;
5464 __u16 params, param_offset, byte_count, offset, count;
5466 cFYI(1, ("In SetEA"));
5468 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5473 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5475 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5476 PATH_MAX, nls_codepage, remap);
5477 name_len++; /* trailing null */
5479 } else { /* BB improve the check for buffer overruns BB */
5480 name_len = strnlen(fileName, PATH_MAX);
5481 name_len++; /* trailing null */
5482 strncpy(pSMB->FileName, fileName, name_len);
5485 params = 6 + name_len;
5487 /* done calculating parms using name_len of file name,
5488 now use name_len to calculate length of ea name
5489 we are going to create in the inode xattrs */
5490 if (ea_name == NULL)
5493 name_len = strnlen(ea_name, 255);
5495 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5496 pSMB->MaxParameterCount = cpu_to_le16(2);
5497 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5498 pSMB->MaxSetupCount = 0;
5502 pSMB->Reserved2 = 0;
5503 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5504 InformationLevel) - 4;
5505 offset = param_offset + params;
5506 pSMB->InformationLevel =
5507 cpu_to_le16(SMB_SET_FILE_EA);
5510 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5512 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5513 pSMB->DataOffset = cpu_to_le16(offset);
5514 pSMB->SetupCount = 1;
5515 pSMB->Reserved3 = 0;
5516 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5517 byte_count = 3 /* pad */ + params + count;
5518 pSMB->DataCount = cpu_to_le16(count);
5519 parm_data->list_len = cpu_to_le32(count);
5520 parm_data->list[0].EA_flags = 0;
5521 /* we checked above that name len is less than 255 */
5522 parm_data->list[0].name_len = (__u8)name_len;
5523 /* EA names are always ASCII */
5525 strncpy(parm_data->list[0].name, ea_name, name_len);
5526 parm_data->list[0].name[name_len] = 0;
5527 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5528 /* caller ensures that ea_value_len is less than 64K but
5529 we need to ensure that it fits within the smb */
5531 /*BB add length check to see if it would fit in
5532 negotiated SMB buffer size BB */
5533 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5535 memcpy(parm_data->list[0].name+name_len+1,
5536 ea_value, ea_value_len);
5538 pSMB->TotalDataCount = pSMB->DataCount;
5539 pSMB->ParameterCount = cpu_to_le16(params);
5540 pSMB->TotalParameterCount = pSMB->ParameterCount;
5541 pSMB->Reserved4 = 0;
5542 pSMB->hdr.smb_buf_length += byte_count;
5543 pSMB->ByteCount = cpu_to_le16(byte_count);
5544 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5545 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5547 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5550 cifs_buf_release(pSMB);