4 * Copyright (C) International Business Machines Corp., 2002,2010
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/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <asm/uaccess.h>
39 #include "cifsproto.h"
40 #include "cifs_unicode.h"
41 #include "cifs_debug.h"
43 #ifdef CONFIG_CIFS_POSIX
48 #ifdef CONFIG_CIFS_WEAK_PW_HASH
49 {LANMAN_PROT
, "\2LM1.2X002"},
50 {LANMAN2_PROT
, "\2LANMAN2.1"},
51 #endif /* weak password hashing for legacy clients */
52 {CIFS_PROT
, "\2NT LM 0.12"},
53 {POSIX_PROT
, "\2POSIX 2"},
61 #ifdef CONFIG_CIFS_WEAK_PW_HASH
62 {LANMAN_PROT
, "\2LM1.2X002"},
63 {LANMAN2_PROT
, "\2LANMAN2.1"},
64 #endif /* weak password hashing for legacy clients */
65 {CIFS_PROT
, "\2NT LM 0.12"},
70 /* define the number of elements in the cifs dialect array */
71 #ifdef CONFIG_CIFS_POSIX
72 #ifdef CONFIG_CIFS_WEAK_PW_HASH
73 #define CIFS_NUM_PROT 4
75 #define CIFS_NUM_PROT 2
76 #endif /* CIFS_WEAK_PW_HASH */
78 #ifdef CONFIG_CIFS_WEAK_PW_HASH
79 #define CIFS_NUM_PROT 3
81 #define CIFS_NUM_PROT 1
82 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
83 #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 spin_lock(&cifs_file_list_lock
);
95 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
96 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
97 open_file
->invalidHandle
= true;
98 open_file
->oplock_break_cancelled
= true;
100 spin_unlock(&cifs_file_list_lock
);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* reconnect the socket, tcon, and smb session if needed */
107 cifs_reconnect_tcon(struct cifsTconInfo
*tcon
, int smb_command
)
110 struct cifsSesInfo
*ses
;
111 struct TCP_Server_Info
*server
;
112 struct nls_table
*nls_codepage
;
115 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
116 * tcp and smb session status done differently for those three - in the
123 server
= ses
->server
;
126 * only tree disconnect, open, and write, (and ulogoff which does not
127 * have tcon) are allowed as we start force umount
129 if (tcon
->tidStatus
== CifsExiting
) {
130 if (smb_command
!= SMB_COM_WRITE_ANDX
&&
131 smb_command
!= SMB_COM_OPEN_ANDX
&&
132 smb_command
!= SMB_COM_TREE_DISCONNECT
) {
133 cFYI(1, "can not send cmd %d while umounting",
140 * Give demultiplex thread up to 10 seconds to reconnect, should be
141 * greater than cifs socket timeout which is 7 seconds
143 while (server
->tcpStatus
== CifsNeedReconnect
) {
144 wait_event_interruptible_timeout(server
->response_q
,
145 (server
->tcpStatus
== CifsGood
), 10 * HZ
);
147 /* is TCP session is reestablished now ?*/
148 if (server
->tcpStatus
!= CifsNeedReconnect
)
152 * on "soft" mounts we wait once. Hard mounts keep
153 * retrying until process is killed or server comes
157 cFYI(1, "gave up waiting on reconnect in smb_init");
162 if (!ses
->need_reconnect
&& !tcon
->need_reconnect
)
165 nls_codepage
= load_nls_default();
168 * need to prevent multiple threads trying to simultaneously
169 * reconnect the same SMB session
171 mutex_lock(&ses
->session_mutex
);
172 rc
= cifs_negotiate_protocol(0, ses
);
173 if (rc
== 0 && ses
->need_reconnect
)
174 rc
= cifs_setup_session(0, ses
, nls_codepage
);
176 /* do we need to reconnect tcon? */
177 if (rc
|| !tcon
->need_reconnect
) {
178 mutex_unlock(&ses
->session_mutex
);
182 mark_open_files_invalid(tcon
);
183 rc
= CIFSTCon(0, ses
, tcon
->treeName
, tcon
, nls_codepage
);
184 mutex_unlock(&ses
->session_mutex
);
185 cFYI(1, "reconnect tcon rc = %d", rc
);
191 * FIXME: check if wsize needs updated due to negotiated smb buffer
194 atomic_inc(&tconInfoReconnectCount
);
196 /* tell server Unix caps we support */
197 if (ses
->capabilities
& CAP_UNIX
)
198 reset_cifs_unix_caps(0, tcon
, NULL
, NULL
);
201 * Removed call to reopen open files here. It is safer (and faster) to
202 * reopen files one at a time as needed in read and write.
204 * FIXME: what about file locks? don't we need to reclaim them ASAP?
209 * Check if handle based operation so we know whether we can continue
210 * or not without returning to caller to reset file handle
212 switch (smb_command
) {
213 case SMB_COM_READ_ANDX
:
214 case SMB_COM_WRITE_ANDX
:
216 case SMB_COM_FIND_CLOSE2
:
217 case SMB_COM_LOCKING_ANDX
:
221 unload_nls(nls_codepage
);
225 /* Allocate and return pointer to an SMB request buffer, and set basic
226 SMB information in the SMB header. If the return code is zero, this
227 function must have filled in request_buf pointer */
229 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
234 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
238 *request_buf
= cifs_small_buf_get();
239 if (*request_buf
== NULL
) {
240 /* BB should we add a retry in here if not a writepage? */
244 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
248 cifs_stats_inc(&tcon
->num_smbs_sent
);
254 small_smb_init_no_tc(const int smb_command
, const int wct
,
255 struct cifsSesInfo
*ses
, void **request_buf
)
258 struct smb_hdr
*buffer
;
260 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
264 buffer
= (struct smb_hdr
*)*request_buf
;
265 buffer
->Mid
= GetNextMid(ses
->server
);
266 if (ses
->capabilities
& CAP_UNICODE
)
267 buffer
->Flags2
|= SMBFLG2_UNICODE
;
268 if (ses
->capabilities
& CAP_STATUS32
)
269 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
271 /* uid, tid can stay at zero as set in header assemble */
273 /* BB add support for turning on the signing when
274 this function is used after 1st of session setup requests */
279 /* If the return code is zero, this function must fill in request_buf pointer */
281 __smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
282 void **request_buf
, void **response_buf
)
284 *request_buf
= cifs_buf_get();
285 if (*request_buf
== NULL
) {
286 /* BB should we add a retry in here if not a writepage? */
289 /* Although the original thought was we needed the response buf for */
290 /* potential retries of smb operations it turns out we can determine */
291 /* from the mid flags when the request buffer can be resent without */
292 /* having to use a second distinct buffer for the response */
294 *response_buf
= *request_buf
;
296 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
300 cifs_stats_inc(&tcon
->num_smbs_sent
);
305 /* If the return code is zero, this function must fill in request_buf pointer */
307 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
308 void **request_buf
, void **response_buf
)
312 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
316 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
320 smb_init_no_reconnect(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
321 void **request_buf
, void **response_buf
)
323 if (tcon
->ses
->need_reconnect
|| tcon
->need_reconnect
)
326 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
329 static int validate_t2(struct smb_t2_rsp
*pSMB
)
331 unsigned int total_size
;
333 /* check for plausible wct */
334 if (pSMB
->hdr
.WordCount
< 10)
337 /* check for parm and data offset going beyond end of smb */
338 if (get_unaligned_le16(&pSMB
->t2_rsp
.ParameterOffset
) > 1024 ||
339 get_unaligned_le16(&pSMB
->t2_rsp
.DataOffset
) > 1024)
342 /* check that bcc is at least as big as parms + data */
343 /* check that bcc is less than negotiated smb buffer */
344 total_size
= get_unaligned_le16(&pSMB
->t2_rsp
.ParameterCount
);
345 if (total_size
>= 512)
348 total_size
+= get_unaligned_le16(&pSMB
->t2_rsp
.DataCount
);
349 if (total_size
> get_bcc(&pSMB
->hdr
) ||
350 total_size
>= CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
)
355 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
356 sizeof(struct smb_t2_rsp
) + 16);
361 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
364 NEGOTIATE_RSP
*pSMBr
;
368 struct TCP_Server_Info
*server
;
370 unsigned int secFlags
;
373 server
= ses
->server
;
378 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
379 (void **) &pSMB
, (void **) &pSMBr
);
383 /* if any of auth flags (ie not sign or seal) are overriden use them */
384 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
385 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
386 else /* if override flags set only sign/seal OR them with global auth */
387 secFlags
= global_secflags
| ses
->overrideSecFlg
;
389 cFYI(1, "secFlags 0x%x", secFlags
);
391 pSMB
->hdr
.Mid
= GetNextMid(server
);
392 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
394 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
395 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
396 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
397 cFYI(1, "Kerberos only mechanism, enable extended security");
398 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
399 } else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
400 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
401 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
402 cFYI(1, "NTLMSSP only mechanism, enable extended security");
403 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
407 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
408 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
409 count
+= strlen(protocols
[i
].name
) + 1;
410 /* null at end of source and target buffers anyway */
412 pSMB
->hdr
.smb_buf_length
+= count
;
413 pSMB
->ByteCount
= cpu_to_le16(count
);
415 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
416 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
420 server
->dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
421 cFYI(1, "Dialect: %d", server
->dialect
);
422 /* Check wct = 1 error case */
423 if ((pSMBr
->hdr
.WordCount
< 13) || (server
->dialect
== BAD_PROT
)) {
424 /* core returns wct = 1, but we do not ask for core - otherwise
425 small wct just comes when dialect index is -1 indicating we
426 could not negotiate a common dialect */
429 #ifdef CONFIG_CIFS_WEAK_PW_HASH
430 } else if ((pSMBr
->hdr
.WordCount
== 13)
431 && ((server
->dialect
== LANMAN_PROT
)
432 || (server
->dialect
== LANMAN2_PROT
))) {
434 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
436 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
437 (secFlags
& CIFSSEC_MAY_PLNTXT
))
438 server
->secType
= LANMAN
;
440 cERROR(1, "mount failed weak security disabled"
441 " in /proc/fs/cifs/SecurityFlags");
445 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
446 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
447 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
448 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
449 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
450 /* even though we do not use raw we might as well set this
451 accurately, in case we ever find a need for it */
452 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
453 server
->max_rw
= 0xFF00;
454 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
456 server
->max_rw
= 0;/* do not need to use raw anyway */
457 server
->capabilities
= CAP_MPX_MODE
;
459 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
461 /* OS/2 often does not set timezone therefore
462 * we must use server time to calc time zone.
463 * Could deviate slightly from the right zone.
464 * Smallest defined timezone difference is 15 minutes
465 * (i.e. Nepal). Rounding up/down is done to match
468 int val
, seconds
, remain
, result
;
469 struct timespec ts
, utc
;
471 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
472 rsp
->SrvTime
.Time
, 0);
473 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
474 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
475 (int)(utc
.tv_sec
- ts
.tv_sec
));
476 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
478 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
479 remain
= seconds
% MIN_TZ_ADJ
;
480 if (remain
>= (MIN_TZ_ADJ
/ 2))
481 result
+= MIN_TZ_ADJ
;
484 server
->timeAdj
= result
;
486 server
->timeAdj
= (int)tmp
;
487 server
->timeAdj
*= 60; /* also in seconds */
489 cFYI(1, "server->timeAdj: %d seconds", server
->timeAdj
);
492 /* BB get server time for time conversions and add
493 code to use it and timezone since this is not UTC */
495 if (rsp
->EncryptionKeyLength
==
496 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
497 memcpy(ses
->server
->cryptkey
, rsp
->EncryptionKey
,
498 CIFS_CRYPTO_KEY_SIZE
);
499 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
500 rc
= -EIO
; /* need cryptkey unless plain text */
504 cFYI(1, "LANMAN negotiated");
505 /* we will not end up setting signing flags - as no signing
506 was in LANMAN and server did not return the flags on */
508 #else /* weak security disabled */
509 } else if (pSMBr
->hdr
.WordCount
== 13) {
510 cERROR(1, "mount failed, cifs module not built "
511 "with CIFS_WEAK_PW_HASH support");
513 #endif /* WEAK_PW_HASH */
515 } else if (pSMBr
->hdr
.WordCount
!= 17) {
520 /* else wct == 17 NTLM */
521 server
->secMode
= pSMBr
->SecurityMode
;
522 if ((server
->secMode
& SECMODE_USER
) == 0)
523 cFYI(1, "share mode security");
525 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
526 #ifdef CONFIG_CIFS_WEAK_PW_HASH
527 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
528 #endif /* CIFS_WEAK_PW_HASH */
529 cERROR(1, "Server requests plain text password"
530 " but client support disabled");
532 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
533 server
->secType
= NTLMv2
;
534 else if (secFlags
& CIFSSEC_MAY_NTLM
)
535 server
->secType
= NTLM
;
536 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
537 server
->secType
= NTLMv2
;
538 else if (secFlags
& CIFSSEC_MAY_KRB5
)
539 server
->secType
= Kerberos
;
540 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
541 server
->secType
= RawNTLMSSP
;
542 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
543 server
->secType
= LANMAN
;
544 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
545 else if (secFlags & CIFSSEC_MAY_PLNTXT)
550 cERROR(1, "Invalid security type");
553 /* else ... any others ...? */
555 /* one byte, so no need to convert this or EncryptionKeyLen from
557 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
558 /* probably no need to store and check maxvcs */
559 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
560 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
561 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
562 cFYI(DBG2
, "Max buf = %d", ses
->server
->maxBuf
);
563 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
564 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
565 server
->timeAdj
*= 60;
566 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
567 memcpy(ses
->server
->cryptkey
, pSMBr
->u
.EncryptionKey
,
568 CIFS_CRYPTO_KEY_SIZE
);
569 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
570 && (pSMBr
->EncryptionKeyLength
== 0)) {
571 /* decode security blob */
572 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
573 rc
= -EIO
; /* no crypt key only if plain text pwd */
577 /* BB might be helpful to save off the domain of server here */
579 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
580 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
581 count
= pSMBr
->ByteCount
;
586 spin_lock(&cifs_tcp_ses_lock
);
587 if (server
->srv_count
> 1) {
588 spin_unlock(&cifs_tcp_ses_lock
);
589 if (memcmp(server
->server_GUID
,
590 pSMBr
->u
.extended_response
.
592 cFYI(1, "server UID changed");
593 memcpy(server
->server_GUID
,
594 pSMBr
->u
.extended_response
.GUID
,
598 spin_unlock(&cifs_tcp_ses_lock
);
599 memcpy(server
->server_GUID
,
600 pSMBr
->u
.extended_response
.GUID
, 16);
604 server
->secType
= RawNTLMSSP
;
606 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
607 SecurityBlob
, count
- 16,
613 if (server
->secType
== Kerberos
) {
614 if (!server
->sec_kerberos
&&
615 !server
->sec_mskerberos
)
617 } else if (server
->secType
== RawNTLMSSP
) {
618 if (!server
->sec_ntlmssp
)
624 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
626 #ifdef CONFIG_CIFS_WEAK_PW_HASH
629 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
630 /* MUST_SIGN already includes the MAY_SIGN FLAG
631 so if this is zero it means that signing is disabled */
632 cFYI(1, "Signing disabled");
633 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
634 cERROR(1, "Server requires "
635 "packet signing to be enabled in "
636 "/proc/fs/cifs/SecurityFlags.");
640 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
641 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
642 /* signing required */
643 cFYI(1, "Must sign - secFlags 0x%x", secFlags
);
644 if ((server
->secMode
&
645 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
646 cERROR(1, "signing required but server lacks support");
649 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
651 /* signing optional ie CIFSSEC_MAY_SIGN */
652 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
654 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
658 cifs_buf_release(pSMB
);
660 cFYI(1, "negprot rc %d", rc
);
665 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
667 struct smb_hdr
*smb_buffer
;
670 cFYI(1, "In tree disconnect");
672 /* BB: do we need to check this? These should never be NULL. */
673 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
677 * No need to return error on this operation if tid invalidated and
678 * closed on server already e.g. due to tcp session crashing. Also,
679 * the tcon is no longer on the list, so no need to take lock before
682 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
685 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
686 (void **)&smb_buffer
);
690 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
692 cFYI(1, "Tree disconnect failed %d", rc
);
694 /* No need to return error on this operation if tid invalidated and
695 closed on server already e.g. due to tcp session crashing */
703 * This is a no-op for now. We're not really interested in the reply, but
704 * rather in the fact that the server sent one and that server->lstrp
707 * FIXME: maybe we should consider checking that the reply matches request?
710 cifs_echo_callback(struct mid_q_entry
*mid
)
712 struct TCP_Server_Info
*server
= mid
->callback_data
;
714 DeleteMidQEntry(mid
);
715 atomic_dec(&server
->inFlight
);
716 wake_up(&server
->request_q
);
720 CIFSSMBEcho(struct TCP_Server_Info
*server
)
725 cFYI(1, "In echo request");
727 rc
= small_smb_init(SMB_COM_ECHO
, 0, NULL
, (void **)&smb
);
731 /* set up echo request */
732 smb
->hdr
.Tid
= cpu_to_le16(0xffff);
733 smb
->hdr
.WordCount
= 1;
734 put_unaligned_le16(1, &smb
->EchoCount
);
735 put_bcc_le(1, &smb
->hdr
);
737 smb
->hdr
.smb_buf_length
+= 3;
739 rc
= cifs_call_async(server
, (struct smb_hdr
*)smb
,
740 cifs_echo_callback
, server
);
742 cFYI(1, "Echo request failed: %d", rc
);
744 cifs_small_buf_release(smb
);
750 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
752 LOGOFF_ANDX_REQ
*pSMB
;
755 cFYI(1, "In SMBLogoff for session disconnect");
758 * BB: do we need to check validity of ses and server? They should
759 * always be valid since we have an active reference. If not, that
760 * should probably be a BUG()
762 if (!ses
|| !ses
->server
)
765 mutex_lock(&ses
->session_mutex
);
766 if (ses
->need_reconnect
)
767 goto session_already_dead
; /* no need to send SMBlogoff if uid
768 already closed due to reconnect */
769 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
771 mutex_unlock(&ses
->session_mutex
);
775 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
777 if (ses
->server
->secMode
&
778 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
779 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
781 pSMB
->hdr
.Uid
= ses
->Suid
;
783 pSMB
->AndXCommand
= 0xFF;
784 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
785 session_already_dead
:
786 mutex_unlock(&ses
->session_mutex
);
788 /* if session dead then we do not need to do ulogoff,
789 since server closed smb session, no sense reporting
797 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
798 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
800 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
801 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
802 struct unlink_psx_rq
*pRqD
;
805 int bytes_returned
= 0;
806 __u16 params
, param_offset
, offset
, byte_count
;
808 cFYI(1, "In POSIX delete");
810 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
815 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
817 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
818 PATH_MAX
, nls_codepage
, remap
);
819 name_len
++; /* trailing null */
821 } else { /* BB add path length overrun check */
822 name_len
= strnlen(fileName
, PATH_MAX
);
823 name_len
++; /* trailing null */
824 strncpy(pSMB
->FileName
, fileName
, name_len
);
827 params
= 6 + name_len
;
828 pSMB
->MaxParameterCount
= cpu_to_le16(2);
829 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
830 pSMB
->MaxSetupCount
= 0;
835 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
836 InformationLevel
) - 4;
837 offset
= param_offset
+ params
;
839 /* Setup pointer to Request Data (inode type) */
840 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
841 pRqD
->type
= cpu_to_le16(type
);
842 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
843 pSMB
->DataOffset
= cpu_to_le16(offset
);
844 pSMB
->SetupCount
= 1;
846 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
847 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
849 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
850 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
851 pSMB
->ParameterCount
= cpu_to_le16(params
);
852 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
853 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
855 pSMB
->hdr
.smb_buf_length
+= byte_count
;
856 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
857 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
858 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
860 cFYI(1, "Posix delete returned %d", rc
);
861 cifs_buf_release(pSMB
);
863 cifs_stats_inc(&tcon
->num_deletes
);
872 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
873 const struct nls_table
*nls_codepage
, int remap
)
875 DELETE_FILE_REQ
*pSMB
= NULL
;
876 DELETE_FILE_RSP
*pSMBr
= NULL
;
882 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
887 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
889 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
890 PATH_MAX
, nls_codepage
, remap
);
891 name_len
++; /* trailing null */
893 } else { /* BB improve check for buffer overruns BB */
894 name_len
= strnlen(fileName
, PATH_MAX
);
895 name_len
++; /* trailing null */
896 strncpy(pSMB
->fileName
, fileName
, name_len
);
898 pSMB
->SearchAttributes
=
899 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
900 pSMB
->BufferFormat
= 0x04;
901 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
902 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
903 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
904 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
905 cifs_stats_inc(&tcon
->num_deletes
);
907 cFYI(1, "Error in RMFile = %d", rc
);
909 cifs_buf_release(pSMB
);
917 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
918 const struct nls_table
*nls_codepage
, int remap
)
920 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
921 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
926 cFYI(1, "In CIFSSMBRmDir");
928 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
933 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
934 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
935 PATH_MAX
, nls_codepage
, remap
);
936 name_len
++; /* trailing null */
938 } else { /* BB improve check for buffer overruns BB */
939 name_len
= strnlen(dirName
, PATH_MAX
);
940 name_len
++; /* trailing null */
941 strncpy(pSMB
->DirName
, dirName
, name_len
);
944 pSMB
->BufferFormat
= 0x04;
945 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
946 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
947 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
948 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
949 cifs_stats_inc(&tcon
->num_rmdirs
);
951 cFYI(1, "Error in RMDir = %d", rc
);
953 cifs_buf_release(pSMB
);
960 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
961 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
964 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
965 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
969 cFYI(1, "In CIFSSMBMkDir");
971 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
976 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
977 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
978 PATH_MAX
, nls_codepage
, remap
);
979 name_len
++; /* trailing null */
981 } else { /* BB improve check for buffer overruns BB */
982 name_len
= strnlen(name
, PATH_MAX
);
983 name_len
++; /* trailing null */
984 strncpy(pSMB
->DirName
, name
, name_len
);
987 pSMB
->BufferFormat
= 0x04;
988 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
989 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
990 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
991 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
992 cifs_stats_inc(&tcon
->num_mkdirs
);
994 cFYI(1, "Error in Mkdir = %d", rc
);
996 cifs_buf_release(pSMB
);
1003 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1004 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1005 __u32
*pOplock
, const char *name
,
1006 const struct nls_table
*nls_codepage
, int remap
)
1008 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1009 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1012 int bytes_returned
= 0;
1013 __u16 params
, param_offset
, offset
, byte_count
, count
;
1014 OPEN_PSX_REQ
*pdata
;
1015 OPEN_PSX_RSP
*psx_rsp
;
1017 cFYI(1, "In POSIX Create");
1019 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1024 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1026 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1027 PATH_MAX
, nls_codepage
, remap
);
1028 name_len
++; /* trailing null */
1030 } else { /* BB improve the check for buffer overruns BB */
1031 name_len
= strnlen(name
, PATH_MAX
);
1032 name_len
++; /* trailing null */
1033 strncpy(pSMB
->FileName
, name
, name_len
);
1036 params
= 6 + name_len
;
1037 count
= sizeof(OPEN_PSX_REQ
);
1038 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1039 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1040 pSMB
->MaxSetupCount
= 0;
1044 pSMB
->Reserved2
= 0;
1045 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1046 InformationLevel
) - 4;
1047 offset
= param_offset
+ params
;
1048 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1049 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1050 pdata
->Permissions
= cpu_to_le64(mode
);
1051 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1052 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1053 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1054 pSMB
->DataOffset
= cpu_to_le16(offset
);
1055 pSMB
->SetupCount
= 1;
1056 pSMB
->Reserved3
= 0;
1057 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1058 byte_count
= 3 /* pad */ + params
+ count
;
1060 pSMB
->DataCount
= cpu_to_le16(count
);
1061 pSMB
->ParameterCount
= cpu_to_le16(params
);
1062 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1063 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1064 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1065 pSMB
->Reserved4
= 0;
1066 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1067 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1068 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1069 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1071 cFYI(1, "Posix create returned %d", rc
);
1072 goto psx_create_err
;
1075 cFYI(1, "copying inode info");
1076 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1078 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1079 rc
= -EIO
; /* bad smb */
1080 goto psx_create_err
;
1083 /* copy return information to pRetData */
1084 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1085 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1087 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1089 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1090 /* Let caller know file was created so we can set the mode. */
1091 /* Do we care about the CreateAction in any other cases? */
1092 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1093 *pOplock
|= CIFS_CREATE_ACTION
;
1094 /* check to make sure response data is there */
1095 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1096 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1097 cFYI(DBG2
, "unknown type");
1099 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1100 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1101 cERROR(1, "Open response data too small");
1102 pRetData
->Type
= cpu_to_le32(-1);
1103 goto psx_create_err
;
1105 memcpy((char *) pRetData
,
1106 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1107 sizeof(FILE_UNIX_BASIC_INFO
));
1111 cifs_buf_release(pSMB
);
1113 if (posix_flags
& SMB_O_DIRECTORY
)
1114 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1116 cifs_stats_inc(&tcon
->num_posixopens
);
1124 static __u16
convert_disposition(int disposition
)
1128 switch (disposition
) {
1129 case FILE_SUPERSEDE
:
1130 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1133 ofun
= SMBOPEN_OAPPEND
;
1136 ofun
= SMBOPEN_OCREATE
;
1139 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1141 case FILE_OVERWRITE
:
1142 ofun
= SMBOPEN_OTRUNC
;
1144 case FILE_OVERWRITE_IF
:
1145 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1148 cFYI(1, "unknown disposition %d", disposition
);
1149 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1155 access_flags_to_smbopen_mode(const int access_flags
)
1157 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1159 if (masked_flags
== GENERIC_READ
)
1160 return SMBOPEN_READ
;
1161 else if (masked_flags
== GENERIC_WRITE
)
1162 return SMBOPEN_WRITE
;
1164 /* just go for read/write */
1165 return SMBOPEN_READWRITE
;
1169 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1170 const char *fileName
, const int openDisposition
,
1171 const int access_flags
, const int create_options
, __u16
*netfid
,
1172 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1173 const struct nls_table
*nls_codepage
, int remap
)
1176 OPENX_REQ
*pSMB
= NULL
;
1177 OPENX_RSP
*pSMBr
= NULL
;
1183 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1188 pSMB
->AndXCommand
= 0xFF; /* none */
1190 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1191 count
= 1; /* account for one byte pad to word boundary */
1193 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1194 fileName
, PATH_MAX
, nls_codepage
, remap
);
1195 name_len
++; /* trailing null */
1197 } else { /* BB improve check for buffer overruns BB */
1198 count
= 0; /* no pad */
1199 name_len
= strnlen(fileName
, PATH_MAX
);
1200 name_len
++; /* trailing null */
1201 strncpy(pSMB
->fileName
, fileName
, name_len
);
1203 if (*pOplock
& REQ_OPLOCK
)
1204 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1205 else if (*pOplock
& REQ_BATCHOPLOCK
)
1206 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1208 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1209 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1210 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1211 /* set file as system file if special file such
1212 as fifo and server expecting SFU style and
1213 no Unix extensions */
1215 if (create_options
& CREATE_OPTION_SPECIAL
)
1216 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1217 else /* BB FIXME BB */
1218 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1220 if (create_options
& CREATE_OPTION_READONLY
)
1221 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1224 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1225 CREATE_OPTIONS_MASK); */
1226 /* BB FIXME END BB */
1228 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1229 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1231 pSMB
->hdr
.smb_buf_length
+= count
;
1233 pSMB
->ByteCount
= cpu_to_le16(count
);
1234 /* long_op set to 1 to allow for oplock break timeouts */
1235 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1236 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1237 cifs_stats_inc(&tcon
->num_opens
);
1239 cFYI(1, "Error in Open = %d", rc
);
1241 /* BB verify if wct == 15 */
1243 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1245 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1246 /* Let caller know file was created so we can set the mode. */
1247 /* Do we care about the CreateAction in any other cases? */
1249 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1250 *pOplock |= CIFS_CREATE_ACTION; */
1254 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1255 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1256 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1257 pfile_info
->ChangeTime
= 0; /* BB fixme */
1258 pfile_info
->Attributes
=
1259 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1260 /* the file_info buf is endian converted by caller */
1261 pfile_info
->AllocationSize
=
1262 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1263 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1264 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1265 pfile_info
->DeletePending
= 0;
1269 cifs_buf_release(pSMB
);
1276 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1277 const char *fileName
, const int openDisposition
,
1278 const int access_flags
, const int create_options
, __u16
*netfid
,
1279 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1280 const struct nls_table
*nls_codepage
, int remap
)
1283 OPEN_REQ
*pSMB
= NULL
;
1284 OPEN_RSP
*pSMBr
= NULL
;
1290 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1295 pSMB
->AndXCommand
= 0xFF; /* none */
1297 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1298 count
= 1; /* account for one byte pad to word boundary */
1300 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1301 fileName
, PATH_MAX
, nls_codepage
, remap
);
1302 name_len
++; /* trailing null */
1304 pSMB
->NameLength
= cpu_to_le16(name_len
);
1305 } else { /* BB improve check for buffer overruns BB */
1306 count
= 0; /* no pad */
1307 name_len
= strnlen(fileName
, PATH_MAX
);
1308 name_len
++; /* trailing null */
1309 pSMB
->NameLength
= cpu_to_le16(name_len
);
1310 strncpy(pSMB
->fileName
, fileName
, name_len
);
1312 if (*pOplock
& REQ_OPLOCK
)
1313 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1314 else if (*pOplock
& REQ_BATCHOPLOCK
)
1315 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1316 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1317 pSMB
->AllocationSize
= 0;
1318 /* set file as system file if special file such
1319 as fifo and server expecting SFU style and
1320 no Unix extensions */
1321 if (create_options
& CREATE_OPTION_SPECIAL
)
1322 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1324 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1326 /* XP does not handle ATTR_POSIX_SEMANTICS */
1327 /* but it helps speed up case sensitive checks for other
1328 servers such as Samba */
1329 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1330 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1332 if (create_options
& CREATE_OPTION_READONLY
)
1333 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1335 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1336 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1337 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1338 /* BB Expirement with various impersonation levels and verify */
1339 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1340 pSMB
->SecurityFlags
=
1341 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1344 pSMB
->hdr
.smb_buf_length
+= count
;
1346 pSMB
->ByteCount
= cpu_to_le16(count
);
1347 /* long_op set to 1 to allow for oplock break timeouts */
1348 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1349 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1350 cifs_stats_inc(&tcon
->num_opens
);
1352 cFYI(1, "Error in Open = %d", rc
);
1354 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1355 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1356 /* Let caller know file was created so we can set the mode. */
1357 /* Do we care about the CreateAction in any other cases? */
1358 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1359 *pOplock
|= CIFS_CREATE_ACTION
;
1361 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1362 36 /* CreationTime to Attributes */);
1363 /* the file_info buf is endian converted by caller */
1364 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1365 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1366 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1367 pfile_info
->DeletePending
= 0;
1371 cifs_buf_release(pSMB
);
1378 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1379 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1380 char **buf
, int *pbuf_type
)
1383 READ_REQ
*pSMB
= NULL
;
1384 READ_RSP
*pSMBr
= NULL
;
1385 char *pReadData
= NULL
;
1387 int resp_buf_type
= 0;
1390 cFYI(1, "Reading %d bytes on fid %d", count
, netfid
);
1391 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1394 wct
= 10; /* old style read */
1395 if ((lseek
>> 32) > 0) {
1396 /* can not handle this big offset for old */
1402 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1406 /* tcon and ses pointer are checked in smb_init */
1407 if (tcon
->ses
->server
== NULL
)
1408 return -ECONNABORTED
;
1410 pSMB
->AndXCommand
= 0xFF; /* none */
1412 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1414 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1416 pSMB
->Remaining
= 0;
1417 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1418 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1420 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1422 /* old style read */
1423 struct smb_com_readx_req
*pSMBW
=
1424 (struct smb_com_readx_req
*)pSMB
;
1425 pSMBW
->ByteCount
= 0;
1428 iov
[0].iov_base
= (char *)pSMB
;
1429 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1430 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1431 &resp_buf_type
, CIFS_LOG_ERROR
);
1432 cifs_stats_inc(&tcon
->num_reads
);
1433 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1435 cERROR(1, "Send error in read = %d", rc
);
1437 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1438 data_length
= data_length
<< 16;
1439 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1440 *nbytes
= data_length
;
1442 /*check that DataLength would not go beyond end of SMB */
1443 if ((data_length
> CIFSMaxBufSize
)
1444 || (data_length
> count
)) {
1445 cFYI(1, "bad length %d for count %d",
1446 data_length
, count
);
1450 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1451 le16_to_cpu(pSMBr
->DataOffset
);
1452 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1453 cERROR(1, "Faulting on read rc = %d",rc);
1455 }*/ /* can not use copy_to_user when using page cache*/
1457 memcpy(*buf
, pReadData
, data_length
);
1461 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1463 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1464 cifs_small_buf_release(iov
[0].iov_base
);
1465 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1466 cifs_buf_release(iov
[0].iov_base
);
1467 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1468 /* return buffer to caller to free */
1469 *buf
= iov
[0].iov_base
;
1470 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1471 *pbuf_type
= CIFS_SMALL_BUFFER
;
1472 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1473 *pbuf_type
= CIFS_LARGE_BUFFER
;
1474 } /* else no valid buffer on return - leave as null */
1476 /* Note: On -EAGAIN error only caller can retry on handle based calls
1477 since file handle passed in no longer valid */
1483 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1484 const int netfid
, const unsigned int count
,
1485 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1486 const char __user
*ubuf
, const int long_op
)
1489 WRITE_REQ
*pSMB
= NULL
;
1490 WRITE_RSP
*pSMBr
= NULL
;
1491 int bytes_returned
, wct
;
1497 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1498 if (tcon
->ses
== NULL
)
1499 return -ECONNABORTED
;
1501 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1505 if ((offset
>> 32) > 0) {
1506 /* can not handle big offset for old srv */
1511 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1515 /* tcon and ses pointer are checked in smb_init */
1516 if (tcon
->ses
->server
== NULL
)
1517 return -ECONNABORTED
;
1519 pSMB
->AndXCommand
= 0xFF; /* none */
1521 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1523 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1525 pSMB
->Reserved
= 0xFFFFFFFF;
1526 pSMB
->WriteMode
= 0;
1527 pSMB
->Remaining
= 0;
1529 /* Can increase buffer size if buffer is big enough in some cases ie we
1530 can send more if LARGE_WRITE_X capability returned by the server and if
1531 our buffer is big enough or if we convert to iovecs on socket writes
1532 and eliminate the copy to the CIFS buffer */
1533 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1534 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1536 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1540 if (bytes_sent
> count
)
1543 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1545 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1547 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1548 cifs_buf_release(pSMB
);
1551 } else if (count
!= 0) {
1553 cifs_buf_release(pSMB
);
1555 } /* else setting file size with write of zero bytes */
1557 byte_count
= bytes_sent
+ 1; /* pad */
1558 else /* wct == 12 */
1559 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1561 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1562 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1563 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1566 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1567 else { /* old style write has byte count 4 bytes earlier
1569 struct smb_com_writex_req
*pSMBW
=
1570 (struct smb_com_writex_req
*)pSMB
;
1571 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1574 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1575 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1576 cifs_stats_inc(&tcon
->num_writes
);
1578 cFYI(1, "Send error in write = %d", rc
);
1580 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1581 *nbytes
= (*nbytes
) << 16;
1582 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1585 * Mask off high 16 bits when bytes written as returned by the
1586 * server is greater than bytes requested by the client. Some
1587 * OS/2 servers are known to set incorrect CountHigh values.
1589 if (*nbytes
> count
)
1593 cifs_buf_release(pSMB
);
1595 /* Note: On -EAGAIN error only caller can retry on handle based calls
1596 since file handle passed in no longer valid */
1602 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1603 const int netfid
, const unsigned int count
,
1604 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1605 int n_vec
, const int long_op
)
1608 WRITE_REQ
*pSMB
= NULL
;
1611 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 if ((offset
>> 32) > 0) {
1622 /* can not handle big offset for old srv */
1626 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1629 /* tcon and ses pointer are checked in smb_init */
1630 if (tcon
->ses
->server
== NULL
)
1631 return -ECONNABORTED
;
1633 pSMB
->AndXCommand
= 0xFF; /* none */
1635 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1637 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1638 pSMB
->Reserved
= 0xFFFFFFFF;
1639 pSMB
->WriteMode
= 0;
1640 pSMB
->Remaining
= 0;
1643 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1645 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1646 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1647 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1649 pSMB
->hdr
.smb_buf_length
+= count
+1;
1650 else /* wct == 12 */
1651 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1653 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1654 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1655 struct smb_com_writex_req
*pSMBW
=
1656 (struct smb_com_writex_req
*)pSMB
;
1657 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1659 iov
[0].iov_base
= pSMB
;
1661 iov
[0].iov_len
= smb_hdr_len
+ 4;
1662 else /* wct == 12 pad bigger by four bytes */
1663 iov
[0].iov_len
= smb_hdr_len
+ 8;
1666 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1668 cifs_stats_inc(&tcon
->num_writes
);
1670 cFYI(1, "Send error Write2 = %d", rc
);
1671 } else if (resp_buf_type
== 0) {
1672 /* presumably this can not happen, but best to be safe */
1675 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1676 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1677 *nbytes
= (*nbytes
) << 16;
1678 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1681 * Mask off high 16 bits when bytes written as returned by the
1682 * server is greater than bytes requested by the client. OS/2
1683 * servers are known to set incorrect CountHigh values.
1685 if (*nbytes
> count
)
1689 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1690 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1691 cifs_small_buf_release(iov
[0].iov_base
);
1692 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1693 cifs_buf_release(iov
[0].iov_base
);
1695 /* Note: On -EAGAIN error only caller can retry on handle based calls
1696 since file handle passed in no longer valid */
1703 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1704 const __u16 smb_file_id
, const __u64 len
,
1705 const __u64 offset
, const __u32 numUnlock
,
1706 const __u32 numLock
, const __u8 lockType
,
1707 const bool waitFlag
, const __u8 oplock_level
)
1710 LOCK_REQ
*pSMB
= NULL
;
1711 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1716 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
);
1717 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1722 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1723 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1725 } else if (waitFlag
) {
1726 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1727 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1732 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1733 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1734 pSMB
->LockType
= lockType
;
1735 pSMB
->OplockLevel
= oplock_level
;
1736 pSMB
->AndXCommand
= 0xFF; /* none */
1737 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1739 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1740 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1741 /* BB where to store pid high? */
1742 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1743 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1744 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1745 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1746 count
= sizeof(LOCKING_ANDX_RANGE
);
1751 pSMB
->hdr
.smb_buf_length
+= count
;
1752 pSMB
->ByteCount
= cpu_to_le16(count
);
1755 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1756 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1757 cifs_small_buf_release(pSMB
);
1759 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1761 /* SMB buffer freed by function above */
1763 cifs_stats_inc(&tcon
->num_locks
);
1765 cFYI(1, "Send error in Lock = %d", rc
);
1767 /* Note: On -EAGAIN error only caller can retry on handle based calls
1768 since file handle passed in no longer valid */
1773 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1774 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1775 struct file_lock
*pLockData
, const __u16 lock_type
,
1776 const bool waitFlag
)
1778 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1779 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1780 struct cifs_posix_lock
*parm_data
;
1783 int bytes_returned
= 0;
1784 int resp_buf_type
= 0;
1785 __u16 params
, param_offset
, offset
, byte_count
, count
;
1788 cFYI(1, "Posix Lock");
1790 if (pLockData
== NULL
)
1793 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1798 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1801 pSMB
->MaxSetupCount
= 0;
1804 pSMB
->Reserved2
= 0;
1805 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1806 offset
= param_offset
+ params
;
1808 count
= sizeof(struct cifs_posix_lock
);
1809 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1810 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1811 pSMB
->SetupCount
= 1;
1812 pSMB
->Reserved3
= 0;
1814 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1816 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1817 byte_count
= 3 /* pad */ + params
+ count
;
1818 pSMB
->DataCount
= cpu_to_le16(count
);
1819 pSMB
->ParameterCount
= cpu_to_le16(params
);
1820 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1821 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1822 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1823 parm_data
= (struct cifs_posix_lock
*)
1824 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1826 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1828 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1829 parm_data
->lock_flags
= cpu_to_le16(1);
1830 pSMB
->Timeout
= cpu_to_le32(-1);
1834 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1835 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1836 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1838 pSMB
->DataOffset
= cpu_to_le16(offset
);
1839 pSMB
->Fid
= smb_file_id
;
1840 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1841 pSMB
->Reserved4
= 0;
1842 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1843 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1845 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1846 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1848 iov
[0].iov_base
= (char *)pSMB
;
1849 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1850 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1851 &resp_buf_type
, timeout
);
1852 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1853 not try to free it twice below on exit */
1854 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1858 cFYI(1, "Send error in Posix Lock = %d", rc
);
1859 } else if (get_flag
) {
1860 /* lock structure can be returned on get */
1863 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1865 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1866 rc
= -EIO
; /* bad smb */
1869 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1870 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1871 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1875 parm_data
= (struct cifs_posix_lock
*)
1876 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1877 if (parm_data
->lock_type
== __constant_cpu_to_le16(CIFS_UNLCK
))
1878 pLockData
->fl_type
= F_UNLCK
;
1880 if (parm_data
->lock_type
==
1881 __constant_cpu_to_le16(CIFS_RDLCK
))
1882 pLockData
->fl_type
= F_RDLCK
;
1883 else if (parm_data
->lock_type
==
1884 __constant_cpu_to_le16(CIFS_WRLCK
))
1885 pLockData
->fl_type
= F_WRLCK
;
1887 pLockData
->fl_start
= parm_data
->start
;
1888 pLockData
->fl_end
= parm_data
->start
+
1889 parm_data
->length
- 1;
1890 pLockData
->fl_pid
= parm_data
->pid
;
1896 cifs_small_buf_release(pSMB
);
1898 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1899 cifs_small_buf_release(iov
[0].iov_base
);
1900 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1901 cifs_buf_release(iov
[0].iov_base
);
1903 /* Note: On -EAGAIN error only caller can retry on handle based calls
1904 since file handle passed in no longer valid */
1911 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1914 CLOSE_REQ
*pSMB
= NULL
;
1915 cFYI(1, "In CIFSSMBClose");
1917 /* do not retry on dead session on close */
1918 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1924 pSMB
->FileID
= (__u16
) smb_file_id
;
1925 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1926 pSMB
->ByteCount
= 0;
1927 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1928 cifs_stats_inc(&tcon
->num_closes
);
1931 /* EINTR is expected when user ctl-c to kill app */
1932 cERROR(1, "Send error in Close = %d", rc
);
1936 /* Since session is dead, file will be closed on server already */
1944 CIFSSMBFlush(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1947 FLUSH_REQ
*pSMB
= NULL
;
1948 cFYI(1, "In CIFSSMBFlush");
1950 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
1954 pSMB
->FileID
= (__u16
) smb_file_id
;
1955 pSMB
->ByteCount
= 0;
1956 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1957 cifs_stats_inc(&tcon
->num_flushes
);
1959 cERROR(1, "Send error in Flush = %d", rc
);
1965 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1966 const char *fromName
, const char *toName
,
1967 const struct nls_table
*nls_codepage
, int remap
)
1970 RENAME_REQ
*pSMB
= NULL
;
1971 RENAME_RSP
*pSMBr
= NULL
;
1973 int name_len
, name_len2
;
1976 cFYI(1, "In CIFSSMBRename");
1978 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1983 pSMB
->BufferFormat
= 0x04;
1984 pSMB
->SearchAttributes
=
1985 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1988 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1990 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1991 PATH_MAX
, nls_codepage
, remap
);
1992 name_len
++; /* trailing null */
1994 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1995 /* protocol requires ASCII signature byte on Unicode string */
1996 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1998 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1999 toName
, PATH_MAX
, nls_codepage
, remap
);
2000 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2001 name_len2
*= 2; /* convert to bytes */
2002 } else { /* BB improve the check for buffer overruns BB */
2003 name_len
= strnlen(fromName
, PATH_MAX
);
2004 name_len
++; /* trailing null */
2005 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2006 name_len2
= strnlen(toName
, PATH_MAX
);
2007 name_len2
++; /* trailing null */
2008 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2009 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2010 name_len2
++; /* trailing null */
2011 name_len2
++; /* signature byte */
2014 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2015 pSMB
->hdr
.smb_buf_length
+= count
;
2016 pSMB
->ByteCount
= cpu_to_le16(count
);
2018 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2019 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2020 cifs_stats_inc(&tcon
->num_renames
);
2022 cFYI(1, "Send error in rename = %d", rc
);
2024 cifs_buf_release(pSMB
);
2032 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
2033 int netfid
, const char *target_name
,
2034 const struct nls_table
*nls_codepage
, int remap
)
2036 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2037 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2038 struct set_file_rename
*rename_info
;
2040 char dummy_string
[30];
2042 int bytes_returned
= 0;
2044 __u16 params
, param_offset
, offset
, count
, byte_count
;
2046 cFYI(1, "Rename to File by handle");
2047 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2053 pSMB
->MaxSetupCount
= 0;
2057 pSMB
->Reserved2
= 0;
2058 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2059 offset
= param_offset
+ params
;
2061 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2062 rename_info
= (struct set_file_rename
*) data_offset
;
2063 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2064 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2065 pSMB
->SetupCount
= 1;
2066 pSMB
->Reserved3
= 0;
2067 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2068 byte_count
= 3 /* pad */ + params
;
2069 pSMB
->ParameterCount
= cpu_to_le16(params
);
2070 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2071 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2072 pSMB
->DataOffset
= cpu_to_le16(offset
);
2073 /* construct random name ".cifs_tmp<inodenum><mid>" */
2074 rename_info
->overwrite
= cpu_to_le32(1);
2075 rename_info
->root_fid
= 0;
2076 /* unicode only call */
2077 if (target_name
== NULL
) {
2078 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2079 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2080 dummy_string
, 24, nls_codepage
, remap
);
2082 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2083 target_name
, PATH_MAX
, nls_codepage
,
2086 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2087 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2088 byte_count
+= count
;
2089 pSMB
->DataCount
= cpu_to_le16(count
);
2090 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2092 pSMB
->InformationLevel
=
2093 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2094 pSMB
->Reserved4
= 0;
2095 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2096 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2097 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2098 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2099 cifs_stats_inc(&pTcon
->num_t2renames
);
2101 cFYI(1, "Send error in Rename (by file handle) = %d", rc
);
2103 cifs_buf_release(pSMB
);
2105 /* Note: On -EAGAIN error only caller can retry on handle based calls
2106 since file handle passed in no longer valid */
2112 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2113 const __u16 target_tid
, const char *toName
, const int flags
,
2114 const struct nls_table
*nls_codepage
, int remap
)
2117 COPY_REQ
*pSMB
= NULL
;
2118 COPY_RSP
*pSMBr
= NULL
;
2120 int name_len
, name_len2
;
2123 cFYI(1, "In CIFSSMBCopy");
2125 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2130 pSMB
->BufferFormat
= 0x04;
2131 pSMB
->Tid2
= target_tid
;
2133 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2135 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2136 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2137 fromName
, PATH_MAX
, nls_codepage
,
2139 name_len
++; /* trailing null */
2141 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2142 /* protocol requires ASCII signature byte on Unicode string */
2143 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2145 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2146 toName
, PATH_MAX
, nls_codepage
, remap
);
2147 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2148 name_len2
*= 2; /* convert to bytes */
2149 } else { /* BB improve the check for buffer overruns BB */
2150 name_len
= strnlen(fromName
, PATH_MAX
);
2151 name_len
++; /* trailing null */
2152 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2153 name_len2
= strnlen(toName
, PATH_MAX
);
2154 name_len2
++; /* trailing null */
2155 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2156 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2157 name_len2
++; /* trailing null */
2158 name_len2
++; /* signature byte */
2161 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2162 pSMB
->hdr
.smb_buf_length
+= count
;
2163 pSMB
->ByteCount
= cpu_to_le16(count
);
2165 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2166 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2168 cFYI(1, "Send error in copy = %d with %d files copied",
2169 rc
, le16_to_cpu(pSMBr
->CopyCount
));
2171 cifs_buf_release(pSMB
);
2180 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2181 const char *fromName
, const char *toName
,
2182 const struct nls_table
*nls_codepage
)
2184 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2185 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2188 int name_len_target
;
2190 int bytes_returned
= 0;
2191 __u16 params
, param_offset
, offset
, byte_count
;
2193 cFYI(1, "In Symlink Unix style");
2195 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2200 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2202 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2203 /* find define for this maxpathcomponent */
2205 name_len
++; /* trailing null */
2208 } else { /* BB improve the check for buffer overruns BB */
2209 name_len
= strnlen(fromName
, PATH_MAX
);
2210 name_len
++; /* trailing null */
2211 strncpy(pSMB
->FileName
, fromName
, name_len
);
2213 params
= 6 + name_len
;
2214 pSMB
->MaxSetupCount
= 0;
2218 pSMB
->Reserved2
= 0;
2219 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2220 InformationLevel
) - 4;
2221 offset
= param_offset
+ params
;
2223 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2224 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2226 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2227 /* find define for this maxpathcomponent */
2229 name_len_target
++; /* trailing null */
2230 name_len_target
*= 2;
2231 } else { /* BB improve the check for buffer overruns BB */
2232 name_len_target
= strnlen(toName
, PATH_MAX
);
2233 name_len_target
++; /* trailing null */
2234 strncpy(data_offset
, toName
, name_len_target
);
2237 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2238 /* BB find exact max on data count below from sess */
2239 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2240 pSMB
->SetupCount
= 1;
2241 pSMB
->Reserved3
= 0;
2242 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2243 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2244 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2245 pSMB
->ParameterCount
= cpu_to_le16(params
);
2246 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2247 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2248 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2249 pSMB
->DataOffset
= cpu_to_le16(offset
);
2250 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2251 pSMB
->Reserved4
= 0;
2252 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2253 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2254 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2255 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2256 cifs_stats_inc(&tcon
->num_symlinks
);
2258 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc
);
2260 cifs_buf_release(pSMB
);
2263 goto createSymLinkRetry
;
2269 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2270 const char *fromName
, const char *toName
,
2271 const struct nls_table
*nls_codepage
, int remap
)
2273 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2274 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2277 int name_len_target
;
2279 int bytes_returned
= 0;
2280 __u16 params
, param_offset
, offset
, byte_count
;
2282 cFYI(1, "In Create Hard link Unix style");
2283 createHardLinkRetry
:
2284 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2289 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2290 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2291 PATH_MAX
, nls_codepage
, remap
);
2292 name_len
++; /* trailing null */
2295 } else { /* BB improve the check for buffer overruns BB */
2296 name_len
= strnlen(toName
, PATH_MAX
);
2297 name_len
++; /* trailing null */
2298 strncpy(pSMB
->FileName
, toName
, name_len
);
2300 params
= 6 + name_len
;
2301 pSMB
->MaxSetupCount
= 0;
2305 pSMB
->Reserved2
= 0;
2306 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2307 InformationLevel
) - 4;
2308 offset
= param_offset
+ params
;
2310 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2311 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2313 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2314 nls_codepage
, remap
);
2315 name_len_target
++; /* trailing null */
2316 name_len_target
*= 2;
2317 } else { /* BB improve the check for buffer overruns BB */
2318 name_len_target
= strnlen(fromName
, PATH_MAX
);
2319 name_len_target
++; /* trailing null */
2320 strncpy(data_offset
, fromName
, name_len_target
);
2323 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2324 /* BB find exact max on data count below from sess*/
2325 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2326 pSMB
->SetupCount
= 1;
2327 pSMB
->Reserved3
= 0;
2328 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2329 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2330 pSMB
->ParameterCount
= cpu_to_le16(params
);
2331 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2332 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2333 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2334 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2335 pSMB
->DataOffset
= cpu_to_le16(offset
);
2336 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2337 pSMB
->Reserved4
= 0;
2338 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2339 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2340 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2341 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2342 cifs_stats_inc(&tcon
->num_hardlinks
);
2344 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc
);
2346 cifs_buf_release(pSMB
);
2348 goto createHardLinkRetry
;
2354 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2355 const char *fromName
, const char *toName
,
2356 const struct nls_table
*nls_codepage
, int remap
)
2359 NT_RENAME_REQ
*pSMB
= NULL
;
2360 RENAME_RSP
*pSMBr
= NULL
;
2362 int name_len
, name_len2
;
2365 cFYI(1, "In CIFSCreateHardLink");
2366 winCreateHardLinkRetry
:
2368 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2373 pSMB
->SearchAttributes
=
2374 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2376 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2377 pSMB
->ClusterCount
= 0;
2379 pSMB
->BufferFormat
= 0x04;
2381 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2383 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2384 PATH_MAX
, nls_codepage
, remap
);
2385 name_len
++; /* trailing null */
2388 /* protocol specifies ASCII buffer format (0x04) for unicode */
2389 pSMB
->OldFileName
[name_len
] = 0x04;
2390 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2392 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2393 toName
, PATH_MAX
, nls_codepage
, remap
);
2394 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2395 name_len2
*= 2; /* convert to bytes */
2396 } else { /* BB improve the check for buffer overruns BB */
2397 name_len
= strnlen(fromName
, PATH_MAX
);
2398 name_len
++; /* trailing null */
2399 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2400 name_len2
= strnlen(toName
, PATH_MAX
);
2401 name_len2
++; /* trailing null */
2402 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2403 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2404 name_len2
++; /* trailing null */
2405 name_len2
++; /* signature byte */
2408 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2409 pSMB
->hdr
.smb_buf_length
+= count
;
2410 pSMB
->ByteCount
= cpu_to_le16(count
);
2412 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2413 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2414 cifs_stats_inc(&tcon
->num_hardlinks
);
2416 cFYI(1, "Send error in hard link (NT rename) = %d", rc
);
2418 cifs_buf_release(pSMB
);
2420 goto winCreateHardLinkRetry
;
2426 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2427 const unsigned char *searchName
, char **symlinkinfo
,
2428 const struct nls_table
*nls_codepage
)
2430 /* SMB_QUERY_FILE_UNIX_LINK */
2431 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2432 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2436 __u16 params
, byte_count
;
2439 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName
);
2442 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2447 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2449 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2450 PATH_MAX
, nls_codepage
);
2451 name_len
++; /* trailing null */
2453 } else { /* BB improve the check for buffer overruns BB */
2454 name_len
= strnlen(searchName
, PATH_MAX
);
2455 name_len
++; /* trailing null */
2456 strncpy(pSMB
->FileName
, searchName
, name_len
);
2459 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2460 pSMB
->TotalDataCount
= 0;
2461 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2462 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
2463 pSMB
->MaxSetupCount
= 0;
2467 pSMB
->Reserved2
= 0;
2468 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2469 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2470 pSMB
->DataCount
= 0;
2471 pSMB
->DataOffset
= 0;
2472 pSMB
->SetupCount
= 1;
2473 pSMB
->Reserved3
= 0;
2474 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2475 byte_count
= params
+ 1 /* pad */ ;
2476 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2477 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2478 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2479 pSMB
->Reserved4
= 0;
2480 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2481 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2483 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2484 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2486 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc
);
2488 /* decode response */
2490 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2491 /* BB also check enough total bytes returned */
2492 if (rc
|| (pSMBr
->ByteCount
< 2))
2496 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2498 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
2499 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2501 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2506 /* BB FIXME investigate remapping reserved chars here */
2507 *symlinkinfo
= cifs_strndup_from_ucs(data_start
, count
,
2508 is_unicode
, nls_codepage
);
2513 cifs_buf_release(pSMB
);
2515 goto querySymLinkRetry
;
2519 #ifdef CONFIG_CIFS_EXPERIMENTAL
2521 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2522 const unsigned char *searchName
,
2523 char *symlinkinfo
, const int buflen
, __u16 fid
,
2524 const struct nls_table
*nls_codepage
)
2528 struct smb_com_transaction_ioctl_req
*pSMB
;
2529 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2531 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName
);
2532 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2537 pSMB
->TotalParameterCount
= 0 ;
2538 pSMB
->TotalDataCount
= 0;
2539 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2540 /* BB find exact data count max from sess structure BB */
2541 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2542 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2543 pSMB
->MaxSetupCount
= 4;
2545 pSMB
->ParameterOffset
= 0;
2546 pSMB
->DataCount
= 0;
2547 pSMB
->DataOffset
= 0;
2548 pSMB
->SetupCount
= 4;
2549 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2550 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2551 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2552 pSMB
->IsFsctl
= 1; /* FSCTL */
2553 pSMB
->IsRootFlag
= 0;
2554 pSMB
->Fid
= fid
; /* file handle always le */
2555 pSMB
->ByteCount
= 0;
2557 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2558 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2560 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc
);
2561 } else { /* decode response */
2562 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2563 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2564 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512)) {
2565 /* BB also check enough total bytes returned */
2566 rc
= -EIO
; /* bad smb */
2569 if (data_count
&& (data_count
< 2048)) {
2570 char *end_of_smb
= 2 /* sizeof byte count */ +
2571 pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
2573 struct reparse_data
*reparse_buf
=
2574 (struct reparse_data
*)
2575 ((char *)&pSMBr
->hdr
.Protocol
2577 if ((char *)reparse_buf
>= end_of_smb
) {
2581 if ((reparse_buf
->LinkNamesBuf
+
2582 reparse_buf
->TargetNameOffset
+
2583 reparse_buf
->TargetNameLen
) > end_of_smb
) {
2584 cFYI(1, "reparse buf beyond SMB");
2589 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2590 cifs_from_ucs2(symlinkinfo
, (__le16
*)
2591 (reparse_buf
->LinkNamesBuf
+
2592 reparse_buf
->TargetNameOffset
),
2594 reparse_buf
->TargetNameLen
,
2596 } else { /* ASCII names */
2597 strncpy(symlinkinfo
,
2598 reparse_buf
->LinkNamesBuf
+
2599 reparse_buf
->TargetNameOffset
,
2600 min_t(const int, buflen
,
2601 reparse_buf
->TargetNameLen
));
2605 cFYI(1, "Invalid return data count on "
2606 "get reparse info ioctl");
2608 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2609 does not go off the end of the buffer */
2610 cFYI(1, "readlink result - %s", symlinkinfo
);
2614 cifs_buf_release(pSMB
);
2616 /* Note: On -EAGAIN error only caller can retry on handle based calls
2617 since file handle passed in no longer valid */
2621 #endif /* CIFS_EXPERIMENTAL */
2623 #ifdef CONFIG_CIFS_POSIX
2625 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2626 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2627 struct cifs_posix_ace
*cifs_ace
)
2629 /* u8 cifs fields do not need le conversion */
2630 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2631 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2632 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2633 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2638 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2639 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2640 const int acl_type
, const int size_of_data_area
)
2645 struct cifs_posix_ace
*pACE
;
2646 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2647 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2649 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2652 if (acl_type
& ACL_TYPE_ACCESS
) {
2653 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2654 pACE
= &cifs_acl
->ace_array
[0];
2655 size
= sizeof(struct cifs_posix_acl
);
2656 size
+= sizeof(struct cifs_posix_ace
) * count
;
2657 /* check if we would go beyond end of SMB */
2658 if (size_of_data_area
< size
) {
2659 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2660 size_of_data_area
, size
);
2663 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2664 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2665 size
= sizeof(struct cifs_posix_acl
);
2666 size
+= sizeof(struct cifs_posix_ace
) * count
;
2667 /* skip past access ACEs to get to default ACEs */
2668 pACE
= &cifs_acl
->ace_array
[count
];
2669 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2670 size
+= sizeof(struct cifs_posix_ace
) * count
;
2671 /* check if we would go beyond end of SMB */
2672 if (size_of_data_area
< size
)
2679 size
= posix_acl_xattr_size(count
);
2680 if ((buflen
== 0) || (local_acl
== NULL
)) {
2681 /* used to query ACL EA size */
2682 } else if (size
> buflen
) {
2684 } else /* buffer big enough */ {
2685 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2686 for (i
= 0; i
< count
; i
++) {
2687 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2694 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2695 const posix_acl_xattr_entry
*local_ace
)
2697 __u16 rc
= 0; /* 0 = ACL converted ok */
2699 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2700 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2701 /* BB is there a better way to handle the large uid? */
2702 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2703 /* Probably no need to le convert -1 on any arch but can not hurt */
2704 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2706 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2707 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2711 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2712 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2713 const int buflen
, const int acl_type
)
2716 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2717 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2721 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2724 count
= posix_acl_xattr_count((size_t)buflen
);
2725 cFYI(1, "setting acl with %d entries from buf of length %d and "
2727 count
, buflen
, le32_to_cpu(local_acl
->a_version
));
2728 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2729 cFYI(1, "unknown POSIX ACL version %d",
2730 le32_to_cpu(local_acl
->a_version
));
2733 cifs_acl
->version
= cpu_to_le16(1);
2734 if (acl_type
== ACL_TYPE_ACCESS
)
2735 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2736 else if (acl_type
== ACL_TYPE_DEFAULT
)
2737 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2739 cFYI(1, "unknown ACL type %d", acl_type
);
2742 for (i
= 0; i
< count
; i
++) {
2743 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2744 &local_acl
->a_entries
[i
]);
2746 /* ACE not converted */
2751 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2752 rc
+= sizeof(struct cifs_posix_acl
);
2753 /* BB add check to make sure ACL does not overflow SMB */
2759 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2760 const unsigned char *searchName
,
2761 char *acl_inf
, const int buflen
, const int acl_type
,
2762 const struct nls_table
*nls_codepage
, int remap
)
2764 /* SMB_QUERY_POSIX_ACL */
2765 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2766 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2770 __u16 params
, byte_count
;
2772 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName
);
2775 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2780 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2782 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2783 PATH_MAX
, nls_codepage
, remap
);
2784 name_len
++; /* trailing null */
2786 pSMB
->FileName
[name_len
] = 0;
2787 pSMB
->FileName
[name_len
+1] = 0;
2788 } else { /* BB improve the check for buffer overruns BB */
2789 name_len
= strnlen(searchName
, PATH_MAX
);
2790 name_len
++; /* trailing null */
2791 strncpy(pSMB
->FileName
, searchName
, name_len
);
2794 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2795 pSMB
->TotalDataCount
= 0;
2796 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2797 /* BB find exact max data count below from sess structure BB */
2798 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2799 pSMB
->MaxSetupCount
= 0;
2803 pSMB
->Reserved2
= 0;
2804 pSMB
->ParameterOffset
= cpu_to_le16(
2805 offsetof(struct smb_com_transaction2_qpi_req
,
2806 InformationLevel
) - 4);
2807 pSMB
->DataCount
= 0;
2808 pSMB
->DataOffset
= 0;
2809 pSMB
->SetupCount
= 1;
2810 pSMB
->Reserved3
= 0;
2811 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2812 byte_count
= params
+ 1 /* pad */ ;
2813 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2814 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2815 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2816 pSMB
->Reserved4
= 0;
2817 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2818 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2820 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2821 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2822 cifs_stats_inc(&tcon
->num_acl_get
);
2824 cFYI(1, "Send error in Query POSIX ACL = %d", rc
);
2826 /* decode response */
2828 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2829 if (rc
|| (pSMBr
->ByteCount
< 2))
2830 /* BB also check enough total bytes returned */
2831 rc
= -EIO
; /* bad smb */
2833 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2834 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2835 rc
= cifs_copy_posix_acl(acl_inf
,
2836 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2837 buflen
, acl_type
, count
);
2840 cifs_buf_release(pSMB
);
2847 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2848 const unsigned char *fileName
,
2849 const char *local_acl
, const int buflen
,
2851 const struct nls_table
*nls_codepage
, int remap
)
2853 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2854 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2858 int bytes_returned
= 0;
2859 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2861 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName
);
2863 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2867 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2869 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2870 PATH_MAX
, nls_codepage
, remap
);
2871 name_len
++; /* trailing null */
2873 } else { /* BB improve the check for buffer overruns BB */
2874 name_len
= strnlen(fileName
, PATH_MAX
);
2875 name_len
++; /* trailing null */
2876 strncpy(pSMB
->FileName
, fileName
, name_len
);
2878 params
= 6 + name_len
;
2879 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2880 /* BB find max SMB size from sess */
2881 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2882 pSMB
->MaxSetupCount
= 0;
2886 pSMB
->Reserved2
= 0;
2887 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2888 InformationLevel
) - 4;
2889 offset
= param_offset
+ params
;
2890 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2891 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2893 /* convert to on the wire format for POSIX ACL */
2894 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2896 if (data_count
== 0) {
2898 goto setACLerrorExit
;
2900 pSMB
->DataOffset
= cpu_to_le16(offset
);
2901 pSMB
->SetupCount
= 1;
2902 pSMB
->Reserved3
= 0;
2903 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2904 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2905 byte_count
= 3 /* pad */ + params
+ data_count
;
2906 pSMB
->DataCount
= cpu_to_le16(data_count
);
2907 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2908 pSMB
->ParameterCount
= cpu_to_le16(params
);
2909 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2910 pSMB
->Reserved4
= 0;
2911 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2912 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2913 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2914 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2916 cFYI(1, "Set POSIX ACL returned %d", rc
);
2919 cifs_buf_release(pSMB
);
2925 /* BB fix tabs in this function FIXME BB */
2927 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2928 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2931 struct smb_t2_qfi_req
*pSMB
= NULL
;
2932 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2934 __u16 params
, byte_count
;
2936 cFYI(1, "In GetExtAttr");
2941 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2946 params
= 2 /* level */ + 2 /* fid */;
2947 pSMB
->t2
.TotalDataCount
= 0;
2948 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2949 /* BB find exact max data count below from sess structure BB */
2950 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2951 pSMB
->t2
.MaxSetupCount
= 0;
2952 pSMB
->t2
.Reserved
= 0;
2954 pSMB
->t2
.Timeout
= 0;
2955 pSMB
->t2
.Reserved2
= 0;
2956 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2958 pSMB
->t2
.DataCount
= 0;
2959 pSMB
->t2
.DataOffset
= 0;
2960 pSMB
->t2
.SetupCount
= 1;
2961 pSMB
->t2
.Reserved3
= 0;
2962 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2963 byte_count
= params
+ 1 /* pad */ ;
2964 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2965 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2966 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2969 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2970 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2972 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2973 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2975 cFYI(1, "error %d in GetExtAttr", rc
);
2977 /* decode response */
2978 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2979 if (rc
|| (pSMBr
->ByteCount
< 2))
2980 /* BB also check enough total bytes returned */
2981 /* If rc should we check for EOPNOSUPP and
2982 disable the srvino flag? or in caller? */
2983 rc
= -EIO
; /* bad smb */
2985 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2986 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2987 struct file_chattr_info
*pfinfo
;
2988 /* BB Do we need a cast or hash here ? */
2990 cFYI(1, "Illegal size ret in GetExtAttr");
2994 pfinfo
= (struct file_chattr_info
*)
2995 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2996 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2997 *pMask
= le64_to_cpu(pfinfo
->mask
);
3001 cifs_buf_release(pSMB
);
3003 goto GetExtAttrRetry
;
3007 #endif /* CONFIG_POSIX */
3009 #ifdef CONFIG_CIFS_ACL
3011 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3012 * all NT TRANSACTS that we init here have total parm and data under about 400
3013 * bytes (to fit in small cifs buffer size), which is the case so far, it
3014 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3015 * returned setup area) and MaxParameterCount (returned parms size) must be set
3019 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
3020 const int parm_len
, struct cifsTconInfo
*tcon
,
3025 struct smb_com_ntransact_req
*pSMB
;
3027 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
3031 *ret_buf
= (void *)pSMB
;
3033 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
3034 pSMB
->TotalDataCount
= 0;
3035 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
3036 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3037 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3038 pSMB
->DataCount
= pSMB
->TotalDataCount
;
3039 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
3040 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
3041 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
3042 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
3043 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
3044 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
3049 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
3050 __u32
*pparmlen
, __u32
*pdatalen
)
3053 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
3054 struct smb_com_ntransact_rsp
*pSMBr
;
3062 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
3064 /* ByteCount was converted from little endian in SendReceive */
3065 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
3066 (char *)&pSMBr
->ByteCount
;
3068 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
3069 data_count
= le32_to_cpu(pSMBr
->DataCount
);
3070 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
3071 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
3073 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
3074 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
3076 /* should we also check that parm and data areas do not overlap? */
3077 if (*ppparm
> end_of_smb
) {
3078 cFYI(1, "parms start after end of smb");
3080 } else if (parm_count
+ *ppparm
> end_of_smb
) {
3081 cFYI(1, "parm end after end of smb");
3083 } else if (*ppdata
> end_of_smb
) {
3084 cFYI(1, "data starts after end of smb");
3086 } else if (data_count
+ *ppdata
> end_of_smb
) {
3087 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3088 *ppdata
, data_count
, (data_count
+ *ppdata
),
3091 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
3092 cFYI(1, "parm count and data count larger than SMB");
3095 *pdatalen
= data_count
;
3096 *pparmlen
= parm_count
;
3100 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3102 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3103 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3107 QUERY_SEC_DESC_REQ
*pSMB
;
3110 cFYI(1, "GetCifsACL");
3115 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3116 8 /* parm len */, tcon
, (void **) &pSMB
);
3120 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3121 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3122 pSMB
->MaxSetupCount
= 0;
3123 pSMB
->Fid
= fid
; /* file handle always le */
3124 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3126 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3127 pSMB
->hdr
.smb_buf_length
+= 11;
3128 iov
[0].iov_base
= (char *)pSMB
;
3129 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3131 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3133 cifs_stats_inc(&tcon
->num_acl_get
);
3135 cFYI(1, "Send error in QuerySecDesc = %d", rc
);
3136 } else { /* decode response */
3140 struct smb_com_ntransact_rsp
*pSMBr
;
3143 /* validate_nttransact */
3144 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3145 &pdata
, &parm_len
, pbuflen
);
3148 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3150 cFYI(1, "smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
);
3152 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3153 rc
= -EIO
; /* bad smb */
3158 /* BB check that data area is minimum length and as big as acl_len */
3160 acl_len
= le32_to_cpu(*parm
);
3161 if (acl_len
!= *pbuflen
) {
3162 cERROR(1, "acl length %d does not match %d",
3164 if (*pbuflen
> acl_len
)
3168 /* check if buffer is big enough for the acl
3169 header followed by the smallest SID */
3170 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3171 (*pbuflen
>= 64 * 1024)) {
3172 cERROR(1, "bad acl length %d", *pbuflen
);
3176 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3177 if (*acl_inf
== NULL
) {
3181 memcpy(*acl_inf
, pdata
, *pbuflen
);
3185 if (buf_type
== CIFS_SMALL_BUFFER
)
3186 cifs_small_buf_release(iov
[0].iov_base
);
3187 else if (buf_type
== CIFS_LARGE_BUFFER
)
3188 cifs_buf_release(iov
[0].iov_base
);
3189 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3194 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3195 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3197 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3199 int bytes_returned
= 0;
3200 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3201 NTRANSACT_RSP
*pSMBr
= NULL
;
3204 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3209 pSMB
->MaxSetupCount
= 0;
3213 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3214 data_count
= acllen
;
3215 data_offset
= param_offset
+ param_count
;
3216 byte_count
= 3 /* pad */ + param_count
;
3218 pSMB
->DataCount
= cpu_to_le32(data_count
);
3219 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3220 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3221 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3222 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3223 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3224 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3225 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3226 pSMB
->SetupCount
= 0;
3227 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3228 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3230 pSMB
->Fid
= fid
; /* file handle always le */
3231 pSMB
->Reserved2
= 0;
3232 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3234 if (pntsd
&& acllen
) {
3235 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3238 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3241 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3243 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3244 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3246 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
);
3248 cFYI(1, "Set CIFS ACL returned %d", rc
);
3249 cifs_buf_release(pSMB
);
3252 goto setCifsAclRetry
;
3257 #endif /* CONFIG_CIFS_ACL */
3259 /* Legacy Query Path Information call for lookup to old servers such
3261 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3262 const unsigned char *searchName
,
3263 FILE_ALL_INFO
*pFinfo
,
3264 const struct nls_table
*nls_codepage
, int remap
)
3266 QUERY_INFORMATION_REQ
*pSMB
;
3267 QUERY_INFORMATION_RSP
*pSMBr
;
3272 cFYI(1, "In SMBQPath path %s", searchName
);
3274 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3279 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3281 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3282 PATH_MAX
, nls_codepage
, remap
);
3283 name_len
++; /* trailing null */
3286 name_len
= strnlen(searchName
, PATH_MAX
);
3287 name_len
++; /* trailing null */
3288 strncpy(pSMB
->FileName
, searchName
, name_len
);
3290 pSMB
->BufferFormat
= 0x04;
3291 name_len
++; /* account for buffer type byte */
3292 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3293 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3295 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3296 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3298 cFYI(1, "Send error in QueryInfo = %d", rc
);
3299 } else if (pFinfo
) {
3301 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3303 /* decode response */
3304 /* BB FIXME - add time zone adjustment BB */
3305 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3308 /* decode time fields */
3309 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3310 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3311 pFinfo
->LastAccessTime
= 0;
3312 pFinfo
->AllocationSize
=
3313 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3314 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3315 pFinfo
->Attributes
=
3316 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3318 rc
= -EIO
; /* bad buffer passed in */
3320 cifs_buf_release(pSMB
);
3329 CIFSSMBQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3330 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3332 struct smb_t2_qfi_req
*pSMB
= NULL
;
3333 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3336 __u16 params
, byte_count
;
3339 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3344 params
= 2 /* level */ + 2 /* fid */;
3345 pSMB
->t2
.TotalDataCount
= 0;
3346 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3347 /* BB find exact max data count below from sess structure BB */
3348 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3349 pSMB
->t2
.MaxSetupCount
= 0;
3350 pSMB
->t2
.Reserved
= 0;
3352 pSMB
->t2
.Timeout
= 0;
3353 pSMB
->t2
.Reserved2
= 0;
3354 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3356 pSMB
->t2
.DataCount
= 0;
3357 pSMB
->t2
.DataOffset
= 0;
3358 pSMB
->t2
.SetupCount
= 1;
3359 pSMB
->t2
.Reserved3
= 0;
3360 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3361 byte_count
= params
+ 1 /* pad */ ;
3362 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3363 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3364 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3367 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3369 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3370 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3372 cFYI(1, "Send error in QPathInfo = %d", rc
);
3373 } else { /* decode response */
3374 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3376 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3378 else if (pSMBr
->ByteCount
< 40)
3379 rc
= -EIO
; /* bad smb */
3380 else if (pFindData
) {
3381 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3382 memcpy((char *) pFindData
,
3383 (char *) &pSMBr
->hdr
.Protocol
+
3384 data_offset
, sizeof(FILE_ALL_INFO
));
3388 cifs_buf_release(pSMB
);
3390 goto QFileInfoRetry
;
3396 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3397 const unsigned char *searchName
,
3398 FILE_ALL_INFO
*pFindData
,
3399 int legacy
/* old style infolevel */,
3400 const struct nls_table
*nls_codepage
, int remap
)
3402 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3403 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3404 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3408 __u16 params
, byte_count
;
3410 /* cFYI(1, "In QPathInfo path %s", searchName); */
3412 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3417 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3419 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3420 PATH_MAX
, nls_codepage
, remap
);
3421 name_len
++; /* trailing null */
3423 } else { /* BB improve the check for buffer overruns BB */
3424 name_len
= strnlen(searchName
, PATH_MAX
);
3425 name_len
++; /* trailing null */
3426 strncpy(pSMB
->FileName
, searchName
, name_len
);
3429 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3430 pSMB
->TotalDataCount
= 0;
3431 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3432 /* BB find exact max SMB PDU from sess structure BB */
3433 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3434 pSMB
->MaxSetupCount
= 0;
3438 pSMB
->Reserved2
= 0;
3439 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3440 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3441 pSMB
->DataCount
= 0;
3442 pSMB
->DataOffset
= 0;
3443 pSMB
->SetupCount
= 1;
3444 pSMB
->Reserved3
= 0;
3445 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3446 byte_count
= params
+ 1 /* pad */ ;
3447 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3448 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3450 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3452 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3453 pSMB
->Reserved4
= 0;
3454 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3455 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3457 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3458 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3460 cFYI(1, "Send error in QPathInfo = %d", rc
);
3461 } else { /* decode response */
3462 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3464 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3466 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3467 rc
= -EIO
; /* bad smb */
3468 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3469 rc
= -EIO
; /* 24 or 26 expected but we do not read
3471 else if (pFindData
) {
3473 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3475 /* On legacy responses we do not read the last field,
3476 EAsize, fortunately since it varies by subdialect and
3477 also note it differs on Set vs. Get, ie two bytes or 4
3478 bytes depending but we don't care here */
3480 size
= sizeof(FILE_INFO_STANDARD
);
3482 size
= sizeof(FILE_ALL_INFO
);
3483 memcpy((char *) pFindData
,
3484 (char *) &pSMBr
->hdr
.Protocol
+
3489 cifs_buf_release(pSMB
);
3491 goto QPathInfoRetry
;
3497 CIFSSMBUnixQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3498 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
3500 struct smb_t2_qfi_req
*pSMB
= NULL
;
3501 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3504 __u16 params
, byte_count
;
3507 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3512 params
= 2 /* level */ + 2 /* fid */;
3513 pSMB
->t2
.TotalDataCount
= 0;
3514 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3515 /* BB find exact max data count below from sess structure BB */
3516 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3517 pSMB
->t2
.MaxSetupCount
= 0;
3518 pSMB
->t2
.Reserved
= 0;
3520 pSMB
->t2
.Timeout
= 0;
3521 pSMB
->t2
.Reserved2
= 0;
3522 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3524 pSMB
->t2
.DataCount
= 0;
3525 pSMB
->t2
.DataOffset
= 0;
3526 pSMB
->t2
.SetupCount
= 1;
3527 pSMB
->t2
.Reserved3
= 0;
3528 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3529 byte_count
= params
+ 1 /* pad */ ;
3530 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3531 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3532 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3535 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3537 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3538 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3540 cFYI(1, "Send error in QPathInfo = %d", rc
);
3541 } else { /* decode response */
3542 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3544 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3545 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3546 "Unix Extensions can be disabled on mount "
3547 "by specifying the nosfu mount option.");
3548 rc
= -EIO
; /* bad smb */
3550 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3551 memcpy((char *) pFindData
,
3552 (char *) &pSMBr
->hdr
.Protocol
+
3554 sizeof(FILE_UNIX_BASIC_INFO
));
3558 cifs_buf_release(pSMB
);
3560 goto UnixQFileInfoRetry
;
3566 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3567 const unsigned char *searchName
,
3568 FILE_UNIX_BASIC_INFO
*pFindData
,
3569 const struct nls_table
*nls_codepage
, int remap
)
3571 /* SMB_QUERY_FILE_UNIX_BASIC */
3572 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3573 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3575 int bytes_returned
= 0;
3577 __u16 params
, byte_count
;
3579 cFYI(1, "In QPathInfo (Unix) the path %s", searchName
);
3581 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3586 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3588 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3589 PATH_MAX
, nls_codepage
, remap
);
3590 name_len
++; /* trailing null */
3592 } else { /* BB improve the check for buffer overruns BB */
3593 name_len
= strnlen(searchName
, PATH_MAX
);
3594 name_len
++; /* trailing null */
3595 strncpy(pSMB
->FileName
, searchName
, name_len
);
3598 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3599 pSMB
->TotalDataCount
= 0;
3600 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3601 /* BB find exact max SMB PDU from sess structure BB */
3602 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3603 pSMB
->MaxSetupCount
= 0;
3607 pSMB
->Reserved2
= 0;
3608 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3609 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3610 pSMB
->DataCount
= 0;
3611 pSMB
->DataOffset
= 0;
3612 pSMB
->SetupCount
= 1;
3613 pSMB
->Reserved3
= 0;
3614 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3615 byte_count
= params
+ 1 /* pad */ ;
3616 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3617 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3618 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3619 pSMB
->Reserved4
= 0;
3620 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3621 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3623 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3624 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3626 cFYI(1, "Send error in QPathInfo = %d", rc
);
3627 } else { /* decode response */
3628 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3630 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3631 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3632 "Unix Extensions can be disabled on mount "
3633 "by specifying the nosfu mount option.");
3634 rc
= -EIO
; /* bad smb */
3636 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3637 memcpy((char *) pFindData
,
3638 (char *) &pSMBr
->hdr
.Protocol
+
3640 sizeof(FILE_UNIX_BASIC_INFO
));
3643 cifs_buf_release(pSMB
);
3645 goto UnixQPathInfoRetry
;
3650 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3652 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3653 const char *searchName
,
3654 const struct nls_table
*nls_codepage
,
3656 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3658 /* level 257 SMB_ */
3659 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3660 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3661 T2_FFIRST_RSP_PARMS
*parms
;
3663 int bytes_returned
= 0;
3665 __u16 params
, byte_count
;
3667 cFYI(1, "In FindFirst for %s", searchName
);
3670 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3675 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3677 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3678 PATH_MAX
, nls_codepage
, remap
);
3679 /* We can not add the asterik earlier in case
3680 it got remapped to 0xF03A as if it were part of the
3681 directory name instead of a wildcard */
3683 pSMB
->FileName
[name_len
] = dirsep
;
3684 pSMB
->FileName
[name_len
+1] = 0;
3685 pSMB
->FileName
[name_len
+2] = '*';
3686 pSMB
->FileName
[name_len
+3] = 0;
3687 name_len
+= 4; /* now the trailing null */
3688 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3689 pSMB
->FileName
[name_len
+1] = 0;
3691 } else { /* BB add check for overrun of SMB buf BB */
3692 name_len
= strnlen(searchName
, PATH_MAX
);
3693 /* BB fix here and in unicode clause above ie
3694 if (name_len > buffersize-header)
3695 free buffer exit; BB */
3696 strncpy(pSMB
->FileName
, searchName
, name_len
);
3697 pSMB
->FileName
[name_len
] = dirsep
;
3698 pSMB
->FileName
[name_len
+1] = '*';
3699 pSMB
->FileName
[name_len
+2] = 0;
3703 params
= 12 + name_len
/* includes null */ ;
3704 pSMB
->TotalDataCount
= 0; /* no EAs */
3705 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3706 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3707 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3708 pSMB
->MaxSetupCount
= 0;
3712 pSMB
->Reserved2
= 0;
3713 byte_count
= params
+ 1 /* pad */ ;
3714 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3715 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3716 pSMB
->ParameterOffset
= cpu_to_le16(
3717 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3719 pSMB
->DataCount
= 0;
3720 pSMB
->DataOffset
= 0;
3721 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3722 pSMB
->Reserved3
= 0;
3723 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3724 pSMB
->SearchAttributes
=
3725 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3727 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3728 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3729 CIFS_SEARCH_RETURN_RESUME
);
3730 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3732 /* BB what should we set StorageType to? Does it matter? BB */
3733 pSMB
->SearchStorageType
= 0;
3734 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3735 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3737 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3738 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3739 cifs_stats_inc(&tcon
->num_ffirst
);
3741 if (rc
) {/* BB add logic to retry regular search if Unix search
3742 rejected unexpectedly by server */
3743 /* BB Add code to handle unsupported level rc */
3744 cFYI(1, "Error in FindFirst = %d", rc
);
3746 cifs_buf_release(pSMB
);
3748 /* BB eventually could optimize out free and realloc of buf */
3751 goto findFirstRetry
;
3752 } else { /* decode response */
3753 /* BB remember to free buffer if error BB */
3754 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3758 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3759 psrch_inf
->unicode
= true;
3761 psrch_inf
->unicode
= false;
3763 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3764 psrch_inf
->smallBuf
= 0;
3765 psrch_inf
->srch_entries_start
=
3766 (char *) &pSMBr
->hdr
.Protocol
+
3767 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3768 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3769 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3771 if (parms
->EndofSearch
)
3772 psrch_inf
->endOfSearch
= true;
3774 psrch_inf
->endOfSearch
= false;
3776 psrch_inf
->entries_in_buffer
=
3777 le16_to_cpu(parms
->SearchCount
);
3778 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3779 psrch_inf
->entries_in_buffer
;
3780 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3781 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3783 cERROR(1, "ignoring corrupt resume name");
3784 psrch_inf
->last_entry
= NULL
;
3788 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3791 *pnetfid
= parms
->SearchHandle
;
3793 cifs_buf_release(pSMB
);
3800 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3801 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3803 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3804 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3805 T2_FNEXT_RSP_PARMS
*parms
;
3806 char *response_data
;
3808 int bytes_returned
, name_len
;
3809 __u16 params
, byte_count
;
3811 cFYI(1, "In FindNext");
3813 if (psrch_inf
->endOfSearch
)
3816 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3821 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3823 pSMB
->TotalDataCount
= 0; /* no EAs */
3824 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3825 pSMB
->MaxDataCount
=
3826 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3828 pSMB
->MaxSetupCount
= 0;
3832 pSMB
->Reserved2
= 0;
3833 pSMB
->ParameterOffset
= cpu_to_le16(
3834 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3835 pSMB
->DataCount
= 0;
3836 pSMB
->DataOffset
= 0;
3837 pSMB
->SetupCount
= 1;
3838 pSMB
->Reserved3
= 0;
3839 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3840 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3842 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3843 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3844 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3846 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3848 name_len
= psrch_inf
->resume_name_len
;
3850 if (name_len
< PATH_MAX
) {
3851 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3852 byte_count
+= name_len
;
3853 /* 14 byte parm len above enough for 2 byte null terminator */
3854 pSMB
->ResumeFileName
[name_len
] = 0;
3855 pSMB
->ResumeFileName
[name_len
+1] = 0;
3858 goto FNext2_err_exit
;
3860 byte_count
= params
+ 1 /* pad */ ;
3861 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3862 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3863 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3864 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3866 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3867 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3868 cifs_stats_inc(&tcon
->num_fnext
);
3871 psrch_inf
->endOfSearch
= true;
3872 cifs_buf_release(pSMB
);
3873 rc
= 0; /* search probably was closed at end of search*/
3875 cFYI(1, "FindNext returned = %d", rc
);
3876 } else { /* decode response */
3877 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3882 /* BB fixme add lock for file (srch_info) struct here */
3883 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3884 psrch_inf
->unicode
= true;
3886 psrch_inf
->unicode
= false;
3887 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3888 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3889 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3890 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3891 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3892 if (psrch_inf
->smallBuf
)
3893 cifs_small_buf_release(
3894 psrch_inf
->ntwrk_buf_start
);
3896 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3897 psrch_inf
->srch_entries_start
= response_data
;
3898 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3899 psrch_inf
->smallBuf
= 0;
3900 if (parms
->EndofSearch
)
3901 psrch_inf
->endOfSearch
= true;
3903 psrch_inf
->endOfSearch
= false;
3904 psrch_inf
->entries_in_buffer
=
3905 le16_to_cpu(parms
->SearchCount
);
3906 psrch_inf
->index_of_last_entry
+=
3907 psrch_inf
->entries_in_buffer
;
3908 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3909 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3911 cERROR(1, "ignoring corrupt resume name");
3912 psrch_inf
->last_entry
= NULL
;
3915 psrch_inf
->last_entry
=
3916 psrch_inf
->srch_entries_start
+ lnoff
;
3918 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3919 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3921 /* BB fixme add unlock here */
3926 /* BB On error, should we leave previous search buf (and count and
3927 last entry fields) intact or free the previous one? */
3929 /* Note: On -EAGAIN error only caller can retry on handle based calls
3930 since file handle passed in no longer valid */
3933 cifs_buf_release(pSMB
);
3938 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3939 const __u16 searchHandle
)
3942 FINDCLOSE_REQ
*pSMB
= NULL
;
3944 cFYI(1, "In CIFSSMBFindClose");
3945 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3947 /* no sense returning error if session restarted
3948 as file handle has been closed */
3954 pSMB
->FileID
= searchHandle
;
3955 pSMB
->ByteCount
= 0;
3956 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3958 cERROR(1, "Send error in FindClose = %d", rc
);
3960 cifs_stats_inc(&tcon
->num_fclose
);
3962 /* Since session is dead, search handle closed on server already */
3970 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3971 const unsigned char *searchName
,
3972 __u64
*inode_number
,
3973 const struct nls_table
*nls_codepage
, int remap
)
3976 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3977 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3978 int name_len
, bytes_returned
;
3979 __u16 params
, byte_count
;
3981 cFYI(1, "In GetSrvInodeNum for %s", searchName
);
3985 GetInodeNumberRetry
:
3986 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3991 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3993 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3994 PATH_MAX
, nls_codepage
, remap
);
3995 name_len
++; /* trailing null */
3997 } else { /* BB improve the check for buffer overruns BB */
3998 name_len
= strnlen(searchName
, PATH_MAX
);
3999 name_len
++; /* trailing null */
4000 strncpy(pSMB
->FileName
, searchName
, name_len
);
4003 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
4004 pSMB
->TotalDataCount
= 0;
4005 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4006 /* BB find exact max data count below from sess structure BB */
4007 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4008 pSMB
->MaxSetupCount
= 0;
4012 pSMB
->Reserved2
= 0;
4013 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4014 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
4015 pSMB
->DataCount
= 0;
4016 pSMB
->DataOffset
= 0;
4017 pSMB
->SetupCount
= 1;
4018 pSMB
->Reserved3
= 0;
4019 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4020 byte_count
= params
+ 1 /* pad */ ;
4021 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4022 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4023 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
4024 pSMB
->Reserved4
= 0;
4025 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4026 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4028 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4029 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4031 cFYI(1, "error %d in QueryInternalInfo", rc
);
4033 /* decode response */
4034 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4035 if (rc
|| (pSMBr
->ByteCount
< 2))
4036 /* BB also check enough total bytes returned */
4037 /* If rc should we check for EOPNOSUPP and
4038 disable the srvino flag? or in caller? */
4039 rc
= -EIO
; /* bad smb */
4041 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4042 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
4043 struct file_internal_info
*pfinfo
;
4044 /* BB Do we need a cast or hash here ? */
4046 cFYI(1, "Illegal size ret in QryIntrnlInf");
4048 goto GetInodeNumOut
;
4050 pfinfo
= (struct file_internal_info
*)
4051 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
4052 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
4056 cifs_buf_release(pSMB
);
4058 goto GetInodeNumberRetry
;
4062 /* parses DFS refferal V3 structure
4063 * caller is responsible for freeing target_nodes
4066 * on failure - errno
4069 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
4070 unsigned int *num_of_nodes
,
4071 struct dfs_info3_param
**target_nodes
,
4072 const struct nls_table
*nls_codepage
, int remap
,
4073 const char *searchName
)
4078 struct dfs_referral_level_3
*ref
;
4080 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4084 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
4086 if (*num_of_nodes
< 1) {
4087 cERROR(1, "num_referrals: must be at least > 0,"
4088 "but we get num_referrals = %d\n", *num_of_nodes
);
4090 goto parse_DFS_referrals_exit
;
4093 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
4094 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4095 cERROR(1, "Referrals of V%d version are not supported,"
4096 "should be V3", le16_to_cpu(ref
->VersionNumber
));
4098 goto parse_DFS_referrals_exit
;
4101 /* get the upper boundary of the resp buffer */
4102 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4103 le16_to_cpu(pSMBr
->t2
.DataCount
);
4105 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4107 le32_to_cpu(pSMBr
->DFSFlags
));
4109 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4110 *num_of_nodes
, GFP_KERNEL
);
4111 if (*target_nodes
== NULL
) {
4112 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4114 goto parse_DFS_referrals_exit
;
4117 /* collect necessary data from referrals */
4118 for (i
= 0; i
< *num_of_nodes
; i
++) {
4121 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4123 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4125 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4129 goto parse_DFS_referrals_exit
;
4131 cifsConvertToUCS((__le16
*) tmp
, searchName
,
4132 PATH_MAX
, nls_codepage
, remap
);
4133 node
->path_consumed
= cifs_ucs2_bytes(tmp
,
4134 le16_to_cpu(pSMBr
->PathConsumed
),
4138 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4140 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4141 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4144 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4145 max_len
= data_end
- temp
;
4146 node
->path_name
= cifs_strndup_from_ucs(temp
, max_len
,
4147 is_unicode
, nls_codepage
);
4148 if (!node
->path_name
) {
4150 goto parse_DFS_referrals_exit
;
4153 /* copy link target UNC */
4154 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4155 max_len
= data_end
- temp
;
4156 node
->node_name
= cifs_strndup_from_ucs(temp
, max_len
,
4157 is_unicode
, nls_codepage
);
4158 if (!node
->node_name
)
4162 parse_DFS_referrals_exit
:
4164 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4165 *target_nodes
= NULL
;
4172 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4173 const unsigned char *searchName
,
4174 struct dfs_info3_param
**target_nodes
,
4175 unsigned int *num_of_nodes
,
4176 const struct nls_table
*nls_codepage
, int remap
)
4178 /* TRANS2_GET_DFS_REFERRAL */
4179 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4180 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4184 __u16 params
, byte_count
;
4186 *target_nodes
= NULL
;
4188 cFYI(1, "In GetDFSRefer the path %s", searchName
);
4192 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4197 /* server pointer checked in called function,
4198 but should never be null here anyway */
4199 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4200 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4201 pSMB
->hdr
.Uid
= ses
->Suid
;
4202 if (ses
->capabilities
& CAP_STATUS32
)
4203 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4204 if (ses
->capabilities
& CAP_DFS
)
4205 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4207 if (ses
->capabilities
& CAP_UNICODE
) {
4208 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4210 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4211 searchName
, PATH_MAX
, nls_codepage
, remap
);
4212 name_len
++; /* trailing null */
4214 } else { /* BB improve the check for buffer overruns BB */
4215 name_len
= strnlen(searchName
, PATH_MAX
);
4216 name_len
++; /* trailing null */
4217 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4221 if (ses
->server
->secMode
&
4222 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4223 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4226 pSMB
->hdr
.Uid
= ses
->Suid
;
4228 params
= 2 /* level */ + name_len
/*includes null */ ;
4229 pSMB
->TotalDataCount
= 0;
4230 pSMB
->DataCount
= 0;
4231 pSMB
->DataOffset
= 0;
4232 pSMB
->MaxParameterCount
= 0;
4233 /* BB find exact max SMB PDU from sess structure BB */
4234 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4235 pSMB
->MaxSetupCount
= 0;
4239 pSMB
->Reserved2
= 0;
4240 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4241 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4242 pSMB
->SetupCount
= 1;
4243 pSMB
->Reserved3
= 0;
4244 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4245 byte_count
= params
+ 3 /* pad */ ;
4246 pSMB
->ParameterCount
= cpu_to_le16(params
);
4247 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4248 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4249 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4250 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4252 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4253 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4255 cFYI(1, "Send error in GetDFSRefer = %d", rc
);
4258 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4260 /* BB Also check if enough total bytes returned? */
4261 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4262 rc
= -EIO
; /* bad smb */
4266 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4268 le16_to_cpu(pSMBr
->t2
.DataOffset
));
4270 /* parse returned result into more usable form */
4271 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4272 target_nodes
, nls_codepage
, remap
,
4276 cifs_buf_release(pSMB
);
4284 /* Query File System Info such as free space to old servers such as Win 9x */
4286 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4288 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4289 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4290 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4291 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4293 int bytes_returned
= 0;
4294 __u16 params
, byte_count
;
4296 cFYI(1, "OldQFSInfo");
4298 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4303 params
= 2; /* level */
4304 pSMB
->TotalDataCount
= 0;
4305 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4306 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4307 pSMB
->MaxSetupCount
= 0;
4311 pSMB
->Reserved2
= 0;
4312 byte_count
= params
+ 1 /* pad */ ;
4313 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4314 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4315 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4316 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4317 pSMB
->DataCount
= 0;
4318 pSMB
->DataOffset
= 0;
4319 pSMB
->SetupCount
= 1;
4320 pSMB
->Reserved3
= 0;
4321 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4322 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4323 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4324 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4326 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4327 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4329 cFYI(1, "Send error in QFSInfo = %d", rc
);
4330 } else { /* decode response */
4331 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4333 if (rc
|| (pSMBr
->ByteCount
< 18))
4334 rc
= -EIO
; /* bad smb */
4336 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4337 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4338 pSMBr
->ByteCount
, data_offset
);
4340 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4341 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4343 le16_to_cpu(response_data
->BytesPerSector
) *
4344 le32_to_cpu(response_data
->
4345 SectorsPerAllocationUnit
);
4347 le32_to_cpu(response_data
->TotalAllocationUnits
);
4348 FSData
->f_bfree
= FSData
->f_bavail
=
4349 le32_to_cpu(response_data
->FreeAllocationUnits
);
4350 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4351 (unsigned long long)FSData
->f_blocks
,
4352 (unsigned long long)FSData
->f_bfree
,
4356 cifs_buf_release(pSMB
);
4359 goto oldQFSInfoRetry
;
4365 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4367 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4368 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4369 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4370 FILE_SYSTEM_INFO
*response_data
;
4372 int bytes_returned
= 0;
4373 __u16 params
, byte_count
;
4375 cFYI(1, "In QFSInfo");
4377 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4382 params
= 2; /* level */
4383 pSMB
->TotalDataCount
= 0;
4384 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4385 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4386 pSMB
->MaxSetupCount
= 0;
4390 pSMB
->Reserved2
= 0;
4391 byte_count
= params
+ 1 /* pad */ ;
4392 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4393 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4394 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4395 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4396 pSMB
->DataCount
= 0;
4397 pSMB
->DataOffset
= 0;
4398 pSMB
->SetupCount
= 1;
4399 pSMB
->Reserved3
= 0;
4400 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4401 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4402 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4403 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4405 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4406 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4408 cFYI(1, "Send error in QFSInfo = %d", rc
);
4409 } else { /* decode response */
4410 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4412 if (rc
|| (pSMBr
->ByteCount
< 24))
4413 rc
= -EIO
; /* bad smb */
4415 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4419 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4422 le32_to_cpu(response_data
->BytesPerSector
) *
4423 le32_to_cpu(response_data
->
4424 SectorsPerAllocationUnit
);
4426 le64_to_cpu(response_data
->TotalAllocationUnits
);
4427 FSData
->f_bfree
= FSData
->f_bavail
=
4428 le64_to_cpu(response_data
->FreeAllocationUnits
);
4429 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4430 (unsigned long long)FSData
->f_blocks
,
4431 (unsigned long long)FSData
->f_bfree
,
4435 cifs_buf_release(pSMB
);
4444 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4446 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4447 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4448 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4449 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4451 int bytes_returned
= 0;
4452 __u16 params
, byte_count
;
4454 cFYI(1, "In QFSAttributeInfo");
4456 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4461 params
= 2; /* level */
4462 pSMB
->TotalDataCount
= 0;
4463 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4464 /* BB find exact max SMB PDU from sess structure BB */
4465 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4466 pSMB
->MaxSetupCount
= 0;
4470 pSMB
->Reserved2
= 0;
4471 byte_count
= params
+ 1 /* pad */ ;
4472 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4473 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4474 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4475 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4476 pSMB
->DataCount
= 0;
4477 pSMB
->DataOffset
= 0;
4478 pSMB
->SetupCount
= 1;
4479 pSMB
->Reserved3
= 0;
4480 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4481 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4482 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4483 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4485 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4486 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4488 cERROR(1, "Send error in QFSAttributeInfo = %d", rc
);
4489 } else { /* decode response */
4490 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4492 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4493 /* BB also check if enough bytes returned */
4494 rc
= -EIO
; /* bad smb */
4496 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4498 (FILE_SYSTEM_ATTRIBUTE_INFO
4499 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4501 memcpy(&tcon
->fsAttrInfo
, response_data
,
4502 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4505 cifs_buf_release(pSMB
);
4508 goto QFSAttributeRetry
;
4514 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4516 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4517 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4518 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4519 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4521 int bytes_returned
= 0;
4522 __u16 params
, byte_count
;
4524 cFYI(1, "In QFSDeviceInfo");
4526 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4531 params
= 2; /* level */
4532 pSMB
->TotalDataCount
= 0;
4533 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4534 /* BB find exact max SMB PDU from sess structure BB */
4535 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4536 pSMB
->MaxSetupCount
= 0;
4540 pSMB
->Reserved2
= 0;
4541 byte_count
= params
+ 1 /* pad */ ;
4542 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4543 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4544 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4545 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4547 pSMB
->DataCount
= 0;
4548 pSMB
->DataOffset
= 0;
4549 pSMB
->SetupCount
= 1;
4550 pSMB
->Reserved3
= 0;
4551 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4552 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4553 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4554 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4556 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4557 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4559 cFYI(1, "Send error in QFSDeviceInfo = %d", rc
);
4560 } else { /* decode response */
4561 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4563 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4564 rc
= -EIO
; /* bad smb */
4566 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4568 (FILE_SYSTEM_DEVICE_INFO
*)
4569 (((char *) &pSMBr
->hdr
.Protocol
) +
4571 memcpy(&tcon
->fsDevInfo
, response_data
,
4572 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4575 cifs_buf_release(pSMB
);
4578 goto QFSDeviceRetry
;
4584 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4586 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4587 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4588 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4589 FILE_SYSTEM_UNIX_INFO
*response_data
;
4591 int bytes_returned
= 0;
4592 __u16 params
, byte_count
;
4594 cFYI(1, "In QFSUnixInfo");
4596 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4597 (void **) &pSMB
, (void **) &pSMBr
);
4601 params
= 2; /* level */
4602 pSMB
->TotalDataCount
= 0;
4603 pSMB
->DataCount
= 0;
4604 pSMB
->DataOffset
= 0;
4605 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4606 /* BB find exact max SMB PDU from sess structure BB */
4607 pSMB
->MaxDataCount
= cpu_to_le16(100);
4608 pSMB
->MaxSetupCount
= 0;
4612 pSMB
->Reserved2
= 0;
4613 byte_count
= params
+ 1 /* pad */ ;
4614 pSMB
->ParameterCount
= cpu_to_le16(params
);
4615 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4616 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4617 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4618 pSMB
->SetupCount
= 1;
4619 pSMB
->Reserved3
= 0;
4620 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4621 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4622 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4623 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4625 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4626 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4628 cERROR(1, "Send error in QFSUnixInfo = %d", rc
);
4629 } else { /* decode response */
4630 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4632 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4633 rc
= -EIO
; /* bad smb */
4635 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4637 (FILE_SYSTEM_UNIX_INFO
4638 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4640 memcpy(&tcon
->fsUnixInfo
, response_data
,
4641 sizeof(FILE_SYSTEM_UNIX_INFO
));
4644 cifs_buf_release(pSMB
);
4654 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4656 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4657 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4658 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4660 int bytes_returned
= 0;
4661 __u16 params
, param_offset
, offset
, byte_count
;
4663 cFYI(1, "In SETFSUnixInfo");
4665 /* BB switch to small buf init to save memory */
4666 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4667 (void **) &pSMB
, (void **) &pSMBr
);
4671 params
= 4; /* 2 bytes zero followed by info level. */
4672 pSMB
->MaxSetupCount
= 0;
4676 pSMB
->Reserved2
= 0;
4677 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4679 offset
= param_offset
+ params
;
4681 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4682 /* BB find exact max SMB PDU from sess structure BB */
4683 pSMB
->MaxDataCount
= cpu_to_le16(100);
4684 pSMB
->SetupCount
= 1;
4685 pSMB
->Reserved3
= 0;
4686 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4687 byte_count
= 1 /* pad */ + params
+ 12;
4689 pSMB
->DataCount
= cpu_to_le16(12);
4690 pSMB
->ParameterCount
= cpu_to_le16(params
);
4691 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4692 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4693 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4694 pSMB
->DataOffset
= cpu_to_le16(offset
);
4698 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4701 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4702 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4703 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4705 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4706 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4708 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4709 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4711 cERROR(1, "Send error in SETFSUnixInfo = %d", rc
);
4712 } else { /* decode response */
4713 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4715 rc
= -EIO
; /* bad smb */
4717 cifs_buf_release(pSMB
);
4720 goto SETFSUnixRetry
;
4728 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4729 struct kstatfs
*FSData
)
4731 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4732 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4733 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4734 FILE_SYSTEM_POSIX_INFO
*response_data
;
4736 int bytes_returned
= 0;
4737 __u16 params
, byte_count
;
4739 cFYI(1, "In QFSPosixInfo");
4741 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4746 params
= 2; /* level */
4747 pSMB
->TotalDataCount
= 0;
4748 pSMB
->DataCount
= 0;
4749 pSMB
->DataOffset
= 0;
4750 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4751 /* BB find exact max SMB PDU from sess structure BB */
4752 pSMB
->MaxDataCount
= cpu_to_le16(100);
4753 pSMB
->MaxSetupCount
= 0;
4757 pSMB
->Reserved2
= 0;
4758 byte_count
= params
+ 1 /* pad */ ;
4759 pSMB
->ParameterCount
= cpu_to_le16(params
);
4760 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4761 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4762 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4763 pSMB
->SetupCount
= 1;
4764 pSMB
->Reserved3
= 0;
4765 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4766 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4767 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4768 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4770 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4771 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4773 cFYI(1, "Send error in QFSUnixInfo = %d", rc
);
4774 } else { /* decode response */
4775 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4777 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4778 rc
= -EIO
; /* bad smb */
4780 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4782 (FILE_SYSTEM_POSIX_INFO
4783 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4786 le32_to_cpu(response_data
->BlockSize
);
4788 le64_to_cpu(response_data
->TotalBlocks
);
4790 le64_to_cpu(response_data
->BlocksAvail
);
4791 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4792 FSData
->f_bavail
= FSData
->f_bfree
;
4795 le64_to_cpu(response_data
->UserBlocksAvail
);
4797 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4799 le64_to_cpu(response_data
->TotalFileNodes
);
4800 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4802 le64_to_cpu(response_data
->FreeFileNodes
);
4805 cifs_buf_release(pSMB
);
4814 /* We can not use write of zero bytes trick to
4815 set file size due to need for large file support. Also note that
4816 this SetPathInfo is preferred to SetFileInfo based method in next
4817 routine which is only needed to work around a sharing violation bug
4818 in Samba which this routine can run into */
4821 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4822 __u64 size
, bool SetAllocation
,
4823 const struct nls_table
*nls_codepage
, int remap
)
4825 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4826 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4827 struct file_end_of_file_info
*parm_data
;
4830 int bytes_returned
= 0;
4831 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4833 cFYI(1, "In SetEOF");
4835 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4840 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4842 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4843 PATH_MAX
, nls_codepage
, remap
);
4844 name_len
++; /* trailing null */
4846 } else { /* BB improve the check for buffer overruns BB */
4847 name_len
= strnlen(fileName
, PATH_MAX
);
4848 name_len
++; /* trailing null */
4849 strncpy(pSMB
->FileName
, fileName
, name_len
);
4851 params
= 6 + name_len
;
4852 data_count
= sizeof(struct file_end_of_file_info
);
4853 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4854 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4855 pSMB
->MaxSetupCount
= 0;
4859 pSMB
->Reserved2
= 0;
4860 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4861 InformationLevel
) - 4;
4862 offset
= param_offset
+ params
;
4863 if (SetAllocation
) {
4864 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4865 pSMB
->InformationLevel
=
4866 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4868 pSMB
->InformationLevel
=
4869 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4870 } else /* Set File Size */ {
4871 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4872 pSMB
->InformationLevel
=
4873 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4875 pSMB
->InformationLevel
=
4876 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4880 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4882 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4883 pSMB
->DataOffset
= cpu_to_le16(offset
);
4884 pSMB
->SetupCount
= 1;
4885 pSMB
->Reserved3
= 0;
4886 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4887 byte_count
= 3 /* pad */ + params
+ data_count
;
4888 pSMB
->DataCount
= cpu_to_le16(data_count
);
4889 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4890 pSMB
->ParameterCount
= cpu_to_le16(params
);
4891 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4892 pSMB
->Reserved4
= 0;
4893 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4894 parm_data
->FileSize
= cpu_to_le64(size
);
4895 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4896 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4897 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4899 cFYI(1, "SetPathInfo (file size) returned %d", rc
);
4901 cifs_buf_release(pSMB
);
4910 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4911 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4913 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4914 struct file_end_of_file_info
*parm_data
;
4916 __u16 params
, param_offset
, offset
, byte_count
, count
;
4918 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4920 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4925 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4926 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4929 pSMB
->MaxSetupCount
= 0;
4933 pSMB
->Reserved2
= 0;
4934 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4935 offset
= param_offset
+ params
;
4937 count
= sizeof(struct file_end_of_file_info
);
4938 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4939 /* BB find exact max SMB PDU from sess structure BB */
4940 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4941 pSMB
->SetupCount
= 1;
4942 pSMB
->Reserved3
= 0;
4943 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4944 byte_count
= 3 /* pad */ + params
+ count
;
4945 pSMB
->DataCount
= cpu_to_le16(count
);
4946 pSMB
->ParameterCount
= cpu_to_le16(params
);
4947 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4948 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4949 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4951 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4953 pSMB
->DataOffset
= cpu_to_le16(offset
);
4954 parm_data
->FileSize
= cpu_to_le64(size
);
4956 if (SetAllocation
) {
4957 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4958 pSMB
->InformationLevel
=
4959 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4961 pSMB
->InformationLevel
=
4962 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4963 } else /* Set File Size */ {
4964 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4965 pSMB
->InformationLevel
=
4966 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4968 pSMB
->InformationLevel
=
4969 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4971 pSMB
->Reserved4
= 0;
4972 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4973 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4974 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4976 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc
);
4979 /* Note: On -EAGAIN error only caller can retry on handle based calls
4980 since file handle passed in no longer valid */
4985 /* Some legacy servers such as NT4 require that the file times be set on
4986 an open handle, rather than by pathname - this is awkward due to
4987 potential access conflicts on the open, but it is unavoidable for these
4988 old servers since the only other choice is to go from 100 nanosecond DCE
4989 time and resort to the original setpathinfo level which takes the ancient
4990 DOS time format with 2 second granularity */
4992 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
4993 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
4995 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4998 __u16 params
, param_offset
, offset
, byte_count
, count
;
5000 cFYI(1, "Set Times (via SetFileInfo)");
5001 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5006 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5007 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5010 pSMB
->MaxSetupCount
= 0;
5014 pSMB
->Reserved2
= 0;
5015 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5016 offset
= param_offset
+ params
;
5018 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5020 count
= sizeof(FILE_BASIC_INFO
);
5021 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5022 /* BB find max SMB PDU from sess */
5023 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5024 pSMB
->SetupCount
= 1;
5025 pSMB
->Reserved3
= 0;
5026 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5027 byte_count
= 3 /* pad */ + params
+ count
;
5028 pSMB
->DataCount
= cpu_to_le16(count
);
5029 pSMB
->ParameterCount
= cpu_to_le16(params
);
5030 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5031 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5032 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5033 pSMB
->DataOffset
= cpu_to_le16(offset
);
5035 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5036 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5038 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5039 pSMB
->Reserved4
= 0;
5040 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5041 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5042 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5043 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5045 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5047 /* Note: On -EAGAIN error only caller can retry on handle based calls
5048 since file handle passed in no longer valid */
5054 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
5055 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
5057 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5060 __u16 params
, param_offset
, offset
, byte_count
, count
;
5062 cFYI(1, "Set File Disposition (via SetFileInfo)");
5063 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5068 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5069 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5072 pSMB
->MaxSetupCount
= 0;
5076 pSMB
->Reserved2
= 0;
5077 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5078 offset
= param_offset
+ params
;
5080 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5083 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5084 /* BB find max SMB PDU from sess */
5085 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5086 pSMB
->SetupCount
= 1;
5087 pSMB
->Reserved3
= 0;
5088 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5089 byte_count
= 3 /* pad */ + params
+ count
;
5090 pSMB
->DataCount
= cpu_to_le16(count
);
5091 pSMB
->ParameterCount
= cpu_to_le16(params
);
5092 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5093 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5094 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5095 pSMB
->DataOffset
= cpu_to_le16(offset
);
5097 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5098 pSMB
->Reserved4
= 0;
5099 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5100 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5101 *data_offset
= delete_file
? 1 : 0;
5102 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5104 cFYI(1, "Send error in SetFileDisposition = %d", rc
);
5110 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
5111 const char *fileName
, const FILE_BASIC_INFO
*data
,
5112 const struct nls_table
*nls_codepage
, int remap
)
5114 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5115 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5118 int bytes_returned
= 0;
5120 __u16 params
, param_offset
, offset
, byte_count
, count
;
5122 cFYI(1, "In SetTimes");
5125 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5130 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5132 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5133 PATH_MAX
, nls_codepage
, remap
);
5134 name_len
++; /* trailing null */
5136 } else { /* BB improve the check for buffer overruns BB */
5137 name_len
= strnlen(fileName
, PATH_MAX
);
5138 name_len
++; /* trailing null */
5139 strncpy(pSMB
->FileName
, fileName
, name_len
);
5142 params
= 6 + name_len
;
5143 count
= sizeof(FILE_BASIC_INFO
);
5144 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5145 /* BB find max SMB PDU from sess structure BB */
5146 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5147 pSMB
->MaxSetupCount
= 0;
5151 pSMB
->Reserved2
= 0;
5152 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5153 InformationLevel
) - 4;
5154 offset
= param_offset
+ params
;
5155 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5156 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5157 pSMB
->DataOffset
= cpu_to_le16(offset
);
5158 pSMB
->SetupCount
= 1;
5159 pSMB
->Reserved3
= 0;
5160 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5161 byte_count
= 3 /* pad */ + params
+ count
;
5163 pSMB
->DataCount
= cpu_to_le16(count
);
5164 pSMB
->ParameterCount
= cpu_to_le16(params
);
5165 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5166 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5167 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5168 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5170 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5171 pSMB
->Reserved4
= 0;
5172 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5173 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5174 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5175 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5176 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5178 cFYI(1, "SetPathInfo (times) returned %d", rc
);
5180 cifs_buf_release(pSMB
);
5188 /* Can not be used to set time stamps yet (due to old DOS time format) */
5189 /* Can be used to set attributes */
5190 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5191 handling it anyway and NT4 was what we thought it would be needed for
5192 Do not delete it until we prove whether needed for Win9x though */
5194 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5195 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5197 SETATTR_REQ
*pSMB
= NULL
;
5198 SETATTR_RSP
*pSMBr
= NULL
;
5203 cFYI(1, "In SetAttrLegacy");
5206 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5211 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5213 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5214 PATH_MAX
, nls_codepage
);
5215 name_len
++; /* trailing null */
5217 } else { /* BB improve the check for buffer overruns BB */
5218 name_len
= strnlen(fileName
, PATH_MAX
);
5219 name_len
++; /* trailing null */
5220 strncpy(pSMB
->fileName
, fileName
, name_len
);
5222 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5223 pSMB
->BufferFormat
= 0x04;
5224 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5225 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5226 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5227 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5229 cFYI(1, "Error in LegacySetAttr = %d", rc
);
5231 cifs_buf_release(pSMB
);
5234 goto SetAttrLgcyRetry
;
5238 #endif /* temporarily unneeded SetAttr legacy function */
5241 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5242 const struct cifs_unix_set_info_args
*args
)
5244 u64 mode
= args
->mode
;
5247 * Samba server ignores set of file size to zero due to bugs in some
5248 * older clients, but we should be precise - we use SetFileSize to
5249 * set file size and do not want to truncate file size to zero
5250 * accidently as happened on one Samba server beta by putting
5251 * zero instead of -1 here
5253 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5254 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5255 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5256 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5257 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5258 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5259 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5260 /* better to leave device as zero when it is */
5261 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5262 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5263 data_offset
->Permissions
= cpu_to_le64(mode
);
5266 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5267 else if (S_ISDIR(mode
))
5268 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5269 else if (S_ISLNK(mode
))
5270 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5271 else if (S_ISCHR(mode
))
5272 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5273 else if (S_ISBLK(mode
))
5274 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5275 else if (S_ISFIFO(mode
))
5276 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5277 else if (S_ISSOCK(mode
))
5278 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5282 CIFSSMBUnixSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
5283 const struct cifs_unix_set_info_args
*args
,
5284 u16 fid
, u32 pid_of_opener
)
5286 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5287 FILE_UNIX_BASIC_INFO
*data_offset
;
5289 u16 params
, param_offset
, offset
, byte_count
, count
;
5291 cFYI(1, "Set Unix Info (via SetFileInfo)");
5292 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5297 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5298 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5301 pSMB
->MaxSetupCount
= 0;
5305 pSMB
->Reserved2
= 0;
5306 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5307 offset
= param_offset
+ params
;
5309 data_offset
= (FILE_UNIX_BASIC_INFO
*)
5310 ((char *)(&pSMB
->hdr
.Protocol
) + offset
);
5311 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5313 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5314 /* BB find max SMB PDU from sess */
5315 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5316 pSMB
->SetupCount
= 1;
5317 pSMB
->Reserved3
= 0;
5318 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5319 byte_count
= 3 /* pad */ + params
+ count
;
5320 pSMB
->DataCount
= cpu_to_le16(count
);
5321 pSMB
->ParameterCount
= cpu_to_le16(params
);
5322 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5323 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5324 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5325 pSMB
->DataOffset
= cpu_to_le16(offset
);
5327 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5328 pSMB
->Reserved4
= 0;
5329 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5330 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5332 cifs_fill_unix_set_info(data_offset
, args
);
5334 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5336 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5338 /* Note: On -EAGAIN error only caller can retry on handle based calls
5339 since file handle passed in no longer valid */
5345 CIFSSMBUnixSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5346 const struct cifs_unix_set_info_args
*args
,
5347 const struct nls_table
*nls_codepage
, int remap
)
5349 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5350 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5353 int bytes_returned
= 0;
5354 FILE_UNIX_BASIC_INFO
*data_offset
;
5355 __u16 params
, param_offset
, offset
, count
, byte_count
;
5357 cFYI(1, "In SetUID/GID/Mode");
5359 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5364 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5366 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5367 PATH_MAX
, nls_codepage
, remap
);
5368 name_len
++; /* trailing null */
5370 } else { /* BB improve the check for buffer overruns BB */
5371 name_len
= strnlen(fileName
, PATH_MAX
);
5372 name_len
++; /* trailing null */
5373 strncpy(pSMB
->FileName
, fileName
, name_len
);
5376 params
= 6 + name_len
;
5377 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5378 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5379 /* BB find max SMB PDU from sess structure BB */
5380 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5381 pSMB
->MaxSetupCount
= 0;
5385 pSMB
->Reserved2
= 0;
5386 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5387 InformationLevel
) - 4;
5388 offset
= param_offset
+ params
;
5390 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5392 memset(data_offset
, 0, count
);
5393 pSMB
->DataOffset
= cpu_to_le16(offset
);
5394 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5395 pSMB
->SetupCount
= 1;
5396 pSMB
->Reserved3
= 0;
5397 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5398 byte_count
= 3 /* pad */ + params
+ count
;
5399 pSMB
->ParameterCount
= cpu_to_le16(params
);
5400 pSMB
->DataCount
= cpu_to_le16(count
);
5401 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5402 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5403 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5404 pSMB
->Reserved4
= 0;
5405 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5407 cifs_fill_unix_set_info(data_offset
, args
);
5409 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5410 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5411 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5413 cFYI(1, "SetPathInfo (perms) returned %d", rc
);
5415 cifs_buf_release(pSMB
);
5421 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5422 const int notify_subdirs
, const __u16 netfid
,
5423 __u32 filter
, struct file
*pfile
, int multishot
,
5424 const struct nls_table
*nls_codepage
)
5427 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5428 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5429 struct dir_notify_req
*dnotify_req
;
5432 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid
);
5433 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5438 pSMB
->TotalParameterCount
= 0 ;
5439 pSMB
->TotalDataCount
= 0;
5440 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5441 /* BB find exact data count max from sess structure BB */
5442 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5443 /* BB VERIFY verify which is correct for above BB */
5444 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5445 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5447 pSMB
->MaxSetupCount
= 4;
5449 pSMB
->ParameterOffset
= 0;
5450 pSMB
->DataCount
= 0;
5451 pSMB
->DataOffset
= 0;
5452 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5453 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5454 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5456 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5457 pSMB
->Reserved2
= 0;
5458 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5459 pSMB
->Fid
= netfid
; /* file handle always le */
5460 pSMB
->ByteCount
= 0;
5462 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5463 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5466 cFYI(1, "Error in Notify = %d", rc
);
5468 /* Add file to outstanding requests */
5469 /* BB change to kmem cache alloc */
5470 dnotify_req
= kmalloc(
5471 sizeof(struct dir_notify_req
),
5474 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5475 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5476 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5477 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5478 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5479 dnotify_req
->netfid
= netfid
;
5480 dnotify_req
->pfile
= pfile
;
5481 dnotify_req
->filter
= filter
;
5482 dnotify_req
->multishot
= multishot
;
5483 spin_lock(&GlobalMid_Lock
);
5484 list_add_tail(&dnotify_req
->lhead
,
5485 &GlobalDnotifyReqList
);
5486 spin_unlock(&GlobalMid_Lock
);
5490 cifs_buf_release(pSMB
);
5494 #ifdef CONFIG_CIFS_XATTR
5496 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5497 * function used by listxattr and getxattr type calls. When ea_name is set,
5498 * it looks for that attribute name and stuffs that value into the EAData
5499 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5500 * buffer. In both cases, the return value is either the length of the
5501 * resulting data or a negative error code. If EAData is a NULL pointer then
5502 * the data isn't copied to it, but the length is returned.
5505 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5506 const unsigned char *searchName
, const unsigned char *ea_name
,
5507 char *EAData
, size_t buf_size
,
5508 const struct nls_table
*nls_codepage
, int remap
)
5510 /* BB assumes one setup word */
5511 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5512 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5516 struct fealist
*ea_response_data
;
5517 struct fea
*temp_fea
;
5520 __u16 params
, byte_count
, data_offset
;
5522 cFYI(1, "In Query All EAs path %s", searchName
);
5524 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5529 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5531 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5532 PATH_MAX
, nls_codepage
, remap
);
5533 list_len
++; /* trailing null */
5535 } else { /* BB improve the check for buffer overruns BB */
5536 list_len
= strnlen(searchName
, PATH_MAX
);
5537 list_len
++; /* trailing null */
5538 strncpy(pSMB
->FileName
, searchName
, list_len
);
5541 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
5542 pSMB
->TotalDataCount
= 0;
5543 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5544 /* BB find exact max SMB PDU from sess structure BB */
5545 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
5546 pSMB
->MaxSetupCount
= 0;
5550 pSMB
->Reserved2
= 0;
5551 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5552 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5553 pSMB
->DataCount
= 0;
5554 pSMB
->DataOffset
= 0;
5555 pSMB
->SetupCount
= 1;
5556 pSMB
->Reserved3
= 0;
5557 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5558 byte_count
= params
+ 1 /* pad */ ;
5559 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5560 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5561 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5562 pSMB
->Reserved4
= 0;
5563 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5564 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5566 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5567 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5569 cFYI(1, "Send error in QueryAllEAs = %d", rc
);
5574 /* BB also check enough total bytes returned */
5575 /* BB we need to improve the validity checking
5576 of these trans2 responses */
5578 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5579 if (rc
|| (pSMBr
->ByteCount
< 4)) {
5580 rc
= -EIO
; /* bad smb */
5584 /* check that length of list is not more than bcc */
5585 /* check that each entry does not go beyond length
5587 /* check that each element of each entry does not
5588 go beyond end of list */
5589 /* validate_trans2_offsets() */
5590 /* BB check if start of smb + data_offset > &bcc+ bcc */
5592 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5593 ea_response_data
= (struct fealist
*)
5594 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
5596 list_len
= le32_to_cpu(ea_response_data
->list_len
);
5597 cFYI(1, "ea length %d", list_len
);
5598 if (list_len
<= 8) {
5599 cFYI(1, "empty EA list returned from server");
5603 /* make sure list_len doesn't go past end of SMB */
5604 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + get_bcc(&pSMBr
->hdr
);
5605 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
5606 cFYI(1, "EA list appears to go beyond SMB");
5611 /* account for ea list len */
5613 temp_fea
= ea_response_data
->list
;
5614 temp_ptr
= (char *)temp_fea
;
5615 while (list_len
> 0) {
5616 unsigned int name_len
;
5621 /* make sure we can read name_len and value_len */
5623 cFYI(1, "EA entry goes beyond length of list");
5628 name_len
= temp_fea
->name_len
;
5629 value_len
= le16_to_cpu(temp_fea
->value_len
);
5630 list_len
-= name_len
+ 1 + value_len
;
5632 cFYI(1, "EA entry goes beyond length of list");
5638 if (strncmp(ea_name
, temp_ptr
, name_len
) == 0) {
5639 temp_ptr
+= name_len
+ 1;
5643 if ((size_t)value_len
> buf_size
) {
5647 memcpy(EAData
, temp_ptr
, value_len
);
5651 /* account for prefix user. and trailing null */
5652 rc
+= (5 + 1 + name_len
);
5653 if (rc
< (int) buf_size
) {
5654 memcpy(EAData
, "user.", 5);
5656 memcpy(EAData
, temp_ptr
, name_len
);
5658 /* null terminate name */
5661 } else if (buf_size
== 0) {
5662 /* skip copy - calc size only */
5664 /* stop before overrun buffer */
5669 temp_ptr
+= name_len
+ 1 + value_len
;
5670 temp_fea
= (struct fea
*)temp_ptr
;
5673 /* didn't find the named attribute */
5678 cifs_buf_release(pSMB
);
5686 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5687 const char *ea_name
, const void *ea_value
,
5688 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5691 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5692 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5693 struct fealist
*parm_data
;
5696 int bytes_returned
= 0;
5697 __u16 params
, param_offset
, byte_count
, offset
, count
;
5699 cFYI(1, "In SetEA");
5701 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5706 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5708 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5709 PATH_MAX
, nls_codepage
, remap
);
5710 name_len
++; /* trailing null */
5712 } else { /* BB improve the check for buffer overruns BB */
5713 name_len
= strnlen(fileName
, PATH_MAX
);
5714 name_len
++; /* trailing null */
5715 strncpy(pSMB
->FileName
, fileName
, name_len
);
5718 params
= 6 + name_len
;
5720 /* done calculating parms using name_len of file name,
5721 now use name_len to calculate length of ea name
5722 we are going to create in the inode xattrs */
5723 if (ea_name
== NULL
)
5726 name_len
= strnlen(ea_name
, 255);
5728 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5729 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5730 /* BB find max SMB PDU from sess */
5731 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5732 pSMB
->MaxSetupCount
= 0;
5736 pSMB
->Reserved2
= 0;
5737 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5738 InformationLevel
) - 4;
5739 offset
= param_offset
+ params
;
5740 pSMB
->InformationLevel
=
5741 cpu_to_le16(SMB_SET_FILE_EA
);
5744 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5746 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5747 pSMB
->DataOffset
= cpu_to_le16(offset
);
5748 pSMB
->SetupCount
= 1;
5749 pSMB
->Reserved3
= 0;
5750 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5751 byte_count
= 3 /* pad */ + params
+ count
;
5752 pSMB
->DataCount
= cpu_to_le16(count
);
5753 parm_data
->list_len
= cpu_to_le32(count
);
5754 parm_data
->list
[0].EA_flags
= 0;
5755 /* we checked above that name len is less than 255 */
5756 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5757 /* EA names are always ASCII */
5759 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5760 parm_data
->list
[0].name
[name_len
] = 0;
5761 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5762 /* caller ensures that ea_value_len is less than 64K but
5763 we need to ensure that it fits within the smb */
5765 /*BB add length check to see if it would fit in
5766 negotiated SMB buffer size BB */
5767 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5769 memcpy(parm_data
->list
[0].name
+name_len
+1,
5770 ea_value
, ea_value_len
);
5772 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5773 pSMB
->ParameterCount
= cpu_to_le16(params
);
5774 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5775 pSMB
->Reserved4
= 0;
5776 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5777 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5778 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5779 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5781 cFYI(1, "SetPathInfo (EA) returned %d", rc
);
5783 cifs_buf_release(pSMB
);