4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT
, "\2LM1.2X002"},
49 {LANMAN2_PROT
, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT
, "\2NT LM 0.12"},
52 {POSIX_PROT
, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT
, "\2LM1.2X002"},
62 {LANMAN2_PROT
, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT
, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo
*pTcon
)
89 struct cifsFileInfo
*open_file
= NULL
;
90 struct list_head
*tmp
;
91 struct list_head
*tmp1
;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock
);
95 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
96 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
98 open_file
->invalidHandle
= TRUE
;
100 write_unlock(&GlobalSMBSeslock
);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* Allocate and return pointer to an SMB request buffer, and set basic
106 SMB information in the SMB header. If the return code is zero, this
107 function must have filled in request_buf pointer */
109 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
114 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
115 check for tcp and smb session status done differently
116 for those three - in the calling routine */
118 if (tcon
->tidStatus
== CifsExiting
) {
119 /* only tree disconnect, open, and write,
120 (and ulogoff which does not have tcon)
121 are allowed as we start force umount */
122 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
123 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
124 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
125 cFYI(1, ("can not send cmd %d while umounting",
130 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
131 (tcon
->ses
->server
)) {
132 struct nls_table
*nls_codepage
;
133 /* Give Demultiplex thread up to 10 seconds to
134 reconnect, should be greater than cifs socket
135 timeout which is 7 seconds */
136 while (tcon
->ses
->server
->tcpStatus
==
138 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
139 (tcon
->ses
->server
->tcpStatus
==
141 if (tcon
->ses
->server
->tcpStatus
==
143 /* on "soft" mounts we wait once */
144 if ((tcon
->retry
== FALSE
) ||
145 (tcon
->ses
->status
== CifsExiting
)) {
146 cFYI(1, ("gave up waiting on "
147 "reconnect in smb_init"));
149 } /* else "hard" mount - keep retrying
150 until process is killed or server
151 comes back on-line */
152 } else /* TCP session is reestablished now */
156 nls_codepage
= load_nls_default();
157 /* need to prevent multiple threads trying to
158 simultaneously reconnect the same SMB session */
159 down(&tcon
->ses
->sesSem
);
160 if (tcon
->ses
->status
== CifsNeedReconnect
)
161 rc
= cifs_setup_session(0, tcon
->ses
,
163 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
164 mark_open_files_invalid(tcon
);
165 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
167 up(&tcon
->ses
->sesSem
);
168 /* BB FIXME add code to check if wsize needs
169 update due to negotiated smb buffer size
172 atomic_inc(&tconInfoReconnectCount
);
173 /* tell server Unix caps we support */
174 if (tcon
->ses
->capabilities
& CAP_UNIX
)
175 reset_cifs_unix_caps(
178 NULL
/* we do not know sb */,
179 NULL
/* no vol info */);
182 cFYI(1, ("reconnect tcon rc = %d", rc
));
183 /* Removed call to reopen open files here.
184 It is safer (and faster) to reopen files
185 one at a time as needed in read and write */
187 /* Check if handle based operation so we
188 know whether we can continue or not without
189 returning to caller to reset file handle */
190 switch (smb_command
) {
191 case SMB_COM_READ_ANDX
:
192 case SMB_COM_WRITE_ANDX
:
194 case SMB_COM_FIND_CLOSE2
:
195 case SMB_COM_LOCKING_ANDX
: {
196 unload_nls(nls_codepage
);
201 up(&tcon
->ses
->sesSem
);
203 unload_nls(nls_codepage
);
212 *request_buf
= cifs_small_buf_get();
213 if (*request_buf
== NULL
) {
214 /* BB should we add a retry in here if not a writepage? */
218 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
222 cifs_stats_inc(&tcon
->num_smbs_sent
);
228 small_smb_init_no_tc(const int smb_command
, const int wct
,
229 struct cifsSesInfo
*ses
, void **request_buf
)
232 struct smb_hdr
*buffer
;
234 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
238 buffer
= (struct smb_hdr
*)*request_buf
;
239 buffer
->Mid
= GetNextMid(ses
->server
);
240 if (ses
->capabilities
& CAP_UNICODE
)
241 buffer
->Flags2
|= SMBFLG2_UNICODE
;
242 if (ses
->capabilities
& CAP_STATUS32
)
243 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
245 /* uid, tid can stay at zero as set in header assemble */
247 /* BB add support for turning on the signing when
248 this function is used after 1st of session setup requests */
253 /* If the return code is zero, this function must fill in request_buf pointer */
255 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
256 void **request_buf
/* returned */ ,
257 void **response_buf
/* returned */ )
261 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
262 check for tcp and smb session status done differently
263 for those three - in the calling routine */
265 if (tcon
->tidStatus
== CifsExiting
) {
266 /* only tree disconnect, open, and write,
267 (and ulogoff which does not have tcon)
268 are allowed as we start force umount */
269 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
270 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
271 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
272 cFYI(1, ("can not send cmd %d while umounting",
278 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
279 (tcon
->ses
->server
)) {
280 struct nls_table
*nls_codepage
;
281 /* Give Demultiplex thread up to 10 seconds to
282 reconnect, should be greater than cifs socket
283 timeout which is 7 seconds */
284 while (tcon
->ses
->server
->tcpStatus
==
286 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
287 (tcon
->ses
->server
->tcpStatus
==
289 if (tcon
->ses
->server
->tcpStatus
==
291 /* on "soft" mounts we wait once */
292 if ((tcon
->retry
== FALSE
) ||
293 (tcon
->ses
->status
== CifsExiting
)) {
294 cFYI(1, ("gave up waiting on "
295 "reconnect in smb_init"));
297 } /* else "hard" mount - keep retrying
298 until process is killed or server
300 } else /* TCP session is reestablished now */
303 nls_codepage
= load_nls_default();
304 /* need to prevent multiple threads trying to
305 simultaneously reconnect the same SMB session */
306 down(&tcon
->ses
->sesSem
);
307 if (tcon
->ses
->status
== CifsNeedReconnect
)
308 rc
= cifs_setup_session(0, tcon
->ses
,
310 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
311 mark_open_files_invalid(tcon
);
312 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
314 up(&tcon
->ses
->sesSem
);
315 /* BB FIXME add code to check if wsize needs
316 update due to negotiated smb buffer size
319 atomic_inc(&tconInfoReconnectCount
);
320 /* tell server Unix caps we support */
321 if (tcon
->ses
->capabilities
& CAP_UNIX
)
322 reset_cifs_unix_caps(
325 NULL
/* do not know sb */,
326 NULL
/* no vol info */);
329 cFYI(1, ("reconnect tcon rc = %d", rc
));
330 /* Removed call to reopen open files here.
331 It is safer (and faster) to reopen files
332 one at a time as needed in read and write */
334 /* Check if handle based operation so we
335 know whether we can continue or not without
336 returning to caller to reset file handle */
337 switch (smb_command
) {
338 case SMB_COM_READ_ANDX
:
339 case SMB_COM_WRITE_ANDX
:
341 case SMB_COM_FIND_CLOSE2
:
342 case SMB_COM_LOCKING_ANDX
: {
343 unload_nls(nls_codepage
);
348 up(&tcon
->ses
->sesSem
);
350 unload_nls(nls_codepage
);
359 *request_buf
= cifs_buf_get();
360 if (*request_buf
== NULL
) {
361 /* BB should we add a retry in here if not a writepage? */
364 /* Although the original thought was we needed the response buf for */
365 /* potential retries of smb operations it turns out we can determine */
366 /* from the mid flags when the request buffer can be resent without */
367 /* having to use a second distinct buffer for the response */
369 *response_buf
= *request_buf
;
371 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
375 cifs_stats_inc(&tcon
->num_smbs_sent
);
380 static int validate_t2(struct smb_t2_rsp
*pSMB
)
386 /* check for plausible wct, bcc and t2 data and parm sizes */
387 /* check for parm and data offset going beyond end of smb */
388 if (pSMB
->hdr
.WordCount
>= 10) {
389 if ((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
390 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
391 /* check that bcc is at least as big as parms + data */
392 /* check that bcc is less than negotiated smb buffer */
393 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
394 if (total_size
< 512) {
396 le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
397 /* BCC le converted in SendReceive */
398 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
399 sizeof(struct smb_hdr
) +
401 if ((total_size
<= (*(u16
*)pBCC
)) &&
403 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
409 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
410 sizeof(struct smb_t2_rsp
) + 16);
414 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
417 NEGOTIATE_RSP
*pSMBr
;
421 struct TCP_Server_Info
*server
;
423 unsigned int secFlags
;
427 server
= ses
->server
;
432 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
433 (void **) &pSMB
, (void **) &pSMBr
);
437 /* if any of auth flags (ie not sign or seal) are overriden use them */
438 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
439 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
440 else /* if override flags set only sign/seal OR them with global auth */
441 secFlags
= extended_security
| ses
->overrideSecFlg
;
443 cFYI(1, ("secFlags 0x%x", secFlags
));
445 pSMB
->hdr
.Mid
= GetNextMid(server
);
446 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
448 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
449 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
450 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
451 cFYI(1, ("Kerberos only mechanism, enable extended security"));
452 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
456 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
457 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
458 count
+= strlen(protocols
[i
].name
) + 1;
459 /* null at end of source and target buffers anyway */
461 pSMB
->hdr
.smb_buf_length
+= count
;
462 pSMB
->ByteCount
= cpu_to_le16(count
);
464 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
465 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
469 dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
470 cFYI(1, ("Dialect: %d", dialect
));
471 /* Check wct = 1 error case */
472 if ((pSMBr
->hdr
.WordCount
< 13) || (dialect
== BAD_PROT
)) {
473 /* core returns wct = 1, but we do not ask for core - otherwise
474 small wct just comes when dialect index is -1 indicating we
475 could not negotiate a common dialect */
478 #ifdef CONFIG_CIFS_WEAK_PW_HASH
479 } else if ((pSMBr
->hdr
.WordCount
== 13)
480 && ((dialect
== LANMAN_PROT
)
481 || (dialect
== LANMAN2_PROT
))) {
483 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
485 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
486 (secFlags
& CIFSSEC_MAY_PLNTXT
))
487 server
->secType
= LANMAN
;
489 cERROR(1, ("mount failed weak security disabled"
490 " in /proc/fs/cifs/SecurityFlags"));
494 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
495 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
496 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
497 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
498 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
499 /* even though we do not use raw we might as well set this
500 accurately, in case we ever find a need for it */
501 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
502 server
->maxRw
= 0xFF00;
503 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
505 server
->maxRw
= 0;/* we do not need to use raw anyway */
506 server
->capabilities
= CAP_MPX_MODE
;
508 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
510 /* OS/2 often does not set timezone therefore
511 * we must use server time to calc time zone.
512 * Could deviate slightly from the right zone.
513 * Smallest defined timezone difference is 15 minutes
514 * (i.e. Nepal). Rounding up/down is done to match
517 int val
, seconds
, remain
, result
;
518 struct timespec ts
, utc
;
520 ts
= cnvrtDosUnixTm(le16_to_cpu(rsp
->SrvTime
.Date
),
521 le16_to_cpu(rsp
->SrvTime
.Time
));
522 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
523 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
524 (int)(utc
.tv_sec
- ts
.tv_sec
)));
525 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
527 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
528 remain
= seconds
% MIN_TZ_ADJ
;
529 if (remain
>= (MIN_TZ_ADJ
/ 2))
530 result
+= MIN_TZ_ADJ
;
533 server
->timeAdj
= result
;
535 server
->timeAdj
= (int)tmp
;
536 server
->timeAdj
*= 60; /* also in seconds */
538 cFYI(1, ("server->timeAdj: %d seconds", server
->timeAdj
));
541 /* BB get server time for time conversions and add
542 code to use it and timezone since this is not UTC */
544 if (rsp
->EncryptionKeyLength
==
545 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
546 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
547 CIFS_CRYPTO_KEY_SIZE
);
548 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
549 rc
= -EIO
; /* need cryptkey unless plain text */
553 cFYI(1, ("LANMAN negotiated"));
554 /* we will not end up setting signing flags - as no signing
555 was in LANMAN and server did not return the flags on */
557 #else /* weak security disabled */
558 } else if (pSMBr
->hdr
.WordCount
== 13) {
559 cERROR(1, ("mount failed, cifs module not built "
560 "with CIFS_WEAK_PW_HASH support"));
562 #endif /* WEAK_PW_HASH */
564 } else if (pSMBr
->hdr
.WordCount
!= 17) {
569 /* else wct == 17 NTLM */
570 server
->secMode
= pSMBr
->SecurityMode
;
571 if ((server
->secMode
& SECMODE_USER
) == 0)
572 cFYI(1, ("share mode security"));
574 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
575 #ifdef CONFIG_CIFS_WEAK_PW_HASH
576 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
577 #endif /* CIFS_WEAK_PW_HASH */
578 cERROR(1, ("Server requests plain text password"
579 " but client support disabled"));
581 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
582 server
->secType
= NTLMv2
;
583 else if (secFlags
& CIFSSEC_MAY_NTLM
)
584 server
->secType
= NTLM
;
585 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
586 server
->secType
= NTLMv2
;
587 else if (secFlags
& CIFSSEC_MAY_KRB5
)
588 server
->secType
= Kerberos
;
589 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
590 server
->secType
= LANMAN
;
591 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
592 else if (secFlags & CIFSSEC_MAY_PLNTXT)
597 cERROR(1, ("Invalid security type"));
600 /* else ... any others ...? */
602 /* one byte, so no need to convert this or EncryptionKeyLen from
604 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
605 /* probably no need to store and check maxvcs */
606 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
607 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
608 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
609 cFYI(DBG2
, ("Max buf = %d", ses
->server
->maxBuf
));
610 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
611 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
612 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
613 server
->timeAdj
*= 60;
614 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
615 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
616 CIFS_CRYPTO_KEY_SIZE
);
617 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
618 && (pSMBr
->EncryptionKeyLength
== 0)) {
619 /* decode security blob */
620 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
621 rc
= -EIO
; /* no crypt key only if plain text pwd */
625 /* BB might be helpful to save off the domain of server here */
627 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
628 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
629 count
= pSMBr
->ByteCount
;
635 if (server
->socketUseCount
.counter
> 1) {
636 if (memcmp(server
->server_GUID
,
637 pSMBr
->u
.extended_response
.
639 cFYI(1, ("server UID changed"));
640 memcpy(server
->server_GUID
,
641 pSMBr
->u
.extended_response
.GUID
,
645 memcpy(server
->server_GUID
,
646 pSMBr
->u
.extended_response
.GUID
, 16);
649 server
->secType
= RawNTLMSSP
;
651 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
662 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
664 #ifdef CONFIG_CIFS_WEAK_PW_HASH
667 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
668 /* MUST_SIGN already includes the MAY_SIGN FLAG
669 so if this is zero it means that signing is disabled */
670 cFYI(1, ("Signing disabled"));
671 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
672 cERROR(1, ("Server requires "
673 "packet signing to be enabled in "
674 "/proc/fs/cifs/SecurityFlags."));
678 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
679 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
680 /* signing required */
681 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
682 if ((server
->secMode
&
683 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
685 ("signing required but server lacks support"));
688 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
690 /* signing optional ie CIFSSEC_MAY_SIGN */
691 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
693 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
697 cifs_buf_release(pSMB
);
699 cFYI(1, ("negprot rc %d", rc
));
704 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
706 struct smb_hdr
*smb_buffer
;
709 cFYI(1, ("In tree disconnect"));
711 * If last user of the connection and
712 * connection alive - disconnect it
713 * If this is the last connection on the server session disconnect it
714 * (and inside session disconnect we should check if tcp socket needs
715 * to be freed and kernel thread woken up).
718 down(&tcon
->tconSem
);
722 atomic_dec(&tcon
->useCount
);
723 if (atomic_read(&tcon
->useCount
) > 0) {
728 /* No need to return error on this operation if tid invalidated and
729 closed on server already e.g. due to tcp session crashing */
730 if (tcon
->tidStatus
== CifsNeedReconnect
) {
735 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
739 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
740 (void **)&smb_buffer
);
746 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
748 cFYI(1, ("Tree disconnect failed %d", rc
));
752 /* No need to return error on this operation if tid invalidated and
753 closed on server already e.g. due to tcp session crashing */
761 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
763 LOGOFF_ANDX_REQ
*pSMB
;
766 cFYI(1, ("In SMBLogoff for session disconnect"));
772 atomic_dec(&ses
->inUse
);
773 if (atomic_read(&ses
->inUse
) > 0) {
777 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
784 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
786 if (ses
->server
->secMode
&
787 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
788 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
791 pSMB
->hdr
.Uid
= ses
->Suid
;
793 pSMB
->AndXCommand
= 0xFF;
794 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
796 atomic_dec(&ses
->server
->socketUseCount
);
797 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
798 spin_lock(&GlobalMid_Lock
);
799 ses
->server
->tcpStatus
= CifsExiting
;
800 spin_unlock(&GlobalMid_Lock
);
806 /* if session dead then we do not need to do ulogoff,
807 since server closed smb session, no sense reporting
815 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
816 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
818 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
819 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
820 struct unlink_psx_rq
*pRqD
;
823 int bytes_returned
= 0;
824 __u16 params
, param_offset
, offset
, byte_count
;
826 cFYI(1, ("In POSIX delete"));
828 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
833 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
835 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
836 PATH_MAX
, nls_codepage
, remap
);
837 name_len
++; /* trailing null */
839 } else { /* BB add path length overrun check */
840 name_len
= strnlen(fileName
, PATH_MAX
);
841 name_len
++; /* trailing null */
842 strncpy(pSMB
->FileName
, fileName
, name_len
);
845 params
= 6 + name_len
;
846 pSMB
->MaxParameterCount
= cpu_to_le16(2);
847 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
848 pSMB
->MaxSetupCount
= 0;
853 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
854 InformationLevel
) - 4;
855 offset
= param_offset
+ params
;
857 /* Setup pointer to Request Data (inode type) */
858 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
859 pRqD
->type
= cpu_to_le16(type
);
860 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
861 pSMB
->DataOffset
= cpu_to_le16(offset
);
862 pSMB
->SetupCount
= 1;
864 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
865 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
867 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
868 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
869 pSMB
->ParameterCount
= cpu_to_le16(params
);
870 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
871 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
873 pSMB
->hdr
.smb_buf_length
+= byte_count
;
874 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
875 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
876 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
878 cFYI(1, ("Posix delete returned %d", rc
));
879 cifs_buf_release(pSMB
);
881 cifs_stats_inc(&tcon
->num_deletes
);
890 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
891 const struct nls_table
*nls_codepage
, int remap
)
893 DELETE_FILE_REQ
*pSMB
= NULL
;
894 DELETE_FILE_RSP
*pSMBr
= NULL
;
900 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
905 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
907 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
908 PATH_MAX
, nls_codepage
, remap
);
909 name_len
++; /* trailing null */
911 } else { /* BB improve check for buffer overruns BB */
912 name_len
= strnlen(fileName
, PATH_MAX
);
913 name_len
++; /* trailing null */
914 strncpy(pSMB
->fileName
, fileName
, name_len
);
916 pSMB
->SearchAttributes
=
917 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
918 pSMB
->BufferFormat
= 0x04;
919 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
920 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
921 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
922 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
923 cifs_stats_inc(&tcon
->num_deletes
);
925 cFYI(1, ("Error in RMFile = %d", rc
));
927 cifs_buf_release(pSMB
);
935 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
936 const struct nls_table
*nls_codepage
, int remap
)
938 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
939 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
944 cFYI(1, ("In CIFSSMBRmDir"));
946 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
951 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
952 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
953 PATH_MAX
, nls_codepage
, remap
);
954 name_len
++; /* trailing null */
956 } else { /* BB improve check for buffer overruns BB */
957 name_len
= strnlen(dirName
, PATH_MAX
);
958 name_len
++; /* trailing null */
959 strncpy(pSMB
->DirName
, dirName
, name_len
);
962 pSMB
->BufferFormat
= 0x04;
963 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
964 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
965 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
966 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
967 cifs_stats_inc(&tcon
->num_rmdirs
);
969 cFYI(1, ("Error in RMDir = %d", rc
));
971 cifs_buf_release(pSMB
);
978 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
979 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
982 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
983 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
987 cFYI(1, ("In CIFSSMBMkDir"));
989 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
994 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
995 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
996 PATH_MAX
, nls_codepage
, remap
);
997 name_len
++; /* trailing null */
999 } else { /* BB improve check for buffer overruns BB */
1000 name_len
= strnlen(name
, PATH_MAX
);
1001 name_len
++; /* trailing null */
1002 strncpy(pSMB
->DirName
, name
, name_len
);
1005 pSMB
->BufferFormat
= 0x04;
1006 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
1007 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
1008 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1009 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1010 cifs_stats_inc(&tcon
->num_mkdirs
);
1012 cFYI(1, ("Error in Mkdir = %d", rc
));
1014 cifs_buf_release(pSMB
);
1021 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1022 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1023 __u32
*pOplock
, const char *name
,
1024 const struct nls_table
*nls_codepage
, int remap
)
1026 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1027 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1030 int bytes_returned
= 0;
1031 __u16 params
, param_offset
, offset
, byte_count
, count
;
1032 OPEN_PSX_REQ
*pdata
;
1033 OPEN_PSX_RSP
*psx_rsp
;
1035 cFYI(1, ("In POSIX Create"));
1037 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1042 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1044 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1045 PATH_MAX
, nls_codepage
, remap
);
1046 name_len
++; /* trailing null */
1048 } else { /* BB improve the check for buffer overruns BB */
1049 name_len
= strnlen(name
, PATH_MAX
);
1050 name_len
++; /* trailing null */
1051 strncpy(pSMB
->FileName
, name
, name_len
);
1054 params
= 6 + name_len
;
1055 count
= sizeof(OPEN_PSX_REQ
);
1056 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1057 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1058 pSMB
->MaxSetupCount
= 0;
1062 pSMB
->Reserved2
= 0;
1063 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1064 InformationLevel
) - 4;
1065 offset
= param_offset
+ params
;
1066 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1067 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1068 pdata
->Permissions
= cpu_to_le64(mode
);
1069 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1070 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1071 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1072 pSMB
->DataOffset
= cpu_to_le16(offset
);
1073 pSMB
->SetupCount
= 1;
1074 pSMB
->Reserved3
= 0;
1075 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1076 byte_count
= 3 /* pad */ + params
+ count
;
1078 pSMB
->DataCount
= cpu_to_le16(count
);
1079 pSMB
->ParameterCount
= cpu_to_le16(params
);
1080 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1081 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1082 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1083 pSMB
->Reserved4
= 0;
1084 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1085 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1086 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1087 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1089 cFYI(1, ("Posix create returned %d", rc
));
1090 goto psx_create_err
;
1093 cFYI(1, ("copying inode info"));
1094 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1096 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1097 rc
= -EIO
; /* bad smb */
1098 goto psx_create_err
;
1101 /* copy return information to pRetData */
1102 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1103 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1105 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1107 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1108 /* Let caller know file was created so we can set the mode. */
1109 /* Do we care about the CreateAction in any other cases? */
1110 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1111 *pOplock
|= CIFS_CREATE_ACTION
;
1112 /* check to make sure response data is there */
1113 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1114 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1115 cFYI(DBG2
, ("unknown type"));
1117 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1118 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1119 cERROR(1, ("Open response data too small"));
1120 pRetData
->Type
= cpu_to_le32(-1);
1121 goto psx_create_err
;
1123 memcpy((char *) pRetData
,
1124 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1125 sizeof(FILE_UNIX_BASIC_INFO
));
1129 cifs_buf_release(pSMB
);
1131 cifs_stats_inc(&tcon
->num_mkdirs
);
1139 static __u16
convert_disposition(int disposition
)
1143 switch (disposition
) {
1144 case FILE_SUPERSEDE
:
1145 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1148 ofun
= SMBOPEN_OAPPEND
;
1151 ofun
= SMBOPEN_OCREATE
;
1154 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1156 case FILE_OVERWRITE
:
1157 ofun
= SMBOPEN_OTRUNC
;
1159 case FILE_OVERWRITE_IF
:
1160 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1163 cFYI(1, ("unknown disposition %d", disposition
));
1164 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1170 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1171 const char *fileName
, const int openDisposition
,
1172 const int access_flags
, const int create_options
, __u16
*netfid
,
1173 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1174 const struct nls_table
*nls_codepage
, int remap
)
1177 OPENX_REQ
*pSMB
= NULL
;
1178 OPENX_RSP
*pSMBr
= NULL
;
1184 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1189 pSMB
->AndXCommand
= 0xFF; /* none */
1191 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1192 count
= 1; /* account for one byte pad to word boundary */
1194 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1195 fileName
, PATH_MAX
, nls_codepage
, remap
);
1196 name_len
++; /* trailing null */
1198 } else { /* BB improve check for buffer overruns BB */
1199 count
= 0; /* no pad */
1200 name_len
= strnlen(fileName
, PATH_MAX
);
1201 name_len
++; /* trailing null */
1202 strncpy(pSMB
->fileName
, fileName
, name_len
);
1204 if (*pOplock
& REQ_OPLOCK
)
1205 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1206 else if (*pOplock
& REQ_BATCHOPLOCK
)
1207 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1209 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1210 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1216 pSMB
->Mode
= cpu_to_le16(2);
1217 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1218 /* set file as system file if special file such
1219 as fifo and server expecting SFU style and
1220 no Unix extensions */
1222 if (create_options
& CREATE_OPTION_SPECIAL
)
1223 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1224 else /* BB FIXME BB */
1225 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1227 /* if ((omode & S_IWUGO) == 0)
1228 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1229 /* Above line causes problems due to vfs splitting create into two
1230 pieces - need to set mode after file created not while it is
1234 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1235 CREATE_OPTIONS_MASK); */
1236 /* BB FIXME END BB */
1238 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1239 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1241 pSMB
->hdr
.smb_buf_length
+= count
;
1243 pSMB
->ByteCount
= cpu_to_le16(count
);
1244 /* long_op set to 1 to allow for oplock break timeouts */
1245 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1246 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1247 cifs_stats_inc(&tcon
->num_opens
);
1249 cFYI(1, ("Error in Open = %d", rc
));
1251 /* BB verify if wct == 15 */
1253 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1255 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1256 /* Let caller know file was created so we can set the mode. */
1257 /* Do we care about the CreateAction in any other cases? */
1259 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1260 *pOplock |= CIFS_CREATE_ACTION; */
1264 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1265 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1266 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1267 pfile_info
->ChangeTime
= 0; /* BB fixme */
1268 pfile_info
->Attributes
=
1269 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1270 /* the file_info buf is endian converted by caller */
1271 pfile_info
->AllocationSize
=
1272 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1273 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1274 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1278 cifs_buf_release(pSMB
);
1285 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1286 const char *fileName
, const int openDisposition
,
1287 const int access_flags
, const int create_options
, __u16
*netfid
,
1288 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1289 const struct nls_table
*nls_codepage
, int remap
)
1292 OPEN_REQ
*pSMB
= NULL
;
1293 OPEN_RSP
*pSMBr
= NULL
;
1299 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1304 pSMB
->AndXCommand
= 0xFF; /* none */
1306 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1307 count
= 1; /* account for one byte pad to word boundary */
1309 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1310 fileName
, PATH_MAX
, nls_codepage
, remap
);
1311 name_len
++; /* trailing null */
1313 pSMB
->NameLength
= cpu_to_le16(name_len
);
1314 } else { /* BB improve check for buffer overruns BB */
1315 count
= 0; /* no pad */
1316 name_len
= strnlen(fileName
, PATH_MAX
);
1317 name_len
++; /* trailing null */
1318 pSMB
->NameLength
= cpu_to_le16(name_len
);
1319 strncpy(pSMB
->fileName
, fileName
, name_len
);
1321 if (*pOplock
& REQ_OPLOCK
)
1322 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1323 else if (*pOplock
& REQ_BATCHOPLOCK
)
1324 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1325 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1326 pSMB
->AllocationSize
= 0;
1327 /* set file as system file if special file such
1328 as fifo and server expecting SFU style and
1329 no Unix extensions */
1330 if (create_options
& CREATE_OPTION_SPECIAL
)
1331 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1333 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1334 /* XP does not handle ATTR_POSIX_SEMANTICS */
1335 /* but it helps speed up case sensitive checks for other
1336 servers such as Samba */
1337 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1338 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1340 /* if ((omode & S_IWUGO) == 0)
1341 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1342 /* Above line causes problems due to vfs splitting create into two
1343 pieces - need to set mode after file created not while it is
1345 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1346 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1347 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1348 /* BB Expirement with various impersonation levels and verify */
1349 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1350 pSMB
->SecurityFlags
=
1351 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1354 pSMB
->hdr
.smb_buf_length
+= count
;
1356 pSMB
->ByteCount
= cpu_to_le16(count
);
1357 /* long_op set to 1 to allow for oplock break timeouts */
1358 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1359 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1360 cifs_stats_inc(&tcon
->num_opens
);
1362 cFYI(1, ("Error in Open = %d", rc
));
1364 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1365 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1366 /* Let caller know file was created so we can set the mode. */
1367 /* Do we care about the CreateAction in any other cases? */
1368 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1369 *pOplock
|= CIFS_CREATE_ACTION
;
1371 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1372 36 /* CreationTime to Attributes */);
1373 /* the file_info buf is endian converted by caller */
1374 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1375 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1376 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1380 cifs_buf_release(pSMB
);
1387 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1388 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1389 char **buf
, int *pbuf_type
)
1392 READ_REQ
*pSMB
= NULL
;
1393 READ_RSP
*pSMBr
= NULL
;
1394 char *pReadData
= NULL
;
1396 int resp_buf_type
= 0;
1399 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1400 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1403 wct
= 10; /* old style read */
1406 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1410 /* tcon and ses pointer are checked in smb_init */
1411 if (tcon
->ses
->server
== NULL
)
1412 return -ECONNABORTED
;
1414 pSMB
->AndXCommand
= 0xFF; /* none */
1416 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1418 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1419 else if ((lseek
>> 32) > 0) /* can not handle this big offset for old */
1422 pSMB
->Remaining
= 0;
1423 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1424 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1426 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1428 /* old style read */
1429 struct smb_com_readx_req
*pSMBW
=
1430 (struct smb_com_readx_req
*)pSMB
;
1431 pSMBW
->ByteCount
= 0;
1434 iov
[0].iov_base
= (char *)pSMB
;
1435 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1436 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1437 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1438 cifs_stats_inc(&tcon
->num_reads
);
1439 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1441 cERROR(1, ("Send error in read = %d", rc
));
1443 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1444 data_length
= data_length
<< 16;
1445 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1446 *nbytes
= data_length
;
1448 /*check that DataLength would not go beyond end of SMB */
1449 if ((data_length
> CIFSMaxBufSize
)
1450 || (data_length
> count
)) {
1451 cFYI(1, ("bad length %d for count %d",
1452 data_length
, count
));
1456 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1457 le16_to_cpu(pSMBr
->DataOffset
);
1458 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1459 cERROR(1,("Faulting on read rc = %d",rc));
1461 }*/ /* can not use copy_to_user when using page cache*/
1463 memcpy(*buf
, pReadData
, data_length
);
1467 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1469 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1470 cifs_small_buf_release(iov
[0].iov_base
);
1471 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1472 cifs_buf_release(iov
[0].iov_base
);
1473 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1474 /* return buffer to caller to free */
1475 *buf
= iov
[0].iov_base
;
1476 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1477 *pbuf_type
= CIFS_SMALL_BUFFER
;
1478 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1479 *pbuf_type
= CIFS_LARGE_BUFFER
;
1480 } /* else no valid buffer on return - leave as null */
1482 /* Note: On -EAGAIN error only caller can retry on handle based calls
1483 since file handle passed in no longer valid */
1489 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1490 const int netfid
, const unsigned int count
,
1491 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1492 const char __user
*ubuf
, const int long_op
)
1495 WRITE_REQ
*pSMB
= NULL
;
1496 WRITE_RSP
*pSMBr
= NULL
;
1497 int bytes_returned
, wct
;
1501 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1502 if (tcon
->ses
== NULL
)
1503 return -ECONNABORTED
;
1505 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1510 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1514 /* tcon and ses pointer are checked in smb_init */
1515 if (tcon
->ses
->server
== NULL
)
1516 return -ECONNABORTED
;
1518 pSMB
->AndXCommand
= 0xFF; /* none */
1520 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1522 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1523 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1526 pSMB
->Reserved
= 0xFFFFFFFF;
1527 pSMB
->WriteMode
= 0;
1528 pSMB
->Remaining
= 0;
1530 /* Can increase buffer size if buffer is big enough in some cases ie we
1531 can send more if LARGE_WRITE_X capability returned by the server and if
1532 our buffer is big enough or if we convert to iovecs on socket writes
1533 and eliminate the copy to the CIFS buffer */
1534 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1535 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1537 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1541 if (bytes_sent
> count
)
1544 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1546 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1548 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1549 cifs_buf_release(pSMB
);
1552 } else if (count
!= 0) {
1554 cifs_buf_release(pSMB
);
1556 } /* else setting file size with write of zero bytes */
1558 byte_count
= bytes_sent
+ 1; /* pad */
1559 else /* wct == 12 */
1560 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1562 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1563 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1564 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1567 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1568 else { /* old style write has byte count 4 bytes earlier
1570 struct smb_com_writex_req
*pSMBW
=
1571 (struct smb_com_writex_req
*)pSMB
;
1572 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1575 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1576 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1577 cifs_stats_inc(&tcon
->num_writes
);
1579 cFYI(1, ("Send error in write = %d", rc
));
1582 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1583 *nbytes
= (*nbytes
) << 16;
1584 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1587 cifs_buf_release(pSMB
);
1589 /* Note: On -EAGAIN error only caller can retry on handle based calls
1590 since file handle passed in no longer valid */
1596 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1597 const int netfid
, const unsigned int count
,
1598 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1599 int n_vec
, const int long_op
)
1602 WRITE_REQ
*pSMB
= NULL
;
1605 int resp_buf_type
= 0;
1607 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1609 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1613 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1616 /* tcon and ses pointer are checked in smb_init */
1617 if (tcon
->ses
->server
== NULL
)
1618 return -ECONNABORTED
;
1620 pSMB
->AndXCommand
= 0xFF; /* none */
1622 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1624 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1625 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1627 pSMB
->Reserved
= 0xFFFFFFFF;
1628 pSMB
->WriteMode
= 0;
1629 pSMB
->Remaining
= 0;
1632 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1634 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1635 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1636 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1638 pSMB
->hdr
.smb_buf_length
+= count
+1;
1639 else /* wct == 12 */
1640 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1642 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1643 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1644 struct smb_com_writex_req
*pSMBW
=
1645 (struct smb_com_writex_req
*)pSMB
;
1646 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1648 iov
[0].iov_base
= pSMB
;
1650 iov
[0].iov_len
= smb_hdr_len
+ 4;
1651 else /* wct == 12 pad bigger by four bytes */
1652 iov
[0].iov_len
= smb_hdr_len
+ 8;
1655 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1657 cifs_stats_inc(&tcon
->num_writes
);
1659 cFYI(1, ("Send error Write2 = %d", rc
));
1661 } else if (resp_buf_type
== 0) {
1662 /* presumably this can not happen, but best to be safe */
1666 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1667 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1668 *nbytes
= (*nbytes
) << 16;
1669 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1672 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1673 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1674 cifs_small_buf_release(iov
[0].iov_base
);
1675 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1676 cifs_buf_release(iov
[0].iov_base
);
1678 /* Note: On -EAGAIN error only caller can retry on handle based calls
1679 since file handle passed in no longer valid */
1686 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1687 const __u16 smb_file_id
, const __u64 len
,
1688 const __u64 offset
, const __u32 numUnlock
,
1689 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1692 LOCK_REQ
*pSMB
= NULL
;
1693 LOCK_RSP
*pSMBr
= NULL
;
1698 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag
, numLock
));
1699 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1704 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1706 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1707 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1709 } else if (waitFlag
== TRUE
) {
1710 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1711 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1716 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1717 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1718 pSMB
->LockType
= lockType
;
1719 pSMB
->AndXCommand
= 0xFF; /* none */
1720 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1722 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1723 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1724 /* BB where to store pid high? */
1725 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1726 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1727 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1728 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1729 count
= sizeof(LOCKING_ANDX_RANGE
);
1734 pSMB
->hdr
.smb_buf_length
+= count
;
1735 pSMB
->ByteCount
= cpu_to_le16(count
);
1738 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1739 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1740 cifs_small_buf_release(pSMB
);
1742 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1744 /* SMB buffer freed by function above */
1746 cifs_stats_inc(&tcon
->num_locks
);
1748 cFYI(1, ("Send error in Lock = %d", rc
));
1750 /* Note: On -EAGAIN error only caller can retry on handle based calls
1751 since file handle passed in no longer valid */
1756 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1757 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1758 struct file_lock
*pLockData
, const __u16 lock_type
,
1761 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1762 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1763 struct cifs_posix_lock
*parm_data
;
1766 int bytes_returned
= 0;
1767 int resp_buf_type
= 0;
1768 __u16 params
, param_offset
, offset
, byte_count
, count
;
1771 cFYI(1, ("Posix Lock"));
1773 if (pLockData
== NULL
)
1776 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1781 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1784 pSMB
->MaxSetupCount
= 0;
1787 pSMB
->Reserved2
= 0;
1788 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1789 offset
= param_offset
+ params
;
1791 count
= sizeof(struct cifs_posix_lock
);
1792 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1793 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1794 pSMB
->SetupCount
= 1;
1795 pSMB
->Reserved3
= 0;
1797 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1799 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1800 byte_count
= 3 /* pad */ + params
+ count
;
1801 pSMB
->DataCount
= cpu_to_le16(count
);
1802 pSMB
->ParameterCount
= cpu_to_le16(params
);
1803 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1804 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1805 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1806 parm_data
= (struct cifs_posix_lock
*)
1807 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1809 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1811 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1812 parm_data
->lock_flags
= cpu_to_le16(1);
1813 pSMB
->Timeout
= cpu_to_le32(-1);
1817 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1818 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1819 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1821 pSMB
->DataOffset
= cpu_to_le16(offset
);
1822 pSMB
->Fid
= smb_file_id
;
1823 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1824 pSMB
->Reserved4
= 0;
1825 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1826 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1828 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1829 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1831 iov
[0].iov_base
= (char *)pSMB
;
1832 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1833 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1834 &resp_buf_type
, timeout
);
1835 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1836 not try to free it twice below on exit */
1837 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1841 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1842 } else if (get_flag
) {
1843 /* lock structure can be returned on get */
1846 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1848 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1849 rc
= -EIO
; /* bad smb */
1852 if (pLockData
== NULL
) {
1856 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1857 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1858 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1862 parm_data
= (struct cifs_posix_lock
*)
1863 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1864 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1865 pLockData
->fl_type
= F_UNLCK
;
1870 cifs_small_buf_release(pSMB
);
1872 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1873 cifs_small_buf_release(iov
[0].iov_base
);
1874 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1875 cifs_buf_release(iov
[0].iov_base
);
1877 /* Note: On -EAGAIN error only caller can retry on handle based calls
1878 since file handle passed in no longer valid */
1885 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1888 CLOSE_REQ
*pSMB
= NULL
;
1889 cFYI(1, ("In CIFSSMBClose"));
1891 /* do not retry on dead session on close */
1892 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1898 pSMB
->FileID
= (__u16
) smb_file_id
;
1899 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1900 pSMB
->ByteCount
= 0;
1901 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1902 cifs_stats_inc(&tcon
->num_closes
);
1905 /* EINTR is expected when user ctl-c to kill app */
1906 cERROR(1, ("Send error in Close = %d", rc
));
1910 /* Since session is dead, file will be closed on server already */
1918 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1919 const char *fromName
, const char *toName
,
1920 const struct nls_table
*nls_codepage
, int remap
)
1923 RENAME_REQ
*pSMB
= NULL
;
1924 RENAME_RSP
*pSMBr
= NULL
;
1926 int name_len
, name_len2
;
1929 cFYI(1, ("In CIFSSMBRename"));
1931 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1936 pSMB
->BufferFormat
= 0x04;
1937 pSMB
->SearchAttributes
=
1938 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1941 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1943 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1944 PATH_MAX
, nls_codepage
, remap
);
1945 name_len
++; /* trailing null */
1947 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1948 /* protocol requires ASCII signature byte on Unicode string */
1949 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1951 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1952 toName
, PATH_MAX
, nls_codepage
, remap
);
1953 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1954 name_len2
*= 2; /* convert to bytes */
1955 } else { /* BB improve the check for buffer overruns BB */
1956 name_len
= strnlen(fromName
, PATH_MAX
);
1957 name_len
++; /* trailing null */
1958 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1959 name_len2
= strnlen(toName
, PATH_MAX
);
1960 name_len2
++; /* trailing null */
1961 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1962 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1963 name_len2
++; /* trailing null */
1964 name_len2
++; /* signature byte */
1967 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1968 pSMB
->hdr
.smb_buf_length
+= count
;
1969 pSMB
->ByteCount
= cpu_to_le16(count
);
1971 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1972 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1973 cifs_stats_inc(&tcon
->num_renames
);
1975 cFYI(1, ("Send error in rename = %d", rc
));
1977 cifs_buf_release(pSMB
);
1985 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
1986 int netfid
, char *target_name
,
1987 const struct nls_table
*nls_codepage
, int remap
)
1989 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1990 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1991 struct set_file_rename
*rename_info
;
1993 char dummy_string
[30];
1995 int bytes_returned
= 0;
1997 __u16 params
, param_offset
, offset
, count
, byte_count
;
1999 cFYI(1, ("Rename to File by handle"));
2000 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2006 pSMB
->MaxSetupCount
= 0;
2010 pSMB
->Reserved2
= 0;
2011 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2012 offset
= param_offset
+ params
;
2014 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2015 rename_info
= (struct set_file_rename
*) data_offset
;
2016 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2017 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2018 pSMB
->SetupCount
= 1;
2019 pSMB
->Reserved3
= 0;
2020 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2021 byte_count
= 3 /* pad */ + params
;
2022 pSMB
->ParameterCount
= cpu_to_le16(params
);
2023 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2024 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2025 pSMB
->DataOffset
= cpu_to_le16(offset
);
2026 /* construct random name ".cifs_tmp<inodenum><mid>" */
2027 rename_info
->overwrite
= cpu_to_le32(1);
2028 rename_info
->root_fid
= 0;
2029 /* unicode only call */
2030 if (target_name
== NULL
) {
2031 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2032 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2033 dummy_string
, 24, nls_codepage
, remap
);
2035 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2036 target_name
, PATH_MAX
, nls_codepage
,
2039 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2040 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
2041 byte_count
+= count
;
2042 pSMB
->DataCount
= cpu_to_le16(count
);
2043 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2045 pSMB
->InformationLevel
=
2046 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2047 pSMB
->Reserved4
= 0;
2048 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2049 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2050 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2051 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2052 cifs_stats_inc(&pTcon
->num_t2renames
);
2054 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2056 cifs_buf_release(pSMB
);
2058 /* Note: On -EAGAIN error only caller can retry on handle based calls
2059 since file handle passed in no longer valid */
2065 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2066 const __u16 target_tid
, const char *toName
, const int flags
,
2067 const struct nls_table
*nls_codepage
, int remap
)
2070 COPY_REQ
*pSMB
= NULL
;
2071 COPY_RSP
*pSMBr
= NULL
;
2073 int name_len
, name_len2
;
2076 cFYI(1, ("In CIFSSMBCopy"));
2078 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2083 pSMB
->BufferFormat
= 0x04;
2084 pSMB
->Tid2
= target_tid
;
2086 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2088 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2089 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2090 fromName
, PATH_MAX
, nls_codepage
,
2092 name_len
++; /* trailing null */
2094 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2095 /* protocol requires ASCII signature byte on Unicode string */
2096 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2098 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2099 toName
, PATH_MAX
, nls_codepage
, remap
);
2100 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2101 name_len2
*= 2; /* convert to bytes */
2102 } else { /* BB improve the check for buffer overruns BB */
2103 name_len
= strnlen(fromName
, PATH_MAX
);
2104 name_len
++; /* trailing null */
2105 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2106 name_len2
= strnlen(toName
, PATH_MAX
);
2107 name_len2
++; /* trailing null */
2108 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2109 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2110 name_len2
++; /* trailing null */
2111 name_len2
++; /* signature byte */
2114 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2115 pSMB
->hdr
.smb_buf_length
+= count
;
2116 pSMB
->ByteCount
= cpu_to_le16(count
);
2118 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2119 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2121 cFYI(1, ("Send error in copy = %d with %d files copied",
2122 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2125 cifs_buf_release(pSMB
);
2134 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2135 const char *fromName
, const char *toName
,
2136 const struct nls_table
*nls_codepage
)
2138 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2139 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2142 int name_len_target
;
2144 int bytes_returned
= 0;
2145 __u16 params
, param_offset
, offset
, byte_count
;
2147 cFYI(1, ("In Symlink Unix style"));
2149 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2154 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2156 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2157 /* find define for this maxpathcomponent */
2159 name_len
++; /* trailing null */
2162 } else { /* BB improve the check for buffer overruns BB */
2163 name_len
= strnlen(fromName
, PATH_MAX
);
2164 name_len
++; /* trailing null */
2165 strncpy(pSMB
->FileName
, fromName
, name_len
);
2167 params
= 6 + name_len
;
2168 pSMB
->MaxSetupCount
= 0;
2172 pSMB
->Reserved2
= 0;
2173 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2174 InformationLevel
) - 4;
2175 offset
= param_offset
+ params
;
2177 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2178 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2180 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2181 /* find define for this maxpathcomponent */
2183 name_len_target
++; /* trailing null */
2184 name_len_target
*= 2;
2185 } else { /* BB improve the check for buffer overruns BB */
2186 name_len_target
= strnlen(toName
, PATH_MAX
);
2187 name_len_target
++; /* trailing null */
2188 strncpy(data_offset
, toName
, name_len_target
);
2191 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2192 /* BB find exact max on data count below from sess */
2193 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2194 pSMB
->SetupCount
= 1;
2195 pSMB
->Reserved3
= 0;
2196 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2197 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2198 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2199 pSMB
->ParameterCount
= cpu_to_le16(params
);
2200 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2201 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2202 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2203 pSMB
->DataOffset
= cpu_to_le16(offset
);
2204 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2205 pSMB
->Reserved4
= 0;
2206 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2207 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2208 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2209 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2210 cifs_stats_inc(&tcon
->num_symlinks
);
2212 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2215 cifs_buf_release(pSMB
);
2218 goto createSymLinkRetry
;
2224 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2225 const char *fromName
, const char *toName
,
2226 const struct nls_table
*nls_codepage
, int remap
)
2228 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2229 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2232 int name_len_target
;
2234 int bytes_returned
= 0;
2235 __u16 params
, param_offset
, offset
, byte_count
;
2237 cFYI(1, ("In Create Hard link Unix style"));
2238 createHardLinkRetry
:
2239 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2244 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2245 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2246 PATH_MAX
, nls_codepage
, remap
);
2247 name_len
++; /* trailing null */
2250 } else { /* BB improve the check for buffer overruns BB */
2251 name_len
= strnlen(toName
, PATH_MAX
);
2252 name_len
++; /* trailing null */
2253 strncpy(pSMB
->FileName
, toName
, name_len
);
2255 params
= 6 + name_len
;
2256 pSMB
->MaxSetupCount
= 0;
2260 pSMB
->Reserved2
= 0;
2261 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2262 InformationLevel
) - 4;
2263 offset
= param_offset
+ params
;
2265 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2266 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2268 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2269 nls_codepage
, remap
);
2270 name_len_target
++; /* trailing null */
2271 name_len_target
*= 2;
2272 } else { /* BB improve the check for buffer overruns BB */
2273 name_len_target
= strnlen(fromName
, PATH_MAX
);
2274 name_len_target
++; /* trailing null */
2275 strncpy(data_offset
, fromName
, name_len_target
);
2278 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2279 /* BB find exact max on data count below from sess*/
2280 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2281 pSMB
->SetupCount
= 1;
2282 pSMB
->Reserved3
= 0;
2283 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2284 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2285 pSMB
->ParameterCount
= cpu_to_le16(params
);
2286 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2287 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2288 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2289 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2290 pSMB
->DataOffset
= cpu_to_le16(offset
);
2291 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2292 pSMB
->Reserved4
= 0;
2293 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2294 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2295 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2296 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2297 cifs_stats_inc(&tcon
->num_hardlinks
);
2299 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2301 cifs_buf_release(pSMB
);
2303 goto createHardLinkRetry
;
2309 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2310 const char *fromName
, const char *toName
,
2311 const struct nls_table
*nls_codepage
, int remap
)
2314 NT_RENAME_REQ
*pSMB
= NULL
;
2315 RENAME_RSP
*pSMBr
= NULL
;
2317 int name_len
, name_len2
;
2320 cFYI(1, ("In CIFSCreateHardLink"));
2321 winCreateHardLinkRetry
:
2323 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2328 pSMB
->SearchAttributes
=
2329 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2331 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2332 pSMB
->ClusterCount
= 0;
2334 pSMB
->BufferFormat
= 0x04;
2336 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2338 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2339 PATH_MAX
, nls_codepage
, remap
);
2340 name_len
++; /* trailing null */
2342 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2343 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2345 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2346 toName
, PATH_MAX
, nls_codepage
, remap
);
2347 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2348 name_len2
*= 2; /* convert to bytes */
2349 } else { /* BB improve the check for buffer overruns BB */
2350 name_len
= strnlen(fromName
, PATH_MAX
);
2351 name_len
++; /* trailing null */
2352 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2353 name_len2
= strnlen(toName
, PATH_MAX
);
2354 name_len2
++; /* trailing null */
2355 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2356 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2357 name_len2
++; /* trailing null */
2358 name_len2
++; /* signature byte */
2361 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2362 pSMB
->hdr
.smb_buf_length
+= count
;
2363 pSMB
->ByteCount
= cpu_to_le16(count
);
2365 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2366 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2367 cifs_stats_inc(&tcon
->num_hardlinks
);
2369 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2371 cifs_buf_release(pSMB
);
2373 goto winCreateHardLinkRetry
;
2379 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2380 const unsigned char *searchName
,
2381 char *symlinkinfo
, const int buflen
,
2382 const struct nls_table
*nls_codepage
)
2384 /* SMB_QUERY_FILE_UNIX_LINK */
2385 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2386 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2390 __u16 params
, byte_count
;
2392 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2395 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2400 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2402 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2403 PATH_MAX
, nls_codepage
);
2404 name_len
++; /* trailing null */
2406 } else { /* BB improve the check for buffer overruns BB */
2407 name_len
= strnlen(searchName
, PATH_MAX
);
2408 name_len
++; /* trailing null */
2409 strncpy(pSMB
->FileName
, searchName
, name_len
);
2412 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2413 pSMB
->TotalDataCount
= 0;
2414 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2415 /* BB find exact max data count below from sess structure BB */
2416 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2417 pSMB
->MaxSetupCount
= 0;
2421 pSMB
->Reserved2
= 0;
2422 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2423 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2424 pSMB
->DataCount
= 0;
2425 pSMB
->DataOffset
= 0;
2426 pSMB
->SetupCount
= 1;
2427 pSMB
->Reserved3
= 0;
2428 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2429 byte_count
= params
+ 1 /* pad */ ;
2430 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2431 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2432 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2433 pSMB
->Reserved4
= 0;
2434 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2435 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2437 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2438 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2440 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2442 /* decode response */
2444 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2445 if (rc
|| (pSMBr
->ByteCount
< 2))
2446 /* BB also check enough total bytes returned */
2447 rc
= -EIO
; /* bad smb */
2449 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2450 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2452 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2453 name_len
= UniStrnlen((wchar_t *) ((char *)
2454 &pSMBr
->hdr
.Protocol
+ data_offset
),
2455 min_t(const int, buflen
, count
) / 2);
2456 /* BB FIXME investigate remapping reserved chars here */
2457 cifs_strfromUCS_le(symlinkinfo
,
2458 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
2460 name_len
, nls_codepage
);
2462 strncpy(symlinkinfo
,
2463 (char *) &pSMBr
->hdr
.Protocol
+
2465 min_t(const int, buflen
, count
));
2467 symlinkinfo
[buflen
] = 0;
2468 /* just in case so calling code does not go off the end of buffer */
2471 cifs_buf_release(pSMB
);
2473 goto querySymLinkRetry
;
2477 #ifdef CONFIG_CIFS_EXPERIMENTAL
2478 /* Initialize NT TRANSACT SMB into small smb request buffer.
2479 This assumes that all NT TRANSACTS that we init here have
2480 total parm and data under about 400 bytes (to fit in small cifs
2481 buffer size), which is the case so far, it easily fits. NB:
2482 Setup words themselves and ByteCount
2483 MaxSetupCount (size of returned setup area) and
2484 MaxParameterCount (returned parms size) must be set by caller */
2486 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2487 const int parm_len
, struct cifsTconInfo
*tcon
,
2492 struct smb_com_ntransact_req
*pSMB
;
2494 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2498 *ret_buf
= (void *)pSMB
;
2500 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2501 pSMB
->TotalDataCount
= 0;
2502 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2503 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2504 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2505 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2506 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2507 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2508 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2509 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2510 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2511 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2516 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2517 __u32
*pparmlen
, __u32
*pdatalen
)
2520 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2521 struct smb_com_ntransact_rsp
*pSMBr
;
2529 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2531 /* ByteCount was converted from little endian in SendReceive */
2532 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2533 (char *)&pSMBr
->ByteCount
;
2535 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2536 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2537 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2538 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2540 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2541 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2543 /* should we also check that parm and data areas do not overlap? */
2544 if (*ppparm
> end_of_smb
) {
2545 cFYI(1, ("parms start after end of smb"));
2547 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2548 cFYI(1, ("parm end after end of smb"));
2550 } else if (*ppdata
> end_of_smb
) {
2551 cFYI(1, ("data starts after end of smb"));
2553 } else if (data_count
+ *ppdata
> end_of_smb
) {
2554 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2555 *ppdata
, data_count
, (data_count
+ *ppdata
),
2556 end_of_smb
, pSMBr
));
2558 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2559 cFYI(1, ("parm count and data count larger than SMB"));
2562 *pdatalen
= data_count
;
2563 *pparmlen
= parm_count
;
2566 #endif /* CIFS_EXPERIMENTAL */
2569 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2570 const unsigned char *searchName
,
2571 char *symlinkinfo
, const int buflen
, __u16 fid
,
2572 const struct nls_table
*nls_codepage
)
2577 struct smb_com_transaction_ioctl_req
*pSMB
;
2578 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2580 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2581 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2586 pSMB
->TotalParameterCount
= 0 ;
2587 pSMB
->TotalDataCount
= 0;
2588 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2589 /* BB find exact data count max from sess structure BB */
2590 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2591 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2592 pSMB
->MaxSetupCount
= 4;
2594 pSMB
->ParameterOffset
= 0;
2595 pSMB
->DataCount
= 0;
2596 pSMB
->DataOffset
= 0;
2597 pSMB
->SetupCount
= 4;
2598 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2599 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2600 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2601 pSMB
->IsFsctl
= 1; /* FSCTL */
2602 pSMB
->IsRootFlag
= 0;
2603 pSMB
->Fid
= fid
; /* file handle always le */
2604 pSMB
->ByteCount
= 0;
2606 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2607 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2609 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2610 } else { /* decode response */
2611 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2612 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2613 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2614 /* BB also check enough total bytes returned */
2615 rc
= -EIO
; /* bad smb */
2617 if (data_count
&& (data_count
< 2048)) {
2618 char *end_of_smb
= 2 /* sizeof byte count */ +
2620 (char *)&pSMBr
->ByteCount
;
2622 struct reparse_data
*reparse_buf
=
2623 (struct reparse_data
*)
2624 ((char *)&pSMBr
->hdr
.Protocol
2626 if ((char *)reparse_buf
>= end_of_smb
) {
2630 if ((reparse_buf
->LinkNamesBuf
+
2631 reparse_buf
->TargetNameOffset
+
2632 reparse_buf
->TargetNameLen
) >
2634 cFYI(1, ("reparse buf beyond SMB"));
2639 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2640 name_len
= UniStrnlen((wchar_t *)
2641 (reparse_buf
->LinkNamesBuf
+
2642 reparse_buf
->TargetNameOffset
),
2644 reparse_buf
->TargetNameLen
/ 2));
2645 cifs_strfromUCS_le(symlinkinfo
,
2646 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2647 reparse_buf
->TargetNameOffset
),
2648 name_len
, nls_codepage
);
2649 } else { /* ASCII names */
2650 strncpy(symlinkinfo
,
2651 reparse_buf
->LinkNamesBuf
+
2652 reparse_buf
->TargetNameOffset
,
2653 min_t(const int, buflen
,
2654 reparse_buf
->TargetNameLen
));
2658 cFYI(1, ("Invalid return data count on "
2659 "get reparse info ioctl"));
2661 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2662 does not go off the end of the buffer */
2663 cFYI(1, ("readlink result - %s", symlinkinfo
));
2667 cifs_buf_release(pSMB
);
2669 /* Note: On -EAGAIN error only caller can retry on handle based calls
2670 since file handle passed in no longer valid */
2675 #ifdef CONFIG_CIFS_POSIX
2677 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2678 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2679 struct cifs_posix_ace
*cifs_ace
)
2681 /* u8 cifs fields do not need le conversion */
2682 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2683 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2684 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2685 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2690 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2691 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2692 const int acl_type
, const int size_of_data_area
)
2697 struct cifs_posix_ace
*pACE
;
2698 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2699 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2701 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2704 if (acl_type
& ACL_TYPE_ACCESS
) {
2705 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2706 pACE
= &cifs_acl
->ace_array
[0];
2707 size
= sizeof(struct cifs_posix_acl
);
2708 size
+= sizeof(struct cifs_posix_ace
) * count
;
2709 /* check if we would go beyond end of SMB */
2710 if (size_of_data_area
< size
) {
2711 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2712 size_of_data_area
, size
));
2715 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2716 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2717 size
= sizeof(struct cifs_posix_acl
);
2718 size
+= sizeof(struct cifs_posix_ace
) * count
;
2719 /* skip past access ACEs to get to default ACEs */
2720 pACE
= &cifs_acl
->ace_array
[count
];
2721 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2722 size
+= sizeof(struct cifs_posix_ace
) * count
;
2723 /* check if we would go beyond end of SMB */
2724 if (size_of_data_area
< size
)
2731 size
= posix_acl_xattr_size(count
);
2732 if ((buflen
== 0) || (local_acl
== NULL
)) {
2733 /* used to query ACL EA size */
2734 } else if (size
> buflen
) {
2736 } else /* buffer big enough */ {
2737 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2738 for (i
= 0; i
< count
; i
++) {
2739 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2746 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2747 const posix_acl_xattr_entry
*local_ace
)
2749 __u16 rc
= 0; /* 0 = ACL converted ok */
2751 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2752 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2753 /* BB is there a better way to handle the large uid? */
2754 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2755 /* Probably no need to le convert -1 on any arch but can not hurt */
2756 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2758 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2759 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2763 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2764 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2765 const int buflen
, const int acl_type
)
2768 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2769 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2773 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2776 count
= posix_acl_xattr_count((size_t)buflen
);
2777 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2779 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2780 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2781 cFYI(1, ("unknown POSIX ACL version %d",
2782 le32_to_cpu(local_acl
->a_version
)));
2785 cifs_acl
->version
= cpu_to_le16(1);
2786 if (acl_type
== ACL_TYPE_ACCESS
)
2787 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2788 else if (acl_type
== ACL_TYPE_DEFAULT
)
2789 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2791 cFYI(1, ("unknown ACL type %d", acl_type
));
2794 for (i
= 0; i
< count
; i
++) {
2795 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2796 &local_acl
->a_entries
[i
]);
2798 /* ACE not converted */
2803 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2804 rc
+= sizeof(struct cifs_posix_acl
);
2805 /* BB add check to make sure ACL does not overflow SMB */
2811 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2812 const unsigned char *searchName
,
2813 char *acl_inf
, const int buflen
, const int acl_type
,
2814 const struct nls_table
*nls_codepage
, int remap
)
2816 /* SMB_QUERY_POSIX_ACL */
2817 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2818 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2822 __u16 params
, byte_count
;
2824 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2827 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2832 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2834 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2835 PATH_MAX
, nls_codepage
, remap
);
2836 name_len
++; /* trailing null */
2838 pSMB
->FileName
[name_len
] = 0;
2839 pSMB
->FileName
[name_len
+1] = 0;
2840 } else { /* BB improve the check for buffer overruns BB */
2841 name_len
= strnlen(searchName
, PATH_MAX
);
2842 name_len
++; /* trailing null */
2843 strncpy(pSMB
->FileName
, searchName
, name_len
);
2846 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2847 pSMB
->TotalDataCount
= 0;
2848 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2849 /* BB find exact max data count below from sess structure BB */
2850 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2851 pSMB
->MaxSetupCount
= 0;
2855 pSMB
->Reserved2
= 0;
2856 pSMB
->ParameterOffset
= cpu_to_le16(
2857 offsetof(struct smb_com_transaction2_qpi_req
,
2858 InformationLevel
) - 4);
2859 pSMB
->DataCount
= 0;
2860 pSMB
->DataOffset
= 0;
2861 pSMB
->SetupCount
= 1;
2862 pSMB
->Reserved3
= 0;
2863 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2864 byte_count
= params
+ 1 /* pad */ ;
2865 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2866 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2867 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2868 pSMB
->Reserved4
= 0;
2869 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2870 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2872 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2873 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2874 cifs_stats_inc(&tcon
->num_acl_get
);
2876 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2878 /* decode response */
2880 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2881 if (rc
|| (pSMBr
->ByteCount
< 2))
2882 /* BB also check enough total bytes returned */
2883 rc
= -EIO
; /* bad smb */
2885 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2886 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2887 rc
= cifs_copy_posix_acl(acl_inf
,
2888 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2889 buflen
, acl_type
, count
);
2892 cifs_buf_release(pSMB
);
2899 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2900 const unsigned char *fileName
,
2901 const char *local_acl
, const int buflen
,
2903 const struct nls_table
*nls_codepage
, int remap
)
2905 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2906 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2910 int bytes_returned
= 0;
2911 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2913 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2915 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2919 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2921 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2922 PATH_MAX
, nls_codepage
, remap
);
2923 name_len
++; /* trailing null */
2925 } else { /* BB improve the check for buffer overruns BB */
2926 name_len
= strnlen(fileName
, PATH_MAX
);
2927 name_len
++; /* trailing null */
2928 strncpy(pSMB
->FileName
, fileName
, name_len
);
2930 params
= 6 + name_len
;
2931 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2932 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2933 pSMB
->MaxSetupCount
= 0;
2937 pSMB
->Reserved2
= 0;
2938 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2939 InformationLevel
) - 4;
2940 offset
= param_offset
+ params
;
2941 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2942 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2944 /* convert to on the wire format for POSIX ACL */
2945 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2947 if (data_count
== 0) {
2949 goto setACLerrorExit
;
2951 pSMB
->DataOffset
= cpu_to_le16(offset
);
2952 pSMB
->SetupCount
= 1;
2953 pSMB
->Reserved3
= 0;
2954 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2955 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2956 byte_count
= 3 /* pad */ + params
+ data_count
;
2957 pSMB
->DataCount
= cpu_to_le16(data_count
);
2958 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2959 pSMB
->ParameterCount
= cpu_to_le16(params
);
2960 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2961 pSMB
->Reserved4
= 0;
2962 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2963 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2964 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2965 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2967 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2970 cifs_buf_release(pSMB
);
2976 /* BB fix tabs in this function FIXME BB */
2978 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2979 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2982 struct smb_t2_qfi_req
*pSMB
= NULL
;
2983 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2985 __u16 params
, byte_count
;
2987 cFYI(1, ("In GetExtAttr"));
2992 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2997 params
= 2 /* level */ + 2 /* fid */;
2998 pSMB
->t2
.TotalDataCount
= 0;
2999 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3000 /* BB find exact max data count below from sess structure BB */
3001 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3002 pSMB
->t2
.MaxSetupCount
= 0;
3003 pSMB
->t2
.Reserved
= 0;
3005 pSMB
->t2
.Timeout
= 0;
3006 pSMB
->t2
.Reserved2
= 0;
3007 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3009 pSMB
->t2
.DataCount
= 0;
3010 pSMB
->t2
.DataOffset
= 0;
3011 pSMB
->t2
.SetupCount
= 1;
3012 pSMB
->t2
.Reserved3
= 0;
3013 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3014 byte_count
= params
+ 1 /* pad */ ;
3015 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3016 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3017 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3020 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3021 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3023 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3024 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3026 cFYI(1, ("error %d in GetExtAttr", rc
));
3028 /* decode response */
3029 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3030 if (rc
|| (pSMBr
->ByteCount
< 2))
3031 /* BB also check enough total bytes returned */
3032 /* If rc should we check for EOPNOSUPP and
3033 disable the srvino flag? or in caller? */
3034 rc
= -EIO
; /* bad smb */
3036 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3037 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3038 struct file_chattr_info
*pfinfo
;
3039 /* BB Do we need a cast or hash here ? */
3041 cFYI(1, ("Illegal size ret in GetExtAttr"));
3045 pfinfo
= (struct file_chattr_info
*)
3046 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3047 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3048 *pMask
= le64_to_cpu(pfinfo
->mask
);
3052 cifs_buf_release(pSMB
);
3054 goto GetExtAttrRetry
;
3058 #endif /* CONFIG_POSIX */
3060 #ifdef CONFIG_CIFS_EXPERIMENTAL
3061 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3063 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3064 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3068 QUERY_SEC_DESC_REQ
*pSMB
;
3071 cFYI(1, ("GetCifsACL"));
3076 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3077 8 /* parm len */, tcon
, (void **) &pSMB
);
3081 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3082 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3083 pSMB
->MaxSetupCount
= 0;
3084 pSMB
->Fid
= fid
; /* file handle always le */
3085 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3087 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3088 pSMB
->hdr
.smb_buf_length
+= 11;
3089 iov
[0].iov_base
= (char *)pSMB
;
3090 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3092 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3094 cifs_stats_inc(&tcon
->num_acl_get
);
3096 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3097 } else { /* decode response */
3101 struct smb_com_ntransact_rsp
*pSMBr
;
3104 /* validate_nttransact */
3105 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3106 &pdata
, &parm_len
, pbuflen
);
3109 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3111 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3113 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3114 rc
= -EIO
; /* bad smb */
3119 /* BB check that data area is minimum length and as big as acl_len */
3121 acl_len
= le32_to_cpu(*parm
);
3122 if (acl_len
!= *pbuflen
) {
3123 cERROR(1, ("acl length %d does not match %d",
3124 acl_len
, *pbuflen
));
3125 if (*pbuflen
> acl_len
)
3129 /* check if buffer is big enough for the acl
3130 header followed by the smallest SID */
3131 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3132 (*pbuflen
>= 64 * 1024)) {
3133 cERROR(1, ("bad acl length %d", *pbuflen
));
3137 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3138 if (*acl_inf
== NULL
) {
3142 memcpy(*acl_inf
, pdata
, *pbuflen
);
3146 if (buf_type
== CIFS_SMALL_BUFFER
)
3147 cifs_small_buf_release(iov
[0].iov_base
);
3148 else if (buf_type
== CIFS_LARGE_BUFFER
)
3149 cifs_buf_release(iov
[0].iov_base
);
3150 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3155 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3156 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3158 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3160 int bytes_returned
= 0;
3161 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3162 NTRANSACT_RSP
*pSMBr
= NULL
;
3165 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3170 pSMB
->MaxSetupCount
= 0;
3174 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3175 data_count
= acllen
;
3176 data_offset
= param_offset
+ param_count
;
3177 byte_count
= 3 /* pad */ + param_count
;
3179 pSMB
->DataCount
= cpu_to_le32(data_count
);
3180 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3181 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3182 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3183 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3184 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3185 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3186 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3187 pSMB
->SetupCount
= 0;
3188 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3189 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3191 pSMB
->Fid
= fid
; /* file handle always le */
3192 pSMB
->Reserved2
= 0;
3193 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3195 if (pntsd
&& acllen
) {
3196 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3199 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3202 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3204 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3205 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3207 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3209 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3210 cifs_buf_release(pSMB
);
3213 goto setCifsAclRetry
;
3218 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3220 /* Legacy Query Path Information call for lookup to old servers such
3222 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3223 const unsigned char *searchName
,
3224 FILE_ALL_INFO
*pFinfo
,
3225 const struct nls_table
*nls_codepage
, int remap
)
3227 QUERY_INFORMATION_REQ
*pSMB
;
3228 QUERY_INFORMATION_RSP
*pSMBr
;
3233 cFYI(1, ("In SMBQPath path %s", searchName
));
3235 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3240 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3242 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3243 PATH_MAX
, nls_codepage
, remap
);
3244 name_len
++; /* trailing null */
3247 name_len
= strnlen(searchName
, PATH_MAX
);
3248 name_len
++; /* trailing null */
3249 strncpy(pSMB
->FileName
, searchName
, name_len
);
3251 pSMB
->BufferFormat
= 0x04;
3252 name_len
++; /* account for buffer type byte */
3253 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3254 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3256 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3257 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3259 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3260 } else if (pFinfo
) {
3262 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3264 /* decode response */
3265 /* BB FIXME - add time zone adjustment BB */
3266 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3269 /* decode time fields */
3270 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3271 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3272 pFinfo
->LastAccessTime
= 0;
3273 pFinfo
->AllocationSize
=
3274 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3275 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3276 pFinfo
->Attributes
=
3277 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3279 rc
= -EIO
; /* bad buffer passed in */
3281 cifs_buf_release(pSMB
);
3293 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3294 const unsigned char *searchName
,
3295 FILE_ALL_INFO
*pFindData
,
3296 int legacy
/* old style infolevel */,
3297 const struct nls_table
*nls_codepage
, int remap
)
3299 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3300 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3301 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3305 __u16 params
, byte_count
;
3307 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3309 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3314 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3316 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3317 PATH_MAX
, nls_codepage
, remap
);
3318 name_len
++; /* trailing null */
3320 } else { /* BB improve the check for buffer overruns BB */
3321 name_len
= strnlen(searchName
, PATH_MAX
);
3322 name_len
++; /* trailing null */
3323 strncpy(pSMB
->FileName
, searchName
, name_len
);
3326 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3327 pSMB
->TotalDataCount
= 0;
3328 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3329 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3330 pSMB
->MaxSetupCount
= 0;
3334 pSMB
->Reserved2
= 0;
3335 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3336 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3337 pSMB
->DataCount
= 0;
3338 pSMB
->DataOffset
= 0;
3339 pSMB
->SetupCount
= 1;
3340 pSMB
->Reserved3
= 0;
3341 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3342 byte_count
= params
+ 1 /* pad */ ;
3343 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3344 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3346 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3348 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3349 pSMB
->Reserved4
= 0;
3350 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3351 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3353 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3354 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3356 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3357 } else { /* decode response */
3358 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3360 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3362 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3363 rc
= -EIO
; /* bad smb */
3364 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3365 rc
= -EIO
; /* 24 or 26 expected but we do not read
3367 else if (pFindData
) {
3369 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3371 /* On legacy responses we do not read the last field,
3372 EAsize, fortunately since it varies by subdialect and
3373 also note it differs on Set vs. Get, ie two bytes or 4
3374 bytes depending but we don't care here */
3376 size
= sizeof(FILE_INFO_STANDARD
);
3378 size
= sizeof(FILE_ALL_INFO
);
3379 memcpy((char *) pFindData
,
3380 (char *) &pSMBr
->hdr
.Protocol
+
3385 cifs_buf_release(pSMB
);
3387 goto QPathInfoRetry
;
3393 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3394 const unsigned char *searchName
,
3395 FILE_UNIX_BASIC_INFO
* pFindData
,
3396 const struct nls_table
*nls_codepage
, int remap
)
3398 /* SMB_QUERY_FILE_UNIX_BASIC */
3399 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3400 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3402 int bytes_returned
= 0;
3404 __u16 params
, byte_count
;
3406 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3408 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3413 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3415 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3416 PATH_MAX
, nls_codepage
, remap
);
3417 name_len
++; /* trailing null */
3419 } else { /* BB improve the check for buffer overruns BB */
3420 name_len
= strnlen(searchName
, PATH_MAX
);
3421 name_len
++; /* trailing null */
3422 strncpy(pSMB
->FileName
, searchName
, name_len
);
3425 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3426 pSMB
->TotalDataCount
= 0;
3427 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3428 /* BB find exact max SMB PDU from sess structure BB */
3429 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3430 pSMB
->MaxSetupCount
= 0;
3434 pSMB
->Reserved2
= 0;
3435 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3436 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3437 pSMB
->DataCount
= 0;
3438 pSMB
->DataOffset
= 0;
3439 pSMB
->SetupCount
= 1;
3440 pSMB
->Reserved3
= 0;
3441 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3442 byte_count
= params
+ 1 /* pad */ ;
3443 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3444 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3445 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3446 pSMB
->Reserved4
= 0;
3447 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3448 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3450 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3451 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3453 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3454 } else { /* decode response */
3455 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3457 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3458 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3459 "Unix Extensions can be disabled on mount "
3460 "by specifying the nosfu mount option."));
3461 rc
= -EIO
; /* bad smb */
3463 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3464 memcpy((char *) pFindData
,
3465 (char *) &pSMBr
->hdr
.Protocol
+
3467 sizeof(FILE_UNIX_BASIC_INFO
));
3470 cifs_buf_release(pSMB
);
3472 goto UnixQPathInfoRetry
;
3477 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3479 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3480 const char *searchName
,
3481 const struct nls_table
*nls_codepage
,
3483 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3485 /* level 257 SMB_ */
3486 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3487 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3488 T2_FFIRST_RSP_PARMS
*parms
;
3490 int bytes_returned
= 0;
3492 __u16 params
, byte_count
;
3494 cFYI(1, ("In FindFirst for %s", searchName
));
3497 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3502 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3504 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3505 PATH_MAX
, nls_codepage
, remap
);
3506 /* We can not add the asterik earlier in case
3507 it got remapped to 0xF03A as if it were part of the
3508 directory name instead of a wildcard */
3510 pSMB
->FileName
[name_len
] = dirsep
;
3511 pSMB
->FileName
[name_len
+1] = 0;
3512 pSMB
->FileName
[name_len
+2] = '*';
3513 pSMB
->FileName
[name_len
+3] = 0;
3514 name_len
+= 4; /* now the trailing null */
3515 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3516 pSMB
->FileName
[name_len
+1] = 0;
3518 } else { /* BB add check for overrun of SMB buf BB */
3519 name_len
= strnlen(searchName
, PATH_MAX
);
3520 /* BB fix here and in unicode clause above ie
3521 if (name_len > buffersize-header)
3522 free buffer exit; BB */
3523 strncpy(pSMB
->FileName
, searchName
, name_len
);
3524 pSMB
->FileName
[name_len
] = dirsep
;
3525 pSMB
->FileName
[name_len
+1] = '*';
3526 pSMB
->FileName
[name_len
+2] = 0;
3530 params
= 12 + name_len
/* includes null */ ;
3531 pSMB
->TotalDataCount
= 0; /* no EAs */
3532 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3533 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3534 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3535 pSMB
->MaxSetupCount
= 0;
3539 pSMB
->Reserved2
= 0;
3540 byte_count
= params
+ 1 /* pad */ ;
3541 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3542 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3543 pSMB
->ParameterOffset
= cpu_to_le16(
3544 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3546 pSMB
->DataCount
= 0;
3547 pSMB
->DataOffset
= 0;
3548 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3549 pSMB
->Reserved3
= 0;
3550 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3551 pSMB
->SearchAttributes
=
3552 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3554 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3555 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3556 CIFS_SEARCH_RETURN_RESUME
);
3557 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3559 /* BB what should we set StorageType to? Does it matter? BB */
3560 pSMB
->SearchStorageType
= 0;
3561 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3562 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3564 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3565 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3566 cifs_stats_inc(&tcon
->num_ffirst
);
3568 if (rc
) {/* BB add logic to retry regular search if Unix search
3569 rejected unexpectedly by server */
3570 /* BB Add code to handle unsupported level rc */
3571 cFYI(1, ("Error in FindFirst = %d", rc
));
3573 cifs_buf_release(pSMB
);
3575 /* BB eventually could optimize out free and realloc of buf */
3578 goto findFirstRetry
;
3579 } else { /* decode response */
3580 /* BB remember to free buffer if error BB */
3581 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3583 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3584 psrch_inf
->unicode
= TRUE
;
3586 psrch_inf
->unicode
= FALSE
;
3588 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3589 psrch_inf
->smallBuf
= 0;
3590 psrch_inf
->srch_entries_start
=
3591 (char *) &pSMBr
->hdr
.Protocol
+
3592 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3593 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3594 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3596 if (parms
->EndofSearch
)
3597 psrch_inf
->endOfSearch
= TRUE
;
3599 psrch_inf
->endOfSearch
= FALSE
;
3601 psrch_inf
->entries_in_buffer
=
3602 le16_to_cpu(parms
->SearchCount
);
3603 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3604 psrch_inf
->entries_in_buffer
;
3605 *pnetfid
= parms
->SearchHandle
;
3607 cifs_buf_release(pSMB
);
3614 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3615 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3617 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3618 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3619 T2_FNEXT_RSP_PARMS
*parms
;
3620 char *response_data
;
3622 int bytes_returned
, name_len
;
3623 __u16 params
, byte_count
;
3625 cFYI(1, ("In FindNext"));
3627 if (psrch_inf
->endOfSearch
== TRUE
)
3630 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3635 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3637 pSMB
->TotalDataCount
= 0; /* no EAs */
3638 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3639 pSMB
->MaxDataCount
=
3640 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3642 pSMB
->MaxSetupCount
= 0;
3646 pSMB
->Reserved2
= 0;
3647 pSMB
->ParameterOffset
= cpu_to_le16(
3648 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3649 pSMB
->DataCount
= 0;
3650 pSMB
->DataOffset
= 0;
3651 pSMB
->SetupCount
= 1;
3652 pSMB
->Reserved3
= 0;
3653 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3654 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3656 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3657 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3658 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3660 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3662 name_len
= psrch_inf
->resume_name_len
;
3664 if (name_len
< PATH_MAX
) {
3665 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3666 byte_count
+= name_len
;
3667 /* 14 byte parm len above enough for 2 byte null terminator */
3668 pSMB
->ResumeFileName
[name_len
] = 0;
3669 pSMB
->ResumeFileName
[name_len
+1] = 0;
3672 goto FNext2_err_exit
;
3674 byte_count
= params
+ 1 /* pad */ ;
3675 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3676 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3677 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3678 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3680 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3681 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3682 cifs_stats_inc(&tcon
->num_fnext
);
3685 psrch_inf
->endOfSearch
= TRUE
;
3686 rc
= 0; /* search probably was closed at end of search*/
3688 cFYI(1, ("FindNext returned = %d", rc
));
3689 } else { /* decode response */
3690 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3693 /* BB fixme add lock for file (srch_info) struct here */
3694 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3695 psrch_inf
->unicode
= TRUE
;
3697 psrch_inf
->unicode
= FALSE
;
3698 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3699 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3700 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3701 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3702 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3703 if (psrch_inf
->smallBuf
)
3704 cifs_small_buf_release(
3705 psrch_inf
->ntwrk_buf_start
);
3707 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3708 psrch_inf
->srch_entries_start
= response_data
;
3709 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3710 psrch_inf
->smallBuf
= 0;
3711 if (parms
->EndofSearch
)
3712 psrch_inf
->endOfSearch
= TRUE
;
3714 psrch_inf
->endOfSearch
= FALSE
;
3715 psrch_inf
->entries_in_buffer
=
3716 le16_to_cpu(parms
->SearchCount
);
3717 psrch_inf
->index_of_last_entry
+=
3718 psrch_inf
->entries_in_buffer
;
3719 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3720 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3722 /* BB fixme add unlock here */
3727 /* BB On error, should we leave previous search buf (and count and
3728 last entry fields) intact or free the previous one? */
3730 /* Note: On -EAGAIN error only caller can retry on handle based calls
3731 since file handle passed in no longer valid */
3734 cifs_buf_release(pSMB
);
3739 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3740 const __u16 searchHandle
)
3743 FINDCLOSE_REQ
*pSMB
= NULL
;
3745 cFYI(1, ("In CIFSSMBFindClose"));
3746 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3748 /* no sense returning error if session restarted
3749 as file handle has been closed */
3755 pSMB
->FileID
= searchHandle
;
3756 pSMB
->ByteCount
= 0;
3757 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3759 cERROR(1, ("Send error in FindClose = %d", rc
));
3761 cifs_stats_inc(&tcon
->num_fclose
);
3763 /* Since session is dead, search handle closed on server already */
3771 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3772 const unsigned char *searchName
,
3773 __u64
*inode_number
,
3774 const struct nls_table
*nls_codepage
, int remap
)
3777 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3778 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3779 int name_len
, bytes_returned
;
3780 __u16 params
, byte_count
;
3782 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3786 GetInodeNumberRetry
:
3787 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3792 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3794 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3795 PATH_MAX
, nls_codepage
, remap
);
3796 name_len
++; /* trailing null */
3798 } else { /* BB improve the check for buffer overruns BB */
3799 name_len
= strnlen(searchName
, PATH_MAX
);
3800 name_len
++; /* trailing null */
3801 strncpy(pSMB
->FileName
, searchName
, name_len
);
3804 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3805 pSMB
->TotalDataCount
= 0;
3806 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3807 /* BB find exact max data count below from sess structure BB */
3808 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3809 pSMB
->MaxSetupCount
= 0;
3813 pSMB
->Reserved2
= 0;
3814 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3815 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3816 pSMB
->DataCount
= 0;
3817 pSMB
->DataOffset
= 0;
3818 pSMB
->SetupCount
= 1;
3819 pSMB
->Reserved3
= 0;
3820 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3821 byte_count
= params
+ 1 /* pad */ ;
3822 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3823 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3824 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3825 pSMB
->Reserved4
= 0;
3826 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3827 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3829 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3830 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3832 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3834 /* decode response */
3835 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3836 if (rc
|| (pSMBr
->ByteCount
< 2))
3837 /* BB also check enough total bytes returned */
3838 /* If rc should we check for EOPNOSUPP and
3839 disable the srvino flag? or in caller? */
3840 rc
= -EIO
; /* bad smb */
3842 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3843 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3844 struct file_internal_info
*pfinfo
;
3845 /* BB Do we need a cast or hash here ? */
3847 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3849 goto GetInodeNumOut
;
3851 pfinfo
= (struct file_internal_info
*)
3852 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3853 *inode_number
= pfinfo
->UniqueId
;
3857 cifs_buf_release(pSMB
);
3859 goto GetInodeNumberRetry
;
3864 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3865 const unsigned char *searchName
,
3866 unsigned char **targetUNCs
,
3867 unsigned int *number_of_UNC_in_array
,
3868 const struct nls_table
*nls_codepage
, int remap
)
3870 /* TRANS2_GET_DFS_REFERRAL */
3871 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3872 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3873 struct dfs_referral_level_3
*referrals
= NULL
;
3879 __u16 params
, byte_count
;
3880 *number_of_UNC_in_array
= 0;
3883 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3887 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3892 /* server pointer checked in called function,
3893 but should never be null here anyway */
3894 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3895 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3896 pSMB
->hdr
.Uid
= ses
->Suid
;
3897 if (ses
->capabilities
& CAP_STATUS32
)
3898 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3899 if (ses
->capabilities
& CAP_DFS
)
3900 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3902 if (ses
->capabilities
& CAP_UNICODE
) {
3903 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3905 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3906 searchName
, PATH_MAX
, nls_codepage
, remap
);
3907 name_len
++; /* trailing null */
3909 } else { /* BB improve the check for buffer overruns BB */
3910 name_len
= strnlen(searchName
, PATH_MAX
);
3911 name_len
++; /* trailing null */
3912 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3916 if (ses
->server
->secMode
&
3917 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
3918 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
3921 pSMB
->hdr
.Uid
= ses
->Suid
;
3923 params
= 2 /* level */ + name_len
/*includes null */ ;
3924 pSMB
->TotalDataCount
= 0;
3925 pSMB
->DataCount
= 0;
3926 pSMB
->DataOffset
= 0;
3927 pSMB
->MaxParameterCount
= 0;
3928 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3929 pSMB
->MaxSetupCount
= 0;
3933 pSMB
->Reserved2
= 0;
3934 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3935 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3936 pSMB
->SetupCount
= 1;
3937 pSMB
->Reserved3
= 0;
3938 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3939 byte_count
= params
+ 3 /* pad */ ;
3940 pSMB
->ParameterCount
= cpu_to_le16(params
);
3941 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3942 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3943 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3944 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3946 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3947 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3949 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3950 } else { /* decode response */
3951 /* BB Add logic to parse referrals here */
3952 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3954 /* BB Also check if enough total bytes returned? */
3955 if (rc
|| (pSMBr
->ByteCount
< 17))
3956 rc
= -EIO
; /* bad smb */
3958 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3959 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3962 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3963 pSMBr
->ByteCount
, data_offset
));
3965 (struct dfs_referral_level_3
*)
3966 (8 /* sizeof start of data block */ +
3968 (char *) &pSMBr
->hdr
.Protocol
);
3969 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3970 "for referral one refer size: 0x%x srv "
3971 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3972 le16_to_cpu(pSMBr
->NumberOfReferrals
),
3973 le16_to_cpu(pSMBr
->DFSFlags
),
3974 le16_to_cpu(referrals
->ReferralSize
),
3975 le16_to_cpu(referrals
->ServerType
),
3976 le16_to_cpu(referrals
->ReferralFlags
),
3977 le16_to_cpu(referrals
->TimeToLive
)));
3978 /* BB This field is actually two bytes in from start of
3979 data block so we could do safety check that DataBlock
3980 begins at address of pSMBr->NumberOfReferrals */
3981 *number_of_UNC_in_array
=
3982 le16_to_cpu(pSMBr
->NumberOfReferrals
);
3984 /* BB Fix below so can return more than one referral */
3985 if (*number_of_UNC_in_array
> 1)
3986 *number_of_UNC_in_array
= 1;
3988 /* get the length of the strings describing refs */
3990 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
3991 /* make sure that DfsPathOffset not past end */
3993 le16_to_cpu(referrals
->DfsPathOffset
);
3994 if (offset
> data_count
) {
3995 /* if invalid referral, stop here and do
3996 not try to copy any more */
3997 *number_of_UNC_in_array
= i
;
4000 temp
= ((char *)referrals
) + offset
;
4002 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4003 name_len
+= UniStrnlen((wchar_t *)temp
,
4006 name_len
+= strnlen(temp
, data_count
);
4009 /* BB add check that referral pointer does
4010 not fall off end PDU */
4012 /* BB add check for name_len bigger than bcc */
4014 kmalloc(name_len
+1+(*number_of_UNC_in_array
),
4016 if (*targetUNCs
== NULL
) {
4020 /* copy the ref strings */
4021 referrals
= (struct dfs_referral_level_3
*)
4022 (8 /* sizeof data hdr */ + data_offset
+
4023 (char *) &pSMBr
->hdr
.Protocol
);
4025 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
4026 temp
= ((char *)referrals
) +
4027 le16_to_cpu(referrals
->DfsPathOffset
);
4028 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4029 cifs_strfromUCS_le(*targetUNCs
,
4034 strncpy(*targetUNCs
, temp
, name_len
);
4036 /* BB update target_uncs pointers */
4046 cifs_buf_release(pSMB
);
4054 /* Query File System Info such as free space to old servers such as Win 9x */
4056 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4058 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4059 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4060 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4061 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4063 int bytes_returned
= 0;
4064 __u16 params
, byte_count
;
4066 cFYI(1, ("OldQFSInfo"));
4068 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4073 params
= 2; /* level */
4074 pSMB
->TotalDataCount
= 0;
4075 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4076 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4077 pSMB
->MaxSetupCount
= 0;
4081 pSMB
->Reserved2
= 0;
4082 byte_count
= params
+ 1 /* pad */ ;
4083 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4084 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4085 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4086 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4087 pSMB
->DataCount
= 0;
4088 pSMB
->DataOffset
= 0;
4089 pSMB
->SetupCount
= 1;
4090 pSMB
->Reserved3
= 0;
4091 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4092 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4093 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4094 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4096 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4097 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4099 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4100 } else { /* decode response */
4101 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4103 if (rc
|| (pSMBr
->ByteCount
< 18))
4104 rc
= -EIO
; /* bad smb */
4106 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4107 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4108 pSMBr
->ByteCount
, data_offset
));
4110 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4111 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4113 le16_to_cpu(response_data
->BytesPerSector
) *
4114 le32_to_cpu(response_data
->
4115 SectorsPerAllocationUnit
);
4117 le32_to_cpu(response_data
->TotalAllocationUnits
);
4118 FSData
->f_bfree
= FSData
->f_bavail
=
4119 le32_to_cpu(response_data
->FreeAllocationUnits
);
4121 ("Blocks: %lld Free: %lld Block size %ld",
4122 (unsigned long long)FSData
->f_blocks
,
4123 (unsigned long long)FSData
->f_bfree
,
4127 cifs_buf_release(pSMB
);
4130 goto oldQFSInfoRetry
;
4136 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4138 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4139 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4140 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4141 FILE_SYSTEM_INFO
*response_data
;
4143 int bytes_returned
= 0;
4144 __u16 params
, byte_count
;
4146 cFYI(1, ("In QFSInfo"));
4148 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4153 params
= 2; /* level */
4154 pSMB
->TotalDataCount
= 0;
4155 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4156 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4157 pSMB
->MaxSetupCount
= 0;
4161 pSMB
->Reserved2
= 0;
4162 byte_count
= params
+ 1 /* pad */ ;
4163 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4164 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4165 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4166 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4167 pSMB
->DataCount
= 0;
4168 pSMB
->DataOffset
= 0;
4169 pSMB
->SetupCount
= 1;
4170 pSMB
->Reserved3
= 0;
4171 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4172 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4173 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4174 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4176 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4177 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4179 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4180 } else { /* decode response */
4181 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4183 if (rc
|| (pSMBr
->ByteCount
< 24))
4184 rc
= -EIO
; /* bad smb */
4186 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4190 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4193 le32_to_cpu(response_data
->BytesPerSector
) *
4194 le32_to_cpu(response_data
->
4195 SectorsPerAllocationUnit
);
4197 le64_to_cpu(response_data
->TotalAllocationUnits
);
4198 FSData
->f_bfree
= FSData
->f_bavail
=
4199 le64_to_cpu(response_data
->FreeAllocationUnits
);
4201 ("Blocks: %lld Free: %lld Block size %ld",
4202 (unsigned long long)FSData
->f_blocks
,
4203 (unsigned long long)FSData
->f_bfree
,
4207 cifs_buf_release(pSMB
);
4216 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4218 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4219 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4220 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4221 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4223 int bytes_returned
= 0;
4224 __u16 params
, byte_count
;
4226 cFYI(1, ("In QFSAttributeInfo"));
4228 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4233 params
= 2; /* level */
4234 pSMB
->TotalDataCount
= 0;
4235 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4236 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4237 pSMB
->MaxSetupCount
= 0;
4241 pSMB
->Reserved2
= 0;
4242 byte_count
= params
+ 1 /* pad */ ;
4243 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4244 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4245 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4246 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4247 pSMB
->DataCount
= 0;
4248 pSMB
->DataOffset
= 0;
4249 pSMB
->SetupCount
= 1;
4250 pSMB
->Reserved3
= 0;
4251 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4252 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4253 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4254 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4256 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4257 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4259 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4260 } else { /* decode response */
4261 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4263 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4264 /* BB also check if enough bytes returned */
4265 rc
= -EIO
; /* bad smb */
4267 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4269 (FILE_SYSTEM_ATTRIBUTE_INFO
4270 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4272 memcpy(&tcon
->fsAttrInfo
, response_data
,
4273 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4276 cifs_buf_release(pSMB
);
4279 goto QFSAttributeRetry
;
4285 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4287 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4288 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4289 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4290 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4292 int bytes_returned
= 0;
4293 __u16 params
, byte_count
;
4295 cFYI(1, ("In QFSDeviceInfo"));
4297 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4302 params
= 2; /* level */
4303 pSMB
->TotalDataCount
= 0;
4304 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4305 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4306 pSMB
->MaxSetupCount
= 0;
4310 pSMB
->Reserved2
= 0;
4311 byte_count
= params
+ 1 /* pad */ ;
4312 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4313 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4314 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4315 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4317 pSMB
->DataCount
= 0;
4318 pSMB
->DataOffset
= 0;
4319 pSMB
->SetupCount
= 1;
4320 pSMB
->Reserved3
= 0;
4321 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4322 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4323 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4324 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4326 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4327 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4329 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4330 } else { /* decode response */
4331 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4333 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4334 rc
= -EIO
; /* bad smb */
4336 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4338 (FILE_SYSTEM_DEVICE_INFO
*)
4339 (((char *) &pSMBr
->hdr
.Protocol
) +
4341 memcpy(&tcon
->fsDevInfo
, response_data
,
4342 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4345 cifs_buf_release(pSMB
);
4348 goto QFSDeviceRetry
;
4354 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4356 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4357 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4358 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4359 FILE_SYSTEM_UNIX_INFO
*response_data
;
4361 int bytes_returned
= 0;
4362 __u16 params
, byte_count
;
4364 cFYI(1, ("In QFSUnixInfo"));
4366 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4371 params
= 2; /* level */
4372 pSMB
->TotalDataCount
= 0;
4373 pSMB
->DataCount
= 0;
4374 pSMB
->DataOffset
= 0;
4375 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4376 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4377 pSMB
->MaxSetupCount
= 0;
4381 pSMB
->Reserved2
= 0;
4382 byte_count
= params
+ 1 /* pad */ ;
4383 pSMB
->ParameterCount
= cpu_to_le16(params
);
4384 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4385 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4386 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4387 pSMB
->SetupCount
= 1;
4388 pSMB
->Reserved3
= 0;
4389 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4390 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4391 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4392 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4394 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4395 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4397 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4398 } else { /* decode response */
4399 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4401 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4402 rc
= -EIO
; /* bad smb */
4404 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4406 (FILE_SYSTEM_UNIX_INFO
4407 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4409 memcpy(&tcon
->fsUnixInfo
, response_data
,
4410 sizeof(FILE_SYSTEM_UNIX_INFO
));
4413 cifs_buf_release(pSMB
);
4423 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4425 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4426 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4427 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4429 int bytes_returned
= 0;
4430 __u16 params
, param_offset
, offset
, byte_count
;
4432 cFYI(1, ("In SETFSUnixInfo"));
4434 /* BB switch to small buf init to save memory */
4435 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4440 params
= 4; /* 2 bytes zero followed by info level. */
4441 pSMB
->MaxSetupCount
= 0;
4445 pSMB
->Reserved2
= 0;
4446 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4448 offset
= param_offset
+ params
;
4450 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4451 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4452 pSMB
->SetupCount
= 1;
4453 pSMB
->Reserved3
= 0;
4454 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4455 byte_count
= 1 /* pad */ + params
+ 12;
4457 pSMB
->DataCount
= cpu_to_le16(12);
4458 pSMB
->ParameterCount
= cpu_to_le16(params
);
4459 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4460 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4461 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4462 pSMB
->DataOffset
= cpu_to_le16(offset
);
4466 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4469 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4470 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4471 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4473 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4474 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4476 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4477 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4479 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4480 } else { /* decode response */
4481 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4483 rc
= -EIO
; /* bad smb */
4485 cifs_buf_release(pSMB
);
4488 goto SETFSUnixRetry
;
4496 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4497 struct kstatfs
*FSData
)
4499 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4500 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4501 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4502 FILE_SYSTEM_POSIX_INFO
*response_data
;
4504 int bytes_returned
= 0;
4505 __u16 params
, byte_count
;
4507 cFYI(1, ("In QFSPosixInfo"));
4509 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4514 params
= 2; /* level */
4515 pSMB
->TotalDataCount
= 0;
4516 pSMB
->DataCount
= 0;
4517 pSMB
->DataOffset
= 0;
4518 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4519 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4520 pSMB
->MaxSetupCount
= 0;
4524 pSMB
->Reserved2
= 0;
4525 byte_count
= params
+ 1 /* pad */ ;
4526 pSMB
->ParameterCount
= cpu_to_le16(params
);
4527 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4528 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4529 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4530 pSMB
->SetupCount
= 1;
4531 pSMB
->Reserved3
= 0;
4532 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4533 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4534 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4535 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4537 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4538 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4540 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4541 } else { /* decode response */
4542 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4544 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4545 rc
= -EIO
; /* bad smb */
4547 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4549 (FILE_SYSTEM_POSIX_INFO
4550 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4553 le32_to_cpu(response_data
->BlockSize
);
4555 le64_to_cpu(response_data
->TotalBlocks
);
4557 le64_to_cpu(response_data
->BlocksAvail
);
4558 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4559 FSData
->f_bavail
= FSData
->f_bfree
;
4562 le64_to_cpu(response_data
->UserBlocksAvail
);
4564 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4566 le64_to_cpu(response_data
->TotalFileNodes
);
4567 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4569 le64_to_cpu(response_data
->FreeFileNodes
);
4572 cifs_buf_release(pSMB
);
4581 /* We can not use write of zero bytes trick to
4582 set file size due to need for large file support. Also note that
4583 this SetPathInfo is preferred to SetFileInfo based method in next
4584 routine which is only needed to work around a sharing violation bug
4585 in Samba which this routine can run into */
4588 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4589 __u64 size
, int SetAllocation
,
4590 const struct nls_table
*nls_codepage
, int remap
)
4592 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4593 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4594 struct file_end_of_file_info
*parm_data
;
4597 int bytes_returned
= 0;
4598 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4600 cFYI(1, ("In SetEOF"));
4602 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4607 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4609 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4610 PATH_MAX
, nls_codepage
, remap
);
4611 name_len
++; /* trailing null */
4613 } else { /* BB improve the check for buffer overruns BB */
4614 name_len
= strnlen(fileName
, PATH_MAX
);
4615 name_len
++; /* trailing null */
4616 strncpy(pSMB
->FileName
, fileName
, name_len
);
4618 params
= 6 + name_len
;
4619 data_count
= sizeof(struct file_end_of_file_info
);
4620 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4621 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4622 pSMB
->MaxSetupCount
= 0;
4626 pSMB
->Reserved2
= 0;
4627 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4628 InformationLevel
) - 4;
4629 offset
= param_offset
+ params
;
4630 if (SetAllocation
) {
4631 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4632 pSMB
->InformationLevel
=
4633 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4635 pSMB
->InformationLevel
=
4636 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4637 } else /* Set File Size */ {
4638 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4639 pSMB
->InformationLevel
=
4640 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4642 pSMB
->InformationLevel
=
4643 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4647 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4649 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4650 pSMB
->DataOffset
= cpu_to_le16(offset
);
4651 pSMB
->SetupCount
= 1;
4652 pSMB
->Reserved3
= 0;
4653 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4654 byte_count
= 3 /* pad */ + params
+ data_count
;
4655 pSMB
->DataCount
= cpu_to_le16(data_count
);
4656 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4657 pSMB
->ParameterCount
= cpu_to_le16(params
);
4658 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4659 pSMB
->Reserved4
= 0;
4660 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4661 parm_data
->FileSize
= cpu_to_le64(size
);
4662 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4663 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4664 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4666 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4668 cifs_buf_release(pSMB
);
4677 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4678 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
4680 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4682 struct file_end_of_file_info
*parm_data
;
4684 __u16 params
, param_offset
, offset
, byte_count
, count
;
4686 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4688 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4693 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4694 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4697 pSMB
->MaxSetupCount
= 0;
4701 pSMB
->Reserved2
= 0;
4702 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4703 offset
= param_offset
+ params
;
4705 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4707 count
= sizeof(struct file_end_of_file_info
);
4708 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4709 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4710 pSMB
->SetupCount
= 1;
4711 pSMB
->Reserved3
= 0;
4712 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4713 byte_count
= 3 /* pad */ + params
+ count
;
4714 pSMB
->DataCount
= cpu_to_le16(count
);
4715 pSMB
->ParameterCount
= cpu_to_le16(params
);
4716 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4717 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4718 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4720 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4722 pSMB
->DataOffset
= cpu_to_le16(offset
);
4723 parm_data
->FileSize
= cpu_to_le64(size
);
4725 if (SetAllocation
) {
4726 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4727 pSMB
->InformationLevel
=
4728 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4730 pSMB
->InformationLevel
=
4731 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4732 } else /* Set File Size */ {
4733 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4734 pSMB
->InformationLevel
=
4735 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4737 pSMB
->InformationLevel
=
4738 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4740 pSMB
->Reserved4
= 0;
4741 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4742 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4743 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4746 ("Send error in SetFileInfo (SetFileSize) = %d",
4750 /* Note: On -EAGAIN error only caller can retry on handle based calls
4751 since file handle passed in no longer valid */
4756 /* Some legacy servers such as NT4 require that the file times be set on
4757 an open handle, rather than by pathname - this is awkward due to
4758 potential access conflicts on the open, but it is unavoidable for these
4759 old servers since the only other choice is to go from 100 nanosecond DCE
4760 time and resort to the original setpathinfo level which takes the ancient
4761 DOS time format with 2 second granularity */
4763 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
,
4764 const FILE_BASIC_INFO
*data
, __u16 fid
)
4766 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4769 __u16 params
, param_offset
, offset
, byte_count
, count
;
4771 cFYI(1, ("Set Times (via SetFileInfo)"));
4772 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4777 /* At this point there is no need to override the current pid
4778 with the pid of the opener, but that could change if we someday
4779 use an existing handle (rather than opening one on the fly) */
4780 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4781 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4784 pSMB
->MaxSetupCount
= 0;
4788 pSMB
->Reserved2
= 0;
4789 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4790 offset
= param_offset
+ params
;
4792 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4794 count
= sizeof(FILE_BASIC_INFO
);
4795 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4796 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4797 pSMB
->SetupCount
= 1;
4798 pSMB
->Reserved3
= 0;
4799 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4800 byte_count
= 3 /* pad */ + params
+ count
;
4801 pSMB
->DataCount
= cpu_to_le16(count
);
4802 pSMB
->ParameterCount
= cpu_to_le16(params
);
4803 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4804 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4805 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4806 pSMB
->DataOffset
= cpu_to_le16(offset
);
4808 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4809 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4811 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4812 pSMB
->Reserved4
= 0;
4813 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4814 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4815 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4816 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4818 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4820 /* Note: On -EAGAIN error only caller can retry on handle based calls
4821 since file handle passed in no longer valid */
4828 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4829 const FILE_BASIC_INFO
*data
,
4830 const struct nls_table
*nls_codepage
, int remap
)
4832 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4833 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4836 int bytes_returned
= 0;
4838 __u16 params
, param_offset
, offset
, byte_count
, count
;
4840 cFYI(1, ("In SetTimes"));
4843 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4848 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4850 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4851 PATH_MAX
, nls_codepage
, remap
);
4852 name_len
++; /* trailing null */
4854 } else { /* BB improve the check for buffer overruns BB */
4855 name_len
= strnlen(fileName
, PATH_MAX
);
4856 name_len
++; /* trailing null */
4857 strncpy(pSMB
->FileName
, fileName
, name_len
);
4860 params
= 6 + name_len
;
4861 count
= sizeof(FILE_BASIC_INFO
);
4862 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4863 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4864 pSMB
->MaxSetupCount
= 0;
4868 pSMB
->Reserved2
= 0;
4869 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4870 InformationLevel
) - 4;
4871 offset
= param_offset
+ params
;
4872 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4873 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4874 pSMB
->DataOffset
= cpu_to_le16(offset
);
4875 pSMB
->SetupCount
= 1;
4876 pSMB
->Reserved3
= 0;
4877 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4878 byte_count
= 3 /* pad */ + params
+ count
;
4880 pSMB
->DataCount
= cpu_to_le16(count
);
4881 pSMB
->ParameterCount
= cpu_to_le16(params
);
4882 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4883 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4884 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4885 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4887 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4888 pSMB
->Reserved4
= 0;
4889 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4890 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4891 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4892 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4893 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4895 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4897 cifs_buf_release(pSMB
);
4905 /* Can not be used to set time stamps yet (due to old DOS time format) */
4906 /* Can be used to set attributes */
4907 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4908 handling it anyway and NT4 was what we thought it would be needed for
4909 Do not delete it until we prove whether needed for Win9x though */
4911 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4912 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4914 SETATTR_REQ
*pSMB
= NULL
;
4915 SETATTR_RSP
*pSMBr
= NULL
;
4920 cFYI(1, ("In SetAttrLegacy"));
4923 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4928 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4930 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4931 PATH_MAX
, nls_codepage
);
4932 name_len
++; /* trailing null */
4934 } else { /* BB improve the check for buffer overruns BB */
4935 name_len
= strnlen(fileName
, PATH_MAX
);
4936 name_len
++; /* trailing null */
4937 strncpy(pSMB
->fileName
, fileName
, name_len
);
4939 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4940 pSMB
->BufferFormat
= 0x04;
4941 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4942 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4943 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4944 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4946 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4948 cifs_buf_release(pSMB
);
4951 goto SetAttrLgcyRetry
;
4955 #endif /* temporarily unneeded SetAttr legacy function */
4958 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4959 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4960 dev_t device
, const struct nls_table
*nls_codepage
,
4963 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4964 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4967 int bytes_returned
= 0;
4968 FILE_UNIX_BASIC_INFO
*data_offset
;
4969 __u16 params
, param_offset
, offset
, count
, byte_count
;
4971 cFYI(1, ("In SetUID/GID/Mode"));
4973 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4978 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4980 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4981 PATH_MAX
, nls_codepage
, remap
);
4982 name_len
++; /* trailing null */
4984 } else { /* BB improve the check for buffer overruns BB */
4985 name_len
= strnlen(fileName
, PATH_MAX
);
4986 name_len
++; /* trailing null */
4987 strncpy(pSMB
->FileName
, fileName
, name_len
);
4990 params
= 6 + name_len
;
4991 count
= sizeof(FILE_UNIX_BASIC_INFO
);
4992 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4993 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4994 pSMB
->MaxSetupCount
= 0;
4998 pSMB
->Reserved2
= 0;
4999 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5000 InformationLevel
) - 4;
5001 offset
= param_offset
+ params
;
5003 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5005 memset(data_offset
, 0, count
);
5006 pSMB
->DataOffset
= cpu_to_le16(offset
);
5007 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5008 pSMB
->SetupCount
= 1;
5009 pSMB
->Reserved3
= 0;
5010 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5011 byte_count
= 3 /* pad */ + params
+ count
;
5012 pSMB
->ParameterCount
= cpu_to_le16(params
);
5013 pSMB
->DataCount
= cpu_to_le16(count
);
5014 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5015 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5016 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5017 pSMB
->Reserved4
= 0;
5018 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5019 /* Samba server ignores set of file size to zero due to bugs in some
5020 older clients, but we should be precise - we use SetFileSize to
5021 set file size and do not want to truncate file size to zero
5022 accidently as happened on one Samba server beta by putting
5023 zero instead of -1 here */
5024 data_offset
->EndOfFile
= NO_CHANGE_64
;
5025 data_offset
->NumOfBytes
= NO_CHANGE_64
;
5026 data_offset
->LastStatusChange
= NO_CHANGE_64
;
5027 data_offset
->LastAccessTime
= NO_CHANGE_64
;
5028 data_offset
->LastModificationTime
= NO_CHANGE_64
;
5029 data_offset
->Uid
= cpu_to_le64(uid
);
5030 data_offset
->Gid
= cpu_to_le64(gid
);
5031 /* better to leave device as zero when it is */
5032 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
5033 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
5034 data_offset
->Permissions
= cpu_to_le64(mode
);
5037 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5038 else if (S_ISDIR(mode
))
5039 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5040 else if (S_ISLNK(mode
))
5041 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5042 else if (S_ISCHR(mode
))
5043 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5044 else if (S_ISBLK(mode
))
5045 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5046 else if (S_ISFIFO(mode
))
5047 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5048 else if (S_ISSOCK(mode
))
5049 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5052 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5053 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5054 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5056 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5059 cifs_buf_release(pSMB
);
5065 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5066 const int notify_subdirs
, const __u16 netfid
,
5067 __u32 filter
, struct file
*pfile
, int multishot
,
5068 const struct nls_table
*nls_codepage
)
5071 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5072 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5073 struct dir_notify_req
*dnotify_req
;
5076 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5077 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5082 pSMB
->TotalParameterCount
= 0 ;
5083 pSMB
->TotalDataCount
= 0;
5084 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5085 /* BB find exact data count max from sess structure BB */
5086 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5087 /* BB VERIFY verify which is correct for above BB */
5088 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5089 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5091 pSMB
->MaxSetupCount
= 4;
5093 pSMB
->ParameterOffset
= 0;
5094 pSMB
->DataCount
= 0;
5095 pSMB
->DataOffset
= 0;
5096 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5097 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5098 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5100 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5101 pSMB
->Reserved2
= 0;
5102 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5103 pSMB
->Fid
= netfid
; /* file handle always le */
5104 pSMB
->ByteCount
= 0;
5106 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5107 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5110 cFYI(1, ("Error in Notify = %d", rc
));
5112 /* Add file to outstanding requests */
5113 /* BB change to kmem cache alloc */
5114 dnotify_req
= kmalloc(
5115 sizeof(struct dir_notify_req
),
5118 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5119 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5120 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5121 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5122 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5123 dnotify_req
->netfid
= netfid
;
5124 dnotify_req
->pfile
= pfile
;
5125 dnotify_req
->filter
= filter
;
5126 dnotify_req
->multishot
= multishot
;
5127 spin_lock(&GlobalMid_Lock
);
5128 list_add_tail(&dnotify_req
->lhead
,
5129 &GlobalDnotifyReqList
);
5130 spin_unlock(&GlobalMid_Lock
);
5134 cifs_buf_release(pSMB
);
5137 #ifdef CONFIG_CIFS_XATTR
5139 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5140 const unsigned char *searchName
,
5141 char *EAData
, size_t buf_size
,
5142 const struct nls_table
*nls_codepage
, int remap
)
5144 /* BB assumes one setup word */
5145 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5146 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5150 struct fea
*temp_fea
;
5152 __u16 params
, byte_count
;
5154 cFYI(1, ("In Query All EAs path %s", searchName
));
5156 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5161 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5163 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5164 PATH_MAX
, nls_codepage
, remap
);
5165 name_len
++; /* trailing null */
5167 } else { /* BB improve the check for buffer overruns BB */
5168 name_len
= strnlen(searchName
, PATH_MAX
);
5169 name_len
++; /* trailing null */
5170 strncpy(pSMB
->FileName
, searchName
, name_len
);
5173 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5174 pSMB
->TotalDataCount
= 0;
5175 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5176 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5177 pSMB
->MaxSetupCount
= 0;
5181 pSMB
->Reserved2
= 0;
5182 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5183 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5184 pSMB
->DataCount
= 0;
5185 pSMB
->DataOffset
= 0;
5186 pSMB
->SetupCount
= 1;
5187 pSMB
->Reserved3
= 0;
5188 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5189 byte_count
= params
+ 1 /* pad */ ;
5190 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5191 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5192 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5193 pSMB
->Reserved4
= 0;
5194 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5195 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5197 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5198 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5200 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5201 } else { /* decode response */
5202 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5204 /* BB also check enough total bytes returned */
5205 /* BB we need to improve the validity checking
5206 of these trans2 responses */
5207 if (rc
|| (pSMBr
->ByteCount
< 4))
5208 rc
= -EIO
; /* bad smb */
5209 /* else if (pFindData){
5210 memcpy((char *) pFindData,
5211 (char *) &pSMBr->hdr.Protocol +
5214 /* check that length of list is not more than bcc */
5215 /* check that each entry does not go beyond length
5217 /* check that each element of each entry does not
5218 go beyond end of list */
5219 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5220 struct fealist
*ea_response_data
;
5222 /* validate_trans2_offsets() */
5223 /* BB check if start of smb + data_offset > &bcc+ bcc */
5224 ea_response_data
= (struct fealist
*)
5225 (((char *) &pSMBr
->hdr
.Protocol
) +
5227 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5228 cFYI(1, ("ea length %d", name_len
));
5229 if (name_len
<= 8) {
5230 /* returned EA size zeroed at top of function */
5231 cFYI(1, ("empty EA list returned from server"));
5233 /* account for ea list len */
5235 temp_fea
= ea_response_data
->list
;
5236 temp_ptr
= (char *)temp_fea
;
5237 while (name_len
> 0) {
5241 rc
+= temp_fea
->name_len
;
5242 /* account for prefix user. and trailing null */
5244 if (rc
< (int)buf_size
) {
5245 memcpy(EAData
, "user.", 5);
5247 memcpy(EAData
, temp_ptr
,
5248 temp_fea
->name_len
);
5249 EAData
+= temp_fea
->name_len
;
5250 /* null terminate name */
5252 EAData
= EAData
+ 1;
5253 } else if (buf_size
== 0) {
5254 /* skip copy - calc size only */
5256 /* stop before overrun buffer */
5260 name_len
-= temp_fea
->name_len
;
5261 temp_ptr
+= temp_fea
->name_len
;
5262 /* account for trailing null */
5266 le16_to_cpu(temp_fea
->value_len
);
5267 name_len
-= value_len
;
5268 temp_ptr
+= value_len
;
5269 /* BB check that temp_ptr is still
5272 /* no trailing null to account for
5274 /* go on to next EA */
5275 temp_fea
= (struct fea
*)temp_ptr
;
5281 cifs_buf_release(pSMB
);
5288 ssize_t
CIFSSMBQueryEA(const int xid
, struct cifsTconInfo
*tcon
,
5289 const unsigned char *searchName
, const unsigned char *ea_name
,
5290 unsigned char *ea_value
, size_t buf_size
,
5291 const struct nls_table
*nls_codepage
, int remap
)
5293 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5294 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5298 struct fea
*temp_fea
;
5300 __u16 params
, byte_count
;
5302 cFYI(1, ("In Query EA path %s", searchName
));
5304 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5309 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5311 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5312 PATH_MAX
, nls_codepage
, remap
);
5313 name_len
++; /* trailing null */
5315 } else { /* BB improve the check for buffer overruns BB */
5316 name_len
= strnlen(searchName
, PATH_MAX
);
5317 name_len
++; /* trailing null */
5318 strncpy(pSMB
->FileName
, searchName
, name_len
);
5321 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5322 pSMB
->TotalDataCount
= 0;
5323 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5324 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5325 pSMB
->MaxSetupCount
= 0;
5329 pSMB
->Reserved2
= 0;
5330 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5331 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5332 pSMB
->DataCount
= 0;
5333 pSMB
->DataOffset
= 0;
5334 pSMB
->SetupCount
= 1;
5335 pSMB
->Reserved3
= 0;
5336 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5337 byte_count
= params
+ 1 /* pad */ ;
5338 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5339 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5340 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5341 pSMB
->Reserved4
= 0;
5342 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5343 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5345 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5346 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5348 cFYI(1, ("Send error in Query EA = %d", rc
));
5349 } else { /* decode response */
5350 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5352 /* BB also check enough total bytes returned */
5353 /* BB we need to improve the validity checking
5354 of these trans2 responses */
5355 if (rc
|| (pSMBr
->ByteCount
< 4))
5356 rc
= -EIO
; /* bad smb */
5357 /* else if (pFindData){
5358 memcpy((char *) pFindData,
5359 (char *) &pSMBr->hdr.Protocol +
5362 /* check that length of list is not more than bcc */
5363 /* check that each entry does not go beyond length
5365 /* check that each element of each entry does not
5366 go beyond end of list */
5367 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5368 struct fealist
*ea_response_data
;
5370 /* validate_trans2_offsets() */
5371 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5372 ea_response_data
= (struct fealist
*)
5373 (((char *) &pSMBr
->hdr
.Protocol
) +
5375 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5376 cFYI(1, ("ea length %d", name_len
));
5377 if (name_len
<= 8) {
5378 /* returned EA size zeroed at top of function */
5379 cFYI(1, ("empty EA list returned from server"));
5381 /* account for ea list len */
5383 temp_fea
= ea_response_data
->list
;
5384 temp_ptr
= (char *)temp_fea
;
5385 /* loop through checking if we have a matching
5386 name and then return the associated value */
5387 while (name_len
> 0) {
5392 le16_to_cpu(temp_fea
->value_len
);
5393 /* BB validate that value_len falls within SMB,
5394 even though maximum for name_len is 255 */
5395 if (memcmp(temp_fea
->name
, ea_name
,
5396 temp_fea
->name_len
) == 0) {
5399 /* account for prefix user. and trailing null */
5400 if (rc
<= (int)buf_size
) {
5402 temp_fea
->name
+temp_fea
->name_len
+1,
5404 /* ea values, unlike ea
5407 } else if (buf_size
== 0) {
5408 /* skip copy - calc size only */
5410 /* stop before overrun buffer */
5415 name_len
-= temp_fea
->name_len
;
5416 temp_ptr
+= temp_fea
->name_len
;
5417 /* account for trailing null */
5420 name_len
-= value_len
;
5421 temp_ptr
+= value_len
;
5422 /* No trailing null to account for in
5423 value_len. Go on to next EA */
5424 temp_fea
= (struct fea
*)temp_ptr
;
5430 cifs_buf_release(pSMB
);
5438 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5439 const char *ea_name
, const void *ea_value
,
5440 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5443 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5444 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5445 struct fealist
*parm_data
;
5448 int bytes_returned
= 0;
5449 __u16 params
, param_offset
, byte_count
, offset
, count
;
5451 cFYI(1, ("In SetEA"));
5453 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5458 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5460 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5461 PATH_MAX
, nls_codepage
, remap
);
5462 name_len
++; /* trailing null */
5464 } else { /* BB improve the check for buffer overruns BB */
5465 name_len
= strnlen(fileName
, PATH_MAX
);
5466 name_len
++; /* trailing null */
5467 strncpy(pSMB
->FileName
, fileName
, name_len
);
5470 params
= 6 + name_len
;
5472 /* done calculating parms using name_len of file name,
5473 now use name_len to calculate length of ea name
5474 we are going to create in the inode xattrs */
5475 if (ea_name
== NULL
)
5478 name_len
= strnlen(ea_name
, 255);
5480 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5481 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5482 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
5483 pSMB
->MaxSetupCount
= 0;
5487 pSMB
->Reserved2
= 0;
5488 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5489 InformationLevel
) - 4;
5490 offset
= param_offset
+ params
;
5491 pSMB
->InformationLevel
=
5492 cpu_to_le16(SMB_SET_FILE_EA
);
5495 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5497 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5498 pSMB
->DataOffset
= cpu_to_le16(offset
);
5499 pSMB
->SetupCount
= 1;
5500 pSMB
->Reserved3
= 0;
5501 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5502 byte_count
= 3 /* pad */ + params
+ count
;
5503 pSMB
->DataCount
= cpu_to_le16(count
);
5504 parm_data
->list_len
= cpu_to_le32(count
);
5505 parm_data
->list
[0].EA_flags
= 0;
5506 /* we checked above that name len is less than 255 */
5507 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5508 /* EA names are always ASCII */
5510 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5511 parm_data
->list
[0].name
[name_len
] = 0;
5512 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5513 /* caller ensures that ea_value_len is less than 64K but
5514 we need to ensure that it fits within the smb */
5516 /*BB add length check to see if it would fit in
5517 negotiated SMB buffer size BB */
5518 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5520 memcpy(parm_data
->list
[0].name
+name_len
+1,
5521 ea_value
, ea_value_len
);
5523 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5524 pSMB
->ParameterCount
= cpu_to_le16(params
);
5525 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5526 pSMB
->Reserved4
= 0;
5527 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5528 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5529 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5530 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5532 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5534 cifs_buf_release(pSMB
);