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",
139 if (ses
->status
== CifsExiting
)
143 * Give demultiplex thread up to 10 seconds to reconnect, should be
144 * greater than cifs socket timeout which is 7 seconds
146 while (server
->tcpStatus
== CifsNeedReconnect
) {
147 wait_event_interruptible_timeout(server
->response_q
,
148 (server
->tcpStatus
== CifsGood
), 10 * HZ
);
150 /* is TCP session is reestablished now ?*/
151 if (server
->tcpStatus
!= CifsNeedReconnect
)
155 * on "soft" mounts we wait once. Hard mounts keep
156 * retrying until process is killed or server comes
159 if (!tcon
->retry
|| ses
->status
== CifsExiting
) {
160 cFYI(1, "gave up waiting on reconnect in smb_init");
165 if (!ses
->need_reconnect
&& !tcon
->need_reconnect
)
168 nls_codepage
= load_nls_default();
171 * need to prevent multiple threads trying to simultaneously
172 * reconnect the same SMB session
174 mutex_lock(&ses
->session_mutex
);
175 rc
= cifs_negotiate_protocol(0, ses
);
176 if (rc
== 0 && ses
->need_reconnect
)
177 rc
= cifs_setup_session(0, ses
, nls_codepage
);
179 /* do we need to reconnect tcon? */
180 if (rc
|| !tcon
->need_reconnect
) {
181 mutex_unlock(&ses
->session_mutex
);
185 mark_open_files_invalid(tcon
);
186 rc
= CIFSTCon(0, ses
, tcon
->treeName
, tcon
, nls_codepage
);
187 mutex_unlock(&ses
->session_mutex
);
188 cFYI(1, "reconnect tcon rc = %d", rc
);
194 * FIXME: check if wsize needs updated due to negotiated smb buffer
197 atomic_inc(&tconInfoReconnectCount
);
199 /* tell server Unix caps we support */
200 if (ses
->capabilities
& CAP_UNIX
)
201 reset_cifs_unix_caps(0, tcon
, NULL
, NULL
);
204 * Removed call to reopen open files here. It is safer (and faster) to
205 * reopen files one at a time as needed in read and write.
207 * FIXME: what about file locks? don't we need to reclaim them ASAP?
212 * Check if handle based operation so we know whether we can continue
213 * or not without returning to caller to reset file handle
215 switch (smb_command
) {
216 case SMB_COM_READ_ANDX
:
217 case SMB_COM_WRITE_ANDX
:
219 case SMB_COM_FIND_CLOSE2
:
220 case SMB_COM_LOCKING_ANDX
:
224 unload_nls(nls_codepage
);
228 /* Allocate and return pointer to an SMB request buffer, and set basic
229 SMB information in the SMB header. If the return code is zero, this
230 function must have filled in request_buf pointer */
232 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
237 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
241 *request_buf
= cifs_small_buf_get();
242 if (*request_buf
== NULL
) {
243 /* BB should we add a retry in here if not a writepage? */
247 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
251 cifs_stats_inc(&tcon
->num_smbs_sent
);
257 small_smb_init_no_tc(const int smb_command
, const int wct
,
258 struct cifsSesInfo
*ses
, void **request_buf
)
261 struct smb_hdr
*buffer
;
263 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
267 buffer
= (struct smb_hdr
*)*request_buf
;
268 buffer
->Mid
= GetNextMid(ses
->server
);
269 if (ses
->capabilities
& CAP_UNICODE
)
270 buffer
->Flags2
|= SMBFLG2_UNICODE
;
271 if (ses
->capabilities
& CAP_STATUS32
)
272 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
274 /* uid, tid can stay at zero as set in header assemble */
276 /* BB add support for turning on the signing when
277 this function is used after 1st of session setup requests */
282 /* If the return code is zero, this function must fill in request_buf pointer */
284 __smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
285 void **request_buf
, void **response_buf
)
287 *request_buf
= cifs_buf_get();
288 if (*request_buf
== NULL
) {
289 /* BB should we add a retry in here if not a writepage? */
292 /* Although the original thought was we needed the response buf for */
293 /* potential retries of smb operations it turns out we can determine */
294 /* from the mid flags when the request buffer can be resent without */
295 /* having to use a second distinct buffer for the response */
297 *response_buf
= *request_buf
;
299 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
303 cifs_stats_inc(&tcon
->num_smbs_sent
);
308 /* If the return code is zero, this function must fill in request_buf pointer */
310 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
311 void **request_buf
, void **response_buf
)
315 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
319 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
323 smb_init_no_reconnect(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
324 void **request_buf
, void **response_buf
)
326 if (tcon
->ses
->need_reconnect
|| tcon
->need_reconnect
)
329 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
332 static int validate_t2(struct smb_t2_rsp
*pSMB
)
334 unsigned int total_size
;
336 /* check for plausible wct */
337 if (pSMB
->hdr
.WordCount
< 10)
340 /* check for parm and data offset going beyond end of smb */
341 if (get_unaligned_le16(&pSMB
->t2_rsp
.ParameterOffset
) > 1024 ||
342 get_unaligned_le16(&pSMB
->t2_rsp
.DataOffset
) > 1024)
345 /* check that bcc is at least as big as parms + data */
346 /* check that bcc is less than negotiated smb buffer */
347 total_size
= get_unaligned_le16(&pSMB
->t2_rsp
.ParameterCount
);
348 if (total_size
>= 512)
351 total_size
+= get_unaligned_le16(&pSMB
->t2_rsp
.DataCount
);
352 if (total_size
> get_bcc(&pSMB
->hdr
) ||
353 total_size
>= CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
)
358 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
359 sizeof(struct smb_t2_rsp
) + 16);
364 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
367 NEGOTIATE_RSP
*pSMBr
;
371 struct TCP_Server_Info
*server
;
373 unsigned int secFlags
;
376 server
= ses
->server
;
381 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
382 (void **) &pSMB
, (void **) &pSMBr
);
386 /* if any of auth flags (ie not sign or seal) are overriden use them */
387 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
388 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
389 else /* if override flags set only sign/seal OR them with global auth */
390 secFlags
= global_secflags
| ses
->overrideSecFlg
;
392 cFYI(1, "secFlags 0x%x", secFlags
);
394 pSMB
->hdr
.Mid
= GetNextMid(server
);
395 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
397 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
398 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
399 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
400 cFYI(1, "Kerberos only mechanism, enable extended security");
401 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
402 } else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
403 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
404 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
405 cFYI(1, "NTLMSSP only mechanism, enable extended security");
406 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
410 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
411 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
412 count
+= strlen(protocols
[i
].name
) + 1;
413 /* null at end of source and target buffers anyway */
415 pSMB
->hdr
.smb_buf_length
+= count
;
416 pSMB
->ByteCount
= cpu_to_le16(count
);
418 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
419 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
423 server
->dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
424 cFYI(1, "Dialect: %d", server
->dialect
);
425 /* Check wct = 1 error case */
426 if ((pSMBr
->hdr
.WordCount
< 13) || (server
->dialect
== BAD_PROT
)) {
427 /* core returns wct = 1, but we do not ask for core - otherwise
428 small wct just comes when dialect index is -1 indicating we
429 could not negotiate a common dialect */
432 #ifdef CONFIG_CIFS_WEAK_PW_HASH
433 } else if ((pSMBr
->hdr
.WordCount
== 13)
434 && ((server
->dialect
== LANMAN_PROT
)
435 || (server
->dialect
== LANMAN2_PROT
))) {
437 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
439 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
440 (secFlags
& CIFSSEC_MAY_PLNTXT
))
441 server
->secType
= LANMAN
;
443 cERROR(1, "mount failed weak security disabled"
444 " in /proc/fs/cifs/SecurityFlags");
448 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
449 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
450 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
451 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
452 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
453 /* even though we do not use raw we might as well set this
454 accurately, in case we ever find a need for it */
455 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
456 server
->max_rw
= 0xFF00;
457 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
459 server
->max_rw
= 0;/* do not need to use raw anyway */
460 server
->capabilities
= CAP_MPX_MODE
;
462 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
464 /* OS/2 often does not set timezone therefore
465 * we must use server time to calc time zone.
466 * Could deviate slightly from the right zone.
467 * Smallest defined timezone difference is 15 minutes
468 * (i.e. Nepal). Rounding up/down is done to match
471 int val
, seconds
, remain
, result
;
472 struct timespec ts
, utc
;
474 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
475 rsp
->SrvTime
.Time
, 0);
476 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
477 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
478 (int)(utc
.tv_sec
- ts
.tv_sec
));
479 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
481 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
482 remain
= seconds
% MIN_TZ_ADJ
;
483 if (remain
>= (MIN_TZ_ADJ
/ 2))
484 result
+= MIN_TZ_ADJ
;
487 server
->timeAdj
= result
;
489 server
->timeAdj
= (int)tmp
;
490 server
->timeAdj
*= 60; /* also in seconds */
492 cFYI(1, "server->timeAdj: %d seconds", server
->timeAdj
);
495 /* BB get server time for time conversions and add
496 code to use it and timezone since this is not UTC */
498 if (rsp
->EncryptionKeyLength
==
499 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
500 memcpy(ses
->server
->cryptkey
, rsp
->EncryptionKey
,
501 CIFS_CRYPTO_KEY_SIZE
);
502 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
503 rc
= -EIO
; /* need cryptkey unless plain text */
507 cFYI(1, "LANMAN negotiated");
508 /* we will not end up setting signing flags - as no signing
509 was in LANMAN and server did not return the flags on */
511 #else /* weak security disabled */
512 } else if (pSMBr
->hdr
.WordCount
== 13) {
513 cERROR(1, "mount failed, cifs module not built "
514 "with CIFS_WEAK_PW_HASH support");
516 #endif /* WEAK_PW_HASH */
518 } else if (pSMBr
->hdr
.WordCount
!= 17) {
523 /* else wct == 17 NTLM */
524 server
->secMode
= pSMBr
->SecurityMode
;
525 if ((server
->secMode
& SECMODE_USER
) == 0)
526 cFYI(1, "share mode security");
528 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
529 #ifdef CONFIG_CIFS_WEAK_PW_HASH
530 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
531 #endif /* CIFS_WEAK_PW_HASH */
532 cERROR(1, "Server requests plain text password"
533 " but client support disabled");
535 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
536 server
->secType
= NTLMv2
;
537 else if (secFlags
& CIFSSEC_MAY_NTLM
)
538 server
->secType
= NTLM
;
539 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
540 server
->secType
= NTLMv2
;
541 else if (secFlags
& CIFSSEC_MAY_KRB5
)
542 server
->secType
= Kerberos
;
543 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
544 server
->secType
= RawNTLMSSP
;
545 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
546 server
->secType
= LANMAN
;
547 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
548 else if (secFlags & CIFSSEC_MAY_PLNTXT)
553 cERROR(1, "Invalid security type");
556 /* else ... any others ...? */
558 /* one byte, so no need to convert this or EncryptionKeyLen from
560 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
561 /* probably no need to store and check maxvcs */
562 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
563 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
564 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
565 cFYI(DBG2
, "Max buf = %d", ses
->server
->maxBuf
);
566 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
567 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
568 server
->timeAdj
*= 60;
569 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
570 memcpy(ses
->server
->cryptkey
, pSMBr
->u
.EncryptionKey
,
571 CIFS_CRYPTO_KEY_SIZE
);
572 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
573 && (pSMBr
->EncryptionKeyLength
== 0)) {
574 /* decode security blob */
575 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
576 rc
= -EIO
; /* no crypt key only if plain text pwd */
580 /* BB might be helpful to save off the domain of server here */
582 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
583 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
584 count
= pSMBr
->ByteCount
;
589 spin_lock(&cifs_tcp_ses_lock
);
590 if (server
->srv_count
> 1) {
591 spin_unlock(&cifs_tcp_ses_lock
);
592 if (memcmp(server
->server_GUID
,
593 pSMBr
->u
.extended_response
.
595 cFYI(1, "server UID changed");
596 memcpy(server
->server_GUID
,
597 pSMBr
->u
.extended_response
.GUID
,
601 spin_unlock(&cifs_tcp_ses_lock
);
602 memcpy(server
->server_GUID
,
603 pSMBr
->u
.extended_response
.GUID
, 16);
607 server
->secType
= RawNTLMSSP
;
609 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
610 SecurityBlob
, count
- 16,
616 if (server
->secType
== Kerberos
) {
617 if (!server
->sec_kerberos
&&
618 !server
->sec_mskerberos
)
620 } else if (server
->secType
== RawNTLMSSP
) {
621 if (!server
->sec_ntlmssp
)
627 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
629 #ifdef CONFIG_CIFS_WEAK_PW_HASH
632 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
633 /* MUST_SIGN already includes the MAY_SIGN FLAG
634 so if this is zero it means that signing is disabled */
635 cFYI(1, "Signing disabled");
636 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
637 cERROR(1, "Server requires "
638 "packet signing to be enabled in "
639 "/proc/fs/cifs/SecurityFlags.");
643 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
644 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
645 /* signing required */
646 cFYI(1, "Must sign - secFlags 0x%x", secFlags
);
647 if ((server
->secMode
&
648 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
649 cERROR(1, "signing required but server lacks support");
652 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
654 /* signing optional ie CIFSSEC_MAY_SIGN */
655 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
657 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
661 cifs_buf_release(pSMB
);
663 cFYI(1, "negprot rc %d", rc
);
668 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
670 struct smb_hdr
*smb_buffer
;
673 cFYI(1, "In tree disconnect");
675 /* BB: do we need to check this? These should never be NULL. */
676 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
680 * No need to return error on this operation if tid invalidated and
681 * closed on server already e.g. due to tcp session crashing. Also,
682 * the tcon is no longer on the list, so no need to take lock before
685 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
688 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
689 (void **)&smb_buffer
);
693 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
695 cFYI(1, "Tree disconnect failed %d", rc
);
697 /* No need to return error on this operation if tid invalidated and
698 closed on server already e.g. due to tcp session crashing */
706 * This is a no-op for now. We're not really interested in the reply, but
707 * rather in the fact that the server sent one and that server->lstrp
710 * FIXME: maybe we should consider checking that the reply matches request?
713 cifs_echo_callback(struct mid_q_entry
*mid
)
715 struct TCP_Server_Info
*server
= mid
->callback_data
;
717 DeleteMidQEntry(mid
);
718 atomic_dec(&server
->inFlight
);
719 wake_up(&server
->request_q
);
723 CIFSSMBEcho(struct TCP_Server_Info
*server
)
728 cFYI(1, "In echo request");
730 rc
= small_smb_init(SMB_COM_ECHO
, 0, NULL
, (void **)&smb
);
734 /* set up echo request */
735 smb
->hdr
.Tid
= cpu_to_le16(0xffff);
736 smb
->hdr
.WordCount
= 1;
737 put_unaligned_le16(1, &smb
->EchoCount
);
738 put_bcc_le(1, &smb
->hdr
);
740 smb
->hdr
.smb_buf_length
+= 3;
742 rc
= cifs_call_async(server
, (struct smb_hdr
*)smb
,
743 cifs_echo_callback
, server
);
745 cFYI(1, "Echo request failed: %d", rc
);
747 cifs_small_buf_release(smb
);
753 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
755 LOGOFF_ANDX_REQ
*pSMB
;
758 cFYI(1, "In SMBLogoff for session disconnect");
761 * BB: do we need to check validity of ses and server? They should
762 * always be valid since we have an active reference. If not, that
763 * should probably be a BUG()
765 if (!ses
|| !ses
->server
)
768 mutex_lock(&ses
->session_mutex
);
769 if (ses
->need_reconnect
)
770 goto session_already_dead
; /* no need to send SMBlogoff if uid
771 already closed due to reconnect */
772 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
774 mutex_unlock(&ses
->session_mutex
);
778 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
780 if (ses
->server
->secMode
&
781 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
782 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
784 pSMB
->hdr
.Uid
= ses
->Suid
;
786 pSMB
->AndXCommand
= 0xFF;
787 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
788 session_already_dead
:
789 mutex_unlock(&ses
->session_mutex
);
791 /* if session dead then we do not need to do ulogoff,
792 since server closed smb session, no sense reporting
800 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
801 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
803 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
804 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
805 struct unlink_psx_rq
*pRqD
;
808 int bytes_returned
= 0;
809 __u16 params
, param_offset
, offset
, byte_count
;
811 cFYI(1, "In POSIX delete");
813 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
818 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
820 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
821 PATH_MAX
, nls_codepage
, remap
);
822 name_len
++; /* trailing null */
824 } else { /* BB add path length overrun check */
825 name_len
= strnlen(fileName
, PATH_MAX
);
826 name_len
++; /* trailing null */
827 strncpy(pSMB
->FileName
, fileName
, name_len
);
830 params
= 6 + name_len
;
831 pSMB
->MaxParameterCount
= cpu_to_le16(2);
832 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
833 pSMB
->MaxSetupCount
= 0;
838 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
839 InformationLevel
) - 4;
840 offset
= param_offset
+ params
;
842 /* Setup pointer to Request Data (inode type) */
843 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
844 pRqD
->type
= cpu_to_le16(type
);
845 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
846 pSMB
->DataOffset
= cpu_to_le16(offset
);
847 pSMB
->SetupCount
= 1;
849 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
850 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
852 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
853 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
854 pSMB
->ParameterCount
= cpu_to_le16(params
);
855 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
856 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
858 pSMB
->hdr
.smb_buf_length
+= byte_count
;
859 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
860 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
861 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
863 cFYI(1, "Posix delete returned %d", rc
);
864 cifs_buf_release(pSMB
);
866 cifs_stats_inc(&tcon
->num_deletes
);
875 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
876 const struct nls_table
*nls_codepage
, int remap
)
878 DELETE_FILE_REQ
*pSMB
= NULL
;
879 DELETE_FILE_RSP
*pSMBr
= NULL
;
885 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
890 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
892 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
893 PATH_MAX
, nls_codepage
, remap
);
894 name_len
++; /* trailing null */
896 } else { /* BB improve check for buffer overruns BB */
897 name_len
= strnlen(fileName
, PATH_MAX
);
898 name_len
++; /* trailing null */
899 strncpy(pSMB
->fileName
, fileName
, name_len
);
901 pSMB
->SearchAttributes
=
902 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
903 pSMB
->BufferFormat
= 0x04;
904 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
905 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
906 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
907 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
908 cifs_stats_inc(&tcon
->num_deletes
);
910 cFYI(1, "Error in RMFile = %d", rc
);
912 cifs_buf_release(pSMB
);
920 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
921 const struct nls_table
*nls_codepage
, int remap
)
923 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
924 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
929 cFYI(1, "In CIFSSMBRmDir");
931 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
936 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
937 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
938 PATH_MAX
, nls_codepage
, remap
);
939 name_len
++; /* trailing null */
941 } else { /* BB improve check for buffer overruns BB */
942 name_len
= strnlen(dirName
, PATH_MAX
);
943 name_len
++; /* trailing null */
944 strncpy(pSMB
->DirName
, dirName
, name_len
);
947 pSMB
->BufferFormat
= 0x04;
948 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
949 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
950 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
951 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
952 cifs_stats_inc(&tcon
->num_rmdirs
);
954 cFYI(1, "Error in RMDir = %d", rc
);
956 cifs_buf_release(pSMB
);
963 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
964 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
967 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
968 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
972 cFYI(1, "In CIFSSMBMkDir");
974 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
979 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
980 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
981 PATH_MAX
, nls_codepage
, remap
);
982 name_len
++; /* trailing null */
984 } else { /* BB improve check for buffer overruns BB */
985 name_len
= strnlen(name
, PATH_MAX
);
986 name_len
++; /* trailing null */
987 strncpy(pSMB
->DirName
, name
, name_len
);
990 pSMB
->BufferFormat
= 0x04;
991 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
992 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
993 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
994 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
995 cifs_stats_inc(&tcon
->num_mkdirs
);
997 cFYI(1, "Error in Mkdir = %d", rc
);
999 cifs_buf_release(pSMB
);
1006 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1007 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1008 __u32
*pOplock
, const char *name
,
1009 const struct nls_table
*nls_codepage
, int remap
)
1011 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1012 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1015 int bytes_returned
= 0;
1016 __u16 params
, param_offset
, offset
, byte_count
, count
;
1017 OPEN_PSX_REQ
*pdata
;
1018 OPEN_PSX_RSP
*psx_rsp
;
1020 cFYI(1, "In POSIX Create");
1022 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1027 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1029 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1030 PATH_MAX
, nls_codepage
, remap
);
1031 name_len
++; /* trailing null */
1033 } else { /* BB improve the check for buffer overruns BB */
1034 name_len
= strnlen(name
, PATH_MAX
);
1035 name_len
++; /* trailing null */
1036 strncpy(pSMB
->FileName
, name
, name_len
);
1039 params
= 6 + name_len
;
1040 count
= sizeof(OPEN_PSX_REQ
);
1041 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1042 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1043 pSMB
->MaxSetupCount
= 0;
1047 pSMB
->Reserved2
= 0;
1048 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1049 InformationLevel
) - 4;
1050 offset
= param_offset
+ params
;
1051 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1052 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1053 pdata
->Permissions
= cpu_to_le64(mode
);
1054 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1055 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1056 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1057 pSMB
->DataOffset
= cpu_to_le16(offset
);
1058 pSMB
->SetupCount
= 1;
1059 pSMB
->Reserved3
= 0;
1060 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1061 byte_count
= 3 /* pad */ + params
+ count
;
1063 pSMB
->DataCount
= cpu_to_le16(count
);
1064 pSMB
->ParameterCount
= cpu_to_le16(params
);
1065 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1066 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1067 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1068 pSMB
->Reserved4
= 0;
1069 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1070 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1071 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1072 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1074 cFYI(1, "Posix create returned %d", rc
);
1075 goto psx_create_err
;
1078 cFYI(1, "copying inode info");
1079 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1081 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1082 rc
= -EIO
; /* bad smb */
1083 goto psx_create_err
;
1086 /* copy return information to pRetData */
1087 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1088 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1090 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1092 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1093 /* Let caller know file was created so we can set the mode. */
1094 /* Do we care about the CreateAction in any other cases? */
1095 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1096 *pOplock
|= CIFS_CREATE_ACTION
;
1097 /* check to make sure response data is there */
1098 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1099 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1100 cFYI(DBG2
, "unknown type");
1102 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1103 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1104 cERROR(1, "Open response data too small");
1105 pRetData
->Type
= cpu_to_le32(-1);
1106 goto psx_create_err
;
1108 memcpy((char *) pRetData
,
1109 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1110 sizeof(FILE_UNIX_BASIC_INFO
));
1114 cifs_buf_release(pSMB
);
1116 if (posix_flags
& SMB_O_DIRECTORY
)
1117 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1119 cifs_stats_inc(&tcon
->num_posixopens
);
1127 static __u16
convert_disposition(int disposition
)
1131 switch (disposition
) {
1132 case FILE_SUPERSEDE
:
1133 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1136 ofun
= SMBOPEN_OAPPEND
;
1139 ofun
= SMBOPEN_OCREATE
;
1142 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1144 case FILE_OVERWRITE
:
1145 ofun
= SMBOPEN_OTRUNC
;
1147 case FILE_OVERWRITE_IF
:
1148 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1151 cFYI(1, "unknown disposition %d", disposition
);
1152 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1158 access_flags_to_smbopen_mode(const int access_flags
)
1160 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1162 if (masked_flags
== GENERIC_READ
)
1163 return SMBOPEN_READ
;
1164 else if (masked_flags
== GENERIC_WRITE
)
1165 return SMBOPEN_WRITE
;
1167 /* just go for read/write */
1168 return SMBOPEN_READWRITE
;
1172 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1173 const char *fileName
, const int openDisposition
,
1174 const int access_flags
, const int create_options
, __u16
*netfid
,
1175 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1176 const struct nls_table
*nls_codepage
, int remap
)
1179 OPENX_REQ
*pSMB
= NULL
;
1180 OPENX_RSP
*pSMBr
= NULL
;
1186 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1191 pSMB
->AndXCommand
= 0xFF; /* none */
1193 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1194 count
= 1; /* account for one byte pad to word boundary */
1196 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1197 fileName
, PATH_MAX
, nls_codepage
, remap
);
1198 name_len
++; /* trailing null */
1200 } else { /* BB improve check for buffer overruns BB */
1201 count
= 0; /* no pad */
1202 name_len
= strnlen(fileName
, PATH_MAX
);
1203 name_len
++; /* trailing null */
1204 strncpy(pSMB
->fileName
, fileName
, name_len
);
1206 if (*pOplock
& REQ_OPLOCK
)
1207 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1208 else if (*pOplock
& REQ_BATCHOPLOCK
)
1209 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1211 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1212 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1213 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1214 /* set file as system file if special file such
1215 as fifo and server expecting SFU style and
1216 no Unix extensions */
1218 if (create_options
& CREATE_OPTION_SPECIAL
)
1219 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1220 else /* BB FIXME BB */
1221 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1223 if (create_options
& CREATE_OPTION_READONLY
)
1224 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1227 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1228 CREATE_OPTIONS_MASK); */
1229 /* BB FIXME END BB */
1231 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1232 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1234 pSMB
->hdr
.smb_buf_length
+= count
;
1236 pSMB
->ByteCount
= cpu_to_le16(count
);
1237 /* long_op set to 1 to allow for oplock break timeouts */
1238 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1239 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1240 cifs_stats_inc(&tcon
->num_opens
);
1242 cFYI(1, "Error in Open = %d", rc
);
1244 /* BB verify if wct == 15 */
1246 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1248 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1249 /* Let caller know file was created so we can set the mode. */
1250 /* Do we care about the CreateAction in any other cases? */
1252 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1253 *pOplock |= CIFS_CREATE_ACTION; */
1257 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1258 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1259 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1260 pfile_info
->ChangeTime
= 0; /* BB fixme */
1261 pfile_info
->Attributes
=
1262 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1263 /* the file_info buf is endian converted by caller */
1264 pfile_info
->AllocationSize
=
1265 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1266 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1267 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1268 pfile_info
->DeletePending
= 0;
1272 cifs_buf_release(pSMB
);
1279 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1280 const char *fileName
, const int openDisposition
,
1281 const int access_flags
, const int create_options
, __u16
*netfid
,
1282 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1283 const struct nls_table
*nls_codepage
, int remap
)
1286 OPEN_REQ
*pSMB
= NULL
;
1287 OPEN_RSP
*pSMBr
= NULL
;
1293 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1298 pSMB
->AndXCommand
= 0xFF; /* none */
1300 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1301 count
= 1; /* account for one byte pad to word boundary */
1303 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1304 fileName
, PATH_MAX
, nls_codepage
, remap
);
1305 name_len
++; /* trailing null */
1307 pSMB
->NameLength
= cpu_to_le16(name_len
);
1308 } else { /* BB improve check for buffer overruns BB */
1309 count
= 0; /* no pad */
1310 name_len
= strnlen(fileName
, PATH_MAX
);
1311 name_len
++; /* trailing null */
1312 pSMB
->NameLength
= cpu_to_le16(name_len
);
1313 strncpy(pSMB
->fileName
, fileName
, name_len
);
1315 if (*pOplock
& REQ_OPLOCK
)
1316 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1317 else if (*pOplock
& REQ_BATCHOPLOCK
)
1318 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1319 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1320 pSMB
->AllocationSize
= 0;
1321 /* set file as system file if special file such
1322 as fifo and server expecting SFU style and
1323 no Unix extensions */
1324 if (create_options
& CREATE_OPTION_SPECIAL
)
1325 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1327 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1329 /* XP does not handle ATTR_POSIX_SEMANTICS */
1330 /* but it helps speed up case sensitive checks for other
1331 servers such as Samba */
1332 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1333 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1335 if (create_options
& CREATE_OPTION_READONLY
)
1336 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1338 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1339 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1340 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1341 /* BB Expirement with various impersonation levels and verify */
1342 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1343 pSMB
->SecurityFlags
=
1344 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1347 pSMB
->hdr
.smb_buf_length
+= count
;
1349 pSMB
->ByteCount
= cpu_to_le16(count
);
1350 /* long_op set to 1 to allow for oplock break timeouts */
1351 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1352 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1353 cifs_stats_inc(&tcon
->num_opens
);
1355 cFYI(1, "Error in Open = %d", rc
);
1357 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1358 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1359 /* Let caller know file was created so we can set the mode. */
1360 /* Do we care about the CreateAction in any other cases? */
1361 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1362 *pOplock
|= CIFS_CREATE_ACTION
;
1364 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1365 36 /* CreationTime to Attributes */);
1366 /* the file_info buf is endian converted by caller */
1367 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1368 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1369 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1370 pfile_info
->DeletePending
= 0;
1374 cifs_buf_release(pSMB
);
1381 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1382 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1383 char **buf
, int *pbuf_type
)
1386 READ_REQ
*pSMB
= NULL
;
1387 READ_RSP
*pSMBr
= NULL
;
1388 char *pReadData
= NULL
;
1390 int resp_buf_type
= 0;
1393 cFYI(1, "Reading %d bytes on fid %d", count
, netfid
);
1394 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1397 wct
= 10; /* old style read */
1398 if ((lseek
>> 32) > 0) {
1399 /* can not handle this big offset for old */
1405 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1409 /* tcon and ses pointer are checked in smb_init */
1410 if (tcon
->ses
->server
== NULL
)
1411 return -ECONNABORTED
;
1413 pSMB
->AndXCommand
= 0xFF; /* none */
1415 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1417 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1419 pSMB
->Remaining
= 0;
1420 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1421 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1423 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1425 /* old style read */
1426 struct smb_com_readx_req
*pSMBW
=
1427 (struct smb_com_readx_req
*)pSMB
;
1428 pSMBW
->ByteCount
= 0;
1431 iov
[0].iov_base
= (char *)pSMB
;
1432 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1433 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1434 &resp_buf_type
, CIFS_LOG_ERROR
);
1435 cifs_stats_inc(&tcon
->num_reads
);
1436 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1438 cERROR(1, "Send error in read = %d", rc
);
1440 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1441 data_length
= data_length
<< 16;
1442 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1443 *nbytes
= data_length
;
1445 /*check that DataLength would not go beyond end of SMB */
1446 if ((data_length
> CIFSMaxBufSize
)
1447 || (data_length
> count
)) {
1448 cFYI(1, "bad length %d for count %d",
1449 data_length
, count
);
1453 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1454 le16_to_cpu(pSMBr
->DataOffset
);
1455 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1456 cERROR(1, "Faulting on read rc = %d",rc);
1458 }*/ /* can not use copy_to_user when using page cache*/
1460 memcpy(*buf
, pReadData
, data_length
);
1464 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1466 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1467 cifs_small_buf_release(iov
[0].iov_base
);
1468 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1469 cifs_buf_release(iov
[0].iov_base
);
1470 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1471 /* return buffer to caller to free */
1472 *buf
= iov
[0].iov_base
;
1473 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1474 *pbuf_type
= CIFS_SMALL_BUFFER
;
1475 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1476 *pbuf_type
= CIFS_LARGE_BUFFER
;
1477 } /* else no valid buffer on return - leave as null */
1479 /* Note: On -EAGAIN error only caller can retry on handle based calls
1480 since file handle passed in no longer valid */
1486 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1487 const int netfid
, const unsigned int count
,
1488 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1489 const char __user
*ubuf
, const int long_op
)
1492 WRITE_REQ
*pSMB
= NULL
;
1493 WRITE_RSP
*pSMBr
= NULL
;
1494 int bytes_returned
, wct
;
1500 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1501 if (tcon
->ses
== NULL
)
1502 return -ECONNABORTED
;
1504 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1508 if ((offset
>> 32) > 0) {
1509 /* can not handle big offset for old srv */
1514 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1518 /* tcon and ses pointer are checked in smb_init */
1519 if (tcon
->ses
->server
== NULL
)
1520 return -ECONNABORTED
;
1522 pSMB
->AndXCommand
= 0xFF; /* none */
1524 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1526 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1528 pSMB
->Reserved
= 0xFFFFFFFF;
1529 pSMB
->WriteMode
= 0;
1530 pSMB
->Remaining
= 0;
1532 /* Can increase buffer size if buffer is big enough in some cases ie we
1533 can send more if LARGE_WRITE_X capability returned by the server and if
1534 our buffer is big enough or if we convert to iovecs on socket writes
1535 and eliminate the copy to the CIFS buffer */
1536 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1537 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1539 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1543 if (bytes_sent
> count
)
1546 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1548 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1550 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1551 cifs_buf_release(pSMB
);
1554 } else if (count
!= 0) {
1556 cifs_buf_release(pSMB
);
1558 } /* else setting file size with write of zero bytes */
1560 byte_count
= bytes_sent
+ 1; /* pad */
1561 else /* wct == 12 */
1562 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1564 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1565 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1566 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1569 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1570 else { /* old style write has byte count 4 bytes earlier
1572 struct smb_com_writex_req
*pSMBW
=
1573 (struct smb_com_writex_req
*)pSMB
;
1574 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1577 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1578 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1579 cifs_stats_inc(&tcon
->num_writes
);
1581 cFYI(1, "Send error in write = %d", rc
);
1583 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1584 *nbytes
= (*nbytes
) << 16;
1585 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1588 * Mask off high 16 bits when bytes written as returned by the
1589 * server is greater than bytes requested by the client. Some
1590 * OS/2 servers are known to set incorrect CountHigh values.
1592 if (*nbytes
> count
)
1596 cifs_buf_release(pSMB
);
1598 /* Note: On -EAGAIN error only caller can retry on handle based calls
1599 since file handle passed in no longer valid */
1605 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1606 const int netfid
, const unsigned int count
,
1607 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1608 int n_vec
, const int long_op
)
1611 WRITE_REQ
*pSMB
= NULL
;
1614 int resp_buf_type
= 0;
1618 cFYI(1, "write2 at %lld %d bytes", (long long)offset
, count
);
1620 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
1624 if ((offset
>> 32) > 0) {
1625 /* can not handle big offset for old srv */
1629 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1632 /* tcon and ses pointer are checked in smb_init */
1633 if (tcon
->ses
->server
== NULL
)
1634 return -ECONNABORTED
;
1636 pSMB
->AndXCommand
= 0xFF; /* none */
1638 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1640 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1641 pSMB
->Reserved
= 0xFFFFFFFF;
1642 pSMB
->WriteMode
= 0;
1643 pSMB
->Remaining
= 0;
1646 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1648 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1649 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1650 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1652 pSMB
->hdr
.smb_buf_length
+= count
+1;
1653 else /* wct == 12 */
1654 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1656 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1657 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1658 struct smb_com_writex_req
*pSMBW
=
1659 (struct smb_com_writex_req
*)pSMB
;
1660 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1662 iov
[0].iov_base
= pSMB
;
1664 iov
[0].iov_len
= smb_hdr_len
+ 4;
1665 else /* wct == 12 pad bigger by four bytes */
1666 iov
[0].iov_len
= smb_hdr_len
+ 8;
1669 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1671 cifs_stats_inc(&tcon
->num_writes
);
1673 cFYI(1, "Send error Write2 = %d", rc
);
1674 } else if (resp_buf_type
== 0) {
1675 /* presumably this can not happen, but best to be safe */
1678 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1679 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1680 *nbytes
= (*nbytes
) << 16;
1681 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1684 * Mask off high 16 bits when bytes written as returned by the
1685 * server is greater than bytes requested by the client. OS/2
1686 * servers are known to set incorrect CountHigh values.
1688 if (*nbytes
> count
)
1692 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1693 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1694 cifs_small_buf_release(iov
[0].iov_base
);
1695 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1696 cifs_buf_release(iov
[0].iov_base
);
1698 /* Note: On -EAGAIN error only caller can retry on handle based calls
1699 since file handle passed in no longer valid */
1706 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1707 const __u16 smb_file_id
, const __u64 len
,
1708 const __u64 offset
, const __u32 numUnlock
,
1709 const __u32 numLock
, const __u8 lockType
,
1710 const bool waitFlag
, const __u8 oplock_level
)
1713 LOCK_REQ
*pSMB
= NULL
;
1714 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1719 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
);
1720 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1725 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1726 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1728 } else if (waitFlag
) {
1729 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1730 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1735 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1736 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1737 pSMB
->LockType
= lockType
;
1738 pSMB
->OplockLevel
= oplock_level
;
1739 pSMB
->AndXCommand
= 0xFF; /* none */
1740 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1742 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1743 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1744 /* BB where to store pid high? */
1745 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1746 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1747 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1748 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1749 count
= sizeof(LOCKING_ANDX_RANGE
);
1754 pSMB
->hdr
.smb_buf_length
+= count
;
1755 pSMB
->ByteCount
= cpu_to_le16(count
);
1758 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1759 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1760 cifs_small_buf_release(pSMB
);
1762 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1764 /* SMB buffer freed by function above */
1766 cifs_stats_inc(&tcon
->num_locks
);
1768 cFYI(1, "Send error in Lock = %d", rc
);
1770 /* Note: On -EAGAIN error only caller can retry on handle based calls
1771 since file handle passed in no longer valid */
1776 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1777 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1778 struct file_lock
*pLockData
, const __u16 lock_type
,
1779 const bool waitFlag
)
1781 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1782 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1783 struct cifs_posix_lock
*parm_data
;
1786 int bytes_returned
= 0;
1787 int resp_buf_type
= 0;
1788 __u16 params
, param_offset
, offset
, byte_count
, count
;
1791 cFYI(1, "Posix Lock");
1793 if (pLockData
== NULL
)
1796 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1801 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1804 pSMB
->MaxSetupCount
= 0;
1807 pSMB
->Reserved2
= 0;
1808 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1809 offset
= param_offset
+ params
;
1811 count
= sizeof(struct cifs_posix_lock
);
1812 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1813 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1814 pSMB
->SetupCount
= 1;
1815 pSMB
->Reserved3
= 0;
1817 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1819 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1820 byte_count
= 3 /* pad */ + params
+ count
;
1821 pSMB
->DataCount
= cpu_to_le16(count
);
1822 pSMB
->ParameterCount
= cpu_to_le16(params
);
1823 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1824 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1825 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1826 parm_data
= (struct cifs_posix_lock
*)
1827 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1829 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1831 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1832 parm_data
->lock_flags
= cpu_to_le16(1);
1833 pSMB
->Timeout
= cpu_to_le32(-1);
1837 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1838 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1839 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1841 pSMB
->DataOffset
= cpu_to_le16(offset
);
1842 pSMB
->Fid
= smb_file_id
;
1843 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1844 pSMB
->Reserved4
= 0;
1845 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1846 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1848 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1849 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1851 iov
[0].iov_base
= (char *)pSMB
;
1852 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1853 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1854 &resp_buf_type
, timeout
);
1855 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1856 not try to free it twice below on exit */
1857 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1861 cFYI(1, "Send error in Posix Lock = %d", rc
);
1862 } else if (get_flag
) {
1863 /* lock structure can be returned on get */
1866 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1868 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1869 rc
= -EIO
; /* bad smb */
1872 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1873 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1874 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1878 parm_data
= (struct cifs_posix_lock
*)
1879 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1880 if (parm_data
->lock_type
== __constant_cpu_to_le16(CIFS_UNLCK
))
1881 pLockData
->fl_type
= F_UNLCK
;
1883 if (parm_data
->lock_type
==
1884 __constant_cpu_to_le16(CIFS_RDLCK
))
1885 pLockData
->fl_type
= F_RDLCK
;
1886 else if (parm_data
->lock_type
==
1887 __constant_cpu_to_le16(CIFS_WRLCK
))
1888 pLockData
->fl_type
= F_WRLCK
;
1890 pLockData
->fl_start
= parm_data
->start
;
1891 pLockData
->fl_end
= parm_data
->start
+
1892 parm_data
->length
- 1;
1893 pLockData
->fl_pid
= parm_data
->pid
;
1899 cifs_small_buf_release(pSMB
);
1901 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1902 cifs_small_buf_release(iov
[0].iov_base
);
1903 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1904 cifs_buf_release(iov
[0].iov_base
);
1906 /* Note: On -EAGAIN error only caller can retry on handle based calls
1907 since file handle passed in no longer valid */
1914 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1917 CLOSE_REQ
*pSMB
= NULL
;
1918 cFYI(1, "In CIFSSMBClose");
1920 /* do not retry on dead session on close */
1921 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1927 pSMB
->FileID
= (__u16
) smb_file_id
;
1928 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1929 pSMB
->ByteCount
= 0;
1930 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1931 cifs_stats_inc(&tcon
->num_closes
);
1934 /* EINTR is expected when user ctl-c to kill app */
1935 cERROR(1, "Send error in Close = %d", rc
);
1939 /* Since session is dead, file will be closed on server already */
1947 CIFSSMBFlush(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1950 FLUSH_REQ
*pSMB
= NULL
;
1951 cFYI(1, "In CIFSSMBFlush");
1953 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
1957 pSMB
->FileID
= (__u16
) smb_file_id
;
1958 pSMB
->ByteCount
= 0;
1959 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1960 cifs_stats_inc(&tcon
->num_flushes
);
1962 cERROR(1, "Send error in Flush = %d", rc
);
1968 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1969 const char *fromName
, const char *toName
,
1970 const struct nls_table
*nls_codepage
, int remap
)
1973 RENAME_REQ
*pSMB
= NULL
;
1974 RENAME_RSP
*pSMBr
= NULL
;
1976 int name_len
, name_len2
;
1979 cFYI(1, "In CIFSSMBRename");
1981 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1986 pSMB
->BufferFormat
= 0x04;
1987 pSMB
->SearchAttributes
=
1988 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1991 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1993 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1994 PATH_MAX
, nls_codepage
, remap
);
1995 name_len
++; /* trailing null */
1997 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1998 /* protocol requires ASCII signature byte on Unicode string */
1999 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2001 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2002 toName
, PATH_MAX
, nls_codepage
, remap
);
2003 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2004 name_len2
*= 2; /* convert to bytes */
2005 } else { /* BB improve the check for buffer overruns BB */
2006 name_len
= strnlen(fromName
, PATH_MAX
);
2007 name_len
++; /* trailing null */
2008 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2009 name_len2
= strnlen(toName
, PATH_MAX
);
2010 name_len2
++; /* trailing null */
2011 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2012 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2013 name_len2
++; /* trailing null */
2014 name_len2
++; /* signature byte */
2017 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2018 pSMB
->hdr
.smb_buf_length
+= count
;
2019 pSMB
->ByteCount
= cpu_to_le16(count
);
2021 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2022 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2023 cifs_stats_inc(&tcon
->num_renames
);
2025 cFYI(1, "Send error in rename = %d", rc
);
2027 cifs_buf_release(pSMB
);
2035 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
2036 int netfid
, const char *target_name
,
2037 const struct nls_table
*nls_codepage
, int remap
)
2039 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2040 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2041 struct set_file_rename
*rename_info
;
2043 char dummy_string
[30];
2045 int bytes_returned
= 0;
2047 __u16 params
, param_offset
, offset
, count
, byte_count
;
2049 cFYI(1, "Rename to File by handle");
2050 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2056 pSMB
->MaxSetupCount
= 0;
2060 pSMB
->Reserved2
= 0;
2061 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2062 offset
= param_offset
+ params
;
2064 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2065 rename_info
= (struct set_file_rename
*) data_offset
;
2066 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2067 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2068 pSMB
->SetupCount
= 1;
2069 pSMB
->Reserved3
= 0;
2070 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2071 byte_count
= 3 /* pad */ + params
;
2072 pSMB
->ParameterCount
= cpu_to_le16(params
);
2073 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2074 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2075 pSMB
->DataOffset
= cpu_to_le16(offset
);
2076 /* construct random name ".cifs_tmp<inodenum><mid>" */
2077 rename_info
->overwrite
= cpu_to_le32(1);
2078 rename_info
->root_fid
= 0;
2079 /* unicode only call */
2080 if (target_name
== NULL
) {
2081 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2082 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2083 dummy_string
, 24, nls_codepage
, remap
);
2085 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2086 target_name
, PATH_MAX
, nls_codepage
,
2089 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2090 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2091 byte_count
+= count
;
2092 pSMB
->DataCount
= cpu_to_le16(count
);
2093 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2095 pSMB
->InformationLevel
=
2096 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2097 pSMB
->Reserved4
= 0;
2098 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2099 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2100 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2101 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2102 cifs_stats_inc(&pTcon
->num_t2renames
);
2104 cFYI(1, "Send error in Rename (by file handle) = %d", rc
);
2106 cifs_buf_release(pSMB
);
2108 /* Note: On -EAGAIN error only caller can retry on handle based calls
2109 since file handle passed in no longer valid */
2115 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2116 const __u16 target_tid
, const char *toName
, const int flags
,
2117 const struct nls_table
*nls_codepage
, int remap
)
2120 COPY_REQ
*pSMB
= NULL
;
2121 COPY_RSP
*pSMBr
= NULL
;
2123 int name_len
, name_len2
;
2126 cFYI(1, "In CIFSSMBCopy");
2128 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2133 pSMB
->BufferFormat
= 0x04;
2134 pSMB
->Tid2
= target_tid
;
2136 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2138 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2139 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2140 fromName
, PATH_MAX
, nls_codepage
,
2142 name_len
++; /* trailing null */
2144 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2145 /* protocol requires ASCII signature byte on Unicode string */
2146 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2148 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2149 toName
, PATH_MAX
, nls_codepage
, remap
);
2150 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2151 name_len2
*= 2; /* convert to bytes */
2152 } else { /* BB improve the check for buffer overruns BB */
2153 name_len
= strnlen(fromName
, PATH_MAX
);
2154 name_len
++; /* trailing null */
2155 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2156 name_len2
= strnlen(toName
, PATH_MAX
);
2157 name_len2
++; /* trailing null */
2158 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2159 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2160 name_len2
++; /* trailing null */
2161 name_len2
++; /* signature byte */
2164 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2165 pSMB
->hdr
.smb_buf_length
+= count
;
2166 pSMB
->ByteCount
= cpu_to_le16(count
);
2168 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2169 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2171 cFYI(1, "Send error in copy = %d with %d files copied",
2172 rc
, le16_to_cpu(pSMBr
->CopyCount
));
2174 cifs_buf_release(pSMB
);
2183 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2184 const char *fromName
, const char *toName
,
2185 const struct nls_table
*nls_codepage
)
2187 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2188 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2191 int name_len_target
;
2193 int bytes_returned
= 0;
2194 __u16 params
, param_offset
, offset
, byte_count
;
2196 cFYI(1, "In Symlink Unix style");
2198 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2203 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2205 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2206 /* find define for this maxpathcomponent */
2208 name_len
++; /* trailing null */
2211 } else { /* BB improve the check for buffer overruns BB */
2212 name_len
= strnlen(fromName
, PATH_MAX
);
2213 name_len
++; /* trailing null */
2214 strncpy(pSMB
->FileName
, fromName
, name_len
);
2216 params
= 6 + name_len
;
2217 pSMB
->MaxSetupCount
= 0;
2221 pSMB
->Reserved2
= 0;
2222 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2223 InformationLevel
) - 4;
2224 offset
= param_offset
+ params
;
2226 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2227 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2229 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2230 /* find define for this maxpathcomponent */
2232 name_len_target
++; /* trailing null */
2233 name_len_target
*= 2;
2234 } else { /* BB improve the check for buffer overruns BB */
2235 name_len_target
= strnlen(toName
, PATH_MAX
);
2236 name_len_target
++; /* trailing null */
2237 strncpy(data_offset
, toName
, name_len_target
);
2240 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2241 /* BB find exact max on data count below from sess */
2242 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2243 pSMB
->SetupCount
= 1;
2244 pSMB
->Reserved3
= 0;
2245 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2246 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2247 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2248 pSMB
->ParameterCount
= cpu_to_le16(params
);
2249 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2250 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2251 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2252 pSMB
->DataOffset
= cpu_to_le16(offset
);
2253 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2254 pSMB
->Reserved4
= 0;
2255 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2256 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2257 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2258 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2259 cifs_stats_inc(&tcon
->num_symlinks
);
2261 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc
);
2263 cifs_buf_release(pSMB
);
2266 goto createSymLinkRetry
;
2272 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2273 const char *fromName
, const char *toName
,
2274 const struct nls_table
*nls_codepage
, int remap
)
2276 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2277 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2280 int name_len_target
;
2282 int bytes_returned
= 0;
2283 __u16 params
, param_offset
, offset
, byte_count
;
2285 cFYI(1, "In Create Hard link Unix style");
2286 createHardLinkRetry
:
2287 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2292 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2293 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2294 PATH_MAX
, nls_codepage
, remap
);
2295 name_len
++; /* trailing null */
2298 } else { /* BB improve the check for buffer overruns BB */
2299 name_len
= strnlen(toName
, PATH_MAX
);
2300 name_len
++; /* trailing null */
2301 strncpy(pSMB
->FileName
, toName
, name_len
);
2303 params
= 6 + name_len
;
2304 pSMB
->MaxSetupCount
= 0;
2308 pSMB
->Reserved2
= 0;
2309 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2310 InformationLevel
) - 4;
2311 offset
= param_offset
+ params
;
2313 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2314 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2316 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2317 nls_codepage
, remap
);
2318 name_len_target
++; /* trailing null */
2319 name_len_target
*= 2;
2320 } else { /* BB improve the check for buffer overruns BB */
2321 name_len_target
= strnlen(fromName
, PATH_MAX
);
2322 name_len_target
++; /* trailing null */
2323 strncpy(data_offset
, fromName
, name_len_target
);
2326 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2327 /* BB find exact max on data count below from sess*/
2328 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2329 pSMB
->SetupCount
= 1;
2330 pSMB
->Reserved3
= 0;
2331 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2332 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2333 pSMB
->ParameterCount
= cpu_to_le16(params
);
2334 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2335 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2336 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2337 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2338 pSMB
->DataOffset
= cpu_to_le16(offset
);
2339 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2340 pSMB
->Reserved4
= 0;
2341 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2342 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2343 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2344 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2345 cifs_stats_inc(&tcon
->num_hardlinks
);
2347 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc
);
2349 cifs_buf_release(pSMB
);
2351 goto createHardLinkRetry
;
2357 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2358 const char *fromName
, const char *toName
,
2359 const struct nls_table
*nls_codepage
, int remap
)
2362 NT_RENAME_REQ
*pSMB
= NULL
;
2363 RENAME_RSP
*pSMBr
= NULL
;
2365 int name_len
, name_len2
;
2368 cFYI(1, "In CIFSCreateHardLink");
2369 winCreateHardLinkRetry
:
2371 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2376 pSMB
->SearchAttributes
=
2377 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2379 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2380 pSMB
->ClusterCount
= 0;
2382 pSMB
->BufferFormat
= 0x04;
2384 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2386 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2387 PATH_MAX
, nls_codepage
, remap
);
2388 name_len
++; /* trailing null */
2391 /* protocol specifies ASCII buffer format (0x04) for unicode */
2392 pSMB
->OldFileName
[name_len
] = 0x04;
2393 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2395 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2396 toName
, PATH_MAX
, nls_codepage
, remap
);
2397 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2398 name_len2
*= 2; /* convert to bytes */
2399 } else { /* BB improve the check for buffer overruns BB */
2400 name_len
= strnlen(fromName
, PATH_MAX
);
2401 name_len
++; /* trailing null */
2402 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2403 name_len2
= strnlen(toName
, PATH_MAX
);
2404 name_len2
++; /* trailing null */
2405 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2406 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2407 name_len2
++; /* trailing null */
2408 name_len2
++; /* signature byte */
2411 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2412 pSMB
->hdr
.smb_buf_length
+= count
;
2413 pSMB
->ByteCount
= cpu_to_le16(count
);
2415 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2416 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2417 cifs_stats_inc(&tcon
->num_hardlinks
);
2419 cFYI(1, "Send error in hard link (NT rename) = %d", rc
);
2421 cifs_buf_release(pSMB
);
2423 goto winCreateHardLinkRetry
;
2429 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2430 const unsigned char *searchName
, char **symlinkinfo
,
2431 const struct nls_table
*nls_codepage
)
2433 /* SMB_QUERY_FILE_UNIX_LINK */
2434 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2435 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2439 __u16 params
, byte_count
;
2442 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName
);
2445 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2450 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2452 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2453 PATH_MAX
, nls_codepage
);
2454 name_len
++; /* trailing null */
2456 } else { /* BB improve the check for buffer overruns BB */
2457 name_len
= strnlen(searchName
, PATH_MAX
);
2458 name_len
++; /* trailing null */
2459 strncpy(pSMB
->FileName
, searchName
, name_len
);
2462 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2463 pSMB
->TotalDataCount
= 0;
2464 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2465 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
2466 pSMB
->MaxSetupCount
= 0;
2470 pSMB
->Reserved2
= 0;
2471 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2472 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2473 pSMB
->DataCount
= 0;
2474 pSMB
->DataOffset
= 0;
2475 pSMB
->SetupCount
= 1;
2476 pSMB
->Reserved3
= 0;
2477 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2478 byte_count
= params
+ 1 /* pad */ ;
2479 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2480 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2481 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2482 pSMB
->Reserved4
= 0;
2483 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2484 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2486 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2487 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2489 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc
);
2491 /* decode response */
2493 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2494 /* BB also check enough total bytes returned */
2495 if (rc
|| (pSMBr
->ByteCount
< 2))
2499 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2501 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
2502 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2504 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2509 /* BB FIXME investigate remapping reserved chars here */
2510 *symlinkinfo
= cifs_strndup_from_ucs(data_start
, count
,
2511 is_unicode
, nls_codepage
);
2516 cifs_buf_release(pSMB
);
2518 goto querySymLinkRetry
;
2522 #ifdef CONFIG_CIFS_EXPERIMENTAL
2524 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2525 const unsigned char *searchName
,
2526 char *symlinkinfo
, const int buflen
, __u16 fid
,
2527 const struct nls_table
*nls_codepage
)
2531 struct smb_com_transaction_ioctl_req
*pSMB
;
2532 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2534 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName
);
2535 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2540 pSMB
->TotalParameterCount
= 0 ;
2541 pSMB
->TotalDataCount
= 0;
2542 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2543 /* BB find exact data count max from sess structure BB */
2544 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2545 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2546 pSMB
->MaxSetupCount
= 4;
2548 pSMB
->ParameterOffset
= 0;
2549 pSMB
->DataCount
= 0;
2550 pSMB
->DataOffset
= 0;
2551 pSMB
->SetupCount
= 4;
2552 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2553 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2554 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2555 pSMB
->IsFsctl
= 1; /* FSCTL */
2556 pSMB
->IsRootFlag
= 0;
2557 pSMB
->Fid
= fid
; /* file handle always le */
2558 pSMB
->ByteCount
= 0;
2560 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2561 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2563 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc
);
2564 } else { /* decode response */
2565 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2566 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2567 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512)) {
2568 /* BB also check enough total bytes returned */
2569 rc
= -EIO
; /* bad smb */
2572 if (data_count
&& (data_count
< 2048)) {
2573 char *end_of_smb
= 2 /* sizeof byte count */ +
2574 pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
2576 struct reparse_data
*reparse_buf
=
2577 (struct reparse_data
*)
2578 ((char *)&pSMBr
->hdr
.Protocol
2580 if ((char *)reparse_buf
>= end_of_smb
) {
2584 if ((reparse_buf
->LinkNamesBuf
+
2585 reparse_buf
->TargetNameOffset
+
2586 reparse_buf
->TargetNameLen
) > end_of_smb
) {
2587 cFYI(1, "reparse buf beyond SMB");
2592 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2593 cifs_from_ucs2(symlinkinfo
, (__le16
*)
2594 (reparse_buf
->LinkNamesBuf
+
2595 reparse_buf
->TargetNameOffset
),
2597 reparse_buf
->TargetNameLen
,
2599 } else { /* ASCII names */
2600 strncpy(symlinkinfo
,
2601 reparse_buf
->LinkNamesBuf
+
2602 reparse_buf
->TargetNameOffset
,
2603 min_t(const int, buflen
,
2604 reparse_buf
->TargetNameLen
));
2608 cFYI(1, "Invalid return data count on "
2609 "get reparse info ioctl");
2611 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2612 does not go off the end of the buffer */
2613 cFYI(1, "readlink result - %s", symlinkinfo
);
2617 cifs_buf_release(pSMB
);
2619 /* Note: On -EAGAIN error only caller can retry on handle based calls
2620 since file handle passed in no longer valid */
2624 #endif /* CIFS_EXPERIMENTAL */
2626 #ifdef CONFIG_CIFS_POSIX
2628 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2629 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2630 struct cifs_posix_ace
*cifs_ace
)
2632 /* u8 cifs fields do not need le conversion */
2633 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2634 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2635 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2636 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2641 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2642 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2643 const int acl_type
, const int size_of_data_area
)
2648 struct cifs_posix_ace
*pACE
;
2649 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2650 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2652 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2655 if (acl_type
& ACL_TYPE_ACCESS
) {
2656 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2657 pACE
= &cifs_acl
->ace_array
[0];
2658 size
= sizeof(struct cifs_posix_acl
);
2659 size
+= sizeof(struct cifs_posix_ace
) * count
;
2660 /* check if we would go beyond end of SMB */
2661 if (size_of_data_area
< size
) {
2662 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2663 size_of_data_area
, size
);
2666 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2667 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2668 size
= sizeof(struct cifs_posix_acl
);
2669 size
+= sizeof(struct cifs_posix_ace
) * count
;
2670 /* skip past access ACEs to get to default ACEs */
2671 pACE
= &cifs_acl
->ace_array
[count
];
2672 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2673 size
+= sizeof(struct cifs_posix_ace
) * count
;
2674 /* check if we would go beyond end of SMB */
2675 if (size_of_data_area
< size
)
2682 size
= posix_acl_xattr_size(count
);
2683 if ((buflen
== 0) || (local_acl
== NULL
)) {
2684 /* used to query ACL EA size */
2685 } else if (size
> buflen
) {
2687 } else /* buffer big enough */ {
2688 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2689 for (i
= 0; i
< count
; i
++) {
2690 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2697 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2698 const posix_acl_xattr_entry
*local_ace
)
2700 __u16 rc
= 0; /* 0 = ACL converted ok */
2702 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2703 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2704 /* BB is there a better way to handle the large uid? */
2705 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2706 /* Probably no need to le convert -1 on any arch but can not hurt */
2707 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2709 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2710 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2714 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2715 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2716 const int buflen
, const int acl_type
)
2719 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2720 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2724 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2727 count
= posix_acl_xattr_count((size_t)buflen
);
2728 cFYI(1, "setting acl with %d entries from buf of length %d and "
2730 count
, buflen
, le32_to_cpu(local_acl
->a_version
));
2731 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2732 cFYI(1, "unknown POSIX ACL version %d",
2733 le32_to_cpu(local_acl
->a_version
));
2736 cifs_acl
->version
= cpu_to_le16(1);
2737 if (acl_type
== ACL_TYPE_ACCESS
)
2738 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2739 else if (acl_type
== ACL_TYPE_DEFAULT
)
2740 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2742 cFYI(1, "unknown ACL type %d", acl_type
);
2745 for (i
= 0; i
< count
; i
++) {
2746 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2747 &local_acl
->a_entries
[i
]);
2749 /* ACE not converted */
2754 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2755 rc
+= sizeof(struct cifs_posix_acl
);
2756 /* BB add check to make sure ACL does not overflow SMB */
2762 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2763 const unsigned char *searchName
,
2764 char *acl_inf
, const int buflen
, const int acl_type
,
2765 const struct nls_table
*nls_codepage
, int remap
)
2767 /* SMB_QUERY_POSIX_ACL */
2768 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2769 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2773 __u16 params
, byte_count
;
2775 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName
);
2778 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2783 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2785 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2786 PATH_MAX
, nls_codepage
, remap
);
2787 name_len
++; /* trailing null */
2789 pSMB
->FileName
[name_len
] = 0;
2790 pSMB
->FileName
[name_len
+1] = 0;
2791 } else { /* BB improve the check for buffer overruns BB */
2792 name_len
= strnlen(searchName
, PATH_MAX
);
2793 name_len
++; /* trailing null */
2794 strncpy(pSMB
->FileName
, searchName
, name_len
);
2797 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2798 pSMB
->TotalDataCount
= 0;
2799 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2800 /* BB find exact max data count below from sess structure BB */
2801 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2802 pSMB
->MaxSetupCount
= 0;
2806 pSMB
->Reserved2
= 0;
2807 pSMB
->ParameterOffset
= cpu_to_le16(
2808 offsetof(struct smb_com_transaction2_qpi_req
,
2809 InformationLevel
) - 4);
2810 pSMB
->DataCount
= 0;
2811 pSMB
->DataOffset
= 0;
2812 pSMB
->SetupCount
= 1;
2813 pSMB
->Reserved3
= 0;
2814 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2815 byte_count
= params
+ 1 /* pad */ ;
2816 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2817 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2818 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2819 pSMB
->Reserved4
= 0;
2820 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2821 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2823 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2824 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2825 cifs_stats_inc(&tcon
->num_acl_get
);
2827 cFYI(1, "Send error in Query POSIX ACL = %d", rc
);
2829 /* decode response */
2831 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2832 if (rc
|| (pSMBr
->ByteCount
< 2))
2833 /* BB also check enough total bytes returned */
2834 rc
= -EIO
; /* bad smb */
2836 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2837 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2838 rc
= cifs_copy_posix_acl(acl_inf
,
2839 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2840 buflen
, acl_type
, count
);
2843 cifs_buf_release(pSMB
);
2850 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2851 const unsigned char *fileName
,
2852 const char *local_acl
, const int buflen
,
2854 const struct nls_table
*nls_codepage
, int remap
)
2856 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2857 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2861 int bytes_returned
= 0;
2862 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2864 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName
);
2866 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2870 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2872 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2873 PATH_MAX
, nls_codepage
, remap
);
2874 name_len
++; /* trailing null */
2876 } else { /* BB improve the check for buffer overruns BB */
2877 name_len
= strnlen(fileName
, PATH_MAX
);
2878 name_len
++; /* trailing null */
2879 strncpy(pSMB
->FileName
, fileName
, name_len
);
2881 params
= 6 + name_len
;
2882 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2883 /* BB find max SMB size from sess */
2884 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2885 pSMB
->MaxSetupCount
= 0;
2889 pSMB
->Reserved2
= 0;
2890 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2891 InformationLevel
) - 4;
2892 offset
= param_offset
+ params
;
2893 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2894 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2896 /* convert to on the wire format for POSIX ACL */
2897 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2899 if (data_count
== 0) {
2901 goto setACLerrorExit
;
2903 pSMB
->DataOffset
= cpu_to_le16(offset
);
2904 pSMB
->SetupCount
= 1;
2905 pSMB
->Reserved3
= 0;
2906 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2907 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2908 byte_count
= 3 /* pad */ + params
+ data_count
;
2909 pSMB
->DataCount
= cpu_to_le16(data_count
);
2910 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2911 pSMB
->ParameterCount
= cpu_to_le16(params
);
2912 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2913 pSMB
->Reserved4
= 0;
2914 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2915 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2916 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2917 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2919 cFYI(1, "Set POSIX ACL returned %d", rc
);
2922 cifs_buf_release(pSMB
);
2928 /* BB fix tabs in this function FIXME BB */
2930 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2931 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2934 struct smb_t2_qfi_req
*pSMB
= NULL
;
2935 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2937 __u16 params
, byte_count
;
2939 cFYI(1, "In GetExtAttr");
2944 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2949 params
= 2 /* level */ + 2 /* fid */;
2950 pSMB
->t2
.TotalDataCount
= 0;
2951 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2952 /* BB find exact max data count below from sess structure BB */
2953 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2954 pSMB
->t2
.MaxSetupCount
= 0;
2955 pSMB
->t2
.Reserved
= 0;
2957 pSMB
->t2
.Timeout
= 0;
2958 pSMB
->t2
.Reserved2
= 0;
2959 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2961 pSMB
->t2
.DataCount
= 0;
2962 pSMB
->t2
.DataOffset
= 0;
2963 pSMB
->t2
.SetupCount
= 1;
2964 pSMB
->t2
.Reserved3
= 0;
2965 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2966 byte_count
= params
+ 1 /* pad */ ;
2967 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2968 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2969 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2972 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2973 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2975 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2976 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2978 cFYI(1, "error %d in GetExtAttr", rc
);
2980 /* decode response */
2981 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2982 if (rc
|| (pSMBr
->ByteCount
< 2))
2983 /* BB also check enough total bytes returned */
2984 /* If rc should we check for EOPNOSUPP and
2985 disable the srvino flag? or in caller? */
2986 rc
= -EIO
; /* bad smb */
2988 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2989 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2990 struct file_chattr_info
*pfinfo
;
2991 /* BB Do we need a cast or hash here ? */
2993 cFYI(1, "Illegal size ret in GetExtAttr");
2997 pfinfo
= (struct file_chattr_info
*)
2998 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2999 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3000 *pMask
= le64_to_cpu(pfinfo
->mask
);
3004 cifs_buf_release(pSMB
);
3006 goto GetExtAttrRetry
;
3010 #endif /* CONFIG_POSIX */
3012 #ifdef CONFIG_CIFS_ACL
3014 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3015 * all NT TRANSACTS that we init here have total parm and data under about 400
3016 * bytes (to fit in small cifs buffer size), which is the case so far, it
3017 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3018 * returned setup area) and MaxParameterCount (returned parms size) must be set
3022 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
3023 const int parm_len
, struct cifsTconInfo
*tcon
,
3028 struct smb_com_ntransact_req
*pSMB
;
3030 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
3034 *ret_buf
= (void *)pSMB
;
3036 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
3037 pSMB
->TotalDataCount
= 0;
3038 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
3039 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3040 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3041 pSMB
->DataCount
= pSMB
->TotalDataCount
;
3042 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
3043 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
3044 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
3045 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
3046 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
3047 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
3052 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
3053 __u32
*pparmlen
, __u32
*pdatalen
)
3056 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
3057 struct smb_com_ntransact_rsp
*pSMBr
;
3065 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
3067 /* ByteCount was converted from little endian in SendReceive */
3068 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
3069 (char *)&pSMBr
->ByteCount
;
3071 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
3072 data_count
= le32_to_cpu(pSMBr
->DataCount
);
3073 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
3074 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
3076 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
3077 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
3079 /* should we also check that parm and data areas do not overlap? */
3080 if (*ppparm
> end_of_smb
) {
3081 cFYI(1, "parms start after end of smb");
3083 } else if (parm_count
+ *ppparm
> end_of_smb
) {
3084 cFYI(1, "parm end after end of smb");
3086 } else if (*ppdata
> end_of_smb
) {
3087 cFYI(1, "data starts after end of smb");
3089 } else if (data_count
+ *ppdata
> end_of_smb
) {
3090 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3091 *ppdata
, data_count
, (data_count
+ *ppdata
),
3094 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
3095 cFYI(1, "parm count and data count larger than SMB");
3098 *pdatalen
= data_count
;
3099 *pparmlen
= parm_count
;
3103 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3105 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3106 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3110 QUERY_SEC_DESC_REQ
*pSMB
;
3113 cFYI(1, "GetCifsACL");
3118 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3119 8 /* parm len */, tcon
, (void **) &pSMB
);
3123 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3124 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3125 pSMB
->MaxSetupCount
= 0;
3126 pSMB
->Fid
= fid
; /* file handle always le */
3127 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3129 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3130 pSMB
->hdr
.smb_buf_length
+= 11;
3131 iov
[0].iov_base
= (char *)pSMB
;
3132 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3134 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3136 cifs_stats_inc(&tcon
->num_acl_get
);
3138 cFYI(1, "Send error in QuerySecDesc = %d", rc
);
3139 } else { /* decode response */
3143 struct smb_com_ntransact_rsp
*pSMBr
;
3146 /* validate_nttransact */
3147 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3148 &pdata
, &parm_len
, pbuflen
);
3151 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3153 cFYI(1, "smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
);
3155 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3156 rc
= -EIO
; /* bad smb */
3161 /* BB check that data area is minimum length and as big as acl_len */
3163 acl_len
= le32_to_cpu(*parm
);
3164 if (acl_len
!= *pbuflen
) {
3165 cERROR(1, "acl length %d does not match %d",
3167 if (*pbuflen
> acl_len
)
3171 /* check if buffer is big enough for the acl
3172 header followed by the smallest SID */
3173 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3174 (*pbuflen
>= 64 * 1024)) {
3175 cERROR(1, "bad acl length %d", *pbuflen
);
3179 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3180 if (*acl_inf
== NULL
) {
3184 memcpy(*acl_inf
, pdata
, *pbuflen
);
3188 if (buf_type
== CIFS_SMALL_BUFFER
)
3189 cifs_small_buf_release(iov
[0].iov_base
);
3190 else if (buf_type
== CIFS_LARGE_BUFFER
)
3191 cifs_buf_release(iov
[0].iov_base
);
3192 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3197 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3198 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3200 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3202 int bytes_returned
= 0;
3203 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3204 NTRANSACT_RSP
*pSMBr
= NULL
;
3207 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3212 pSMB
->MaxSetupCount
= 0;
3216 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3217 data_count
= acllen
;
3218 data_offset
= param_offset
+ param_count
;
3219 byte_count
= 3 /* pad */ + param_count
;
3221 pSMB
->DataCount
= cpu_to_le32(data_count
);
3222 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3223 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3224 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3225 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3226 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3227 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3228 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3229 pSMB
->SetupCount
= 0;
3230 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3231 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3233 pSMB
->Fid
= fid
; /* file handle always le */
3234 pSMB
->Reserved2
= 0;
3235 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3237 if (pntsd
&& acllen
) {
3238 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3241 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3244 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3246 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3247 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3249 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
);
3251 cFYI(1, "Set CIFS ACL returned %d", rc
);
3252 cifs_buf_release(pSMB
);
3255 goto setCifsAclRetry
;
3260 #endif /* CONFIG_CIFS_ACL */
3262 /* Legacy Query Path Information call for lookup to old servers such
3264 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3265 const unsigned char *searchName
,
3266 FILE_ALL_INFO
*pFinfo
,
3267 const struct nls_table
*nls_codepage
, int remap
)
3269 QUERY_INFORMATION_REQ
*pSMB
;
3270 QUERY_INFORMATION_RSP
*pSMBr
;
3275 cFYI(1, "In SMBQPath path %s", searchName
);
3277 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3282 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3284 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3285 PATH_MAX
, nls_codepage
, remap
);
3286 name_len
++; /* trailing null */
3289 name_len
= strnlen(searchName
, PATH_MAX
);
3290 name_len
++; /* trailing null */
3291 strncpy(pSMB
->FileName
, searchName
, name_len
);
3293 pSMB
->BufferFormat
= 0x04;
3294 name_len
++; /* account for buffer type byte */
3295 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3296 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3298 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3299 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3301 cFYI(1, "Send error in QueryInfo = %d", rc
);
3302 } else if (pFinfo
) {
3304 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3306 /* decode response */
3307 /* BB FIXME - add time zone adjustment BB */
3308 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3311 /* decode time fields */
3312 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3313 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3314 pFinfo
->LastAccessTime
= 0;
3315 pFinfo
->AllocationSize
=
3316 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3317 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3318 pFinfo
->Attributes
=
3319 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3321 rc
= -EIO
; /* bad buffer passed in */
3323 cifs_buf_release(pSMB
);
3332 CIFSSMBQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3333 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3335 struct smb_t2_qfi_req
*pSMB
= NULL
;
3336 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3339 __u16 params
, byte_count
;
3342 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3347 params
= 2 /* level */ + 2 /* fid */;
3348 pSMB
->t2
.TotalDataCount
= 0;
3349 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3350 /* BB find exact max data count below from sess structure BB */
3351 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3352 pSMB
->t2
.MaxSetupCount
= 0;
3353 pSMB
->t2
.Reserved
= 0;
3355 pSMB
->t2
.Timeout
= 0;
3356 pSMB
->t2
.Reserved2
= 0;
3357 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3359 pSMB
->t2
.DataCount
= 0;
3360 pSMB
->t2
.DataOffset
= 0;
3361 pSMB
->t2
.SetupCount
= 1;
3362 pSMB
->t2
.Reserved3
= 0;
3363 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3364 byte_count
= params
+ 1 /* pad */ ;
3365 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3366 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3367 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3370 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3372 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3373 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3375 cFYI(1, "Send error in QPathInfo = %d", rc
);
3376 } else { /* decode response */
3377 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3379 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3381 else if (pSMBr
->ByteCount
< 40)
3382 rc
= -EIO
; /* bad smb */
3383 else if (pFindData
) {
3384 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3385 memcpy((char *) pFindData
,
3386 (char *) &pSMBr
->hdr
.Protocol
+
3387 data_offset
, sizeof(FILE_ALL_INFO
));
3391 cifs_buf_release(pSMB
);
3393 goto QFileInfoRetry
;
3399 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3400 const unsigned char *searchName
,
3401 FILE_ALL_INFO
*pFindData
,
3402 int legacy
/* old style infolevel */,
3403 const struct nls_table
*nls_codepage
, int remap
)
3405 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3406 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3407 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3411 __u16 params
, byte_count
;
3413 /* cFYI(1, "In QPathInfo path %s", searchName); */
3415 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3420 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3422 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3423 PATH_MAX
, nls_codepage
, remap
);
3424 name_len
++; /* trailing null */
3426 } else { /* BB improve the check for buffer overruns BB */
3427 name_len
= strnlen(searchName
, PATH_MAX
);
3428 name_len
++; /* trailing null */
3429 strncpy(pSMB
->FileName
, searchName
, name_len
);
3432 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3433 pSMB
->TotalDataCount
= 0;
3434 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3435 /* BB find exact max SMB PDU from sess structure BB */
3436 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3437 pSMB
->MaxSetupCount
= 0;
3441 pSMB
->Reserved2
= 0;
3442 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3443 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3444 pSMB
->DataCount
= 0;
3445 pSMB
->DataOffset
= 0;
3446 pSMB
->SetupCount
= 1;
3447 pSMB
->Reserved3
= 0;
3448 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3449 byte_count
= params
+ 1 /* pad */ ;
3450 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3451 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3453 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3455 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3456 pSMB
->Reserved4
= 0;
3457 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3458 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3460 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3461 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3463 cFYI(1, "Send error in QPathInfo = %d", rc
);
3464 } else { /* decode response */
3465 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3467 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3469 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3470 rc
= -EIO
; /* bad smb */
3471 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3472 rc
= -EIO
; /* 24 or 26 expected but we do not read
3474 else if (pFindData
) {
3476 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3478 /* On legacy responses we do not read the last field,
3479 EAsize, fortunately since it varies by subdialect and
3480 also note it differs on Set vs. Get, ie two bytes or 4
3481 bytes depending but we don't care here */
3483 size
= sizeof(FILE_INFO_STANDARD
);
3485 size
= sizeof(FILE_ALL_INFO
);
3486 memcpy((char *) pFindData
,
3487 (char *) &pSMBr
->hdr
.Protocol
+
3492 cifs_buf_release(pSMB
);
3494 goto QPathInfoRetry
;
3500 CIFSSMBUnixQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3501 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
3503 struct smb_t2_qfi_req
*pSMB
= NULL
;
3504 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3507 __u16 params
, byte_count
;
3510 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3515 params
= 2 /* level */ + 2 /* fid */;
3516 pSMB
->t2
.TotalDataCount
= 0;
3517 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3518 /* BB find exact max data count below from sess structure BB */
3519 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3520 pSMB
->t2
.MaxSetupCount
= 0;
3521 pSMB
->t2
.Reserved
= 0;
3523 pSMB
->t2
.Timeout
= 0;
3524 pSMB
->t2
.Reserved2
= 0;
3525 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3527 pSMB
->t2
.DataCount
= 0;
3528 pSMB
->t2
.DataOffset
= 0;
3529 pSMB
->t2
.SetupCount
= 1;
3530 pSMB
->t2
.Reserved3
= 0;
3531 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3532 byte_count
= params
+ 1 /* pad */ ;
3533 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3534 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3535 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3538 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3540 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3541 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3543 cFYI(1, "Send error in QPathInfo = %d", rc
);
3544 } else { /* decode response */
3545 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3547 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3548 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3549 "Unix Extensions can be disabled on mount "
3550 "by specifying the nosfu mount option.");
3551 rc
= -EIO
; /* bad smb */
3553 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3554 memcpy((char *) pFindData
,
3555 (char *) &pSMBr
->hdr
.Protocol
+
3557 sizeof(FILE_UNIX_BASIC_INFO
));
3561 cifs_buf_release(pSMB
);
3563 goto UnixQFileInfoRetry
;
3569 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3570 const unsigned char *searchName
,
3571 FILE_UNIX_BASIC_INFO
*pFindData
,
3572 const struct nls_table
*nls_codepage
, int remap
)
3574 /* SMB_QUERY_FILE_UNIX_BASIC */
3575 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3576 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3578 int bytes_returned
= 0;
3580 __u16 params
, byte_count
;
3582 cFYI(1, "In QPathInfo (Unix) the path %s", searchName
);
3584 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3589 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3591 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3592 PATH_MAX
, nls_codepage
, remap
);
3593 name_len
++; /* trailing null */
3595 } else { /* BB improve the check for buffer overruns BB */
3596 name_len
= strnlen(searchName
, PATH_MAX
);
3597 name_len
++; /* trailing null */
3598 strncpy(pSMB
->FileName
, searchName
, name_len
);
3601 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3602 pSMB
->TotalDataCount
= 0;
3603 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3604 /* BB find exact max SMB PDU from sess structure BB */
3605 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3606 pSMB
->MaxSetupCount
= 0;
3610 pSMB
->Reserved2
= 0;
3611 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3612 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3613 pSMB
->DataCount
= 0;
3614 pSMB
->DataOffset
= 0;
3615 pSMB
->SetupCount
= 1;
3616 pSMB
->Reserved3
= 0;
3617 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3618 byte_count
= params
+ 1 /* pad */ ;
3619 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3620 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3621 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3622 pSMB
->Reserved4
= 0;
3623 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3624 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3626 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3627 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3629 cFYI(1, "Send error in QPathInfo = %d", rc
);
3630 } else { /* decode response */
3631 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3633 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3634 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3635 "Unix Extensions can be disabled on mount "
3636 "by specifying the nosfu mount option.");
3637 rc
= -EIO
; /* bad smb */
3639 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3640 memcpy((char *) pFindData
,
3641 (char *) &pSMBr
->hdr
.Protocol
+
3643 sizeof(FILE_UNIX_BASIC_INFO
));
3646 cifs_buf_release(pSMB
);
3648 goto UnixQPathInfoRetry
;
3653 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3655 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3656 const char *searchName
,
3657 const struct nls_table
*nls_codepage
,
3659 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3661 /* level 257 SMB_ */
3662 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3663 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3664 T2_FFIRST_RSP_PARMS
*parms
;
3666 int bytes_returned
= 0;
3668 __u16 params
, byte_count
;
3670 cFYI(1, "In FindFirst for %s", searchName
);
3673 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3678 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3680 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3681 PATH_MAX
, nls_codepage
, remap
);
3682 /* We can not add the asterik earlier in case
3683 it got remapped to 0xF03A as if it were part of the
3684 directory name instead of a wildcard */
3686 pSMB
->FileName
[name_len
] = dirsep
;
3687 pSMB
->FileName
[name_len
+1] = 0;
3688 pSMB
->FileName
[name_len
+2] = '*';
3689 pSMB
->FileName
[name_len
+3] = 0;
3690 name_len
+= 4; /* now the trailing null */
3691 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3692 pSMB
->FileName
[name_len
+1] = 0;
3694 } else { /* BB add check for overrun of SMB buf BB */
3695 name_len
= strnlen(searchName
, PATH_MAX
);
3696 /* BB fix here and in unicode clause above ie
3697 if (name_len > buffersize-header)
3698 free buffer exit; BB */
3699 strncpy(pSMB
->FileName
, searchName
, name_len
);
3700 pSMB
->FileName
[name_len
] = dirsep
;
3701 pSMB
->FileName
[name_len
+1] = '*';
3702 pSMB
->FileName
[name_len
+2] = 0;
3706 params
= 12 + name_len
/* includes null */ ;
3707 pSMB
->TotalDataCount
= 0; /* no EAs */
3708 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3709 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3710 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3711 pSMB
->MaxSetupCount
= 0;
3715 pSMB
->Reserved2
= 0;
3716 byte_count
= params
+ 1 /* pad */ ;
3717 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3718 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3719 pSMB
->ParameterOffset
= cpu_to_le16(
3720 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3722 pSMB
->DataCount
= 0;
3723 pSMB
->DataOffset
= 0;
3724 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3725 pSMB
->Reserved3
= 0;
3726 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3727 pSMB
->SearchAttributes
=
3728 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3730 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3731 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3732 CIFS_SEARCH_RETURN_RESUME
);
3733 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3735 /* BB what should we set StorageType to? Does it matter? BB */
3736 pSMB
->SearchStorageType
= 0;
3737 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3738 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3740 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3741 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3742 cifs_stats_inc(&tcon
->num_ffirst
);
3744 if (rc
) {/* BB add logic to retry regular search if Unix search
3745 rejected unexpectedly by server */
3746 /* BB Add code to handle unsupported level rc */
3747 cFYI(1, "Error in FindFirst = %d", rc
);
3749 cifs_buf_release(pSMB
);
3751 /* BB eventually could optimize out free and realloc of buf */
3754 goto findFirstRetry
;
3755 } else { /* decode response */
3756 /* BB remember to free buffer if error BB */
3757 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3761 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3762 psrch_inf
->unicode
= true;
3764 psrch_inf
->unicode
= false;
3766 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3767 psrch_inf
->smallBuf
= 0;
3768 psrch_inf
->srch_entries_start
=
3769 (char *) &pSMBr
->hdr
.Protocol
+
3770 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3771 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3772 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3774 if (parms
->EndofSearch
)
3775 psrch_inf
->endOfSearch
= true;
3777 psrch_inf
->endOfSearch
= false;
3779 psrch_inf
->entries_in_buffer
=
3780 le16_to_cpu(parms
->SearchCount
);
3781 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3782 psrch_inf
->entries_in_buffer
;
3783 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3784 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3786 cERROR(1, "ignoring corrupt resume name");
3787 psrch_inf
->last_entry
= NULL
;
3791 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3794 *pnetfid
= parms
->SearchHandle
;
3796 cifs_buf_release(pSMB
);
3803 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3804 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3806 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3807 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3808 T2_FNEXT_RSP_PARMS
*parms
;
3809 char *response_data
;
3811 int bytes_returned
, name_len
;
3812 __u16 params
, byte_count
;
3814 cFYI(1, "In FindNext");
3816 if (psrch_inf
->endOfSearch
)
3819 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3824 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3826 pSMB
->TotalDataCount
= 0; /* no EAs */
3827 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3828 pSMB
->MaxDataCount
=
3829 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3831 pSMB
->MaxSetupCount
= 0;
3835 pSMB
->Reserved2
= 0;
3836 pSMB
->ParameterOffset
= cpu_to_le16(
3837 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3838 pSMB
->DataCount
= 0;
3839 pSMB
->DataOffset
= 0;
3840 pSMB
->SetupCount
= 1;
3841 pSMB
->Reserved3
= 0;
3842 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3843 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3845 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3846 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3847 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3849 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3851 name_len
= psrch_inf
->resume_name_len
;
3853 if (name_len
< PATH_MAX
) {
3854 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3855 byte_count
+= name_len
;
3856 /* 14 byte parm len above enough for 2 byte null terminator */
3857 pSMB
->ResumeFileName
[name_len
] = 0;
3858 pSMB
->ResumeFileName
[name_len
+1] = 0;
3861 goto FNext2_err_exit
;
3863 byte_count
= params
+ 1 /* pad */ ;
3864 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3865 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3866 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3867 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3869 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3870 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3871 cifs_stats_inc(&tcon
->num_fnext
);
3874 psrch_inf
->endOfSearch
= true;
3875 cifs_buf_release(pSMB
);
3876 rc
= 0; /* search probably was closed at end of search*/
3878 cFYI(1, "FindNext returned = %d", rc
);
3879 } else { /* decode response */
3880 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3885 /* BB fixme add lock for file (srch_info) struct here */
3886 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3887 psrch_inf
->unicode
= true;
3889 psrch_inf
->unicode
= false;
3890 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3891 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3892 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3893 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3894 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3895 if (psrch_inf
->smallBuf
)
3896 cifs_small_buf_release(
3897 psrch_inf
->ntwrk_buf_start
);
3899 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3900 psrch_inf
->srch_entries_start
= response_data
;
3901 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3902 psrch_inf
->smallBuf
= 0;
3903 if (parms
->EndofSearch
)
3904 psrch_inf
->endOfSearch
= true;
3906 psrch_inf
->endOfSearch
= false;
3907 psrch_inf
->entries_in_buffer
=
3908 le16_to_cpu(parms
->SearchCount
);
3909 psrch_inf
->index_of_last_entry
+=
3910 psrch_inf
->entries_in_buffer
;
3911 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3912 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3914 cERROR(1, "ignoring corrupt resume name");
3915 psrch_inf
->last_entry
= NULL
;
3918 psrch_inf
->last_entry
=
3919 psrch_inf
->srch_entries_start
+ lnoff
;
3921 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3922 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3924 /* BB fixme add unlock here */
3929 /* BB On error, should we leave previous search buf (and count and
3930 last entry fields) intact or free the previous one? */
3932 /* Note: On -EAGAIN error only caller can retry on handle based calls
3933 since file handle passed in no longer valid */
3936 cifs_buf_release(pSMB
);
3941 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3942 const __u16 searchHandle
)
3945 FINDCLOSE_REQ
*pSMB
= NULL
;
3947 cFYI(1, "In CIFSSMBFindClose");
3948 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3950 /* no sense returning error if session restarted
3951 as file handle has been closed */
3957 pSMB
->FileID
= searchHandle
;
3958 pSMB
->ByteCount
= 0;
3959 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3961 cERROR(1, "Send error in FindClose = %d", rc
);
3963 cifs_stats_inc(&tcon
->num_fclose
);
3965 /* Since session is dead, search handle closed on server already */
3973 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3974 const unsigned char *searchName
,
3975 __u64
*inode_number
,
3976 const struct nls_table
*nls_codepage
, int remap
)
3979 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3980 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3981 int name_len
, bytes_returned
;
3982 __u16 params
, byte_count
;
3984 cFYI(1, "In GetSrvInodeNum for %s", searchName
);
3988 GetInodeNumberRetry
:
3989 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3994 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3996 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3997 PATH_MAX
, nls_codepage
, remap
);
3998 name_len
++; /* trailing null */
4000 } else { /* BB improve the check for buffer overruns BB */
4001 name_len
= strnlen(searchName
, PATH_MAX
);
4002 name_len
++; /* trailing null */
4003 strncpy(pSMB
->FileName
, searchName
, name_len
);
4006 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
4007 pSMB
->TotalDataCount
= 0;
4008 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4009 /* BB find exact max data count below from sess structure BB */
4010 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4011 pSMB
->MaxSetupCount
= 0;
4015 pSMB
->Reserved2
= 0;
4016 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4017 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
4018 pSMB
->DataCount
= 0;
4019 pSMB
->DataOffset
= 0;
4020 pSMB
->SetupCount
= 1;
4021 pSMB
->Reserved3
= 0;
4022 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4023 byte_count
= params
+ 1 /* pad */ ;
4024 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4025 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4026 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
4027 pSMB
->Reserved4
= 0;
4028 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4029 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4031 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4032 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4034 cFYI(1, "error %d in QueryInternalInfo", rc
);
4036 /* decode response */
4037 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4038 if (rc
|| (pSMBr
->ByteCount
< 2))
4039 /* BB also check enough total bytes returned */
4040 /* If rc should we check for EOPNOSUPP and
4041 disable the srvino flag? or in caller? */
4042 rc
= -EIO
; /* bad smb */
4044 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4045 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
4046 struct file_internal_info
*pfinfo
;
4047 /* BB Do we need a cast or hash here ? */
4049 cFYI(1, "Illegal size ret in QryIntrnlInf");
4051 goto GetInodeNumOut
;
4053 pfinfo
= (struct file_internal_info
*)
4054 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
4055 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
4059 cifs_buf_release(pSMB
);
4061 goto GetInodeNumberRetry
;
4065 /* parses DFS refferal V3 structure
4066 * caller is responsible for freeing target_nodes
4069 * on failure - errno
4072 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
4073 unsigned int *num_of_nodes
,
4074 struct dfs_info3_param
**target_nodes
,
4075 const struct nls_table
*nls_codepage
, int remap
,
4076 const char *searchName
)
4081 struct dfs_referral_level_3
*ref
;
4083 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4087 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
4089 if (*num_of_nodes
< 1) {
4090 cERROR(1, "num_referrals: must be at least > 0,"
4091 "but we get num_referrals = %d\n", *num_of_nodes
);
4093 goto parse_DFS_referrals_exit
;
4096 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
4097 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4098 cERROR(1, "Referrals of V%d version are not supported,"
4099 "should be V3", le16_to_cpu(ref
->VersionNumber
));
4101 goto parse_DFS_referrals_exit
;
4104 /* get the upper boundary of the resp buffer */
4105 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4106 le16_to_cpu(pSMBr
->t2
.DataCount
);
4108 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4110 le32_to_cpu(pSMBr
->DFSFlags
));
4112 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4113 *num_of_nodes
, GFP_KERNEL
);
4114 if (*target_nodes
== NULL
) {
4115 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4117 goto parse_DFS_referrals_exit
;
4120 /* collect necessary data from referrals */
4121 for (i
= 0; i
< *num_of_nodes
; i
++) {
4124 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4126 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4128 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4132 goto parse_DFS_referrals_exit
;
4134 cifsConvertToUCS((__le16
*) tmp
, searchName
,
4135 PATH_MAX
, nls_codepage
, remap
);
4136 node
->path_consumed
= cifs_ucs2_bytes(tmp
,
4137 le16_to_cpu(pSMBr
->PathConsumed
),
4141 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4143 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4144 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4147 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4148 max_len
= data_end
- temp
;
4149 node
->path_name
= cifs_strndup_from_ucs(temp
, max_len
,
4150 is_unicode
, nls_codepage
);
4151 if (!node
->path_name
) {
4153 goto parse_DFS_referrals_exit
;
4156 /* copy link target UNC */
4157 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4158 max_len
= data_end
- temp
;
4159 node
->node_name
= cifs_strndup_from_ucs(temp
, max_len
,
4160 is_unicode
, nls_codepage
);
4161 if (!node
->node_name
)
4165 parse_DFS_referrals_exit
:
4167 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4168 *target_nodes
= NULL
;
4175 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4176 const unsigned char *searchName
,
4177 struct dfs_info3_param
**target_nodes
,
4178 unsigned int *num_of_nodes
,
4179 const struct nls_table
*nls_codepage
, int remap
)
4181 /* TRANS2_GET_DFS_REFERRAL */
4182 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4183 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4187 __u16 params
, byte_count
;
4189 *target_nodes
= NULL
;
4191 cFYI(1, "In GetDFSRefer the path %s", searchName
);
4195 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4200 /* server pointer checked in called function,
4201 but should never be null here anyway */
4202 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4203 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4204 pSMB
->hdr
.Uid
= ses
->Suid
;
4205 if (ses
->capabilities
& CAP_STATUS32
)
4206 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4207 if (ses
->capabilities
& CAP_DFS
)
4208 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4210 if (ses
->capabilities
& CAP_UNICODE
) {
4211 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4213 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4214 searchName
, PATH_MAX
, nls_codepage
, remap
);
4215 name_len
++; /* trailing null */
4217 } else { /* BB improve the check for buffer overruns BB */
4218 name_len
= strnlen(searchName
, PATH_MAX
);
4219 name_len
++; /* trailing null */
4220 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4224 if (ses
->server
->secMode
&
4225 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4226 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4229 pSMB
->hdr
.Uid
= ses
->Suid
;
4231 params
= 2 /* level */ + name_len
/*includes null */ ;
4232 pSMB
->TotalDataCount
= 0;
4233 pSMB
->DataCount
= 0;
4234 pSMB
->DataOffset
= 0;
4235 pSMB
->MaxParameterCount
= 0;
4236 /* BB find exact max SMB PDU from sess structure BB */
4237 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4238 pSMB
->MaxSetupCount
= 0;
4242 pSMB
->Reserved2
= 0;
4243 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4244 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4245 pSMB
->SetupCount
= 1;
4246 pSMB
->Reserved3
= 0;
4247 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4248 byte_count
= params
+ 3 /* pad */ ;
4249 pSMB
->ParameterCount
= cpu_to_le16(params
);
4250 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4251 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4252 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4253 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4255 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4256 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4258 cFYI(1, "Send error in GetDFSRefer = %d", rc
);
4261 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4263 /* BB Also check if enough total bytes returned? */
4264 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4265 rc
= -EIO
; /* bad smb */
4269 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4271 le16_to_cpu(pSMBr
->t2
.DataOffset
));
4273 /* parse returned result into more usable form */
4274 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4275 target_nodes
, nls_codepage
, remap
,
4279 cifs_buf_release(pSMB
);
4287 /* Query File System Info such as free space to old servers such as Win 9x */
4289 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4291 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4292 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4293 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4294 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4296 int bytes_returned
= 0;
4297 __u16 params
, byte_count
;
4299 cFYI(1, "OldQFSInfo");
4301 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4306 params
= 2; /* level */
4307 pSMB
->TotalDataCount
= 0;
4308 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4309 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4310 pSMB
->MaxSetupCount
= 0;
4314 pSMB
->Reserved2
= 0;
4315 byte_count
= params
+ 1 /* pad */ ;
4316 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4317 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4318 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4319 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4320 pSMB
->DataCount
= 0;
4321 pSMB
->DataOffset
= 0;
4322 pSMB
->SetupCount
= 1;
4323 pSMB
->Reserved3
= 0;
4324 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4325 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4326 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4327 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4329 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4330 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4332 cFYI(1, "Send error in QFSInfo = %d", rc
);
4333 } else { /* decode response */
4334 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4336 if (rc
|| (pSMBr
->ByteCount
< 18))
4337 rc
= -EIO
; /* bad smb */
4339 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4340 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4341 pSMBr
->ByteCount
, data_offset
);
4343 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4344 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4346 le16_to_cpu(response_data
->BytesPerSector
) *
4347 le32_to_cpu(response_data
->
4348 SectorsPerAllocationUnit
);
4350 le32_to_cpu(response_data
->TotalAllocationUnits
);
4351 FSData
->f_bfree
= FSData
->f_bavail
=
4352 le32_to_cpu(response_data
->FreeAllocationUnits
);
4353 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4354 (unsigned long long)FSData
->f_blocks
,
4355 (unsigned long long)FSData
->f_bfree
,
4359 cifs_buf_release(pSMB
);
4362 goto oldQFSInfoRetry
;
4368 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4370 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4371 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4372 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4373 FILE_SYSTEM_INFO
*response_data
;
4375 int bytes_returned
= 0;
4376 __u16 params
, byte_count
;
4378 cFYI(1, "In QFSInfo");
4380 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4385 params
= 2; /* level */
4386 pSMB
->TotalDataCount
= 0;
4387 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4388 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4389 pSMB
->MaxSetupCount
= 0;
4393 pSMB
->Reserved2
= 0;
4394 byte_count
= params
+ 1 /* pad */ ;
4395 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4396 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4397 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4398 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4399 pSMB
->DataCount
= 0;
4400 pSMB
->DataOffset
= 0;
4401 pSMB
->SetupCount
= 1;
4402 pSMB
->Reserved3
= 0;
4403 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4404 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4405 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4406 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4408 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4409 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4411 cFYI(1, "Send error in QFSInfo = %d", rc
);
4412 } else { /* decode response */
4413 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4415 if (rc
|| (pSMBr
->ByteCount
< 24))
4416 rc
= -EIO
; /* bad smb */
4418 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4422 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4425 le32_to_cpu(response_data
->BytesPerSector
) *
4426 le32_to_cpu(response_data
->
4427 SectorsPerAllocationUnit
);
4429 le64_to_cpu(response_data
->TotalAllocationUnits
);
4430 FSData
->f_bfree
= FSData
->f_bavail
=
4431 le64_to_cpu(response_data
->FreeAllocationUnits
);
4432 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4433 (unsigned long long)FSData
->f_blocks
,
4434 (unsigned long long)FSData
->f_bfree
,
4438 cifs_buf_release(pSMB
);
4447 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4449 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4450 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4451 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4452 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4454 int bytes_returned
= 0;
4455 __u16 params
, byte_count
;
4457 cFYI(1, "In QFSAttributeInfo");
4459 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4464 params
= 2; /* level */
4465 pSMB
->TotalDataCount
= 0;
4466 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4467 /* BB find exact max SMB PDU from sess structure BB */
4468 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4469 pSMB
->MaxSetupCount
= 0;
4473 pSMB
->Reserved2
= 0;
4474 byte_count
= params
+ 1 /* pad */ ;
4475 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4476 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4477 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4478 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4479 pSMB
->DataCount
= 0;
4480 pSMB
->DataOffset
= 0;
4481 pSMB
->SetupCount
= 1;
4482 pSMB
->Reserved3
= 0;
4483 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4484 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4485 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4486 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4488 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4489 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4491 cERROR(1, "Send error in QFSAttributeInfo = %d", rc
);
4492 } else { /* decode response */
4493 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4495 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4496 /* BB also check if enough bytes returned */
4497 rc
= -EIO
; /* bad smb */
4499 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4501 (FILE_SYSTEM_ATTRIBUTE_INFO
4502 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4504 memcpy(&tcon
->fsAttrInfo
, response_data
,
4505 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4508 cifs_buf_release(pSMB
);
4511 goto QFSAttributeRetry
;
4517 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4519 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4520 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4521 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4522 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4524 int bytes_returned
= 0;
4525 __u16 params
, byte_count
;
4527 cFYI(1, "In QFSDeviceInfo");
4529 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4534 params
= 2; /* level */
4535 pSMB
->TotalDataCount
= 0;
4536 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4537 /* BB find exact max SMB PDU from sess structure BB */
4538 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4539 pSMB
->MaxSetupCount
= 0;
4543 pSMB
->Reserved2
= 0;
4544 byte_count
= params
+ 1 /* pad */ ;
4545 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4546 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4547 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4548 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4550 pSMB
->DataCount
= 0;
4551 pSMB
->DataOffset
= 0;
4552 pSMB
->SetupCount
= 1;
4553 pSMB
->Reserved3
= 0;
4554 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4555 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4556 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4557 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4559 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4560 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4562 cFYI(1, "Send error in QFSDeviceInfo = %d", rc
);
4563 } else { /* decode response */
4564 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4566 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4567 rc
= -EIO
; /* bad smb */
4569 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4571 (FILE_SYSTEM_DEVICE_INFO
*)
4572 (((char *) &pSMBr
->hdr
.Protocol
) +
4574 memcpy(&tcon
->fsDevInfo
, response_data
,
4575 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4578 cifs_buf_release(pSMB
);
4581 goto QFSDeviceRetry
;
4587 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4589 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4590 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4591 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4592 FILE_SYSTEM_UNIX_INFO
*response_data
;
4594 int bytes_returned
= 0;
4595 __u16 params
, byte_count
;
4597 cFYI(1, "In QFSUnixInfo");
4599 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4600 (void **) &pSMB
, (void **) &pSMBr
);
4604 params
= 2; /* level */
4605 pSMB
->TotalDataCount
= 0;
4606 pSMB
->DataCount
= 0;
4607 pSMB
->DataOffset
= 0;
4608 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4609 /* BB find exact max SMB PDU from sess structure BB */
4610 pSMB
->MaxDataCount
= cpu_to_le16(100);
4611 pSMB
->MaxSetupCount
= 0;
4615 pSMB
->Reserved2
= 0;
4616 byte_count
= params
+ 1 /* pad */ ;
4617 pSMB
->ParameterCount
= cpu_to_le16(params
);
4618 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4619 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4620 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4621 pSMB
->SetupCount
= 1;
4622 pSMB
->Reserved3
= 0;
4623 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4624 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4625 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4626 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4628 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4629 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4631 cERROR(1, "Send error in QFSUnixInfo = %d", rc
);
4632 } else { /* decode response */
4633 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4635 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4636 rc
= -EIO
; /* bad smb */
4638 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4640 (FILE_SYSTEM_UNIX_INFO
4641 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4643 memcpy(&tcon
->fsUnixInfo
, response_data
,
4644 sizeof(FILE_SYSTEM_UNIX_INFO
));
4647 cifs_buf_release(pSMB
);
4657 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4659 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4660 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4661 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4663 int bytes_returned
= 0;
4664 __u16 params
, param_offset
, offset
, byte_count
;
4666 cFYI(1, "In SETFSUnixInfo");
4668 /* BB switch to small buf init to save memory */
4669 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4670 (void **) &pSMB
, (void **) &pSMBr
);
4674 params
= 4; /* 2 bytes zero followed by info level. */
4675 pSMB
->MaxSetupCount
= 0;
4679 pSMB
->Reserved2
= 0;
4680 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4682 offset
= param_offset
+ params
;
4684 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4685 /* BB find exact max SMB PDU from sess structure BB */
4686 pSMB
->MaxDataCount
= cpu_to_le16(100);
4687 pSMB
->SetupCount
= 1;
4688 pSMB
->Reserved3
= 0;
4689 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4690 byte_count
= 1 /* pad */ + params
+ 12;
4692 pSMB
->DataCount
= cpu_to_le16(12);
4693 pSMB
->ParameterCount
= cpu_to_le16(params
);
4694 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4695 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4696 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4697 pSMB
->DataOffset
= cpu_to_le16(offset
);
4701 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4704 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4705 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4706 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4708 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4709 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4711 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4712 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4714 cERROR(1, "Send error in SETFSUnixInfo = %d", rc
);
4715 } else { /* decode response */
4716 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4718 rc
= -EIO
; /* bad smb */
4720 cifs_buf_release(pSMB
);
4723 goto SETFSUnixRetry
;
4731 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4732 struct kstatfs
*FSData
)
4734 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4735 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4736 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4737 FILE_SYSTEM_POSIX_INFO
*response_data
;
4739 int bytes_returned
= 0;
4740 __u16 params
, byte_count
;
4742 cFYI(1, "In QFSPosixInfo");
4744 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4749 params
= 2; /* level */
4750 pSMB
->TotalDataCount
= 0;
4751 pSMB
->DataCount
= 0;
4752 pSMB
->DataOffset
= 0;
4753 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4754 /* BB find exact max SMB PDU from sess structure BB */
4755 pSMB
->MaxDataCount
= cpu_to_le16(100);
4756 pSMB
->MaxSetupCount
= 0;
4760 pSMB
->Reserved2
= 0;
4761 byte_count
= params
+ 1 /* pad */ ;
4762 pSMB
->ParameterCount
= cpu_to_le16(params
);
4763 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4764 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4765 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4766 pSMB
->SetupCount
= 1;
4767 pSMB
->Reserved3
= 0;
4768 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4769 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4770 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4771 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4773 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4774 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4776 cFYI(1, "Send error in QFSUnixInfo = %d", rc
);
4777 } else { /* decode response */
4778 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4780 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4781 rc
= -EIO
; /* bad smb */
4783 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4785 (FILE_SYSTEM_POSIX_INFO
4786 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4789 le32_to_cpu(response_data
->BlockSize
);
4791 le64_to_cpu(response_data
->TotalBlocks
);
4793 le64_to_cpu(response_data
->BlocksAvail
);
4794 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4795 FSData
->f_bavail
= FSData
->f_bfree
;
4798 le64_to_cpu(response_data
->UserBlocksAvail
);
4800 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4802 le64_to_cpu(response_data
->TotalFileNodes
);
4803 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4805 le64_to_cpu(response_data
->FreeFileNodes
);
4808 cifs_buf_release(pSMB
);
4817 /* We can not use write of zero bytes trick to
4818 set file size due to need for large file support. Also note that
4819 this SetPathInfo is preferred to SetFileInfo based method in next
4820 routine which is only needed to work around a sharing violation bug
4821 in Samba which this routine can run into */
4824 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4825 __u64 size
, bool SetAllocation
,
4826 const struct nls_table
*nls_codepage
, int remap
)
4828 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4829 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4830 struct file_end_of_file_info
*parm_data
;
4833 int bytes_returned
= 0;
4834 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4836 cFYI(1, "In SetEOF");
4838 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4843 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4845 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4846 PATH_MAX
, nls_codepage
, remap
);
4847 name_len
++; /* trailing null */
4849 } else { /* BB improve the check for buffer overruns BB */
4850 name_len
= strnlen(fileName
, PATH_MAX
);
4851 name_len
++; /* trailing null */
4852 strncpy(pSMB
->FileName
, fileName
, name_len
);
4854 params
= 6 + name_len
;
4855 data_count
= sizeof(struct file_end_of_file_info
);
4856 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4857 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4858 pSMB
->MaxSetupCount
= 0;
4862 pSMB
->Reserved2
= 0;
4863 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4864 InformationLevel
) - 4;
4865 offset
= param_offset
+ params
;
4866 if (SetAllocation
) {
4867 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4868 pSMB
->InformationLevel
=
4869 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4871 pSMB
->InformationLevel
=
4872 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4873 } else /* Set File Size */ {
4874 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4875 pSMB
->InformationLevel
=
4876 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4878 pSMB
->InformationLevel
=
4879 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4883 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4885 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4886 pSMB
->DataOffset
= cpu_to_le16(offset
);
4887 pSMB
->SetupCount
= 1;
4888 pSMB
->Reserved3
= 0;
4889 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4890 byte_count
= 3 /* pad */ + params
+ data_count
;
4891 pSMB
->DataCount
= cpu_to_le16(data_count
);
4892 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4893 pSMB
->ParameterCount
= cpu_to_le16(params
);
4894 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4895 pSMB
->Reserved4
= 0;
4896 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4897 parm_data
->FileSize
= cpu_to_le64(size
);
4898 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4899 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4900 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4902 cFYI(1, "SetPathInfo (file size) returned %d", rc
);
4904 cifs_buf_release(pSMB
);
4913 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4914 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4916 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4918 struct file_end_of_file_info
*parm_data
;
4920 __u16 params
, param_offset
, offset
, byte_count
, count
;
4922 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4924 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4929 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4930 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4933 pSMB
->MaxSetupCount
= 0;
4937 pSMB
->Reserved2
= 0;
4938 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4939 offset
= param_offset
+ params
;
4941 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4943 count
= sizeof(struct file_end_of_file_info
);
4944 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4945 /* BB find exact max SMB PDU from sess structure BB */
4946 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4947 pSMB
->SetupCount
= 1;
4948 pSMB
->Reserved3
= 0;
4949 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4950 byte_count
= 3 /* pad */ + params
+ count
;
4951 pSMB
->DataCount
= cpu_to_le16(count
);
4952 pSMB
->ParameterCount
= cpu_to_le16(params
);
4953 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4954 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4955 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4957 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4959 pSMB
->DataOffset
= cpu_to_le16(offset
);
4960 parm_data
->FileSize
= cpu_to_le64(size
);
4962 if (SetAllocation
) {
4963 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4964 pSMB
->InformationLevel
=
4965 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4967 pSMB
->InformationLevel
=
4968 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4969 } else /* Set File Size */ {
4970 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4971 pSMB
->InformationLevel
=
4972 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4974 pSMB
->InformationLevel
=
4975 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4977 pSMB
->Reserved4
= 0;
4978 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4979 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4980 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4982 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc
);
4985 /* Note: On -EAGAIN error only caller can retry on handle based calls
4986 since file handle passed in no longer valid */
4991 /* Some legacy servers such as NT4 require that the file times be set on
4992 an open handle, rather than by pathname - this is awkward due to
4993 potential access conflicts on the open, but it is unavoidable for these
4994 old servers since the only other choice is to go from 100 nanosecond DCE
4995 time and resort to the original setpathinfo level which takes the ancient
4996 DOS time format with 2 second granularity */
4998 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
4999 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
5001 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5004 __u16 params
, param_offset
, offset
, byte_count
, count
;
5006 cFYI(1, "Set Times (via SetFileInfo)");
5007 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5012 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5013 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5016 pSMB
->MaxSetupCount
= 0;
5020 pSMB
->Reserved2
= 0;
5021 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5022 offset
= param_offset
+ params
;
5024 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5026 count
= sizeof(FILE_BASIC_INFO
);
5027 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5028 /* BB find max SMB PDU from sess */
5029 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5030 pSMB
->SetupCount
= 1;
5031 pSMB
->Reserved3
= 0;
5032 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5033 byte_count
= 3 /* pad */ + params
+ count
;
5034 pSMB
->DataCount
= cpu_to_le16(count
);
5035 pSMB
->ParameterCount
= cpu_to_le16(params
);
5036 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5037 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5038 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5039 pSMB
->DataOffset
= cpu_to_le16(offset
);
5041 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5042 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5044 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5045 pSMB
->Reserved4
= 0;
5046 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5047 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5048 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5049 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5051 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5053 /* Note: On -EAGAIN error only caller can retry on handle based calls
5054 since file handle passed in no longer valid */
5060 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
5061 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
5063 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5066 __u16 params
, param_offset
, offset
, byte_count
, count
;
5068 cFYI(1, "Set File Disposition (via SetFileInfo)");
5069 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5074 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5075 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5078 pSMB
->MaxSetupCount
= 0;
5082 pSMB
->Reserved2
= 0;
5083 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5084 offset
= param_offset
+ params
;
5086 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5089 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5090 /* BB find max SMB PDU from sess */
5091 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5092 pSMB
->SetupCount
= 1;
5093 pSMB
->Reserved3
= 0;
5094 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5095 byte_count
= 3 /* pad */ + params
+ count
;
5096 pSMB
->DataCount
= cpu_to_le16(count
);
5097 pSMB
->ParameterCount
= cpu_to_le16(params
);
5098 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5099 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5100 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5101 pSMB
->DataOffset
= cpu_to_le16(offset
);
5103 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5104 pSMB
->Reserved4
= 0;
5105 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5106 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5107 *data_offset
= delete_file
? 1 : 0;
5108 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5110 cFYI(1, "Send error in SetFileDisposition = %d", rc
);
5116 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
5117 const char *fileName
, const FILE_BASIC_INFO
*data
,
5118 const struct nls_table
*nls_codepage
, int remap
)
5120 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5121 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5124 int bytes_returned
= 0;
5126 __u16 params
, param_offset
, offset
, byte_count
, count
;
5128 cFYI(1, "In SetTimes");
5131 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5136 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5138 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5139 PATH_MAX
, nls_codepage
, remap
);
5140 name_len
++; /* trailing null */
5142 } else { /* BB improve the check for buffer overruns BB */
5143 name_len
= strnlen(fileName
, PATH_MAX
);
5144 name_len
++; /* trailing null */
5145 strncpy(pSMB
->FileName
, fileName
, name_len
);
5148 params
= 6 + name_len
;
5149 count
= sizeof(FILE_BASIC_INFO
);
5150 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5151 /* BB find max SMB PDU from sess structure BB */
5152 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5153 pSMB
->MaxSetupCount
= 0;
5157 pSMB
->Reserved2
= 0;
5158 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5159 InformationLevel
) - 4;
5160 offset
= param_offset
+ params
;
5161 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5162 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5163 pSMB
->DataOffset
= cpu_to_le16(offset
);
5164 pSMB
->SetupCount
= 1;
5165 pSMB
->Reserved3
= 0;
5166 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5167 byte_count
= 3 /* pad */ + params
+ count
;
5169 pSMB
->DataCount
= cpu_to_le16(count
);
5170 pSMB
->ParameterCount
= cpu_to_le16(params
);
5171 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5172 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5173 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5174 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5176 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5177 pSMB
->Reserved4
= 0;
5178 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5179 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5180 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5181 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5182 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5184 cFYI(1, "SetPathInfo (times) returned %d", rc
);
5186 cifs_buf_release(pSMB
);
5194 /* Can not be used to set time stamps yet (due to old DOS time format) */
5195 /* Can be used to set attributes */
5196 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5197 handling it anyway and NT4 was what we thought it would be needed for
5198 Do not delete it until we prove whether needed for Win9x though */
5200 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5201 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5203 SETATTR_REQ
*pSMB
= NULL
;
5204 SETATTR_RSP
*pSMBr
= NULL
;
5209 cFYI(1, "In SetAttrLegacy");
5212 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5217 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5219 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5220 PATH_MAX
, nls_codepage
);
5221 name_len
++; /* trailing null */
5223 } else { /* BB improve the check for buffer overruns BB */
5224 name_len
= strnlen(fileName
, PATH_MAX
);
5225 name_len
++; /* trailing null */
5226 strncpy(pSMB
->fileName
, fileName
, name_len
);
5228 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5229 pSMB
->BufferFormat
= 0x04;
5230 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5231 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5232 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5233 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5235 cFYI(1, "Error in LegacySetAttr = %d", rc
);
5237 cifs_buf_release(pSMB
);
5240 goto SetAttrLgcyRetry
;
5244 #endif /* temporarily unneeded SetAttr legacy function */
5247 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5248 const struct cifs_unix_set_info_args
*args
)
5250 u64 mode
= args
->mode
;
5253 * Samba server ignores set of file size to zero due to bugs in some
5254 * older clients, but we should be precise - we use SetFileSize to
5255 * set file size and do not want to truncate file size to zero
5256 * accidently as happened on one Samba server beta by putting
5257 * zero instead of -1 here
5259 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5260 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5261 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5262 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5263 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5264 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5265 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5266 /* better to leave device as zero when it is */
5267 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5268 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5269 data_offset
->Permissions
= cpu_to_le64(mode
);
5272 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5273 else if (S_ISDIR(mode
))
5274 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5275 else if (S_ISLNK(mode
))
5276 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5277 else if (S_ISCHR(mode
))
5278 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5279 else if (S_ISBLK(mode
))
5280 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5281 else if (S_ISFIFO(mode
))
5282 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5283 else if (S_ISSOCK(mode
))
5284 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5288 CIFSSMBUnixSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
5289 const struct cifs_unix_set_info_args
*args
,
5290 u16 fid
, u32 pid_of_opener
)
5292 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5293 FILE_UNIX_BASIC_INFO
*data_offset
;
5295 u16 params
, param_offset
, offset
, byte_count
, count
;
5297 cFYI(1, "Set Unix Info (via SetFileInfo)");
5298 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5303 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5304 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5307 pSMB
->MaxSetupCount
= 0;
5311 pSMB
->Reserved2
= 0;
5312 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5313 offset
= param_offset
+ params
;
5315 data_offset
= (FILE_UNIX_BASIC_INFO
*)
5316 ((char *)(&pSMB
->hdr
.Protocol
) + offset
);
5317 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5319 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5320 /* BB find max SMB PDU from sess */
5321 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5322 pSMB
->SetupCount
= 1;
5323 pSMB
->Reserved3
= 0;
5324 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5325 byte_count
= 3 /* pad */ + params
+ count
;
5326 pSMB
->DataCount
= cpu_to_le16(count
);
5327 pSMB
->ParameterCount
= cpu_to_le16(params
);
5328 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5329 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5330 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5331 pSMB
->DataOffset
= cpu_to_le16(offset
);
5333 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5334 pSMB
->Reserved4
= 0;
5335 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5336 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5338 cifs_fill_unix_set_info(data_offset
, args
);
5340 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5342 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5344 /* Note: On -EAGAIN error only caller can retry on handle based calls
5345 since file handle passed in no longer valid */
5351 CIFSSMBUnixSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5352 const struct cifs_unix_set_info_args
*args
,
5353 const struct nls_table
*nls_codepage
, int remap
)
5355 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5356 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5359 int bytes_returned
= 0;
5360 FILE_UNIX_BASIC_INFO
*data_offset
;
5361 __u16 params
, param_offset
, offset
, count
, byte_count
;
5363 cFYI(1, "In SetUID/GID/Mode");
5365 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5370 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5372 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5373 PATH_MAX
, nls_codepage
, remap
);
5374 name_len
++; /* trailing null */
5376 } else { /* BB improve the check for buffer overruns BB */
5377 name_len
= strnlen(fileName
, PATH_MAX
);
5378 name_len
++; /* trailing null */
5379 strncpy(pSMB
->FileName
, fileName
, name_len
);
5382 params
= 6 + name_len
;
5383 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5384 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5385 /* BB find max SMB PDU from sess structure BB */
5386 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5387 pSMB
->MaxSetupCount
= 0;
5391 pSMB
->Reserved2
= 0;
5392 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5393 InformationLevel
) - 4;
5394 offset
= param_offset
+ params
;
5396 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5398 memset(data_offset
, 0, count
);
5399 pSMB
->DataOffset
= cpu_to_le16(offset
);
5400 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5401 pSMB
->SetupCount
= 1;
5402 pSMB
->Reserved3
= 0;
5403 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5404 byte_count
= 3 /* pad */ + params
+ count
;
5405 pSMB
->ParameterCount
= cpu_to_le16(params
);
5406 pSMB
->DataCount
= cpu_to_le16(count
);
5407 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5408 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5409 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5410 pSMB
->Reserved4
= 0;
5411 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5413 cifs_fill_unix_set_info(data_offset
, args
);
5415 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5416 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5417 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5419 cFYI(1, "SetPathInfo (perms) returned %d", rc
);
5421 cifs_buf_release(pSMB
);
5427 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5428 const int notify_subdirs
, const __u16 netfid
,
5429 __u32 filter
, struct file
*pfile
, int multishot
,
5430 const struct nls_table
*nls_codepage
)
5433 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5434 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5435 struct dir_notify_req
*dnotify_req
;
5438 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid
);
5439 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5444 pSMB
->TotalParameterCount
= 0 ;
5445 pSMB
->TotalDataCount
= 0;
5446 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5447 /* BB find exact data count max from sess structure BB */
5448 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5449 /* BB VERIFY verify which is correct for above BB */
5450 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5451 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5453 pSMB
->MaxSetupCount
= 4;
5455 pSMB
->ParameterOffset
= 0;
5456 pSMB
->DataCount
= 0;
5457 pSMB
->DataOffset
= 0;
5458 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5459 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5460 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5462 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5463 pSMB
->Reserved2
= 0;
5464 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5465 pSMB
->Fid
= netfid
; /* file handle always le */
5466 pSMB
->ByteCount
= 0;
5468 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5469 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5472 cFYI(1, "Error in Notify = %d", rc
);
5474 /* Add file to outstanding requests */
5475 /* BB change to kmem cache alloc */
5476 dnotify_req
= kmalloc(
5477 sizeof(struct dir_notify_req
),
5480 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5481 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5482 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5483 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5484 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5485 dnotify_req
->netfid
= netfid
;
5486 dnotify_req
->pfile
= pfile
;
5487 dnotify_req
->filter
= filter
;
5488 dnotify_req
->multishot
= multishot
;
5489 spin_lock(&GlobalMid_Lock
);
5490 list_add_tail(&dnotify_req
->lhead
,
5491 &GlobalDnotifyReqList
);
5492 spin_unlock(&GlobalMid_Lock
);
5496 cifs_buf_release(pSMB
);
5500 #ifdef CONFIG_CIFS_XATTR
5502 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5503 * function used by listxattr and getxattr type calls. When ea_name is set,
5504 * it looks for that attribute name and stuffs that value into the EAData
5505 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5506 * buffer. In both cases, the return value is either the length of the
5507 * resulting data or a negative error code. If EAData is a NULL pointer then
5508 * the data isn't copied to it, but the length is returned.
5511 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5512 const unsigned char *searchName
, const unsigned char *ea_name
,
5513 char *EAData
, size_t buf_size
,
5514 const struct nls_table
*nls_codepage
, int remap
)
5516 /* BB assumes one setup word */
5517 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5518 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5522 struct fealist
*ea_response_data
;
5523 struct fea
*temp_fea
;
5526 __u16 params
, byte_count
, data_offset
;
5528 cFYI(1, "In Query All EAs path %s", searchName
);
5530 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5535 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5537 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5538 PATH_MAX
, nls_codepage
, remap
);
5539 list_len
++; /* trailing null */
5541 } else { /* BB improve the check for buffer overruns BB */
5542 list_len
= strnlen(searchName
, PATH_MAX
);
5543 list_len
++; /* trailing null */
5544 strncpy(pSMB
->FileName
, searchName
, list_len
);
5547 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
5548 pSMB
->TotalDataCount
= 0;
5549 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5550 /* BB find exact max SMB PDU from sess structure BB */
5551 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
5552 pSMB
->MaxSetupCount
= 0;
5556 pSMB
->Reserved2
= 0;
5557 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5558 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5559 pSMB
->DataCount
= 0;
5560 pSMB
->DataOffset
= 0;
5561 pSMB
->SetupCount
= 1;
5562 pSMB
->Reserved3
= 0;
5563 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5564 byte_count
= params
+ 1 /* pad */ ;
5565 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5566 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5567 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5568 pSMB
->Reserved4
= 0;
5569 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5570 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5572 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5573 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5575 cFYI(1, "Send error in QueryAllEAs = %d", rc
);
5580 /* BB also check enough total bytes returned */
5581 /* BB we need to improve the validity checking
5582 of these trans2 responses */
5584 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5585 if (rc
|| (pSMBr
->ByteCount
< 4)) {
5586 rc
= -EIO
; /* bad smb */
5590 /* check that length of list is not more than bcc */
5591 /* check that each entry does not go beyond length
5593 /* check that each element of each entry does not
5594 go beyond end of list */
5595 /* validate_trans2_offsets() */
5596 /* BB check if start of smb + data_offset > &bcc+ bcc */
5598 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5599 ea_response_data
= (struct fealist
*)
5600 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
5602 list_len
= le32_to_cpu(ea_response_data
->list_len
);
5603 cFYI(1, "ea length %d", list_len
);
5604 if (list_len
<= 8) {
5605 cFYI(1, "empty EA list returned from server");
5609 /* make sure list_len doesn't go past end of SMB */
5610 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + get_bcc(&pSMBr
->hdr
);
5611 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
5612 cFYI(1, "EA list appears to go beyond SMB");
5617 /* account for ea list len */
5619 temp_fea
= ea_response_data
->list
;
5620 temp_ptr
= (char *)temp_fea
;
5621 while (list_len
> 0) {
5622 unsigned int name_len
;
5627 /* make sure we can read name_len and value_len */
5629 cFYI(1, "EA entry goes beyond length of list");
5634 name_len
= temp_fea
->name_len
;
5635 value_len
= le16_to_cpu(temp_fea
->value_len
);
5636 list_len
-= name_len
+ 1 + value_len
;
5638 cFYI(1, "EA entry goes beyond length of list");
5644 if (strncmp(ea_name
, temp_ptr
, name_len
) == 0) {
5645 temp_ptr
+= name_len
+ 1;
5649 if ((size_t)value_len
> buf_size
) {
5653 memcpy(EAData
, temp_ptr
, value_len
);
5657 /* account for prefix user. and trailing null */
5658 rc
+= (5 + 1 + name_len
);
5659 if (rc
< (int) buf_size
) {
5660 memcpy(EAData
, "user.", 5);
5662 memcpy(EAData
, temp_ptr
, name_len
);
5664 /* null terminate name */
5667 } else if (buf_size
== 0) {
5668 /* skip copy - calc size only */
5670 /* stop before overrun buffer */
5675 temp_ptr
+= name_len
+ 1 + value_len
;
5676 temp_fea
= (struct fea
*)temp_ptr
;
5679 /* didn't find the named attribute */
5684 cifs_buf_release(pSMB
);
5692 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5693 const char *ea_name
, const void *ea_value
,
5694 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5697 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5698 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5699 struct fealist
*parm_data
;
5702 int bytes_returned
= 0;
5703 __u16 params
, param_offset
, byte_count
, offset
, count
;
5705 cFYI(1, "In SetEA");
5707 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5712 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5714 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5715 PATH_MAX
, nls_codepage
, remap
);
5716 name_len
++; /* trailing null */
5718 } else { /* BB improve the check for buffer overruns BB */
5719 name_len
= strnlen(fileName
, PATH_MAX
);
5720 name_len
++; /* trailing null */
5721 strncpy(pSMB
->FileName
, fileName
, name_len
);
5724 params
= 6 + name_len
;
5726 /* done calculating parms using name_len of file name,
5727 now use name_len to calculate length of ea name
5728 we are going to create in the inode xattrs */
5729 if (ea_name
== NULL
)
5732 name_len
= strnlen(ea_name
, 255);
5734 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5735 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5736 /* BB find max SMB PDU from sess */
5737 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5738 pSMB
->MaxSetupCount
= 0;
5742 pSMB
->Reserved2
= 0;
5743 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5744 InformationLevel
) - 4;
5745 offset
= param_offset
+ params
;
5746 pSMB
->InformationLevel
=
5747 cpu_to_le16(SMB_SET_FILE_EA
);
5750 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5752 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5753 pSMB
->DataOffset
= cpu_to_le16(offset
);
5754 pSMB
->SetupCount
= 1;
5755 pSMB
->Reserved3
= 0;
5756 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5757 byte_count
= 3 /* pad */ + params
+ count
;
5758 pSMB
->DataCount
= cpu_to_le16(count
);
5759 parm_data
->list_len
= cpu_to_le32(count
);
5760 parm_data
->list
[0].EA_flags
= 0;
5761 /* we checked above that name len is less than 255 */
5762 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5763 /* EA names are always ASCII */
5765 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5766 parm_data
->list
[0].name
[name_len
] = 0;
5767 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5768 /* caller ensures that ea_value_len is less than 64K but
5769 we need to ensure that it fits within the smb */
5771 /*BB add length check to see if it would fit in
5772 negotiated SMB buffer size BB */
5773 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5775 memcpy(parm_data
->list
[0].name
+name_len
+1,
5776 ea_value
, ea_value_len
);
5778 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5779 pSMB
->ParameterCount
= cpu_to_le16(params
);
5780 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5781 pSMB
->Reserved4
= 0;
5782 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5783 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5784 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5785 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5787 cFYI(1, "SetPathInfo (EA) returned %d", rc
);
5789 cifs_buf_release(pSMB
);