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);
1312 pfile_info
->DeletePending
= 0;
1316 cifs_buf_release(pSMB
);
1323 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1324 const char *fileName
, const int openDisposition
,
1325 const int access_flags
, const int create_options
, __u16
*netfid
,
1326 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1327 const struct nls_table
*nls_codepage
, int remap
)
1330 OPEN_REQ
*pSMB
= NULL
;
1331 OPEN_RSP
*pSMBr
= NULL
;
1337 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1342 pSMB
->AndXCommand
= 0xFF; /* none */
1344 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1345 count
= 1; /* account for one byte pad to word boundary */
1347 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1348 fileName
, PATH_MAX
, nls_codepage
, remap
);
1349 name_len
++; /* trailing null */
1351 pSMB
->NameLength
= cpu_to_le16(name_len
);
1352 } else { /* BB improve check for buffer overruns BB */
1353 count
= 0; /* no pad */
1354 name_len
= strnlen(fileName
, PATH_MAX
);
1355 name_len
++; /* trailing null */
1356 pSMB
->NameLength
= cpu_to_le16(name_len
);
1357 strncpy(pSMB
->fileName
, fileName
, name_len
);
1359 if (*pOplock
& REQ_OPLOCK
)
1360 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1361 else if (*pOplock
& REQ_BATCHOPLOCK
)
1362 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1363 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1364 pSMB
->AllocationSize
= 0;
1365 /* set file as system file if special file such
1366 as fifo and server expecting SFU style and
1367 no Unix extensions */
1368 if (create_options
& CREATE_OPTION_SPECIAL
)
1369 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1371 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1373 /* XP does not handle ATTR_POSIX_SEMANTICS */
1374 /* but it helps speed up case sensitive checks for other
1375 servers such as Samba */
1376 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1377 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1379 if (create_options
& CREATE_OPTION_READONLY
)
1380 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1382 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1383 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1384 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1385 /* BB Expirement with various impersonation levels and verify */
1386 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1387 pSMB
->SecurityFlags
=
1388 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1391 pSMB
->hdr
.smb_buf_length
+= count
;
1393 pSMB
->ByteCount
= cpu_to_le16(count
);
1394 /* long_op set to 1 to allow for oplock break timeouts */
1395 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1396 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1397 cifs_stats_inc(&tcon
->num_opens
);
1399 cFYI(1, ("Error in Open = %d", rc
));
1401 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1402 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1403 /* Let caller know file was created so we can set the mode. */
1404 /* Do we care about the CreateAction in any other cases? */
1405 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1406 *pOplock
|= CIFS_CREATE_ACTION
;
1408 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1409 36 /* CreationTime to Attributes */);
1410 /* the file_info buf is endian converted by caller */
1411 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1412 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1413 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1414 pfile_info
->DeletePending
= 0;
1418 cifs_buf_release(pSMB
);
1425 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1426 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1427 char **buf
, int *pbuf_type
)
1430 READ_REQ
*pSMB
= NULL
;
1431 READ_RSP
*pSMBr
= NULL
;
1432 char *pReadData
= NULL
;
1434 int resp_buf_type
= 0;
1437 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1438 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1441 wct
= 10; /* old style read */
1444 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1448 /* tcon and ses pointer are checked in smb_init */
1449 if (tcon
->ses
->server
== NULL
)
1450 return -ECONNABORTED
;
1452 pSMB
->AndXCommand
= 0xFF; /* none */
1454 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1456 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1457 else if ((lseek
>> 32) > 0) /* can not handle this big offset for old */
1460 pSMB
->Remaining
= 0;
1461 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1462 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1464 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1466 /* old style read */
1467 struct smb_com_readx_req
*pSMBW
=
1468 (struct smb_com_readx_req
*)pSMB
;
1469 pSMBW
->ByteCount
= 0;
1472 iov
[0].iov_base
= (char *)pSMB
;
1473 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1474 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1475 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1476 cifs_stats_inc(&tcon
->num_reads
);
1477 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1479 cERROR(1, ("Send error in read = %d", rc
));
1481 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1482 data_length
= data_length
<< 16;
1483 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1484 *nbytes
= data_length
;
1486 /*check that DataLength would not go beyond end of SMB */
1487 if ((data_length
> CIFSMaxBufSize
)
1488 || (data_length
> count
)) {
1489 cFYI(1, ("bad length %d for count %d",
1490 data_length
, count
));
1494 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1495 le16_to_cpu(pSMBr
->DataOffset
);
1496 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1497 cERROR(1,("Faulting on read rc = %d",rc));
1499 }*/ /* can not use copy_to_user when using page cache*/
1501 memcpy(*buf
, pReadData
, data_length
);
1505 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1507 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1508 cifs_small_buf_release(iov
[0].iov_base
);
1509 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1510 cifs_buf_release(iov
[0].iov_base
);
1511 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1512 /* return buffer to caller to free */
1513 *buf
= iov
[0].iov_base
;
1514 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1515 *pbuf_type
= CIFS_SMALL_BUFFER
;
1516 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1517 *pbuf_type
= CIFS_LARGE_BUFFER
;
1518 } /* else no valid buffer on return - leave as null */
1520 /* Note: On -EAGAIN error only caller can retry on handle based calls
1521 since file handle passed in no longer valid */
1527 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1528 const int netfid
, const unsigned int count
,
1529 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1530 const char __user
*ubuf
, const int long_op
)
1533 WRITE_REQ
*pSMB
= NULL
;
1534 WRITE_RSP
*pSMBr
= NULL
;
1535 int bytes_returned
, wct
;
1539 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1540 if (tcon
->ses
== NULL
)
1541 return -ECONNABORTED
;
1543 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1548 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1552 /* tcon and ses pointer are checked in smb_init */
1553 if (tcon
->ses
->server
== NULL
)
1554 return -ECONNABORTED
;
1556 pSMB
->AndXCommand
= 0xFF; /* none */
1558 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1560 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1561 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1564 pSMB
->Reserved
= 0xFFFFFFFF;
1565 pSMB
->WriteMode
= 0;
1566 pSMB
->Remaining
= 0;
1568 /* Can increase buffer size if buffer is big enough in some cases ie we
1569 can send more if LARGE_WRITE_X capability returned by the server and if
1570 our buffer is big enough or if we convert to iovecs on socket writes
1571 and eliminate the copy to the CIFS buffer */
1572 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1573 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1575 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1579 if (bytes_sent
> count
)
1582 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1584 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1586 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1587 cifs_buf_release(pSMB
);
1590 } else if (count
!= 0) {
1592 cifs_buf_release(pSMB
);
1594 } /* else setting file size with write of zero bytes */
1596 byte_count
= bytes_sent
+ 1; /* pad */
1597 else /* wct == 12 */
1598 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1600 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1601 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1602 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1605 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1606 else { /* old style write has byte count 4 bytes earlier
1608 struct smb_com_writex_req
*pSMBW
=
1609 (struct smb_com_writex_req
*)pSMB
;
1610 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1613 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1614 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1615 cifs_stats_inc(&tcon
->num_writes
);
1617 cFYI(1, ("Send error in write = %d", rc
));
1620 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1621 *nbytes
= (*nbytes
) << 16;
1622 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1625 cifs_buf_release(pSMB
);
1627 /* Note: On -EAGAIN error only caller can retry on handle based calls
1628 since file handle passed in no longer valid */
1634 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1635 const int netfid
, const unsigned int count
,
1636 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1637 int n_vec
, const int long_op
)
1640 WRITE_REQ
*pSMB
= NULL
;
1643 int resp_buf_type
= 0;
1645 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1647 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1651 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1654 /* tcon and ses pointer are checked in smb_init */
1655 if (tcon
->ses
->server
== NULL
)
1656 return -ECONNABORTED
;
1658 pSMB
->AndXCommand
= 0xFF; /* none */
1660 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1662 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1663 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1665 pSMB
->Reserved
= 0xFFFFFFFF;
1666 pSMB
->WriteMode
= 0;
1667 pSMB
->Remaining
= 0;
1670 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1672 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1673 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1674 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1676 pSMB
->hdr
.smb_buf_length
+= count
+1;
1677 else /* wct == 12 */
1678 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1680 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1681 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1682 struct smb_com_writex_req
*pSMBW
=
1683 (struct smb_com_writex_req
*)pSMB
;
1684 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1686 iov
[0].iov_base
= pSMB
;
1688 iov
[0].iov_len
= smb_hdr_len
+ 4;
1689 else /* wct == 12 pad bigger by four bytes */
1690 iov
[0].iov_len
= smb_hdr_len
+ 8;
1693 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1695 cifs_stats_inc(&tcon
->num_writes
);
1697 cFYI(1, ("Send error Write2 = %d", rc
));
1699 } else if (resp_buf_type
== 0) {
1700 /* presumably this can not happen, but best to be safe */
1704 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1705 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1706 *nbytes
= (*nbytes
) << 16;
1707 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1710 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1711 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1712 cifs_small_buf_release(iov
[0].iov_base
);
1713 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1714 cifs_buf_release(iov
[0].iov_base
);
1716 /* Note: On -EAGAIN error only caller can retry on handle based calls
1717 since file handle passed in no longer valid */
1724 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1725 const __u16 smb_file_id
, const __u64 len
,
1726 const __u64 offset
, const __u32 numUnlock
,
1727 const __u32 numLock
, const __u8 lockType
, const bool waitFlag
)
1730 LOCK_REQ
*pSMB
= NULL
;
1731 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1736 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
));
1737 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1742 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1743 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1745 } else if (waitFlag
) {
1746 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1747 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1752 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1753 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1754 pSMB
->LockType
= lockType
;
1755 pSMB
->AndXCommand
= 0xFF; /* none */
1756 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1758 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1759 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1760 /* BB where to store pid high? */
1761 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1762 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1763 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1764 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1765 count
= sizeof(LOCKING_ANDX_RANGE
);
1770 pSMB
->hdr
.smb_buf_length
+= count
;
1771 pSMB
->ByteCount
= cpu_to_le16(count
);
1774 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1775 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1776 cifs_small_buf_release(pSMB
);
1778 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1780 /* SMB buffer freed by function above */
1782 cifs_stats_inc(&tcon
->num_locks
);
1784 cFYI(1, ("Send error in Lock = %d", rc
));
1786 /* Note: On -EAGAIN error only caller can retry on handle based calls
1787 since file handle passed in no longer valid */
1792 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1793 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1794 struct file_lock
*pLockData
, const __u16 lock_type
,
1795 const bool waitFlag
)
1797 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1798 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1799 struct cifs_posix_lock
*parm_data
;
1802 int bytes_returned
= 0;
1803 int resp_buf_type
= 0;
1804 __u16 params
, param_offset
, offset
, byte_count
, count
;
1807 cFYI(1, ("Posix Lock"));
1809 if (pLockData
== NULL
)
1812 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1817 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1820 pSMB
->MaxSetupCount
= 0;
1823 pSMB
->Reserved2
= 0;
1824 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1825 offset
= param_offset
+ params
;
1827 count
= sizeof(struct cifs_posix_lock
);
1828 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1829 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1830 pSMB
->SetupCount
= 1;
1831 pSMB
->Reserved3
= 0;
1833 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1835 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1836 byte_count
= 3 /* pad */ + params
+ count
;
1837 pSMB
->DataCount
= cpu_to_le16(count
);
1838 pSMB
->ParameterCount
= cpu_to_le16(params
);
1839 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1840 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1841 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1842 parm_data
= (struct cifs_posix_lock
*)
1843 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1845 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1847 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1848 parm_data
->lock_flags
= cpu_to_le16(1);
1849 pSMB
->Timeout
= cpu_to_le32(-1);
1853 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1854 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1855 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1857 pSMB
->DataOffset
= cpu_to_le16(offset
);
1858 pSMB
->Fid
= smb_file_id
;
1859 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1860 pSMB
->Reserved4
= 0;
1861 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1862 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1864 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1865 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1867 iov
[0].iov_base
= (char *)pSMB
;
1868 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1869 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1870 &resp_buf_type
, timeout
);
1871 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1872 not try to free it twice below on exit */
1873 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1877 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1878 } else if (get_flag
) {
1879 /* lock structure can be returned on get */
1882 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1884 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1885 rc
= -EIO
; /* bad smb */
1888 if (pLockData
== NULL
) {
1892 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1893 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1894 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1898 parm_data
= (struct cifs_posix_lock
*)
1899 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1900 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1901 pLockData
->fl_type
= F_UNLCK
;
1906 cifs_small_buf_release(pSMB
);
1908 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1909 cifs_small_buf_release(iov
[0].iov_base
);
1910 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1911 cifs_buf_release(iov
[0].iov_base
);
1913 /* Note: On -EAGAIN error only caller can retry on handle based calls
1914 since file handle passed in no longer valid */
1921 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1924 CLOSE_REQ
*pSMB
= NULL
;
1925 cFYI(1, ("In CIFSSMBClose"));
1927 /* do not retry on dead session on close */
1928 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1934 pSMB
->FileID
= (__u16
) smb_file_id
;
1935 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1936 pSMB
->ByteCount
= 0;
1937 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1938 cifs_stats_inc(&tcon
->num_closes
);
1941 /* EINTR is expected when user ctl-c to kill app */
1942 cERROR(1, ("Send error in Close = %d", rc
));
1946 /* Since session is dead, file will be closed on server already */
1954 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1955 const char *fromName
, const char *toName
,
1956 const struct nls_table
*nls_codepage
, int remap
)
1959 RENAME_REQ
*pSMB
= NULL
;
1960 RENAME_RSP
*pSMBr
= NULL
;
1962 int name_len
, name_len2
;
1965 cFYI(1, ("In CIFSSMBRename"));
1967 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1972 pSMB
->BufferFormat
= 0x04;
1973 pSMB
->SearchAttributes
=
1974 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1977 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1979 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1980 PATH_MAX
, nls_codepage
, remap
);
1981 name_len
++; /* trailing null */
1983 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1984 /* protocol requires ASCII signature byte on Unicode string */
1985 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1987 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1988 toName
, PATH_MAX
, nls_codepage
, remap
);
1989 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1990 name_len2
*= 2; /* convert to bytes */
1991 } else { /* BB improve the check for buffer overruns BB */
1992 name_len
= strnlen(fromName
, PATH_MAX
);
1993 name_len
++; /* trailing null */
1994 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1995 name_len2
= strnlen(toName
, PATH_MAX
);
1996 name_len2
++; /* trailing null */
1997 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1998 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1999 name_len2
++; /* trailing null */
2000 name_len2
++; /* signature byte */
2003 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2004 pSMB
->hdr
.smb_buf_length
+= count
;
2005 pSMB
->ByteCount
= cpu_to_le16(count
);
2007 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2008 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2009 cifs_stats_inc(&tcon
->num_renames
);
2011 cFYI(1, ("Send error in rename = %d", rc
));
2013 cifs_buf_release(pSMB
);
2021 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
2022 int netfid
, const char *target_name
,
2023 const struct nls_table
*nls_codepage
, int remap
)
2025 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2026 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2027 struct set_file_rename
*rename_info
;
2029 char dummy_string
[30];
2031 int bytes_returned
= 0;
2033 __u16 params
, param_offset
, offset
, count
, byte_count
;
2035 cFYI(1, ("Rename to File by handle"));
2036 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2042 pSMB
->MaxSetupCount
= 0;
2046 pSMB
->Reserved2
= 0;
2047 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2048 offset
= param_offset
+ params
;
2050 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2051 rename_info
= (struct set_file_rename
*) data_offset
;
2052 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2053 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2054 pSMB
->SetupCount
= 1;
2055 pSMB
->Reserved3
= 0;
2056 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2057 byte_count
= 3 /* pad */ + params
;
2058 pSMB
->ParameterCount
= cpu_to_le16(params
);
2059 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2060 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2061 pSMB
->DataOffset
= cpu_to_le16(offset
);
2062 /* construct random name ".cifs_tmp<inodenum><mid>" */
2063 rename_info
->overwrite
= cpu_to_le32(1);
2064 rename_info
->root_fid
= 0;
2065 /* unicode only call */
2066 if (target_name
== NULL
) {
2067 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2068 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2069 dummy_string
, 24, nls_codepage
, remap
);
2071 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2072 target_name
, PATH_MAX
, nls_codepage
,
2075 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2076 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2077 byte_count
+= count
;
2078 pSMB
->DataCount
= cpu_to_le16(count
);
2079 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2081 pSMB
->InformationLevel
=
2082 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2083 pSMB
->Reserved4
= 0;
2084 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2085 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2086 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2087 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2088 cifs_stats_inc(&pTcon
->num_t2renames
);
2090 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2092 cifs_buf_release(pSMB
);
2094 /* Note: On -EAGAIN error only caller can retry on handle based calls
2095 since file handle passed in no longer valid */
2101 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2102 const __u16 target_tid
, const char *toName
, const int flags
,
2103 const struct nls_table
*nls_codepage
, int remap
)
2106 COPY_REQ
*pSMB
= NULL
;
2107 COPY_RSP
*pSMBr
= NULL
;
2109 int name_len
, name_len2
;
2112 cFYI(1, ("In CIFSSMBCopy"));
2114 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2119 pSMB
->BufferFormat
= 0x04;
2120 pSMB
->Tid2
= target_tid
;
2122 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2124 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2125 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2126 fromName
, PATH_MAX
, nls_codepage
,
2128 name_len
++; /* trailing null */
2130 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2131 /* protocol requires ASCII signature byte on Unicode string */
2132 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2134 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2135 toName
, PATH_MAX
, nls_codepage
, remap
);
2136 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2137 name_len2
*= 2; /* convert to bytes */
2138 } else { /* BB improve the check for buffer overruns BB */
2139 name_len
= strnlen(fromName
, PATH_MAX
);
2140 name_len
++; /* trailing null */
2141 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2142 name_len2
= strnlen(toName
, PATH_MAX
);
2143 name_len2
++; /* trailing null */
2144 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2145 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2146 name_len2
++; /* trailing null */
2147 name_len2
++; /* signature byte */
2150 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2151 pSMB
->hdr
.smb_buf_length
+= count
;
2152 pSMB
->ByteCount
= cpu_to_le16(count
);
2154 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2155 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2157 cFYI(1, ("Send error in copy = %d with %d files copied",
2158 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2160 cifs_buf_release(pSMB
);
2169 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2170 const char *fromName
, const char *toName
,
2171 const struct nls_table
*nls_codepage
)
2173 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2174 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2177 int name_len_target
;
2179 int bytes_returned
= 0;
2180 __u16 params
, param_offset
, offset
, byte_count
;
2182 cFYI(1, ("In Symlink Unix style"));
2184 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2189 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2191 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2192 /* find define for this maxpathcomponent */
2194 name_len
++; /* trailing null */
2197 } else { /* BB improve the check for buffer overruns BB */
2198 name_len
= strnlen(fromName
, PATH_MAX
);
2199 name_len
++; /* trailing null */
2200 strncpy(pSMB
->FileName
, fromName
, name_len
);
2202 params
= 6 + name_len
;
2203 pSMB
->MaxSetupCount
= 0;
2207 pSMB
->Reserved2
= 0;
2208 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2209 InformationLevel
) - 4;
2210 offset
= param_offset
+ params
;
2212 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2213 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2215 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2216 /* find define for this maxpathcomponent */
2218 name_len_target
++; /* trailing null */
2219 name_len_target
*= 2;
2220 } else { /* BB improve the check for buffer overruns BB */
2221 name_len_target
= strnlen(toName
, PATH_MAX
);
2222 name_len_target
++; /* trailing null */
2223 strncpy(data_offset
, toName
, name_len_target
);
2226 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2227 /* BB find exact max on data count below from sess */
2228 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2229 pSMB
->SetupCount
= 1;
2230 pSMB
->Reserved3
= 0;
2231 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2232 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2233 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2234 pSMB
->ParameterCount
= cpu_to_le16(params
);
2235 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2236 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2237 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2238 pSMB
->DataOffset
= cpu_to_le16(offset
);
2239 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2240 pSMB
->Reserved4
= 0;
2241 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2242 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2243 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2244 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2245 cifs_stats_inc(&tcon
->num_symlinks
);
2247 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2249 cifs_buf_release(pSMB
);
2252 goto createSymLinkRetry
;
2258 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2259 const char *fromName
, const char *toName
,
2260 const struct nls_table
*nls_codepage
, int remap
)
2262 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2263 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2266 int name_len_target
;
2268 int bytes_returned
= 0;
2269 __u16 params
, param_offset
, offset
, byte_count
;
2271 cFYI(1, ("In Create Hard link Unix style"));
2272 createHardLinkRetry
:
2273 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2278 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2279 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2280 PATH_MAX
, nls_codepage
, remap
);
2281 name_len
++; /* trailing null */
2284 } else { /* BB improve the check for buffer overruns BB */
2285 name_len
= strnlen(toName
, PATH_MAX
);
2286 name_len
++; /* trailing null */
2287 strncpy(pSMB
->FileName
, toName
, name_len
);
2289 params
= 6 + name_len
;
2290 pSMB
->MaxSetupCount
= 0;
2294 pSMB
->Reserved2
= 0;
2295 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2296 InformationLevel
) - 4;
2297 offset
= param_offset
+ params
;
2299 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2300 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2302 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2303 nls_codepage
, remap
);
2304 name_len_target
++; /* trailing null */
2305 name_len_target
*= 2;
2306 } else { /* BB improve the check for buffer overruns BB */
2307 name_len_target
= strnlen(fromName
, PATH_MAX
);
2308 name_len_target
++; /* trailing null */
2309 strncpy(data_offset
, fromName
, name_len_target
);
2312 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2313 /* BB find exact max on data count below from sess*/
2314 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2315 pSMB
->SetupCount
= 1;
2316 pSMB
->Reserved3
= 0;
2317 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2318 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2319 pSMB
->ParameterCount
= cpu_to_le16(params
);
2320 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2321 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2322 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2323 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2324 pSMB
->DataOffset
= cpu_to_le16(offset
);
2325 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2326 pSMB
->Reserved4
= 0;
2327 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2328 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2329 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2330 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2331 cifs_stats_inc(&tcon
->num_hardlinks
);
2333 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2335 cifs_buf_release(pSMB
);
2337 goto createHardLinkRetry
;
2343 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2344 const char *fromName
, const char *toName
,
2345 const struct nls_table
*nls_codepage
, int remap
)
2348 NT_RENAME_REQ
*pSMB
= NULL
;
2349 RENAME_RSP
*pSMBr
= NULL
;
2351 int name_len
, name_len2
;
2354 cFYI(1, ("In CIFSCreateHardLink"));
2355 winCreateHardLinkRetry
:
2357 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2362 pSMB
->SearchAttributes
=
2363 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2365 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2366 pSMB
->ClusterCount
= 0;
2368 pSMB
->BufferFormat
= 0x04;
2370 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2372 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2373 PATH_MAX
, nls_codepage
, remap
);
2374 name_len
++; /* trailing null */
2376 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2377 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2379 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2380 toName
, PATH_MAX
, nls_codepage
, remap
);
2381 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2382 name_len2
*= 2; /* convert to bytes */
2383 } else { /* BB improve the check for buffer overruns BB */
2384 name_len
= strnlen(fromName
, PATH_MAX
);
2385 name_len
++; /* trailing null */
2386 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2387 name_len2
= strnlen(toName
, PATH_MAX
);
2388 name_len2
++; /* trailing null */
2389 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2390 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2391 name_len2
++; /* trailing null */
2392 name_len2
++; /* signature byte */
2395 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2396 pSMB
->hdr
.smb_buf_length
+= count
;
2397 pSMB
->ByteCount
= cpu_to_le16(count
);
2399 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2400 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2401 cifs_stats_inc(&tcon
->num_hardlinks
);
2403 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2405 cifs_buf_release(pSMB
);
2407 goto winCreateHardLinkRetry
;
2413 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2414 const unsigned char *searchName
,
2415 char *symlinkinfo
, const int buflen
,
2416 const struct nls_table
*nls_codepage
)
2418 /* SMB_QUERY_FILE_UNIX_LINK */
2419 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2420 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2424 __u16 params
, byte_count
;
2426 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2429 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2434 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2436 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2437 PATH_MAX
, nls_codepage
);
2438 name_len
++; /* trailing null */
2440 } else { /* BB improve the check for buffer overruns BB */
2441 name_len
= strnlen(searchName
, PATH_MAX
);
2442 name_len
++; /* trailing null */
2443 strncpy(pSMB
->FileName
, searchName
, name_len
);
2446 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2447 pSMB
->TotalDataCount
= 0;
2448 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2449 /* BB find exact max data count below from sess structure BB */
2450 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2451 pSMB
->MaxSetupCount
= 0;
2455 pSMB
->Reserved2
= 0;
2456 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2457 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2458 pSMB
->DataCount
= 0;
2459 pSMB
->DataOffset
= 0;
2460 pSMB
->SetupCount
= 1;
2461 pSMB
->Reserved3
= 0;
2462 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2463 byte_count
= params
+ 1 /* pad */ ;
2464 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2465 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2466 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2467 pSMB
->Reserved4
= 0;
2468 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2469 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2471 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2472 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2474 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2476 /* decode response */
2478 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2479 if (rc
|| (pSMBr
->ByteCount
< 2))
2480 /* BB also check enough total bytes returned */
2481 rc
= -EIO
; /* bad smb */
2483 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2484 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2486 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2487 name_len
= UniStrnlen((wchar_t *) ((char *)
2488 &pSMBr
->hdr
.Protocol
+ data_offset
),
2489 min_t(const int, buflen
, count
) / 2);
2490 /* BB FIXME investigate remapping reserved chars here */
2491 cifs_strfromUCS_le(symlinkinfo
,
2492 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
2494 name_len
, nls_codepage
);
2496 strncpy(symlinkinfo
,
2497 (char *) &pSMBr
->hdr
.Protocol
+
2499 min_t(const int, buflen
, count
));
2501 symlinkinfo
[buflen
] = 0;
2502 /* just in case so calling code does not go off the end of buffer */
2505 cifs_buf_release(pSMB
);
2507 goto querySymLinkRetry
;
2511 #ifdef CONFIG_CIFS_EXPERIMENTAL
2512 /* Initialize NT TRANSACT SMB into small smb request buffer.
2513 This assumes that all NT TRANSACTS that we init here have
2514 total parm and data under about 400 bytes (to fit in small cifs
2515 buffer size), which is the case so far, it easily fits. NB:
2516 Setup words themselves and ByteCount
2517 MaxSetupCount (size of returned setup area) and
2518 MaxParameterCount (returned parms size) must be set by caller */
2520 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2521 const int parm_len
, struct cifsTconInfo
*tcon
,
2526 struct smb_com_ntransact_req
*pSMB
;
2528 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2532 *ret_buf
= (void *)pSMB
;
2534 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2535 pSMB
->TotalDataCount
= 0;
2536 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2537 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2538 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2539 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2540 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2541 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2542 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2543 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2544 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2545 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2550 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2551 __u32
*pparmlen
, __u32
*pdatalen
)
2554 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2555 struct smb_com_ntransact_rsp
*pSMBr
;
2563 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2565 /* ByteCount was converted from little endian in SendReceive */
2566 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2567 (char *)&pSMBr
->ByteCount
;
2569 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2570 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2571 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2572 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2574 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2575 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2577 /* should we also check that parm and data areas do not overlap? */
2578 if (*ppparm
> end_of_smb
) {
2579 cFYI(1, ("parms start after end of smb"));
2581 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2582 cFYI(1, ("parm end after end of smb"));
2584 } else if (*ppdata
> end_of_smb
) {
2585 cFYI(1, ("data starts after end of smb"));
2587 } else if (data_count
+ *ppdata
> end_of_smb
) {
2588 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2589 *ppdata
, data_count
, (data_count
+ *ppdata
),
2590 end_of_smb
, pSMBr
));
2592 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2593 cFYI(1, ("parm count and data count larger than SMB"));
2596 *pdatalen
= data_count
;
2597 *pparmlen
= parm_count
;
2600 #endif /* CIFS_EXPERIMENTAL */
2603 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2604 const unsigned char *searchName
,
2605 char *symlinkinfo
, const int buflen
, __u16 fid
,
2606 const struct nls_table
*nls_codepage
)
2611 struct smb_com_transaction_ioctl_req
*pSMB
;
2612 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2614 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2615 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2620 pSMB
->TotalParameterCount
= 0 ;
2621 pSMB
->TotalDataCount
= 0;
2622 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2623 /* BB find exact data count max from sess structure BB */
2624 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2625 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2626 pSMB
->MaxSetupCount
= 4;
2628 pSMB
->ParameterOffset
= 0;
2629 pSMB
->DataCount
= 0;
2630 pSMB
->DataOffset
= 0;
2631 pSMB
->SetupCount
= 4;
2632 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2633 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2634 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2635 pSMB
->IsFsctl
= 1; /* FSCTL */
2636 pSMB
->IsRootFlag
= 0;
2637 pSMB
->Fid
= fid
; /* file handle always le */
2638 pSMB
->ByteCount
= 0;
2640 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2641 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2643 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2644 } else { /* decode response */
2645 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2646 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2647 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2648 /* BB also check enough total bytes returned */
2649 rc
= -EIO
; /* bad smb */
2651 if (data_count
&& (data_count
< 2048)) {
2652 char *end_of_smb
= 2 /* sizeof byte count */ +
2654 (char *)&pSMBr
->ByteCount
;
2656 struct reparse_data
*reparse_buf
=
2657 (struct reparse_data
*)
2658 ((char *)&pSMBr
->hdr
.Protocol
2660 if ((char *)reparse_buf
>= end_of_smb
) {
2664 if ((reparse_buf
->LinkNamesBuf
+
2665 reparse_buf
->TargetNameOffset
+
2666 reparse_buf
->TargetNameLen
) >
2668 cFYI(1, ("reparse buf beyond SMB"));
2673 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2674 name_len
= UniStrnlen((wchar_t *)
2675 (reparse_buf
->LinkNamesBuf
+
2676 reparse_buf
->TargetNameOffset
),
2678 reparse_buf
->TargetNameLen
/ 2));
2679 cifs_strfromUCS_le(symlinkinfo
,
2680 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2681 reparse_buf
->TargetNameOffset
),
2682 name_len
, nls_codepage
);
2683 } else { /* ASCII names */
2684 strncpy(symlinkinfo
,
2685 reparse_buf
->LinkNamesBuf
+
2686 reparse_buf
->TargetNameOffset
,
2687 min_t(const int, buflen
,
2688 reparse_buf
->TargetNameLen
));
2692 cFYI(1, ("Invalid return data count on "
2693 "get reparse info ioctl"));
2695 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2696 does not go off the end of the buffer */
2697 cFYI(1, ("readlink result - %s", symlinkinfo
));
2701 cifs_buf_release(pSMB
);
2703 /* Note: On -EAGAIN error only caller can retry on handle based calls
2704 since file handle passed in no longer valid */
2709 #ifdef CONFIG_CIFS_POSIX
2711 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2712 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2713 struct cifs_posix_ace
*cifs_ace
)
2715 /* u8 cifs fields do not need le conversion */
2716 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2717 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2718 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2719 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2724 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2725 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2726 const int acl_type
, const int size_of_data_area
)
2731 struct cifs_posix_ace
*pACE
;
2732 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2733 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2735 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2738 if (acl_type
& ACL_TYPE_ACCESS
) {
2739 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2740 pACE
= &cifs_acl
->ace_array
[0];
2741 size
= sizeof(struct cifs_posix_acl
);
2742 size
+= sizeof(struct cifs_posix_ace
) * count
;
2743 /* check if we would go beyond end of SMB */
2744 if (size_of_data_area
< size
) {
2745 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2746 size_of_data_area
, size
));
2749 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2750 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2751 size
= sizeof(struct cifs_posix_acl
);
2752 size
+= sizeof(struct cifs_posix_ace
) * count
;
2753 /* skip past access ACEs to get to default ACEs */
2754 pACE
= &cifs_acl
->ace_array
[count
];
2755 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2756 size
+= sizeof(struct cifs_posix_ace
) * count
;
2757 /* check if we would go beyond end of SMB */
2758 if (size_of_data_area
< size
)
2765 size
= posix_acl_xattr_size(count
);
2766 if ((buflen
== 0) || (local_acl
== NULL
)) {
2767 /* used to query ACL EA size */
2768 } else if (size
> buflen
) {
2770 } else /* buffer big enough */ {
2771 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2772 for (i
= 0; i
< count
; i
++) {
2773 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2780 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2781 const posix_acl_xattr_entry
*local_ace
)
2783 __u16 rc
= 0; /* 0 = ACL converted ok */
2785 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2786 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2787 /* BB is there a better way to handle the large uid? */
2788 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2789 /* Probably no need to le convert -1 on any arch but can not hurt */
2790 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2792 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2793 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2797 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2798 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2799 const int buflen
, const int acl_type
)
2802 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2803 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2807 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2810 count
= posix_acl_xattr_count((size_t)buflen
);
2811 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2813 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2814 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2815 cFYI(1, ("unknown POSIX ACL version %d",
2816 le32_to_cpu(local_acl
->a_version
)));
2819 cifs_acl
->version
= cpu_to_le16(1);
2820 if (acl_type
== ACL_TYPE_ACCESS
)
2821 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2822 else if (acl_type
== ACL_TYPE_DEFAULT
)
2823 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2825 cFYI(1, ("unknown ACL type %d", acl_type
));
2828 for (i
= 0; i
< count
; i
++) {
2829 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2830 &local_acl
->a_entries
[i
]);
2832 /* ACE not converted */
2837 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2838 rc
+= sizeof(struct cifs_posix_acl
);
2839 /* BB add check to make sure ACL does not overflow SMB */
2845 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2846 const unsigned char *searchName
,
2847 char *acl_inf
, const int buflen
, const int acl_type
,
2848 const struct nls_table
*nls_codepage
, int remap
)
2850 /* SMB_QUERY_POSIX_ACL */
2851 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2852 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2856 __u16 params
, byte_count
;
2858 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2861 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2866 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2868 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2869 PATH_MAX
, nls_codepage
, remap
);
2870 name_len
++; /* trailing null */
2872 pSMB
->FileName
[name_len
] = 0;
2873 pSMB
->FileName
[name_len
+1] = 0;
2874 } else { /* BB improve the check for buffer overruns BB */
2875 name_len
= strnlen(searchName
, PATH_MAX
);
2876 name_len
++; /* trailing null */
2877 strncpy(pSMB
->FileName
, searchName
, name_len
);
2880 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2881 pSMB
->TotalDataCount
= 0;
2882 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2883 /* BB find exact max data count below from sess structure BB */
2884 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2885 pSMB
->MaxSetupCount
= 0;
2889 pSMB
->Reserved2
= 0;
2890 pSMB
->ParameterOffset
= cpu_to_le16(
2891 offsetof(struct smb_com_transaction2_qpi_req
,
2892 InformationLevel
) - 4);
2893 pSMB
->DataCount
= 0;
2894 pSMB
->DataOffset
= 0;
2895 pSMB
->SetupCount
= 1;
2896 pSMB
->Reserved3
= 0;
2897 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2898 byte_count
= params
+ 1 /* pad */ ;
2899 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2900 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2901 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2902 pSMB
->Reserved4
= 0;
2903 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2904 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2906 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2907 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2908 cifs_stats_inc(&tcon
->num_acl_get
);
2910 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2912 /* decode response */
2914 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2915 if (rc
|| (pSMBr
->ByteCount
< 2))
2916 /* BB also check enough total bytes returned */
2917 rc
= -EIO
; /* bad smb */
2919 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2920 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2921 rc
= cifs_copy_posix_acl(acl_inf
,
2922 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2923 buflen
, acl_type
, count
);
2926 cifs_buf_release(pSMB
);
2933 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2934 const unsigned char *fileName
,
2935 const char *local_acl
, const int buflen
,
2937 const struct nls_table
*nls_codepage
, int remap
)
2939 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2940 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2944 int bytes_returned
= 0;
2945 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2947 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2949 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2953 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2955 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2956 PATH_MAX
, nls_codepage
, remap
);
2957 name_len
++; /* trailing null */
2959 } else { /* BB improve the check for buffer overruns BB */
2960 name_len
= strnlen(fileName
, PATH_MAX
);
2961 name_len
++; /* trailing null */
2962 strncpy(pSMB
->FileName
, fileName
, name_len
);
2964 params
= 6 + name_len
;
2965 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2966 /* BB find max SMB size from sess */
2967 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2968 pSMB
->MaxSetupCount
= 0;
2972 pSMB
->Reserved2
= 0;
2973 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2974 InformationLevel
) - 4;
2975 offset
= param_offset
+ params
;
2976 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2977 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2979 /* convert to on the wire format for POSIX ACL */
2980 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2982 if (data_count
== 0) {
2984 goto setACLerrorExit
;
2986 pSMB
->DataOffset
= cpu_to_le16(offset
);
2987 pSMB
->SetupCount
= 1;
2988 pSMB
->Reserved3
= 0;
2989 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2990 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2991 byte_count
= 3 /* pad */ + params
+ data_count
;
2992 pSMB
->DataCount
= cpu_to_le16(data_count
);
2993 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2994 pSMB
->ParameterCount
= cpu_to_le16(params
);
2995 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2996 pSMB
->Reserved4
= 0;
2997 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2998 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2999 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3000 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3002 cFYI(1, ("Set POSIX ACL returned %d", rc
));
3005 cifs_buf_release(pSMB
);
3011 /* BB fix tabs in this function FIXME BB */
3013 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
3014 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
3017 struct smb_t2_qfi_req
*pSMB
= NULL
;
3018 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3020 __u16 params
, byte_count
;
3022 cFYI(1, ("In GetExtAttr"));
3027 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3032 params
= 2 /* level */ + 2 /* fid */;
3033 pSMB
->t2
.TotalDataCount
= 0;
3034 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3035 /* BB find exact max data count below from sess structure BB */
3036 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3037 pSMB
->t2
.MaxSetupCount
= 0;
3038 pSMB
->t2
.Reserved
= 0;
3040 pSMB
->t2
.Timeout
= 0;
3041 pSMB
->t2
.Reserved2
= 0;
3042 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3044 pSMB
->t2
.DataCount
= 0;
3045 pSMB
->t2
.DataOffset
= 0;
3046 pSMB
->t2
.SetupCount
= 1;
3047 pSMB
->t2
.Reserved3
= 0;
3048 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3049 byte_count
= params
+ 1 /* pad */ ;
3050 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3051 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3052 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3055 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3056 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3058 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3059 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3061 cFYI(1, ("error %d in GetExtAttr", rc
));
3063 /* decode response */
3064 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3065 if (rc
|| (pSMBr
->ByteCount
< 2))
3066 /* BB also check enough total bytes returned */
3067 /* If rc should we check for EOPNOSUPP and
3068 disable the srvino flag? or in caller? */
3069 rc
= -EIO
; /* bad smb */
3071 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3072 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3073 struct file_chattr_info
*pfinfo
;
3074 /* BB Do we need a cast or hash here ? */
3076 cFYI(1, ("Illegal size ret in GetExtAttr"));
3080 pfinfo
= (struct file_chattr_info
*)
3081 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3082 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3083 *pMask
= le64_to_cpu(pfinfo
->mask
);
3087 cifs_buf_release(pSMB
);
3089 goto GetExtAttrRetry
;
3093 #endif /* CONFIG_POSIX */
3095 #ifdef CONFIG_CIFS_EXPERIMENTAL
3096 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3098 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3099 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3103 QUERY_SEC_DESC_REQ
*pSMB
;
3106 cFYI(1, ("GetCifsACL"));
3111 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3112 8 /* parm len */, tcon
, (void **) &pSMB
);
3116 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3117 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3118 pSMB
->MaxSetupCount
= 0;
3119 pSMB
->Fid
= fid
; /* file handle always le */
3120 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3122 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3123 pSMB
->hdr
.smb_buf_length
+= 11;
3124 iov
[0].iov_base
= (char *)pSMB
;
3125 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3127 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3129 cifs_stats_inc(&tcon
->num_acl_get
);
3131 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3132 } else { /* decode response */
3136 struct smb_com_ntransact_rsp
*pSMBr
;
3139 /* validate_nttransact */
3140 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3141 &pdata
, &parm_len
, pbuflen
);
3144 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3146 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3148 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3149 rc
= -EIO
; /* bad smb */
3154 /* BB check that data area is minimum length and as big as acl_len */
3156 acl_len
= le32_to_cpu(*parm
);
3157 if (acl_len
!= *pbuflen
) {
3158 cERROR(1, ("acl length %d does not match %d",
3159 acl_len
, *pbuflen
));
3160 if (*pbuflen
> acl_len
)
3164 /* check if buffer is big enough for the acl
3165 header followed by the smallest SID */
3166 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3167 (*pbuflen
>= 64 * 1024)) {
3168 cERROR(1, ("bad acl length %d", *pbuflen
));
3172 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3173 if (*acl_inf
== NULL
) {
3177 memcpy(*acl_inf
, pdata
, *pbuflen
);
3181 if (buf_type
== CIFS_SMALL_BUFFER
)
3182 cifs_small_buf_release(iov
[0].iov_base
);
3183 else if (buf_type
== CIFS_LARGE_BUFFER
)
3184 cifs_buf_release(iov
[0].iov_base
);
3185 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3190 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3191 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3193 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3195 int bytes_returned
= 0;
3196 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3197 NTRANSACT_RSP
*pSMBr
= NULL
;
3200 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3205 pSMB
->MaxSetupCount
= 0;
3209 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3210 data_count
= acllen
;
3211 data_offset
= param_offset
+ param_count
;
3212 byte_count
= 3 /* pad */ + param_count
;
3214 pSMB
->DataCount
= cpu_to_le32(data_count
);
3215 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3216 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3217 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3218 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3219 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3220 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3221 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3222 pSMB
->SetupCount
= 0;
3223 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3224 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3226 pSMB
->Fid
= fid
; /* file handle always le */
3227 pSMB
->Reserved2
= 0;
3228 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3230 if (pntsd
&& acllen
) {
3231 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3234 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3237 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3239 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3240 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3242 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3244 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3245 cifs_buf_release(pSMB
);
3248 goto setCifsAclRetry
;
3253 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3255 /* Legacy Query Path Information call for lookup to old servers such
3257 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3258 const unsigned char *searchName
,
3259 FILE_ALL_INFO
*pFinfo
,
3260 const struct nls_table
*nls_codepage
, int remap
)
3262 QUERY_INFORMATION_REQ
*pSMB
;
3263 QUERY_INFORMATION_RSP
*pSMBr
;
3268 cFYI(1, ("In SMBQPath path %s", searchName
));
3270 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3275 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3277 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3278 PATH_MAX
, nls_codepage
, remap
);
3279 name_len
++; /* trailing null */
3282 name_len
= strnlen(searchName
, PATH_MAX
);
3283 name_len
++; /* trailing null */
3284 strncpy(pSMB
->FileName
, searchName
, name_len
);
3286 pSMB
->BufferFormat
= 0x04;
3287 name_len
++; /* account for buffer type byte */
3288 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3289 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3291 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3292 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3294 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3295 } else if (pFinfo
) {
3297 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3299 /* decode response */
3300 /* BB FIXME - add time zone adjustment BB */
3301 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3304 /* decode time fields */
3305 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3306 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3307 pFinfo
->LastAccessTime
= 0;
3308 pFinfo
->AllocationSize
=
3309 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3310 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3311 pFinfo
->Attributes
=
3312 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3314 rc
= -EIO
; /* bad buffer passed in */
3316 cifs_buf_release(pSMB
);
3328 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3329 const unsigned char *searchName
,
3330 FILE_ALL_INFO
*pFindData
,
3331 int legacy
/* old style infolevel */,
3332 const struct nls_table
*nls_codepage
, int remap
)
3334 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3335 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3336 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3340 __u16 params
, byte_count
;
3342 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3344 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3349 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3351 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3352 PATH_MAX
, nls_codepage
, remap
);
3353 name_len
++; /* trailing null */
3355 } else { /* BB improve the check for buffer overruns BB */
3356 name_len
= strnlen(searchName
, PATH_MAX
);
3357 name_len
++; /* trailing null */
3358 strncpy(pSMB
->FileName
, searchName
, name_len
);
3361 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3362 pSMB
->TotalDataCount
= 0;
3363 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3364 /* BB find exact max SMB PDU from sess structure BB */
3365 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3366 pSMB
->MaxSetupCount
= 0;
3370 pSMB
->Reserved2
= 0;
3371 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3372 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3373 pSMB
->DataCount
= 0;
3374 pSMB
->DataOffset
= 0;
3375 pSMB
->SetupCount
= 1;
3376 pSMB
->Reserved3
= 0;
3377 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3378 byte_count
= params
+ 1 /* pad */ ;
3379 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3380 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3382 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3384 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3385 pSMB
->Reserved4
= 0;
3386 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3387 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3389 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3390 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3392 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3393 } else { /* decode response */
3394 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3396 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3398 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3399 rc
= -EIO
; /* bad smb */
3400 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3401 rc
= -EIO
; /* 24 or 26 expected but we do not read
3403 else if (pFindData
) {
3405 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3407 /* On legacy responses we do not read the last field,
3408 EAsize, fortunately since it varies by subdialect and
3409 also note it differs on Set vs. Get, ie two bytes or 4
3410 bytes depending but we don't care here */
3412 size
= sizeof(FILE_INFO_STANDARD
);
3414 size
= sizeof(FILE_ALL_INFO
);
3415 memcpy((char *) pFindData
,
3416 (char *) &pSMBr
->hdr
.Protocol
+
3421 cifs_buf_release(pSMB
);
3423 goto QPathInfoRetry
;
3429 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3430 const unsigned char *searchName
,
3431 FILE_UNIX_BASIC_INFO
*pFindData
,
3432 const struct nls_table
*nls_codepage
, int remap
)
3434 /* SMB_QUERY_FILE_UNIX_BASIC */
3435 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3436 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3438 int bytes_returned
= 0;
3440 __u16 params
, byte_count
;
3442 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3444 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3449 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3451 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3452 PATH_MAX
, nls_codepage
, remap
);
3453 name_len
++; /* trailing null */
3455 } else { /* BB improve the check for buffer overruns BB */
3456 name_len
= strnlen(searchName
, PATH_MAX
);
3457 name_len
++; /* trailing null */
3458 strncpy(pSMB
->FileName
, searchName
, name_len
);
3461 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3462 pSMB
->TotalDataCount
= 0;
3463 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3464 /* BB find exact max SMB PDU from sess structure BB */
3465 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3466 pSMB
->MaxSetupCount
= 0;
3470 pSMB
->Reserved2
= 0;
3471 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3472 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3473 pSMB
->DataCount
= 0;
3474 pSMB
->DataOffset
= 0;
3475 pSMB
->SetupCount
= 1;
3476 pSMB
->Reserved3
= 0;
3477 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3478 byte_count
= params
+ 1 /* pad */ ;
3479 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3480 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3481 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3482 pSMB
->Reserved4
= 0;
3483 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3484 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3486 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3487 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3489 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3490 } else { /* decode response */
3491 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3493 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3494 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3495 "Unix Extensions can be disabled on mount "
3496 "by specifying the nosfu mount option."));
3497 rc
= -EIO
; /* bad smb */
3499 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3500 memcpy((char *) pFindData
,
3501 (char *) &pSMBr
->hdr
.Protocol
+
3503 sizeof(FILE_UNIX_BASIC_INFO
));
3506 cifs_buf_release(pSMB
);
3508 goto UnixQPathInfoRetry
;
3513 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3515 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3516 const char *searchName
,
3517 const struct nls_table
*nls_codepage
,
3519 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3521 /* level 257 SMB_ */
3522 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3523 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3524 T2_FFIRST_RSP_PARMS
*parms
;
3526 int bytes_returned
= 0;
3528 __u16 params
, byte_count
;
3530 cFYI(1, ("In FindFirst for %s", searchName
));
3533 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3538 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3540 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3541 PATH_MAX
, nls_codepage
, remap
);
3542 /* We can not add the asterik earlier in case
3543 it got remapped to 0xF03A as if it were part of the
3544 directory name instead of a wildcard */
3546 pSMB
->FileName
[name_len
] = dirsep
;
3547 pSMB
->FileName
[name_len
+1] = 0;
3548 pSMB
->FileName
[name_len
+2] = '*';
3549 pSMB
->FileName
[name_len
+3] = 0;
3550 name_len
+= 4; /* now the trailing null */
3551 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3552 pSMB
->FileName
[name_len
+1] = 0;
3554 } else { /* BB add check for overrun of SMB buf BB */
3555 name_len
= strnlen(searchName
, PATH_MAX
);
3556 /* BB fix here and in unicode clause above ie
3557 if (name_len > buffersize-header)
3558 free buffer exit; BB */
3559 strncpy(pSMB
->FileName
, searchName
, name_len
);
3560 pSMB
->FileName
[name_len
] = dirsep
;
3561 pSMB
->FileName
[name_len
+1] = '*';
3562 pSMB
->FileName
[name_len
+2] = 0;
3566 params
= 12 + name_len
/* includes null */ ;
3567 pSMB
->TotalDataCount
= 0; /* no EAs */
3568 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3569 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3570 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3571 pSMB
->MaxSetupCount
= 0;
3575 pSMB
->Reserved2
= 0;
3576 byte_count
= params
+ 1 /* pad */ ;
3577 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3578 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3579 pSMB
->ParameterOffset
= cpu_to_le16(
3580 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3582 pSMB
->DataCount
= 0;
3583 pSMB
->DataOffset
= 0;
3584 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3585 pSMB
->Reserved3
= 0;
3586 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3587 pSMB
->SearchAttributes
=
3588 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3590 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3591 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3592 CIFS_SEARCH_RETURN_RESUME
);
3593 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3595 /* BB what should we set StorageType to? Does it matter? BB */
3596 pSMB
->SearchStorageType
= 0;
3597 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3598 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3600 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3601 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3602 cifs_stats_inc(&tcon
->num_ffirst
);
3604 if (rc
) {/* BB add logic to retry regular search if Unix search
3605 rejected unexpectedly by server */
3606 /* BB Add code to handle unsupported level rc */
3607 cFYI(1, ("Error in FindFirst = %d", rc
));
3609 cifs_buf_release(pSMB
);
3611 /* BB eventually could optimize out free and realloc of buf */
3614 goto findFirstRetry
;
3615 } else { /* decode response */
3616 /* BB remember to free buffer if error BB */
3617 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3621 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3622 psrch_inf
->unicode
= true;
3624 psrch_inf
->unicode
= false;
3626 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3627 psrch_inf
->smallBuf
= 0;
3628 psrch_inf
->srch_entries_start
=
3629 (char *) &pSMBr
->hdr
.Protocol
+
3630 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3631 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3632 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3634 if (parms
->EndofSearch
)
3635 psrch_inf
->endOfSearch
= true;
3637 psrch_inf
->endOfSearch
= false;
3639 psrch_inf
->entries_in_buffer
=
3640 le16_to_cpu(parms
->SearchCount
);
3641 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3642 psrch_inf
->entries_in_buffer
;
3643 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3644 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3646 cERROR(1, ("ignoring corrupt resume name"));
3647 psrch_inf
->last_entry
= NULL
;
3651 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3654 *pnetfid
= parms
->SearchHandle
;
3656 cifs_buf_release(pSMB
);
3663 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3664 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3666 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3667 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3668 T2_FNEXT_RSP_PARMS
*parms
;
3669 char *response_data
;
3671 int bytes_returned
, name_len
;
3672 __u16 params
, byte_count
;
3674 cFYI(1, ("In FindNext"));
3676 if (psrch_inf
->endOfSearch
)
3679 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3684 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3686 pSMB
->TotalDataCount
= 0; /* no EAs */
3687 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3688 pSMB
->MaxDataCount
=
3689 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3691 pSMB
->MaxSetupCount
= 0;
3695 pSMB
->Reserved2
= 0;
3696 pSMB
->ParameterOffset
= cpu_to_le16(
3697 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3698 pSMB
->DataCount
= 0;
3699 pSMB
->DataOffset
= 0;
3700 pSMB
->SetupCount
= 1;
3701 pSMB
->Reserved3
= 0;
3702 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3703 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3705 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3706 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3707 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3709 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3711 name_len
= psrch_inf
->resume_name_len
;
3713 if (name_len
< PATH_MAX
) {
3714 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3715 byte_count
+= name_len
;
3716 /* 14 byte parm len above enough for 2 byte null terminator */
3717 pSMB
->ResumeFileName
[name_len
] = 0;
3718 pSMB
->ResumeFileName
[name_len
+1] = 0;
3721 goto FNext2_err_exit
;
3723 byte_count
= params
+ 1 /* pad */ ;
3724 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3725 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3726 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3727 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3729 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3730 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3731 cifs_stats_inc(&tcon
->num_fnext
);
3734 psrch_inf
->endOfSearch
= true;
3735 cifs_buf_release(pSMB
);
3736 rc
= 0; /* search probably was closed at end of search*/
3738 cFYI(1, ("FindNext returned = %d", rc
));
3739 } else { /* decode response */
3740 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3745 /* BB fixme add lock for file (srch_info) struct here */
3746 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3747 psrch_inf
->unicode
= true;
3749 psrch_inf
->unicode
= false;
3750 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3751 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3752 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3753 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3754 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3755 if (psrch_inf
->smallBuf
)
3756 cifs_small_buf_release(
3757 psrch_inf
->ntwrk_buf_start
);
3759 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3760 psrch_inf
->srch_entries_start
= response_data
;
3761 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3762 psrch_inf
->smallBuf
= 0;
3763 if (parms
->EndofSearch
)
3764 psrch_inf
->endOfSearch
= true;
3766 psrch_inf
->endOfSearch
= false;
3767 psrch_inf
->entries_in_buffer
=
3768 le16_to_cpu(parms
->SearchCount
);
3769 psrch_inf
->index_of_last_entry
+=
3770 psrch_inf
->entries_in_buffer
;
3771 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3772 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3774 cERROR(1, ("ignoring corrupt resume name"));
3775 psrch_inf
->last_entry
= NULL
;
3778 psrch_inf
->last_entry
=
3779 psrch_inf
->srch_entries_start
+ lnoff
;
3781 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3782 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3784 /* BB fixme add unlock here */
3789 /* BB On error, should we leave previous search buf (and count and
3790 last entry fields) intact or free the previous one? */
3792 /* Note: On -EAGAIN error only caller can retry on handle based calls
3793 since file handle passed in no longer valid */
3796 cifs_buf_release(pSMB
);
3801 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3802 const __u16 searchHandle
)
3805 FINDCLOSE_REQ
*pSMB
= NULL
;
3807 cFYI(1, ("In CIFSSMBFindClose"));
3808 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3810 /* no sense returning error if session restarted
3811 as file handle has been closed */
3817 pSMB
->FileID
= searchHandle
;
3818 pSMB
->ByteCount
= 0;
3819 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3821 cERROR(1, ("Send error in FindClose = %d", rc
));
3823 cifs_stats_inc(&tcon
->num_fclose
);
3825 /* Since session is dead, search handle closed on server already */
3833 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3834 const unsigned char *searchName
,
3835 __u64
*inode_number
,
3836 const struct nls_table
*nls_codepage
, int remap
)
3839 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3840 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3841 int name_len
, bytes_returned
;
3842 __u16 params
, byte_count
;
3844 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3848 GetInodeNumberRetry
:
3849 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3854 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3856 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3857 PATH_MAX
, nls_codepage
, remap
);
3858 name_len
++; /* trailing null */
3860 } else { /* BB improve the check for buffer overruns BB */
3861 name_len
= strnlen(searchName
, PATH_MAX
);
3862 name_len
++; /* trailing null */
3863 strncpy(pSMB
->FileName
, searchName
, name_len
);
3866 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3867 pSMB
->TotalDataCount
= 0;
3868 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3869 /* BB find exact max data count below from sess structure BB */
3870 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3871 pSMB
->MaxSetupCount
= 0;
3875 pSMB
->Reserved2
= 0;
3876 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3877 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3878 pSMB
->DataCount
= 0;
3879 pSMB
->DataOffset
= 0;
3880 pSMB
->SetupCount
= 1;
3881 pSMB
->Reserved3
= 0;
3882 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3883 byte_count
= params
+ 1 /* pad */ ;
3884 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3885 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3886 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3887 pSMB
->Reserved4
= 0;
3888 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3889 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3891 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3892 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3894 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3896 /* decode response */
3897 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3898 if (rc
|| (pSMBr
->ByteCount
< 2))
3899 /* BB also check enough total bytes returned */
3900 /* If rc should we check for EOPNOSUPP and
3901 disable the srvino flag? or in caller? */
3902 rc
= -EIO
; /* bad smb */
3904 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3905 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3906 struct file_internal_info
*pfinfo
;
3907 /* BB Do we need a cast or hash here ? */
3909 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3911 goto GetInodeNumOut
;
3913 pfinfo
= (struct file_internal_info
*)
3914 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3915 *inode_number
= pfinfo
->UniqueId
;
3919 cifs_buf_release(pSMB
);
3921 goto GetInodeNumberRetry
;
3925 /* parses DFS refferal V3 structure
3926 * caller is responsible for freeing target_nodes
3929 * on failure - errno
3932 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
3933 unsigned int *num_of_nodes
,
3934 struct dfs_info3_param
**target_nodes
,
3935 const struct nls_table
*nls_codepage
)
3940 struct dfs_referral_level_3
*ref
;
3942 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3946 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3948 if (*num_of_nodes
< 1) {
3949 cERROR(1, ("num_referrals: must be at least > 0,"
3950 "but we get num_referrals = %d\n", *num_of_nodes
));
3952 goto parse_DFS_referrals_exit
;
3955 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
3956 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
3957 cERROR(1, ("Referrals of V%d version are not supported,"
3958 "should be V3", le16_to_cpu(ref
->VersionNumber
)));
3960 goto parse_DFS_referrals_exit
;
3963 /* get the upper boundary of the resp buffer */
3964 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
3965 le16_to_cpu(pSMBr
->t2
.DataCount
);
3967 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3969 le16_to_cpu(pSMBr
->DFSFlags
)));
3971 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
3972 *num_of_nodes
, GFP_KERNEL
);
3973 if (*target_nodes
== NULL
) {
3974 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3976 goto parse_DFS_referrals_exit
;
3979 /* collect neccessary data from referrals */
3980 for (i
= 0; i
< *num_of_nodes
; i
++) {
3983 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
3985 node
->flags
= le16_to_cpu(pSMBr
->DFSFlags
);
3986 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
3987 node
->server_type
= le16_to_cpu(ref
->ServerType
);
3988 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
3991 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
3992 max_len
= data_end
- temp
;
3993 rc
= cifs_strncpy_to_host(&(node
->path_name
), temp
,
3994 max_len
, is_unicode
, nls_codepage
);
3996 goto parse_DFS_referrals_exit
;
3998 /* copy link target UNC */
3999 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4000 max_len
= data_end
- temp
;
4001 rc
= cifs_strncpy_to_host(&(node
->node_name
), temp
,
4002 max_len
, is_unicode
, nls_codepage
);
4004 goto parse_DFS_referrals_exit
;
4006 ref
+= le16_to_cpu(ref
->Size
);
4009 parse_DFS_referrals_exit
:
4011 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4012 *target_nodes
= NULL
;
4019 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4020 const unsigned char *searchName
,
4021 struct dfs_info3_param
**target_nodes
,
4022 unsigned int *num_of_nodes
,
4023 const struct nls_table
*nls_codepage
, int remap
)
4025 /* TRANS2_GET_DFS_REFERRAL */
4026 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4027 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4031 __u16 params
, byte_count
;
4033 *target_nodes
= NULL
;
4035 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
4039 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4044 /* server pointer checked in called function,
4045 but should never be null here anyway */
4046 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4047 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4048 pSMB
->hdr
.Uid
= ses
->Suid
;
4049 if (ses
->capabilities
& CAP_STATUS32
)
4050 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4051 if (ses
->capabilities
& CAP_DFS
)
4052 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4054 if (ses
->capabilities
& CAP_UNICODE
) {
4055 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4057 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4058 searchName
, PATH_MAX
, nls_codepage
, remap
);
4059 name_len
++; /* trailing null */
4061 } else { /* BB improve the check for buffer overruns BB */
4062 name_len
= strnlen(searchName
, PATH_MAX
);
4063 name_len
++; /* trailing null */
4064 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4068 if (ses
->server
->secMode
&
4069 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4070 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4073 pSMB
->hdr
.Uid
= ses
->Suid
;
4075 params
= 2 /* level */ + name_len
/*includes null */ ;
4076 pSMB
->TotalDataCount
= 0;
4077 pSMB
->DataCount
= 0;
4078 pSMB
->DataOffset
= 0;
4079 pSMB
->MaxParameterCount
= 0;
4080 /* BB find exact max SMB PDU from sess structure BB */
4081 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4082 pSMB
->MaxSetupCount
= 0;
4086 pSMB
->Reserved2
= 0;
4087 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4088 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4089 pSMB
->SetupCount
= 1;
4090 pSMB
->Reserved3
= 0;
4091 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4092 byte_count
= params
+ 3 /* pad */ ;
4093 pSMB
->ParameterCount
= cpu_to_le16(params
);
4094 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4095 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4096 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4097 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4099 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4100 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4102 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
4105 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4107 /* BB Also check if enough total bytes returned? */
4108 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4109 rc
= -EIO
; /* bad smb */
4113 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4115 le16_to_cpu(pSMBr
->t2
.DataOffset
)));
4117 /* parse returned result into more usable form */
4118 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4119 target_nodes
, nls_codepage
);
4122 cifs_buf_release(pSMB
);
4130 /* Query File System Info such as free space to old servers such as Win 9x */
4132 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4134 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4135 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4136 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4137 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4139 int bytes_returned
= 0;
4140 __u16 params
, byte_count
;
4142 cFYI(1, ("OldQFSInfo"));
4144 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4149 params
= 2; /* level */
4150 pSMB
->TotalDataCount
= 0;
4151 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4152 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4153 pSMB
->MaxSetupCount
= 0;
4157 pSMB
->Reserved2
= 0;
4158 byte_count
= params
+ 1 /* pad */ ;
4159 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4160 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4161 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4162 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4163 pSMB
->DataCount
= 0;
4164 pSMB
->DataOffset
= 0;
4165 pSMB
->SetupCount
= 1;
4166 pSMB
->Reserved3
= 0;
4167 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4168 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4169 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4170 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4172 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4173 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4175 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4176 } else { /* decode response */
4177 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4179 if (rc
|| (pSMBr
->ByteCount
< 18))
4180 rc
= -EIO
; /* bad smb */
4182 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4183 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4184 pSMBr
->ByteCount
, data_offset
));
4186 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4187 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4189 le16_to_cpu(response_data
->BytesPerSector
) *
4190 le32_to_cpu(response_data
->
4191 SectorsPerAllocationUnit
);
4193 le32_to_cpu(response_data
->TotalAllocationUnits
);
4194 FSData
->f_bfree
= FSData
->f_bavail
=
4195 le32_to_cpu(response_data
->FreeAllocationUnits
);
4197 ("Blocks: %lld Free: %lld Block size %ld",
4198 (unsigned long long)FSData
->f_blocks
,
4199 (unsigned long long)FSData
->f_bfree
,
4203 cifs_buf_release(pSMB
);
4206 goto oldQFSInfoRetry
;
4212 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4214 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4215 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4216 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4217 FILE_SYSTEM_INFO
*response_data
;
4219 int bytes_returned
= 0;
4220 __u16 params
, byte_count
;
4222 cFYI(1, ("In QFSInfo"));
4224 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4229 params
= 2; /* level */
4230 pSMB
->TotalDataCount
= 0;
4231 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4232 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4233 pSMB
->MaxSetupCount
= 0;
4237 pSMB
->Reserved2
= 0;
4238 byte_count
= params
+ 1 /* pad */ ;
4239 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4240 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4241 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4242 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4243 pSMB
->DataCount
= 0;
4244 pSMB
->DataOffset
= 0;
4245 pSMB
->SetupCount
= 1;
4246 pSMB
->Reserved3
= 0;
4247 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4248 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4249 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4250 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4252 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4253 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4255 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4256 } else { /* decode response */
4257 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4259 if (rc
|| (pSMBr
->ByteCount
< 24))
4260 rc
= -EIO
; /* bad smb */
4262 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4266 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4269 le32_to_cpu(response_data
->BytesPerSector
) *
4270 le32_to_cpu(response_data
->
4271 SectorsPerAllocationUnit
);
4273 le64_to_cpu(response_data
->TotalAllocationUnits
);
4274 FSData
->f_bfree
= FSData
->f_bavail
=
4275 le64_to_cpu(response_data
->FreeAllocationUnits
);
4277 ("Blocks: %lld Free: %lld Block size %ld",
4278 (unsigned long long)FSData
->f_blocks
,
4279 (unsigned long long)FSData
->f_bfree
,
4283 cifs_buf_release(pSMB
);
4292 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4294 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4295 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4296 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4297 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4299 int bytes_returned
= 0;
4300 __u16 params
, byte_count
;
4302 cFYI(1, ("In QFSAttributeInfo"));
4304 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4309 params
= 2; /* level */
4310 pSMB
->TotalDataCount
= 0;
4311 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4312 /* BB find exact max SMB PDU from sess structure BB */
4313 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4314 pSMB
->MaxSetupCount
= 0;
4318 pSMB
->Reserved2
= 0;
4319 byte_count
= params
+ 1 /* pad */ ;
4320 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4321 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4322 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4323 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4324 pSMB
->DataCount
= 0;
4325 pSMB
->DataOffset
= 0;
4326 pSMB
->SetupCount
= 1;
4327 pSMB
->Reserved3
= 0;
4328 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4329 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4330 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4331 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4333 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4334 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4336 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4337 } else { /* decode response */
4338 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4340 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4341 /* BB also check if enough bytes returned */
4342 rc
= -EIO
; /* bad smb */
4344 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4346 (FILE_SYSTEM_ATTRIBUTE_INFO
4347 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4349 memcpy(&tcon
->fsAttrInfo
, response_data
,
4350 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4353 cifs_buf_release(pSMB
);
4356 goto QFSAttributeRetry
;
4362 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4364 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4365 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4366 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4367 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4369 int bytes_returned
= 0;
4370 __u16 params
, byte_count
;
4372 cFYI(1, ("In QFSDeviceInfo"));
4374 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4379 params
= 2; /* level */
4380 pSMB
->TotalDataCount
= 0;
4381 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4382 /* BB find exact max SMB PDU from sess structure BB */
4383 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4384 pSMB
->MaxSetupCount
= 0;
4388 pSMB
->Reserved2
= 0;
4389 byte_count
= params
+ 1 /* pad */ ;
4390 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4391 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4392 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4393 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4395 pSMB
->DataCount
= 0;
4396 pSMB
->DataOffset
= 0;
4397 pSMB
->SetupCount
= 1;
4398 pSMB
->Reserved3
= 0;
4399 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4400 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4401 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4402 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4404 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4405 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4407 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4408 } else { /* decode response */
4409 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4411 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4412 rc
= -EIO
; /* bad smb */
4414 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4416 (FILE_SYSTEM_DEVICE_INFO
*)
4417 (((char *) &pSMBr
->hdr
.Protocol
) +
4419 memcpy(&tcon
->fsDevInfo
, response_data
,
4420 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4423 cifs_buf_release(pSMB
);
4426 goto QFSDeviceRetry
;
4432 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4434 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4435 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4436 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4437 FILE_SYSTEM_UNIX_INFO
*response_data
;
4439 int bytes_returned
= 0;
4440 __u16 params
, byte_count
;
4442 cFYI(1, ("In QFSUnixInfo"));
4444 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4449 params
= 2; /* level */
4450 pSMB
->TotalDataCount
= 0;
4451 pSMB
->DataCount
= 0;
4452 pSMB
->DataOffset
= 0;
4453 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4454 /* BB find exact max SMB PDU from sess structure BB */
4455 pSMB
->MaxDataCount
= cpu_to_le16(100);
4456 pSMB
->MaxSetupCount
= 0;
4460 pSMB
->Reserved2
= 0;
4461 byte_count
= params
+ 1 /* pad */ ;
4462 pSMB
->ParameterCount
= cpu_to_le16(params
);
4463 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4464 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4465 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4466 pSMB
->SetupCount
= 1;
4467 pSMB
->Reserved3
= 0;
4468 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4469 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4470 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4471 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4473 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4474 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4476 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4477 } else { /* decode response */
4478 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4480 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4481 rc
= -EIO
; /* bad smb */
4483 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4485 (FILE_SYSTEM_UNIX_INFO
4486 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4488 memcpy(&tcon
->fsUnixInfo
, response_data
,
4489 sizeof(FILE_SYSTEM_UNIX_INFO
));
4492 cifs_buf_release(pSMB
);
4502 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4504 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4505 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4506 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4508 int bytes_returned
= 0;
4509 __u16 params
, param_offset
, offset
, byte_count
;
4511 cFYI(1, ("In SETFSUnixInfo"));
4513 /* BB switch to small buf init to save memory */
4514 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4519 params
= 4; /* 2 bytes zero followed by info level. */
4520 pSMB
->MaxSetupCount
= 0;
4524 pSMB
->Reserved2
= 0;
4525 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4527 offset
= param_offset
+ params
;
4529 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4530 /* BB find exact max SMB PDU from sess structure BB */
4531 pSMB
->MaxDataCount
= cpu_to_le16(100);
4532 pSMB
->SetupCount
= 1;
4533 pSMB
->Reserved3
= 0;
4534 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4535 byte_count
= 1 /* pad */ + params
+ 12;
4537 pSMB
->DataCount
= cpu_to_le16(12);
4538 pSMB
->ParameterCount
= cpu_to_le16(params
);
4539 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4540 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4541 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4542 pSMB
->DataOffset
= cpu_to_le16(offset
);
4546 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4549 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4550 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4551 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4553 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4554 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4556 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4557 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4559 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4560 } else { /* decode response */
4561 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4563 rc
= -EIO
; /* bad smb */
4565 cifs_buf_release(pSMB
);
4568 goto SETFSUnixRetry
;
4576 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4577 struct kstatfs
*FSData
)
4579 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4580 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4581 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4582 FILE_SYSTEM_POSIX_INFO
*response_data
;
4584 int bytes_returned
= 0;
4585 __u16 params
, byte_count
;
4587 cFYI(1, ("In QFSPosixInfo"));
4589 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4594 params
= 2; /* level */
4595 pSMB
->TotalDataCount
= 0;
4596 pSMB
->DataCount
= 0;
4597 pSMB
->DataOffset
= 0;
4598 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4599 /* BB find exact max SMB PDU from sess structure BB */
4600 pSMB
->MaxDataCount
= cpu_to_le16(100);
4601 pSMB
->MaxSetupCount
= 0;
4605 pSMB
->Reserved2
= 0;
4606 byte_count
= params
+ 1 /* pad */ ;
4607 pSMB
->ParameterCount
= cpu_to_le16(params
);
4608 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4609 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4610 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4611 pSMB
->SetupCount
= 1;
4612 pSMB
->Reserved3
= 0;
4613 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4614 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4615 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4616 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4618 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4619 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4621 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4622 } else { /* decode response */
4623 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4625 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4626 rc
= -EIO
; /* bad smb */
4628 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4630 (FILE_SYSTEM_POSIX_INFO
4631 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4634 le32_to_cpu(response_data
->BlockSize
);
4636 le64_to_cpu(response_data
->TotalBlocks
);
4638 le64_to_cpu(response_data
->BlocksAvail
);
4639 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4640 FSData
->f_bavail
= FSData
->f_bfree
;
4643 le64_to_cpu(response_data
->UserBlocksAvail
);
4645 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4647 le64_to_cpu(response_data
->TotalFileNodes
);
4648 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4650 le64_to_cpu(response_data
->FreeFileNodes
);
4653 cifs_buf_release(pSMB
);
4662 /* We can not use write of zero bytes trick to
4663 set file size due to need for large file support. Also note that
4664 this SetPathInfo is preferred to SetFileInfo based method in next
4665 routine which is only needed to work around a sharing violation bug
4666 in Samba which this routine can run into */
4669 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4670 __u64 size
, bool SetAllocation
,
4671 const struct nls_table
*nls_codepage
, int remap
)
4673 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4674 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4675 struct file_end_of_file_info
*parm_data
;
4678 int bytes_returned
= 0;
4679 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4681 cFYI(1, ("In SetEOF"));
4683 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4688 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4690 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4691 PATH_MAX
, nls_codepage
, remap
);
4692 name_len
++; /* trailing null */
4694 } else { /* BB improve the check for buffer overruns BB */
4695 name_len
= strnlen(fileName
, PATH_MAX
);
4696 name_len
++; /* trailing null */
4697 strncpy(pSMB
->FileName
, fileName
, name_len
);
4699 params
= 6 + name_len
;
4700 data_count
= sizeof(struct file_end_of_file_info
);
4701 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4702 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4703 pSMB
->MaxSetupCount
= 0;
4707 pSMB
->Reserved2
= 0;
4708 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4709 InformationLevel
) - 4;
4710 offset
= param_offset
+ params
;
4711 if (SetAllocation
) {
4712 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4713 pSMB
->InformationLevel
=
4714 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4716 pSMB
->InformationLevel
=
4717 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4718 } else /* Set File Size */ {
4719 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4720 pSMB
->InformationLevel
=
4721 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4723 pSMB
->InformationLevel
=
4724 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4728 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4730 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4731 pSMB
->DataOffset
= cpu_to_le16(offset
);
4732 pSMB
->SetupCount
= 1;
4733 pSMB
->Reserved3
= 0;
4734 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4735 byte_count
= 3 /* pad */ + params
+ data_count
;
4736 pSMB
->DataCount
= cpu_to_le16(data_count
);
4737 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4738 pSMB
->ParameterCount
= cpu_to_le16(params
);
4739 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4740 pSMB
->Reserved4
= 0;
4741 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4742 parm_data
->FileSize
= cpu_to_le64(size
);
4743 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4744 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4745 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4747 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4749 cifs_buf_release(pSMB
);
4758 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4759 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4761 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4763 struct file_end_of_file_info
*parm_data
;
4765 __u16 params
, param_offset
, offset
, byte_count
, count
;
4767 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4769 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4774 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4775 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4778 pSMB
->MaxSetupCount
= 0;
4782 pSMB
->Reserved2
= 0;
4783 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4784 offset
= param_offset
+ params
;
4786 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4788 count
= sizeof(struct file_end_of_file_info
);
4789 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4790 /* BB find exact max SMB PDU from sess structure BB */
4791 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4792 pSMB
->SetupCount
= 1;
4793 pSMB
->Reserved3
= 0;
4794 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4795 byte_count
= 3 /* pad */ + params
+ count
;
4796 pSMB
->DataCount
= cpu_to_le16(count
);
4797 pSMB
->ParameterCount
= cpu_to_le16(params
);
4798 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4799 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4800 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4802 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4804 pSMB
->DataOffset
= cpu_to_le16(offset
);
4805 parm_data
->FileSize
= cpu_to_le64(size
);
4807 if (SetAllocation
) {
4808 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4809 pSMB
->InformationLevel
=
4810 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4812 pSMB
->InformationLevel
=
4813 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4814 } else /* Set File Size */ {
4815 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4816 pSMB
->InformationLevel
=
4817 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4819 pSMB
->InformationLevel
=
4820 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4822 pSMB
->Reserved4
= 0;
4823 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4824 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4825 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4828 ("Send error in SetFileInfo (SetFileSize) = %d",
4832 /* Note: On -EAGAIN error only caller can retry on handle based calls
4833 since file handle passed in no longer valid */
4838 /* Some legacy servers such as NT4 require that the file times be set on
4839 an open handle, rather than by pathname - this is awkward due to
4840 potential access conflicts on the open, but it is unavoidable for these
4841 old servers since the only other choice is to go from 100 nanosecond DCE
4842 time and resort to the original setpathinfo level which takes the ancient
4843 DOS time format with 2 second granularity */
4845 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
4846 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
4848 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4851 __u16 params
, param_offset
, offset
, byte_count
, count
;
4853 cFYI(1, ("Set Times (via SetFileInfo)"));
4854 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4859 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4860 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4863 pSMB
->MaxSetupCount
= 0;
4867 pSMB
->Reserved2
= 0;
4868 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4869 offset
= param_offset
+ params
;
4871 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4873 count
= sizeof(FILE_BASIC_INFO
);
4874 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4875 /* BB find max SMB PDU from sess */
4876 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4877 pSMB
->SetupCount
= 1;
4878 pSMB
->Reserved3
= 0;
4879 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4880 byte_count
= 3 /* pad */ + params
+ count
;
4881 pSMB
->DataCount
= cpu_to_le16(count
);
4882 pSMB
->ParameterCount
= cpu_to_le16(params
);
4883 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4884 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4885 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4886 pSMB
->DataOffset
= cpu_to_le16(offset
);
4888 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4889 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4891 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4892 pSMB
->Reserved4
= 0;
4893 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4894 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4895 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4896 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4898 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4900 /* Note: On -EAGAIN error only caller can retry on handle based calls
4901 since file handle passed in no longer valid */
4907 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
4908 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
4910 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4913 __u16 params
, param_offset
, offset
, byte_count
, count
;
4915 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4916 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4921 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4922 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4925 pSMB
->MaxSetupCount
= 0;
4929 pSMB
->Reserved2
= 0;
4930 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4931 offset
= param_offset
+ params
;
4933 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4936 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4937 /* BB find max SMB PDU from sess */
4938 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4939 pSMB
->SetupCount
= 1;
4940 pSMB
->Reserved3
= 0;
4941 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4942 byte_count
= 3 /* pad */ + params
+ count
;
4943 pSMB
->DataCount
= cpu_to_le16(count
);
4944 pSMB
->ParameterCount
= cpu_to_le16(params
);
4945 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4946 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4947 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4948 pSMB
->DataOffset
= cpu_to_le16(offset
);
4950 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
4951 pSMB
->Reserved4
= 0;
4952 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4953 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4954 *data_offset
= delete_file
? 1 : 0;
4955 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4957 cFYI(1, ("Send error in SetFileDisposition = %d", rc
));
4963 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
4964 const char *fileName
, const FILE_BASIC_INFO
*data
,
4965 const struct nls_table
*nls_codepage
, int remap
)
4967 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4968 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4971 int bytes_returned
= 0;
4973 __u16 params
, param_offset
, offset
, byte_count
, count
;
4975 cFYI(1, ("In SetTimes"));
4978 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4983 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4985 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4986 PATH_MAX
, nls_codepage
, remap
);
4987 name_len
++; /* trailing null */
4989 } else { /* BB improve the check for buffer overruns BB */
4990 name_len
= strnlen(fileName
, PATH_MAX
);
4991 name_len
++; /* trailing null */
4992 strncpy(pSMB
->FileName
, fileName
, name_len
);
4995 params
= 6 + name_len
;
4996 count
= sizeof(FILE_BASIC_INFO
);
4997 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4998 /* BB find max SMB PDU from sess structure BB */
4999 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5000 pSMB
->MaxSetupCount
= 0;
5004 pSMB
->Reserved2
= 0;
5005 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5006 InformationLevel
) - 4;
5007 offset
= param_offset
+ params
;
5008 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5009 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5010 pSMB
->DataOffset
= cpu_to_le16(offset
);
5011 pSMB
->SetupCount
= 1;
5012 pSMB
->Reserved3
= 0;
5013 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5014 byte_count
= 3 /* pad */ + params
+ count
;
5016 pSMB
->DataCount
= cpu_to_le16(count
);
5017 pSMB
->ParameterCount
= cpu_to_le16(params
);
5018 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5019 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5020 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5021 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5023 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5024 pSMB
->Reserved4
= 0;
5025 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5026 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5027 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5028 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5029 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5031 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
5033 cifs_buf_release(pSMB
);
5041 /* Can not be used to set time stamps yet (due to old DOS time format) */
5042 /* Can be used to set attributes */
5043 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5044 handling it anyway and NT4 was what we thought it would be needed for
5045 Do not delete it until we prove whether needed for Win9x though */
5047 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5048 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5050 SETATTR_REQ
*pSMB
= NULL
;
5051 SETATTR_RSP
*pSMBr
= NULL
;
5056 cFYI(1, ("In SetAttrLegacy"));
5059 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5064 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5066 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5067 PATH_MAX
, nls_codepage
);
5068 name_len
++; /* trailing null */
5070 } else { /* BB improve the check for buffer overruns BB */
5071 name_len
= strnlen(fileName
, PATH_MAX
);
5072 name_len
++; /* trailing null */
5073 strncpy(pSMB
->fileName
, fileName
, name_len
);
5075 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5076 pSMB
->BufferFormat
= 0x04;
5077 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5078 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5079 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5080 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5082 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
5084 cifs_buf_release(pSMB
);
5087 goto SetAttrLgcyRetry
;
5091 #endif /* temporarily unneeded SetAttr legacy function */
5094 CIFSSMBUnixSetInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5095 const struct cifs_unix_set_info_args
*args
,
5096 const struct nls_table
*nls_codepage
, int remap
)
5098 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5099 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5102 int bytes_returned
= 0;
5103 FILE_UNIX_BASIC_INFO
*data_offset
;
5104 __u16 params
, param_offset
, offset
, count
, byte_count
;
5105 __u64 mode
= args
->mode
;
5107 cFYI(1, ("In SetUID/GID/Mode"));
5109 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5114 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5116 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5117 PATH_MAX
, nls_codepage
, remap
);
5118 name_len
++; /* trailing null */
5120 } else { /* BB improve the check for buffer overruns BB */
5121 name_len
= strnlen(fileName
, PATH_MAX
);
5122 name_len
++; /* trailing null */
5123 strncpy(pSMB
->FileName
, fileName
, name_len
);
5126 params
= 6 + name_len
;
5127 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5128 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5129 /* BB find max SMB PDU from sess structure BB */
5130 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5131 pSMB
->MaxSetupCount
= 0;
5135 pSMB
->Reserved2
= 0;
5136 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5137 InformationLevel
) - 4;
5138 offset
= param_offset
+ params
;
5140 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5142 memset(data_offset
, 0, count
);
5143 pSMB
->DataOffset
= cpu_to_le16(offset
);
5144 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5145 pSMB
->SetupCount
= 1;
5146 pSMB
->Reserved3
= 0;
5147 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5148 byte_count
= 3 /* pad */ + params
+ count
;
5149 pSMB
->ParameterCount
= cpu_to_le16(params
);
5150 pSMB
->DataCount
= cpu_to_le16(count
);
5151 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5152 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5153 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5154 pSMB
->Reserved4
= 0;
5155 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5156 /* Samba server ignores set of file size to zero due to bugs in some
5157 older clients, but we should be precise - we use SetFileSize to
5158 set file size and do not want to truncate file size to zero
5159 accidently as happened on one Samba server beta by putting
5160 zero instead of -1 here */
5161 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5162 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5163 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5164 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5165 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5166 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5167 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5168 /* better to leave device as zero when it is */
5169 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5170 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5171 data_offset
->Permissions
= cpu_to_le64(mode
);
5174 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5175 else if (S_ISDIR(mode
))
5176 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5177 else if (S_ISLNK(mode
))
5178 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5179 else if (S_ISCHR(mode
))
5180 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5181 else if (S_ISBLK(mode
))
5182 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5183 else if (S_ISFIFO(mode
))
5184 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5185 else if (S_ISSOCK(mode
))
5186 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5189 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5190 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5191 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5193 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5195 cifs_buf_release(pSMB
);
5201 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5202 const int notify_subdirs
, const __u16 netfid
,
5203 __u32 filter
, struct file
*pfile
, int multishot
,
5204 const struct nls_table
*nls_codepage
)
5207 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5208 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5209 struct dir_notify_req
*dnotify_req
;
5212 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5213 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5218 pSMB
->TotalParameterCount
= 0 ;
5219 pSMB
->TotalDataCount
= 0;
5220 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5221 /* BB find exact data count max from sess structure BB */
5222 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5223 /* BB VERIFY verify which is correct for above BB */
5224 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5225 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5227 pSMB
->MaxSetupCount
= 4;
5229 pSMB
->ParameterOffset
= 0;
5230 pSMB
->DataCount
= 0;
5231 pSMB
->DataOffset
= 0;
5232 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5233 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5234 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5236 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5237 pSMB
->Reserved2
= 0;
5238 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5239 pSMB
->Fid
= netfid
; /* file handle always le */
5240 pSMB
->ByteCount
= 0;
5242 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5243 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5246 cFYI(1, ("Error in Notify = %d", rc
));
5248 /* Add file to outstanding requests */
5249 /* BB change to kmem cache alloc */
5250 dnotify_req
= kmalloc(
5251 sizeof(struct dir_notify_req
),
5254 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5255 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5256 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5257 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5258 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5259 dnotify_req
->netfid
= netfid
;
5260 dnotify_req
->pfile
= pfile
;
5261 dnotify_req
->filter
= filter
;
5262 dnotify_req
->multishot
= multishot
;
5263 spin_lock(&GlobalMid_Lock
);
5264 list_add_tail(&dnotify_req
->lhead
,
5265 &GlobalDnotifyReqList
);
5266 spin_unlock(&GlobalMid_Lock
);
5270 cifs_buf_release(pSMB
);
5273 #ifdef CONFIG_CIFS_XATTR
5275 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5276 const unsigned char *searchName
,
5277 char *EAData
, size_t buf_size
,
5278 const struct nls_table
*nls_codepage
, int remap
)
5280 /* BB assumes one setup word */
5281 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5282 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5286 struct fea
*temp_fea
;
5288 __u16 params
, byte_count
;
5290 cFYI(1, ("In Query All EAs path %s", searchName
));
5292 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5297 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5299 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5300 PATH_MAX
, nls_codepage
, remap
);
5301 name_len
++; /* trailing null */
5303 } else { /* BB improve the check for buffer overruns BB */
5304 name_len
= strnlen(searchName
, PATH_MAX
);
5305 name_len
++; /* trailing null */
5306 strncpy(pSMB
->FileName
, searchName
, name_len
);
5309 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5310 pSMB
->TotalDataCount
= 0;
5311 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5312 /* BB find exact max SMB PDU from sess structure BB */
5313 pSMB
->MaxDataCount
= cpu_to_le16(4000);
5314 pSMB
->MaxSetupCount
= 0;
5318 pSMB
->Reserved2
= 0;
5319 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5320 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5321 pSMB
->DataCount
= 0;
5322 pSMB
->DataOffset
= 0;
5323 pSMB
->SetupCount
= 1;
5324 pSMB
->Reserved3
= 0;
5325 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5326 byte_count
= params
+ 1 /* pad */ ;
5327 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5328 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5329 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5330 pSMB
->Reserved4
= 0;
5331 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5332 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5334 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5335 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5337 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5338 } else { /* decode response */
5339 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5341 /* BB also check enough total bytes returned */
5342 /* BB we need to improve the validity checking
5343 of these trans2 responses */
5344 if (rc
|| (pSMBr
->ByteCount
< 4))
5345 rc
= -EIO
; /* bad smb */
5346 /* else if (pFindData){
5347 memcpy((char *) pFindData,
5348 (char *) &pSMBr->hdr.Protocol +
5351 /* check that length of list is not more than bcc */
5352 /* check that each entry does not go beyond length
5354 /* check that each element of each entry does not
5355 go beyond end of list */
5356 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5357 struct fealist
*ea_response_data
;
5359 /* validate_trans2_offsets() */
5360 /* BB check if start of smb + data_offset > &bcc+ bcc */
5361 ea_response_data
= (struct fealist
*)
5362 (((char *) &pSMBr
->hdr
.Protocol
) +
5364 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5365 cFYI(1, ("ea length %d", name_len
));
5366 if (name_len
<= 8) {
5367 /* returned EA size zeroed at top of function */
5368 cFYI(1, ("empty EA list returned from server"));
5370 /* account for ea list len */
5372 temp_fea
= ea_response_data
->list
;
5373 temp_ptr
= (char *)temp_fea
;
5374 while (name_len
> 0) {
5378 rc
+= temp_fea
->name_len
;
5379 /* account for prefix user. and trailing null */
5381 if (rc
< (int)buf_size
) {
5382 memcpy(EAData
, "user.", 5);
5384 memcpy(EAData
, temp_ptr
,
5385 temp_fea
->name_len
);
5386 EAData
+= temp_fea
->name_len
;
5387 /* null terminate name */
5389 EAData
= EAData
+ 1;
5390 } else if (buf_size
== 0) {
5391 /* skip copy - calc size only */
5393 /* stop before overrun buffer */
5397 name_len
-= temp_fea
->name_len
;
5398 temp_ptr
+= temp_fea
->name_len
;
5399 /* account for trailing null */
5403 le16_to_cpu(temp_fea
->value_len
);
5404 name_len
-= value_len
;
5405 temp_ptr
+= value_len
;
5406 /* BB check that temp_ptr is still
5409 /* no trailing null to account for
5411 /* go on to next EA */
5412 temp_fea
= (struct fea
*)temp_ptr
;
5417 cifs_buf_release(pSMB
);
5424 ssize_t
CIFSSMBQueryEA(const int xid
, struct cifsTconInfo
*tcon
,
5425 const unsigned char *searchName
, const unsigned char *ea_name
,
5426 unsigned char *ea_value
, size_t buf_size
,
5427 const struct nls_table
*nls_codepage
, int remap
)
5429 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5430 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5434 struct fea
*temp_fea
;
5436 __u16 params
, byte_count
;
5438 cFYI(1, ("In Query EA path %s", searchName
));
5440 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5445 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5447 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5448 PATH_MAX
, nls_codepage
, remap
);
5449 name_len
++; /* trailing null */
5451 } else { /* BB improve the check for buffer overruns BB */
5452 name_len
= strnlen(searchName
, PATH_MAX
);
5453 name_len
++; /* trailing null */
5454 strncpy(pSMB
->FileName
, searchName
, name_len
);
5457 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5458 pSMB
->TotalDataCount
= 0;
5459 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5460 /* BB find exact max SMB PDU from sess structure BB */
5461 pSMB
->MaxDataCount
= cpu_to_le16(4000);
5462 pSMB
->MaxSetupCount
= 0;
5466 pSMB
->Reserved2
= 0;
5467 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5468 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5469 pSMB
->DataCount
= 0;
5470 pSMB
->DataOffset
= 0;
5471 pSMB
->SetupCount
= 1;
5472 pSMB
->Reserved3
= 0;
5473 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5474 byte_count
= params
+ 1 /* pad */ ;
5475 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5476 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5477 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5478 pSMB
->Reserved4
= 0;
5479 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5480 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5482 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5483 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5485 cFYI(1, ("Send error in Query EA = %d", rc
));
5486 } else { /* decode response */
5487 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5489 /* BB also check enough total bytes returned */
5490 /* BB we need to improve the validity checking
5491 of these trans2 responses */
5492 if (rc
|| (pSMBr
->ByteCount
< 4))
5493 rc
= -EIO
; /* bad smb */
5494 /* else if (pFindData){
5495 memcpy((char *) pFindData,
5496 (char *) &pSMBr->hdr.Protocol +
5499 /* check that length of list is not more than bcc */
5500 /* check that each entry does not go beyond length
5502 /* check that each element of each entry does not
5503 go beyond end of list */
5504 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5505 struct fealist
*ea_response_data
;
5507 /* validate_trans2_offsets() */
5508 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5509 ea_response_data
= (struct fealist
*)
5510 (((char *) &pSMBr
->hdr
.Protocol
) +
5512 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5513 cFYI(1, ("ea length %d", name_len
));
5514 if (name_len
<= 8) {
5515 /* returned EA size zeroed at top of function */
5516 cFYI(1, ("empty EA list returned from server"));
5518 /* account for ea list len */
5520 temp_fea
= ea_response_data
->list
;
5521 temp_ptr
= (char *)temp_fea
;
5522 /* loop through checking if we have a matching
5523 name and then return the associated value */
5524 while (name_len
> 0) {
5529 le16_to_cpu(temp_fea
->value_len
);
5530 /* BB validate that value_len falls within SMB,
5531 even though maximum for name_len is 255 */
5532 if (memcmp(temp_fea
->name
, ea_name
,
5533 temp_fea
->name_len
) == 0) {
5536 /* account for prefix user. and trailing null */
5537 if (rc
<= (int)buf_size
) {
5539 temp_fea
->name
+temp_fea
->name_len
+1,
5541 /* ea values, unlike ea
5544 } else if (buf_size
== 0) {
5545 /* skip copy - calc size only */
5547 /* stop before overrun buffer */
5552 name_len
-= temp_fea
->name_len
;
5553 temp_ptr
+= temp_fea
->name_len
;
5554 /* account for trailing null */
5557 name_len
-= value_len
;
5558 temp_ptr
+= value_len
;
5559 /* No trailing null to account for in
5560 value_len. Go on to next EA */
5561 temp_fea
= (struct fea
*)temp_ptr
;
5566 cifs_buf_release(pSMB
);
5574 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5575 const char *ea_name
, const void *ea_value
,
5576 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5579 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5580 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5581 struct fealist
*parm_data
;
5584 int bytes_returned
= 0;
5585 __u16 params
, param_offset
, byte_count
, offset
, count
;
5587 cFYI(1, ("In SetEA"));
5589 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5594 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5596 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5597 PATH_MAX
, nls_codepage
, remap
);
5598 name_len
++; /* trailing null */
5600 } else { /* BB improve the check for buffer overruns BB */
5601 name_len
= strnlen(fileName
, PATH_MAX
);
5602 name_len
++; /* trailing null */
5603 strncpy(pSMB
->FileName
, fileName
, name_len
);
5606 params
= 6 + name_len
;
5608 /* done calculating parms using name_len of file name,
5609 now use name_len to calculate length of ea name
5610 we are going to create in the inode xattrs */
5611 if (ea_name
== NULL
)
5614 name_len
= strnlen(ea_name
, 255);
5616 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5617 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5618 /* BB find max SMB PDU from sess */
5619 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5620 pSMB
->MaxSetupCount
= 0;
5624 pSMB
->Reserved2
= 0;
5625 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5626 InformationLevel
) - 4;
5627 offset
= param_offset
+ params
;
5628 pSMB
->InformationLevel
=
5629 cpu_to_le16(SMB_SET_FILE_EA
);
5632 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5634 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5635 pSMB
->DataOffset
= cpu_to_le16(offset
);
5636 pSMB
->SetupCount
= 1;
5637 pSMB
->Reserved3
= 0;
5638 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5639 byte_count
= 3 /* pad */ + params
+ count
;
5640 pSMB
->DataCount
= cpu_to_le16(count
);
5641 parm_data
->list_len
= cpu_to_le32(count
);
5642 parm_data
->list
[0].EA_flags
= 0;
5643 /* we checked above that name len is less than 255 */
5644 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5645 /* EA names are always ASCII */
5647 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5648 parm_data
->list
[0].name
[name_len
] = 0;
5649 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5650 /* caller ensures that ea_value_len is less than 64K but
5651 we need to ensure that it fits within the smb */
5653 /*BB add length check to see if it would fit in
5654 negotiated SMB buffer size BB */
5655 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5657 memcpy(parm_data
->list
[0].name
+name_len
+1,
5658 ea_value
, ea_value_len
);
5660 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5661 pSMB
->ParameterCount
= cpu_to_le16(params
);
5662 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5663 pSMB
->Reserved4
= 0;
5664 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5665 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5666 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5667 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5669 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5671 cifs_buf_release(pSMB
);