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 */
84 /* Allocates buffer into dst and copies smb string from src to it.
85 * caller is responsible for freeing dst if function returned 0.
91 cifs_strncpy_to_host(char **dst
, const char *src
, const int maxlen
,
92 const bool is_unicode
, const struct nls_table
*nls_codepage
)
97 plen
= UniStrnlen((wchar_t *)src
, maxlen
);
98 *dst
= kmalloc(plen
+ 2, GFP_KERNEL
);
100 goto cifs_strncpy_to_host_ErrExit
;
101 cifs_strfromUCS_le(*dst
, (__le16
*)src
, plen
, nls_codepage
);
103 plen
= strnlen(src
, maxlen
);
104 *dst
= kmalloc(plen
+ 2, GFP_KERNEL
);
106 goto cifs_strncpy_to_host_ErrExit
;
107 strncpy(*dst
, src
, plen
);
112 cifs_strncpy_to_host_ErrExit
:
113 cERROR(1, ("Failed to allocate buffer for string\n"));
118 /* Mark as invalid, all open files on tree connections since they
119 were closed when session to server was lost */
120 static void mark_open_files_invalid(struct cifsTconInfo
*pTcon
)
122 struct cifsFileInfo
*open_file
= NULL
;
123 struct list_head
*tmp
;
124 struct list_head
*tmp1
;
126 /* list all files open on tree connection and mark them invalid */
127 write_lock(&GlobalSMBSeslock
);
128 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
129 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
131 open_file
->invalidHandle
= true;
133 write_unlock(&GlobalSMBSeslock
);
134 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
138 /* Allocate and return pointer to an SMB request buffer, and set basic
139 SMB information in the SMB header. If the return code is zero, this
140 function must have filled in request_buf pointer */
142 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
147 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
148 check for tcp and smb session status done differently
149 for those three - in the calling routine */
151 if (tcon
->tidStatus
== CifsExiting
) {
152 /* only tree disconnect, open, and write,
153 (and ulogoff which does not have tcon)
154 are allowed as we start force umount */
155 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
156 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
157 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
158 cFYI(1, ("can not send cmd %d while umounting",
163 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
164 (tcon
->ses
->server
)) {
165 struct nls_table
*nls_codepage
;
166 /* Give Demultiplex thread up to 10 seconds to
167 reconnect, should be greater than cifs socket
168 timeout which is 7 seconds */
169 while (tcon
->ses
->server
->tcpStatus
==
171 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
172 (tcon
->ses
->server
->tcpStatus
==
174 if (tcon
->ses
->server
->tcpStatus
==
176 /* on "soft" mounts we wait once */
178 (tcon
->ses
->status
== CifsExiting
)) {
179 cFYI(1, ("gave up waiting on "
180 "reconnect in smb_init"));
182 } /* else "hard" mount - keep retrying
183 until process is killed or server
184 comes back on-line */
185 } else /* TCP session is reestablished now */
189 nls_codepage
= load_nls_default();
190 /* need to prevent multiple threads trying to
191 simultaneously reconnect the same SMB session */
192 down(&tcon
->ses
->sesSem
);
193 if (tcon
->ses
->status
== CifsNeedReconnect
)
194 rc
= cifs_setup_session(0, tcon
->ses
,
196 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
197 mark_open_files_invalid(tcon
);
198 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
200 up(&tcon
->ses
->sesSem
);
201 /* BB FIXME add code to check if wsize needs
202 update due to negotiated smb buffer size
205 atomic_inc(&tconInfoReconnectCount
);
206 /* tell server Unix caps we support */
207 if (tcon
->ses
->capabilities
& CAP_UNIX
)
208 reset_cifs_unix_caps(
211 NULL
/* we do not know sb */,
212 NULL
/* no vol info */);
215 cFYI(1, ("reconnect tcon rc = %d", rc
));
216 /* Removed call to reopen open files here.
217 It is safer (and faster) to reopen files
218 one at a time as needed in read and write */
220 /* Check if handle based operation so we
221 know whether we can continue or not without
222 returning to caller to reset file handle */
223 switch (smb_command
) {
224 case SMB_COM_READ_ANDX
:
225 case SMB_COM_WRITE_ANDX
:
227 case SMB_COM_FIND_CLOSE2
:
228 case SMB_COM_LOCKING_ANDX
: {
229 unload_nls(nls_codepage
);
234 up(&tcon
->ses
->sesSem
);
236 unload_nls(nls_codepage
);
245 *request_buf
= cifs_small_buf_get();
246 if (*request_buf
== NULL
) {
247 /* BB should we add a retry in here if not a writepage? */
251 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
255 cifs_stats_inc(&tcon
->num_smbs_sent
);
261 small_smb_init_no_tc(const int smb_command
, const int wct
,
262 struct cifsSesInfo
*ses
, void **request_buf
)
265 struct smb_hdr
*buffer
;
267 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
271 buffer
= (struct smb_hdr
*)*request_buf
;
272 buffer
->Mid
= GetNextMid(ses
->server
);
273 if (ses
->capabilities
& CAP_UNICODE
)
274 buffer
->Flags2
|= SMBFLG2_UNICODE
;
275 if (ses
->capabilities
& CAP_STATUS32
)
276 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
278 /* uid, tid can stay at zero as set in header assemble */
280 /* BB add support for turning on the signing when
281 this function is used after 1st of session setup requests */
286 /* If the return code is zero, this function must fill in request_buf pointer */
288 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
289 void **request_buf
/* returned */ ,
290 void **response_buf
/* returned */ )
294 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
295 check for tcp and smb session status done differently
296 for those three - in the calling routine */
298 if (tcon
->tidStatus
== CifsExiting
) {
299 /* only tree disconnect, open, and write,
300 (and ulogoff which does not have tcon)
301 are allowed as we start force umount */
302 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
303 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
304 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
305 cFYI(1, ("can not send cmd %d while umounting",
311 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
312 (tcon
->ses
->server
)) {
313 struct nls_table
*nls_codepage
;
314 /* Give Demultiplex thread up to 10 seconds to
315 reconnect, should be greater than cifs socket
316 timeout which is 7 seconds */
317 while (tcon
->ses
->server
->tcpStatus
==
319 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
320 (tcon
->ses
->server
->tcpStatus
==
322 if (tcon
->ses
->server
->tcpStatus
==
324 /* on "soft" mounts we wait once */
326 (tcon
->ses
->status
== CifsExiting
)) {
327 cFYI(1, ("gave up waiting on "
328 "reconnect in smb_init"));
330 } /* else "hard" mount - keep retrying
331 until process is killed or server
333 } else /* TCP session is reestablished now */
336 nls_codepage
= load_nls_default();
337 /* need to prevent multiple threads trying to
338 simultaneously reconnect the same SMB session */
339 down(&tcon
->ses
->sesSem
);
340 if (tcon
->ses
->status
== CifsNeedReconnect
)
341 rc
= cifs_setup_session(0, tcon
->ses
,
343 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
344 mark_open_files_invalid(tcon
);
345 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
347 up(&tcon
->ses
->sesSem
);
348 /* BB FIXME add code to check if wsize needs
349 update due to negotiated smb buffer size
352 atomic_inc(&tconInfoReconnectCount
);
353 /* tell server Unix caps we support */
354 if (tcon
->ses
->capabilities
& CAP_UNIX
)
355 reset_cifs_unix_caps(
358 NULL
/* do not know sb */,
359 NULL
/* no vol info */);
362 cFYI(1, ("reconnect tcon rc = %d", rc
));
363 /* Removed call to reopen open files here.
364 It is safer (and faster) to reopen files
365 one at a time as needed in read and write */
367 /* Check if handle based operation so we
368 know whether we can continue or not without
369 returning to caller to reset file handle */
370 switch (smb_command
) {
371 case SMB_COM_READ_ANDX
:
372 case SMB_COM_WRITE_ANDX
:
374 case SMB_COM_FIND_CLOSE2
:
375 case SMB_COM_LOCKING_ANDX
: {
376 unload_nls(nls_codepage
);
381 up(&tcon
->ses
->sesSem
);
383 unload_nls(nls_codepage
);
392 *request_buf
= cifs_buf_get();
393 if (*request_buf
== NULL
) {
394 /* BB should we add a retry in here if not a writepage? */
397 /* Although the original thought was we needed the response buf for */
398 /* potential retries of smb operations it turns out we can determine */
399 /* from the mid flags when the request buffer can be resent without */
400 /* having to use a second distinct buffer for the response */
402 *response_buf
= *request_buf
;
404 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
408 cifs_stats_inc(&tcon
->num_smbs_sent
);
413 static int validate_t2(struct smb_t2_rsp
*pSMB
)
419 /* check for plausible wct, bcc and t2 data and parm sizes */
420 /* check for parm and data offset going beyond end of smb */
421 if (pSMB
->hdr
.WordCount
>= 10) {
422 if ((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
423 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
424 /* check that bcc is at least as big as parms + data */
425 /* check that bcc is less than negotiated smb buffer */
426 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
427 if (total_size
< 512) {
429 le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
430 /* BCC le converted in SendReceive */
431 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
432 sizeof(struct smb_hdr
) +
434 if ((total_size
<= (*(u16
*)pBCC
)) &&
436 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
442 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
443 sizeof(struct smb_t2_rsp
) + 16);
447 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
450 NEGOTIATE_RSP
*pSMBr
;
454 struct TCP_Server_Info
*server
;
456 unsigned int secFlags
;
460 server
= ses
->server
;
465 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
466 (void **) &pSMB
, (void **) &pSMBr
);
470 /* if any of auth flags (ie not sign or seal) are overriden use them */
471 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
472 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
473 else /* if override flags set only sign/seal OR them with global auth */
474 secFlags
= extended_security
| ses
->overrideSecFlg
;
476 cFYI(1, ("secFlags 0x%x", secFlags
));
478 pSMB
->hdr
.Mid
= GetNextMid(server
);
479 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
481 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
482 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
483 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
484 cFYI(1, ("Kerberos only mechanism, enable extended security"));
485 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
489 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
490 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
491 count
+= strlen(protocols
[i
].name
) + 1;
492 /* null at end of source and target buffers anyway */
494 pSMB
->hdr
.smb_buf_length
+= count
;
495 pSMB
->ByteCount
= cpu_to_le16(count
);
497 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
498 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
502 dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
503 cFYI(1, ("Dialect: %d", dialect
));
504 /* Check wct = 1 error case */
505 if ((pSMBr
->hdr
.WordCount
< 13) || (dialect
== BAD_PROT
)) {
506 /* core returns wct = 1, but we do not ask for core - otherwise
507 small wct just comes when dialect index is -1 indicating we
508 could not negotiate a common dialect */
511 #ifdef CONFIG_CIFS_WEAK_PW_HASH
512 } else if ((pSMBr
->hdr
.WordCount
== 13)
513 && ((dialect
== LANMAN_PROT
)
514 || (dialect
== LANMAN2_PROT
))) {
516 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
518 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
519 (secFlags
& CIFSSEC_MAY_PLNTXT
))
520 server
->secType
= LANMAN
;
522 cERROR(1, ("mount failed weak security disabled"
523 " in /proc/fs/cifs/SecurityFlags"));
527 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
528 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
529 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
530 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
531 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
532 /* even though we do not use raw we might as well set this
533 accurately, in case we ever find a need for it */
534 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
535 server
->maxRw
= 0xFF00;
536 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
538 server
->maxRw
= 0;/* we do not need to use raw anyway */
539 server
->capabilities
= CAP_MPX_MODE
;
541 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
543 /* OS/2 often does not set timezone therefore
544 * we must use server time to calc time zone.
545 * Could deviate slightly from the right zone.
546 * Smallest defined timezone difference is 15 minutes
547 * (i.e. Nepal). Rounding up/down is done to match
550 int val
, seconds
, remain
, result
;
551 struct timespec ts
, utc
;
553 ts
= cnvrtDosUnixTm(le16_to_cpu(rsp
->SrvTime
.Date
),
554 le16_to_cpu(rsp
->SrvTime
.Time
));
555 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
556 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
557 (int)(utc
.tv_sec
- ts
.tv_sec
)));
558 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
560 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
561 remain
= seconds
% MIN_TZ_ADJ
;
562 if (remain
>= (MIN_TZ_ADJ
/ 2))
563 result
+= MIN_TZ_ADJ
;
566 server
->timeAdj
= result
;
568 server
->timeAdj
= (int)tmp
;
569 server
->timeAdj
*= 60; /* also in seconds */
571 cFYI(1, ("server->timeAdj: %d seconds", server
->timeAdj
));
574 /* BB get server time for time conversions and add
575 code to use it and timezone since this is not UTC */
577 if (rsp
->EncryptionKeyLength
==
578 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
579 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
580 CIFS_CRYPTO_KEY_SIZE
);
581 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
582 rc
= -EIO
; /* need cryptkey unless plain text */
586 cFYI(1, ("LANMAN negotiated"));
587 /* we will not end up setting signing flags - as no signing
588 was in LANMAN and server did not return the flags on */
590 #else /* weak security disabled */
591 } else if (pSMBr
->hdr
.WordCount
== 13) {
592 cERROR(1, ("mount failed, cifs module not built "
593 "with CIFS_WEAK_PW_HASH support"));
595 #endif /* WEAK_PW_HASH */
597 } else if (pSMBr
->hdr
.WordCount
!= 17) {
602 /* else wct == 17 NTLM */
603 server
->secMode
= pSMBr
->SecurityMode
;
604 if ((server
->secMode
& SECMODE_USER
) == 0)
605 cFYI(1, ("share mode security"));
607 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
608 #ifdef CONFIG_CIFS_WEAK_PW_HASH
609 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
610 #endif /* CIFS_WEAK_PW_HASH */
611 cERROR(1, ("Server requests plain text password"
612 " but client support disabled"));
614 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
615 server
->secType
= NTLMv2
;
616 else if (secFlags
& CIFSSEC_MAY_NTLM
)
617 server
->secType
= NTLM
;
618 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
619 server
->secType
= NTLMv2
;
620 else if (secFlags
& CIFSSEC_MAY_KRB5
)
621 server
->secType
= Kerberos
;
622 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
623 server
->secType
= LANMAN
;
624 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
625 else if (secFlags & CIFSSEC_MAY_PLNTXT)
630 cERROR(1, ("Invalid security type"));
633 /* else ... any others ...? */
635 /* one byte, so no need to convert this or EncryptionKeyLen from
637 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
638 /* probably no need to store and check maxvcs */
639 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
640 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
641 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
642 cFYI(DBG2
, ("Max buf = %d", ses
->server
->maxBuf
));
643 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
644 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
645 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
646 server
->timeAdj
*= 60;
647 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
648 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
649 CIFS_CRYPTO_KEY_SIZE
);
650 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
651 && (pSMBr
->EncryptionKeyLength
== 0)) {
652 /* decode security blob */
653 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
654 rc
= -EIO
; /* no crypt key only if plain text pwd */
658 /* BB might be helpful to save off the domain of server here */
660 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
661 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
662 count
= pSMBr
->ByteCount
;
668 if (server
->socketUseCount
.counter
> 1) {
669 if (memcmp(server
->server_GUID
,
670 pSMBr
->u
.extended_response
.
672 cFYI(1, ("server UID changed"));
673 memcpy(server
->server_GUID
,
674 pSMBr
->u
.extended_response
.GUID
,
678 memcpy(server
->server_GUID
,
679 pSMBr
->u
.extended_response
.GUID
, 16);
682 server
->secType
= RawNTLMSSP
;
684 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
695 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
697 #ifdef CONFIG_CIFS_WEAK_PW_HASH
700 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
701 /* MUST_SIGN already includes the MAY_SIGN FLAG
702 so if this is zero it means that signing is disabled */
703 cFYI(1, ("Signing disabled"));
704 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
705 cERROR(1, ("Server requires "
706 "packet signing to be enabled in "
707 "/proc/fs/cifs/SecurityFlags."));
711 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
712 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
713 /* signing required */
714 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
715 if ((server
->secMode
&
716 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
718 ("signing required but server lacks support"));
721 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
723 /* signing optional ie CIFSSEC_MAY_SIGN */
724 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
726 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
730 cifs_buf_release(pSMB
);
732 cFYI(1, ("negprot rc %d", rc
));
737 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
739 struct smb_hdr
*smb_buffer
;
742 cFYI(1, ("In tree disconnect"));
744 * If last user of the connection and
745 * connection alive - disconnect it
746 * If this is the last connection on the server session disconnect it
747 * (and inside session disconnect we should check if tcp socket needs
748 * to be freed and kernel thread woken up).
751 down(&tcon
->tconSem
);
755 atomic_dec(&tcon
->useCount
);
756 if (atomic_read(&tcon
->useCount
) > 0) {
761 /* No need to return error on this operation if tid invalidated and
762 closed on server already e.g. due to tcp session crashing */
763 if (tcon
->tidStatus
== CifsNeedReconnect
) {
768 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
772 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
773 (void **)&smb_buffer
);
779 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
781 cFYI(1, ("Tree disconnect failed %d", rc
));
785 /* No need to return error on this operation if tid invalidated and
786 closed on server already e.g. due to tcp session crashing */
794 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
796 LOGOFF_ANDX_REQ
*pSMB
;
799 cFYI(1, ("In SMBLogoff for session disconnect"));
805 atomic_dec(&ses
->inUse
);
806 if (atomic_read(&ses
->inUse
) > 0) {
810 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
817 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
819 if (ses
->server
->secMode
&
820 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
821 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
824 pSMB
->hdr
.Uid
= ses
->Suid
;
826 pSMB
->AndXCommand
= 0xFF;
827 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
829 atomic_dec(&ses
->server
->socketUseCount
);
830 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
831 spin_lock(&GlobalMid_Lock
);
832 ses
->server
->tcpStatus
= CifsExiting
;
833 spin_unlock(&GlobalMid_Lock
);
839 /* if session dead then we do not need to do ulogoff,
840 since server closed smb session, no sense reporting
848 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
849 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
851 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
852 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
853 struct unlink_psx_rq
*pRqD
;
856 int bytes_returned
= 0;
857 __u16 params
, param_offset
, offset
, byte_count
;
859 cFYI(1, ("In POSIX delete"));
861 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
866 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
868 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
869 PATH_MAX
, nls_codepage
, remap
);
870 name_len
++; /* trailing null */
872 } else { /* BB add path length overrun check */
873 name_len
= strnlen(fileName
, PATH_MAX
);
874 name_len
++; /* trailing null */
875 strncpy(pSMB
->FileName
, fileName
, name_len
);
878 params
= 6 + name_len
;
879 pSMB
->MaxParameterCount
= cpu_to_le16(2);
880 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
881 pSMB
->MaxSetupCount
= 0;
886 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
887 InformationLevel
) - 4;
888 offset
= param_offset
+ params
;
890 /* Setup pointer to Request Data (inode type) */
891 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
892 pRqD
->type
= cpu_to_le16(type
);
893 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
894 pSMB
->DataOffset
= cpu_to_le16(offset
);
895 pSMB
->SetupCount
= 1;
897 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
898 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
900 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
901 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
902 pSMB
->ParameterCount
= cpu_to_le16(params
);
903 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
904 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
906 pSMB
->hdr
.smb_buf_length
+= byte_count
;
907 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
908 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
909 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
911 cFYI(1, ("Posix delete returned %d", rc
));
912 cifs_buf_release(pSMB
);
914 cifs_stats_inc(&tcon
->num_deletes
);
923 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
924 const struct nls_table
*nls_codepage
, int remap
)
926 DELETE_FILE_REQ
*pSMB
= NULL
;
927 DELETE_FILE_RSP
*pSMBr
= NULL
;
933 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
938 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
940 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
941 PATH_MAX
, nls_codepage
, remap
);
942 name_len
++; /* trailing null */
944 } else { /* BB improve check for buffer overruns BB */
945 name_len
= strnlen(fileName
, PATH_MAX
);
946 name_len
++; /* trailing null */
947 strncpy(pSMB
->fileName
, fileName
, name_len
);
949 pSMB
->SearchAttributes
=
950 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
951 pSMB
->BufferFormat
= 0x04;
952 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
953 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
954 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
955 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
956 cifs_stats_inc(&tcon
->num_deletes
);
958 cFYI(1, ("Error in RMFile = %d", rc
));
960 cifs_buf_release(pSMB
);
968 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
969 const struct nls_table
*nls_codepage
, int remap
)
971 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
972 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
977 cFYI(1, ("In CIFSSMBRmDir"));
979 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
984 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
985 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
986 PATH_MAX
, nls_codepage
, remap
);
987 name_len
++; /* trailing null */
989 } else { /* BB improve check for buffer overruns BB */
990 name_len
= strnlen(dirName
, PATH_MAX
);
991 name_len
++; /* trailing null */
992 strncpy(pSMB
->DirName
, dirName
, name_len
);
995 pSMB
->BufferFormat
= 0x04;
996 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
997 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
998 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
999 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1000 cifs_stats_inc(&tcon
->num_rmdirs
);
1002 cFYI(1, ("Error in RMDir = %d", rc
));
1004 cifs_buf_release(pSMB
);
1011 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
1012 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
1015 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
1016 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
1020 cFYI(1, ("In CIFSSMBMkDir"));
1022 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
1027 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1028 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
1029 PATH_MAX
, nls_codepage
, remap
);
1030 name_len
++; /* trailing null */
1032 } else { /* BB improve check for buffer overruns BB */
1033 name_len
= strnlen(name
, PATH_MAX
);
1034 name_len
++; /* trailing null */
1035 strncpy(pSMB
->DirName
, name
, name_len
);
1038 pSMB
->BufferFormat
= 0x04;
1039 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
1040 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
1041 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1042 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1043 cifs_stats_inc(&tcon
->num_mkdirs
);
1045 cFYI(1, ("Error in Mkdir = %d", rc
));
1047 cifs_buf_release(pSMB
);
1054 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1055 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1056 __u32
*pOplock
, const char *name
,
1057 const struct nls_table
*nls_codepage
, int remap
)
1059 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1060 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1063 int bytes_returned
= 0;
1064 __u16 params
, param_offset
, offset
, byte_count
, count
;
1065 OPEN_PSX_REQ
*pdata
;
1066 OPEN_PSX_RSP
*psx_rsp
;
1068 cFYI(1, ("In POSIX Create"));
1070 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1075 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1077 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1078 PATH_MAX
, nls_codepage
, remap
);
1079 name_len
++; /* trailing null */
1081 } else { /* BB improve the check for buffer overruns BB */
1082 name_len
= strnlen(name
, PATH_MAX
);
1083 name_len
++; /* trailing null */
1084 strncpy(pSMB
->FileName
, name
, name_len
);
1087 params
= 6 + name_len
;
1088 count
= sizeof(OPEN_PSX_REQ
);
1089 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1090 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1091 pSMB
->MaxSetupCount
= 0;
1095 pSMB
->Reserved2
= 0;
1096 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1097 InformationLevel
) - 4;
1098 offset
= param_offset
+ params
;
1099 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1100 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1101 pdata
->Permissions
= cpu_to_le64(mode
);
1102 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1103 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1104 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1105 pSMB
->DataOffset
= cpu_to_le16(offset
);
1106 pSMB
->SetupCount
= 1;
1107 pSMB
->Reserved3
= 0;
1108 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1109 byte_count
= 3 /* pad */ + params
+ count
;
1111 pSMB
->DataCount
= cpu_to_le16(count
);
1112 pSMB
->ParameterCount
= cpu_to_le16(params
);
1113 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1114 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1115 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1116 pSMB
->Reserved4
= 0;
1117 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1118 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1119 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1120 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1122 cFYI(1, ("Posix create returned %d", rc
));
1123 goto psx_create_err
;
1126 cFYI(1, ("copying inode info"));
1127 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1129 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1130 rc
= -EIO
; /* bad smb */
1131 goto psx_create_err
;
1134 /* copy return information to pRetData */
1135 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1136 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1138 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1140 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1141 /* Let caller know file was created so we can set the mode. */
1142 /* Do we care about the CreateAction in any other cases? */
1143 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1144 *pOplock
|= CIFS_CREATE_ACTION
;
1145 /* check to make sure response data is there */
1146 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1147 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1148 cFYI(DBG2
, ("unknown type"));
1150 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1151 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1152 cERROR(1, ("Open response data too small"));
1153 pRetData
->Type
= cpu_to_le32(-1);
1154 goto psx_create_err
;
1156 memcpy((char *) pRetData
,
1157 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1158 sizeof(FILE_UNIX_BASIC_INFO
));
1162 cifs_buf_release(pSMB
);
1164 cifs_stats_inc(&tcon
->num_mkdirs
);
1172 static __u16
convert_disposition(int disposition
)
1176 switch (disposition
) {
1177 case FILE_SUPERSEDE
:
1178 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1181 ofun
= SMBOPEN_OAPPEND
;
1184 ofun
= SMBOPEN_OCREATE
;
1187 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1189 case FILE_OVERWRITE
:
1190 ofun
= SMBOPEN_OTRUNC
;
1192 case FILE_OVERWRITE_IF
:
1193 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1196 cFYI(1, ("unknown disposition %d", disposition
));
1197 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1203 access_flags_to_smbopen_mode(const int access_flags
)
1205 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1207 if (masked_flags
== GENERIC_READ
)
1208 return SMBOPEN_READ
;
1209 else if (masked_flags
== GENERIC_WRITE
)
1210 return SMBOPEN_WRITE
;
1212 /* just go for read/write */
1213 return SMBOPEN_READWRITE
;
1217 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1218 const char *fileName
, const int openDisposition
,
1219 const int access_flags
, const int create_options
, __u16
*netfid
,
1220 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1221 const struct nls_table
*nls_codepage
, int remap
)
1224 OPENX_REQ
*pSMB
= NULL
;
1225 OPENX_RSP
*pSMBr
= NULL
;
1231 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1236 pSMB
->AndXCommand
= 0xFF; /* none */
1238 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1239 count
= 1; /* account for one byte pad to word boundary */
1241 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1242 fileName
, PATH_MAX
, nls_codepage
, remap
);
1243 name_len
++; /* trailing null */
1245 } else { /* BB improve check for buffer overruns BB */
1246 count
= 0; /* no pad */
1247 name_len
= strnlen(fileName
, PATH_MAX
);
1248 name_len
++; /* trailing null */
1249 strncpy(pSMB
->fileName
, fileName
, name_len
);
1251 if (*pOplock
& REQ_OPLOCK
)
1252 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1253 else if (*pOplock
& REQ_BATCHOPLOCK
)
1254 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1256 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1257 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1258 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1259 /* set file as system file if special file such
1260 as fifo and server expecting SFU style and
1261 no Unix extensions */
1263 if (create_options
& CREATE_OPTION_SPECIAL
)
1264 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1265 else /* BB FIXME BB */
1266 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1268 if (create_options
& CREATE_OPTION_READONLY
)
1269 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1272 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1273 CREATE_OPTIONS_MASK); */
1274 /* BB FIXME END BB */
1276 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1277 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1279 pSMB
->hdr
.smb_buf_length
+= count
;
1281 pSMB
->ByteCount
= cpu_to_le16(count
);
1282 /* long_op set to 1 to allow for oplock break timeouts */
1283 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1284 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1285 cifs_stats_inc(&tcon
->num_opens
);
1287 cFYI(1, ("Error in Open = %d", rc
));
1289 /* BB verify if wct == 15 */
1291 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1293 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1294 /* Let caller know file was created so we can set the mode. */
1295 /* Do we care about the CreateAction in any other cases? */
1297 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1298 *pOplock |= CIFS_CREATE_ACTION; */
1302 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1303 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1304 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1305 pfile_info
->ChangeTime
= 0; /* BB fixme */
1306 pfile_info
->Attributes
=
1307 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1308 /* the file_info buf is endian converted by caller */
1309 pfile_info
->AllocationSize
=
1310 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1311 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1312 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1316 cifs_buf_release(pSMB
);
1323 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1324 const char *fileName
, const int openDisposition
,
1325 const int access_flags
, const int create_options
, __u16
*netfid
,
1326 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1327 const struct nls_table
*nls_codepage
, int remap
)
1330 OPEN_REQ
*pSMB
= NULL
;
1331 OPEN_RSP
*pSMBr
= NULL
;
1337 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1342 pSMB
->AndXCommand
= 0xFF; /* none */
1344 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1345 count
= 1; /* account for one byte pad to word boundary */
1347 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1348 fileName
, PATH_MAX
, nls_codepage
, remap
);
1349 name_len
++; /* trailing null */
1351 pSMB
->NameLength
= cpu_to_le16(name_len
);
1352 } else { /* BB improve check for buffer overruns BB */
1353 count
= 0; /* no pad */
1354 name_len
= strnlen(fileName
, PATH_MAX
);
1355 name_len
++; /* trailing null */
1356 pSMB
->NameLength
= cpu_to_le16(name_len
);
1357 strncpy(pSMB
->fileName
, fileName
, name_len
);
1359 if (*pOplock
& REQ_OPLOCK
)
1360 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1361 else if (*pOplock
& REQ_BATCHOPLOCK
)
1362 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1363 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1364 pSMB
->AllocationSize
= 0;
1365 /* set file as system file if special file such
1366 as fifo and server expecting SFU style and
1367 no Unix extensions */
1368 if (create_options
& CREATE_OPTION_SPECIAL
)
1369 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1371 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1373 /* XP does not handle ATTR_POSIX_SEMANTICS */
1374 /* but it helps speed up case sensitive checks for other
1375 servers such as Samba */
1376 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1377 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1379 if (create_options
& CREATE_OPTION_READONLY
)
1380 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1382 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1383 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1384 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1385 /* BB Expirement with various impersonation levels and verify */
1386 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1387 pSMB
->SecurityFlags
=
1388 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1391 pSMB
->hdr
.smb_buf_length
+= count
;
1393 pSMB
->ByteCount
= cpu_to_le16(count
);
1394 /* long_op set to 1 to allow for oplock break timeouts */
1395 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1396 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1397 cifs_stats_inc(&tcon
->num_opens
);
1399 cFYI(1, ("Error in Open = %d", rc
));
1401 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1402 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1403 /* Let caller know file was created so we can set the mode. */
1404 /* Do we care about the CreateAction in any other cases? */
1405 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1406 *pOplock
|= CIFS_CREATE_ACTION
;
1408 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1409 36 /* CreationTime to Attributes */);
1410 /* the file_info buf is endian converted by caller */
1411 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1412 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1413 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1417 cifs_buf_release(pSMB
);
1424 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1425 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1426 char **buf
, int *pbuf_type
)
1429 READ_REQ
*pSMB
= NULL
;
1430 READ_RSP
*pSMBr
= NULL
;
1431 char *pReadData
= NULL
;
1433 int resp_buf_type
= 0;
1436 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1437 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1440 wct
= 10; /* old style read */
1443 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1447 /* tcon and ses pointer are checked in smb_init */
1448 if (tcon
->ses
->server
== NULL
)
1449 return -ECONNABORTED
;
1451 pSMB
->AndXCommand
= 0xFF; /* none */
1453 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1455 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1456 else if ((lseek
>> 32) > 0) /* can not handle this big offset for old */
1459 pSMB
->Remaining
= 0;
1460 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1461 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1463 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1465 /* old style read */
1466 struct smb_com_readx_req
*pSMBW
=
1467 (struct smb_com_readx_req
*)pSMB
;
1468 pSMBW
->ByteCount
= 0;
1471 iov
[0].iov_base
= (char *)pSMB
;
1472 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1473 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1474 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1475 cifs_stats_inc(&tcon
->num_reads
);
1476 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1478 cERROR(1, ("Send error in read = %d", rc
));
1480 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1481 data_length
= data_length
<< 16;
1482 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1483 *nbytes
= data_length
;
1485 /*check that DataLength would not go beyond end of SMB */
1486 if ((data_length
> CIFSMaxBufSize
)
1487 || (data_length
> count
)) {
1488 cFYI(1, ("bad length %d for count %d",
1489 data_length
, count
));
1493 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1494 le16_to_cpu(pSMBr
->DataOffset
);
1495 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1496 cERROR(1,("Faulting on read rc = %d",rc));
1498 }*/ /* can not use copy_to_user when using page cache*/
1500 memcpy(*buf
, pReadData
, data_length
);
1504 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1506 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1507 cifs_small_buf_release(iov
[0].iov_base
);
1508 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1509 cifs_buf_release(iov
[0].iov_base
);
1510 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1511 /* return buffer to caller to free */
1512 *buf
= iov
[0].iov_base
;
1513 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1514 *pbuf_type
= CIFS_SMALL_BUFFER
;
1515 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1516 *pbuf_type
= CIFS_LARGE_BUFFER
;
1517 } /* else no valid buffer on return - leave as null */
1519 /* Note: On -EAGAIN error only caller can retry on handle based calls
1520 since file handle passed in no longer valid */
1526 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1527 const int netfid
, const unsigned int count
,
1528 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1529 const char __user
*ubuf
, const int long_op
)
1532 WRITE_REQ
*pSMB
= NULL
;
1533 WRITE_RSP
*pSMBr
= NULL
;
1534 int bytes_returned
, wct
;
1538 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1539 if (tcon
->ses
== NULL
)
1540 return -ECONNABORTED
;
1542 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1547 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1551 /* tcon and ses pointer are checked in smb_init */
1552 if (tcon
->ses
->server
== NULL
)
1553 return -ECONNABORTED
;
1555 pSMB
->AndXCommand
= 0xFF; /* none */
1557 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1559 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1560 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1563 pSMB
->Reserved
= 0xFFFFFFFF;
1564 pSMB
->WriteMode
= 0;
1565 pSMB
->Remaining
= 0;
1567 /* Can increase buffer size if buffer is big enough in some cases ie we
1568 can send more if LARGE_WRITE_X capability returned by the server and if
1569 our buffer is big enough or if we convert to iovecs on socket writes
1570 and eliminate the copy to the CIFS buffer */
1571 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1572 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1574 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1578 if (bytes_sent
> count
)
1581 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1583 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1585 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1586 cifs_buf_release(pSMB
);
1589 } else if (count
!= 0) {
1591 cifs_buf_release(pSMB
);
1593 } /* else setting file size with write of zero bytes */
1595 byte_count
= bytes_sent
+ 1; /* pad */
1596 else /* wct == 12 */
1597 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1599 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1600 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1601 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1604 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1605 else { /* old style write has byte count 4 bytes earlier
1607 struct smb_com_writex_req
*pSMBW
=
1608 (struct smb_com_writex_req
*)pSMB
;
1609 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1612 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1613 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1614 cifs_stats_inc(&tcon
->num_writes
);
1616 cFYI(1, ("Send error in write = %d", rc
));
1619 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1620 *nbytes
= (*nbytes
) << 16;
1621 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1624 cifs_buf_release(pSMB
);
1626 /* Note: On -EAGAIN error only caller can retry on handle based calls
1627 since file handle passed in no longer valid */
1633 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1634 const int netfid
, const unsigned int count
,
1635 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1636 int n_vec
, const int long_op
)
1639 WRITE_REQ
*pSMB
= NULL
;
1642 int resp_buf_type
= 0;
1644 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1646 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1650 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1653 /* tcon and ses pointer are checked in smb_init */
1654 if (tcon
->ses
->server
== NULL
)
1655 return -ECONNABORTED
;
1657 pSMB
->AndXCommand
= 0xFF; /* none */
1659 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1661 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1662 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1664 pSMB
->Reserved
= 0xFFFFFFFF;
1665 pSMB
->WriteMode
= 0;
1666 pSMB
->Remaining
= 0;
1669 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1671 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1672 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1673 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1675 pSMB
->hdr
.smb_buf_length
+= count
+1;
1676 else /* wct == 12 */
1677 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1679 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1680 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1681 struct smb_com_writex_req
*pSMBW
=
1682 (struct smb_com_writex_req
*)pSMB
;
1683 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1685 iov
[0].iov_base
= pSMB
;
1687 iov
[0].iov_len
= smb_hdr_len
+ 4;
1688 else /* wct == 12 pad bigger by four bytes */
1689 iov
[0].iov_len
= smb_hdr_len
+ 8;
1692 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1694 cifs_stats_inc(&tcon
->num_writes
);
1696 cFYI(1, ("Send error Write2 = %d", rc
));
1698 } else if (resp_buf_type
== 0) {
1699 /* presumably this can not happen, but best to be safe */
1703 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1704 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1705 *nbytes
= (*nbytes
) << 16;
1706 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1709 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1710 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1711 cifs_small_buf_release(iov
[0].iov_base
);
1712 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1713 cifs_buf_release(iov
[0].iov_base
);
1715 /* Note: On -EAGAIN error only caller can retry on handle based calls
1716 since file handle passed in no longer valid */
1723 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1724 const __u16 smb_file_id
, const __u64 len
,
1725 const __u64 offset
, const __u32 numUnlock
,
1726 const __u32 numLock
, const __u8 lockType
, const bool waitFlag
)
1729 LOCK_REQ
*pSMB
= NULL
;
1730 LOCK_RSP
*pSMBr
= NULL
;
1735 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
));
1736 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1741 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1743 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1744 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1746 } else if (waitFlag
) {
1747 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1748 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1753 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1754 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1755 pSMB
->LockType
= lockType
;
1756 pSMB
->AndXCommand
= 0xFF; /* none */
1757 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1759 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1760 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1761 /* BB where to store pid high? */
1762 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1763 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1764 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1765 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1766 count
= sizeof(LOCKING_ANDX_RANGE
);
1771 pSMB
->hdr
.smb_buf_length
+= count
;
1772 pSMB
->ByteCount
= cpu_to_le16(count
);
1775 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1776 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1777 cifs_small_buf_release(pSMB
);
1779 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1781 /* SMB buffer freed by function above */
1783 cifs_stats_inc(&tcon
->num_locks
);
1785 cFYI(1, ("Send error in Lock = %d", rc
));
1787 /* Note: On -EAGAIN error only caller can retry on handle based calls
1788 since file handle passed in no longer valid */
1793 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1794 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1795 struct file_lock
*pLockData
, const __u16 lock_type
,
1796 const bool waitFlag
)
1798 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1799 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1800 struct cifs_posix_lock
*parm_data
;
1803 int bytes_returned
= 0;
1804 int resp_buf_type
= 0;
1805 __u16 params
, param_offset
, offset
, byte_count
, count
;
1808 cFYI(1, ("Posix Lock"));
1810 if (pLockData
== NULL
)
1813 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1818 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1821 pSMB
->MaxSetupCount
= 0;
1824 pSMB
->Reserved2
= 0;
1825 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1826 offset
= param_offset
+ params
;
1828 count
= sizeof(struct cifs_posix_lock
);
1829 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1830 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1831 pSMB
->SetupCount
= 1;
1832 pSMB
->Reserved3
= 0;
1834 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1836 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1837 byte_count
= 3 /* pad */ + params
+ count
;
1838 pSMB
->DataCount
= cpu_to_le16(count
);
1839 pSMB
->ParameterCount
= cpu_to_le16(params
);
1840 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1841 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1842 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1843 parm_data
= (struct cifs_posix_lock
*)
1844 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1846 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1848 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1849 parm_data
->lock_flags
= cpu_to_le16(1);
1850 pSMB
->Timeout
= cpu_to_le32(-1);
1854 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1855 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1856 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1858 pSMB
->DataOffset
= cpu_to_le16(offset
);
1859 pSMB
->Fid
= smb_file_id
;
1860 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1861 pSMB
->Reserved4
= 0;
1862 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1863 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1865 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1866 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1868 iov
[0].iov_base
= (char *)pSMB
;
1869 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1870 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1871 &resp_buf_type
, timeout
);
1872 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1873 not try to free it twice below on exit */
1874 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1878 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1879 } else if (get_flag
) {
1880 /* lock structure can be returned on get */
1883 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1885 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1886 rc
= -EIO
; /* bad smb */
1889 if (pLockData
== NULL
) {
1893 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1894 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1895 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1899 parm_data
= (struct cifs_posix_lock
*)
1900 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1901 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1902 pLockData
->fl_type
= F_UNLCK
;
1907 cifs_small_buf_release(pSMB
);
1909 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1910 cifs_small_buf_release(iov
[0].iov_base
);
1911 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1912 cifs_buf_release(iov
[0].iov_base
);
1914 /* Note: On -EAGAIN error only caller can retry on handle based calls
1915 since file handle passed in no longer valid */
1922 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1925 CLOSE_REQ
*pSMB
= NULL
;
1926 cFYI(1, ("In CIFSSMBClose"));
1928 /* do not retry on dead session on close */
1929 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1935 pSMB
->FileID
= (__u16
) smb_file_id
;
1936 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1937 pSMB
->ByteCount
= 0;
1938 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1939 cifs_stats_inc(&tcon
->num_closes
);
1942 /* EINTR is expected when user ctl-c to kill app */
1943 cERROR(1, ("Send error in Close = %d", rc
));
1947 /* Since session is dead, file will be closed on server already */
1955 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1956 const char *fromName
, const char *toName
,
1957 const struct nls_table
*nls_codepage
, int remap
)
1960 RENAME_REQ
*pSMB
= NULL
;
1961 RENAME_RSP
*pSMBr
= NULL
;
1963 int name_len
, name_len2
;
1966 cFYI(1, ("In CIFSSMBRename"));
1968 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1973 pSMB
->BufferFormat
= 0x04;
1974 pSMB
->SearchAttributes
=
1975 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1978 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1980 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1981 PATH_MAX
, nls_codepage
, remap
);
1982 name_len
++; /* trailing null */
1984 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1985 /* protocol requires ASCII signature byte on Unicode string */
1986 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1988 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1989 toName
, PATH_MAX
, nls_codepage
, remap
);
1990 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1991 name_len2
*= 2; /* convert to bytes */
1992 } else { /* BB improve the check for buffer overruns BB */
1993 name_len
= strnlen(fromName
, PATH_MAX
);
1994 name_len
++; /* trailing null */
1995 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1996 name_len2
= strnlen(toName
, PATH_MAX
);
1997 name_len2
++; /* trailing null */
1998 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1999 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2000 name_len2
++; /* trailing null */
2001 name_len2
++; /* signature byte */
2004 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2005 pSMB
->hdr
.smb_buf_length
+= count
;
2006 pSMB
->ByteCount
= cpu_to_le16(count
);
2008 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2009 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2010 cifs_stats_inc(&tcon
->num_renames
);
2012 cFYI(1, ("Send error in rename = %d", rc
));
2014 cifs_buf_release(pSMB
);
2022 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
2023 int netfid
, char *target_name
,
2024 const struct nls_table
*nls_codepage
, int remap
)
2026 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2027 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2028 struct set_file_rename
*rename_info
;
2030 char dummy_string
[30];
2032 int bytes_returned
= 0;
2034 __u16 params
, param_offset
, offset
, count
, byte_count
;
2036 cFYI(1, ("Rename to File by handle"));
2037 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2043 pSMB
->MaxSetupCount
= 0;
2047 pSMB
->Reserved2
= 0;
2048 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2049 offset
= param_offset
+ params
;
2051 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2052 rename_info
= (struct set_file_rename
*) data_offset
;
2053 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2054 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2055 pSMB
->SetupCount
= 1;
2056 pSMB
->Reserved3
= 0;
2057 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2058 byte_count
= 3 /* pad */ + params
;
2059 pSMB
->ParameterCount
= cpu_to_le16(params
);
2060 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2061 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2062 pSMB
->DataOffset
= cpu_to_le16(offset
);
2063 /* construct random name ".cifs_tmp<inodenum><mid>" */
2064 rename_info
->overwrite
= cpu_to_le32(1);
2065 rename_info
->root_fid
= 0;
2066 /* unicode only call */
2067 if (target_name
== NULL
) {
2068 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2069 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2070 dummy_string
, 24, nls_codepage
, remap
);
2072 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2073 target_name
, PATH_MAX
, nls_codepage
,
2076 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2077 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
2078 byte_count
+= count
;
2079 pSMB
->DataCount
= cpu_to_le16(count
);
2080 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2082 pSMB
->InformationLevel
=
2083 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2084 pSMB
->Reserved4
= 0;
2085 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2086 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2087 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2088 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2089 cifs_stats_inc(&pTcon
->num_t2renames
);
2091 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2093 cifs_buf_release(pSMB
);
2095 /* Note: On -EAGAIN error only caller can retry on handle based calls
2096 since file handle passed in no longer valid */
2102 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2103 const __u16 target_tid
, const char *toName
, const int flags
,
2104 const struct nls_table
*nls_codepage
, int remap
)
2107 COPY_REQ
*pSMB
= NULL
;
2108 COPY_RSP
*pSMBr
= NULL
;
2110 int name_len
, name_len2
;
2113 cFYI(1, ("In CIFSSMBCopy"));
2115 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2120 pSMB
->BufferFormat
= 0x04;
2121 pSMB
->Tid2
= target_tid
;
2123 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2125 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2126 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2127 fromName
, PATH_MAX
, nls_codepage
,
2129 name_len
++; /* trailing null */
2131 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2132 /* protocol requires ASCII signature byte on Unicode string */
2133 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2135 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2136 toName
, PATH_MAX
, nls_codepage
, remap
);
2137 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2138 name_len2
*= 2; /* convert to bytes */
2139 } else { /* BB improve the check for buffer overruns BB */
2140 name_len
= strnlen(fromName
, PATH_MAX
);
2141 name_len
++; /* trailing null */
2142 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2143 name_len2
= strnlen(toName
, PATH_MAX
);
2144 name_len2
++; /* trailing null */
2145 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2146 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2147 name_len2
++; /* trailing null */
2148 name_len2
++; /* signature byte */
2151 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2152 pSMB
->hdr
.smb_buf_length
+= count
;
2153 pSMB
->ByteCount
= cpu_to_le16(count
);
2155 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2156 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2158 cFYI(1, ("Send error in copy = %d with %d files copied",
2159 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2162 cifs_buf_release(pSMB
);
2171 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2172 const char *fromName
, const char *toName
,
2173 const struct nls_table
*nls_codepage
)
2175 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2176 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2179 int name_len_target
;
2181 int bytes_returned
= 0;
2182 __u16 params
, param_offset
, offset
, byte_count
;
2184 cFYI(1, ("In Symlink Unix style"));
2186 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2191 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2193 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2194 /* find define for this maxpathcomponent */
2196 name_len
++; /* trailing null */
2199 } else { /* BB improve the check for buffer overruns BB */
2200 name_len
= strnlen(fromName
, PATH_MAX
);
2201 name_len
++; /* trailing null */
2202 strncpy(pSMB
->FileName
, fromName
, name_len
);
2204 params
= 6 + name_len
;
2205 pSMB
->MaxSetupCount
= 0;
2209 pSMB
->Reserved2
= 0;
2210 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2211 InformationLevel
) - 4;
2212 offset
= param_offset
+ params
;
2214 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2215 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2217 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2218 /* find define for this maxpathcomponent */
2220 name_len_target
++; /* trailing null */
2221 name_len_target
*= 2;
2222 } else { /* BB improve the check for buffer overruns BB */
2223 name_len_target
= strnlen(toName
, PATH_MAX
);
2224 name_len_target
++; /* trailing null */
2225 strncpy(data_offset
, toName
, name_len_target
);
2228 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2229 /* BB find exact max on data count below from sess */
2230 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2231 pSMB
->SetupCount
= 1;
2232 pSMB
->Reserved3
= 0;
2233 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2234 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2235 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2236 pSMB
->ParameterCount
= cpu_to_le16(params
);
2237 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2238 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2239 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2240 pSMB
->DataOffset
= cpu_to_le16(offset
);
2241 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2242 pSMB
->Reserved4
= 0;
2243 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2244 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2245 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2246 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2247 cifs_stats_inc(&tcon
->num_symlinks
);
2249 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2252 cifs_buf_release(pSMB
);
2255 goto createSymLinkRetry
;
2261 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2262 const char *fromName
, const char *toName
,
2263 const struct nls_table
*nls_codepage
, int remap
)
2265 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2266 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2269 int name_len_target
;
2271 int bytes_returned
= 0;
2272 __u16 params
, param_offset
, offset
, byte_count
;
2274 cFYI(1, ("In Create Hard link Unix style"));
2275 createHardLinkRetry
:
2276 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2281 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2282 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2283 PATH_MAX
, nls_codepage
, remap
);
2284 name_len
++; /* trailing null */
2287 } else { /* BB improve the check for buffer overruns BB */
2288 name_len
= strnlen(toName
, PATH_MAX
);
2289 name_len
++; /* trailing null */
2290 strncpy(pSMB
->FileName
, toName
, name_len
);
2292 params
= 6 + name_len
;
2293 pSMB
->MaxSetupCount
= 0;
2297 pSMB
->Reserved2
= 0;
2298 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2299 InformationLevel
) - 4;
2300 offset
= param_offset
+ params
;
2302 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2303 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2305 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2306 nls_codepage
, remap
);
2307 name_len_target
++; /* trailing null */
2308 name_len_target
*= 2;
2309 } else { /* BB improve the check for buffer overruns BB */
2310 name_len_target
= strnlen(fromName
, PATH_MAX
);
2311 name_len_target
++; /* trailing null */
2312 strncpy(data_offset
, fromName
, name_len_target
);
2315 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2316 /* BB find exact max on data count below from sess*/
2317 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2318 pSMB
->SetupCount
= 1;
2319 pSMB
->Reserved3
= 0;
2320 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2321 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2322 pSMB
->ParameterCount
= cpu_to_le16(params
);
2323 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2324 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2325 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2326 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2327 pSMB
->DataOffset
= cpu_to_le16(offset
);
2328 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2329 pSMB
->Reserved4
= 0;
2330 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2331 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2332 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2333 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2334 cifs_stats_inc(&tcon
->num_hardlinks
);
2336 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2338 cifs_buf_release(pSMB
);
2340 goto createHardLinkRetry
;
2346 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2347 const char *fromName
, const char *toName
,
2348 const struct nls_table
*nls_codepage
, int remap
)
2351 NT_RENAME_REQ
*pSMB
= NULL
;
2352 RENAME_RSP
*pSMBr
= NULL
;
2354 int name_len
, name_len2
;
2357 cFYI(1, ("In CIFSCreateHardLink"));
2358 winCreateHardLinkRetry
:
2360 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2365 pSMB
->SearchAttributes
=
2366 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2368 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2369 pSMB
->ClusterCount
= 0;
2371 pSMB
->BufferFormat
= 0x04;
2373 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2375 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2376 PATH_MAX
, nls_codepage
, remap
);
2377 name_len
++; /* trailing null */
2379 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2380 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2382 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2383 toName
, PATH_MAX
, nls_codepage
, remap
);
2384 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2385 name_len2
*= 2; /* convert to bytes */
2386 } else { /* BB improve the check for buffer overruns BB */
2387 name_len
= strnlen(fromName
, PATH_MAX
);
2388 name_len
++; /* trailing null */
2389 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2390 name_len2
= strnlen(toName
, PATH_MAX
);
2391 name_len2
++; /* trailing null */
2392 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2393 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2394 name_len2
++; /* trailing null */
2395 name_len2
++; /* signature byte */
2398 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2399 pSMB
->hdr
.smb_buf_length
+= count
;
2400 pSMB
->ByteCount
= cpu_to_le16(count
);
2402 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2403 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2404 cifs_stats_inc(&tcon
->num_hardlinks
);
2406 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2408 cifs_buf_release(pSMB
);
2410 goto winCreateHardLinkRetry
;
2416 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2417 const unsigned char *searchName
,
2418 char *symlinkinfo
, const int buflen
,
2419 const struct nls_table
*nls_codepage
)
2421 /* SMB_QUERY_FILE_UNIX_LINK */
2422 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2423 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2427 __u16 params
, byte_count
;
2429 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2432 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2437 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2439 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2440 PATH_MAX
, nls_codepage
);
2441 name_len
++; /* trailing null */
2443 } else { /* BB improve the check for buffer overruns BB */
2444 name_len
= strnlen(searchName
, PATH_MAX
);
2445 name_len
++; /* trailing null */
2446 strncpy(pSMB
->FileName
, searchName
, name_len
);
2449 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2450 pSMB
->TotalDataCount
= 0;
2451 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2452 /* BB find exact max data count below from sess structure BB */
2453 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2454 pSMB
->MaxSetupCount
= 0;
2458 pSMB
->Reserved2
= 0;
2459 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2460 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2461 pSMB
->DataCount
= 0;
2462 pSMB
->DataOffset
= 0;
2463 pSMB
->SetupCount
= 1;
2464 pSMB
->Reserved3
= 0;
2465 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2466 byte_count
= params
+ 1 /* pad */ ;
2467 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2468 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2469 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2470 pSMB
->Reserved4
= 0;
2471 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2472 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2474 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2475 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2477 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2479 /* decode response */
2481 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2482 if (rc
|| (pSMBr
->ByteCount
< 2))
2483 /* BB also check enough total bytes returned */
2484 rc
= -EIO
; /* bad smb */
2486 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2487 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2489 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2490 name_len
= UniStrnlen((wchar_t *) ((char *)
2491 &pSMBr
->hdr
.Protocol
+ data_offset
),
2492 min_t(const int, buflen
, count
) / 2);
2493 /* BB FIXME investigate remapping reserved chars here */
2494 cifs_strfromUCS_le(symlinkinfo
,
2495 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
2497 name_len
, nls_codepage
);
2499 strncpy(symlinkinfo
,
2500 (char *) &pSMBr
->hdr
.Protocol
+
2502 min_t(const int, buflen
, count
));
2504 symlinkinfo
[buflen
] = 0;
2505 /* just in case so calling code does not go off the end of buffer */
2508 cifs_buf_release(pSMB
);
2510 goto querySymLinkRetry
;
2514 #ifdef CONFIG_CIFS_EXPERIMENTAL
2515 /* Initialize NT TRANSACT SMB into small smb request buffer.
2516 This assumes that all NT TRANSACTS that we init here have
2517 total parm and data under about 400 bytes (to fit in small cifs
2518 buffer size), which is the case so far, it easily fits. NB:
2519 Setup words themselves and ByteCount
2520 MaxSetupCount (size of returned setup area) and
2521 MaxParameterCount (returned parms size) must be set by caller */
2523 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2524 const int parm_len
, struct cifsTconInfo
*tcon
,
2529 struct smb_com_ntransact_req
*pSMB
;
2531 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2535 *ret_buf
= (void *)pSMB
;
2537 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2538 pSMB
->TotalDataCount
= 0;
2539 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2540 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2541 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2542 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2543 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2544 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2545 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2546 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2547 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2548 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2553 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2554 __u32
*pparmlen
, __u32
*pdatalen
)
2557 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2558 struct smb_com_ntransact_rsp
*pSMBr
;
2566 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2568 /* ByteCount was converted from little endian in SendReceive */
2569 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2570 (char *)&pSMBr
->ByteCount
;
2572 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2573 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2574 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2575 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2577 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2578 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2580 /* should we also check that parm and data areas do not overlap? */
2581 if (*ppparm
> end_of_smb
) {
2582 cFYI(1, ("parms start after end of smb"));
2584 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2585 cFYI(1, ("parm end after end of smb"));
2587 } else if (*ppdata
> end_of_smb
) {
2588 cFYI(1, ("data starts after end of smb"));
2590 } else if (data_count
+ *ppdata
> end_of_smb
) {
2591 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2592 *ppdata
, data_count
, (data_count
+ *ppdata
),
2593 end_of_smb
, pSMBr
));
2595 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2596 cFYI(1, ("parm count and data count larger than SMB"));
2599 *pdatalen
= data_count
;
2600 *pparmlen
= parm_count
;
2603 #endif /* CIFS_EXPERIMENTAL */
2606 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2607 const unsigned char *searchName
,
2608 char *symlinkinfo
, const int buflen
, __u16 fid
,
2609 const struct nls_table
*nls_codepage
)
2614 struct smb_com_transaction_ioctl_req
*pSMB
;
2615 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2617 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2618 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2623 pSMB
->TotalParameterCount
= 0 ;
2624 pSMB
->TotalDataCount
= 0;
2625 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2626 /* BB find exact data count max from sess structure BB */
2627 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2628 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2629 pSMB
->MaxSetupCount
= 4;
2631 pSMB
->ParameterOffset
= 0;
2632 pSMB
->DataCount
= 0;
2633 pSMB
->DataOffset
= 0;
2634 pSMB
->SetupCount
= 4;
2635 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2636 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2637 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2638 pSMB
->IsFsctl
= 1; /* FSCTL */
2639 pSMB
->IsRootFlag
= 0;
2640 pSMB
->Fid
= fid
; /* file handle always le */
2641 pSMB
->ByteCount
= 0;
2643 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2644 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2646 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2647 } else { /* decode response */
2648 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2649 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2650 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2651 /* BB also check enough total bytes returned */
2652 rc
= -EIO
; /* bad smb */
2654 if (data_count
&& (data_count
< 2048)) {
2655 char *end_of_smb
= 2 /* sizeof byte count */ +
2657 (char *)&pSMBr
->ByteCount
;
2659 struct reparse_data
*reparse_buf
=
2660 (struct reparse_data
*)
2661 ((char *)&pSMBr
->hdr
.Protocol
2663 if ((char *)reparse_buf
>= end_of_smb
) {
2667 if ((reparse_buf
->LinkNamesBuf
+
2668 reparse_buf
->TargetNameOffset
+
2669 reparse_buf
->TargetNameLen
) >
2671 cFYI(1, ("reparse buf beyond SMB"));
2676 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2677 name_len
= UniStrnlen((wchar_t *)
2678 (reparse_buf
->LinkNamesBuf
+
2679 reparse_buf
->TargetNameOffset
),
2681 reparse_buf
->TargetNameLen
/ 2));
2682 cifs_strfromUCS_le(symlinkinfo
,
2683 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2684 reparse_buf
->TargetNameOffset
),
2685 name_len
, nls_codepage
);
2686 } else { /* ASCII names */
2687 strncpy(symlinkinfo
,
2688 reparse_buf
->LinkNamesBuf
+
2689 reparse_buf
->TargetNameOffset
,
2690 min_t(const int, buflen
,
2691 reparse_buf
->TargetNameLen
));
2695 cFYI(1, ("Invalid return data count on "
2696 "get reparse info ioctl"));
2698 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2699 does not go off the end of the buffer */
2700 cFYI(1, ("readlink result - %s", symlinkinfo
));
2704 cifs_buf_release(pSMB
);
2706 /* Note: On -EAGAIN error only caller can retry on handle based calls
2707 since file handle passed in no longer valid */
2712 #ifdef CONFIG_CIFS_POSIX
2714 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2715 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2716 struct cifs_posix_ace
*cifs_ace
)
2718 /* u8 cifs fields do not need le conversion */
2719 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2720 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2721 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2722 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2727 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2728 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2729 const int acl_type
, const int size_of_data_area
)
2734 struct cifs_posix_ace
*pACE
;
2735 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2736 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2738 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2741 if (acl_type
& ACL_TYPE_ACCESS
) {
2742 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2743 pACE
= &cifs_acl
->ace_array
[0];
2744 size
= sizeof(struct cifs_posix_acl
);
2745 size
+= sizeof(struct cifs_posix_ace
) * count
;
2746 /* check if we would go beyond end of SMB */
2747 if (size_of_data_area
< size
) {
2748 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2749 size_of_data_area
, size
));
2752 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2753 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2754 size
= sizeof(struct cifs_posix_acl
);
2755 size
+= sizeof(struct cifs_posix_ace
) * count
;
2756 /* skip past access ACEs to get to default ACEs */
2757 pACE
= &cifs_acl
->ace_array
[count
];
2758 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2759 size
+= sizeof(struct cifs_posix_ace
) * count
;
2760 /* check if we would go beyond end of SMB */
2761 if (size_of_data_area
< size
)
2768 size
= posix_acl_xattr_size(count
);
2769 if ((buflen
== 0) || (local_acl
== NULL
)) {
2770 /* used to query ACL EA size */
2771 } else if (size
> buflen
) {
2773 } else /* buffer big enough */ {
2774 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2775 for (i
= 0; i
< count
; i
++) {
2776 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2783 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2784 const posix_acl_xattr_entry
*local_ace
)
2786 __u16 rc
= 0; /* 0 = ACL converted ok */
2788 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2789 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2790 /* BB is there a better way to handle the large uid? */
2791 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2792 /* Probably no need to le convert -1 on any arch but can not hurt */
2793 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2795 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2796 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2800 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2801 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2802 const int buflen
, const int acl_type
)
2805 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2806 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2810 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2813 count
= posix_acl_xattr_count((size_t)buflen
);
2814 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2816 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2817 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2818 cFYI(1, ("unknown POSIX ACL version %d",
2819 le32_to_cpu(local_acl
->a_version
)));
2822 cifs_acl
->version
= cpu_to_le16(1);
2823 if (acl_type
== ACL_TYPE_ACCESS
)
2824 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2825 else if (acl_type
== ACL_TYPE_DEFAULT
)
2826 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2828 cFYI(1, ("unknown ACL type %d", acl_type
));
2831 for (i
= 0; i
< count
; i
++) {
2832 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2833 &local_acl
->a_entries
[i
]);
2835 /* ACE not converted */
2840 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2841 rc
+= sizeof(struct cifs_posix_acl
);
2842 /* BB add check to make sure ACL does not overflow SMB */
2848 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2849 const unsigned char *searchName
,
2850 char *acl_inf
, const int buflen
, const int acl_type
,
2851 const struct nls_table
*nls_codepage
, int remap
)
2853 /* SMB_QUERY_POSIX_ACL */
2854 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2855 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2859 __u16 params
, byte_count
;
2861 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2864 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2869 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2871 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2872 PATH_MAX
, nls_codepage
, remap
);
2873 name_len
++; /* trailing null */
2875 pSMB
->FileName
[name_len
] = 0;
2876 pSMB
->FileName
[name_len
+1] = 0;
2877 } else { /* BB improve the check for buffer overruns BB */
2878 name_len
= strnlen(searchName
, PATH_MAX
);
2879 name_len
++; /* trailing null */
2880 strncpy(pSMB
->FileName
, searchName
, name_len
);
2883 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2884 pSMB
->TotalDataCount
= 0;
2885 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2886 /* BB find exact max data count below from sess structure BB */
2887 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2888 pSMB
->MaxSetupCount
= 0;
2892 pSMB
->Reserved2
= 0;
2893 pSMB
->ParameterOffset
= cpu_to_le16(
2894 offsetof(struct smb_com_transaction2_qpi_req
,
2895 InformationLevel
) - 4);
2896 pSMB
->DataCount
= 0;
2897 pSMB
->DataOffset
= 0;
2898 pSMB
->SetupCount
= 1;
2899 pSMB
->Reserved3
= 0;
2900 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2901 byte_count
= params
+ 1 /* pad */ ;
2902 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2903 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2904 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2905 pSMB
->Reserved4
= 0;
2906 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2907 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2909 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2910 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2911 cifs_stats_inc(&tcon
->num_acl_get
);
2913 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2915 /* decode response */
2917 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2918 if (rc
|| (pSMBr
->ByteCount
< 2))
2919 /* BB also check enough total bytes returned */
2920 rc
= -EIO
; /* bad smb */
2922 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2923 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2924 rc
= cifs_copy_posix_acl(acl_inf
,
2925 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2926 buflen
, acl_type
, count
);
2929 cifs_buf_release(pSMB
);
2936 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2937 const unsigned char *fileName
,
2938 const char *local_acl
, const int buflen
,
2940 const struct nls_table
*nls_codepage
, int remap
)
2942 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2943 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2947 int bytes_returned
= 0;
2948 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2950 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2952 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2956 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2958 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2959 PATH_MAX
, nls_codepage
, remap
);
2960 name_len
++; /* trailing null */
2962 } else { /* BB improve the check for buffer overruns BB */
2963 name_len
= strnlen(fileName
, PATH_MAX
);
2964 name_len
++; /* trailing null */
2965 strncpy(pSMB
->FileName
, fileName
, name_len
);
2967 params
= 6 + name_len
;
2968 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2969 /* BB find max SMB size from sess */
2970 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2971 pSMB
->MaxSetupCount
= 0;
2975 pSMB
->Reserved2
= 0;
2976 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2977 InformationLevel
) - 4;
2978 offset
= param_offset
+ params
;
2979 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2980 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2982 /* convert to on the wire format for POSIX ACL */
2983 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2985 if (data_count
== 0) {
2987 goto setACLerrorExit
;
2989 pSMB
->DataOffset
= cpu_to_le16(offset
);
2990 pSMB
->SetupCount
= 1;
2991 pSMB
->Reserved3
= 0;
2992 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2993 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2994 byte_count
= 3 /* pad */ + params
+ data_count
;
2995 pSMB
->DataCount
= cpu_to_le16(data_count
);
2996 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2997 pSMB
->ParameterCount
= cpu_to_le16(params
);
2998 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2999 pSMB
->Reserved4
= 0;
3000 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3001 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3002 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3003 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3005 cFYI(1, ("Set POSIX ACL returned %d", rc
));
3008 cifs_buf_release(pSMB
);
3014 /* BB fix tabs in this function FIXME BB */
3016 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
3017 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
3020 struct smb_t2_qfi_req
*pSMB
= NULL
;
3021 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3023 __u16 params
, byte_count
;
3025 cFYI(1, ("In GetExtAttr"));
3030 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3035 params
= 2 /* level */ + 2 /* fid */;
3036 pSMB
->t2
.TotalDataCount
= 0;
3037 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3038 /* BB find exact max data count below from sess structure BB */
3039 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3040 pSMB
->t2
.MaxSetupCount
= 0;
3041 pSMB
->t2
.Reserved
= 0;
3043 pSMB
->t2
.Timeout
= 0;
3044 pSMB
->t2
.Reserved2
= 0;
3045 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3047 pSMB
->t2
.DataCount
= 0;
3048 pSMB
->t2
.DataOffset
= 0;
3049 pSMB
->t2
.SetupCount
= 1;
3050 pSMB
->t2
.Reserved3
= 0;
3051 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3052 byte_count
= params
+ 1 /* pad */ ;
3053 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3054 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3055 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3058 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3059 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3061 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3062 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3064 cFYI(1, ("error %d in GetExtAttr", rc
));
3066 /* decode response */
3067 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3068 if (rc
|| (pSMBr
->ByteCount
< 2))
3069 /* BB also check enough total bytes returned */
3070 /* If rc should we check for EOPNOSUPP and
3071 disable the srvino flag? or in caller? */
3072 rc
= -EIO
; /* bad smb */
3074 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3075 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3076 struct file_chattr_info
*pfinfo
;
3077 /* BB Do we need a cast or hash here ? */
3079 cFYI(1, ("Illegal size ret in GetExtAttr"));
3083 pfinfo
= (struct file_chattr_info
*)
3084 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3085 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3086 *pMask
= le64_to_cpu(pfinfo
->mask
);
3090 cifs_buf_release(pSMB
);
3092 goto GetExtAttrRetry
;
3096 #endif /* CONFIG_POSIX */
3098 #ifdef CONFIG_CIFS_EXPERIMENTAL
3099 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3101 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3102 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3106 QUERY_SEC_DESC_REQ
*pSMB
;
3109 cFYI(1, ("GetCifsACL"));
3114 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3115 8 /* parm len */, tcon
, (void **) &pSMB
);
3119 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3120 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3121 pSMB
->MaxSetupCount
= 0;
3122 pSMB
->Fid
= fid
; /* file handle always le */
3123 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3125 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3126 pSMB
->hdr
.smb_buf_length
+= 11;
3127 iov
[0].iov_base
= (char *)pSMB
;
3128 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3130 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3132 cifs_stats_inc(&tcon
->num_acl_get
);
3134 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3135 } else { /* decode response */
3139 struct smb_com_ntransact_rsp
*pSMBr
;
3142 /* validate_nttransact */
3143 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3144 &pdata
, &parm_len
, pbuflen
);
3147 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3149 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3151 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3152 rc
= -EIO
; /* bad smb */
3157 /* BB check that data area is minimum length and as big as acl_len */
3159 acl_len
= le32_to_cpu(*parm
);
3160 if (acl_len
!= *pbuflen
) {
3161 cERROR(1, ("acl length %d does not match %d",
3162 acl_len
, *pbuflen
));
3163 if (*pbuflen
> acl_len
)
3167 /* check if buffer is big enough for the acl
3168 header followed by the smallest SID */
3169 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3170 (*pbuflen
>= 64 * 1024)) {
3171 cERROR(1, ("bad acl length %d", *pbuflen
));
3175 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3176 if (*acl_inf
== NULL
) {
3180 memcpy(*acl_inf
, pdata
, *pbuflen
);
3184 if (buf_type
== CIFS_SMALL_BUFFER
)
3185 cifs_small_buf_release(iov
[0].iov_base
);
3186 else if (buf_type
== CIFS_LARGE_BUFFER
)
3187 cifs_buf_release(iov
[0].iov_base
);
3188 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3193 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3194 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3196 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3198 int bytes_returned
= 0;
3199 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3200 NTRANSACT_RSP
*pSMBr
= NULL
;
3203 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3208 pSMB
->MaxSetupCount
= 0;
3212 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3213 data_count
= acllen
;
3214 data_offset
= param_offset
+ param_count
;
3215 byte_count
= 3 /* pad */ + param_count
;
3217 pSMB
->DataCount
= cpu_to_le32(data_count
);
3218 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3219 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3220 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3221 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3222 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3223 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3224 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3225 pSMB
->SetupCount
= 0;
3226 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3227 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3229 pSMB
->Fid
= fid
; /* file handle always le */
3230 pSMB
->Reserved2
= 0;
3231 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3233 if (pntsd
&& acllen
) {
3234 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3237 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3240 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3242 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3243 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3245 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3247 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3248 cifs_buf_release(pSMB
);
3251 goto setCifsAclRetry
;
3256 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3258 /* Legacy Query Path Information call for lookup to old servers such
3260 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3261 const unsigned char *searchName
,
3262 FILE_ALL_INFO
*pFinfo
,
3263 const struct nls_table
*nls_codepage
, int remap
)
3265 QUERY_INFORMATION_REQ
*pSMB
;
3266 QUERY_INFORMATION_RSP
*pSMBr
;
3271 cFYI(1, ("In SMBQPath path %s", searchName
));
3273 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3278 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3280 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3281 PATH_MAX
, nls_codepage
, remap
);
3282 name_len
++; /* trailing null */
3285 name_len
= strnlen(searchName
, PATH_MAX
);
3286 name_len
++; /* trailing null */
3287 strncpy(pSMB
->FileName
, searchName
, name_len
);
3289 pSMB
->BufferFormat
= 0x04;
3290 name_len
++; /* account for buffer type byte */
3291 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3292 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3294 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3295 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3297 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3298 } else if (pFinfo
) {
3300 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3302 /* decode response */
3303 /* BB FIXME - add time zone adjustment BB */
3304 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3307 /* decode time fields */
3308 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3309 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3310 pFinfo
->LastAccessTime
= 0;
3311 pFinfo
->AllocationSize
=
3312 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3313 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3314 pFinfo
->Attributes
=
3315 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3317 rc
= -EIO
; /* bad buffer passed in */
3319 cifs_buf_release(pSMB
);
3331 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3332 const unsigned char *searchName
,
3333 FILE_ALL_INFO
*pFindData
,
3334 int legacy
/* old style infolevel */,
3335 const struct nls_table
*nls_codepage
, int remap
)
3337 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3338 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3339 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3343 __u16 params
, byte_count
;
3345 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3347 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3352 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3354 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3355 PATH_MAX
, nls_codepage
, remap
);
3356 name_len
++; /* trailing null */
3358 } else { /* BB improve the check for buffer overruns BB */
3359 name_len
= strnlen(searchName
, PATH_MAX
);
3360 name_len
++; /* trailing null */
3361 strncpy(pSMB
->FileName
, searchName
, name_len
);
3364 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3365 pSMB
->TotalDataCount
= 0;
3366 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3367 /* BB find exact max SMB PDU from sess structure BB */
3368 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3369 pSMB
->MaxSetupCount
= 0;
3373 pSMB
->Reserved2
= 0;
3374 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3375 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3376 pSMB
->DataCount
= 0;
3377 pSMB
->DataOffset
= 0;
3378 pSMB
->SetupCount
= 1;
3379 pSMB
->Reserved3
= 0;
3380 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3381 byte_count
= params
+ 1 /* pad */ ;
3382 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3383 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3385 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3387 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3388 pSMB
->Reserved4
= 0;
3389 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3390 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3392 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3393 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3395 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3396 } else { /* decode response */
3397 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3399 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3401 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3402 rc
= -EIO
; /* bad smb */
3403 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3404 rc
= -EIO
; /* 24 or 26 expected but we do not read
3406 else if (pFindData
) {
3408 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3410 /* On legacy responses we do not read the last field,
3411 EAsize, fortunately since it varies by subdialect and
3412 also note it differs on Set vs. Get, ie two bytes or 4
3413 bytes depending but we don't care here */
3415 size
= sizeof(FILE_INFO_STANDARD
);
3417 size
= sizeof(FILE_ALL_INFO
);
3418 memcpy((char *) pFindData
,
3419 (char *) &pSMBr
->hdr
.Protocol
+
3424 cifs_buf_release(pSMB
);
3426 goto QPathInfoRetry
;
3432 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3433 const unsigned char *searchName
,
3434 FILE_UNIX_BASIC_INFO
*pFindData
,
3435 const struct nls_table
*nls_codepage
, int remap
)
3437 /* SMB_QUERY_FILE_UNIX_BASIC */
3438 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3439 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3441 int bytes_returned
= 0;
3443 __u16 params
, byte_count
;
3445 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3447 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3452 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3454 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3455 PATH_MAX
, nls_codepage
, remap
);
3456 name_len
++; /* trailing null */
3458 } else { /* BB improve the check for buffer overruns BB */
3459 name_len
= strnlen(searchName
, PATH_MAX
);
3460 name_len
++; /* trailing null */
3461 strncpy(pSMB
->FileName
, searchName
, name_len
);
3464 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3465 pSMB
->TotalDataCount
= 0;
3466 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3467 /* BB find exact max SMB PDU from sess structure BB */
3468 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3469 pSMB
->MaxSetupCount
= 0;
3473 pSMB
->Reserved2
= 0;
3474 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3475 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3476 pSMB
->DataCount
= 0;
3477 pSMB
->DataOffset
= 0;
3478 pSMB
->SetupCount
= 1;
3479 pSMB
->Reserved3
= 0;
3480 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3481 byte_count
= params
+ 1 /* pad */ ;
3482 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3483 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3484 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3485 pSMB
->Reserved4
= 0;
3486 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3487 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3489 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3490 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3492 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3493 } else { /* decode response */
3494 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3496 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3497 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3498 "Unix Extensions can be disabled on mount "
3499 "by specifying the nosfu mount option."));
3500 rc
= -EIO
; /* bad smb */
3502 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3503 memcpy((char *) pFindData
,
3504 (char *) &pSMBr
->hdr
.Protocol
+
3506 sizeof(FILE_UNIX_BASIC_INFO
));
3509 cifs_buf_release(pSMB
);
3511 goto UnixQPathInfoRetry
;
3516 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3518 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3519 const char *searchName
,
3520 const struct nls_table
*nls_codepage
,
3522 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3524 /* level 257 SMB_ */
3525 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3526 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3527 T2_FFIRST_RSP_PARMS
*parms
;
3529 int bytes_returned
= 0;
3531 __u16 params
, byte_count
;
3533 cFYI(1, ("In FindFirst for %s", searchName
));
3536 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3541 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3543 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3544 PATH_MAX
, nls_codepage
, remap
);
3545 /* We can not add the asterik earlier in case
3546 it got remapped to 0xF03A as if it were part of the
3547 directory name instead of a wildcard */
3549 pSMB
->FileName
[name_len
] = dirsep
;
3550 pSMB
->FileName
[name_len
+1] = 0;
3551 pSMB
->FileName
[name_len
+2] = '*';
3552 pSMB
->FileName
[name_len
+3] = 0;
3553 name_len
+= 4; /* now the trailing null */
3554 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3555 pSMB
->FileName
[name_len
+1] = 0;
3557 } else { /* BB add check for overrun of SMB buf BB */
3558 name_len
= strnlen(searchName
, PATH_MAX
);
3559 /* BB fix here and in unicode clause above ie
3560 if (name_len > buffersize-header)
3561 free buffer exit; BB */
3562 strncpy(pSMB
->FileName
, searchName
, name_len
);
3563 pSMB
->FileName
[name_len
] = dirsep
;
3564 pSMB
->FileName
[name_len
+1] = '*';
3565 pSMB
->FileName
[name_len
+2] = 0;
3569 params
= 12 + name_len
/* includes null */ ;
3570 pSMB
->TotalDataCount
= 0; /* no EAs */
3571 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3572 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3573 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3574 pSMB
->MaxSetupCount
= 0;
3578 pSMB
->Reserved2
= 0;
3579 byte_count
= params
+ 1 /* pad */ ;
3580 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3581 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3582 pSMB
->ParameterOffset
= cpu_to_le16(
3583 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3585 pSMB
->DataCount
= 0;
3586 pSMB
->DataOffset
= 0;
3587 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3588 pSMB
->Reserved3
= 0;
3589 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3590 pSMB
->SearchAttributes
=
3591 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3593 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3594 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3595 CIFS_SEARCH_RETURN_RESUME
);
3596 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3598 /* BB what should we set StorageType to? Does it matter? BB */
3599 pSMB
->SearchStorageType
= 0;
3600 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3601 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3603 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3604 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3605 cifs_stats_inc(&tcon
->num_ffirst
);
3607 if (rc
) {/* BB add logic to retry regular search if Unix search
3608 rejected unexpectedly by server */
3609 /* BB Add code to handle unsupported level rc */
3610 cFYI(1, ("Error in FindFirst = %d", rc
));
3612 cifs_buf_release(pSMB
);
3614 /* BB eventually could optimize out free and realloc of buf */
3617 goto findFirstRetry
;
3618 } else { /* decode response */
3619 /* BB remember to free buffer if error BB */
3620 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3622 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3623 psrch_inf
->unicode
= true;
3625 psrch_inf
->unicode
= false;
3627 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3628 psrch_inf
->smallBuf
= 0;
3629 psrch_inf
->srch_entries_start
=
3630 (char *) &pSMBr
->hdr
.Protocol
+
3631 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3632 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3633 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3635 if (parms
->EndofSearch
)
3636 psrch_inf
->endOfSearch
= true;
3638 psrch_inf
->endOfSearch
= false;
3640 psrch_inf
->entries_in_buffer
=
3641 le16_to_cpu(parms
->SearchCount
);
3642 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3643 psrch_inf
->entries_in_buffer
;
3644 *pnetfid
= parms
->SearchHandle
;
3646 cifs_buf_release(pSMB
);
3653 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3654 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3656 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3657 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3658 T2_FNEXT_RSP_PARMS
*parms
;
3659 char *response_data
;
3661 int bytes_returned
, name_len
;
3662 __u16 params
, byte_count
;
3664 cFYI(1, ("In FindNext"));
3666 if (psrch_inf
->endOfSearch
)
3669 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3674 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3676 pSMB
->TotalDataCount
= 0; /* no EAs */
3677 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3678 pSMB
->MaxDataCount
=
3679 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3681 pSMB
->MaxSetupCount
= 0;
3685 pSMB
->Reserved2
= 0;
3686 pSMB
->ParameterOffset
= cpu_to_le16(
3687 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3688 pSMB
->DataCount
= 0;
3689 pSMB
->DataOffset
= 0;
3690 pSMB
->SetupCount
= 1;
3691 pSMB
->Reserved3
= 0;
3692 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3693 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3695 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3696 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3697 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3699 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3701 name_len
= psrch_inf
->resume_name_len
;
3703 if (name_len
< PATH_MAX
) {
3704 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3705 byte_count
+= name_len
;
3706 /* 14 byte parm len above enough for 2 byte null terminator */
3707 pSMB
->ResumeFileName
[name_len
] = 0;
3708 pSMB
->ResumeFileName
[name_len
+1] = 0;
3711 goto FNext2_err_exit
;
3713 byte_count
= params
+ 1 /* pad */ ;
3714 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3715 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3716 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3717 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3719 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3720 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3721 cifs_stats_inc(&tcon
->num_fnext
);
3724 psrch_inf
->endOfSearch
= true;
3725 cifs_buf_release(pSMB
);
3726 rc
= 0; /* search probably was closed at end of search*/
3728 cFYI(1, ("FindNext returned = %d", rc
));
3729 } else { /* decode response */
3730 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3733 /* BB fixme add lock for file (srch_info) struct here */
3734 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3735 psrch_inf
->unicode
= true;
3737 psrch_inf
->unicode
= false;
3738 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3739 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3740 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3741 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3742 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3743 if (psrch_inf
->smallBuf
)
3744 cifs_small_buf_release(
3745 psrch_inf
->ntwrk_buf_start
);
3747 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3748 psrch_inf
->srch_entries_start
= response_data
;
3749 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3750 psrch_inf
->smallBuf
= 0;
3751 if (parms
->EndofSearch
)
3752 psrch_inf
->endOfSearch
= true;
3754 psrch_inf
->endOfSearch
= false;
3755 psrch_inf
->entries_in_buffer
=
3756 le16_to_cpu(parms
->SearchCount
);
3757 psrch_inf
->index_of_last_entry
+=
3758 psrch_inf
->entries_in_buffer
;
3759 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3760 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3762 /* BB fixme add unlock here */
3767 /* BB On error, should we leave previous search buf (and count and
3768 last entry fields) intact or free the previous one? */
3770 /* Note: On -EAGAIN error only caller can retry on handle based calls
3771 since file handle passed in no longer valid */
3774 cifs_buf_release(pSMB
);
3779 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3780 const __u16 searchHandle
)
3783 FINDCLOSE_REQ
*pSMB
= NULL
;
3785 cFYI(1, ("In CIFSSMBFindClose"));
3786 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3788 /* no sense returning error if session restarted
3789 as file handle has been closed */
3795 pSMB
->FileID
= searchHandle
;
3796 pSMB
->ByteCount
= 0;
3797 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3799 cERROR(1, ("Send error in FindClose = %d", rc
));
3801 cifs_stats_inc(&tcon
->num_fclose
);
3803 /* Since session is dead, search handle closed on server already */
3811 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3812 const unsigned char *searchName
,
3813 __u64
*inode_number
,
3814 const struct nls_table
*nls_codepage
, int remap
)
3817 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3818 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3819 int name_len
, bytes_returned
;
3820 __u16 params
, byte_count
;
3822 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3826 GetInodeNumberRetry
:
3827 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3832 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3834 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3835 PATH_MAX
, nls_codepage
, remap
);
3836 name_len
++; /* trailing null */
3838 } else { /* BB improve the check for buffer overruns BB */
3839 name_len
= strnlen(searchName
, PATH_MAX
);
3840 name_len
++; /* trailing null */
3841 strncpy(pSMB
->FileName
, searchName
, name_len
);
3844 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3845 pSMB
->TotalDataCount
= 0;
3846 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3847 /* BB find exact max data count below from sess structure BB */
3848 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3849 pSMB
->MaxSetupCount
= 0;
3853 pSMB
->Reserved2
= 0;
3854 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3855 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3856 pSMB
->DataCount
= 0;
3857 pSMB
->DataOffset
= 0;
3858 pSMB
->SetupCount
= 1;
3859 pSMB
->Reserved3
= 0;
3860 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3861 byte_count
= params
+ 1 /* pad */ ;
3862 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3863 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3864 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3865 pSMB
->Reserved4
= 0;
3866 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3867 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3869 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3870 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3872 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3874 /* decode response */
3875 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3876 if (rc
|| (pSMBr
->ByteCount
< 2))
3877 /* BB also check enough total bytes returned */
3878 /* If rc should we check for EOPNOSUPP and
3879 disable the srvino flag? or in caller? */
3880 rc
= -EIO
; /* bad smb */
3882 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3883 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3884 struct file_internal_info
*pfinfo
;
3885 /* BB Do we need a cast or hash here ? */
3887 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3889 goto GetInodeNumOut
;
3891 pfinfo
= (struct file_internal_info
*)
3892 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3893 *inode_number
= pfinfo
->UniqueId
;
3897 cifs_buf_release(pSMB
);
3899 goto GetInodeNumberRetry
;
3903 /* parses DFS refferal V3 structure
3904 * caller is responsible for freeing target_nodes
3907 * on failure - errno
3910 parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
3911 unsigned int *num_of_nodes
,
3912 struct dfs_info3_param
**target_nodes
,
3913 const struct nls_table
*nls_codepage
)
3918 struct dfs_referral_level_3
*ref
;
3920 is_unicode
= pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
;
3921 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3923 if (*num_of_nodes
< 1) {
3924 cERROR(1, ("num_referrals: must be at least > 0,"
3925 "but we get num_referrals = %d\n", *num_of_nodes
));
3927 goto parse_DFS_REFERRALS_exit
;
3930 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
3931 if (ref
->VersionNumber
!= 3) {
3932 cERROR(1, ("Referrals of V%d version are not supported,"
3933 "should be V3", ref
->VersionNumber
));
3935 goto parse_DFS_REFERRALS_exit
;
3938 /* get the upper boundary of the resp buffer */
3939 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
3940 le16_to_cpu(pSMBr
->t2
.DataCount
);
3942 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3944 le16_to_cpu(pSMBr
->DFSFlags
)));
3946 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
3947 *num_of_nodes
, GFP_KERNEL
);
3948 if (*target_nodes
== NULL
) {
3949 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3951 goto parse_DFS_REFERRALS_exit
;
3954 /* collect neccessary data from referrals */
3955 for (i
= 0; i
< *num_of_nodes
; i
++) {
3958 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
3960 node
->flags
= le16_to_cpu(pSMBr
->DFSFlags
);
3961 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
3962 node
->server_type
= le16_to_cpu(ref
->ServerType
);
3963 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
3966 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
3967 max_len
= data_end
- temp
;
3968 rc
= cifs_strncpy_to_host(&(node
->path_name
), temp
,
3969 max_len
, is_unicode
, nls_codepage
);
3971 goto parse_DFS_REFERRALS_exit
;
3973 /* copy link target UNC */
3974 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
3975 max_len
= data_end
- temp
;
3976 rc
= cifs_strncpy_to_host(&(node
->node_name
), temp
,
3977 max_len
, is_unicode
, nls_codepage
);
3979 goto parse_DFS_REFERRALS_exit
;
3984 parse_DFS_REFERRALS_exit
:
3986 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
3987 *target_nodes
= NULL
;
3994 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3995 const unsigned char *searchName
,
3996 struct dfs_info3_param
**target_nodes
,
3997 unsigned int *num_of_nodes
,
3998 const struct nls_table
*nls_codepage
, int remap
)
4000 /* TRANS2_GET_DFS_REFERRAL */
4001 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4002 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4006 __u16 params
, byte_count
;
4008 *target_nodes
= NULL
;
4010 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
4014 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4019 /* server pointer checked in called function,
4020 but should never be null here anyway */
4021 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4022 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4023 pSMB
->hdr
.Uid
= ses
->Suid
;
4024 if (ses
->capabilities
& CAP_STATUS32
)
4025 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4026 if (ses
->capabilities
& CAP_DFS
)
4027 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4029 if (ses
->capabilities
& CAP_UNICODE
) {
4030 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4032 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4033 searchName
, PATH_MAX
, nls_codepage
, remap
);
4034 name_len
++; /* trailing null */
4036 } else { /* BB improve the check for buffer overruns BB */
4037 name_len
= strnlen(searchName
, PATH_MAX
);
4038 name_len
++; /* trailing null */
4039 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4043 if (ses
->server
->secMode
&
4044 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4045 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4048 pSMB
->hdr
.Uid
= ses
->Suid
;
4050 params
= 2 /* level */ + name_len
/*includes null */ ;
4051 pSMB
->TotalDataCount
= 0;
4052 pSMB
->DataCount
= 0;
4053 pSMB
->DataOffset
= 0;
4054 pSMB
->MaxParameterCount
= 0;
4055 /* BB find exact max SMB PDU from sess structure BB */
4056 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4057 pSMB
->MaxSetupCount
= 0;
4061 pSMB
->Reserved2
= 0;
4062 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4063 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4064 pSMB
->SetupCount
= 1;
4065 pSMB
->Reserved3
= 0;
4066 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4067 byte_count
= params
+ 3 /* pad */ ;
4068 pSMB
->ParameterCount
= cpu_to_le16(params
);
4069 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4070 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4071 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4072 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4074 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4075 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4077 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
4080 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4082 /* BB Also check if enough total bytes returned? */
4083 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4084 rc
= -EIO
; /* bad smb */
4088 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4090 le16_to_cpu(pSMBr
->t2
.DataOffset
)));
4092 /* parse returned result into more usable form */
4093 rc
= parse_DFS_REFERRALS(pSMBr
, num_of_nodes
,
4094 target_nodes
, nls_codepage
);
4098 cifs_buf_release(pSMB
);
4106 /* Query File System Info such as free space to old servers such as Win 9x */
4108 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4110 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4111 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4112 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4113 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4115 int bytes_returned
= 0;
4116 __u16 params
, byte_count
;
4118 cFYI(1, ("OldQFSInfo"));
4120 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4125 params
= 2; /* level */
4126 pSMB
->TotalDataCount
= 0;
4127 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4128 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4129 pSMB
->MaxSetupCount
= 0;
4133 pSMB
->Reserved2
= 0;
4134 byte_count
= params
+ 1 /* pad */ ;
4135 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4136 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4137 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4138 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4139 pSMB
->DataCount
= 0;
4140 pSMB
->DataOffset
= 0;
4141 pSMB
->SetupCount
= 1;
4142 pSMB
->Reserved3
= 0;
4143 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4144 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4145 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4146 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4148 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4149 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4151 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4152 } else { /* decode response */
4153 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4155 if (rc
|| (pSMBr
->ByteCount
< 18))
4156 rc
= -EIO
; /* bad smb */
4158 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4159 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4160 pSMBr
->ByteCount
, data_offset
));
4162 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4163 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4165 le16_to_cpu(response_data
->BytesPerSector
) *
4166 le32_to_cpu(response_data
->
4167 SectorsPerAllocationUnit
);
4169 le32_to_cpu(response_data
->TotalAllocationUnits
);
4170 FSData
->f_bfree
= FSData
->f_bavail
=
4171 le32_to_cpu(response_data
->FreeAllocationUnits
);
4173 ("Blocks: %lld Free: %lld Block size %ld",
4174 (unsigned long long)FSData
->f_blocks
,
4175 (unsigned long long)FSData
->f_bfree
,
4179 cifs_buf_release(pSMB
);
4182 goto oldQFSInfoRetry
;
4188 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4190 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4191 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4192 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4193 FILE_SYSTEM_INFO
*response_data
;
4195 int bytes_returned
= 0;
4196 __u16 params
, byte_count
;
4198 cFYI(1, ("In QFSInfo"));
4200 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4205 params
= 2; /* level */
4206 pSMB
->TotalDataCount
= 0;
4207 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4208 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4209 pSMB
->MaxSetupCount
= 0;
4213 pSMB
->Reserved2
= 0;
4214 byte_count
= params
+ 1 /* pad */ ;
4215 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4216 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4217 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4218 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4219 pSMB
->DataCount
= 0;
4220 pSMB
->DataOffset
= 0;
4221 pSMB
->SetupCount
= 1;
4222 pSMB
->Reserved3
= 0;
4223 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4224 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4225 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4226 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4228 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4229 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4231 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4232 } else { /* decode response */
4233 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4235 if (rc
|| (pSMBr
->ByteCount
< 24))
4236 rc
= -EIO
; /* bad smb */
4238 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4242 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4245 le32_to_cpu(response_data
->BytesPerSector
) *
4246 le32_to_cpu(response_data
->
4247 SectorsPerAllocationUnit
);
4249 le64_to_cpu(response_data
->TotalAllocationUnits
);
4250 FSData
->f_bfree
= FSData
->f_bavail
=
4251 le64_to_cpu(response_data
->FreeAllocationUnits
);
4253 ("Blocks: %lld Free: %lld Block size %ld",
4254 (unsigned long long)FSData
->f_blocks
,
4255 (unsigned long long)FSData
->f_bfree
,
4259 cifs_buf_release(pSMB
);
4268 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4270 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4271 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4272 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4273 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4275 int bytes_returned
= 0;
4276 __u16 params
, byte_count
;
4278 cFYI(1, ("In QFSAttributeInfo"));
4280 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4285 params
= 2; /* level */
4286 pSMB
->TotalDataCount
= 0;
4287 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4288 /* BB find exact max SMB PDU from sess structure BB */
4289 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4290 pSMB
->MaxSetupCount
= 0;
4294 pSMB
->Reserved2
= 0;
4295 byte_count
= params
+ 1 /* pad */ ;
4296 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4297 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4298 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4299 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4300 pSMB
->DataCount
= 0;
4301 pSMB
->DataOffset
= 0;
4302 pSMB
->SetupCount
= 1;
4303 pSMB
->Reserved3
= 0;
4304 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4305 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4306 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4307 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4309 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4310 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4312 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4313 } else { /* decode response */
4314 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4316 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4317 /* BB also check if enough bytes returned */
4318 rc
= -EIO
; /* bad smb */
4320 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4322 (FILE_SYSTEM_ATTRIBUTE_INFO
4323 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4325 memcpy(&tcon
->fsAttrInfo
, response_data
,
4326 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4329 cifs_buf_release(pSMB
);
4332 goto QFSAttributeRetry
;
4338 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4340 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4341 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4342 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4343 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4345 int bytes_returned
= 0;
4346 __u16 params
, byte_count
;
4348 cFYI(1, ("In QFSDeviceInfo"));
4350 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4355 params
= 2; /* level */
4356 pSMB
->TotalDataCount
= 0;
4357 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4358 /* BB find exact max SMB PDU from sess structure BB */
4359 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4360 pSMB
->MaxSetupCount
= 0;
4364 pSMB
->Reserved2
= 0;
4365 byte_count
= params
+ 1 /* pad */ ;
4366 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4367 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4368 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4369 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4371 pSMB
->DataCount
= 0;
4372 pSMB
->DataOffset
= 0;
4373 pSMB
->SetupCount
= 1;
4374 pSMB
->Reserved3
= 0;
4375 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4376 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4377 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4378 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4380 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4381 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4383 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4384 } else { /* decode response */
4385 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4387 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4388 rc
= -EIO
; /* bad smb */
4390 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4392 (FILE_SYSTEM_DEVICE_INFO
*)
4393 (((char *) &pSMBr
->hdr
.Protocol
) +
4395 memcpy(&tcon
->fsDevInfo
, response_data
,
4396 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4399 cifs_buf_release(pSMB
);
4402 goto QFSDeviceRetry
;
4408 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4410 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4411 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4412 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4413 FILE_SYSTEM_UNIX_INFO
*response_data
;
4415 int bytes_returned
= 0;
4416 __u16 params
, byte_count
;
4418 cFYI(1, ("In QFSUnixInfo"));
4420 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4425 params
= 2; /* level */
4426 pSMB
->TotalDataCount
= 0;
4427 pSMB
->DataCount
= 0;
4428 pSMB
->DataOffset
= 0;
4429 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4430 /* BB find exact max SMB PDU from sess structure BB */
4431 pSMB
->MaxDataCount
= cpu_to_le16(100);
4432 pSMB
->MaxSetupCount
= 0;
4436 pSMB
->Reserved2
= 0;
4437 byte_count
= params
+ 1 /* pad */ ;
4438 pSMB
->ParameterCount
= cpu_to_le16(params
);
4439 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4440 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4441 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4442 pSMB
->SetupCount
= 1;
4443 pSMB
->Reserved3
= 0;
4444 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4445 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4446 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4447 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4449 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4450 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4452 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4453 } else { /* decode response */
4454 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4456 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4457 rc
= -EIO
; /* bad smb */
4459 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4461 (FILE_SYSTEM_UNIX_INFO
4462 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4464 memcpy(&tcon
->fsUnixInfo
, response_data
,
4465 sizeof(FILE_SYSTEM_UNIX_INFO
));
4468 cifs_buf_release(pSMB
);
4478 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4480 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4481 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4482 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4484 int bytes_returned
= 0;
4485 __u16 params
, param_offset
, offset
, byte_count
;
4487 cFYI(1, ("In SETFSUnixInfo"));
4489 /* BB switch to small buf init to save memory */
4490 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4495 params
= 4; /* 2 bytes zero followed by info level. */
4496 pSMB
->MaxSetupCount
= 0;
4500 pSMB
->Reserved2
= 0;
4501 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4503 offset
= param_offset
+ params
;
4505 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4506 /* BB find exact max SMB PDU from sess structure BB */
4507 pSMB
->MaxDataCount
= cpu_to_le16(100);
4508 pSMB
->SetupCount
= 1;
4509 pSMB
->Reserved3
= 0;
4510 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4511 byte_count
= 1 /* pad */ + params
+ 12;
4513 pSMB
->DataCount
= cpu_to_le16(12);
4514 pSMB
->ParameterCount
= cpu_to_le16(params
);
4515 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4516 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4517 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4518 pSMB
->DataOffset
= cpu_to_le16(offset
);
4522 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4525 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4526 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4527 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4529 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4530 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4532 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4533 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4535 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4536 } else { /* decode response */
4537 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4539 rc
= -EIO
; /* bad smb */
4541 cifs_buf_release(pSMB
);
4544 goto SETFSUnixRetry
;
4552 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4553 struct kstatfs
*FSData
)
4555 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4556 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4557 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4558 FILE_SYSTEM_POSIX_INFO
*response_data
;
4560 int bytes_returned
= 0;
4561 __u16 params
, byte_count
;
4563 cFYI(1, ("In QFSPosixInfo"));
4565 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4570 params
= 2; /* level */
4571 pSMB
->TotalDataCount
= 0;
4572 pSMB
->DataCount
= 0;
4573 pSMB
->DataOffset
= 0;
4574 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4575 /* BB find exact max SMB PDU from sess structure BB */
4576 pSMB
->MaxDataCount
= cpu_to_le16(100);
4577 pSMB
->MaxSetupCount
= 0;
4581 pSMB
->Reserved2
= 0;
4582 byte_count
= params
+ 1 /* pad */ ;
4583 pSMB
->ParameterCount
= cpu_to_le16(params
);
4584 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4585 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4586 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4587 pSMB
->SetupCount
= 1;
4588 pSMB
->Reserved3
= 0;
4589 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4590 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4591 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4592 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4594 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4595 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4597 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4598 } else { /* decode response */
4599 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4601 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4602 rc
= -EIO
; /* bad smb */
4604 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4606 (FILE_SYSTEM_POSIX_INFO
4607 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4610 le32_to_cpu(response_data
->BlockSize
);
4612 le64_to_cpu(response_data
->TotalBlocks
);
4614 le64_to_cpu(response_data
->BlocksAvail
);
4615 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4616 FSData
->f_bavail
= FSData
->f_bfree
;
4619 le64_to_cpu(response_data
->UserBlocksAvail
);
4621 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4623 le64_to_cpu(response_data
->TotalFileNodes
);
4624 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4626 le64_to_cpu(response_data
->FreeFileNodes
);
4629 cifs_buf_release(pSMB
);
4638 /* We can not use write of zero bytes trick to
4639 set file size due to need for large file support. Also note that
4640 this SetPathInfo is preferred to SetFileInfo based method in next
4641 routine which is only needed to work around a sharing violation bug
4642 in Samba which this routine can run into */
4645 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4646 __u64 size
, bool SetAllocation
,
4647 const struct nls_table
*nls_codepage
, int remap
)
4649 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4650 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4651 struct file_end_of_file_info
*parm_data
;
4654 int bytes_returned
= 0;
4655 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4657 cFYI(1, ("In SetEOF"));
4659 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4664 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4666 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4667 PATH_MAX
, nls_codepage
, remap
);
4668 name_len
++; /* trailing null */
4670 } else { /* BB improve the check for buffer overruns BB */
4671 name_len
= strnlen(fileName
, PATH_MAX
);
4672 name_len
++; /* trailing null */
4673 strncpy(pSMB
->FileName
, fileName
, name_len
);
4675 params
= 6 + name_len
;
4676 data_count
= sizeof(struct file_end_of_file_info
);
4677 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4678 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4679 pSMB
->MaxSetupCount
= 0;
4683 pSMB
->Reserved2
= 0;
4684 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4685 InformationLevel
) - 4;
4686 offset
= param_offset
+ params
;
4687 if (SetAllocation
) {
4688 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4689 pSMB
->InformationLevel
=
4690 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4692 pSMB
->InformationLevel
=
4693 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4694 } else /* Set File Size */ {
4695 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4696 pSMB
->InformationLevel
=
4697 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4699 pSMB
->InformationLevel
=
4700 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4704 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4706 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4707 pSMB
->DataOffset
= cpu_to_le16(offset
);
4708 pSMB
->SetupCount
= 1;
4709 pSMB
->Reserved3
= 0;
4710 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4711 byte_count
= 3 /* pad */ + params
+ data_count
;
4712 pSMB
->DataCount
= cpu_to_le16(data_count
);
4713 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4714 pSMB
->ParameterCount
= cpu_to_le16(params
);
4715 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4716 pSMB
->Reserved4
= 0;
4717 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4718 parm_data
->FileSize
= cpu_to_le64(size
);
4719 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4720 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4721 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4723 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4725 cifs_buf_release(pSMB
);
4734 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4735 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4737 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4739 struct file_end_of_file_info
*parm_data
;
4741 __u16 params
, param_offset
, offset
, byte_count
, count
;
4743 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4745 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4750 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4751 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4754 pSMB
->MaxSetupCount
= 0;
4758 pSMB
->Reserved2
= 0;
4759 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4760 offset
= param_offset
+ params
;
4762 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4764 count
= sizeof(struct file_end_of_file_info
);
4765 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4766 /* BB find exact max SMB PDU from sess structure BB */
4767 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4768 pSMB
->SetupCount
= 1;
4769 pSMB
->Reserved3
= 0;
4770 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4771 byte_count
= 3 /* pad */ + params
+ count
;
4772 pSMB
->DataCount
= cpu_to_le16(count
);
4773 pSMB
->ParameterCount
= cpu_to_le16(params
);
4774 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4775 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4776 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4778 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4780 pSMB
->DataOffset
= cpu_to_le16(offset
);
4781 parm_data
->FileSize
= cpu_to_le64(size
);
4783 if (SetAllocation
) {
4784 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4785 pSMB
->InformationLevel
=
4786 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4788 pSMB
->InformationLevel
=
4789 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4790 } else /* Set File Size */ {
4791 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4792 pSMB
->InformationLevel
=
4793 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4795 pSMB
->InformationLevel
=
4796 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4798 pSMB
->Reserved4
= 0;
4799 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4800 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4801 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4804 ("Send error in SetFileInfo (SetFileSize) = %d",
4808 /* Note: On -EAGAIN error only caller can retry on handle based calls
4809 since file handle passed in no longer valid */
4814 /* Some legacy servers such as NT4 require that the file times be set on
4815 an open handle, rather than by pathname - this is awkward due to
4816 potential access conflicts on the open, but it is unavoidable for these
4817 old servers since the only other choice is to go from 100 nanosecond DCE
4818 time and resort to the original setpathinfo level which takes the ancient
4819 DOS time format with 2 second granularity */
4821 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
,
4822 const FILE_BASIC_INFO
*data
, __u16 fid
)
4824 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4827 __u16 params
, param_offset
, offset
, byte_count
, count
;
4829 cFYI(1, ("Set Times (via SetFileInfo)"));
4830 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4835 /* At this point there is no need to override the current pid
4836 with the pid of the opener, but that could change if we someday
4837 use an existing handle (rather than opening one on the fly) */
4838 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4839 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4842 pSMB
->MaxSetupCount
= 0;
4846 pSMB
->Reserved2
= 0;
4847 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4848 offset
= param_offset
+ params
;
4850 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4852 count
= sizeof(FILE_BASIC_INFO
);
4853 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4854 /* BB find max SMB PDU from sess */
4855 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4856 pSMB
->SetupCount
= 1;
4857 pSMB
->Reserved3
= 0;
4858 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4859 byte_count
= 3 /* pad */ + params
+ count
;
4860 pSMB
->DataCount
= cpu_to_le16(count
);
4861 pSMB
->ParameterCount
= cpu_to_le16(params
);
4862 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4863 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4864 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4865 pSMB
->DataOffset
= cpu_to_le16(offset
);
4867 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4868 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4870 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4871 pSMB
->Reserved4
= 0;
4872 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4873 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4874 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4875 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4877 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4879 /* Note: On -EAGAIN error only caller can retry on handle based calls
4880 since file handle passed in no longer valid */
4887 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4888 const FILE_BASIC_INFO
*data
,
4889 const struct nls_table
*nls_codepage
, int remap
)
4891 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4892 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4895 int bytes_returned
= 0;
4897 __u16 params
, param_offset
, offset
, byte_count
, count
;
4899 cFYI(1, ("In SetTimes"));
4902 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4907 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4909 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4910 PATH_MAX
, nls_codepage
, remap
);
4911 name_len
++; /* trailing null */
4913 } else { /* BB improve the check for buffer overruns BB */
4914 name_len
= strnlen(fileName
, PATH_MAX
);
4915 name_len
++; /* trailing null */
4916 strncpy(pSMB
->FileName
, fileName
, name_len
);
4919 params
= 6 + name_len
;
4920 count
= sizeof(FILE_BASIC_INFO
);
4921 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4922 /* BB find max SMB PDU from sess structure BB */
4923 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4924 pSMB
->MaxSetupCount
= 0;
4928 pSMB
->Reserved2
= 0;
4929 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4930 InformationLevel
) - 4;
4931 offset
= param_offset
+ params
;
4932 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4933 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4934 pSMB
->DataOffset
= cpu_to_le16(offset
);
4935 pSMB
->SetupCount
= 1;
4936 pSMB
->Reserved3
= 0;
4937 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4938 byte_count
= 3 /* pad */ + params
+ count
;
4940 pSMB
->DataCount
= cpu_to_le16(count
);
4941 pSMB
->ParameterCount
= cpu_to_le16(params
);
4942 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4943 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4944 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4945 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4947 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4948 pSMB
->Reserved4
= 0;
4949 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4950 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4951 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4952 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4953 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4955 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4957 cifs_buf_release(pSMB
);
4965 /* Can not be used to set time stamps yet (due to old DOS time format) */
4966 /* Can be used to set attributes */
4967 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4968 handling it anyway and NT4 was what we thought it would be needed for
4969 Do not delete it until we prove whether needed for Win9x though */
4971 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4972 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4974 SETATTR_REQ
*pSMB
= NULL
;
4975 SETATTR_RSP
*pSMBr
= NULL
;
4980 cFYI(1, ("In SetAttrLegacy"));
4983 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4988 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4990 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4991 PATH_MAX
, nls_codepage
);
4992 name_len
++; /* trailing null */
4994 } else { /* BB improve the check for buffer overruns BB */
4995 name_len
= strnlen(fileName
, PATH_MAX
);
4996 name_len
++; /* trailing null */
4997 strncpy(pSMB
->fileName
, fileName
, name_len
);
4999 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5000 pSMB
->BufferFormat
= 0x04;
5001 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5002 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5003 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5004 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5006 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
5008 cifs_buf_release(pSMB
);
5011 goto SetAttrLgcyRetry
;
5015 #endif /* temporarily unneeded SetAttr legacy function */
5018 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
5019 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
5020 dev_t device
, const struct nls_table
*nls_codepage
,
5023 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5024 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5027 int bytes_returned
= 0;
5028 FILE_UNIX_BASIC_INFO
*data_offset
;
5029 __u16 params
, param_offset
, offset
, count
, byte_count
;
5031 cFYI(1, ("In SetUID/GID/Mode"));
5033 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5038 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5040 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5041 PATH_MAX
, nls_codepage
, remap
);
5042 name_len
++; /* trailing null */
5044 } else { /* BB improve the check for buffer overruns BB */
5045 name_len
= strnlen(fileName
, PATH_MAX
);
5046 name_len
++; /* trailing null */
5047 strncpy(pSMB
->FileName
, fileName
, name_len
);
5050 params
= 6 + name_len
;
5051 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5052 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5053 /* BB find max SMB PDU from sess structure BB */
5054 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5055 pSMB
->MaxSetupCount
= 0;
5059 pSMB
->Reserved2
= 0;
5060 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5061 InformationLevel
) - 4;
5062 offset
= param_offset
+ params
;
5064 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5066 memset(data_offset
, 0, count
);
5067 pSMB
->DataOffset
= cpu_to_le16(offset
);
5068 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5069 pSMB
->SetupCount
= 1;
5070 pSMB
->Reserved3
= 0;
5071 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5072 byte_count
= 3 /* pad */ + params
+ count
;
5073 pSMB
->ParameterCount
= cpu_to_le16(params
);
5074 pSMB
->DataCount
= cpu_to_le16(count
);
5075 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5076 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5077 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5078 pSMB
->Reserved4
= 0;
5079 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5080 /* Samba server ignores set of file size to zero due to bugs in some
5081 older clients, but we should be precise - we use SetFileSize to
5082 set file size and do not want to truncate file size to zero
5083 accidently as happened on one Samba server beta by putting
5084 zero instead of -1 here */
5085 data_offset
->EndOfFile
= NO_CHANGE_64
;
5086 data_offset
->NumOfBytes
= NO_CHANGE_64
;
5087 data_offset
->LastStatusChange
= NO_CHANGE_64
;
5088 data_offset
->LastAccessTime
= NO_CHANGE_64
;
5089 data_offset
->LastModificationTime
= NO_CHANGE_64
;
5090 data_offset
->Uid
= cpu_to_le64(uid
);
5091 data_offset
->Gid
= cpu_to_le64(gid
);
5092 /* better to leave device as zero when it is */
5093 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
5094 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
5095 data_offset
->Permissions
= cpu_to_le64(mode
);
5098 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5099 else if (S_ISDIR(mode
))
5100 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5101 else if (S_ISLNK(mode
))
5102 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5103 else if (S_ISCHR(mode
))
5104 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5105 else if (S_ISBLK(mode
))
5106 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5107 else if (S_ISFIFO(mode
))
5108 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5109 else if (S_ISSOCK(mode
))
5110 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5113 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5114 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5115 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5117 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5120 cifs_buf_release(pSMB
);
5126 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5127 const int notify_subdirs
, const __u16 netfid
,
5128 __u32 filter
, struct file
*pfile
, int multishot
,
5129 const struct nls_table
*nls_codepage
)
5132 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5133 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5134 struct dir_notify_req
*dnotify_req
;
5137 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5138 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5143 pSMB
->TotalParameterCount
= 0 ;
5144 pSMB
->TotalDataCount
= 0;
5145 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5146 /* BB find exact data count max from sess structure BB */
5147 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5148 /* BB VERIFY verify which is correct for above BB */
5149 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5150 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5152 pSMB
->MaxSetupCount
= 4;
5154 pSMB
->ParameterOffset
= 0;
5155 pSMB
->DataCount
= 0;
5156 pSMB
->DataOffset
= 0;
5157 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5158 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5159 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5161 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5162 pSMB
->Reserved2
= 0;
5163 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5164 pSMB
->Fid
= netfid
; /* file handle always le */
5165 pSMB
->ByteCount
= 0;
5167 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5168 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5171 cFYI(1, ("Error in Notify = %d", rc
));
5173 /* Add file to outstanding requests */
5174 /* BB change to kmem cache alloc */
5175 dnotify_req
= kmalloc(
5176 sizeof(struct dir_notify_req
),
5179 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5180 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5181 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5182 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5183 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5184 dnotify_req
->netfid
= netfid
;
5185 dnotify_req
->pfile
= pfile
;
5186 dnotify_req
->filter
= filter
;
5187 dnotify_req
->multishot
= multishot
;
5188 spin_lock(&GlobalMid_Lock
);
5189 list_add_tail(&dnotify_req
->lhead
,
5190 &GlobalDnotifyReqList
);
5191 spin_unlock(&GlobalMid_Lock
);
5195 cifs_buf_release(pSMB
);
5198 #ifdef CONFIG_CIFS_XATTR
5200 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5201 const unsigned char *searchName
,
5202 char *EAData
, size_t buf_size
,
5203 const struct nls_table
*nls_codepage
, int remap
)
5205 /* BB assumes one setup word */
5206 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5207 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5211 struct fea
*temp_fea
;
5213 __u16 params
, byte_count
;
5215 cFYI(1, ("In Query All EAs path %s", searchName
));
5217 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5222 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5224 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5225 PATH_MAX
, nls_codepage
, remap
);
5226 name_len
++; /* trailing null */
5228 } else { /* BB improve the check for buffer overruns BB */
5229 name_len
= strnlen(searchName
, PATH_MAX
);
5230 name_len
++; /* trailing null */
5231 strncpy(pSMB
->FileName
, searchName
, name_len
);
5234 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5235 pSMB
->TotalDataCount
= 0;
5236 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5237 /* BB find exact max SMB PDU from sess structure BB */
5238 pSMB
->MaxDataCount
= cpu_to_le16(4000);
5239 pSMB
->MaxSetupCount
= 0;
5243 pSMB
->Reserved2
= 0;
5244 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5245 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5246 pSMB
->DataCount
= 0;
5247 pSMB
->DataOffset
= 0;
5248 pSMB
->SetupCount
= 1;
5249 pSMB
->Reserved3
= 0;
5250 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5251 byte_count
= params
+ 1 /* pad */ ;
5252 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5253 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5254 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5255 pSMB
->Reserved4
= 0;
5256 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5257 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5259 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5260 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5262 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5263 } else { /* decode response */
5264 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5266 /* BB also check enough total bytes returned */
5267 /* BB we need to improve the validity checking
5268 of these trans2 responses */
5269 if (rc
|| (pSMBr
->ByteCount
< 4))
5270 rc
= -EIO
; /* bad smb */
5271 /* else if (pFindData){
5272 memcpy((char *) pFindData,
5273 (char *) &pSMBr->hdr.Protocol +
5276 /* check that length of list is not more than bcc */
5277 /* check that each entry does not go beyond length
5279 /* check that each element of each entry does not
5280 go beyond end of list */
5281 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5282 struct fealist
*ea_response_data
;
5284 /* validate_trans2_offsets() */
5285 /* BB check if start of smb + data_offset > &bcc+ bcc */
5286 ea_response_data
= (struct fealist
*)
5287 (((char *) &pSMBr
->hdr
.Protocol
) +
5289 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5290 cFYI(1, ("ea length %d", name_len
));
5291 if (name_len
<= 8) {
5292 /* returned EA size zeroed at top of function */
5293 cFYI(1, ("empty EA list returned from server"));
5295 /* account for ea list len */
5297 temp_fea
= ea_response_data
->list
;
5298 temp_ptr
= (char *)temp_fea
;
5299 while (name_len
> 0) {
5303 rc
+= temp_fea
->name_len
;
5304 /* account for prefix user. and trailing null */
5306 if (rc
< (int)buf_size
) {
5307 memcpy(EAData
, "user.", 5);
5309 memcpy(EAData
, temp_ptr
,
5310 temp_fea
->name_len
);
5311 EAData
+= temp_fea
->name_len
;
5312 /* null terminate name */
5314 EAData
= EAData
+ 1;
5315 } else if (buf_size
== 0) {
5316 /* skip copy - calc size only */
5318 /* stop before overrun buffer */
5322 name_len
-= temp_fea
->name_len
;
5323 temp_ptr
+= temp_fea
->name_len
;
5324 /* account for trailing null */
5328 le16_to_cpu(temp_fea
->value_len
);
5329 name_len
-= value_len
;
5330 temp_ptr
+= value_len
;
5331 /* BB check that temp_ptr is still
5334 /* no trailing null to account for
5336 /* go on to next EA */
5337 temp_fea
= (struct fea
*)temp_ptr
;
5343 cifs_buf_release(pSMB
);
5350 ssize_t
CIFSSMBQueryEA(const int xid
, struct cifsTconInfo
*tcon
,
5351 const unsigned char *searchName
, const unsigned char *ea_name
,
5352 unsigned char *ea_value
, size_t buf_size
,
5353 const struct nls_table
*nls_codepage
, int remap
)
5355 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5356 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5360 struct fea
*temp_fea
;
5362 __u16 params
, byte_count
;
5364 cFYI(1, ("In Query EA path %s", searchName
));
5366 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5371 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5373 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5374 PATH_MAX
, nls_codepage
, remap
);
5375 name_len
++; /* trailing null */
5377 } else { /* BB improve the check for buffer overruns BB */
5378 name_len
= strnlen(searchName
, PATH_MAX
);
5379 name_len
++; /* trailing null */
5380 strncpy(pSMB
->FileName
, searchName
, name_len
);
5383 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5384 pSMB
->TotalDataCount
= 0;
5385 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5386 /* BB find exact max SMB PDU from sess structure BB */
5387 pSMB
->MaxDataCount
= cpu_to_le16(4000);
5388 pSMB
->MaxSetupCount
= 0;
5392 pSMB
->Reserved2
= 0;
5393 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5394 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5395 pSMB
->DataCount
= 0;
5396 pSMB
->DataOffset
= 0;
5397 pSMB
->SetupCount
= 1;
5398 pSMB
->Reserved3
= 0;
5399 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5400 byte_count
= params
+ 1 /* pad */ ;
5401 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5402 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5403 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5404 pSMB
->Reserved4
= 0;
5405 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5406 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5408 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5409 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5411 cFYI(1, ("Send error in Query EA = %d", rc
));
5412 } else { /* decode response */
5413 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5415 /* BB also check enough total bytes returned */
5416 /* BB we need to improve the validity checking
5417 of these trans2 responses */
5418 if (rc
|| (pSMBr
->ByteCount
< 4))
5419 rc
= -EIO
; /* bad smb */
5420 /* else if (pFindData){
5421 memcpy((char *) pFindData,
5422 (char *) &pSMBr->hdr.Protocol +
5425 /* check that length of list is not more than bcc */
5426 /* check that each entry does not go beyond length
5428 /* check that each element of each entry does not
5429 go beyond end of list */
5430 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5431 struct fealist
*ea_response_data
;
5433 /* validate_trans2_offsets() */
5434 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5435 ea_response_data
= (struct fealist
*)
5436 (((char *) &pSMBr
->hdr
.Protocol
) +
5438 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5439 cFYI(1, ("ea length %d", name_len
));
5440 if (name_len
<= 8) {
5441 /* returned EA size zeroed at top of function */
5442 cFYI(1, ("empty EA list returned from server"));
5444 /* account for ea list len */
5446 temp_fea
= ea_response_data
->list
;
5447 temp_ptr
= (char *)temp_fea
;
5448 /* loop through checking if we have a matching
5449 name and then return the associated value */
5450 while (name_len
> 0) {
5455 le16_to_cpu(temp_fea
->value_len
);
5456 /* BB validate that value_len falls within SMB,
5457 even though maximum for name_len is 255 */
5458 if (memcmp(temp_fea
->name
, ea_name
,
5459 temp_fea
->name_len
) == 0) {
5462 /* account for prefix user. and trailing null */
5463 if (rc
<= (int)buf_size
) {
5465 temp_fea
->name
+temp_fea
->name_len
+1,
5467 /* ea values, unlike ea
5470 } else if (buf_size
== 0) {
5471 /* skip copy - calc size only */
5473 /* stop before overrun buffer */
5478 name_len
-= temp_fea
->name_len
;
5479 temp_ptr
+= temp_fea
->name_len
;
5480 /* account for trailing null */
5483 name_len
-= value_len
;
5484 temp_ptr
+= value_len
;
5485 /* No trailing null to account for in
5486 value_len. Go on to next EA */
5487 temp_fea
= (struct fea
*)temp_ptr
;
5493 cifs_buf_release(pSMB
);
5501 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5502 const char *ea_name
, const void *ea_value
,
5503 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5506 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5507 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5508 struct fealist
*parm_data
;
5511 int bytes_returned
= 0;
5512 __u16 params
, param_offset
, byte_count
, offset
, count
;
5514 cFYI(1, ("In SetEA"));
5516 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5521 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5523 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5524 PATH_MAX
, nls_codepage
, remap
);
5525 name_len
++; /* trailing null */
5527 } else { /* BB improve the check for buffer overruns BB */
5528 name_len
= strnlen(fileName
, PATH_MAX
);
5529 name_len
++; /* trailing null */
5530 strncpy(pSMB
->FileName
, fileName
, name_len
);
5533 params
= 6 + name_len
;
5535 /* done calculating parms using name_len of file name,
5536 now use name_len to calculate length of ea name
5537 we are going to create in the inode xattrs */
5538 if (ea_name
== NULL
)
5541 name_len
= strnlen(ea_name
, 255);
5543 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5544 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5545 /* BB find max SMB PDU from sess */
5546 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5547 pSMB
->MaxSetupCount
= 0;
5551 pSMB
->Reserved2
= 0;
5552 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5553 InformationLevel
) - 4;
5554 offset
= param_offset
+ params
;
5555 pSMB
->InformationLevel
=
5556 cpu_to_le16(SMB_SET_FILE_EA
);
5559 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5561 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5562 pSMB
->DataOffset
= cpu_to_le16(offset
);
5563 pSMB
->SetupCount
= 1;
5564 pSMB
->Reserved3
= 0;
5565 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5566 byte_count
= 3 /* pad */ + params
+ count
;
5567 pSMB
->DataCount
= cpu_to_le16(count
);
5568 parm_data
->list_len
= cpu_to_le32(count
);
5569 parm_data
->list
[0].EA_flags
= 0;
5570 /* we checked above that name len is less than 255 */
5571 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5572 /* EA names are always ASCII */
5574 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5575 parm_data
->list
[0].name
[name_len
] = 0;
5576 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5577 /* caller ensures that ea_value_len is less than 64K but
5578 we need to ensure that it fits within the smb */
5580 /*BB add length check to see if it would fit in
5581 negotiated SMB buffer size BB */
5582 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5584 memcpy(parm_data
->list
[0].name
+name_len
+1,
5585 ea_value
, ea_value_len
);
5587 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5588 pSMB
->ParameterCount
= cpu_to_le16(params
);
5589 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5590 pSMB
->Reserved4
= 0;
5591 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5592 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5593 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5594 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5596 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5598 cifs_buf_release(pSMB
);