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 /* tell server which Unix caps we support */
169 if (tcon
->ses
->capabilities
& CAP_UNIX
)
170 reset_cifs_unix_caps(0 /* no xid */,
172 NULL
/* we do not know sb */,
173 NULL
/* no vol info */);
174 /* BB FIXME add code to check if wsize needs
175 update due to negotiated smb buffer size
178 atomic_inc(&tconInfoReconnectCount
);
180 cFYI(1, ("reconnect tcon rc = %d", rc
));
181 /* Removed call to reopen open files here.
182 It is safer (and faster) to reopen files
183 one at a time as needed in read and write */
185 /* Check if handle based operation so we
186 know whether we can continue or not without
187 returning to caller to reset file handle */
188 switch (smb_command
) {
189 case SMB_COM_READ_ANDX
:
190 case SMB_COM_WRITE_ANDX
:
192 case SMB_COM_FIND_CLOSE2
:
193 case SMB_COM_LOCKING_ANDX
: {
194 unload_nls(nls_codepage
);
199 up(&tcon
->ses
->sesSem
);
201 unload_nls(nls_codepage
);
210 *request_buf
= cifs_small_buf_get();
211 if (*request_buf
== NULL
) {
212 /* BB should we add a retry in here if not a writepage? */
216 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
220 cifs_stats_inc(&tcon
->num_smbs_sent
);
226 small_smb_init_no_tc(const int smb_command
, const int wct
,
227 struct cifsSesInfo
*ses
, void **request_buf
)
230 struct smb_hdr
*buffer
;
232 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
236 buffer
= (struct smb_hdr
*)*request_buf
;
237 buffer
->Mid
= GetNextMid(ses
->server
);
238 if (ses
->capabilities
& CAP_UNICODE
)
239 buffer
->Flags2
|= SMBFLG2_UNICODE
;
240 if (ses
->capabilities
& CAP_STATUS32
)
241 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
243 /* uid, tid can stay at zero as set in header assemble */
245 /* BB add support for turning on the signing when
246 this function is used after 1st of session setup requests */
251 /* If the return code is zero, this function must fill in request_buf pointer */
253 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
254 void **request_buf
/* returned */ ,
255 void **response_buf
/* returned */ )
259 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
260 check for tcp and smb session status done differently
261 for those three - in the calling routine */
263 if (tcon
->tidStatus
== CifsExiting
) {
264 /* only tree disconnect, open, and write,
265 (and ulogoff which does not have tcon)
266 are allowed as we start force umount */
267 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
268 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
269 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
270 cFYI(1, ("can not send cmd %d while umounting",
276 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
277 (tcon
->ses
->server
)) {
278 struct nls_table
*nls_codepage
;
279 /* Give Demultiplex thread up to 10 seconds to
280 reconnect, should be greater than cifs socket
281 timeout which is 7 seconds */
282 while (tcon
->ses
->server
->tcpStatus
==
284 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
285 (tcon
->ses
->server
->tcpStatus
==
287 if (tcon
->ses
->server
->tcpStatus
==
289 /* on "soft" mounts we wait once */
290 if ((tcon
->retry
== FALSE
) ||
291 (tcon
->ses
->status
== CifsExiting
)) {
292 cFYI(1, ("gave up waiting on "
293 "reconnect in smb_init"));
295 } /* else "hard" mount - keep retrying
296 until process is killed or server
298 } else /* TCP session is reestablished now */
301 nls_codepage
= load_nls_default();
302 /* need to prevent multiple threads trying to
303 simultaneously reconnect the same SMB session */
304 down(&tcon
->ses
->sesSem
);
305 if (tcon
->ses
->status
== CifsNeedReconnect
)
306 rc
= cifs_setup_session(0, tcon
->ses
,
308 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
309 mark_open_files_invalid(tcon
);
310 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
312 up(&tcon
->ses
->sesSem
);
313 /* tell server which Unix caps we support */
314 if (tcon
->ses
->capabilities
& CAP_UNIX
)
315 reset_cifs_unix_caps(0 /* no xid */,
317 NULL
/* do not know sb */,
318 NULL
/* no vol info */);
319 /* BB FIXME add code to check if wsize needs
320 update due to negotiated smb buffer size
323 atomic_inc(&tconInfoReconnectCount
);
325 cFYI(1, ("reconnect tcon rc = %d", rc
));
326 /* Removed call to reopen open files here.
327 It is safer (and faster) to reopen files
328 one at a time as needed in read and write */
330 /* Check if handle based operation so we
331 know whether we can continue or not without
332 returning to caller to reset file handle */
333 switch (smb_command
) {
334 case SMB_COM_READ_ANDX
:
335 case SMB_COM_WRITE_ANDX
:
337 case SMB_COM_FIND_CLOSE2
:
338 case SMB_COM_LOCKING_ANDX
: {
339 unload_nls(nls_codepage
);
344 up(&tcon
->ses
->sesSem
);
346 unload_nls(nls_codepage
);
355 *request_buf
= cifs_buf_get();
356 if (*request_buf
== NULL
) {
357 /* BB should we add a retry in here if not a writepage? */
360 /* Although the original thought was we needed the response buf for */
361 /* potential retries of smb operations it turns out we can determine */
362 /* from the mid flags when the request buffer can be resent without */
363 /* having to use a second distinct buffer for the response */
365 *response_buf
= *request_buf
;
367 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
371 cifs_stats_inc(&tcon
->num_smbs_sent
);
376 static int validate_t2(struct smb_t2_rsp
*pSMB
)
382 /* check for plausible wct, bcc and t2 data and parm sizes */
383 /* check for parm and data offset going beyond end of smb */
384 if (pSMB
->hdr
.WordCount
>= 10) {
385 if ((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
386 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
387 /* check that bcc is at least as big as parms + data */
388 /* check that bcc is less than negotiated smb buffer */
389 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
390 if (total_size
< 512) {
392 le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
393 /* BCC le converted in SendReceive */
394 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
395 sizeof(struct smb_hdr
) +
397 if ((total_size
<= (*(u16
*)pBCC
)) &&
399 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
405 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
406 sizeof(struct smb_t2_rsp
) + 16);
410 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
413 NEGOTIATE_RSP
*pSMBr
;
417 struct TCP_Server_Info
*server
;
419 unsigned int secFlags
;
423 server
= ses
->server
;
428 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
429 (void **) &pSMB
, (void **) &pSMBr
);
433 /* if any of auth flags (ie not sign or seal) are overriden use them */
434 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
435 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
436 else /* if override flags set only sign/seal OR them with global auth */
437 secFlags
= extended_security
| ses
->overrideSecFlg
;
439 cFYI(1, ("secFlags 0x%x", secFlags
));
441 pSMB
->hdr
.Mid
= GetNextMid(server
);
442 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
444 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
445 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
446 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
447 cFYI(1, ("Kerberos only mechanism, enable extended security"));
448 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
452 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
453 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
454 count
+= strlen(protocols
[i
].name
) + 1;
455 /* null at end of source and target buffers anyway */
457 pSMB
->hdr
.smb_buf_length
+= count
;
458 pSMB
->ByteCount
= cpu_to_le16(count
);
460 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
461 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
465 dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
466 cFYI(1, ("Dialect: %d", dialect
));
467 /* Check wct = 1 error case */
468 if ((pSMBr
->hdr
.WordCount
< 13) || (dialect
== BAD_PROT
)) {
469 /* core returns wct = 1, but we do not ask for core - otherwise
470 small wct just comes when dialect index is -1 indicating we
471 could not negotiate a common dialect */
474 #ifdef CONFIG_CIFS_WEAK_PW_HASH
475 } else if ((pSMBr
->hdr
.WordCount
== 13)
476 && ((dialect
== LANMAN_PROT
)
477 || (dialect
== LANMAN2_PROT
))) {
479 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
481 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
482 (secFlags
& CIFSSEC_MAY_PLNTXT
))
483 server
->secType
= LANMAN
;
485 cERROR(1, ("mount failed weak security disabled"
486 " in /proc/fs/cifs/SecurityFlags"));
490 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
491 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
492 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
493 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
494 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
495 /* even though we do not use raw we might as well set this
496 accurately, in case we ever find a need for it */
497 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
498 server
->maxRw
= 0xFF00;
499 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
501 server
->maxRw
= 0;/* we do not need to use raw anyway */
502 server
->capabilities
= CAP_MPX_MODE
;
504 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
506 /* OS/2 often does not set timezone therefore
507 * we must use server time to calc time zone.
508 * Could deviate slightly from the right zone.
509 * Smallest defined timezone difference is 15 minutes
510 * (i.e. Nepal). Rounding up/down is done to match
513 int val
, seconds
, remain
, result
;
514 struct timespec ts
, utc
;
516 ts
= cnvrtDosUnixTm(le16_to_cpu(rsp
->SrvTime
.Date
),
517 le16_to_cpu(rsp
->SrvTime
.Time
));
518 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
519 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
520 (int)(utc
.tv_sec
- ts
.tv_sec
)));
521 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
523 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
524 remain
= seconds
% MIN_TZ_ADJ
;
525 if (remain
>= (MIN_TZ_ADJ
/ 2))
526 result
+= MIN_TZ_ADJ
;
529 server
->timeAdj
= result
;
531 server
->timeAdj
= (int)tmp
;
532 server
->timeAdj
*= 60; /* also in seconds */
534 cFYI(1, ("server->timeAdj: %d seconds", server
->timeAdj
));
537 /* BB get server time for time conversions and add
538 code to use it and timezone since this is not UTC */
540 if (rsp
->EncryptionKeyLength
==
541 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
542 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
543 CIFS_CRYPTO_KEY_SIZE
);
544 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
545 rc
= -EIO
; /* need cryptkey unless plain text */
549 cFYI(1, ("LANMAN negotiated"));
550 /* we will not end up setting signing flags - as no signing
551 was in LANMAN and server did not return the flags on */
553 #else /* weak security disabled */
554 } else if (pSMBr
->hdr
.WordCount
== 13) {
555 cERROR(1, ("mount failed, cifs module not built "
556 "with CIFS_WEAK_PW_HASH support"));
558 #endif /* WEAK_PW_HASH */
560 } else if (pSMBr
->hdr
.WordCount
!= 17) {
565 /* else wct == 17 NTLM */
566 server
->secMode
= pSMBr
->SecurityMode
;
567 if ((server
->secMode
& SECMODE_USER
) == 0)
568 cFYI(1, ("share mode security"));
570 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
571 #ifdef CONFIG_CIFS_WEAK_PW_HASH
572 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
573 #endif /* CIFS_WEAK_PW_HASH */
574 cERROR(1, ("Server requests plain text password"
575 " but client support disabled"));
577 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
578 server
->secType
= NTLMv2
;
579 else if (secFlags
& CIFSSEC_MAY_NTLM
)
580 server
->secType
= NTLM
;
581 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
582 server
->secType
= NTLMv2
;
583 else if (secFlags
& CIFSSEC_MAY_KRB5
)
584 server
->secType
= Kerberos
;
585 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
586 server
->secType
= LANMAN
;
587 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
588 else if (secFlags & CIFSSEC_MAY_PLNTXT)
593 cERROR(1, ("Invalid security type"));
596 /* else ... any others ...? */
598 /* one byte, so no need to convert this or EncryptionKeyLen from
600 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
601 /* probably no need to store and check maxvcs */
602 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
603 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
604 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
605 cFYI(0, ("Max buf = %d", ses
->server
->maxBuf
));
606 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
607 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
608 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
609 server
->timeAdj
*= 60;
610 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
611 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
612 CIFS_CRYPTO_KEY_SIZE
);
613 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
614 && (pSMBr
->EncryptionKeyLength
== 0)) {
615 /* decode security blob */
616 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
617 rc
= -EIO
; /* no crypt key only if plain text pwd */
621 /* BB might be helpful to save off the domain of server here */
623 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
624 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
625 count
= pSMBr
->ByteCount
;
631 if (server
->socketUseCount
.counter
> 1) {
632 if (memcmp(server
->server_GUID
,
633 pSMBr
->u
.extended_response
.
635 cFYI(1, ("server UID changed"));
636 memcpy(server
->server_GUID
,
637 pSMBr
->u
.extended_response
.GUID
,
641 memcpy(server
->server_GUID
,
642 pSMBr
->u
.extended_response
.GUID
, 16);
645 server
->secType
= RawNTLMSSP
;
647 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
658 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
660 #ifdef CONFIG_CIFS_WEAK_PW_HASH
663 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
664 /* MUST_SIGN already includes the MAY_SIGN FLAG
665 so if this is zero it means that signing is disabled */
666 cFYI(1, ("Signing disabled"));
667 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
668 cERROR(1, ("Server requires "
669 "packet signing to be enabled in "
670 "/proc/fs/cifs/SecurityFlags."));
674 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
675 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
676 /* signing required */
677 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
678 if ((server
->secMode
&
679 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
681 ("signing required but server lacks support"));
684 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
686 /* signing optional ie CIFSSEC_MAY_SIGN */
687 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
689 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
693 cifs_buf_release(pSMB
);
695 cFYI(1, ("negprot rc %d", rc
));
700 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
702 struct smb_hdr
*smb_buffer
;
705 cFYI(1, ("In tree disconnect"));
707 * If last user of the connection and
708 * connection alive - disconnect it
709 * If this is the last connection on the server session disconnect it
710 * (and inside session disconnect we should check if tcp socket needs
711 * to be freed and kernel thread woken up).
714 down(&tcon
->tconSem
);
718 atomic_dec(&tcon
->useCount
);
719 if (atomic_read(&tcon
->useCount
) > 0) {
724 /* No need to return error on this operation if tid invalidated and
725 closed on server already e.g. due to tcp session crashing */
726 if (tcon
->tidStatus
== CifsNeedReconnect
) {
731 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
735 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
736 (void **)&smb_buffer
);
742 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
744 cFYI(1, ("Tree disconnect failed %d", rc
));
748 /* No need to return error on this operation if tid invalidated and
749 closed on server already e.g. due to tcp session crashing */
757 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
759 LOGOFF_ANDX_REQ
*pSMB
;
762 cFYI(1, ("In SMBLogoff for session disconnect"));
768 atomic_dec(&ses
->inUse
);
769 if (atomic_read(&ses
->inUse
) > 0) {
773 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
780 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
782 if (ses
->server
->secMode
&
783 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
784 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
787 pSMB
->hdr
.Uid
= ses
->Suid
;
789 pSMB
->AndXCommand
= 0xFF;
790 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
792 atomic_dec(&ses
->server
->socketUseCount
);
793 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
794 spin_lock(&GlobalMid_Lock
);
795 ses
->server
->tcpStatus
= CifsExiting
;
796 spin_unlock(&GlobalMid_Lock
);
802 /* if session dead then we do not need to do ulogoff,
803 since server closed smb session, no sense reporting
811 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
812 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
814 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
815 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
816 struct unlink_psx_rq
*pRqD
;
819 int bytes_returned
= 0;
820 __u16 params
, param_offset
, offset
, byte_count
;
822 cFYI(1, ("In POSIX delete"));
824 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
829 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
831 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
832 PATH_MAX
, nls_codepage
, remap
);
833 name_len
++; /* trailing null */
835 } else { /* BB add path length overrun check */
836 name_len
= strnlen(fileName
, PATH_MAX
);
837 name_len
++; /* trailing null */
838 strncpy(pSMB
->FileName
, fileName
, name_len
);
841 params
= 6 + name_len
;
842 pSMB
->MaxParameterCount
= cpu_to_le16(2);
843 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
844 pSMB
->MaxSetupCount
= 0;
849 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
850 InformationLevel
) - 4;
851 offset
= param_offset
+ params
;
853 /* Setup pointer to Request Data (inode type) */
854 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
855 pRqD
->type
= cpu_to_le16(type
);
856 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
857 pSMB
->DataOffset
= cpu_to_le16(offset
);
858 pSMB
->SetupCount
= 1;
860 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
861 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
863 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
864 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
865 pSMB
->ParameterCount
= cpu_to_le16(params
);
866 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
867 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
869 pSMB
->hdr
.smb_buf_length
+= byte_count
;
870 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
871 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
872 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
874 cFYI(1, ("Posix delete returned %d", rc
));
875 cifs_buf_release(pSMB
);
877 cifs_stats_inc(&tcon
->num_deletes
);
886 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
887 const struct nls_table
*nls_codepage
, int remap
)
889 DELETE_FILE_REQ
*pSMB
= NULL
;
890 DELETE_FILE_RSP
*pSMBr
= NULL
;
896 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
901 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
903 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
904 PATH_MAX
, nls_codepage
, remap
);
905 name_len
++; /* trailing null */
907 } else { /* BB improve check for buffer overruns BB */
908 name_len
= strnlen(fileName
, PATH_MAX
);
909 name_len
++; /* trailing null */
910 strncpy(pSMB
->fileName
, fileName
, name_len
);
912 pSMB
->SearchAttributes
=
913 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
914 pSMB
->BufferFormat
= 0x04;
915 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
916 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
917 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
918 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
919 cifs_stats_inc(&tcon
->num_deletes
);
921 cFYI(1, ("Error in RMFile = %d", rc
));
923 cifs_buf_release(pSMB
);
931 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
932 const struct nls_table
*nls_codepage
, int remap
)
934 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
935 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
940 cFYI(1, ("In CIFSSMBRmDir"));
942 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
947 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
948 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
949 PATH_MAX
, nls_codepage
, remap
);
950 name_len
++; /* trailing null */
952 } else { /* BB improve check for buffer overruns BB */
953 name_len
= strnlen(dirName
, PATH_MAX
);
954 name_len
++; /* trailing null */
955 strncpy(pSMB
->DirName
, dirName
, name_len
);
958 pSMB
->BufferFormat
= 0x04;
959 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
960 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
961 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
962 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
963 cifs_stats_inc(&tcon
->num_rmdirs
);
965 cFYI(1, ("Error in RMDir = %d", rc
));
967 cifs_buf_release(pSMB
);
974 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
975 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
978 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
979 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
983 cFYI(1, ("In CIFSSMBMkDir"));
985 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
990 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
991 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
992 PATH_MAX
, nls_codepage
, remap
);
993 name_len
++; /* trailing null */
995 } else { /* BB improve check for buffer overruns BB */
996 name_len
= strnlen(name
, PATH_MAX
);
997 name_len
++; /* trailing null */
998 strncpy(pSMB
->DirName
, name
, name_len
);
1001 pSMB
->BufferFormat
= 0x04;
1002 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
1003 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
1004 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1005 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1006 cifs_stats_inc(&tcon
->num_mkdirs
);
1008 cFYI(1, ("Error in Mkdir = %d", rc
));
1010 cifs_buf_release(pSMB
);
1017 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1018 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1019 __u32
*pOplock
, const char *name
,
1020 const struct nls_table
*nls_codepage
, int remap
)
1022 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1023 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1026 int bytes_returned
= 0;
1027 __u16 params
, param_offset
, offset
, byte_count
, count
;
1028 OPEN_PSX_REQ
*pdata
;
1029 OPEN_PSX_RSP
*psx_rsp
;
1031 cFYI(1, ("In POSIX Create"));
1033 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1038 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1040 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1041 PATH_MAX
, nls_codepage
, remap
);
1042 name_len
++; /* trailing null */
1044 } else { /* BB improve the check for buffer overruns BB */
1045 name_len
= strnlen(name
, PATH_MAX
);
1046 name_len
++; /* trailing null */
1047 strncpy(pSMB
->FileName
, name
, name_len
);
1050 params
= 6 + name_len
;
1051 count
= sizeof(OPEN_PSX_REQ
);
1052 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1053 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1054 pSMB
->MaxSetupCount
= 0;
1058 pSMB
->Reserved2
= 0;
1059 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1060 InformationLevel
) - 4;
1061 offset
= param_offset
+ params
;
1062 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1063 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1064 pdata
->Permissions
= cpu_to_le64(mode
);
1065 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1066 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1067 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1068 pSMB
->DataOffset
= cpu_to_le16(offset
);
1069 pSMB
->SetupCount
= 1;
1070 pSMB
->Reserved3
= 0;
1071 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1072 byte_count
= 3 /* pad */ + params
+ count
;
1074 pSMB
->DataCount
= cpu_to_le16(count
);
1075 pSMB
->ParameterCount
= cpu_to_le16(params
);
1076 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1077 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1078 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1079 pSMB
->Reserved4
= 0;
1080 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1081 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1082 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1083 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1085 cFYI(1, ("Posix create returned %d", rc
));
1086 goto psx_create_err
;
1089 cFYI(1, ("copying inode info"));
1090 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1092 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1093 rc
= -EIO
; /* bad smb */
1094 goto psx_create_err
;
1097 /* copy return information to pRetData */
1098 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1099 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1101 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1103 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1104 /* Let caller know file was created so we can set the mode. */
1105 /* Do we care about the CreateAction in any other cases? */
1106 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1107 *pOplock
|= CIFS_CREATE_ACTION
;
1108 /* check to make sure response data is there */
1109 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1110 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1111 #ifdef CONFIG_CIFS_DEBUG2
1112 cFYI(1, ("unknown type"));
1115 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1116 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1117 cERROR(1, ("Open response data too small"));
1118 pRetData
->Type
= cpu_to_le32(-1);
1119 goto psx_create_err
;
1121 memcpy((char *) pRetData
,
1122 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1123 sizeof(FILE_UNIX_BASIC_INFO
));
1127 cifs_buf_release(pSMB
);
1129 cifs_stats_inc(&tcon
->num_mkdirs
);
1137 static __u16
convert_disposition(int disposition
)
1141 switch (disposition
) {
1142 case FILE_SUPERSEDE
:
1143 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1146 ofun
= SMBOPEN_OAPPEND
;
1149 ofun
= SMBOPEN_OCREATE
;
1152 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1154 case FILE_OVERWRITE
:
1155 ofun
= SMBOPEN_OTRUNC
;
1157 case FILE_OVERWRITE_IF
:
1158 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1161 cFYI(1, ("unknown disposition %d", disposition
));
1162 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1168 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1169 const char *fileName
, const int openDisposition
,
1170 const int access_flags
, const int create_options
, __u16
*netfid
,
1171 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1172 const struct nls_table
*nls_codepage
, int remap
)
1175 OPENX_REQ
*pSMB
= NULL
;
1176 OPENX_RSP
*pSMBr
= NULL
;
1182 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1187 pSMB
->AndXCommand
= 0xFF; /* none */
1189 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1190 count
= 1; /* account for one byte pad to word boundary */
1192 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1193 fileName
, PATH_MAX
, nls_codepage
, remap
);
1194 name_len
++; /* trailing null */
1196 } else { /* BB improve check for buffer overruns BB */
1197 count
= 0; /* no pad */
1198 name_len
= strnlen(fileName
, PATH_MAX
);
1199 name_len
++; /* trailing null */
1200 strncpy(pSMB
->fileName
, fileName
, name_len
);
1202 if (*pOplock
& REQ_OPLOCK
)
1203 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1204 else if (*pOplock
& REQ_BATCHOPLOCK
)
1205 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1207 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1208 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1214 pSMB
->Mode
= cpu_to_le16(2);
1215 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1216 /* set file as system file if special file such
1217 as fifo and server expecting SFU style and
1218 no Unix extensions */
1220 if (create_options
& CREATE_OPTION_SPECIAL
)
1221 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1222 else /* BB FIXME BB */
1223 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1225 /* if ((omode & S_IWUGO) == 0)
1226 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1227 /* Above line causes problems due to vfs splitting create into two
1228 pieces - need to set mode after file created not while it is
1232 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1233 CREATE_OPTIONS_MASK); */
1234 /* BB FIXME END BB */
1236 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1237 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1239 pSMB
->hdr
.smb_buf_length
+= count
;
1241 pSMB
->ByteCount
= cpu_to_le16(count
);
1242 /* long_op set to 1 to allow for oplock break timeouts */
1243 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1244 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1245 cifs_stats_inc(&tcon
->num_opens
);
1247 cFYI(1, ("Error in Open = %d", rc
));
1249 /* BB verify if wct == 15 */
1251 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1253 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1254 /* Let caller know file was created so we can set the mode. */
1255 /* Do we care about the CreateAction in any other cases? */
1257 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1258 *pOplock |= CIFS_CREATE_ACTION; */
1262 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1263 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1264 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1265 pfile_info
->ChangeTime
= 0; /* BB fixme */
1266 pfile_info
->Attributes
=
1267 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1268 /* the file_info buf is endian converted by caller */
1269 pfile_info
->AllocationSize
=
1270 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1271 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1272 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1276 cifs_buf_release(pSMB
);
1283 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1284 const char *fileName
, const int openDisposition
,
1285 const int access_flags
, const int create_options
, __u16
*netfid
,
1286 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1287 const struct nls_table
*nls_codepage
, int remap
)
1290 OPEN_REQ
*pSMB
= NULL
;
1291 OPEN_RSP
*pSMBr
= NULL
;
1297 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1302 pSMB
->AndXCommand
= 0xFF; /* none */
1304 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1305 count
= 1; /* account for one byte pad to word boundary */
1307 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1308 fileName
, PATH_MAX
, nls_codepage
, remap
);
1309 name_len
++; /* trailing null */
1311 pSMB
->NameLength
= cpu_to_le16(name_len
);
1312 } else { /* BB improve check for buffer overruns BB */
1313 count
= 0; /* no pad */
1314 name_len
= strnlen(fileName
, PATH_MAX
);
1315 name_len
++; /* trailing null */
1316 pSMB
->NameLength
= cpu_to_le16(name_len
);
1317 strncpy(pSMB
->fileName
, fileName
, name_len
);
1319 if (*pOplock
& REQ_OPLOCK
)
1320 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1321 else if (*pOplock
& REQ_BATCHOPLOCK
)
1322 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1323 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1324 pSMB
->AllocationSize
= 0;
1325 /* set file as system file if special file such
1326 as fifo and server expecting SFU style and
1327 no Unix extensions */
1328 if (create_options
& CREATE_OPTION_SPECIAL
)
1329 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1331 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1332 /* XP does not handle ATTR_POSIX_SEMANTICS */
1333 /* but it helps speed up case sensitive checks for other
1334 servers such as Samba */
1335 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1336 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1338 /* if ((omode & S_IWUGO) == 0)
1339 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1340 /* Above line causes problems due to vfs splitting create into two
1341 pieces - need to set mode after file created not while it is
1343 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1344 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1345 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1346 /* BB Expirement with various impersonation levels and verify */
1347 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1348 pSMB
->SecurityFlags
=
1349 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1352 pSMB
->hdr
.smb_buf_length
+= count
;
1354 pSMB
->ByteCount
= cpu_to_le16(count
);
1355 /* long_op set to 1 to allow for oplock break timeouts */
1356 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1357 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1358 cifs_stats_inc(&tcon
->num_opens
);
1360 cFYI(1, ("Error in Open = %d", rc
));
1362 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1363 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1364 /* Let caller know file was created so we can set the mode. */
1365 /* Do we care about the CreateAction in any other cases? */
1366 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1367 *pOplock
|= CIFS_CREATE_ACTION
;
1369 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1370 36 /* CreationTime to Attributes */);
1371 /* the file_info buf is endian converted by caller */
1372 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1373 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1374 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1378 cifs_buf_release(pSMB
);
1385 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1386 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1387 char **buf
, int *pbuf_type
)
1390 READ_REQ
*pSMB
= NULL
;
1391 READ_RSP
*pSMBr
= NULL
;
1392 char *pReadData
= NULL
;
1394 int resp_buf_type
= 0;
1397 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1398 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1401 wct
= 10; /* old style read */
1404 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1408 /* tcon and ses pointer are checked in smb_init */
1409 if (tcon
->ses
->server
== NULL
)
1410 return -ECONNABORTED
;
1412 pSMB
->AndXCommand
= 0xFF; /* none */
1414 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1416 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1417 else if ((lseek
>> 32) > 0) /* can not handle this big offset for old */
1420 pSMB
->Remaining
= 0;
1421 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1422 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1424 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1426 /* old style read */
1427 struct smb_com_readx_req
*pSMBW
=
1428 (struct smb_com_readx_req
*)pSMB
;
1429 pSMBW
->ByteCount
= 0;
1432 iov
[0].iov_base
= (char *)pSMB
;
1433 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1434 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1435 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1436 cifs_stats_inc(&tcon
->num_reads
);
1437 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1439 cERROR(1, ("Send error in read = %d", rc
));
1441 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1442 data_length
= data_length
<< 16;
1443 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1444 *nbytes
= data_length
;
1446 /*check that DataLength would not go beyond end of SMB */
1447 if ((data_length
> CIFSMaxBufSize
)
1448 || (data_length
> count
)) {
1449 cFYI(1, ("bad length %d for count %d",
1450 data_length
, count
));
1454 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1455 le16_to_cpu(pSMBr
->DataOffset
);
1456 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1457 cERROR(1,("Faulting on read rc = %d",rc));
1459 }*/ /* can not use copy_to_user when using page cache*/
1461 memcpy(*buf
, pReadData
, data_length
);
1465 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1467 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1468 cifs_small_buf_release(iov
[0].iov_base
);
1469 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1470 cifs_buf_release(iov
[0].iov_base
);
1471 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1472 /* return buffer to caller to free */
1473 *buf
= iov
[0].iov_base
;
1474 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1475 *pbuf_type
= CIFS_SMALL_BUFFER
;
1476 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1477 *pbuf_type
= CIFS_LARGE_BUFFER
;
1478 } /* else no valid buffer on return - leave as null */
1480 /* Note: On -EAGAIN error only caller can retry on handle based calls
1481 since file handle passed in no longer valid */
1487 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1488 const int netfid
, const unsigned int count
,
1489 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1490 const char __user
*ubuf
, const int long_op
)
1493 WRITE_REQ
*pSMB
= NULL
;
1494 WRITE_RSP
*pSMBr
= NULL
;
1495 int bytes_returned
, wct
;
1499 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1500 if (tcon
->ses
== NULL
)
1501 return -ECONNABORTED
;
1503 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1508 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1512 /* tcon and ses pointer are checked in smb_init */
1513 if (tcon
->ses
->server
== NULL
)
1514 return -ECONNABORTED
;
1516 pSMB
->AndXCommand
= 0xFF; /* none */
1518 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1520 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1521 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1524 pSMB
->Reserved
= 0xFFFFFFFF;
1525 pSMB
->WriteMode
= 0;
1526 pSMB
->Remaining
= 0;
1528 /* Can increase buffer size if buffer is big enough in some cases ie we
1529 can send more if LARGE_WRITE_X capability returned by the server and if
1530 our buffer is big enough or if we convert to iovecs on socket writes
1531 and eliminate the copy to the CIFS buffer */
1532 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1533 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1535 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1539 if (bytes_sent
> count
)
1542 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1544 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1546 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1547 cifs_buf_release(pSMB
);
1550 } else if (count
!= 0) {
1552 cifs_buf_release(pSMB
);
1554 } /* else setting file size with write of zero bytes */
1556 byte_count
= bytes_sent
+ 1; /* pad */
1557 else /* wct == 12 */
1558 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1560 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1561 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1562 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1565 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1566 else { /* old style write has byte count 4 bytes earlier
1568 struct smb_com_writex_req
*pSMBW
=
1569 (struct smb_com_writex_req
*)pSMB
;
1570 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1573 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1574 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1575 cifs_stats_inc(&tcon
->num_writes
);
1577 cFYI(1, ("Send error in write = %d", rc
));
1580 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1581 *nbytes
= (*nbytes
) << 16;
1582 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1585 cifs_buf_release(pSMB
);
1587 /* Note: On -EAGAIN error only caller can retry on handle based calls
1588 since file handle passed in no longer valid */
1594 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1595 const int netfid
, const unsigned int count
,
1596 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1597 int n_vec
, const int long_op
)
1600 WRITE_REQ
*pSMB
= NULL
;
1603 int resp_buf_type
= 0;
1605 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1607 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1611 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1614 /* tcon and ses pointer are checked in smb_init */
1615 if (tcon
->ses
->server
== NULL
)
1616 return -ECONNABORTED
;
1618 pSMB
->AndXCommand
= 0xFF; /* none */
1620 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1622 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1623 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1625 pSMB
->Reserved
= 0xFFFFFFFF;
1626 pSMB
->WriteMode
= 0;
1627 pSMB
->Remaining
= 0;
1630 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1632 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1633 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1634 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1636 pSMB
->hdr
.smb_buf_length
+= count
+1;
1637 else /* wct == 12 */
1638 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1640 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1641 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1642 struct smb_com_writex_req
*pSMBW
=
1643 (struct smb_com_writex_req
*)pSMB
;
1644 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1646 iov
[0].iov_base
= pSMB
;
1648 iov
[0].iov_len
= smb_hdr_len
+ 4;
1649 else /* wct == 12 pad bigger by four bytes */
1650 iov
[0].iov_len
= smb_hdr_len
+ 8;
1653 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1655 cifs_stats_inc(&tcon
->num_writes
);
1657 cFYI(1, ("Send error Write2 = %d", rc
));
1659 } else if (resp_buf_type
== 0) {
1660 /* presumably this can not happen, but best to be safe */
1664 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1665 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1666 *nbytes
= (*nbytes
) << 16;
1667 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1670 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1671 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1672 cifs_small_buf_release(iov
[0].iov_base
);
1673 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1674 cifs_buf_release(iov
[0].iov_base
);
1676 /* Note: On -EAGAIN error only caller can retry on handle based calls
1677 since file handle passed in no longer valid */
1684 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1685 const __u16 smb_file_id
, const __u64 len
,
1686 const __u64 offset
, const __u32 numUnlock
,
1687 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1690 LOCK_REQ
*pSMB
= NULL
;
1691 LOCK_RSP
*pSMBr
= NULL
;
1696 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag
, numLock
));
1697 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1702 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1704 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1705 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1707 } else if (waitFlag
== TRUE
) {
1708 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1709 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1714 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1715 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1716 pSMB
->LockType
= lockType
;
1717 pSMB
->AndXCommand
= 0xFF; /* none */
1718 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1720 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1721 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1722 /* BB where to store pid high? */
1723 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1724 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1725 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1726 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1727 count
= sizeof(LOCKING_ANDX_RANGE
);
1732 pSMB
->hdr
.smb_buf_length
+= count
;
1733 pSMB
->ByteCount
= cpu_to_le16(count
);
1736 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1737 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1738 cifs_small_buf_release(pSMB
);
1740 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1742 /* SMB buffer freed by function above */
1744 cifs_stats_inc(&tcon
->num_locks
);
1746 cFYI(1, ("Send error in Lock = %d", rc
));
1748 /* Note: On -EAGAIN error only caller can retry on handle based calls
1749 since file handle passed in no longer valid */
1754 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1755 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1756 struct file_lock
*pLockData
, const __u16 lock_type
,
1759 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1760 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1761 struct cifs_posix_lock
*parm_data
;
1764 int bytes_returned
= 0;
1765 int resp_buf_type
= 0;
1766 __u16 params
, param_offset
, offset
, byte_count
, count
;
1769 cFYI(1, ("Posix Lock"));
1771 if (pLockData
== NULL
)
1774 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1779 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1782 pSMB
->MaxSetupCount
= 0;
1785 pSMB
->Reserved2
= 0;
1786 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1787 offset
= param_offset
+ params
;
1789 count
= sizeof(struct cifs_posix_lock
);
1790 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1791 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1792 pSMB
->SetupCount
= 1;
1793 pSMB
->Reserved3
= 0;
1795 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1797 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1798 byte_count
= 3 /* pad */ + params
+ count
;
1799 pSMB
->DataCount
= cpu_to_le16(count
);
1800 pSMB
->ParameterCount
= cpu_to_le16(params
);
1801 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1802 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1803 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1804 parm_data
= (struct cifs_posix_lock
*)
1805 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1807 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1809 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1810 parm_data
->lock_flags
= cpu_to_le16(1);
1811 pSMB
->Timeout
= cpu_to_le32(-1);
1815 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1816 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1817 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1819 pSMB
->DataOffset
= cpu_to_le16(offset
);
1820 pSMB
->Fid
= smb_file_id
;
1821 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1822 pSMB
->Reserved4
= 0;
1823 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1824 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1826 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1827 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1829 iov
[0].iov_base
= (char *)pSMB
;
1830 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1831 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1832 &resp_buf_type
, timeout
);
1833 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1834 not try to free it twice below on exit */
1835 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1839 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1840 } else if (get_flag
) {
1841 /* lock structure can be returned on get */
1844 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1846 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1847 rc
= -EIO
; /* bad smb */
1850 if (pLockData
== NULL
) {
1854 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1855 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1856 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1860 parm_data
= (struct cifs_posix_lock
*)
1861 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1862 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1863 pLockData
->fl_type
= F_UNLCK
;
1868 cifs_small_buf_release(pSMB
);
1870 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1871 cifs_small_buf_release(iov
[0].iov_base
);
1872 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1873 cifs_buf_release(iov
[0].iov_base
);
1875 /* Note: On -EAGAIN error only caller can retry on handle based calls
1876 since file handle passed in no longer valid */
1883 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1886 CLOSE_REQ
*pSMB
= NULL
;
1887 cFYI(1, ("In CIFSSMBClose"));
1889 /* do not retry on dead session on close */
1890 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1896 pSMB
->FileID
= (__u16
) smb_file_id
;
1897 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1898 pSMB
->ByteCount
= 0;
1899 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1900 cifs_stats_inc(&tcon
->num_closes
);
1903 /* EINTR is expected when user ctl-c to kill app */
1904 cERROR(1, ("Send error in Close = %d", rc
));
1908 /* Since session is dead, file will be closed on server already */
1916 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1917 const char *fromName
, const char *toName
,
1918 const struct nls_table
*nls_codepage
, int remap
)
1921 RENAME_REQ
*pSMB
= NULL
;
1922 RENAME_RSP
*pSMBr
= NULL
;
1924 int name_len
, name_len2
;
1927 cFYI(1, ("In CIFSSMBRename"));
1929 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1934 pSMB
->BufferFormat
= 0x04;
1935 pSMB
->SearchAttributes
=
1936 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1939 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1941 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1942 PATH_MAX
, nls_codepage
, remap
);
1943 name_len
++; /* trailing null */
1945 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1946 /* protocol requires ASCII signature byte on Unicode string */
1947 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1949 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1950 toName
, PATH_MAX
, nls_codepage
, remap
);
1951 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1952 name_len2
*= 2; /* convert to bytes */
1953 } else { /* BB improve the check for buffer overruns BB */
1954 name_len
= strnlen(fromName
, PATH_MAX
);
1955 name_len
++; /* trailing null */
1956 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1957 name_len2
= strnlen(toName
, PATH_MAX
);
1958 name_len2
++; /* trailing null */
1959 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1960 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1961 name_len2
++; /* trailing null */
1962 name_len2
++; /* signature byte */
1965 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1966 pSMB
->hdr
.smb_buf_length
+= count
;
1967 pSMB
->ByteCount
= cpu_to_le16(count
);
1969 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1970 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1971 cifs_stats_inc(&tcon
->num_renames
);
1973 cFYI(1, ("Send error in rename = %d", rc
));
1975 cifs_buf_release(pSMB
);
1983 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
1984 int netfid
, char *target_name
,
1985 const struct nls_table
*nls_codepage
, int remap
)
1987 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1988 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1989 struct set_file_rename
*rename_info
;
1991 char dummy_string
[30];
1993 int bytes_returned
= 0;
1995 __u16 params
, param_offset
, offset
, count
, byte_count
;
1997 cFYI(1, ("Rename to File by handle"));
1998 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2004 pSMB
->MaxSetupCount
= 0;
2008 pSMB
->Reserved2
= 0;
2009 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2010 offset
= param_offset
+ params
;
2012 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2013 rename_info
= (struct set_file_rename
*) data_offset
;
2014 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2015 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2016 pSMB
->SetupCount
= 1;
2017 pSMB
->Reserved3
= 0;
2018 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2019 byte_count
= 3 /* pad */ + params
;
2020 pSMB
->ParameterCount
= cpu_to_le16(params
);
2021 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2022 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2023 pSMB
->DataOffset
= cpu_to_le16(offset
);
2024 /* construct random name ".cifs_tmp<inodenum><mid>" */
2025 rename_info
->overwrite
= cpu_to_le32(1);
2026 rename_info
->root_fid
= 0;
2027 /* unicode only call */
2028 if (target_name
== NULL
) {
2029 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2030 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2031 dummy_string
, 24, nls_codepage
, remap
);
2033 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2034 target_name
, PATH_MAX
, nls_codepage
,
2037 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2038 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
2039 byte_count
+= count
;
2040 pSMB
->DataCount
= cpu_to_le16(count
);
2041 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2043 pSMB
->InformationLevel
=
2044 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2045 pSMB
->Reserved4
= 0;
2046 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2047 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2048 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2049 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2050 cifs_stats_inc(&pTcon
->num_t2renames
);
2052 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2054 cifs_buf_release(pSMB
);
2056 /* Note: On -EAGAIN error only caller can retry on handle based calls
2057 since file handle passed in no longer valid */
2063 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2064 const __u16 target_tid
, const char *toName
, const int flags
,
2065 const struct nls_table
*nls_codepage
, int remap
)
2068 COPY_REQ
*pSMB
= NULL
;
2069 COPY_RSP
*pSMBr
= NULL
;
2071 int name_len
, name_len2
;
2074 cFYI(1, ("In CIFSSMBCopy"));
2076 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2081 pSMB
->BufferFormat
= 0x04;
2082 pSMB
->Tid2
= target_tid
;
2084 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2086 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2087 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2088 fromName
, PATH_MAX
, nls_codepage
,
2090 name_len
++; /* trailing null */
2092 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2093 /* protocol requires ASCII signature byte on Unicode string */
2094 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2096 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2097 toName
, PATH_MAX
, nls_codepage
, remap
);
2098 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2099 name_len2
*= 2; /* convert to bytes */
2100 } else { /* BB improve the check for buffer overruns BB */
2101 name_len
= strnlen(fromName
, PATH_MAX
);
2102 name_len
++; /* trailing null */
2103 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2104 name_len2
= strnlen(toName
, PATH_MAX
);
2105 name_len2
++; /* trailing null */
2106 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2107 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2108 name_len2
++; /* trailing null */
2109 name_len2
++; /* signature byte */
2112 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2113 pSMB
->hdr
.smb_buf_length
+= count
;
2114 pSMB
->ByteCount
= cpu_to_le16(count
);
2116 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2117 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2119 cFYI(1, ("Send error in copy = %d with %d files copied",
2120 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2123 cifs_buf_release(pSMB
);
2132 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2133 const char *fromName
, const char *toName
,
2134 const struct nls_table
*nls_codepage
)
2136 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2137 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2140 int name_len_target
;
2142 int bytes_returned
= 0;
2143 __u16 params
, param_offset
, offset
, byte_count
;
2145 cFYI(1, ("In Symlink Unix style"));
2147 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2152 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2154 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2155 /* find define for this maxpathcomponent */
2157 name_len
++; /* trailing null */
2160 } else { /* BB improve the check for buffer overruns BB */
2161 name_len
= strnlen(fromName
, PATH_MAX
);
2162 name_len
++; /* trailing null */
2163 strncpy(pSMB
->FileName
, fromName
, name_len
);
2165 params
= 6 + name_len
;
2166 pSMB
->MaxSetupCount
= 0;
2170 pSMB
->Reserved2
= 0;
2171 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2172 InformationLevel
) - 4;
2173 offset
= param_offset
+ params
;
2175 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2176 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2178 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2179 /* find define for this maxpathcomponent */
2181 name_len_target
++; /* trailing null */
2182 name_len_target
*= 2;
2183 } else { /* BB improve the check for buffer overruns BB */
2184 name_len_target
= strnlen(toName
, PATH_MAX
);
2185 name_len_target
++; /* trailing null */
2186 strncpy(data_offset
, toName
, name_len_target
);
2189 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2190 /* BB find exact max on data count below from sess */
2191 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2192 pSMB
->SetupCount
= 1;
2193 pSMB
->Reserved3
= 0;
2194 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2195 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2196 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2197 pSMB
->ParameterCount
= cpu_to_le16(params
);
2198 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2199 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2200 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2201 pSMB
->DataOffset
= cpu_to_le16(offset
);
2202 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2203 pSMB
->Reserved4
= 0;
2204 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2205 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2206 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2207 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2208 cifs_stats_inc(&tcon
->num_symlinks
);
2210 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2213 cifs_buf_release(pSMB
);
2216 goto createSymLinkRetry
;
2222 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2223 const char *fromName
, const char *toName
,
2224 const struct nls_table
*nls_codepage
, int remap
)
2226 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2227 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2230 int name_len_target
;
2232 int bytes_returned
= 0;
2233 __u16 params
, param_offset
, offset
, byte_count
;
2235 cFYI(1, ("In Create Hard link Unix style"));
2236 createHardLinkRetry
:
2237 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2242 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2243 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2244 PATH_MAX
, nls_codepage
, remap
);
2245 name_len
++; /* trailing null */
2248 } else { /* BB improve the check for buffer overruns BB */
2249 name_len
= strnlen(toName
, PATH_MAX
);
2250 name_len
++; /* trailing null */
2251 strncpy(pSMB
->FileName
, toName
, name_len
);
2253 params
= 6 + name_len
;
2254 pSMB
->MaxSetupCount
= 0;
2258 pSMB
->Reserved2
= 0;
2259 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2260 InformationLevel
) - 4;
2261 offset
= param_offset
+ params
;
2263 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2264 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2266 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2267 nls_codepage
, remap
);
2268 name_len_target
++; /* trailing null */
2269 name_len_target
*= 2;
2270 } else { /* BB improve the check for buffer overruns BB */
2271 name_len_target
= strnlen(fromName
, PATH_MAX
);
2272 name_len_target
++; /* trailing null */
2273 strncpy(data_offset
, fromName
, name_len_target
);
2276 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2277 /* BB find exact max on data count below from sess*/
2278 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2279 pSMB
->SetupCount
= 1;
2280 pSMB
->Reserved3
= 0;
2281 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2282 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2283 pSMB
->ParameterCount
= cpu_to_le16(params
);
2284 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2285 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2286 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2287 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2288 pSMB
->DataOffset
= cpu_to_le16(offset
);
2289 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2290 pSMB
->Reserved4
= 0;
2291 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2292 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2293 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2294 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2295 cifs_stats_inc(&tcon
->num_hardlinks
);
2297 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2299 cifs_buf_release(pSMB
);
2301 goto createHardLinkRetry
;
2307 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2308 const char *fromName
, const char *toName
,
2309 const struct nls_table
*nls_codepage
, int remap
)
2312 NT_RENAME_REQ
*pSMB
= NULL
;
2313 RENAME_RSP
*pSMBr
= NULL
;
2315 int name_len
, name_len2
;
2318 cFYI(1, ("In CIFSCreateHardLink"));
2319 winCreateHardLinkRetry
:
2321 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2326 pSMB
->SearchAttributes
=
2327 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2329 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2330 pSMB
->ClusterCount
= 0;
2332 pSMB
->BufferFormat
= 0x04;
2334 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2336 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2337 PATH_MAX
, nls_codepage
, remap
);
2338 name_len
++; /* trailing null */
2340 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2341 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2343 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2344 toName
, PATH_MAX
, nls_codepage
, remap
);
2345 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2346 name_len2
*= 2; /* convert to bytes */
2347 } else { /* BB improve the check for buffer overruns BB */
2348 name_len
= strnlen(fromName
, PATH_MAX
);
2349 name_len
++; /* trailing null */
2350 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2351 name_len2
= strnlen(toName
, PATH_MAX
);
2352 name_len2
++; /* trailing null */
2353 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2354 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2355 name_len2
++; /* trailing null */
2356 name_len2
++; /* signature byte */
2359 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2360 pSMB
->hdr
.smb_buf_length
+= count
;
2361 pSMB
->ByteCount
= cpu_to_le16(count
);
2363 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2364 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2365 cifs_stats_inc(&tcon
->num_hardlinks
);
2367 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2369 cifs_buf_release(pSMB
);
2371 goto winCreateHardLinkRetry
;
2377 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2378 const unsigned char *searchName
,
2379 char *symlinkinfo
, const int buflen
,
2380 const struct nls_table
*nls_codepage
)
2382 /* SMB_QUERY_FILE_UNIX_LINK */
2383 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2384 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2388 __u16 params
, byte_count
;
2390 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2393 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2398 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2400 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2401 PATH_MAX
, nls_codepage
);
2402 name_len
++; /* trailing null */
2404 } else { /* BB improve the check for buffer overruns BB */
2405 name_len
= strnlen(searchName
, PATH_MAX
);
2406 name_len
++; /* trailing null */
2407 strncpy(pSMB
->FileName
, searchName
, name_len
);
2410 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2411 pSMB
->TotalDataCount
= 0;
2412 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2413 /* BB find exact max data count below from sess structure BB */
2414 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2415 pSMB
->MaxSetupCount
= 0;
2419 pSMB
->Reserved2
= 0;
2420 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2421 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2422 pSMB
->DataCount
= 0;
2423 pSMB
->DataOffset
= 0;
2424 pSMB
->SetupCount
= 1;
2425 pSMB
->Reserved3
= 0;
2426 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2427 byte_count
= params
+ 1 /* pad */ ;
2428 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2429 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2430 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2431 pSMB
->Reserved4
= 0;
2432 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2433 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2435 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2436 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2438 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2440 /* decode response */
2442 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2443 if (rc
|| (pSMBr
->ByteCount
< 2))
2444 /* BB also check enough total bytes returned */
2445 rc
= -EIO
; /* bad smb */
2447 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2448 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2450 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2451 name_len
= UniStrnlen((wchar_t *) ((char *)
2452 &pSMBr
->hdr
.Protocol
+ data_offset
),
2453 min_t(const int, buflen
, count
) / 2);
2454 /* BB FIXME investigate remapping reserved chars here */
2455 cifs_strfromUCS_le(symlinkinfo
,
2456 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
2458 name_len
, nls_codepage
);
2460 strncpy(symlinkinfo
,
2461 (char *) &pSMBr
->hdr
.Protocol
+
2463 min_t(const int, buflen
, count
));
2465 symlinkinfo
[buflen
] = 0;
2466 /* just in case so calling code does not go off the end of buffer */
2469 cifs_buf_release(pSMB
);
2471 goto querySymLinkRetry
;
2475 #ifdef CONFIG_CIFS_EXPERIMENTAL
2476 /* Initialize NT TRANSACT SMB into small smb request buffer.
2477 This assumes that all NT TRANSACTS that we init here have
2478 total parm and data under about 400 bytes (to fit in small cifs
2479 buffer size), which is the case so far, it easily fits. NB:
2480 Setup words themselves and ByteCount
2481 MaxSetupCount (size of returned setup area) and
2482 MaxParameterCount (returned parms size) must be set by caller */
2484 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2485 const int parm_len
, struct cifsTconInfo
*tcon
,
2490 struct smb_com_ntransact_req
*pSMB
;
2492 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2496 *ret_buf
= (void *)pSMB
;
2498 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2499 pSMB
->TotalDataCount
= 0;
2500 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2501 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2502 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2503 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2504 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2505 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2506 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2507 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2508 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2509 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2514 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2515 __u32
*pparmlen
, __u32
*pdatalen
)
2518 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2519 struct smb_com_ntransact_rsp
*pSMBr
;
2527 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2529 /* ByteCount was converted from little endian in SendReceive */
2530 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2531 (char *)&pSMBr
->ByteCount
;
2533 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2534 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2535 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2536 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2538 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2539 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2541 /* should we also check that parm and data areas do not overlap? */
2542 if (*ppparm
> end_of_smb
) {
2543 cFYI(1, ("parms start after end of smb"));
2545 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2546 cFYI(1, ("parm end after end of smb"));
2548 } else if (*ppdata
> end_of_smb
) {
2549 cFYI(1, ("data starts after end of smb"));
2551 } else if (data_count
+ *ppdata
> end_of_smb
) {
2552 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2553 *ppdata
, data_count
, (data_count
+ *ppdata
),
2554 end_of_smb
, pSMBr
));
2556 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2557 cFYI(1, ("parm count and data count larger than SMB"));
2560 *pdatalen
= data_count
;
2561 *pparmlen
= parm_count
;
2564 #endif /* CIFS_EXPERIMENTAL */
2567 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2568 const unsigned char *searchName
,
2569 char *symlinkinfo
, const int buflen
, __u16 fid
,
2570 const struct nls_table
*nls_codepage
)
2575 struct smb_com_transaction_ioctl_req
*pSMB
;
2576 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2578 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2579 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2584 pSMB
->TotalParameterCount
= 0 ;
2585 pSMB
->TotalDataCount
= 0;
2586 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2587 /* BB find exact data count max from sess structure BB */
2588 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2589 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2590 pSMB
->MaxSetupCount
= 4;
2592 pSMB
->ParameterOffset
= 0;
2593 pSMB
->DataCount
= 0;
2594 pSMB
->DataOffset
= 0;
2595 pSMB
->SetupCount
= 4;
2596 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2597 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2598 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2599 pSMB
->IsFsctl
= 1; /* FSCTL */
2600 pSMB
->IsRootFlag
= 0;
2601 pSMB
->Fid
= fid
; /* file handle always le */
2602 pSMB
->ByteCount
= 0;
2604 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2605 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2607 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2608 } else { /* decode response */
2609 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2610 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2611 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2612 /* BB also check enough total bytes returned */
2613 rc
= -EIO
; /* bad smb */
2615 if (data_count
&& (data_count
< 2048)) {
2616 char *end_of_smb
= 2 /* sizeof byte count */ +
2618 (char *)&pSMBr
->ByteCount
;
2620 struct reparse_data
*reparse_buf
=
2621 (struct reparse_data
*)
2622 ((char *)&pSMBr
->hdr
.Protocol
2624 if ((char *)reparse_buf
>= end_of_smb
) {
2628 if ((reparse_buf
->LinkNamesBuf
+
2629 reparse_buf
->TargetNameOffset
+
2630 reparse_buf
->TargetNameLen
) >
2632 cFYI(1, ("reparse buf beyond SMB"));
2637 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2638 name_len
= UniStrnlen((wchar_t *)
2639 (reparse_buf
->LinkNamesBuf
+
2640 reparse_buf
->TargetNameOffset
),
2642 reparse_buf
->TargetNameLen
/ 2));
2643 cifs_strfromUCS_le(symlinkinfo
,
2644 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2645 reparse_buf
->TargetNameOffset
),
2646 name_len
, nls_codepage
);
2647 } else { /* ASCII names */
2648 strncpy(symlinkinfo
,
2649 reparse_buf
->LinkNamesBuf
+
2650 reparse_buf
->TargetNameOffset
,
2651 min_t(const int, buflen
,
2652 reparse_buf
->TargetNameLen
));
2656 cFYI(1, ("Invalid return data count on "
2657 "get reparse info ioctl"));
2659 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2660 does not go off the end of the buffer */
2661 cFYI(1, ("readlink result - %s", symlinkinfo
));
2665 cifs_buf_release(pSMB
);
2667 /* Note: On -EAGAIN error only caller can retry on handle based calls
2668 since file handle passed in no longer valid */
2673 #ifdef CONFIG_CIFS_POSIX
2675 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2676 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2677 struct cifs_posix_ace
*cifs_ace
)
2679 /* u8 cifs fields do not need le conversion */
2680 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2681 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2682 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2683 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2688 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2689 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2690 const int acl_type
, const int size_of_data_area
)
2695 struct cifs_posix_ace
*pACE
;
2696 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2697 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2699 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2702 if (acl_type
& ACL_TYPE_ACCESS
) {
2703 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2704 pACE
= &cifs_acl
->ace_array
[0];
2705 size
= sizeof(struct cifs_posix_acl
);
2706 size
+= sizeof(struct cifs_posix_ace
) * count
;
2707 /* check if we would go beyond end of SMB */
2708 if (size_of_data_area
< size
) {
2709 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2710 size_of_data_area
, size
));
2713 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2714 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2715 size
= sizeof(struct cifs_posix_acl
);
2716 size
+= sizeof(struct cifs_posix_ace
) * count
;
2717 /* skip past access ACEs to get to default ACEs */
2718 pACE
= &cifs_acl
->ace_array
[count
];
2719 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2720 size
+= sizeof(struct cifs_posix_ace
) * count
;
2721 /* check if we would go beyond end of SMB */
2722 if (size_of_data_area
< size
)
2729 size
= posix_acl_xattr_size(count
);
2730 if ((buflen
== 0) || (local_acl
== NULL
)) {
2731 /* used to query ACL EA size */
2732 } else if (size
> buflen
) {
2734 } else /* buffer big enough */ {
2735 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2736 for (i
= 0; i
< count
; i
++) {
2737 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2744 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2745 const posix_acl_xattr_entry
*local_ace
)
2747 __u16 rc
= 0; /* 0 = ACL converted ok */
2749 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2750 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2751 /* BB is there a better way to handle the large uid? */
2752 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2753 /* Probably no need to le convert -1 on any arch but can not hurt */
2754 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2756 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2757 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2761 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2762 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2763 const int buflen
, const int acl_type
)
2766 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2767 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2771 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2774 count
= posix_acl_xattr_count((size_t)buflen
);
2775 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2777 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2778 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2779 cFYI(1, ("unknown POSIX ACL version %d",
2780 le32_to_cpu(local_acl
->a_version
)));
2783 cifs_acl
->version
= cpu_to_le16(1);
2784 if (acl_type
== ACL_TYPE_ACCESS
)
2785 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2786 else if (acl_type
== ACL_TYPE_DEFAULT
)
2787 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2789 cFYI(1, ("unknown ACL type %d", acl_type
));
2792 for (i
= 0; i
< count
; i
++) {
2793 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2794 &local_acl
->a_entries
[i
]);
2796 /* ACE not converted */
2801 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2802 rc
+= sizeof(struct cifs_posix_acl
);
2803 /* BB add check to make sure ACL does not overflow SMB */
2809 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2810 const unsigned char *searchName
,
2811 char *acl_inf
, const int buflen
, const int acl_type
,
2812 const struct nls_table
*nls_codepage
, int remap
)
2814 /* SMB_QUERY_POSIX_ACL */
2815 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2816 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2820 __u16 params
, byte_count
;
2822 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2825 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2830 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2832 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2833 PATH_MAX
, nls_codepage
, remap
);
2834 name_len
++; /* trailing null */
2836 pSMB
->FileName
[name_len
] = 0;
2837 pSMB
->FileName
[name_len
+1] = 0;
2838 } else { /* BB improve the check for buffer overruns BB */
2839 name_len
= strnlen(searchName
, PATH_MAX
);
2840 name_len
++; /* trailing null */
2841 strncpy(pSMB
->FileName
, searchName
, name_len
);
2844 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2845 pSMB
->TotalDataCount
= 0;
2846 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2847 /* BB find exact max data count below from sess structure BB */
2848 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2849 pSMB
->MaxSetupCount
= 0;
2853 pSMB
->Reserved2
= 0;
2854 pSMB
->ParameterOffset
= cpu_to_le16(
2855 offsetof(struct smb_com_transaction2_qpi_req
,
2856 InformationLevel
) - 4);
2857 pSMB
->DataCount
= 0;
2858 pSMB
->DataOffset
= 0;
2859 pSMB
->SetupCount
= 1;
2860 pSMB
->Reserved3
= 0;
2861 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2862 byte_count
= params
+ 1 /* pad */ ;
2863 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2864 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2865 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2866 pSMB
->Reserved4
= 0;
2867 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2868 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2870 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2871 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2872 cifs_stats_inc(&tcon
->num_acl_get
);
2874 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2876 /* decode response */
2878 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2879 if (rc
|| (pSMBr
->ByteCount
< 2))
2880 /* BB also check enough total bytes returned */
2881 rc
= -EIO
; /* bad smb */
2883 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2884 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2885 rc
= cifs_copy_posix_acl(acl_inf
,
2886 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2887 buflen
, acl_type
, count
);
2890 cifs_buf_release(pSMB
);
2897 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2898 const unsigned char *fileName
,
2899 const char *local_acl
, const int buflen
,
2901 const struct nls_table
*nls_codepage
, int remap
)
2903 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2904 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2908 int bytes_returned
= 0;
2909 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2911 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2913 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2917 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2919 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2920 PATH_MAX
, nls_codepage
, remap
);
2921 name_len
++; /* trailing null */
2923 } else { /* BB improve the check for buffer overruns BB */
2924 name_len
= strnlen(fileName
, PATH_MAX
);
2925 name_len
++; /* trailing null */
2926 strncpy(pSMB
->FileName
, fileName
, name_len
);
2928 params
= 6 + name_len
;
2929 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2930 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2931 pSMB
->MaxSetupCount
= 0;
2935 pSMB
->Reserved2
= 0;
2936 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2937 InformationLevel
) - 4;
2938 offset
= param_offset
+ params
;
2939 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2940 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2942 /* convert to on the wire format for POSIX ACL */
2943 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2945 if (data_count
== 0) {
2947 goto setACLerrorExit
;
2949 pSMB
->DataOffset
= cpu_to_le16(offset
);
2950 pSMB
->SetupCount
= 1;
2951 pSMB
->Reserved3
= 0;
2952 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2953 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2954 byte_count
= 3 /* pad */ + params
+ data_count
;
2955 pSMB
->DataCount
= cpu_to_le16(data_count
);
2956 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2957 pSMB
->ParameterCount
= cpu_to_le16(params
);
2958 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2959 pSMB
->Reserved4
= 0;
2960 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2961 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2962 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2963 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2965 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2968 cifs_buf_release(pSMB
);
2974 /* BB fix tabs in this function FIXME BB */
2976 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2977 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2980 struct smb_t2_qfi_req
*pSMB
= NULL
;
2981 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2983 __u16 params
, byte_count
;
2985 cFYI(1, ("In GetExtAttr"));
2990 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2995 params
= 2 /* level */ + 2 /* fid */;
2996 pSMB
->t2
.TotalDataCount
= 0;
2997 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2998 /* BB find exact max data count below from sess structure BB */
2999 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3000 pSMB
->t2
.MaxSetupCount
= 0;
3001 pSMB
->t2
.Reserved
= 0;
3003 pSMB
->t2
.Timeout
= 0;
3004 pSMB
->t2
.Reserved2
= 0;
3005 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3007 pSMB
->t2
.DataCount
= 0;
3008 pSMB
->t2
.DataOffset
= 0;
3009 pSMB
->t2
.SetupCount
= 1;
3010 pSMB
->t2
.Reserved3
= 0;
3011 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3012 byte_count
= params
+ 1 /* pad */ ;
3013 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3014 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3015 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3018 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3019 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3021 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3022 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3024 cFYI(1, ("error %d in GetExtAttr", rc
));
3026 /* decode response */
3027 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3028 if (rc
|| (pSMBr
->ByteCount
< 2))
3029 /* BB also check enough total bytes returned */
3030 /* If rc should we check for EOPNOSUPP and
3031 disable the srvino flag? or in caller? */
3032 rc
= -EIO
; /* bad smb */
3034 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3035 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3036 struct file_chattr_info
*pfinfo
;
3037 /* BB Do we need a cast or hash here ? */
3039 cFYI(1, ("Illegal size ret in GetExtAttr"));
3043 pfinfo
= (struct file_chattr_info
*)
3044 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3045 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3046 *pMask
= le64_to_cpu(pfinfo
->mask
);
3050 cifs_buf_release(pSMB
);
3052 goto GetExtAttrRetry
;
3056 #endif /* CONFIG_POSIX */
3058 #ifdef CONFIG_CIFS_EXPERIMENTAL
3059 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3061 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3062 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3066 QUERY_SEC_DESC_REQ
*pSMB
;
3069 cFYI(1, ("GetCifsACL"));
3074 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3075 8 /* parm len */, tcon
, (void **) &pSMB
);
3079 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3080 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3081 pSMB
->MaxSetupCount
= 0;
3082 pSMB
->Fid
= fid
; /* file handle always le */
3083 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3085 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3086 pSMB
->hdr
.smb_buf_length
+= 11;
3087 iov
[0].iov_base
= (char *)pSMB
;
3088 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3090 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3092 cifs_stats_inc(&tcon
->num_acl_get
);
3094 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3095 } else { /* decode response */
3099 struct smb_com_ntransact_rsp
*pSMBr
;
3102 /* validate_nttransact */
3103 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3104 &pdata
, &parm_len
, pbuflen
);
3107 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3109 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3111 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3112 rc
= -EIO
; /* bad smb */
3117 /* BB check that data area is minimum length and as big as acl_len */
3119 acl_len
= le32_to_cpu(*parm
);
3120 if (acl_len
!= *pbuflen
) {
3121 cERROR(1, ("acl length %d does not match %d",
3122 acl_len
, *pbuflen
));
3123 if (*pbuflen
> acl_len
)
3127 /* check if buffer is big enough for the acl
3128 header followed by the smallest SID */
3129 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3130 (*pbuflen
>= 64 * 1024)) {
3131 cERROR(1, ("bad acl length %d", *pbuflen
));
3135 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3136 if (*acl_inf
== NULL
) {
3140 memcpy(*acl_inf
, pdata
, *pbuflen
);
3144 if (buf_type
== CIFS_SMALL_BUFFER
)
3145 cifs_small_buf_release(iov
[0].iov_base
);
3146 else if (buf_type
== CIFS_LARGE_BUFFER
)
3147 cifs_buf_release(iov
[0].iov_base
);
3148 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3153 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3154 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3156 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3158 int bytes_returned
= 0;
3159 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3160 NTRANSACT_RSP
*pSMBr
= NULL
;
3163 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3168 pSMB
->MaxSetupCount
= 0;
3172 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3173 data_count
= acllen
;
3174 data_offset
= param_offset
+ param_count
;
3175 byte_count
= 3 /* pad */ + param_count
;
3177 pSMB
->DataCount
= cpu_to_le32(data_count
);
3178 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3179 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3180 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3181 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3182 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3183 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3184 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3185 pSMB
->SetupCount
= 0;
3186 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3187 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3189 pSMB
->Fid
= fid
; /* file handle always le */
3190 pSMB
->Reserved2
= 0;
3191 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3193 if (pntsd
&& acllen
) {
3194 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3197 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3200 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3202 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3203 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3205 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3207 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3208 cifs_buf_release(pSMB
);
3211 goto setCifsAclRetry
;
3216 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3218 /* Legacy Query Path Information call for lookup to old servers such
3220 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3221 const unsigned char *searchName
,
3222 FILE_ALL_INFO
*pFinfo
,
3223 const struct nls_table
*nls_codepage
, int remap
)
3225 QUERY_INFORMATION_REQ
*pSMB
;
3226 QUERY_INFORMATION_RSP
*pSMBr
;
3231 cFYI(1, ("In SMBQPath path %s", searchName
));
3233 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3238 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3240 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3241 PATH_MAX
, nls_codepage
, remap
);
3242 name_len
++; /* trailing null */
3245 name_len
= strnlen(searchName
, PATH_MAX
);
3246 name_len
++; /* trailing null */
3247 strncpy(pSMB
->FileName
, searchName
, name_len
);
3249 pSMB
->BufferFormat
= 0x04;
3250 name_len
++; /* account for buffer type byte */
3251 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3252 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3254 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3255 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3257 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3258 } else if (pFinfo
) {
3260 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3262 /* decode response */
3263 /* BB FIXME - add time zone adjustment BB */
3264 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3267 /* decode time fields */
3268 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3269 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3270 pFinfo
->LastAccessTime
= 0;
3271 pFinfo
->AllocationSize
=
3272 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3273 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3274 pFinfo
->Attributes
=
3275 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3277 rc
= -EIO
; /* bad buffer passed in */
3279 cifs_buf_release(pSMB
);
3291 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3292 const unsigned char *searchName
,
3293 FILE_ALL_INFO
*pFindData
,
3294 int legacy
/* old style infolevel */,
3295 const struct nls_table
*nls_codepage
, int remap
)
3297 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3298 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3299 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3303 __u16 params
, byte_count
;
3305 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3307 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3312 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3314 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3315 PATH_MAX
, nls_codepage
, remap
);
3316 name_len
++; /* trailing null */
3318 } else { /* BB improve the check for buffer overruns BB */
3319 name_len
= strnlen(searchName
, PATH_MAX
);
3320 name_len
++; /* trailing null */
3321 strncpy(pSMB
->FileName
, searchName
, name_len
);
3324 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3325 pSMB
->TotalDataCount
= 0;
3326 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3327 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3328 pSMB
->MaxSetupCount
= 0;
3332 pSMB
->Reserved2
= 0;
3333 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3334 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3335 pSMB
->DataCount
= 0;
3336 pSMB
->DataOffset
= 0;
3337 pSMB
->SetupCount
= 1;
3338 pSMB
->Reserved3
= 0;
3339 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3340 byte_count
= params
+ 1 /* pad */ ;
3341 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3342 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3344 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3346 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3347 pSMB
->Reserved4
= 0;
3348 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3349 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3351 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3352 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3354 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3355 } else { /* decode response */
3356 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3358 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3360 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3361 rc
= -EIO
; /* bad smb */
3362 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3363 rc
= -EIO
; /* 24 or 26 expected but we do not read
3365 else if (pFindData
) {
3367 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3369 /* On legacy responses we do not read the last field,
3370 EAsize, fortunately since it varies by subdialect and
3371 also note it differs on Set vs. Get, ie two bytes or 4
3372 bytes depending but we don't care here */
3374 size
= sizeof(FILE_INFO_STANDARD
);
3376 size
= sizeof(FILE_ALL_INFO
);
3377 memcpy((char *) pFindData
,
3378 (char *) &pSMBr
->hdr
.Protocol
+
3383 cifs_buf_release(pSMB
);
3385 goto QPathInfoRetry
;
3391 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3392 const unsigned char *searchName
,
3393 FILE_UNIX_BASIC_INFO
* pFindData
,
3394 const struct nls_table
*nls_codepage
, int remap
)
3396 /* SMB_QUERY_FILE_UNIX_BASIC */
3397 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3398 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3400 int bytes_returned
= 0;
3402 __u16 params
, byte_count
;
3404 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3406 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3411 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3413 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3414 PATH_MAX
, nls_codepage
, remap
);
3415 name_len
++; /* trailing null */
3417 } else { /* BB improve the check for buffer overruns BB */
3418 name_len
= strnlen(searchName
, PATH_MAX
);
3419 name_len
++; /* trailing null */
3420 strncpy(pSMB
->FileName
, searchName
, name_len
);
3423 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3424 pSMB
->TotalDataCount
= 0;
3425 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3426 /* BB find exact max SMB PDU from sess structure BB */
3427 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3428 pSMB
->MaxSetupCount
= 0;
3432 pSMB
->Reserved2
= 0;
3433 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3434 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3435 pSMB
->DataCount
= 0;
3436 pSMB
->DataOffset
= 0;
3437 pSMB
->SetupCount
= 1;
3438 pSMB
->Reserved3
= 0;
3439 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3440 byte_count
= params
+ 1 /* pad */ ;
3441 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3442 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3443 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3444 pSMB
->Reserved4
= 0;
3445 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3446 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3448 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3449 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3451 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3452 } else { /* decode response */
3453 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3455 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3456 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3457 "Unix Extensions can be disabled on mount "
3458 "by specifying the nosfu mount option."));
3459 rc
= -EIO
; /* bad smb */
3461 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3462 memcpy((char *) pFindData
,
3463 (char *) &pSMBr
->hdr
.Protocol
+
3465 sizeof(FILE_UNIX_BASIC_INFO
));
3468 cifs_buf_release(pSMB
);
3470 goto UnixQPathInfoRetry
;
3475 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3477 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3478 const char *searchName
,
3479 const struct nls_table
*nls_codepage
,
3481 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3483 /* level 257 SMB_ */
3484 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3485 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3486 T2_FFIRST_RSP_PARMS
*parms
;
3488 int bytes_returned
= 0;
3490 __u16 params
, byte_count
;
3492 cFYI(1, ("In FindFirst for %s", searchName
));
3495 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3500 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3502 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3503 PATH_MAX
, nls_codepage
, remap
);
3504 /* We can not add the asterik earlier in case
3505 it got remapped to 0xF03A as if it were part of the
3506 directory name instead of a wildcard */
3508 pSMB
->FileName
[name_len
] = dirsep
;
3509 pSMB
->FileName
[name_len
+1] = 0;
3510 pSMB
->FileName
[name_len
+2] = '*';
3511 pSMB
->FileName
[name_len
+3] = 0;
3512 name_len
+= 4; /* now the trailing null */
3513 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3514 pSMB
->FileName
[name_len
+1] = 0;
3516 } else { /* BB add check for overrun of SMB buf BB */
3517 name_len
= strnlen(searchName
, PATH_MAX
);
3518 /* BB fix here and in unicode clause above ie
3519 if (name_len > buffersize-header)
3520 free buffer exit; BB */
3521 strncpy(pSMB
->FileName
, searchName
, name_len
);
3522 pSMB
->FileName
[name_len
] = dirsep
;
3523 pSMB
->FileName
[name_len
+1] = '*';
3524 pSMB
->FileName
[name_len
+2] = 0;
3528 params
= 12 + name_len
/* includes null */ ;
3529 pSMB
->TotalDataCount
= 0; /* no EAs */
3530 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3531 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3532 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3533 pSMB
->MaxSetupCount
= 0;
3537 pSMB
->Reserved2
= 0;
3538 byte_count
= params
+ 1 /* pad */ ;
3539 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3540 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3541 pSMB
->ParameterOffset
= cpu_to_le16(
3542 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3544 pSMB
->DataCount
= 0;
3545 pSMB
->DataOffset
= 0;
3546 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3547 pSMB
->Reserved3
= 0;
3548 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3549 pSMB
->SearchAttributes
=
3550 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3552 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3553 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3554 CIFS_SEARCH_RETURN_RESUME
);
3555 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3557 /* BB what should we set StorageType to? Does it matter? BB */
3558 pSMB
->SearchStorageType
= 0;
3559 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3560 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3562 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3563 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3564 cifs_stats_inc(&tcon
->num_ffirst
);
3566 if (rc
) {/* BB add logic to retry regular search if Unix search
3567 rejected unexpectedly by server */
3568 /* BB Add code to handle unsupported level rc */
3569 cFYI(1, ("Error in FindFirst = %d", rc
));
3571 cifs_buf_release(pSMB
);
3573 /* BB eventually could optimize out free and realloc of buf */
3576 goto findFirstRetry
;
3577 } else { /* decode response */
3578 /* BB remember to free buffer if error BB */
3579 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3581 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3582 psrch_inf
->unicode
= TRUE
;
3584 psrch_inf
->unicode
= FALSE
;
3586 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3587 psrch_inf
->smallBuf
= 0;
3588 psrch_inf
->srch_entries_start
=
3589 (char *) &pSMBr
->hdr
.Protocol
+
3590 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3591 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3592 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3594 if (parms
->EndofSearch
)
3595 psrch_inf
->endOfSearch
= TRUE
;
3597 psrch_inf
->endOfSearch
= FALSE
;
3599 psrch_inf
->entries_in_buffer
=
3600 le16_to_cpu(parms
->SearchCount
);
3601 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3602 psrch_inf
->entries_in_buffer
;
3603 *pnetfid
= parms
->SearchHandle
;
3605 cifs_buf_release(pSMB
);
3612 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3613 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3615 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3616 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3617 T2_FNEXT_RSP_PARMS
*parms
;
3618 char *response_data
;
3620 int bytes_returned
, name_len
;
3621 __u16 params
, byte_count
;
3623 cFYI(1, ("In FindNext"));
3625 if (psrch_inf
->endOfSearch
== TRUE
)
3628 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3633 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3635 pSMB
->TotalDataCount
= 0; /* no EAs */
3636 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3637 pSMB
->MaxDataCount
=
3638 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3640 pSMB
->MaxSetupCount
= 0;
3644 pSMB
->Reserved2
= 0;
3645 pSMB
->ParameterOffset
= cpu_to_le16(
3646 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3647 pSMB
->DataCount
= 0;
3648 pSMB
->DataOffset
= 0;
3649 pSMB
->SetupCount
= 1;
3650 pSMB
->Reserved3
= 0;
3651 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3652 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3654 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3655 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3656 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3658 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3660 name_len
= psrch_inf
->resume_name_len
;
3662 if (name_len
< PATH_MAX
) {
3663 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3664 byte_count
+= name_len
;
3665 /* 14 byte parm len above enough for 2 byte null terminator */
3666 pSMB
->ResumeFileName
[name_len
] = 0;
3667 pSMB
->ResumeFileName
[name_len
+1] = 0;
3670 goto FNext2_err_exit
;
3672 byte_count
= params
+ 1 /* pad */ ;
3673 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3674 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3675 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3676 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3678 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3679 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3680 cifs_stats_inc(&tcon
->num_fnext
);
3683 psrch_inf
->endOfSearch
= TRUE
;
3684 rc
= 0; /* search probably was closed at end of search*/
3686 cFYI(1, ("FindNext returned = %d", rc
));
3687 } else { /* decode response */
3688 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3691 /* BB fixme add lock for file (srch_info) struct here */
3692 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3693 psrch_inf
->unicode
= TRUE
;
3695 psrch_inf
->unicode
= FALSE
;
3696 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3697 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3698 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3699 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3700 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3701 if (psrch_inf
->smallBuf
)
3702 cifs_small_buf_release(
3703 psrch_inf
->ntwrk_buf_start
);
3705 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3706 psrch_inf
->srch_entries_start
= response_data
;
3707 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3708 psrch_inf
->smallBuf
= 0;
3709 if (parms
->EndofSearch
)
3710 psrch_inf
->endOfSearch
= TRUE
;
3712 psrch_inf
->endOfSearch
= FALSE
;
3713 psrch_inf
->entries_in_buffer
=
3714 le16_to_cpu(parms
->SearchCount
);
3715 psrch_inf
->index_of_last_entry
+=
3716 psrch_inf
->entries_in_buffer
;
3717 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3718 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3720 /* BB fixme add unlock here */
3725 /* BB On error, should we leave previous search buf (and count and
3726 last entry fields) intact or free the previous one? */
3728 /* Note: On -EAGAIN error only caller can retry on handle based calls
3729 since file handle passed in no longer valid */
3732 cifs_buf_release(pSMB
);
3737 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3738 const __u16 searchHandle
)
3741 FINDCLOSE_REQ
*pSMB
= NULL
;
3743 cFYI(1, ("In CIFSSMBFindClose"));
3744 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3746 /* no sense returning error if session restarted
3747 as file handle has been closed */
3753 pSMB
->FileID
= searchHandle
;
3754 pSMB
->ByteCount
= 0;
3755 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3757 cERROR(1, ("Send error in FindClose = %d", rc
));
3759 cifs_stats_inc(&tcon
->num_fclose
);
3761 /* Since session is dead, search handle closed on server already */
3769 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3770 const unsigned char *searchName
,
3771 __u64
*inode_number
,
3772 const struct nls_table
*nls_codepage
, int remap
)
3775 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3776 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3777 int name_len
, bytes_returned
;
3778 __u16 params
, byte_count
;
3780 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3784 GetInodeNumberRetry
:
3785 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3790 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3792 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3793 PATH_MAX
, nls_codepage
, remap
);
3794 name_len
++; /* trailing null */
3796 } else { /* BB improve the check for buffer overruns BB */
3797 name_len
= strnlen(searchName
, PATH_MAX
);
3798 name_len
++; /* trailing null */
3799 strncpy(pSMB
->FileName
, searchName
, name_len
);
3802 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3803 pSMB
->TotalDataCount
= 0;
3804 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3805 /* BB find exact max data count below from sess structure BB */
3806 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3807 pSMB
->MaxSetupCount
= 0;
3811 pSMB
->Reserved2
= 0;
3812 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3813 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3814 pSMB
->DataCount
= 0;
3815 pSMB
->DataOffset
= 0;
3816 pSMB
->SetupCount
= 1;
3817 pSMB
->Reserved3
= 0;
3818 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3819 byte_count
= params
+ 1 /* pad */ ;
3820 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3821 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3822 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3823 pSMB
->Reserved4
= 0;
3824 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3825 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3827 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3828 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3830 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3832 /* decode response */
3833 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3834 if (rc
|| (pSMBr
->ByteCount
< 2))
3835 /* BB also check enough total bytes returned */
3836 /* If rc should we check for EOPNOSUPP and
3837 disable the srvino flag? or in caller? */
3838 rc
= -EIO
; /* bad smb */
3840 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3841 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3842 struct file_internal_info
*pfinfo
;
3843 /* BB Do we need a cast or hash here ? */
3845 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3847 goto GetInodeNumOut
;
3849 pfinfo
= (struct file_internal_info
*)
3850 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3851 *inode_number
= pfinfo
->UniqueId
;
3855 cifs_buf_release(pSMB
);
3857 goto GetInodeNumberRetry
;
3862 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3863 const unsigned char *searchName
,
3864 unsigned char **targetUNCs
,
3865 unsigned int *number_of_UNC_in_array
,
3866 const struct nls_table
*nls_codepage
, int remap
)
3868 /* TRANS2_GET_DFS_REFERRAL */
3869 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3870 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3871 struct dfs_referral_level_3
*referrals
= NULL
;
3877 __u16 params
, byte_count
;
3878 *number_of_UNC_in_array
= 0;
3881 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3885 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3890 /* server pointer checked in called function,
3891 but should never be null here anyway */
3892 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3893 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3894 pSMB
->hdr
.Uid
= ses
->Suid
;
3895 if (ses
->capabilities
& CAP_STATUS32
)
3896 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3897 if (ses
->capabilities
& CAP_DFS
)
3898 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3900 if (ses
->capabilities
& CAP_UNICODE
) {
3901 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3903 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3904 searchName
, PATH_MAX
, nls_codepage
, remap
);
3905 name_len
++; /* trailing null */
3907 } else { /* BB improve the check for buffer overruns BB */
3908 name_len
= strnlen(searchName
, PATH_MAX
);
3909 name_len
++; /* trailing null */
3910 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3914 if (ses
->server
->secMode
&
3915 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
3916 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
3919 pSMB
->hdr
.Uid
= ses
->Suid
;
3921 params
= 2 /* level */ + name_len
/*includes null */ ;
3922 pSMB
->TotalDataCount
= 0;
3923 pSMB
->DataCount
= 0;
3924 pSMB
->DataOffset
= 0;
3925 pSMB
->MaxParameterCount
= 0;
3926 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3927 pSMB
->MaxSetupCount
= 0;
3931 pSMB
->Reserved2
= 0;
3932 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3933 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3934 pSMB
->SetupCount
= 1;
3935 pSMB
->Reserved3
= 0;
3936 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3937 byte_count
= params
+ 3 /* pad */ ;
3938 pSMB
->ParameterCount
= cpu_to_le16(params
);
3939 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3940 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3941 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3942 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3944 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3945 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3947 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3948 } else { /* decode response */
3949 /* BB Add logic to parse referrals here */
3950 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3952 /* BB Also check if enough total bytes returned? */
3953 if (rc
|| (pSMBr
->ByteCount
< 17))
3954 rc
= -EIO
; /* bad smb */
3956 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3957 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3960 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3961 pSMBr
->ByteCount
, data_offset
));
3963 (struct dfs_referral_level_3
*)
3964 (8 /* sizeof start of data block */ +
3966 (char *) &pSMBr
->hdr
.Protocol
);
3967 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3968 "for referral one refer size: 0x%x srv "
3969 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3970 le16_to_cpu(pSMBr
->NumberOfReferrals
),
3971 le16_to_cpu(pSMBr
->DFSFlags
),
3972 le16_to_cpu(referrals
->ReferralSize
),
3973 le16_to_cpu(referrals
->ServerType
),
3974 le16_to_cpu(referrals
->ReferralFlags
),
3975 le16_to_cpu(referrals
->TimeToLive
)));
3976 /* BB This field is actually two bytes in from start of
3977 data block so we could do safety check that DataBlock
3978 begins at address of pSMBr->NumberOfReferrals */
3979 *number_of_UNC_in_array
=
3980 le16_to_cpu(pSMBr
->NumberOfReferrals
);
3982 /* BB Fix below so can return more than one referral */
3983 if (*number_of_UNC_in_array
> 1)
3984 *number_of_UNC_in_array
= 1;
3986 /* get the length of the strings describing refs */
3988 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
3989 /* make sure that DfsPathOffset not past end */
3991 le16_to_cpu(referrals
->DfsPathOffset
);
3992 if (offset
> data_count
) {
3993 /* if invalid referral, stop here and do
3994 not try to copy any more */
3995 *number_of_UNC_in_array
= i
;
3998 temp
= ((char *)referrals
) + offset
;
4000 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4001 name_len
+= UniStrnlen((wchar_t *)temp
,
4004 name_len
+= strnlen(temp
, data_count
);
4007 /* BB add check that referral pointer does
4008 not fall off end PDU */
4010 /* BB add check for name_len bigger than bcc */
4012 kmalloc(name_len
+1+(*number_of_UNC_in_array
),
4014 if (*targetUNCs
== NULL
) {
4018 /* copy the ref strings */
4019 referrals
= (struct dfs_referral_level_3
*)
4020 (8 /* sizeof data hdr */ + data_offset
+
4021 (char *) &pSMBr
->hdr
.Protocol
);
4023 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
4024 temp
= ((char *)referrals
) +
4025 le16_to_cpu(referrals
->DfsPathOffset
);
4026 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4027 cifs_strfromUCS_le(*targetUNCs
,
4032 strncpy(*targetUNCs
, temp
, name_len
);
4034 /* BB update target_uncs pointers */
4044 cifs_buf_release(pSMB
);
4052 /* Query File System Info such as free space to old servers such as Win 9x */
4054 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4056 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4057 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4058 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4059 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4061 int bytes_returned
= 0;
4062 __u16 params
, byte_count
;
4064 cFYI(1, ("OldQFSInfo"));
4066 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4071 params
= 2; /* level */
4072 pSMB
->TotalDataCount
= 0;
4073 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4074 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4075 pSMB
->MaxSetupCount
= 0;
4079 pSMB
->Reserved2
= 0;
4080 byte_count
= params
+ 1 /* pad */ ;
4081 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4082 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4083 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4084 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4085 pSMB
->DataCount
= 0;
4086 pSMB
->DataOffset
= 0;
4087 pSMB
->SetupCount
= 1;
4088 pSMB
->Reserved3
= 0;
4089 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4090 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4091 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4092 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4094 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4095 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4097 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4098 } else { /* decode response */
4099 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4101 if (rc
|| (pSMBr
->ByteCount
< 18))
4102 rc
= -EIO
; /* bad smb */
4104 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4105 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4106 pSMBr
->ByteCount
, data_offset
));
4108 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4109 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4111 le16_to_cpu(response_data
->BytesPerSector
) *
4112 le32_to_cpu(response_data
->
4113 SectorsPerAllocationUnit
);
4115 le32_to_cpu(response_data
->TotalAllocationUnits
);
4116 FSData
->f_bfree
= FSData
->f_bavail
=
4117 le32_to_cpu(response_data
->FreeAllocationUnits
);
4119 ("Blocks: %lld Free: %lld Block size %ld",
4120 (unsigned long long)FSData
->f_blocks
,
4121 (unsigned long long)FSData
->f_bfree
,
4125 cifs_buf_release(pSMB
);
4128 goto oldQFSInfoRetry
;
4134 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4136 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4137 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4138 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4139 FILE_SYSTEM_INFO
*response_data
;
4141 int bytes_returned
= 0;
4142 __u16 params
, byte_count
;
4144 cFYI(1, ("In QFSInfo"));
4146 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4151 params
= 2; /* level */
4152 pSMB
->TotalDataCount
= 0;
4153 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4154 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4155 pSMB
->MaxSetupCount
= 0;
4159 pSMB
->Reserved2
= 0;
4160 byte_count
= params
+ 1 /* pad */ ;
4161 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4162 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4163 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4164 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4165 pSMB
->DataCount
= 0;
4166 pSMB
->DataOffset
= 0;
4167 pSMB
->SetupCount
= 1;
4168 pSMB
->Reserved3
= 0;
4169 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4170 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4171 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4172 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4174 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4175 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4177 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4178 } else { /* decode response */
4179 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4181 if (rc
|| (pSMBr
->ByteCount
< 24))
4182 rc
= -EIO
; /* bad smb */
4184 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4188 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4191 le32_to_cpu(response_data
->BytesPerSector
) *
4192 le32_to_cpu(response_data
->
4193 SectorsPerAllocationUnit
);
4195 le64_to_cpu(response_data
->TotalAllocationUnits
);
4196 FSData
->f_bfree
= FSData
->f_bavail
=
4197 le64_to_cpu(response_data
->FreeAllocationUnits
);
4199 ("Blocks: %lld Free: %lld Block size %ld",
4200 (unsigned long long)FSData
->f_blocks
,
4201 (unsigned long long)FSData
->f_bfree
,
4205 cifs_buf_release(pSMB
);
4214 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4216 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4217 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4218 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4219 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4221 int bytes_returned
= 0;
4222 __u16 params
, byte_count
;
4224 cFYI(1, ("In QFSAttributeInfo"));
4226 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4231 params
= 2; /* level */
4232 pSMB
->TotalDataCount
= 0;
4233 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4234 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4235 pSMB
->MaxSetupCount
= 0;
4239 pSMB
->Reserved2
= 0;
4240 byte_count
= params
+ 1 /* pad */ ;
4241 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4242 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4243 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4244 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4245 pSMB
->DataCount
= 0;
4246 pSMB
->DataOffset
= 0;
4247 pSMB
->SetupCount
= 1;
4248 pSMB
->Reserved3
= 0;
4249 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4250 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4251 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4252 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4254 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4255 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4257 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4258 } else { /* decode response */
4259 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4261 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4262 /* BB also check if enough bytes returned */
4263 rc
= -EIO
; /* bad smb */
4265 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4267 (FILE_SYSTEM_ATTRIBUTE_INFO
4268 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4270 memcpy(&tcon
->fsAttrInfo
, response_data
,
4271 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4274 cifs_buf_release(pSMB
);
4277 goto QFSAttributeRetry
;
4283 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4285 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4286 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4287 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4288 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4290 int bytes_returned
= 0;
4291 __u16 params
, byte_count
;
4293 cFYI(1, ("In QFSDeviceInfo"));
4295 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4300 params
= 2; /* level */
4301 pSMB
->TotalDataCount
= 0;
4302 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4303 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4304 pSMB
->MaxSetupCount
= 0;
4308 pSMB
->Reserved2
= 0;
4309 byte_count
= params
+ 1 /* pad */ ;
4310 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4311 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4312 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4313 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4315 pSMB
->DataCount
= 0;
4316 pSMB
->DataOffset
= 0;
4317 pSMB
->SetupCount
= 1;
4318 pSMB
->Reserved3
= 0;
4319 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4320 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4321 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4322 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4324 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4325 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4327 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4328 } else { /* decode response */
4329 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4331 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4332 rc
= -EIO
; /* bad smb */
4334 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4336 (FILE_SYSTEM_DEVICE_INFO
*)
4337 (((char *) &pSMBr
->hdr
.Protocol
) +
4339 memcpy(&tcon
->fsDevInfo
, response_data
,
4340 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4343 cifs_buf_release(pSMB
);
4346 goto QFSDeviceRetry
;
4352 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4354 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4355 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4356 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4357 FILE_SYSTEM_UNIX_INFO
*response_data
;
4359 int bytes_returned
= 0;
4360 __u16 params
, byte_count
;
4362 cFYI(1, ("In QFSUnixInfo"));
4364 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4369 params
= 2; /* level */
4370 pSMB
->TotalDataCount
= 0;
4371 pSMB
->DataCount
= 0;
4372 pSMB
->DataOffset
= 0;
4373 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4374 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4375 pSMB
->MaxSetupCount
= 0;
4379 pSMB
->Reserved2
= 0;
4380 byte_count
= params
+ 1 /* pad */ ;
4381 pSMB
->ParameterCount
= cpu_to_le16(params
);
4382 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4383 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4384 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4385 pSMB
->SetupCount
= 1;
4386 pSMB
->Reserved3
= 0;
4387 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4388 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4389 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4390 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4392 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4393 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4395 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4396 } else { /* decode response */
4397 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4399 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4400 rc
= -EIO
; /* bad smb */
4402 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4404 (FILE_SYSTEM_UNIX_INFO
4405 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4407 memcpy(&tcon
->fsUnixInfo
, response_data
,
4408 sizeof(FILE_SYSTEM_UNIX_INFO
));
4411 cifs_buf_release(pSMB
);
4421 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4423 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4424 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4425 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4427 int bytes_returned
= 0;
4428 __u16 params
, param_offset
, offset
, byte_count
;
4430 cFYI(1, ("In SETFSUnixInfo"));
4432 /* BB switch to small buf init to save memory */
4433 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4438 params
= 4; /* 2 bytes zero followed by info level. */
4439 pSMB
->MaxSetupCount
= 0;
4443 pSMB
->Reserved2
= 0;
4444 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4446 offset
= param_offset
+ params
;
4448 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4449 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4450 pSMB
->SetupCount
= 1;
4451 pSMB
->Reserved3
= 0;
4452 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4453 byte_count
= 1 /* pad */ + params
+ 12;
4455 pSMB
->DataCount
= cpu_to_le16(12);
4456 pSMB
->ParameterCount
= cpu_to_le16(params
);
4457 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4458 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4459 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4460 pSMB
->DataOffset
= cpu_to_le16(offset
);
4464 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4467 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4468 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4469 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4471 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4472 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4474 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4475 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4477 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4478 } else { /* decode response */
4479 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4481 rc
= -EIO
; /* bad smb */
4483 cifs_buf_release(pSMB
);
4486 goto SETFSUnixRetry
;
4494 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4495 struct kstatfs
*FSData
)
4497 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4498 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4499 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4500 FILE_SYSTEM_POSIX_INFO
*response_data
;
4502 int bytes_returned
= 0;
4503 __u16 params
, byte_count
;
4505 cFYI(1, ("In QFSPosixInfo"));
4507 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4512 params
= 2; /* level */
4513 pSMB
->TotalDataCount
= 0;
4514 pSMB
->DataCount
= 0;
4515 pSMB
->DataOffset
= 0;
4516 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4517 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4518 pSMB
->MaxSetupCount
= 0;
4522 pSMB
->Reserved2
= 0;
4523 byte_count
= params
+ 1 /* pad */ ;
4524 pSMB
->ParameterCount
= cpu_to_le16(params
);
4525 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4526 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4527 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4528 pSMB
->SetupCount
= 1;
4529 pSMB
->Reserved3
= 0;
4530 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4531 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4532 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4533 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4535 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4536 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4538 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4539 } else { /* decode response */
4540 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4542 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4543 rc
= -EIO
; /* bad smb */
4545 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4547 (FILE_SYSTEM_POSIX_INFO
4548 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4551 le32_to_cpu(response_data
->BlockSize
);
4553 le64_to_cpu(response_data
->TotalBlocks
);
4555 le64_to_cpu(response_data
->BlocksAvail
);
4556 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4557 FSData
->f_bavail
= FSData
->f_bfree
;
4560 le64_to_cpu(response_data
->UserBlocksAvail
);
4562 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4564 le64_to_cpu(response_data
->TotalFileNodes
);
4565 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4567 le64_to_cpu(response_data
->FreeFileNodes
);
4570 cifs_buf_release(pSMB
);
4579 /* We can not use write of zero bytes trick to
4580 set file size due to need for large file support. Also note that
4581 this SetPathInfo is preferred to SetFileInfo based method in next
4582 routine which is only needed to work around a sharing violation bug
4583 in Samba which this routine can run into */
4586 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4587 __u64 size
, int SetAllocation
,
4588 const struct nls_table
*nls_codepage
, int remap
)
4590 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4591 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4592 struct file_end_of_file_info
*parm_data
;
4595 int bytes_returned
= 0;
4596 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4598 cFYI(1, ("In SetEOF"));
4600 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4605 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4607 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4608 PATH_MAX
, nls_codepage
, remap
);
4609 name_len
++; /* trailing null */
4611 } else { /* BB improve the check for buffer overruns BB */
4612 name_len
= strnlen(fileName
, PATH_MAX
);
4613 name_len
++; /* trailing null */
4614 strncpy(pSMB
->FileName
, fileName
, name_len
);
4616 params
= 6 + name_len
;
4617 data_count
= sizeof(struct file_end_of_file_info
);
4618 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4619 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4620 pSMB
->MaxSetupCount
= 0;
4624 pSMB
->Reserved2
= 0;
4625 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4626 InformationLevel
) - 4;
4627 offset
= param_offset
+ params
;
4628 if (SetAllocation
) {
4629 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4630 pSMB
->InformationLevel
=
4631 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4633 pSMB
->InformationLevel
=
4634 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4635 } else /* Set File Size */ {
4636 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4637 pSMB
->InformationLevel
=
4638 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4640 pSMB
->InformationLevel
=
4641 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4645 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4647 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4648 pSMB
->DataOffset
= cpu_to_le16(offset
);
4649 pSMB
->SetupCount
= 1;
4650 pSMB
->Reserved3
= 0;
4651 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4652 byte_count
= 3 /* pad */ + params
+ data_count
;
4653 pSMB
->DataCount
= cpu_to_le16(data_count
);
4654 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4655 pSMB
->ParameterCount
= cpu_to_le16(params
);
4656 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4657 pSMB
->Reserved4
= 0;
4658 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4659 parm_data
->FileSize
= cpu_to_le64(size
);
4660 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4661 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4662 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4664 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4666 cifs_buf_release(pSMB
);
4675 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4676 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
4678 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4680 struct file_end_of_file_info
*parm_data
;
4682 __u16 params
, param_offset
, offset
, byte_count
, count
;
4684 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4686 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4691 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4692 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4695 pSMB
->MaxSetupCount
= 0;
4699 pSMB
->Reserved2
= 0;
4700 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4701 offset
= param_offset
+ params
;
4703 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4705 count
= sizeof(struct file_end_of_file_info
);
4706 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4707 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4708 pSMB
->SetupCount
= 1;
4709 pSMB
->Reserved3
= 0;
4710 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4711 byte_count
= 3 /* pad */ + params
+ count
;
4712 pSMB
->DataCount
= cpu_to_le16(count
);
4713 pSMB
->ParameterCount
= cpu_to_le16(params
);
4714 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4715 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4716 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4718 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4720 pSMB
->DataOffset
= cpu_to_le16(offset
);
4721 parm_data
->FileSize
= cpu_to_le64(size
);
4723 if (SetAllocation
) {
4724 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4725 pSMB
->InformationLevel
=
4726 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4728 pSMB
->InformationLevel
=
4729 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4730 } else /* Set File Size */ {
4731 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4732 pSMB
->InformationLevel
=
4733 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4735 pSMB
->InformationLevel
=
4736 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4738 pSMB
->Reserved4
= 0;
4739 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4740 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4741 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4744 ("Send error in SetFileInfo (SetFileSize) = %d",
4748 /* Note: On -EAGAIN error only caller can retry on handle based calls
4749 since file handle passed in no longer valid */
4754 /* Some legacy servers such as NT4 require that the file times be set on
4755 an open handle, rather than by pathname - this is awkward due to
4756 potential access conflicts on the open, but it is unavoidable for these
4757 old servers since the only other choice is to go from 100 nanosecond DCE
4758 time and resort to the original setpathinfo level which takes the ancient
4759 DOS time format with 2 second granularity */
4761 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
,
4762 const FILE_BASIC_INFO
*data
, __u16 fid
)
4764 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4767 __u16 params
, param_offset
, offset
, byte_count
, count
;
4769 cFYI(1, ("Set Times (via SetFileInfo)"));
4770 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4775 /* At this point there is no need to override the current pid
4776 with the pid of the opener, but that could change if we someday
4777 use an existing handle (rather than opening one on the fly) */
4778 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4779 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4782 pSMB
->MaxSetupCount
= 0;
4786 pSMB
->Reserved2
= 0;
4787 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4788 offset
= param_offset
+ params
;
4790 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4792 count
= sizeof(FILE_BASIC_INFO
);
4793 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4794 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4795 pSMB
->SetupCount
= 1;
4796 pSMB
->Reserved3
= 0;
4797 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4798 byte_count
= 3 /* pad */ + params
+ count
;
4799 pSMB
->DataCount
= cpu_to_le16(count
);
4800 pSMB
->ParameterCount
= cpu_to_le16(params
);
4801 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4802 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4803 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4804 pSMB
->DataOffset
= cpu_to_le16(offset
);
4806 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4807 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4809 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4810 pSMB
->Reserved4
= 0;
4811 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4812 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4813 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4814 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4816 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4818 /* Note: On -EAGAIN error only caller can retry on handle based calls
4819 since file handle passed in no longer valid */
4826 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4827 const FILE_BASIC_INFO
*data
,
4828 const struct nls_table
*nls_codepage
, int remap
)
4830 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4831 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4834 int bytes_returned
= 0;
4836 __u16 params
, param_offset
, offset
, byte_count
, count
;
4838 cFYI(1, ("In SetTimes"));
4841 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4846 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4848 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4849 PATH_MAX
, nls_codepage
, remap
);
4850 name_len
++; /* trailing null */
4852 } else { /* BB improve the check for buffer overruns BB */
4853 name_len
= strnlen(fileName
, PATH_MAX
);
4854 name_len
++; /* trailing null */
4855 strncpy(pSMB
->FileName
, fileName
, name_len
);
4858 params
= 6 + name_len
;
4859 count
= sizeof(FILE_BASIC_INFO
);
4860 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4861 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4862 pSMB
->MaxSetupCount
= 0;
4866 pSMB
->Reserved2
= 0;
4867 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4868 InformationLevel
) - 4;
4869 offset
= param_offset
+ params
;
4870 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4871 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4872 pSMB
->DataOffset
= cpu_to_le16(offset
);
4873 pSMB
->SetupCount
= 1;
4874 pSMB
->Reserved3
= 0;
4875 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4876 byte_count
= 3 /* pad */ + params
+ count
;
4878 pSMB
->DataCount
= cpu_to_le16(count
);
4879 pSMB
->ParameterCount
= cpu_to_le16(params
);
4880 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4881 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4882 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4883 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4885 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4886 pSMB
->Reserved4
= 0;
4887 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4888 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4889 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4890 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4891 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4893 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4895 cifs_buf_release(pSMB
);
4903 /* Can not be used to set time stamps yet (due to old DOS time format) */
4904 /* Can be used to set attributes */
4905 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4906 handling it anyway and NT4 was what we thought it would be needed for
4907 Do not delete it until we prove whether needed for Win9x though */
4909 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4910 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4912 SETATTR_REQ
*pSMB
= NULL
;
4913 SETATTR_RSP
*pSMBr
= NULL
;
4918 cFYI(1, ("In SetAttrLegacy"));
4921 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4926 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4928 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4929 PATH_MAX
, nls_codepage
);
4930 name_len
++; /* trailing null */
4932 } else { /* BB improve the check for buffer overruns BB */
4933 name_len
= strnlen(fileName
, PATH_MAX
);
4934 name_len
++; /* trailing null */
4935 strncpy(pSMB
->fileName
, fileName
, name_len
);
4937 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4938 pSMB
->BufferFormat
= 0x04;
4939 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4940 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4941 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4942 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4944 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4946 cifs_buf_release(pSMB
);
4949 goto SetAttrLgcyRetry
;
4953 #endif /* temporarily unneeded SetAttr legacy function */
4956 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4957 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4958 dev_t device
, const struct nls_table
*nls_codepage
,
4961 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4962 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4965 int bytes_returned
= 0;
4966 FILE_UNIX_BASIC_INFO
*data_offset
;
4967 __u16 params
, param_offset
, offset
, count
, byte_count
;
4969 cFYI(1, ("In SetUID/GID/Mode"));
4971 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4976 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4978 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4979 PATH_MAX
, nls_codepage
, remap
);
4980 name_len
++; /* trailing null */
4982 } else { /* BB improve the check for buffer overruns BB */
4983 name_len
= strnlen(fileName
, PATH_MAX
);
4984 name_len
++; /* trailing null */
4985 strncpy(pSMB
->FileName
, fileName
, name_len
);
4988 params
= 6 + name_len
;
4989 count
= sizeof(FILE_UNIX_BASIC_INFO
);
4990 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4991 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4992 pSMB
->MaxSetupCount
= 0;
4996 pSMB
->Reserved2
= 0;
4997 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4998 InformationLevel
) - 4;
4999 offset
= param_offset
+ params
;
5001 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5003 memset(data_offset
, 0, count
);
5004 pSMB
->DataOffset
= cpu_to_le16(offset
);
5005 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5006 pSMB
->SetupCount
= 1;
5007 pSMB
->Reserved3
= 0;
5008 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5009 byte_count
= 3 /* pad */ + params
+ count
;
5010 pSMB
->ParameterCount
= cpu_to_le16(params
);
5011 pSMB
->DataCount
= cpu_to_le16(count
);
5012 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5013 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5014 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5015 pSMB
->Reserved4
= 0;
5016 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5017 /* Samba server ignores set of file size to zero due to bugs in some
5018 older clients, but we should be precise - we use SetFileSize to
5019 set file size and do not want to truncate file size to zero
5020 accidently as happened on one Samba server beta by putting
5021 zero instead of -1 here */
5022 data_offset
->EndOfFile
= NO_CHANGE_64
;
5023 data_offset
->NumOfBytes
= NO_CHANGE_64
;
5024 data_offset
->LastStatusChange
= NO_CHANGE_64
;
5025 data_offset
->LastAccessTime
= NO_CHANGE_64
;
5026 data_offset
->LastModificationTime
= NO_CHANGE_64
;
5027 data_offset
->Uid
= cpu_to_le64(uid
);
5028 data_offset
->Gid
= cpu_to_le64(gid
);
5029 /* better to leave device as zero when it is */
5030 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
5031 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
5032 data_offset
->Permissions
= cpu_to_le64(mode
);
5035 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5036 else if (S_ISDIR(mode
))
5037 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5038 else if (S_ISLNK(mode
))
5039 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5040 else if (S_ISCHR(mode
))
5041 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5042 else if (S_ISBLK(mode
))
5043 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5044 else if (S_ISFIFO(mode
))
5045 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5046 else if (S_ISSOCK(mode
))
5047 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5050 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5051 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5052 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5054 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5057 cifs_buf_release(pSMB
);
5063 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5064 const int notify_subdirs
, const __u16 netfid
,
5065 __u32 filter
, struct file
*pfile
, int multishot
,
5066 const struct nls_table
*nls_codepage
)
5069 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5070 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5071 struct dir_notify_req
*dnotify_req
;
5074 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5075 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5080 pSMB
->TotalParameterCount
= 0 ;
5081 pSMB
->TotalDataCount
= 0;
5082 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5083 /* BB find exact data count max from sess structure BB */
5084 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5085 /* BB VERIFY verify which is correct for above BB */
5086 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5087 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5089 pSMB
->MaxSetupCount
= 4;
5091 pSMB
->ParameterOffset
= 0;
5092 pSMB
->DataCount
= 0;
5093 pSMB
->DataOffset
= 0;
5094 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5095 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5096 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5098 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5099 pSMB
->Reserved2
= 0;
5100 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5101 pSMB
->Fid
= netfid
; /* file handle always le */
5102 pSMB
->ByteCount
= 0;
5104 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5105 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5108 cFYI(1, ("Error in Notify = %d", rc
));
5110 /* Add file to outstanding requests */
5111 /* BB change to kmem cache alloc */
5112 dnotify_req
= kmalloc(
5113 sizeof(struct dir_notify_req
),
5116 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5117 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5118 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5119 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5120 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5121 dnotify_req
->netfid
= netfid
;
5122 dnotify_req
->pfile
= pfile
;
5123 dnotify_req
->filter
= filter
;
5124 dnotify_req
->multishot
= multishot
;
5125 spin_lock(&GlobalMid_Lock
);
5126 list_add_tail(&dnotify_req
->lhead
,
5127 &GlobalDnotifyReqList
);
5128 spin_unlock(&GlobalMid_Lock
);
5132 cifs_buf_release(pSMB
);
5135 #ifdef CONFIG_CIFS_XATTR
5137 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5138 const unsigned char *searchName
,
5139 char *EAData
, size_t buf_size
,
5140 const struct nls_table
*nls_codepage
, int remap
)
5142 /* BB assumes one setup word */
5143 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5144 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5148 struct fea
*temp_fea
;
5150 __u16 params
, byte_count
;
5152 cFYI(1, ("In Query All EAs path %s", searchName
));
5154 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5159 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5161 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5162 PATH_MAX
, nls_codepage
, remap
);
5163 name_len
++; /* trailing null */
5165 } else { /* BB improve the check for buffer overruns BB */
5166 name_len
= strnlen(searchName
, PATH_MAX
);
5167 name_len
++; /* trailing null */
5168 strncpy(pSMB
->FileName
, searchName
, name_len
);
5171 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5172 pSMB
->TotalDataCount
= 0;
5173 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5174 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5175 pSMB
->MaxSetupCount
= 0;
5179 pSMB
->Reserved2
= 0;
5180 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5181 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5182 pSMB
->DataCount
= 0;
5183 pSMB
->DataOffset
= 0;
5184 pSMB
->SetupCount
= 1;
5185 pSMB
->Reserved3
= 0;
5186 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5187 byte_count
= params
+ 1 /* pad */ ;
5188 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5189 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5190 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5191 pSMB
->Reserved4
= 0;
5192 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5193 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5195 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5196 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5198 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5199 } else { /* decode response */
5200 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5202 /* BB also check enough total bytes returned */
5203 /* BB we need to improve the validity checking
5204 of these trans2 responses */
5205 if (rc
|| (pSMBr
->ByteCount
< 4))
5206 rc
= -EIO
; /* bad smb */
5207 /* else if (pFindData){
5208 memcpy((char *) pFindData,
5209 (char *) &pSMBr->hdr.Protocol +
5212 /* check that length of list is not more than bcc */
5213 /* check that each entry does not go beyond length
5215 /* check that each element of each entry does not
5216 go beyond end of list */
5217 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5218 struct fealist
*ea_response_data
;
5220 /* validate_trans2_offsets() */
5221 /* BB check if start of smb + data_offset > &bcc+ bcc */
5222 ea_response_data
= (struct fealist
*)
5223 (((char *) &pSMBr
->hdr
.Protocol
) +
5225 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5226 cFYI(1, ("ea length %d", name_len
));
5227 if (name_len
<= 8) {
5228 /* returned EA size zeroed at top of function */
5229 cFYI(1, ("empty EA list returned from server"));
5231 /* account for ea list len */
5233 temp_fea
= ea_response_data
->list
;
5234 temp_ptr
= (char *)temp_fea
;
5235 while (name_len
> 0) {
5239 rc
+= temp_fea
->name_len
;
5240 /* account for prefix user. and trailing null */
5242 if (rc
< (int)buf_size
) {
5243 memcpy(EAData
, "user.", 5);
5245 memcpy(EAData
, temp_ptr
,
5246 temp_fea
->name_len
);
5247 EAData
+= temp_fea
->name_len
;
5248 /* null terminate name */
5250 EAData
= EAData
+ 1;
5251 } else if (buf_size
== 0) {
5252 /* skip copy - calc size only */
5254 /* stop before overrun buffer */
5258 name_len
-= temp_fea
->name_len
;
5259 temp_ptr
+= temp_fea
->name_len
;
5260 /* account for trailing null */
5264 le16_to_cpu(temp_fea
->value_len
);
5265 name_len
-= value_len
;
5266 temp_ptr
+= value_len
;
5267 /* BB check that temp_ptr is still
5270 /* no trailing null to account for
5272 /* go on to next EA */
5273 temp_fea
= (struct fea
*)temp_ptr
;
5279 cifs_buf_release(pSMB
);
5286 ssize_t
CIFSSMBQueryEA(const int xid
, struct cifsTconInfo
*tcon
,
5287 const unsigned char *searchName
, const unsigned char *ea_name
,
5288 unsigned char *ea_value
, size_t buf_size
,
5289 const struct nls_table
*nls_codepage
, int remap
)
5291 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5292 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5296 struct fea
*temp_fea
;
5298 __u16 params
, byte_count
;
5300 cFYI(1, ("In Query EA path %s", searchName
));
5302 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5307 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5309 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5310 PATH_MAX
, nls_codepage
, remap
);
5311 name_len
++; /* trailing null */
5313 } else { /* BB improve the check for buffer overruns BB */
5314 name_len
= strnlen(searchName
, PATH_MAX
);
5315 name_len
++; /* trailing null */
5316 strncpy(pSMB
->FileName
, searchName
, name_len
);
5319 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5320 pSMB
->TotalDataCount
= 0;
5321 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5322 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5323 pSMB
->MaxSetupCount
= 0;
5327 pSMB
->Reserved2
= 0;
5328 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5329 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5330 pSMB
->DataCount
= 0;
5331 pSMB
->DataOffset
= 0;
5332 pSMB
->SetupCount
= 1;
5333 pSMB
->Reserved3
= 0;
5334 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5335 byte_count
= params
+ 1 /* pad */ ;
5336 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5337 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5338 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5339 pSMB
->Reserved4
= 0;
5340 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5341 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5343 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5344 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5346 cFYI(1, ("Send error in Query EA = %d", rc
));
5347 } else { /* decode response */
5348 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5350 /* BB also check enough total bytes returned */
5351 /* BB we need to improve the validity checking
5352 of these trans2 responses */
5353 if (rc
|| (pSMBr
->ByteCount
< 4))
5354 rc
= -EIO
; /* bad smb */
5355 /* else if (pFindData){
5356 memcpy((char *) pFindData,
5357 (char *) &pSMBr->hdr.Protocol +
5360 /* check that length of list is not more than bcc */
5361 /* check that each entry does not go beyond length
5363 /* check that each element of each entry does not
5364 go beyond end of list */
5365 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5366 struct fealist
*ea_response_data
;
5368 /* validate_trans2_offsets() */
5369 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5370 ea_response_data
= (struct fealist
*)
5371 (((char *) &pSMBr
->hdr
.Protocol
) +
5373 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5374 cFYI(1, ("ea length %d", name_len
));
5375 if (name_len
<= 8) {
5376 /* returned EA size zeroed at top of function */
5377 cFYI(1, ("empty EA list returned from server"));
5379 /* account for ea list len */
5381 temp_fea
= ea_response_data
->list
;
5382 temp_ptr
= (char *)temp_fea
;
5383 /* loop through checking if we have a matching
5384 name and then return the associated value */
5385 while (name_len
> 0) {
5390 le16_to_cpu(temp_fea
->value_len
);
5391 /* BB validate that value_len falls within SMB,
5392 even though maximum for name_len is 255 */
5393 if (memcmp(temp_fea
->name
, ea_name
,
5394 temp_fea
->name_len
) == 0) {
5397 /* account for prefix user. and trailing null */
5398 if (rc
<= (int)buf_size
) {
5400 temp_fea
->name
+temp_fea
->name_len
+1,
5402 /* ea values, unlike ea
5405 } else if (buf_size
== 0) {
5406 /* skip copy - calc size only */
5408 /* stop before overrun buffer */
5413 name_len
-= temp_fea
->name_len
;
5414 temp_ptr
+= temp_fea
->name_len
;
5415 /* account for trailing null */
5418 name_len
-= value_len
;
5419 temp_ptr
+= value_len
;
5420 /* No trailing null to account for in
5421 value_len. Go on to next EA */
5422 temp_fea
= (struct fea
*)temp_ptr
;
5428 cifs_buf_release(pSMB
);
5436 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5437 const char *ea_name
, const void *ea_value
,
5438 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5441 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5442 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5443 struct fealist
*parm_data
;
5446 int bytes_returned
= 0;
5447 __u16 params
, param_offset
, byte_count
, offset
, count
;
5449 cFYI(1, ("In SetEA"));
5451 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5456 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5458 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5459 PATH_MAX
, nls_codepage
, remap
);
5460 name_len
++; /* trailing null */
5462 } else { /* BB improve the check for buffer overruns BB */
5463 name_len
= strnlen(fileName
, PATH_MAX
);
5464 name_len
++; /* trailing null */
5465 strncpy(pSMB
->FileName
, fileName
, name_len
);
5468 params
= 6 + name_len
;
5470 /* done calculating parms using name_len of file name,
5471 now use name_len to calculate length of ea name
5472 we are going to create in the inode xattrs */
5473 if (ea_name
== NULL
)
5476 name_len
= strnlen(ea_name
, 255);
5478 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5479 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5480 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
5481 pSMB
->MaxSetupCount
= 0;
5485 pSMB
->Reserved2
= 0;
5486 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5487 InformationLevel
) - 4;
5488 offset
= param_offset
+ params
;
5489 pSMB
->InformationLevel
=
5490 cpu_to_le16(SMB_SET_FILE_EA
);
5493 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5495 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5496 pSMB
->DataOffset
= cpu_to_le16(offset
);
5497 pSMB
->SetupCount
= 1;
5498 pSMB
->Reserved3
= 0;
5499 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5500 byte_count
= 3 /* pad */ + params
+ count
;
5501 pSMB
->DataCount
= cpu_to_le16(count
);
5502 parm_data
->list_len
= cpu_to_le32(count
);
5503 parm_data
->list
[0].EA_flags
= 0;
5504 /* we checked above that name len is less than 255 */
5505 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5506 /* EA names are always ASCII */
5508 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5509 parm_data
->list
[0].name
[name_len
] = 0;
5510 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5511 /* caller ensures that ea_value_len is less than 64K but
5512 we need to ensure that it fits within the smb */
5514 /*BB add length check to see if it would fit in
5515 negotiated SMB buffer size BB */
5516 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5518 memcpy(parm_data
->list
[0].name
+name_len
+1,
5519 ea_value
, ea_value_len
);
5521 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5522 pSMB
->ParameterCount
= cpu_to_le16(params
);
5523 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5524 pSMB
->Reserved4
= 0;
5525 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5526 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5527 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5528 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5530 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5532 cifs_buf_release(pSMB
);