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
);
110 (*dst
)[plen
+1] = 0; /* harmless for ASCII case, needed for Unicode */
113 cifs_strncpy_to_host_ErrExit
:
114 cERROR(1, ("Failed to allocate buffer for string\n"));
119 /* Mark as invalid, all open files on tree connections since they
120 were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo
*pTcon
)
123 struct cifsFileInfo
*open_file
= NULL
;
124 struct list_head
*tmp
;
125 struct list_head
*tmp1
;
127 /* list all files open on tree connection and mark them invalid */
128 write_lock(&GlobalSMBSeslock
);
129 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
130 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
.
694 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
696 #ifdef CONFIG_CIFS_WEAK_PW_HASH
699 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
700 /* MUST_SIGN already includes the MAY_SIGN FLAG
701 so if this is zero it means that signing is disabled */
702 cFYI(1, ("Signing disabled"));
703 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
704 cERROR(1, ("Server requires "
705 "packet signing to be enabled in "
706 "/proc/fs/cifs/SecurityFlags."));
710 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
711 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
712 /* signing required */
713 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
714 if ((server
->secMode
&
715 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
717 ("signing required but server lacks support"));
720 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
722 /* signing optional ie CIFSSEC_MAY_SIGN */
723 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
725 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
729 cifs_buf_release(pSMB
);
731 cFYI(1, ("negprot rc %d", rc
));
736 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
738 struct smb_hdr
*smb_buffer
;
741 cFYI(1, ("In tree disconnect"));
743 * If last user of the connection and
744 * connection alive - disconnect it
745 * If this is the last connection on the server session disconnect it
746 * (and inside session disconnect we should check if tcp socket needs
747 * to be freed and kernel thread woken up).
750 down(&tcon
->tconSem
);
754 atomic_dec(&tcon
->useCount
);
755 if (atomic_read(&tcon
->useCount
) > 0) {
760 /* No need to return error on this operation if tid invalidated and
761 closed on server already e.g. due to tcp session crashing */
762 if (tcon
->tidStatus
== CifsNeedReconnect
) {
767 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
771 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
772 (void **)&smb_buffer
);
778 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
780 cFYI(1, ("Tree disconnect failed %d", rc
));
784 /* No need to return error on this operation if tid invalidated and
785 closed on server already e.g. due to tcp session crashing */
793 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
795 LOGOFF_ANDX_REQ
*pSMB
;
798 cFYI(1, ("In SMBLogoff for session disconnect"));
804 atomic_dec(&ses
->inUse
);
805 if (atomic_read(&ses
->inUse
) > 0) {
809 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
816 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
818 if (ses
->server
->secMode
&
819 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
820 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
823 pSMB
->hdr
.Uid
= ses
->Suid
;
825 pSMB
->AndXCommand
= 0xFF;
826 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
828 atomic_dec(&ses
->server
->socketUseCount
);
829 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
830 spin_lock(&GlobalMid_Lock
);
831 ses
->server
->tcpStatus
= CifsExiting
;
832 spin_unlock(&GlobalMid_Lock
);
838 /* if session dead then we do not need to do ulogoff,
839 since server closed smb session, no sense reporting
847 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
848 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
850 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
851 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
852 struct unlink_psx_rq
*pRqD
;
855 int bytes_returned
= 0;
856 __u16 params
, param_offset
, offset
, byte_count
;
858 cFYI(1, ("In POSIX delete"));
860 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
865 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
867 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
868 PATH_MAX
, nls_codepage
, remap
);
869 name_len
++; /* trailing null */
871 } else { /* BB add path length overrun check */
872 name_len
= strnlen(fileName
, PATH_MAX
);
873 name_len
++; /* trailing null */
874 strncpy(pSMB
->FileName
, fileName
, name_len
);
877 params
= 6 + name_len
;
878 pSMB
->MaxParameterCount
= cpu_to_le16(2);
879 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
880 pSMB
->MaxSetupCount
= 0;
885 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
886 InformationLevel
) - 4;
887 offset
= param_offset
+ params
;
889 /* Setup pointer to Request Data (inode type) */
890 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
891 pRqD
->type
= cpu_to_le16(type
);
892 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
893 pSMB
->DataOffset
= cpu_to_le16(offset
);
894 pSMB
->SetupCount
= 1;
896 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
897 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
899 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
900 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
901 pSMB
->ParameterCount
= cpu_to_le16(params
);
902 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
903 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
905 pSMB
->hdr
.smb_buf_length
+= byte_count
;
906 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
907 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
908 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
910 cFYI(1, ("Posix delete returned %d", rc
));
911 cifs_buf_release(pSMB
);
913 cifs_stats_inc(&tcon
->num_deletes
);
922 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
923 const struct nls_table
*nls_codepage
, int remap
)
925 DELETE_FILE_REQ
*pSMB
= NULL
;
926 DELETE_FILE_RSP
*pSMBr
= NULL
;
932 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
937 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
939 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
940 PATH_MAX
, nls_codepage
, remap
);
941 name_len
++; /* trailing null */
943 } else { /* BB improve check for buffer overruns BB */
944 name_len
= strnlen(fileName
, PATH_MAX
);
945 name_len
++; /* trailing null */
946 strncpy(pSMB
->fileName
, fileName
, name_len
);
948 pSMB
->SearchAttributes
=
949 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
950 pSMB
->BufferFormat
= 0x04;
951 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
952 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
953 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
954 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
955 cifs_stats_inc(&tcon
->num_deletes
);
957 cFYI(1, ("Error in RMFile = %d", rc
));
959 cifs_buf_release(pSMB
);
967 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
968 const struct nls_table
*nls_codepage
, int remap
)
970 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
971 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
976 cFYI(1, ("In CIFSSMBRmDir"));
978 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
983 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
984 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
985 PATH_MAX
, nls_codepage
, remap
);
986 name_len
++; /* trailing null */
988 } else { /* BB improve check for buffer overruns BB */
989 name_len
= strnlen(dirName
, PATH_MAX
);
990 name_len
++; /* trailing null */
991 strncpy(pSMB
->DirName
, dirName
, name_len
);
994 pSMB
->BufferFormat
= 0x04;
995 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
996 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
997 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
998 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
999 cifs_stats_inc(&tcon
->num_rmdirs
);
1001 cFYI(1, ("Error in RMDir = %d", rc
));
1003 cifs_buf_release(pSMB
);
1010 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
1011 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
1014 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
1015 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
1019 cFYI(1, ("In CIFSSMBMkDir"));
1021 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
1026 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1027 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
1028 PATH_MAX
, nls_codepage
, remap
);
1029 name_len
++; /* trailing null */
1031 } else { /* BB improve check for buffer overruns BB */
1032 name_len
= strnlen(name
, PATH_MAX
);
1033 name_len
++; /* trailing null */
1034 strncpy(pSMB
->DirName
, name
, name_len
);
1037 pSMB
->BufferFormat
= 0x04;
1038 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
1039 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
1040 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1041 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1042 cifs_stats_inc(&tcon
->num_mkdirs
);
1044 cFYI(1, ("Error in Mkdir = %d", rc
));
1046 cifs_buf_release(pSMB
);
1053 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1054 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1055 __u32
*pOplock
, const char *name
,
1056 const struct nls_table
*nls_codepage
, int remap
)
1058 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1059 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1062 int bytes_returned
= 0;
1063 __u16 params
, param_offset
, offset
, byte_count
, count
;
1064 OPEN_PSX_REQ
*pdata
;
1065 OPEN_PSX_RSP
*psx_rsp
;
1067 cFYI(1, ("In POSIX Create"));
1069 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1074 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1076 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1077 PATH_MAX
, nls_codepage
, remap
);
1078 name_len
++; /* trailing null */
1080 } else { /* BB improve the check for buffer overruns BB */
1081 name_len
= strnlen(name
, PATH_MAX
);
1082 name_len
++; /* trailing null */
1083 strncpy(pSMB
->FileName
, name
, name_len
);
1086 params
= 6 + name_len
;
1087 count
= sizeof(OPEN_PSX_REQ
);
1088 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1089 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1090 pSMB
->MaxSetupCount
= 0;
1094 pSMB
->Reserved2
= 0;
1095 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1096 InformationLevel
) - 4;
1097 offset
= param_offset
+ params
;
1098 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1099 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1100 pdata
->Permissions
= cpu_to_le64(mode
);
1101 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1102 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1103 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1104 pSMB
->DataOffset
= cpu_to_le16(offset
);
1105 pSMB
->SetupCount
= 1;
1106 pSMB
->Reserved3
= 0;
1107 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1108 byte_count
= 3 /* pad */ + params
+ count
;
1110 pSMB
->DataCount
= cpu_to_le16(count
);
1111 pSMB
->ParameterCount
= cpu_to_le16(params
);
1112 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1113 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1114 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1115 pSMB
->Reserved4
= 0;
1116 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1117 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1118 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1119 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1121 cFYI(1, ("Posix create returned %d", rc
));
1122 goto psx_create_err
;
1125 cFYI(1, ("copying inode info"));
1126 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1128 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1129 rc
= -EIO
; /* bad smb */
1130 goto psx_create_err
;
1133 /* copy return information to pRetData */
1134 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1135 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1137 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1139 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1140 /* Let caller know file was created so we can set the mode. */
1141 /* Do we care about the CreateAction in any other cases? */
1142 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1143 *pOplock
|= CIFS_CREATE_ACTION
;
1144 /* check to make sure response data is there */
1145 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1146 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1147 cFYI(DBG2
, ("unknown type"));
1149 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1150 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1151 cERROR(1, ("Open response data too small"));
1152 pRetData
->Type
= cpu_to_le32(-1);
1153 goto psx_create_err
;
1155 memcpy((char *) pRetData
,
1156 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1157 sizeof(FILE_UNIX_BASIC_INFO
));
1161 cifs_buf_release(pSMB
);
1163 cifs_stats_inc(&tcon
->num_mkdirs
);
1171 static __u16
convert_disposition(int disposition
)
1175 switch (disposition
) {
1176 case FILE_SUPERSEDE
:
1177 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1180 ofun
= SMBOPEN_OAPPEND
;
1183 ofun
= SMBOPEN_OCREATE
;
1186 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1188 case FILE_OVERWRITE
:
1189 ofun
= SMBOPEN_OTRUNC
;
1191 case FILE_OVERWRITE_IF
:
1192 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1195 cFYI(1, ("unknown disposition %d", disposition
));
1196 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1202 access_flags_to_smbopen_mode(const int access_flags
)
1204 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1206 if (masked_flags
== GENERIC_READ
)
1207 return SMBOPEN_READ
;
1208 else if (masked_flags
== GENERIC_WRITE
)
1209 return SMBOPEN_WRITE
;
1211 /* just go for read/write */
1212 return SMBOPEN_READWRITE
;
1216 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1217 const char *fileName
, const int openDisposition
,
1218 const int access_flags
, const int create_options
, __u16
*netfid
,
1219 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1220 const struct nls_table
*nls_codepage
, int remap
)
1223 OPENX_REQ
*pSMB
= NULL
;
1224 OPENX_RSP
*pSMBr
= NULL
;
1230 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1235 pSMB
->AndXCommand
= 0xFF; /* none */
1237 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1238 count
= 1; /* account for one byte pad to word boundary */
1240 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1241 fileName
, PATH_MAX
, nls_codepage
, remap
);
1242 name_len
++; /* trailing null */
1244 } else { /* BB improve check for buffer overruns BB */
1245 count
= 0; /* no pad */
1246 name_len
= strnlen(fileName
, PATH_MAX
);
1247 name_len
++; /* trailing null */
1248 strncpy(pSMB
->fileName
, fileName
, name_len
);
1250 if (*pOplock
& REQ_OPLOCK
)
1251 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1252 else if (*pOplock
& REQ_BATCHOPLOCK
)
1253 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1255 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1256 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1257 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1258 /* set file as system file if special file such
1259 as fifo and server expecting SFU style and
1260 no Unix extensions */
1262 if (create_options
& CREATE_OPTION_SPECIAL
)
1263 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1264 else /* BB FIXME BB */
1265 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1267 if (create_options
& CREATE_OPTION_READONLY
)
1268 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1271 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1272 CREATE_OPTIONS_MASK); */
1273 /* BB FIXME END BB */
1275 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1276 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1278 pSMB
->hdr
.smb_buf_length
+= count
;
1280 pSMB
->ByteCount
= cpu_to_le16(count
);
1281 /* long_op set to 1 to allow for oplock break timeouts */
1282 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1283 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1284 cifs_stats_inc(&tcon
->num_opens
);
1286 cFYI(1, ("Error in Open = %d", rc
));
1288 /* BB verify if wct == 15 */
1290 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1292 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1293 /* Let caller know file was created so we can set the mode. */
1294 /* Do we care about the CreateAction in any other cases? */
1296 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1297 *pOplock |= CIFS_CREATE_ACTION; */
1301 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1302 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1303 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1304 pfile_info
->ChangeTime
= 0; /* BB fixme */
1305 pfile_info
->Attributes
=
1306 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1307 /* the file_info buf is endian converted by caller */
1308 pfile_info
->AllocationSize
=
1309 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1310 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1311 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1315 cifs_buf_release(pSMB
);
1322 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1323 const char *fileName
, const int openDisposition
,
1324 const int access_flags
, const int create_options
, __u16
*netfid
,
1325 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1326 const struct nls_table
*nls_codepage
, int remap
)
1329 OPEN_REQ
*pSMB
= NULL
;
1330 OPEN_RSP
*pSMBr
= NULL
;
1336 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1341 pSMB
->AndXCommand
= 0xFF; /* none */
1343 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1344 count
= 1; /* account for one byte pad to word boundary */
1346 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1347 fileName
, PATH_MAX
, nls_codepage
, remap
);
1348 name_len
++; /* trailing null */
1350 pSMB
->NameLength
= cpu_to_le16(name_len
);
1351 } else { /* BB improve check for buffer overruns BB */
1352 count
= 0; /* no pad */
1353 name_len
= strnlen(fileName
, PATH_MAX
);
1354 name_len
++; /* trailing null */
1355 pSMB
->NameLength
= cpu_to_le16(name_len
);
1356 strncpy(pSMB
->fileName
, fileName
, name_len
);
1358 if (*pOplock
& REQ_OPLOCK
)
1359 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1360 else if (*pOplock
& REQ_BATCHOPLOCK
)
1361 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1362 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1363 pSMB
->AllocationSize
= 0;
1364 /* set file as system file if special file such
1365 as fifo and server expecting SFU style and
1366 no Unix extensions */
1367 if (create_options
& CREATE_OPTION_SPECIAL
)
1368 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1370 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1372 /* XP does not handle ATTR_POSIX_SEMANTICS */
1373 /* but it helps speed up case sensitive checks for other
1374 servers such as Samba */
1375 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1376 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1378 if (create_options
& CREATE_OPTION_READONLY
)
1379 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1381 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1382 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1383 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1384 /* BB Expirement with various impersonation levels and verify */
1385 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1386 pSMB
->SecurityFlags
=
1387 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1390 pSMB
->hdr
.smb_buf_length
+= count
;
1392 pSMB
->ByteCount
= cpu_to_le16(count
);
1393 /* long_op set to 1 to allow for oplock break timeouts */
1394 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1395 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1396 cifs_stats_inc(&tcon
->num_opens
);
1398 cFYI(1, ("Error in Open = %d", rc
));
1400 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1401 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1402 /* Let caller know file was created so we can set the mode. */
1403 /* Do we care about the CreateAction in any other cases? */
1404 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1405 *pOplock
|= CIFS_CREATE_ACTION
;
1407 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1408 36 /* CreationTime to Attributes */);
1409 /* the file_info buf is endian converted by caller */
1410 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1411 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1412 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1416 cifs_buf_release(pSMB
);
1423 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1424 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1425 char **buf
, int *pbuf_type
)
1428 READ_REQ
*pSMB
= NULL
;
1429 READ_RSP
*pSMBr
= NULL
;
1430 char *pReadData
= NULL
;
1432 int resp_buf_type
= 0;
1435 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1436 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1439 wct
= 10; /* old style read */
1442 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1446 /* tcon and ses pointer are checked in smb_init */
1447 if (tcon
->ses
->server
== NULL
)
1448 return -ECONNABORTED
;
1450 pSMB
->AndXCommand
= 0xFF; /* none */
1452 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1454 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1455 else if ((lseek
>> 32) > 0) /* can not handle this big offset for old */
1458 pSMB
->Remaining
= 0;
1459 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1460 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1462 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1464 /* old style read */
1465 struct smb_com_readx_req
*pSMBW
=
1466 (struct smb_com_readx_req
*)pSMB
;
1467 pSMBW
->ByteCount
= 0;
1470 iov
[0].iov_base
= (char *)pSMB
;
1471 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1472 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1473 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1474 cifs_stats_inc(&tcon
->num_reads
);
1475 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1477 cERROR(1, ("Send error in read = %d", rc
));
1479 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1480 data_length
= data_length
<< 16;
1481 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1482 *nbytes
= data_length
;
1484 /*check that DataLength would not go beyond end of SMB */
1485 if ((data_length
> CIFSMaxBufSize
)
1486 || (data_length
> count
)) {
1487 cFYI(1, ("bad length %d for count %d",
1488 data_length
, count
));
1492 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1493 le16_to_cpu(pSMBr
->DataOffset
);
1494 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1495 cERROR(1,("Faulting on read rc = %d",rc));
1497 }*/ /* can not use copy_to_user when using page cache*/
1499 memcpy(*buf
, pReadData
, data_length
);
1503 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1505 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1506 cifs_small_buf_release(iov
[0].iov_base
);
1507 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1508 cifs_buf_release(iov
[0].iov_base
);
1509 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1510 /* return buffer to caller to free */
1511 *buf
= iov
[0].iov_base
;
1512 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1513 *pbuf_type
= CIFS_SMALL_BUFFER
;
1514 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1515 *pbuf_type
= CIFS_LARGE_BUFFER
;
1516 } /* else no valid buffer on return - leave as null */
1518 /* Note: On -EAGAIN error only caller can retry on handle based calls
1519 since file handle passed in no longer valid */
1525 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1526 const int netfid
, const unsigned int count
,
1527 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1528 const char __user
*ubuf
, const int long_op
)
1531 WRITE_REQ
*pSMB
= NULL
;
1532 WRITE_RSP
*pSMBr
= NULL
;
1533 int bytes_returned
, wct
;
1537 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1538 if (tcon
->ses
== NULL
)
1539 return -ECONNABORTED
;
1541 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1546 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1550 /* tcon and ses pointer are checked in smb_init */
1551 if (tcon
->ses
->server
== NULL
)
1552 return -ECONNABORTED
;
1554 pSMB
->AndXCommand
= 0xFF; /* none */
1556 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1558 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1559 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1562 pSMB
->Reserved
= 0xFFFFFFFF;
1563 pSMB
->WriteMode
= 0;
1564 pSMB
->Remaining
= 0;
1566 /* Can increase buffer size if buffer is big enough in some cases ie we
1567 can send more if LARGE_WRITE_X capability returned by the server and if
1568 our buffer is big enough or if we convert to iovecs on socket writes
1569 and eliminate the copy to the CIFS buffer */
1570 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1571 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1573 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1577 if (bytes_sent
> count
)
1580 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1582 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1584 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1585 cifs_buf_release(pSMB
);
1588 } else if (count
!= 0) {
1590 cifs_buf_release(pSMB
);
1592 } /* else setting file size with write of zero bytes */
1594 byte_count
= bytes_sent
+ 1; /* pad */
1595 else /* wct == 12 */
1596 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1598 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1599 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1600 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1603 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1604 else { /* old style write has byte count 4 bytes earlier
1606 struct smb_com_writex_req
*pSMBW
=
1607 (struct smb_com_writex_req
*)pSMB
;
1608 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1611 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1612 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1613 cifs_stats_inc(&tcon
->num_writes
);
1615 cFYI(1, ("Send error in write = %d", rc
));
1618 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1619 *nbytes
= (*nbytes
) << 16;
1620 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1623 cifs_buf_release(pSMB
);
1625 /* Note: On -EAGAIN error only caller can retry on handle based calls
1626 since file handle passed in no longer valid */
1632 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1633 const int netfid
, const unsigned int count
,
1634 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1635 int n_vec
, const int long_op
)
1638 WRITE_REQ
*pSMB
= NULL
;
1641 int resp_buf_type
= 0;
1643 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1645 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1649 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1652 /* tcon and ses pointer are checked in smb_init */
1653 if (tcon
->ses
->server
== NULL
)
1654 return -ECONNABORTED
;
1656 pSMB
->AndXCommand
= 0xFF; /* none */
1658 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1660 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1661 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1663 pSMB
->Reserved
= 0xFFFFFFFF;
1664 pSMB
->WriteMode
= 0;
1665 pSMB
->Remaining
= 0;
1668 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1670 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1671 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1672 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1674 pSMB
->hdr
.smb_buf_length
+= count
+1;
1675 else /* wct == 12 */
1676 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1678 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1679 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1680 struct smb_com_writex_req
*pSMBW
=
1681 (struct smb_com_writex_req
*)pSMB
;
1682 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1684 iov
[0].iov_base
= pSMB
;
1686 iov
[0].iov_len
= smb_hdr_len
+ 4;
1687 else /* wct == 12 pad bigger by four bytes */
1688 iov
[0].iov_len
= smb_hdr_len
+ 8;
1691 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1693 cifs_stats_inc(&tcon
->num_writes
);
1695 cFYI(1, ("Send error Write2 = %d", rc
));
1697 } else if (resp_buf_type
== 0) {
1698 /* presumably this can not happen, but best to be safe */
1702 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1703 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1704 *nbytes
= (*nbytes
) << 16;
1705 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1708 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1709 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1710 cifs_small_buf_release(iov
[0].iov_base
);
1711 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1712 cifs_buf_release(iov
[0].iov_base
);
1714 /* Note: On -EAGAIN error only caller can retry on handle based calls
1715 since file handle passed in no longer valid */
1722 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1723 const __u16 smb_file_id
, const __u64 len
,
1724 const __u64 offset
, const __u32 numUnlock
,
1725 const __u32 numLock
, const __u8 lockType
, const bool waitFlag
)
1728 LOCK_REQ
*pSMB
= NULL
;
1729 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1734 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
));
1735 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1740 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1741 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1743 } else if (waitFlag
) {
1744 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1745 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1750 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1751 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1752 pSMB
->LockType
= lockType
;
1753 pSMB
->AndXCommand
= 0xFF; /* none */
1754 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1756 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1757 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1758 /* BB where to store pid high? */
1759 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1760 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1761 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1762 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1763 count
= sizeof(LOCKING_ANDX_RANGE
);
1768 pSMB
->hdr
.smb_buf_length
+= count
;
1769 pSMB
->ByteCount
= cpu_to_le16(count
);
1772 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1773 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1774 cifs_small_buf_release(pSMB
);
1776 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1778 /* SMB buffer freed by function above */
1780 cifs_stats_inc(&tcon
->num_locks
);
1782 cFYI(1, ("Send error in Lock = %d", rc
));
1784 /* Note: On -EAGAIN error only caller can retry on handle based calls
1785 since file handle passed in no longer valid */
1790 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1791 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1792 struct file_lock
*pLockData
, const __u16 lock_type
,
1793 const bool waitFlag
)
1795 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1796 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1797 struct cifs_posix_lock
*parm_data
;
1800 int bytes_returned
= 0;
1801 int resp_buf_type
= 0;
1802 __u16 params
, param_offset
, offset
, byte_count
, count
;
1805 cFYI(1, ("Posix Lock"));
1807 if (pLockData
== NULL
)
1810 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1815 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1818 pSMB
->MaxSetupCount
= 0;
1821 pSMB
->Reserved2
= 0;
1822 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1823 offset
= param_offset
+ params
;
1825 count
= sizeof(struct cifs_posix_lock
);
1826 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1827 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1828 pSMB
->SetupCount
= 1;
1829 pSMB
->Reserved3
= 0;
1831 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1833 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1834 byte_count
= 3 /* pad */ + params
+ count
;
1835 pSMB
->DataCount
= cpu_to_le16(count
);
1836 pSMB
->ParameterCount
= cpu_to_le16(params
);
1837 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1838 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1839 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1840 parm_data
= (struct cifs_posix_lock
*)
1841 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1843 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1845 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1846 parm_data
->lock_flags
= cpu_to_le16(1);
1847 pSMB
->Timeout
= cpu_to_le32(-1);
1851 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1852 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1853 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1855 pSMB
->DataOffset
= cpu_to_le16(offset
);
1856 pSMB
->Fid
= smb_file_id
;
1857 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1858 pSMB
->Reserved4
= 0;
1859 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1860 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1862 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1863 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1865 iov
[0].iov_base
= (char *)pSMB
;
1866 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1867 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1868 &resp_buf_type
, timeout
);
1869 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1870 not try to free it twice below on exit */
1871 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1875 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1876 } else if (get_flag
) {
1877 /* lock structure can be returned on get */
1880 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1882 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1883 rc
= -EIO
; /* bad smb */
1886 if (pLockData
== NULL
) {
1890 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1891 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1892 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1896 parm_data
= (struct cifs_posix_lock
*)
1897 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1898 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1899 pLockData
->fl_type
= F_UNLCK
;
1904 cifs_small_buf_release(pSMB
);
1906 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1907 cifs_small_buf_release(iov
[0].iov_base
);
1908 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1909 cifs_buf_release(iov
[0].iov_base
);
1911 /* Note: On -EAGAIN error only caller can retry on handle based calls
1912 since file handle passed in no longer valid */
1919 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1922 CLOSE_REQ
*pSMB
= NULL
;
1923 cFYI(1, ("In CIFSSMBClose"));
1925 /* do not retry on dead session on close */
1926 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1932 pSMB
->FileID
= (__u16
) smb_file_id
;
1933 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1934 pSMB
->ByteCount
= 0;
1935 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1936 cifs_stats_inc(&tcon
->num_closes
);
1939 /* EINTR is expected when user ctl-c to kill app */
1940 cERROR(1, ("Send error in Close = %d", rc
));
1944 /* Since session is dead, file will be closed on server already */
1952 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1953 const char *fromName
, const char *toName
,
1954 const struct nls_table
*nls_codepage
, int remap
)
1957 RENAME_REQ
*pSMB
= NULL
;
1958 RENAME_RSP
*pSMBr
= NULL
;
1960 int name_len
, name_len2
;
1963 cFYI(1, ("In CIFSSMBRename"));
1965 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1970 pSMB
->BufferFormat
= 0x04;
1971 pSMB
->SearchAttributes
=
1972 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1975 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1977 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1978 PATH_MAX
, nls_codepage
, remap
);
1979 name_len
++; /* trailing null */
1981 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1982 /* protocol requires ASCII signature byte on Unicode string */
1983 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1985 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1986 toName
, PATH_MAX
, nls_codepage
, remap
);
1987 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1988 name_len2
*= 2; /* convert to bytes */
1989 } else { /* BB improve the check for buffer overruns BB */
1990 name_len
= strnlen(fromName
, PATH_MAX
);
1991 name_len
++; /* trailing null */
1992 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1993 name_len2
= strnlen(toName
, PATH_MAX
);
1994 name_len2
++; /* trailing null */
1995 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1996 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1997 name_len2
++; /* trailing null */
1998 name_len2
++; /* signature byte */
2001 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2002 pSMB
->hdr
.smb_buf_length
+= count
;
2003 pSMB
->ByteCount
= cpu_to_le16(count
);
2005 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2006 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2007 cifs_stats_inc(&tcon
->num_renames
);
2009 cFYI(1, ("Send error in rename = %d", rc
));
2011 cifs_buf_release(pSMB
);
2019 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
2020 int netfid
, const char *target_name
,
2021 const struct nls_table
*nls_codepage
, int remap
)
2023 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2024 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2025 struct set_file_rename
*rename_info
;
2027 char dummy_string
[30];
2029 int bytes_returned
= 0;
2031 __u16 params
, param_offset
, offset
, count
, byte_count
;
2033 cFYI(1, ("Rename to File by handle"));
2034 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2040 pSMB
->MaxSetupCount
= 0;
2044 pSMB
->Reserved2
= 0;
2045 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2046 offset
= param_offset
+ params
;
2048 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2049 rename_info
= (struct set_file_rename
*) data_offset
;
2050 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2051 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2052 pSMB
->SetupCount
= 1;
2053 pSMB
->Reserved3
= 0;
2054 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2055 byte_count
= 3 /* pad */ + params
;
2056 pSMB
->ParameterCount
= cpu_to_le16(params
);
2057 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2058 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2059 pSMB
->DataOffset
= cpu_to_le16(offset
);
2060 /* construct random name ".cifs_tmp<inodenum><mid>" */
2061 rename_info
->overwrite
= cpu_to_le32(1);
2062 rename_info
->root_fid
= 0;
2063 /* unicode only call */
2064 if (target_name
== NULL
) {
2065 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2066 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2067 dummy_string
, 24, nls_codepage
, remap
);
2069 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2070 target_name
, PATH_MAX
, nls_codepage
,
2073 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2074 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2075 byte_count
+= count
;
2076 pSMB
->DataCount
= cpu_to_le16(count
);
2077 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2079 pSMB
->InformationLevel
=
2080 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2081 pSMB
->Reserved4
= 0;
2082 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2083 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2084 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2085 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2086 cifs_stats_inc(&pTcon
->num_t2renames
);
2088 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2090 cifs_buf_release(pSMB
);
2092 /* Note: On -EAGAIN error only caller can retry on handle based calls
2093 since file handle passed in no longer valid */
2099 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2100 const __u16 target_tid
, const char *toName
, const int flags
,
2101 const struct nls_table
*nls_codepage
, int remap
)
2104 COPY_REQ
*pSMB
= NULL
;
2105 COPY_RSP
*pSMBr
= NULL
;
2107 int name_len
, name_len2
;
2110 cFYI(1, ("In CIFSSMBCopy"));
2112 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2117 pSMB
->BufferFormat
= 0x04;
2118 pSMB
->Tid2
= target_tid
;
2120 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2122 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2123 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2124 fromName
, PATH_MAX
, nls_codepage
,
2126 name_len
++; /* trailing null */
2128 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2129 /* protocol requires ASCII signature byte on Unicode string */
2130 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2132 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2133 toName
, PATH_MAX
, nls_codepage
, remap
);
2134 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2135 name_len2
*= 2; /* convert to bytes */
2136 } else { /* BB improve the check for buffer overruns BB */
2137 name_len
= strnlen(fromName
, PATH_MAX
);
2138 name_len
++; /* trailing null */
2139 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2140 name_len2
= strnlen(toName
, PATH_MAX
);
2141 name_len2
++; /* trailing null */
2142 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2143 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2144 name_len2
++; /* trailing null */
2145 name_len2
++; /* signature byte */
2148 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2149 pSMB
->hdr
.smb_buf_length
+= count
;
2150 pSMB
->ByteCount
= cpu_to_le16(count
);
2152 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2153 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2155 cFYI(1, ("Send error in copy = %d with %d files copied",
2156 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2158 cifs_buf_release(pSMB
);
2167 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2168 const char *fromName
, const char *toName
,
2169 const struct nls_table
*nls_codepage
)
2171 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2172 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2175 int name_len_target
;
2177 int bytes_returned
= 0;
2178 __u16 params
, param_offset
, offset
, byte_count
;
2180 cFYI(1, ("In Symlink Unix style"));
2182 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2187 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2189 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2190 /* find define for this maxpathcomponent */
2192 name_len
++; /* trailing null */
2195 } else { /* BB improve the check for buffer overruns BB */
2196 name_len
= strnlen(fromName
, PATH_MAX
);
2197 name_len
++; /* trailing null */
2198 strncpy(pSMB
->FileName
, fromName
, name_len
);
2200 params
= 6 + name_len
;
2201 pSMB
->MaxSetupCount
= 0;
2205 pSMB
->Reserved2
= 0;
2206 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2207 InformationLevel
) - 4;
2208 offset
= param_offset
+ params
;
2210 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2211 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2213 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2214 /* find define for this maxpathcomponent */
2216 name_len_target
++; /* trailing null */
2217 name_len_target
*= 2;
2218 } else { /* BB improve the check for buffer overruns BB */
2219 name_len_target
= strnlen(toName
, PATH_MAX
);
2220 name_len_target
++; /* trailing null */
2221 strncpy(data_offset
, toName
, name_len_target
);
2224 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2225 /* BB find exact max on data count below from sess */
2226 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2227 pSMB
->SetupCount
= 1;
2228 pSMB
->Reserved3
= 0;
2229 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2230 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2231 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2232 pSMB
->ParameterCount
= cpu_to_le16(params
);
2233 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2234 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2235 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2236 pSMB
->DataOffset
= cpu_to_le16(offset
);
2237 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2238 pSMB
->Reserved4
= 0;
2239 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2240 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2241 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2242 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2243 cifs_stats_inc(&tcon
->num_symlinks
);
2245 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2247 cifs_buf_release(pSMB
);
2250 goto createSymLinkRetry
;
2256 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2257 const char *fromName
, const char *toName
,
2258 const struct nls_table
*nls_codepage
, int remap
)
2260 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2261 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2264 int name_len_target
;
2266 int bytes_returned
= 0;
2267 __u16 params
, param_offset
, offset
, byte_count
;
2269 cFYI(1, ("In Create Hard link Unix style"));
2270 createHardLinkRetry
:
2271 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2276 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2277 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2278 PATH_MAX
, nls_codepage
, remap
);
2279 name_len
++; /* trailing null */
2282 } else { /* BB improve the check for buffer overruns BB */
2283 name_len
= strnlen(toName
, PATH_MAX
);
2284 name_len
++; /* trailing null */
2285 strncpy(pSMB
->FileName
, toName
, name_len
);
2287 params
= 6 + name_len
;
2288 pSMB
->MaxSetupCount
= 0;
2292 pSMB
->Reserved2
= 0;
2293 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2294 InformationLevel
) - 4;
2295 offset
= param_offset
+ params
;
2297 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2298 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2300 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2301 nls_codepage
, remap
);
2302 name_len_target
++; /* trailing null */
2303 name_len_target
*= 2;
2304 } else { /* BB improve the check for buffer overruns BB */
2305 name_len_target
= strnlen(fromName
, PATH_MAX
);
2306 name_len_target
++; /* trailing null */
2307 strncpy(data_offset
, fromName
, name_len_target
);
2310 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2311 /* BB find exact max on data count below from sess*/
2312 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2313 pSMB
->SetupCount
= 1;
2314 pSMB
->Reserved3
= 0;
2315 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2316 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2317 pSMB
->ParameterCount
= cpu_to_le16(params
);
2318 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2319 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2320 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2321 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2322 pSMB
->DataOffset
= cpu_to_le16(offset
);
2323 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2324 pSMB
->Reserved4
= 0;
2325 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2326 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2327 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2328 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2329 cifs_stats_inc(&tcon
->num_hardlinks
);
2331 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2333 cifs_buf_release(pSMB
);
2335 goto createHardLinkRetry
;
2341 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2342 const char *fromName
, const char *toName
,
2343 const struct nls_table
*nls_codepage
, int remap
)
2346 NT_RENAME_REQ
*pSMB
= NULL
;
2347 RENAME_RSP
*pSMBr
= NULL
;
2349 int name_len
, name_len2
;
2352 cFYI(1, ("In CIFSCreateHardLink"));
2353 winCreateHardLinkRetry
:
2355 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2360 pSMB
->SearchAttributes
=
2361 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2363 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2364 pSMB
->ClusterCount
= 0;
2366 pSMB
->BufferFormat
= 0x04;
2368 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2370 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2371 PATH_MAX
, nls_codepage
, remap
);
2372 name_len
++; /* trailing null */
2374 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2375 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2377 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2378 toName
, PATH_MAX
, nls_codepage
, remap
);
2379 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2380 name_len2
*= 2; /* convert to bytes */
2381 } else { /* BB improve the check for buffer overruns BB */
2382 name_len
= strnlen(fromName
, PATH_MAX
);
2383 name_len
++; /* trailing null */
2384 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2385 name_len2
= strnlen(toName
, PATH_MAX
);
2386 name_len2
++; /* trailing null */
2387 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2388 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2389 name_len2
++; /* trailing null */
2390 name_len2
++; /* signature byte */
2393 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2394 pSMB
->hdr
.smb_buf_length
+= count
;
2395 pSMB
->ByteCount
= cpu_to_le16(count
);
2397 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2398 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2399 cifs_stats_inc(&tcon
->num_hardlinks
);
2401 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2403 cifs_buf_release(pSMB
);
2405 goto winCreateHardLinkRetry
;
2411 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2412 const unsigned char *searchName
,
2413 char *symlinkinfo
, const int buflen
,
2414 const struct nls_table
*nls_codepage
)
2416 /* SMB_QUERY_FILE_UNIX_LINK */
2417 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2418 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2422 __u16 params
, byte_count
;
2424 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2427 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2432 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2434 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2435 PATH_MAX
, nls_codepage
);
2436 name_len
++; /* trailing null */
2438 } else { /* BB improve the check for buffer overruns BB */
2439 name_len
= strnlen(searchName
, PATH_MAX
);
2440 name_len
++; /* trailing null */
2441 strncpy(pSMB
->FileName
, searchName
, name_len
);
2444 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2445 pSMB
->TotalDataCount
= 0;
2446 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2447 /* BB find exact max data count below from sess structure BB */
2448 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2449 pSMB
->MaxSetupCount
= 0;
2453 pSMB
->Reserved2
= 0;
2454 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2455 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2456 pSMB
->DataCount
= 0;
2457 pSMB
->DataOffset
= 0;
2458 pSMB
->SetupCount
= 1;
2459 pSMB
->Reserved3
= 0;
2460 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2461 byte_count
= params
+ 1 /* pad */ ;
2462 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2463 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2464 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2465 pSMB
->Reserved4
= 0;
2466 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2467 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2469 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2470 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2472 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2474 /* decode response */
2476 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2477 if (rc
|| (pSMBr
->ByteCount
< 2))
2478 /* BB also check enough total bytes returned */
2479 rc
= -EIO
; /* bad smb */
2481 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2482 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2484 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2485 name_len
= UniStrnlen((wchar_t *) ((char *)
2486 &pSMBr
->hdr
.Protocol
+ data_offset
),
2487 min_t(const int, buflen
, count
) / 2);
2488 /* BB FIXME investigate remapping reserved chars here */
2489 cifs_strfromUCS_le(symlinkinfo
,
2490 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
2492 name_len
, nls_codepage
);
2494 strncpy(symlinkinfo
,
2495 (char *) &pSMBr
->hdr
.Protocol
+
2497 min_t(const int, buflen
, count
));
2499 symlinkinfo
[buflen
] = 0;
2500 /* just in case so calling code does not go off the end of buffer */
2503 cifs_buf_release(pSMB
);
2505 goto querySymLinkRetry
;
2509 #ifdef CONFIG_CIFS_EXPERIMENTAL
2510 /* Initialize NT TRANSACT SMB into small smb request buffer.
2511 This assumes that all NT TRANSACTS that we init here have
2512 total parm and data under about 400 bytes (to fit in small cifs
2513 buffer size), which is the case so far, it easily fits. NB:
2514 Setup words themselves and ByteCount
2515 MaxSetupCount (size of returned setup area) and
2516 MaxParameterCount (returned parms size) must be set by caller */
2518 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2519 const int parm_len
, struct cifsTconInfo
*tcon
,
2524 struct smb_com_ntransact_req
*pSMB
;
2526 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2530 *ret_buf
= (void *)pSMB
;
2532 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2533 pSMB
->TotalDataCount
= 0;
2534 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2535 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2536 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2537 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2538 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2539 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2540 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2541 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2542 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2543 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2548 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2549 __u32
*pparmlen
, __u32
*pdatalen
)
2552 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2553 struct smb_com_ntransact_rsp
*pSMBr
;
2561 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2563 /* ByteCount was converted from little endian in SendReceive */
2564 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2565 (char *)&pSMBr
->ByteCount
;
2567 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2568 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2569 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2570 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2572 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2573 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2575 /* should we also check that parm and data areas do not overlap? */
2576 if (*ppparm
> end_of_smb
) {
2577 cFYI(1, ("parms start after end of smb"));
2579 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2580 cFYI(1, ("parm end after end of smb"));
2582 } else if (*ppdata
> end_of_smb
) {
2583 cFYI(1, ("data starts after end of smb"));
2585 } else if (data_count
+ *ppdata
> end_of_smb
) {
2586 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2587 *ppdata
, data_count
, (data_count
+ *ppdata
),
2588 end_of_smb
, pSMBr
));
2590 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2591 cFYI(1, ("parm count and data count larger than SMB"));
2594 *pdatalen
= data_count
;
2595 *pparmlen
= parm_count
;
2598 #endif /* CIFS_EXPERIMENTAL */
2601 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2602 const unsigned char *searchName
,
2603 char *symlinkinfo
, const int buflen
, __u16 fid
,
2604 const struct nls_table
*nls_codepage
)
2609 struct smb_com_transaction_ioctl_req
*pSMB
;
2610 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2612 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2613 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2618 pSMB
->TotalParameterCount
= 0 ;
2619 pSMB
->TotalDataCount
= 0;
2620 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2621 /* BB find exact data count max from sess structure BB */
2622 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2623 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2624 pSMB
->MaxSetupCount
= 4;
2626 pSMB
->ParameterOffset
= 0;
2627 pSMB
->DataCount
= 0;
2628 pSMB
->DataOffset
= 0;
2629 pSMB
->SetupCount
= 4;
2630 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2631 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2632 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2633 pSMB
->IsFsctl
= 1; /* FSCTL */
2634 pSMB
->IsRootFlag
= 0;
2635 pSMB
->Fid
= fid
; /* file handle always le */
2636 pSMB
->ByteCount
= 0;
2638 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2639 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2641 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2642 } else { /* decode response */
2643 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2644 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2645 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2646 /* BB also check enough total bytes returned */
2647 rc
= -EIO
; /* bad smb */
2649 if (data_count
&& (data_count
< 2048)) {
2650 char *end_of_smb
= 2 /* sizeof byte count */ +
2652 (char *)&pSMBr
->ByteCount
;
2654 struct reparse_data
*reparse_buf
=
2655 (struct reparse_data
*)
2656 ((char *)&pSMBr
->hdr
.Protocol
2658 if ((char *)reparse_buf
>= end_of_smb
) {
2662 if ((reparse_buf
->LinkNamesBuf
+
2663 reparse_buf
->TargetNameOffset
+
2664 reparse_buf
->TargetNameLen
) >
2666 cFYI(1, ("reparse buf beyond SMB"));
2671 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2672 name_len
= UniStrnlen((wchar_t *)
2673 (reparse_buf
->LinkNamesBuf
+
2674 reparse_buf
->TargetNameOffset
),
2676 reparse_buf
->TargetNameLen
/ 2));
2677 cifs_strfromUCS_le(symlinkinfo
,
2678 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2679 reparse_buf
->TargetNameOffset
),
2680 name_len
, nls_codepage
);
2681 } else { /* ASCII names */
2682 strncpy(symlinkinfo
,
2683 reparse_buf
->LinkNamesBuf
+
2684 reparse_buf
->TargetNameOffset
,
2685 min_t(const int, buflen
,
2686 reparse_buf
->TargetNameLen
));
2690 cFYI(1, ("Invalid return data count on "
2691 "get reparse info ioctl"));
2693 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2694 does not go off the end of the buffer */
2695 cFYI(1, ("readlink result - %s", symlinkinfo
));
2699 cifs_buf_release(pSMB
);
2701 /* Note: On -EAGAIN error only caller can retry on handle based calls
2702 since file handle passed in no longer valid */
2707 #ifdef CONFIG_CIFS_POSIX
2709 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2710 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2711 struct cifs_posix_ace
*cifs_ace
)
2713 /* u8 cifs fields do not need le conversion */
2714 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2715 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2716 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2717 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2722 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2723 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2724 const int acl_type
, const int size_of_data_area
)
2729 struct cifs_posix_ace
*pACE
;
2730 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2731 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2733 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2736 if (acl_type
& ACL_TYPE_ACCESS
) {
2737 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2738 pACE
= &cifs_acl
->ace_array
[0];
2739 size
= sizeof(struct cifs_posix_acl
);
2740 size
+= sizeof(struct cifs_posix_ace
) * count
;
2741 /* check if we would go beyond end of SMB */
2742 if (size_of_data_area
< size
) {
2743 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2744 size_of_data_area
, size
));
2747 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2748 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2749 size
= sizeof(struct cifs_posix_acl
);
2750 size
+= sizeof(struct cifs_posix_ace
) * count
;
2751 /* skip past access ACEs to get to default ACEs */
2752 pACE
= &cifs_acl
->ace_array
[count
];
2753 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2754 size
+= sizeof(struct cifs_posix_ace
) * count
;
2755 /* check if we would go beyond end of SMB */
2756 if (size_of_data_area
< size
)
2763 size
= posix_acl_xattr_size(count
);
2764 if ((buflen
== 0) || (local_acl
== NULL
)) {
2765 /* used to query ACL EA size */
2766 } else if (size
> buflen
) {
2768 } else /* buffer big enough */ {
2769 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2770 for (i
= 0; i
< count
; i
++) {
2771 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2778 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2779 const posix_acl_xattr_entry
*local_ace
)
2781 __u16 rc
= 0; /* 0 = ACL converted ok */
2783 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2784 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2785 /* BB is there a better way to handle the large uid? */
2786 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2787 /* Probably no need to le convert -1 on any arch but can not hurt */
2788 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2790 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2791 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2795 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2796 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2797 const int buflen
, const int acl_type
)
2800 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2801 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2805 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2808 count
= posix_acl_xattr_count((size_t)buflen
);
2809 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2811 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2812 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2813 cFYI(1, ("unknown POSIX ACL version %d",
2814 le32_to_cpu(local_acl
->a_version
)));
2817 cifs_acl
->version
= cpu_to_le16(1);
2818 if (acl_type
== ACL_TYPE_ACCESS
)
2819 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2820 else if (acl_type
== ACL_TYPE_DEFAULT
)
2821 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2823 cFYI(1, ("unknown ACL type %d", acl_type
));
2826 for (i
= 0; i
< count
; i
++) {
2827 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2828 &local_acl
->a_entries
[i
]);
2830 /* ACE not converted */
2835 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2836 rc
+= sizeof(struct cifs_posix_acl
);
2837 /* BB add check to make sure ACL does not overflow SMB */
2843 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2844 const unsigned char *searchName
,
2845 char *acl_inf
, const int buflen
, const int acl_type
,
2846 const struct nls_table
*nls_codepage
, int remap
)
2848 /* SMB_QUERY_POSIX_ACL */
2849 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2850 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2854 __u16 params
, byte_count
;
2856 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2859 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2864 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2866 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2867 PATH_MAX
, nls_codepage
, remap
);
2868 name_len
++; /* trailing null */
2870 pSMB
->FileName
[name_len
] = 0;
2871 pSMB
->FileName
[name_len
+1] = 0;
2872 } else { /* BB improve the check for buffer overruns BB */
2873 name_len
= strnlen(searchName
, PATH_MAX
);
2874 name_len
++; /* trailing null */
2875 strncpy(pSMB
->FileName
, searchName
, name_len
);
2878 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2879 pSMB
->TotalDataCount
= 0;
2880 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2881 /* BB find exact max data count below from sess structure BB */
2882 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2883 pSMB
->MaxSetupCount
= 0;
2887 pSMB
->Reserved2
= 0;
2888 pSMB
->ParameterOffset
= cpu_to_le16(
2889 offsetof(struct smb_com_transaction2_qpi_req
,
2890 InformationLevel
) - 4);
2891 pSMB
->DataCount
= 0;
2892 pSMB
->DataOffset
= 0;
2893 pSMB
->SetupCount
= 1;
2894 pSMB
->Reserved3
= 0;
2895 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2896 byte_count
= params
+ 1 /* pad */ ;
2897 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2898 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2899 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2900 pSMB
->Reserved4
= 0;
2901 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2902 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2904 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2905 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2906 cifs_stats_inc(&tcon
->num_acl_get
);
2908 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2910 /* decode response */
2912 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2913 if (rc
|| (pSMBr
->ByteCount
< 2))
2914 /* BB also check enough total bytes returned */
2915 rc
= -EIO
; /* bad smb */
2917 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2918 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2919 rc
= cifs_copy_posix_acl(acl_inf
,
2920 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2921 buflen
, acl_type
, count
);
2924 cifs_buf_release(pSMB
);
2931 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2932 const unsigned char *fileName
,
2933 const char *local_acl
, const int buflen
,
2935 const struct nls_table
*nls_codepage
, int remap
)
2937 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2938 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2942 int bytes_returned
= 0;
2943 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2945 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2947 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2951 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2953 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2954 PATH_MAX
, nls_codepage
, remap
);
2955 name_len
++; /* trailing null */
2957 } else { /* BB improve the check for buffer overruns BB */
2958 name_len
= strnlen(fileName
, PATH_MAX
);
2959 name_len
++; /* trailing null */
2960 strncpy(pSMB
->FileName
, fileName
, name_len
);
2962 params
= 6 + name_len
;
2963 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2964 /* BB find max SMB size from sess */
2965 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2966 pSMB
->MaxSetupCount
= 0;
2970 pSMB
->Reserved2
= 0;
2971 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2972 InformationLevel
) - 4;
2973 offset
= param_offset
+ params
;
2974 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2975 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2977 /* convert to on the wire format for POSIX ACL */
2978 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2980 if (data_count
== 0) {
2982 goto setACLerrorExit
;
2984 pSMB
->DataOffset
= cpu_to_le16(offset
);
2985 pSMB
->SetupCount
= 1;
2986 pSMB
->Reserved3
= 0;
2987 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2988 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2989 byte_count
= 3 /* pad */ + params
+ data_count
;
2990 pSMB
->DataCount
= cpu_to_le16(data_count
);
2991 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2992 pSMB
->ParameterCount
= cpu_to_le16(params
);
2993 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2994 pSMB
->Reserved4
= 0;
2995 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2996 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2997 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2998 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3000 cFYI(1, ("Set POSIX ACL returned %d", rc
));
3003 cifs_buf_release(pSMB
);
3009 /* BB fix tabs in this function FIXME BB */
3011 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
3012 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
3015 struct smb_t2_qfi_req
*pSMB
= NULL
;
3016 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3018 __u16 params
, byte_count
;
3020 cFYI(1, ("In GetExtAttr"));
3025 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3030 params
= 2 /* level */ + 2 /* fid */;
3031 pSMB
->t2
.TotalDataCount
= 0;
3032 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3033 /* BB find exact max data count below from sess structure BB */
3034 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3035 pSMB
->t2
.MaxSetupCount
= 0;
3036 pSMB
->t2
.Reserved
= 0;
3038 pSMB
->t2
.Timeout
= 0;
3039 pSMB
->t2
.Reserved2
= 0;
3040 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3042 pSMB
->t2
.DataCount
= 0;
3043 pSMB
->t2
.DataOffset
= 0;
3044 pSMB
->t2
.SetupCount
= 1;
3045 pSMB
->t2
.Reserved3
= 0;
3046 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3047 byte_count
= params
+ 1 /* pad */ ;
3048 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3049 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3050 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3053 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3054 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3056 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3057 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3059 cFYI(1, ("error %d in GetExtAttr", rc
));
3061 /* decode response */
3062 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3063 if (rc
|| (pSMBr
->ByteCount
< 2))
3064 /* BB also check enough total bytes returned */
3065 /* If rc should we check for EOPNOSUPP and
3066 disable the srvino flag? or in caller? */
3067 rc
= -EIO
; /* bad smb */
3069 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3070 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3071 struct file_chattr_info
*pfinfo
;
3072 /* BB Do we need a cast or hash here ? */
3074 cFYI(1, ("Illegal size ret in GetExtAttr"));
3078 pfinfo
= (struct file_chattr_info
*)
3079 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3080 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3081 *pMask
= le64_to_cpu(pfinfo
->mask
);
3085 cifs_buf_release(pSMB
);
3087 goto GetExtAttrRetry
;
3091 #endif /* CONFIG_POSIX */
3093 #ifdef CONFIG_CIFS_EXPERIMENTAL
3094 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3096 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3097 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3101 QUERY_SEC_DESC_REQ
*pSMB
;
3104 cFYI(1, ("GetCifsACL"));
3109 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3110 8 /* parm len */, tcon
, (void **) &pSMB
);
3114 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3115 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3116 pSMB
->MaxSetupCount
= 0;
3117 pSMB
->Fid
= fid
; /* file handle always le */
3118 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3120 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3121 pSMB
->hdr
.smb_buf_length
+= 11;
3122 iov
[0].iov_base
= (char *)pSMB
;
3123 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3125 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3127 cifs_stats_inc(&tcon
->num_acl_get
);
3129 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3130 } else { /* decode response */
3134 struct smb_com_ntransact_rsp
*pSMBr
;
3137 /* validate_nttransact */
3138 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3139 &pdata
, &parm_len
, pbuflen
);
3142 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3144 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3146 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3147 rc
= -EIO
; /* bad smb */
3152 /* BB check that data area is minimum length and as big as acl_len */
3154 acl_len
= le32_to_cpu(*parm
);
3155 if (acl_len
!= *pbuflen
) {
3156 cERROR(1, ("acl length %d does not match %d",
3157 acl_len
, *pbuflen
));
3158 if (*pbuflen
> acl_len
)
3162 /* check if buffer is big enough for the acl
3163 header followed by the smallest SID */
3164 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3165 (*pbuflen
>= 64 * 1024)) {
3166 cERROR(1, ("bad acl length %d", *pbuflen
));
3170 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3171 if (*acl_inf
== NULL
) {
3175 memcpy(*acl_inf
, pdata
, *pbuflen
);
3179 if (buf_type
== CIFS_SMALL_BUFFER
)
3180 cifs_small_buf_release(iov
[0].iov_base
);
3181 else if (buf_type
== CIFS_LARGE_BUFFER
)
3182 cifs_buf_release(iov
[0].iov_base
);
3183 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3188 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3189 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3191 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3193 int bytes_returned
= 0;
3194 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3195 NTRANSACT_RSP
*pSMBr
= NULL
;
3198 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3203 pSMB
->MaxSetupCount
= 0;
3207 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3208 data_count
= acllen
;
3209 data_offset
= param_offset
+ param_count
;
3210 byte_count
= 3 /* pad */ + param_count
;
3212 pSMB
->DataCount
= cpu_to_le32(data_count
);
3213 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3214 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3215 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3216 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3217 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3218 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3219 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3220 pSMB
->SetupCount
= 0;
3221 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3222 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3224 pSMB
->Fid
= fid
; /* file handle always le */
3225 pSMB
->Reserved2
= 0;
3226 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3228 if (pntsd
&& acllen
) {
3229 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3232 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3235 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3237 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3238 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3240 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3242 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3243 cifs_buf_release(pSMB
);
3246 goto setCifsAclRetry
;
3251 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3253 /* Legacy Query Path Information call for lookup to old servers such
3255 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3256 const unsigned char *searchName
,
3257 FILE_ALL_INFO
*pFinfo
,
3258 const struct nls_table
*nls_codepage
, int remap
)
3260 QUERY_INFORMATION_REQ
*pSMB
;
3261 QUERY_INFORMATION_RSP
*pSMBr
;
3266 cFYI(1, ("In SMBQPath path %s", searchName
));
3268 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3273 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3275 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3276 PATH_MAX
, nls_codepage
, remap
);
3277 name_len
++; /* trailing null */
3280 name_len
= strnlen(searchName
, PATH_MAX
);
3281 name_len
++; /* trailing null */
3282 strncpy(pSMB
->FileName
, searchName
, name_len
);
3284 pSMB
->BufferFormat
= 0x04;
3285 name_len
++; /* account for buffer type byte */
3286 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3287 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3289 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3290 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3292 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3293 } else if (pFinfo
) {
3295 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3297 /* decode response */
3298 /* BB FIXME - add time zone adjustment BB */
3299 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3302 /* decode time fields */
3303 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3304 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3305 pFinfo
->LastAccessTime
= 0;
3306 pFinfo
->AllocationSize
=
3307 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3308 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3309 pFinfo
->Attributes
=
3310 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3312 rc
= -EIO
; /* bad buffer passed in */
3314 cifs_buf_release(pSMB
);
3326 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3327 const unsigned char *searchName
,
3328 FILE_ALL_INFO
*pFindData
,
3329 int legacy
/* old style infolevel */,
3330 const struct nls_table
*nls_codepage
, int remap
)
3332 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3333 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3334 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3338 __u16 params
, byte_count
;
3340 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3342 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3347 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3349 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3350 PATH_MAX
, nls_codepage
, remap
);
3351 name_len
++; /* trailing null */
3353 } else { /* BB improve the check for buffer overruns BB */
3354 name_len
= strnlen(searchName
, PATH_MAX
);
3355 name_len
++; /* trailing null */
3356 strncpy(pSMB
->FileName
, searchName
, name_len
);
3359 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3360 pSMB
->TotalDataCount
= 0;
3361 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3362 /* BB find exact max SMB PDU from sess structure BB */
3363 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3364 pSMB
->MaxSetupCount
= 0;
3368 pSMB
->Reserved2
= 0;
3369 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3370 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3371 pSMB
->DataCount
= 0;
3372 pSMB
->DataOffset
= 0;
3373 pSMB
->SetupCount
= 1;
3374 pSMB
->Reserved3
= 0;
3375 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3376 byte_count
= params
+ 1 /* pad */ ;
3377 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3378 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3380 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3382 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3383 pSMB
->Reserved4
= 0;
3384 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3385 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3387 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3388 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3390 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3391 } else { /* decode response */
3392 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3394 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3396 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3397 rc
= -EIO
; /* bad smb */
3398 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3399 rc
= -EIO
; /* 24 or 26 expected but we do not read
3401 else if (pFindData
) {
3403 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3405 /* On legacy responses we do not read the last field,
3406 EAsize, fortunately since it varies by subdialect and
3407 also note it differs on Set vs. Get, ie two bytes or 4
3408 bytes depending but we don't care here */
3410 size
= sizeof(FILE_INFO_STANDARD
);
3412 size
= sizeof(FILE_ALL_INFO
);
3413 memcpy((char *) pFindData
,
3414 (char *) &pSMBr
->hdr
.Protocol
+
3419 cifs_buf_release(pSMB
);
3421 goto QPathInfoRetry
;
3427 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3428 const unsigned char *searchName
,
3429 FILE_UNIX_BASIC_INFO
*pFindData
,
3430 const struct nls_table
*nls_codepage
, int remap
)
3432 /* SMB_QUERY_FILE_UNIX_BASIC */
3433 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3434 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3436 int bytes_returned
= 0;
3438 __u16 params
, byte_count
;
3440 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3442 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3447 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3449 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3450 PATH_MAX
, nls_codepage
, remap
);
3451 name_len
++; /* trailing null */
3453 } else { /* BB improve the check for buffer overruns BB */
3454 name_len
= strnlen(searchName
, PATH_MAX
);
3455 name_len
++; /* trailing null */
3456 strncpy(pSMB
->FileName
, searchName
, name_len
);
3459 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3460 pSMB
->TotalDataCount
= 0;
3461 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3462 /* BB find exact max SMB PDU from sess structure BB */
3463 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3464 pSMB
->MaxSetupCount
= 0;
3468 pSMB
->Reserved2
= 0;
3469 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3470 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3471 pSMB
->DataCount
= 0;
3472 pSMB
->DataOffset
= 0;
3473 pSMB
->SetupCount
= 1;
3474 pSMB
->Reserved3
= 0;
3475 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3476 byte_count
= params
+ 1 /* pad */ ;
3477 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3478 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3479 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3480 pSMB
->Reserved4
= 0;
3481 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3482 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3484 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3485 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3487 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3488 } else { /* decode response */
3489 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3491 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3492 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3493 "Unix Extensions can be disabled on mount "
3494 "by specifying the nosfu mount option."));
3495 rc
= -EIO
; /* bad smb */
3497 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3498 memcpy((char *) pFindData
,
3499 (char *) &pSMBr
->hdr
.Protocol
+
3501 sizeof(FILE_UNIX_BASIC_INFO
));
3504 cifs_buf_release(pSMB
);
3506 goto UnixQPathInfoRetry
;
3511 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3513 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3514 const char *searchName
,
3515 const struct nls_table
*nls_codepage
,
3517 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3519 /* level 257 SMB_ */
3520 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3521 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3522 T2_FFIRST_RSP_PARMS
*parms
;
3524 int bytes_returned
= 0;
3526 __u16 params
, byte_count
;
3528 cFYI(1, ("In FindFirst for %s", searchName
));
3531 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3536 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3538 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3539 PATH_MAX
, nls_codepage
, remap
);
3540 /* We can not add the asterik earlier in case
3541 it got remapped to 0xF03A as if it were part of the
3542 directory name instead of a wildcard */
3544 pSMB
->FileName
[name_len
] = dirsep
;
3545 pSMB
->FileName
[name_len
+1] = 0;
3546 pSMB
->FileName
[name_len
+2] = '*';
3547 pSMB
->FileName
[name_len
+3] = 0;
3548 name_len
+= 4; /* now the trailing null */
3549 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3550 pSMB
->FileName
[name_len
+1] = 0;
3552 } else { /* BB add check for overrun of SMB buf BB */
3553 name_len
= strnlen(searchName
, PATH_MAX
);
3554 /* BB fix here and in unicode clause above ie
3555 if (name_len > buffersize-header)
3556 free buffer exit; BB */
3557 strncpy(pSMB
->FileName
, searchName
, name_len
);
3558 pSMB
->FileName
[name_len
] = dirsep
;
3559 pSMB
->FileName
[name_len
+1] = '*';
3560 pSMB
->FileName
[name_len
+2] = 0;
3564 params
= 12 + name_len
/* includes null */ ;
3565 pSMB
->TotalDataCount
= 0; /* no EAs */
3566 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3567 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3568 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3569 pSMB
->MaxSetupCount
= 0;
3573 pSMB
->Reserved2
= 0;
3574 byte_count
= params
+ 1 /* pad */ ;
3575 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3576 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3577 pSMB
->ParameterOffset
= cpu_to_le16(
3578 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3580 pSMB
->DataCount
= 0;
3581 pSMB
->DataOffset
= 0;
3582 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3583 pSMB
->Reserved3
= 0;
3584 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3585 pSMB
->SearchAttributes
=
3586 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3588 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3589 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3590 CIFS_SEARCH_RETURN_RESUME
);
3591 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3593 /* BB what should we set StorageType to? Does it matter? BB */
3594 pSMB
->SearchStorageType
= 0;
3595 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3596 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3598 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3599 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3600 cifs_stats_inc(&tcon
->num_ffirst
);
3602 if (rc
) {/* BB add logic to retry regular search if Unix search
3603 rejected unexpectedly by server */
3604 /* BB Add code to handle unsupported level rc */
3605 cFYI(1, ("Error in FindFirst = %d", rc
));
3607 cifs_buf_release(pSMB
);
3609 /* BB eventually could optimize out free and realloc of buf */
3612 goto findFirstRetry
;
3613 } else { /* decode response */
3614 /* BB remember to free buffer if error BB */
3615 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3619 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3620 psrch_inf
->unicode
= true;
3622 psrch_inf
->unicode
= false;
3624 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3625 psrch_inf
->smallBuf
= 0;
3626 psrch_inf
->srch_entries_start
=
3627 (char *) &pSMBr
->hdr
.Protocol
+
3628 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3629 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3630 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3632 if (parms
->EndofSearch
)
3633 psrch_inf
->endOfSearch
= true;
3635 psrch_inf
->endOfSearch
= false;
3637 psrch_inf
->entries_in_buffer
=
3638 le16_to_cpu(parms
->SearchCount
);
3639 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3640 psrch_inf
->entries_in_buffer
;
3641 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3642 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3644 cERROR(1, ("ignoring corrupt resume name"));
3645 psrch_inf
->last_entry
= NULL
;
3649 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3652 *pnetfid
= parms
->SearchHandle
;
3654 cifs_buf_release(pSMB
);
3661 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3662 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3664 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3665 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3666 T2_FNEXT_RSP_PARMS
*parms
;
3667 char *response_data
;
3669 int bytes_returned
, name_len
;
3670 __u16 params
, byte_count
;
3672 cFYI(1, ("In FindNext"));
3674 if (psrch_inf
->endOfSearch
)
3677 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3682 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3684 pSMB
->TotalDataCount
= 0; /* no EAs */
3685 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3686 pSMB
->MaxDataCount
=
3687 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3689 pSMB
->MaxSetupCount
= 0;
3693 pSMB
->Reserved2
= 0;
3694 pSMB
->ParameterOffset
= cpu_to_le16(
3695 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3696 pSMB
->DataCount
= 0;
3697 pSMB
->DataOffset
= 0;
3698 pSMB
->SetupCount
= 1;
3699 pSMB
->Reserved3
= 0;
3700 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3701 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3703 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3704 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3705 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3707 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3709 name_len
= psrch_inf
->resume_name_len
;
3711 if (name_len
< PATH_MAX
) {
3712 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3713 byte_count
+= name_len
;
3714 /* 14 byte parm len above enough for 2 byte null terminator */
3715 pSMB
->ResumeFileName
[name_len
] = 0;
3716 pSMB
->ResumeFileName
[name_len
+1] = 0;
3719 goto FNext2_err_exit
;
3721 byte_count
= params
+ 1 /* pad */ ;
3722 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3723 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3724 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3725 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3727 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3728 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3729 cifs_stats_inc(&tcon
->num_fnext
);
3732 psrch_inf
->endOfSearch
= true;
3733 cifs_buf_release(pSMB
);
3734 rc
= 0; /* search probably was closed at end of search*/
3736 cFYI(1, ("FindNext returned = %d", rc
));
3737 } else { /* decode response */
3738 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3743 /* BB fixme add lock for file (srch_info) struct here */
3744 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3745 psrch_inf
->unicode
= true;
3747 psrch_inf
->unicode
= false;
3748 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3749 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3750 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3751 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3752 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3753 if (psrch_inf
->smallBuf
)
3754 cifs_small_buf_release(
3755 psrch_inf
->ntwrk_buf_start
);
3757 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3758 psrch_inf
->srch_entries_start
= response_data
;
3759 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3760 psrch_inf
->smallBuf
= 0;
3761 if (parms
->EndofSearch
)
3762 psrch_inf
->endOfSearch
= true;
3764 psrch_inf
->endOfSearch
= false;
3765 psrch_inf
->entries_in_buffer
=
3766 le16_to_cpu(parms
->SearchCount
);
3767 psrch_inf
->index_of_last_entry
+=
3768 psrch_inf
->entries_in_buffer
;
3769 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3770 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3772 cERROR(1, ("ignoring corrupt resume name"));
3773 psrch_inf
->last_entry
= NULL
;
3776 psrch_inf
->last_entry
=
3777 psrch_inf
->srch_entries_start
+ lnoff
;
3779 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3780 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3782 /* BB fixme add unlock here */
3787 /* BB On error, should we leave previous search buf (and count and
3788 last entry fields) intact or free the previous one? */
3790 /* Note: On -EAGAIN error only caller can retry on handle based calls
3791 since file handle passed in no longer valid */
3794 cifs_buf_release(pSMB
);
3799 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3800 const __u16 searchHandle
)
3803 FINDCLOSE_REQ
*pSMB
= NULL
;
3805 cFYI(1, ("In CIFSSMBFindClose"));
3806 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3808 /* no sense returning error if session restarted
3809 as file handle has been closed */
3815 pSMB
->FileID
= searchHandle
;
3816 pSMB
->ByteCount
= 0;
3817 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3819 cERROR(1, ("Send error in FindClose = %d", rc
));
3821 cifs_stats_inc(&tcon
->num_fclose
);
3823 /* Since session is dead, search handle closed on server already */
3831 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3832 const unsigned char *searchName
,
3833 __u64
*inode_number
,
3834 const struct nls_table
*nls_codepage
, int remap
)
3837 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3838 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3839 int name_len
, bytes_returned
;
3840 __u16 params
, byte_count
;
3842 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3846 GetInodeNumberRetry
:
3847 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3852 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3854 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3855 PATH_MAX
, nls_codepage
, remap
);
3856 name_len
++; /* trailing null */
3858 } else { /* BB improve the check for buffer overruns BB */
3859 name_len
= strnlen(searchName
, PATH_MAX
);
3860 name_len
++; /* trailing null */
3861 strncpy(pSMB
->FileName
, searchName
, name_len
);
3864 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3865 pSMB
->TotalDataCount
= 0;
3866 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3867 /* BB find exact max data count below from sess structure BB */
3868 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3869 pSMB
->MaxSetupCount
= 0;
3873 pSMB
->Reserved2
= 0;
3874 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3875 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3876 pSMB
->DataCount
= 0;
3877 pSMB
->DataOffset
= 0;
3878 pSMB
->SetupCount
= 1;
3879 pSMB
->Reserved3
= 0;
3880 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3881 byte_count
= params
+ 1 /* pad */ ;
3882 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3883 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3884 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3885 pSMB
->Reserved4
= 0;
3886 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3887 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3889 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3890 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3892 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3894 /* decode response */
3895 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3896 if (rc
|| (pSMBr
->ByteCount
< 2))
3897 /* BB also check enough total bytes returned */
3898 /* If rc should we check for EOPNOSUPP and
3899 disable the srvino flag? or in caller? */
3900 rc
= -EIO
; /* bad smb */
3902 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3903 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3904 struct file_internal_info
*pfinfo
;
3905 /* BB Do we need a cast or hash here ? */
3907 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3909 goto GetInodeNumOut
;
3911 pfinfo
= (struct file_internal_info
*)
3912 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3913 *inode_number
= pfinfo
->UniqueId
;
3917 cifs_buf_release(pSMB
);
3919 goto GetInodeNumberRetry
;
3923 /* parses DFS refferal V3 structure
3924 * caller is responsible for freeing target_nodes
3927 * on failure - errno
3930 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
3931 unsigned int *num_of_nodes
,
3932 struct dfs_info3_param
**target_nodes
,
3933 const struct nls_table
*nls_codepage
)
3938 struct dfs_referral_level_3
*ref
;
3940 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3944 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3946 if (*num_of_nodes
< 1) {
3947 cERROR(1, ("num_referrals: must be at least > 0,"
3948 "but we get num_referrals = %d\n", *num_of_nodes
));
3950 goto parse_DFS_referrals_exit
;
3953 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
3954 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
3955 cERROR(1, ("Referrals of V%d version are not supported,"
3956 "should be V3", le16_to_cpu(ref
->VersionNumber
)));
3958 goto parse_DFS_referrals_exit
;
3961 /* get the upper boundary of the resp buffer */
3962 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
3963 le16_to_cpu(pSMBr
->t2
.DataCount
);
3965 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3967 le16_to_cpu(pSMBr
->DFSFlags
)));
3969 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
3970 *num_of_nodes
, GFP_KERNEL
);
3971 if (*target_nodes
== NULL
) {
3972 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3974 goto parse_DFS_referrals_exit
;
3977 /* collect neccessary data from referrals */
3978 for (i
= 0; i
< *num_of_nodes
; i
++) {
3981 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
3983 node
->flags
= le16_to_cpu(pSMBr
->DFSFlags
);
3984 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
3985 node
->server_type
= le16_to_cpu(ref
->ServerType
);
3986 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
3989 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
3990 max_len
= data_end
- temp
;
3991 rc
= cifs_strncpy_to_host(&(node
->path_name
), temp
,
3992 max_len
, is_unicode
, nls_codepage
);
3994 goto parse_DFS_referrals_exit
;
3996 /* copy link target UNC */
3997 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
3998 max_len
= data_end
- temp
;
3999 rc
= cifs_strncpy_to_host(&(node
->node_name
), temp
,
4000 max_len
, is_unicode
, nls_codepage
);
4002 goto parse_DFS_referrals_exit
;
4004 ref
+= le16_to_cpu(ref
->Size
);
4007 parse_DFS_referrals_exit
:
4009 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4010 *target_nodes
= NULL
;
4017 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4018 const unsigned char *searchName
,
4019 struct dfs_info3_param
**target_nodes
,
4020 unsigned int *num_of_nodes
,
4021 const struct nls_table
*nls_codepage
, int remap
)
4023 /* TRANS2_GET_DFS_REFERRAL */
4024 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4025 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4029 __u16 params
, byte_count
;
4031 *target_nodes
= NULL
;
4033 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
4037 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4042 /* server pointer checked in called function,
4043 but should never be null here anyway */
4044 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4045 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4046 pSMB
->hdr
.Uid
= ses
->Suid
;
4047 if (ses
->capabilities
& CAP_STATUS32
)
4048 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4049 if (ses
->capabilities
& CAP_DFS
)
4050 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4052 if (ses
->capabilities
& CAP_UNICODE
) {
4053 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4055 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4056 searchName
, PATH_MAX
, nls_codepage
, remap
);
4057 name_len
++; /* trailing null */
4059 } else { /* BB improve the check for buffer overruns BB */
4060 name_len
= strnlen(searchName
, PATH_MAX
);
4061 name_len
++; /* trailing null */
4062 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4066 if (ses
->server
->secMode
&
4067 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4068 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4071 pSMB
->hdr
.Uid
= ses
->Suid
;
4073 params
= 2 /* level */ + name_len
/*includes null */ ;
4074 pSMB
->TotalDataCount
= 0;
4075 pSMB
->DataCount
= 0;
4076 pSMB
->DataOffset
= 0;
4077 pSMB
->MaxParameterCount
= 0;
4078 /* BB find exact max SMB PDU from sess structure BB */
4079 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4080 pSMB
->MaxSetupCount
= 0;
4084 pSMB
->Reserved2
= 0;
4085 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4086 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4087 pSMB
->SetupCount
= 1;
4088 pSMB
->Reserved3
= 0;
4089 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4090 byte_count
= params
+ 3 /* pad */ ;
4091 pSMB
->ParameterCount
= cpu_to_le16(params
);
4092 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4093 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4094 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4095 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4097 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4098 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4100 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
4103 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4105 /* BB Also check if enough total bytes returned? */
4106 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4107 rc
= -EIO
; /* bad smb */
4111 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4113 le16_to_cpu(pSMBr
->t2
.DataOffset
)));
4115 /* parse returned result into more usable form */
4116 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4117 target_nodes
, nls_codepage
);
4120 cifs_buf_release(pSMB
);
4128 /* Query File System Info such as free space to old servers such as Win 9x */
4130 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4132 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4133 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4134 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4135 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4137 int bytes_returned
= 0;
4138 __u16 params
, byte_count
;
4140 cFYI(1, ("OldQFSInfo"));
4142 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4147 params
= 2; /* level */
4148 pSMB
->TotalDataCount
= 0;
4149 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4150 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4151 pSMB
->MaxSetupCount
= 0;
4155 pSMB
->Reserved2
= 0;
4156 byte_count
= params
+ 1 /* pad */ ;
4157 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4158 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4159 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4160 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4161 pSMB
->DataCount
= 0;
4162 pSMB
->DataOffset
= 0;
4163 pSMB
->SetupCount
= 1;
4164 pSMB
->Reserved3
= 0;
4165 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4166 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4167 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4168 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4170 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4171 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4173 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4174 } else { /* decode response */
4175 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4177 if (rc
|| (pSMBr
->ByteCount
< 18))
4178 rc
= -EIO
; /* bad smb */
4180 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4181 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4182 pSMBr
->ByteCount
, data_offset
));
4184 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4185 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4187 le16_to_cpu(response_data
->BytesPerSector
) *
4188 le32_to_cpu(response_data
->
4189 SectorsPerAllocationUnit
);
4191 le32_to_cpu(response_data
->TotalAllocationUnits
);
4192 FSData
->f_bfree
= FSData
->f_bavail
=
4193 le32_to_cpu(response_data
->FreeAllocationUnits
);
4195 ("Blocks: %lld Free: %lld Block size %ld",
4196 (unsigned long long)FSData
->f_blocks
,
4197 (unsigned long long)FSData
->f_bfree
,
4201 cifs_buf_release(pSMB
);
4204 goto oldQFSInfoRetry
;
4210 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4212 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4213 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4214 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4215 FILE_SYSTEM_INFO
*response_data
;
4217 int bytes_returned
= 0;
4218 __u16 params
, byte_count
;
4220 cFYI(1, ("In QFSInfo"));
4222 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4227 params
= 2; /* level */
4228 pSMB
->TotalDataCount
= 0;
4229 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4230 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4231 pSMB
->MaxSetupCount
= 0;
4235 pSMB
->Reserved2
= 0;
4236 byte_count
= params
+ 1 /* pad */ ;
4237 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4238 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4239 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4240 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4241 pSMB
->DataCount
= 0;
4242 pSMB
->DataOffset
= 0;
4243 pSMB
->SetupCount
= 1;
4244 pSMB
->Reserved3
= 0;
4245 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4246 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4247 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4248 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4250 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4251 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4253 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4254 } else { /* decode response */
4255 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4257 if (rc
|| (pSMBr
->ByteCount
< 24))
4258 rc
= -EIO
; /* bad smb */
4260 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4264 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4267 le32_to_cpu(response_data
->BytesPerSector
) *
4268 le32_to_cpu(response_data
->
4269 SectorsPerAllocationUnit
);
4271 le64_to_cpu(response_data
->TotalAllocationUnits
);
4272 FSData
->f_bfree
= FSData
->f_bavail
=
4273 le64_to_cpu(response_data
->FreeAllocationUnits
);
4275 ("Blocks: %lld Free: %lld Block size %ld",
4276 (unsigned long long)FSData
->f_blocks
,
4277 (unsigned long long)FSData
->f_bfree
,
4281 cifs_buf_release(pSMB
);
4290 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4292 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4293 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4294 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4295 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4297 int bytes_returned
= 0;
4298 __u16 params
, byte_count
;
4300 cFYI(1, ("In QFSAttributeInfo"));
4302 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4307 params
= 2; /* level */
4308 pSMB
->TotalDataCount
= 0;
4309 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4310 /* BB find exact max SMB PDU from sess structure BB */
4311 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4312 pSMB
->MaxSetupCount
= 0;
4316 pSMB
->Reserved2
= 0;
4317 byte_count
= params
+ 1 /* pad */ ;
4318 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4319 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4320 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4321 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4322 pSMB
->DataCount
= 0;
4323 pSMB
->DataOffset
= 0;
4324 pSMB
->SetupCount
= 1;
4325 pSMB
->Reserved3
= 0;
4326 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4327 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4328 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4329 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4331 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4332 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4334 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4335 } else { /* decode response */
4336 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4338 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4339 /* BB also check if enough bytes returned */
4340 rc
= -EIO
; /* bad smb */
4342 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4344 (FILE_SYSTEM_ATTRIBUTE_INFO
4345 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4347 memcpy(&tcon
->fsAttrInfo
, response_data
,
4348 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4351 cifs_buf_release(pSMB
);
4354 goto QFSAttributeRetry
;
4360 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4362 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4363 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4364 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4365 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4367 int bytes_returned
= 0;
4368 __u16 params
, byte_count
;
4370 cFYI(1, ("In QFSDeviceInfo"));
4372 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4377 params
= 2; /* level */
4378 pSMB
->TotalDataCount
= 0;
4379 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4380 /* BB find exact max SMB PDU from sess structure BB */
4381 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4382 pSMB
->MaxSetupCount
= 0;
4386 pSMB
->Reserved2
= 0;
4387 byte_count
= params
+ 1 /* pad */ ;
4388 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4389 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4390 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4391 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4393 pSMB
->DataCount
= 0;
4394 pSMB
->DataOffset
= 0;
4395 pSMB
->SetupCount
= 1;
4396 pSMB
->Reserved3
= 0;
4397 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4398 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4399 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4400 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4402 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4403 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4405 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4406 } else { /* decode response */
4407 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4409 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4410 rc
= -EIO
; /* bad smb */
4412 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4414 (FILE_SYSTEM_DEVICE_INFO
*)
4415 (((char *) &pSMBr
->hdr
.Protocol
) +
4417 memcpy(&tcon
->fsDevInfo
, response_data
,
4418 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4421 cifs_buf_release(pSMB
);
4424 goto QFSDeviceRetry
;
4430 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4432 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4433 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4434 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4435 FILE_SYSTEM_UNIX_INFO
*response_data
;
4437 int bytes_returned
= 0;
4438 __u16 params
, byte_count
;
4440 cFYI(1, ("In QFSUnixInfo"));
4442 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4447 params
= 2; /* level */
4448 pSMB
->TotalDataCount
= 0;
4449 pSMB
->DataCount
= 0;
4450 pSMB
->DataOffset
= 0;
4451 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4452 /* BB find exact max SMB PDU from sess structure BB */
4453 pSMB
->MaxDataCount
= cpu_to_le16(100);
4454 pSMB
->MaxSetupCount
= 0;
4458 pSMB
->Reserved2
= 0;
4459 byte_count
= params
+ 1 /* pad */ ;
4460 pSMB
->ParameterCount
= cpu_to_le16(params
);
4461 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4462 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4463 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4464 pSMB
->SetupCount
= 1;
4465 pSMB
->Reserved3
= 0;
4466 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4467 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4468 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4469 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4471 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4472 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4474 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4475 } else { /* decode response */
4476 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4478 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4479 rc
= -EIO
; /* bad smb */
4481 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4483 (FILE_SYSTEM_UNIX_INFO
4484 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4486 memcpy(&tcon
->fsUnixInfo
, response_data
,
4487 sizeof(FILE_SYSTEM_UNIX_INFO
));
4490 cifs_buf_release(pSMB
);
4500 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4502 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4503 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4504 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4506 int bytes_returned
= 0;
4507 __u16 params
, param_offset
, offset
, byte_count
;
4509 cFYI(1, ("In SETFSUnixInfo"));
4511 /* BB switch to small buf init to save memory */
4512 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4517 params
= 4; /* 2 bytes zero followed by info level. */
4518 pSMB
->MaxSetupCount
= 0;
4522 pSMB
->Reserved2
= 0;
4523 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4525 offset
= param_offset
+ params
;
4527 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4528 /* BB find exact max SMB PDU from sess structure BB */
4529 pSMB
->MaxDataCount
= cpu_to_le16(100);
4530 pSMB
->SetupCount
= 1;
4531 pSMB
->Reserved3
= 0;
4532 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4533 byte_count
= 1 /* pad */ + params
+ 12;
4535 pSMB
->DataCount
= cpu_to_le16(12);
4536 pSMB
->ParameterCount
= cpu_to_le16(params
);
4537 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4538 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4539 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4540 pSMB
->DataOffset
= cpu_to_le16(offset
);
4544 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4547 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4548 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4549 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4551 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4552 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4554 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4555 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4557 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4558 } else { /* decode response */
4559 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4561 rc
= -EIO
; /* bad smb */
4563 cifs_buf_release(pSMB
);
4566 goto SETFSUnixRetry
;
4574 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4575 struct kstatfs
*FSData
)
4577 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4578 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4579 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4580 FILE_SYSTEM_POSIX_INFO
*response_data
;
4582 int bytes_returned
= 0;
4583 __u16 params
, byte_count
;
4585 cFYI(1, ("In QFSPosixInfo"));
4587 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4592 params
= 2; /* level */
4593 pSMB
->TotalDataCount
= 0;
4594 pSMB
->DataCount
= 0;
4595 pSMB
->DataOffset
= 0;
4596 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4597 /* BB find exact max SMB PDU from sess structure BB */
4598 pSMB
->MaxDataCount
= cpu_to_le16(100);
4599 pSMB
->MaxSetupCount
= 0;
4603 pSMB
->Reserved2
= 0;
4604 byte_count
= params
+ 1 /* pad */ ;
4605 pSMB
->ParameterCount
= cpu_to_le16(params
);
4606 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4607 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4608 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4609 pSMB
->SetupCount
= 1;
4610 pSMB
->Reserved3
= 0;
4611 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4612 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4613 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4614 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4616 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4617 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4619 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4620 } else { /* decode response */
4621 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4623 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4624 rc
= -EIO
; /* bad smb */
4626 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4628 (FILE_SYSTEM_POSIX_INFO
4629 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4632 le32_to_cpu(response_data
->BlockSize
);
4634 le64_to_cpu(response_data
->TotalBlocks
);
4636 le64_to_cpu(response_data
->BlocksAvail
);
4637 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4638 FSData
->f_bavail
= FSData
->f_bfree
;
4641 le64_to_cpu(response_data
->UserBlocksAvail
);
4643 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4645 le64_to_cpu(response_data
->TotalFileNodes
);
4646 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4648 le64_to_cpu(response_data
->FreeFileNodes
);
4651 cifs_buf_release(pSMB
);
4660 /* We can not use write of zero bytes trick to
4661 set file size due to need for large file support. Also note that
4662 this SetPathInfo is preferred to SetFileInfo based method in next
4663 routine which is only needed to work around a sharing violation bug
4664 in Samba which this routine can run into */
4667 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4668 __u64 size
, bool SetAllocation
,
4669 const struct nls_table
*nls_codepage
, int remap
)
4671 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4672 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4673 struct file_end_of_file_info
*parm_data
;
4676 int bytes_returned
= 0;
4677 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4679 cFYI(1, ("In SetEOF"));
4681 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4686 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4688 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4689 PATH_MAX
, nls_codepage
, remap
);
4690 name_len
++; /* trailing null */
4692 } else { /* BB improve the check for buffer overruns BB */
4693 name_len
= strnlen(fileName
, PATH_MAX
);
4694 name_len
++; /* trailing null */
4695 strncpy(pSMB
->FileName
, fileName
, name_len
);
4697 params
= 6 + name_len
;
4698 data_count
= sizeof(struct file_end_of_file_info
);
4699 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4700 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4701 pSMB
->MaxSetupCount
= 0;
4705 pSMB
->Reserved2
= 0;
4706 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4707 InformationLevel
) - 4;
4708 offset
= param_offset
+ params
;
4709 if (SetAllocation
) {
4710 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4711 pSMB
->InformationLevel
=
4712 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4714 pSMB
->InformationLevel
=
4715 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4716 } else /* Set File Size */ {
4717 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4718 pSMB
->InformationLevel
=
4719 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4721 pSMB
->InformationLevel
=
4722 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4726 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4728 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4729 pSMB
->DataOffset
= cpu_to_le16(offset
);
4730 pSMB
->SetupCount
= 1;
4731 pSMB
->Reserved3
= 0;
4732 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4733 byte_count
= 3 /* pad */ + params
+ data_count
;
4734 pSMB
->DataCount
= cpu_to_le16(data_count
);
4735 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4736 pSMB
->ParameterCount
= cpu_to_le16(params
);
4737 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4738 pSMB
->Reserved4
= 0;
4739 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4740 parm_data
->FileSize
= cpu_to_le64(size
);
4741 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4742 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4743 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4745 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4747 cifs_buf_release(pSMB
);
4756 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4757 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4759 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4761 struct file_end_of_file_info
*parm_data
;
4763 __u16 params
, param_offset
, offset
, byte_count
, count
;
4765 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4767 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4772 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4773 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4776 pSMB
->MaxSetupCount
= 0;
4780 pSMB
->Reserved2
= 0;
4781 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4782 offset
= param_offset
+ params
;
4784 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4786 count
= sizeof(struct file_end_of_file_info
);
4787 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4788 /* BB find exact max SMB PDU from sess structure BB */
4789 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4790 pSMB
->SetupCount
= 1;
4791 pSMB
->Reserved3
= 0;
4792 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4793 byte_count
= 3 /* pad */ + params
+ count
;
4794 pSMB
->DataCount
= cpu_to_le16(count
);
4795 pSMB
->ParameterCount
= cpu_to_le16(params
);
4796 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4797 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4798 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4800 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4802 pSMB
->DataOffset
= cpu_to_le16(offset
);
4803 parm_data
->FileSize
= cpu_to_le64(size
);
4805 if (SetAllocation
) {
4806 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4807 pSMB
->InformationLevel
=
4808 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4810 pSMB
->InformationLevel
=
4811 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4812 } else /* Set File Size */ {
4813 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4814 pSMB
->InformationLevel
=
4815 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4817 pSMB
->InformationLevel
=
4818 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4820 pSMB
->Reserved4
= 0;
4821 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4822 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4823 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4826 ("Send error in SetFileInfo (SetFileSize) = %d",
4830 /* Note: On -EAGAIN error only caller can retry on handle based calls
4831 since file handle passed in no longer valid */
4836 /* Some legacy servers such as NT4 require that the file times be set on
4837 an open handle, rather than by pathname - this is awkward due to
4838 potential access conflicts on the open, but it is unavoidable for these
4839 old servers since the only other choice is to go from 100 nanosecond DCE
4840 time and resort to the original setpathinfo level which takes the ancient
4841 DOS time format with 2 second granularity */
4843 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
4844 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
4846 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4849 __u16 params
, param_offset
, offset
, byte_count
, count
;
4851 cFYI(1, ("Set Times (via SetFileInfo)"));
4852 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4857 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4858 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4861 pSMB
->MaxSetupCount
= 0;
4865 pSMB
->Reserved2
= 0;
4866 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4867 offset
= param_offset
+ params
;
4869 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4871 count
= sizeof(FILE_BASIC_INFO
);
4872 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4873 /* BB find max SMB PDU from sess */
4874 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4875 pSMB
->SetupCount
= 1;
4876 pSMB
->Reserved3
= 0;
4877 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4878 byte_count
= 3 /* pad */ + params
+ count
;
4879 pSMB
->DataCount
= cpu_to_le16(count
);
4880 pSMB
->ParameterCount
= cpu_to_le16(params
);
4881 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4882 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4883 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4884 pSMB
->DataOffset
= cpu_to_le16(offset
);
4886 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4887 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4889 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4890 pSMB
->Reserved4
= 0;
4891 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4892 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4893 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4894 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4896 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4898 /* Note: On -EAGAIN error only caller can retry on handle based calls
4899 since file handle passed in no longer valid */
4905 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
4906 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
4908 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4911 __u16 params
, param_offset
, offset
, byte_count
, count
;
4913 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4914 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4919 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4920 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4923 pSMB
->MaxSetupCount
= 0;
4927 pSMB
->Reserved2
= 0;
4928 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4929 offset
= param_offset
+ params
;
4931 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4934 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4935 /* BB find max SMB PDU from sess */
4936 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4937 pSMB
->SetupCount
= 1;
4938 pSMB
->Reserved3
= 0;
4939 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4940 byte_count
= 3 /* pad */ + params
+ count
;
4941 pSMB
->DataCount
= cpu_to_le16(count
);
4942 pSMB
->ParameterCount
= cpu_to_le16(params
);
4943 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4944 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4945 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4946 pSMB
->DataOffset
= cpu_to_le16(offset
);
4948 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
4949 pSMB
->Reserved4
= 0;
4950 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4951 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4952 *data_offset
= delete_file
? 1 : 0;
4953 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4955 cFYI(1, ("Send error in SetFileDisposition = %d", rc
));
4961 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
4962 const char *fileName
, const FILE_BASIC_INFO
*data
,
4963 const struct nls_table
*nls_codepage
, int remap
)
4965 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4966 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4969 int bytes_returned
= 0;
4971 __u16 params
, param_offset
, offset
, byte_count
, count
;
4973 cFYI(1, ("In SetTimes"));
4976 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4981 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4983 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4984 PATH_MAX
, nls_codepage
, remap
);
4985 name_len
++; /* trailing null */
4987 } else { /* BB improve the check for buffer overruns BB */
4988 name_len
= strnlen(fileName
, PATH_MAX
);
4989 name_len
++; /* trailing null */
4990 strncpy(pSMB
->FileName
, fileName
, name_len
);
4993 params
= 6 + name_len
;
4994 count
= sizeof(FILE_BASIC_INFO
);
4995 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4996 /* BB find max SMB PDU from sess structure BB */
4997 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4998 pSMB
->MaxSetupCount
= 0;
5002 pSMB
->Reserved2
= 0;
5003 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5004 InformationLevel
) - 4;
5005 offset
= param_offset
+ params
;
5006 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5007 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5008 pSMB
->DataOffset
= cpu_to_le16(offset
);
5009 pSMB
->SetupCount
= 1;
5010 pSMB
->Reserved3
= 0;
5011 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5012 byte_count
= 3 /* pad */ + params
+ count
;
5014 pSMB
->DataCount
= cpu_to_le16(count
);
5015 pSMB
->ParameterCount
= cpu_to_le16(params
);
5016 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5017 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5018 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5019 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5021 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5022 pSMB
->Reserved4
= 0;
5023 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5024 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5025 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5026 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5027 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5029 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
5031 cifs_buf_release(pSMB
);
5039 /* Can not be used to set time stamps yet (due to old DOS time format) */
5040 /* Can be used to set attributes */
5041 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5042 handling it anyway and NT4 was what we thought it would be needed for
5043 Do not delete it until we prove whether needed for Win9x though */
5045 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5046 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5048 SETATTR_REQ
*pSMB
= NULL
;
5049 SETATTR_RSP
*pSMBr
= NULL
;
5054 cFYI(1, ("In SetAttrLegacy"));
5057 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5062 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5064 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5065 PATH_MAX
, nls_codepage
);
5066 name_len
++; /* trailing null */
5068 } else { /* BB improve the check for buffer overruns BB */
5069 name_len
= strnlen(fileName
, PATH_MAX
);
5070 name_len
++; /* trailing null */
5071 strncpy(pSMB
->fileName
, fileName
, name_len
);
5073 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5074 pSMB
->BufferFormat
= 0x04;
5075 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5076 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5077 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5078 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5080 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
5082 cifs_buf_release(pSMB
);
5085 goto SetAttrLgcyRetry
;
5089 #endif /* temporarily unneeded SetAttr legacy function */
5092 CIFSSMBUnixSetInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5093 const struct cifs_unix_set_info_args
*args
,
5094 const struct nls_table
*nls_codepage
, int remap
)
5096 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5097 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5100 int bytes_returned
= 0;
5101 FILE_UNIX_BASIC_INFO
*data_offset
;
5102 __u16 params
, param_offset
, offset
, count
, byte_count
;
5103 __u64 mode
= args
->mode
;
5105 cFYI(1, ("In SetUID/GID/Mode"));
5107 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5112 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5114 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5115 PATH_MAX
, nls_codepage
, remap
);
5116 name_len
++; /* trailing null */
5118 } else { /* BB improve the check for buffer overruns BB */
5119 name_len
= strnlen(fileName
, PATH_MAX
);
5120 name_len
++; /* trailing null */
5121 strncpy(pSMB
->FileName
, fileName
, name_len
);
5124 params
= 6 + name_len
;
5125 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5126 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5127 /* BB find max SMB PDU from sess structure BB */
5128 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5129 pSMB
->MaxSetupCount
= 0;
5133 pSMB
->Reserved2
= 0;
5134 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5135 InformationLevel
) - 4;
5136 offset
= param_offset
+ params
;
5138 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5140 memset(data_offset
, 0, count
);
5141 pSMB
->DataOffset
= cpu_to_le16(offset
);
5142 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5143 pSMB
->SetupCount
= 1;
5144 pSMB
->Reserved3
= 0;
5145 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5146 byte_count
= 3 /* pad */ + params
+ count
;
5147 pSMB
->ParameterCount
= cpu_to_le16(params
);
5148 pSMB
->DataCount
= cpu_to_le16(count
);
5149 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5150 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5151 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5152 pSMB
->Reserved4
= 0;
5153 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5154 /* Samba server ignores set of file size to zero due to bugs in some
5155 older clients, but we should be precise - we use SetFileSize to
5156 set file size and do not want to truncate file size to zero
5157 accidently as happened on one Samba server beta by putting
5158 zero instead of -1 here */
5159 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5160 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5161 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5162 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5163 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5164 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5165 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5166 /* better to leave device as zero when it is */
5167 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5168 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5169 data_offset
->Permissions
= cpu_to_le64(mode
);
5172 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5173 else if (S_ISDIR(mode
))
5174 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5175 else if (S_ISLNK(mode
))
5176 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5177 else if (S_ISCHR(mode
))
5178 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5179 else if (S_ISBLK(mode
))
5180 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5181 else if (S_ISFIFO(mode
))
5182 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5183 else if (S_ISSOCK(mode
))
5184 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5187 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5188 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5189 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5191 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5193 cifs_buf_release(pSMB
);
5199 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5200 const int notify_subdirs
, const __u16 netfid
,
5201 __u32 filter
, struct file
*pfile
, int multishot
,
5202 const struct nls_table
*nls_codepage
)
5205 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5206 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5207 struct dir_notify_req
*dnotify_req
;
5210 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5211 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5216 pSMB
->TotalParameterCount
= 0 ;
5217 pSMB
->TotalDataCount
= 0;
5218 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5219 /* BB find exact data count max from sess structure BB */
5220 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5221 /* BB VERIFY verify which is correct for above BB */
5222 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5223 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5225 pSMB
->MaxSetupCount
= 4;
5227 pSMB
->ParameterOffset
= 0;
5228 pSMB
->DataCount
= 0;
5229 pSMB
->DataOffset
= 0;
5230 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5231 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5232 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5234 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5235 pSMB
->Reserved2
= 0;
5236 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5237 pSMB
->Fid
= netfid
; /* file handle always le */
5238 pSMB
->ByteCount
= 0;
5240 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5241 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5244 cFYI(1, ("Error in Notify = %d", rc
));
5246 /* Add file to outstanding requests */
5247 /* BB change to kmem cache alloc */
5248 dnotify_req
= kmalloc(
5249 sizeof(struct dir_notify_req
),
5252 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5253 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5254 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5255 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5256 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5257 dnotify_req
->netfid
= netfid
;
5258 dnotify_req
->pfile
= pfile
;
5259 dnotify_req
->filter
= filter
;
5260 dnotify_req
->multishot
= multishot
;
5261 spin_lock(&GlobalMid_Lock
);
5262 list_add_tail(&dnotify_req
->lhead
,
5263 &GlobalDnotifyReqList
);
5264 spin_unlock(&GlobalMid_Lock
);
5268 cifs_buf_release(pSMB
);
5271 #ifdef CONFIG_CIFS_XATTR
5273 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5274 const unsigned char *searchName
,
5275 char *EAData
, size_t buf_size
,
5276 const struct nls_table
*nls_codepage
, int remap
)
5278 /* BB assumes one setup word */
5279 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5280 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5284 struct fea
*temp_fea
;
5286 __u16 params
, byte_count
;
5288 cFYI(1, ("In Query All EAs path %s", searchName
));
5290 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5295 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5297 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5298 PATH_MAX
, nls_codepage
, remap
);
5299 name_len
++; /* trailing null */
5301 } else { /* BB improve the check for buffer overruns BB */
5302 name_len
= strnlen(searchName
, PATH_MAX
);
5303 name_len
++; /* trailing null */
5304 strncpy(pSMB
->FileName
, searchName
, name_len
);
5307 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5308 pSMB
->TotalDataCount
= 0;
5309 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5310 /* BB find exact max SMB PDU from sess structure BB */
5311 pSMB
->MaxDataCount
= cpu_to_le16(4000);
5312 pSMB
->MaxSetupCount
= 0;
5316 pSMB
->Reserved2
= 0;
5317 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5318 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5319 pSMB
->DataCount
= 0;
5320 pSMB
->DataOffset
= 0;
5321 pSMB
->SetupCount
= 1;
5322 pSMB
->Reserved3
= 0;
5323 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5324 byte_count
= params
+ 1 /* pad */ ;
5325 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5326 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5327 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5328 pSMB
->Reserved4
= 0;
5329 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5330 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5332 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5333 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5335 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5336 } else { /* decode response */
5337 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5339 /* BB also check enough total bytes returned */
5340 /* BB we need to improve the validity checking
5341 of these trans2 responses */
5342 if (rc
|| (pSMBr
->ByteCount
< 4))
5343 rc
= -EIO
; /* bad smb */
5344 /* else if (pFindData){
5345 memcpy((char *) pFindData,
5346 (char *) &pSMBr->hdr.Protocol +
5349 /* check that length of list is not more than bcc */
5350 /* check that each entry does not go beyond length
5352 /* check that each element of each entry does not
5353 go beyond end of list */
5354 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5355 struct fealist
*ea_response_data
;
5357 /* validate_trans2_offsets() */
5358 /* BB check if start of smb + data_offset > &bcc+ bcc */
5359 ea_response_data
= (struct fealist
*)
5360 (((char *) &pSMBr
->hdr
.Protocol
) +
5362 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5363 cFYI(1, ("ea length %d", name_len
));
5364 if (name_len
<= 8) {
5365 /* returned EA size zeroed at top of function */
5366 cFYI(1, ("empty EA list returned from server"));
5368 /* account for ea list len */
5370 temp_fea
= ea_response_data
->list
;
5371 temp_ptr
= (char *)temp_fea
;
5372 while (name_len
> 0) {
5376 rc
+= temp_fea
->name_len
;
5377 /* account for prefix user. and trailing null */
5379 if (rc
< (int)buf_size
) {
5380 memcpy(EAData
, "user.", 5);
5382 memcpy(EAData
, temp_ptr
,
5383 temp_fea
->name_len
);
5384 EAData
+= temp_fea
->name_len
;
5385 /* null terminate name */
5387 EAData
= EAData
+ 1;
5388 } else if (buf_size
== 0) {
5389 /* skip copy - calc size only */
5391 /* stop before overrun buffer */
5395 name_len
-= temp_fea
->name_len
;
5396 temp_ptr
+= temp_fea
->name_len
;
5397 /* account for trailing null */
5401 le16_to_cpu(temp_fea
->value_len
);
5402 name_len
-= value_len
;
5403 temp_ptr
+= value_len
;
5404 /* BB check that temp_ptr is still
5407 /* no trailing null to account for
5409 /* go on to next EA */
5410 temp_fea
= (struct fea
*)temp_ptr
;
5415 cifs_buf_release(pSMB
);
5422 ssize_t
CIFSSMBQueryEA(const int xid
, struct cifsTconInfo
*tcon
,
5423 const unsigned char *searchName
, const unsigned char *ea_name
,
5424 unsigned char *ea_value
, size_t buf_size
,
5425 const struct nls_table
*nls_codepage
, int remap
)
5427 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5428 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5432 struct fea
*temp_fea
;
5434 __u16 params
, byte_count
;
5436 cFYI(1, ("In Query EA path %s", searchName
));
5438 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5443 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5445 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5446 PATH_MAX
, nls_codepage
, remap
);
5447 name_len
++; /* trailing null */
5449 } else { /* BB improve the check for buffer overruns BB */
5450 name_len
= strnlen(searchName
, PATH_MAX
);
5451 name_len
++; /* trailing null */
5452 strncpy(pSMB
->FileName
, searchName
, name_len
);
5455 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5456 pSMB
->TotalDataCount
= 0;
5457 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5458 /* BB find exact max SMB PDU from sess structure BB */
5459 pSMB
->MaxDataCount
= cpu_to_le16(4000);
5460 pSMB
->MaxSetupCount
= 0;
5464 pSMB
->Reserved2
= 0;
5465 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5466 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5467 pSMB
->DataCount
= 0;
5468 pSMB
->DataOffset
= 0;
5469 pSMB
->SetupCount
= 1;
5470 pSMB
->Reserved3
= 0;
5471 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5472 byte_count
= params
+ 1 /* pad */ ;
5473 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5474 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5475 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5476 pSMB
->Reserved4
= 0;
5477 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5478 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5480 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5481 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5483 cFYI(1, ("Send error in Query EA = %d", rc
));
5484 } else { /* decode response */
5485 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5487 /* BB also check enough total bytes returned */
5488 /* BB we need to improve the validity checking
5489 of these trans2 responses */
5490 if (rc
|| (pSMBr
->ByteCount
< 4))
5491 rc
= -EIO
; /* bad smb */
5492 /* else if (pFindData){
5493 memcpy((char *) pFindData,
5494 (char *) &pSMBr->hdr.Protocol +
5497 /* check that length of list is not more than bcc */
5498 /* check that each entry does not go beyond length
5500 /* check that each element of each entry does not
5501 go beyond end of list */
5502 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5503 struct fealist
*ea_response_data
;
5505 /* validate_trans2_offsets() */
5506 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5507 ea_response_data
= (struct fealist
*)
5508 (((char *) &pSMBr
->hdr
.Protocol
) +
5510 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5511 cFYI(1, ("ea length %d", name_len
));
5512 if (name_len
<= 8) {
5513 /* returned EA size zeroed at top of function */
5514 cFYI(1, ("empty EA list returned from server"));
5516 /* account for ea list len */
5518 temp_fea
= ea_response_data
->list
;
5519 temp_ptr
= (char *)temp_fea
;
5520 /* loop through checking if we have a matching
5521 name and then return the associated value */
5522 while (name_len
> 0) {
5527 le16_to_cpu(temp_fea
->value_len
);
5528 /* BB validate that value_len falls within SMB,
5529 even though maximum for name_len is 255 */
5530 if (memcmp(temp_fea
->name
, ea_name
,
5531 temp_fea
->name_len
) == 0) {
5534 /* account for prefix user. and trailing null */
5535 if (rc
<= (int)buf_size
) {
5537 temp_fea
->name
+temp_fea
->name_len
+1,
5539 /* ea values, unlike ea
5542 } else if (buf_size
== 0) {
5543 /* skip copy - calc size only */
5545 /* stop before overrun buffer */
5550 name_len
-= temp_fea
->name_len
;
5551 temp_ptr
+= temp_fea
->name_len
;
5552 /* account for trailing null */
5555 name_len
-= value_len
;
5556 temp_ptr
+= value_len
;
5557 /* No trailing null to account for in
5558 value_len. Go on to next EA */
5559 temp_fea
= (struct fea
*)temp_ptr
;
5564 cifs_buf_release(pSMB
);
5572 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5573 const char *ea_name
, const void *ea_value
,
5574 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5577 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5578 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5579 struct fealist
*parm_data
;
5582 int bytes_returned
= 0;
5583 __u16 params
, param_offset
, byte_count
, offset
, count
;
5585 cFYI(1, ("In SetEA"));
5587 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5592 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5594 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5595 PATH_MAX
, nls_codepage
, remap
);
5596 name_len
++; /* trailing null */
5598 } else { /* BB improve the check for buffer overruns BB */
5599 name_len
= strnlen(fileName
, PATH_MAX
);
5600 name_len
++; /* trailing null */
5601 strncpy(pSMB
->FileName
, fileName
, name_len
);
5604 params
= 6 + name_len
;
5606 /* done calculating parms using name_len of file name,
5607 now use name_len to calculate length of ea name
5608 we are going to create in the inode xattrs */
5609 if (ea_name
== NULL
)
5612 name_len
= strnlen(ea_name
, 255);
5614 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5615 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5616 /* BB find max SMB PDU from sess */
5617 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5618 pSMB
->MaxSetupCount
= 0;
5622 pSMB
->Reserved2
= 0;
5623 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5624 InformationLevel
) - 4;
5625 offset
= param_offset
+ params
;
5626 pSMB
->InformationLevel
=
5627 cpu_to_le16(SMB_SET_FILE_EA
);
5630 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5632 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5633 pSMB
->DataOffset
= cpu_to_le16(offset
);
5634 pSMB
->SetupCount
= 1;
5635 pSMB
->Reserved3
= 0;
5636 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5637 byte_count
= 3 /* pad */ + params
+ count
;
5638 pSMB
->DataCount
= cpu_to_le16(count
);
5639 parm_data
->list_len
= cpu_to_le32(count
);
5640 parm_data
->list
[0].EA_flags
= 0;
5641 /* we checked above that name len is less than 255 */
5642 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5643 /* EA names are always ASCII */
5645 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5646 parm_data
->list
[0].name
[name_len
] = 0;
5647 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5648 /* caller ensures that ea_value_len is less than 64K but
5649 we need to ensure that it fits within the smb */
5651 /*BB add length check to see if it would fit in
5652 negotiated SMB buffer size BB */
5653 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5655 memcpy(parm_data
->list
[0].name
+name_len
+1,
5656 ea_value
, ea_value_len
);
5658 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5659 pSMB
->ParameterCount
= cpu_to_le16(params
);
5660 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5661 pSMB
->Reserved4
= 0;
5662 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5663 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5664 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5665 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5667 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5669 cifs_buf_release(pSMB
);