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->need_reconnect)
194 rc = cifs_setup_session(0, tcon->ses,
196 if (!rc && (tcon->need_reconnect)) {
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->need_reconnect) {
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->need_reconnect)
341 rc = cifs_setup_session(0, tcon->ses,
343 if (!rc && (tcon->need_reconnect)) {
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->need_reconnect) {
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) {
810 if (ses->server == NULL)
813 if (ses->need_reconnect)
814 goto session_already_dead; /* no need to send SMBlogoff if uid
815 already closed due to reconnect */
816 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
822 pSMB->hdr.Mid = GetNextMid(ses->server);
824 if (ses->server->secMode &
825 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
826 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
828 pSMB->hdr.Uid = ses->Suid;
830 pSMB->AndXCommand = 0xFF;
831 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
832 session_already_dead:
833 atomic_dec(&ses->server->socketUseCount);
834 if (atomic_read(&ses->server->socketUseCount) == 0) {
835 spin_lock(&GlobalMid_Lock);
836 ses->server->tcpStatus = CifsExiting;
837 spin_unlock(&GlobalMid_Lock);
842 /* if session dead then we do not need to do ulogoff,
843 since server closed smb session, no sense reporting
851 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
852 __u16 type, const struct nls_table *nls_codepage, int remap)
854 TRANSACTION2_SPI_REQ *pSMB = NULL;
855 TRANSACTION2_SPI_RSP *pSMBr = NULL;
856 struct unlink_psx_rq *pRqD;
859 int bytes_returned = 0;
860 __u16 params, param_offset, offset, byte_count;
862 cFYI(1, ("In POSIX delete"));
864 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
869 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
871 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
872 PATH_MAX, nls_codepage, remap);
873 name_len++; /* trailing null */
875 } else { /* BB add path length overrun check */
876 name_len = strnlen(fileName, PATH_MAX);
877 name_len++; /* trailing null */
878 strncpy(pSMB->FileName, fileName, name_len);
881 params = 6 + name_len;
882 pSMB->MaxParameterCount = cpu_to_le16(2);
883 pSMB->MaxDataCount = 0; /* BB double check this with jra */
884 pSMB->MaxSetupCount = 0;
889 param_offset = offsetof(struct smb_com_transaction2_spi_req,
890 InformationLevel) - 4;
891 offset = param_offset + params;
893 /* Setup pointer to Request Data (inode type) */
894 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
895 pRqD->type = cpu_to_le16(type);
896 pSMB->ParameterOffset = cpu_to_le16(param_offset);
897 pSMB->DataOffset = cpu_to_le16(offset);
898 pSMB->SetupCount = 1;
900 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
901 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
903 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
904 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
905 pSMB->ParameterCount = cpu_to_le16(params);
906 pSMB->TotalParameterCount = pSMB->ParameterCount;
907 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
909 pSMB->hdr.smb_buf_length += byte_count;
910 pSMB->ByteCount = cpu_to_le16(byte_count);
911 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
912 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
914 cFYI(1, ("Posix delete returned %d", rc));
915 cifs_buf_release(pSMB);
917 cifs_stats_inc(&tcon->num_deletes);
926 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
927 const struct nls_table *nls_codepage, int remap)
929 DELETE_FILE_REQ *pSMB = NULL;
930 DELETE_FILE_RSP *pSMBr = NULL;
936 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
941 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
943 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
944 PATH_MAX, nls_codepage, remap);
945 name_len++; /* trailing null */
947 } else { /* BB improve check for buffer overruns BB */
948 name_len = strnlen(fileName, PATH_MAX);
949 name_len++; /* trailing null */
950 strncpy(pSMB->fileName, fileName, name_len);
952 pSMB->SearchAttributes =
953 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
954 pSMB->BufferFormat = 0x04;
955 pSMB->hdr.smb_buf_length += name_len + 1;
956 pSMB->ByteCount = cpu_to_le16(name_len + 1);
957 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
958 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
959 cifs_stats_inc(&tcon->num_deletes);
961 cFYI(1, ("Error in RMFile = %d", rc));
963 cifs_buf_release(pSMB);
971 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
972 const struct nls_table *nls_codepage, int remap)
974 DELETE_DIRECTORY_REQ *pSMB = NULL;
975 DELETE_DIRECTORY_RSP *pSMBr = NULL;
980 cFYI(1, ("In CIFSSMBRmDir"));
982 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
987 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
988 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
989 PATH_MAX, nls_codepage, remap);
990 name_len++; /* trailing null */
992 } else { /* BB improve check for buffer overruns BB */
993 name_len = strnlen(dirName, PATH_MAX);
994 name_len++; /* trailing null */
995 strncpy(pSMB->DirName, dirName, name_len);
998 pSMB->BufferFormat = 0x04;
999 pSMB->hdr.smb_buf_length += name_len + 1;
1000 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1001 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1002 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1003 cifs_stats_inc(&tcon->num_rmdirs);
1005 cFYI(1, ("Error in RMDir = %d", rc));
1007 cifs_buf_release(pSMB);
1014 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
1015 const char *name, const struct nls_table *nls_codepage, int remap)
1018 CREATE_DIRECTORY_REQ *pSMB = NULL;
1019 CREATE_DIRECTORY_RSP *pSMBr = NULL;
1023 cFYI(1, ("In CIFSSMBMkDir"));
1025 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1030 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1031 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1032 PATH_MAX, nls_codepage, remap);
1033 name_len++; /* trailing null */
1035 } else { /* BB improve check for buffer overruns BB */
1036 name_len = strnlen(name, PATH_MAX);
1037 name_len++; /* trailing null */
1038 strncpy(pSMB->DirName, name, name_len);
1041 pSMB->BufferFormat = 0x04;
1042 pSMB->hdr.smb_buf_length += name_len + 1;
1043 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1044 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1045 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1046 cifs_stats_inc(&tcon->num_mkdirs);
1048 cFYI(1, ("Error in Mkdir = %d", rc));
1050 cifs_buf_release(pSMB);
1057 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1058 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1059 __u32 *pOplock, const char *name,
1060 const struct nls_table *nls_codepage, int remap)
1062 TRANSACTION2_SPI_REQ *pSMB = NULL;
1063 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1066 int bytes_returned = 0;
1067 __u16 params, param_offset, offset, byte_count, count;
1068 OPEN_PSX_REQ *pdata;
1069 OPEN_PSX_RSP *psx_rsp;
1071 cFYI(1, ("In POSIX Create"));
1073 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1078 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1080 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1081 PATH_MAX, nls_codepage, remap);
1082 name_len++; /* trailing null */
1084 } else { /* BB improve the check for buffer overruns BB */
1085 name_len = strnlen(name, PATH_MAX);
1086 name_len++; /* trailing null */
1087 strncpy(pSMB->FileName, name, name_len);
1090 params = 6 + name_len;
1091 count = sizeof(OPEN_PSX_REQ);
1092 pSMB->MaxParameterCount = cpu_to_le16(2);
1093 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1094 pSMB->MaxSetupCount = 0;
1098 pSMB->Reserved2 = 0;
1099 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1100 InformationLevel) - 4;
1101 offset = param_offset + params;
1102 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1103 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1104 pdata->Permissions = cpu_to_le64(mode);
1105 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1106 pdata->OpenFlags = cpu_to_le32(*pOplock);
1107 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1108 pSMB->DataOffset = cpu_to_le16(offset);
1109 pSMB->SetupCount = 1;
1110 pSMB->Reserved3 = 0;
1111 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1112 byte_count = 3 /* pad */ + params + count;
1114 pSMB->DataCount = cpu_to_le16(count);
1115 pSMB->ParameterCount = cpu_to_le16(params);
1116 pSMB->TotalDataCount = pSMB->DataCount;
1117 pSMB->TotalParameterCount = pSMB->ParameterCount;
1118 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1119 pSMB->Reserved4 = 0;
1120 pSMB->hdr.smb_buf_length += byte_count;
1121 pSMB->ByteCount = cpu_to_le16(byte_count);
1122 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1123 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1125 cFYI(1, ("Posix create returned %d", rc));
1126 goto psx_create_err;
1129 cFYI(1, ("copying inode info"));
1130 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1132 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1133 rc = -EIO; /* bad smb */
1134 goto psx_create_err;
1137 /* copy return information to pRetData */
1138 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1139 + le16_to_cpu(pSMBr->t2.DataOffset));
1141 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1143 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1144 /* Let caller know file was created so we can set the mode. */
1145 /* Do we care about the CreateAction in any other cases? */
1146 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1147 *pOplock |= CIFS_CREATE_ACTION;
1148 /* check to make sure response data is there */
1149 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1150 pRetData->Type = cpu_to_le32(-1); /* unknown */
1151 cFYI(DBG2, ("unknown type"));
1153 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1154 + sizeof(FILE_UNIX_BASIC_INFO)) {
1155 cERROR(1, ("Open response data too small"));
1156 pRetData->Type = cpu_to_le32(-1);
1157 goto psx_create_err;
1159 memcpy((char *) pRetData,
1160 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1161 sizeof(FILE_UNIX_BASIC_INFO));
1165 cifs_buf_release(pSMB);
1167 cifs_stats_inc(&tcon->num_mkdirs);
1175 static __u16 convert_disposition(int disposition)
1179 switch (disposition) {
1180 case FILE_SUPERSEDE:
1181 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1184 ofun = SMBOPEN_OAPPEND;
1187 ofun = SMBOPEN_OCREATE;
1190 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1192 case FILE_OVERWRITE:
1193 ofun = SMBOPEN_OTRUNC;
1195 case FILE_OVERWRITE_IF:
1196 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1199 cFYI(1, ("unknown disposition %d", disposition));
1200 ofun = SMBOPEN_OAPPEND; /* regular open */
1206 access_flags_to_smbopen_mode(const int access_flags)
1208 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1210 if (masked_flags == GENERIC_READ)
1211 return SMBOPEN_READ;
1212 else if (masked_flags == GENERIC_WRITE)
1213 return SMBOPEN_WRITE;
1215 /* just go for read/write */
1216 return SMBOPEN_READWRITE;
1220 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1221 const char *fileName, const int openDisposition,
1222 const int access_flags, const int create_options, __u16 *netfid,
1223 int *pOplock, FILE_ALL_INFO *pfile_info,
1224 const struct nls_table *nls_codepage, int remap)
1227 OPENX_REQ *pSMB = NULL;
1228 OPENX_RSP *pSMBr = NULL;
1234 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1239 pSMB->AndXCommand = 0xFF; /* none */
1241 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1242 count = 1; /* account for one byte pad to word boundary */
1244 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1245 fileName, PATH_MAX, nls_codepage, remap);
1246 name_len++; /* trailing null */
1248 } else { /* BB improve check for buffer overruns BB */
1249 count = 0; /* no pad */
1250 name_len = strnlen(fileName, PATH_MAX);
1251 name_len++; /* trailing null */
1252 strncpy(pSMB->fileName, fileName, name_len);
1254 if (*pOplock & REQ_OPLOCK)
1255 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1256 else if (*pOplock & REQ_BATCHOPLOCK)
1257 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1259 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1260 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1261 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1262 /* set file as system file if special file such
1263 as fifo and server expecting SFU style and
1264 no Unix extensions */
1266 if (create_options & CREATE_OPTION_SPECIAL)
1267 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1268 else /* BB FIXME BB */
1269 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1271 if (create_options & CREATE_OPTION_READONLY)
1272 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1275 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1276 CREATE_OPTIONS_MASK); */
1277 /* BB FIXME END BB */
1279 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1280 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1282 pSMB->hdr.smb_buf_length += count;
1284 pSMB->ByteCount = cpu_to_le16(count);
1285 /* long_op set to 1 to allow for oplock break timeouts */
1286 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1287 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1288 cifs_stats_inc(&tcon->num_opens);
1290 cFYI(1, ("Error in Open = %d", rc));
1292 /* BB verify if wct == 15 */
1294 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1296 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1297 /* Let caller know file was created so we can set the mode. */
1298 /* Do we care about the CreateAction in any other cases? */
1300 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1301 *pOplock |= CIFS_CREATE_ACTION; */
1305 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1306 pfile_info->LastAccessTime = 0; /* BB fixme */
1307 pfile_info->LastWriteTime = 0; /* BB fixme */
1308 pfile_info->ChangeTime = 0; /* BB fixme */
1309 pfile_info->Attributes =
1310 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1311 /* the file_info buf is endian converted by caller */
1312 pfile_info->AllocationSize =
1313 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1314 pfile_info->EndOfFile = pfile_info->AllocationSize;
1315 pfile_info->NumberOfLinks = cpu_to_le32(1);
1316 pfile_info->DeletePending = 0;
1320 cifs_buf_release(pSMB);
1327 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1328 const char *fileName, const int openDisposition,
1329 const int access_flags, const int create_options, __u16 *netfid,
1330 int *pOplock, FILE_ALL_INFO *pfile_info,
1331 const struct nls_table *nls_codepage, int remap)
1334 OPEN_REQ *pSMB = NULL;
1335 OPEN_RSP *pSMBr = NULL;
1341 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1346 pSMB->AndXCommand = 0xFF; /* none */
1348 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1349 count = 1; /* account for one byte pad to word boundary */
1351 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1352 fileName, PATH_MAX, nls_codepage, remap);
1353 name_len++; /* trailing null */
1355 pSMB->NameLength = cpu_to_le16(name_len);
1356 } else { /* BB improve check for buffer overruns BB */
1357 count = 0; /* no pad */
1358 name_len = strnlen(fileName, PATH_MAX);
1359 name_len++; /* trailing null */
1360 pSMB->NameLength = cpu_to_le16(name_len);
1361 strncpy(pSMB->fileName, fileName, name_len);
1363 if (*pOplock & REQ_OPLOCK)
1364 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1365 else if (*pOplock & REQ_BATCHOPLOCK)
1366 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1367 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1368 pSMB->AllocationSize = 0;
1369 /* set file as system file if special file such
1370 as fifo and server expecting SFU style and
1371 no Unix extensions */
1372 if (create_options & CREATE_OPTION_SPECIAL)
1373 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1375 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1377 /* XP does not handle ATTR_POSIX_SEMANTICS */
1378 /* but it helps speed up case sensitive checks for other
1379 servers such as Samba */
1380 if (tcon->ses->capabilities & CAP_UNIX)
1381 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1383 if (create_options & CREATE_OPTION_READONLY)
1384 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1386 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1387 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1388 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1389 /* BB Expirement with various impersonation levels and verify */
1390 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1391 pSMB->SecurityFlags =
1392 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1395 pSMB->hdr.smb_buf_length += count;
1397 pSMB->ByteCount = cpu_to_le16(count);
1398 /* long_op set to 1 to allow for oplock break timeouts */
1399 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1400 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1401 cifs_stats_inc(&tcon->num_opens);
1403 cFYI(1, ("Error in Open = %d", rc));
1405 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1406 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1407 /* Let caller know file was created so we can set the mode. */
1408 /* Do we care about the CreateAction in any other cases? */
1409 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1410 *pOplock |= CIFS_CREATE_ACTION;
1412 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1413 36 /* CreationTime to Attributes */);
1414 /* the file_info buf is endian converted by caller */
1415 pfile_info->AllocationSize = pSMBr->AllocationSize;
1416 pfile_info->EndOfFile = pSMBr->EndOfFile;
1417 pfile_info->NumberOfLinks = cpu_to_le32(1);
1418 pfile_info->DeletePending = 0;
1422 cifs_buf_release(pSMB);
1429 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1430 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1431 char **buf, int *pbuf_type)
1434 READ_REQ *pSMB = NULL;
1435 READ_RSP *pSMBr = NULL;
1436 char *pReadData = NULL;
1438 int resp_buf_type = 0;
1441 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1442 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1445 wct = 10; /* old style read */
1448 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1452 /* tcon and ses pointer are checked in smb_init */
1453 if (tcon->ses->server == NULL)
1454 return -ECONNABORTED;
1456 pSMB->AndXCommand = 0xFF; /* none */
1458 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1460 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1461 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1464 pSMB->Remaining = 0;
1465 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1466 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1468 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1470 /* old style read */
1471 struct smb_com_readx_req *pSMBW =
1472 (struct smb_com_readx_req *)pSMB;
1473 pSMBW->ByteCount = 0;
1476 iov[0].iov_base = (char *)pSMB;
1477 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1478 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1479 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1480 cifs_stats_inc(&tcon->num_reads);
1481 pSMBr = (READ_RSP *)iov[0].iov_base;
1483 cERROR(1, ("Send error in read = %d", rc));
1485 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1486 data_length = data_length << 16;
1487 data_length += le16_to_cpu(pSMBr->DataLength);
1488 *nbytes = data_length;
1490 /*check that DataLength would not go beyond end of SMB */
1491 if ((data_length > CIFSMaxBufSize)
1492 || (data_length > count)) {
1493 cFYI(1, ("bad length %d for count %d",
1494 data_length, count));
1498 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1499 le16_to_cpu(pSMBr->DataOffset);
1500 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1501 cERROR(1,("Faulting on read rc = %d",rc));
1503 }*/ /* can not use copy_to_user when using page cache*/
1505 memcpy(*buf, pReadData, data_length);
1509 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1511 if (resp_buf_type == CIFS_SMALL_BUFFER)
1512 cifs_small_buf_release(iov[0].iov_base);
1513 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1514 cifs_buf_release(iov[0].iov_base);
1515 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1516 /* return buffer to caller to free */
1517 *buf = iov[0].iov_base;
1518 if (resp_buf_type == CIFS_SMALL_BUFFER)
1519 *pbuf_type = CIFS_SMALL_BUFFER;
1520 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1521 *pbuf_type = CIFS_LARGE_BUFFER;
1522 } /* else no valid buffer on return - leave as null */
1524 /* Note: On -EAGAIN error only caller can retry on handle based calls
1525 since file handle passed in no longer valid */
1531 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1532 const int netfid, const unsigned int count,
1533 const __u64 offset, unsigned int *nbytes, const char *buf,
1534 const char __user *ubuf, const int long_op)
1537 WRITE_REQ *pSMB = NULL;
1538 WRITE_RSP *pSMBr = NULL;
1539 int bytes_returned, wct;
1543 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1544 if (tcon->ses == NULL)
1545 return -ECONNABORTED;
1547 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1552 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1556 /* tcon and ses pointer are checked in smb_init */
1557 if (tcon->ses->server == NULL)
1558 return -ECONNABORTED;
1560 pSMB->AndXCommand = 0xFF; /* none */
1562 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1564 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1565 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1568 pSMB->Reserved = 0xFFFFFFFF;
1569 pSMB->WriteMode = 0;
1570 pSMB->Remaining = 0;
1572 /* Can increase buffer size if buffer is big enough in some cases ie we
1573 can send more if LARGE_WRITE_X capability returned by the server and if
1574 our buffer is big enough or if we convert to iovecs on socket writes
1575 and eliminate the copy to the CIFS buffer */
1576 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1577 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1579 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1583 if (bytes_sent > count)
1586 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1588 memcpy(pSMB->Data, buf, bytes_sent);
1590 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1591 cifs_buf_release(pSMB);
1594 } else if (count != 0) {
1596 cifs_buf_release(pSMB);
1598 } /* else setting file size with write of zero bytes */
1600 byte_count = bytes_sent + 1; /* pad */
1601 else /* wct == 12 */
1602 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1604 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1605 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1606 pSMB->hdr.smb_buf_length += byte_count;
1609 pSMB->ByteCount = cpu_to_le16(byte_count);
1610 else { /* old style write has byte count 4 bytes earlier
1612 struct smb_com_writex_req *pSMBW =
1613 (struct smb_com_writex_req *)pSMB;
1614 pSMBW->ByteCount = cpu_to_le16(byte_count);
1617 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1618 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1619 cifs_stats_inc(&tcon->num_writes);
1621 cFYI(1, ("Send error in write = %d", rc));
1624 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1625 *nbytes = (*nbytes) << 16;
1626 *nbytes += le16_to_cpu(pSMBr->Count);
1629 cifs_buf_release(pSMB);
1631 /* Note: On -EAGAIN error only caller can retry on handle based calls
1632 since file handle passed in no longer valid */
1638 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1639 const int netfid, const unsigned int count,
1640 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1641 int n_vec, const int long_op)
1644 WRITE_REQ *pSMB = NULL;
1647 int resp_buf_type = 0;
1649 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1651 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1655 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1658 /* tcon and ses pointer are checked in smb_init */
1659 if (tcon->ses->server == NULL)
1660 return -ECONNABORTED;
1662 pSMB->AndXCommand = 0xFF; /* none */
1664 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1666 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1667 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1669 pSMB->Reserved = 0xFFFFFFFF;
1670 pSMB->WriteMode = 0;
1671 pSMB->Remaining = 0;
1674 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1676 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1677 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1678 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1680 pSMB->hdr.smb_buf_length += count+1;
1681 else /* wct == 12 */
1682 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1684 pSMB->ByteCount = cpu_to_le16(count + 1);
1685 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1686 struct smb_com_writex_req *pSMBW =
1687 (struct smb_com_writex_req *)pSMB;
1688 pSMBW->ByteCount = cpu_to_le16(count + 5);
1690 iov[0].iov_base = pSMB;
1692 iov[0].iov_len = smb_hdr_len + 4;
1693 else /* wct == 12 pad bigger by four bytes */
1694 iov[0].iov_len = smb_hdr_len + 8;
1697 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1699 cifs_stats_inc(&tcon->num_writes);
1701 cFYI(1, ("Send error Write2 = %d", rc));
1703 } else if (resp_buf_type == 0) {
1704 /* presumably this can not happen, but best to be safe */
1708 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1709 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1710 *nbytes = (*nbytes) << 16;
1711 *nbytes += le16_to_cpu(pSMBr->Count);
1714 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1715 if (resp_buf_type == CIFS_SMALL_BUFFER)
1716 cifs_small_buf_release(iov[0].iov_base);
1717 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1718 cifs_buf_release(iov[0].iov_base);
1720 /* Note: On -EAGAIN error only caller can retry on handle based calls
1721 since file handle passed in no longer valid */
1728 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1729 const __u16 smb_file_id, const __u64 len,
1730 const __u64 offset, const __u32 numUnlock,
1731 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1734 LOCK_REQ *pSMB = NULL;
1735 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1740 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1741 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1746 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1747 timeout = CIFS_ASYNC_OP; /* no response expected */
1749 } else if (waitFlag) {
1750 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1751 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1756 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1757 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1758 pSMB->LockType = lockType;
1759 pSMB->AndXCommand = 0xFF; /* none */
1760 pSMB->Fid = smb_file_id; /* netfid stays le */
1762 if ((numLock != 0) || (numUnlock != 0)) {
1763 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1764 /* BB where to store pid high? */
1765 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1766 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1767 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1768 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1769 count = sizeof(LOCKING_ANDX_RANGE);
1774 pSMB->hdr.smb_buf_length += count;
1775 pSMB->ByteCount = cpu_to_le16(count);
1778 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1779 (struct smb_hdr *) pSMB, &bytes_returned);
1780 cifs_small_buf_release(pSMB);
1782 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1784 /* SMB buffer freed by function above */
1786 cifs_stats_inc(&tcon->num_locks);
1788 cFYI(1, ("Send error in Lock = %d", rc));
1790 /* Note: On -EAGAIN error only caller can retry on handle based calls
1791 since file handle passed in no longer valid */
1796 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1797 const __u16 smb_file_id, const int get_flag, const __u64 len,
1798 struct file_lock *pLockData, const __u16 lock_type,
1799 const bool waitFlag)
1801 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1802 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1803 struct cifs_posix_lock *parm_data;
1806 int bytes_returned = 0;
1807 int resp_buf_type = 0;
1808 __u16 params, param_offset, offset, byte_count, count;
1811 cFYI(1, ("Posix Lock"));
1813 if (pLockData == NULL)
1816 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1821 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1824 pSMB->MaxSetupCount = 0;
1827 pSMB->Reserved2 = 0;
1828 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1829 offset = param_offset + params;
1831 count = sizeof(struct cifs_posix_lock);
1832 pSMB->MaxParameterCount = cpu_to_le16(2);
1833 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1834 pSMB->SetupCount = 1;
1835 pSMB->Reserved3 = 0;
1837 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1839 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1840 byte_count = 3 /* pad */ + params + count;
1841 pSMB->DataCount = cpu_to_le16(count);
1842 pSMB->ParameterCount = cpu_to_le16(params);
1843 pSMB->TotalDataCount = pSMB->DataCount;
1844 pSMB->TotalParameterCount = pSMB->ParameterCount;
1845 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1846 parm_data = (struct cifs_posix_lock *)
1847 (((char *) &pSMB->hdr.Protocol) + offset);
1849 parm_data->lock_type = cpu_to_le16(lock_type);
1851 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1852 parm_data->lock_flags = cpu_to_le16(1);
1853 pSMB->Timeout = cpu_to_le32(-1);
1857 parm_data->pid = cpu_to_le32(current->tgid);
1858 parm_data->start = cpu_to_le64(pLockData->fl_start);
1859 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1861 pSMB->DataOffset = cpu_to_le16(offset);
1862 pSMB->Fid = smb_file_id;
1863 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1864 pSMB->Reserved4 = 0;
1865 pSMB->hdr.smb_buf_length += byte_count;
1866 pSMB->ByteCount = cpu_to_le16(byte_count);
1868 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1869 (struct smb_hdr *) pSMBr, &bytes_returned);
1871 iov[0].iov_base = (char *)pSMB;
1872 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1873 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1874 &resp_buf_type, timeout);
1875 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1876 not try to free it twice below on exit */
1877 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1881 cFYI(1, ("Send error in Posix Lock = %d", rc));
1882 } else if (get_flag) {
1883 /* lock structure can be returned on get */
1886 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1888 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1889 rc = -EIO; /* bad smb */
1892 if (pLockData == NULL) {
1896 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1897 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1898 if (data_count < sizeof(struct cifs_posix_lock)) {
1902 parm_data = (struct cifs_posix_lock *)
1903 ((char *)&pSMBr->hdr.Protocol + data_offset);
1904 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1905 pLockData->fl_type = F_UNLCK;
1910 cifs_small_buf_release(pSMB);
1912 if (resp_buf_type == CIFS_SMALL_BUFFER)
1913 cifs_small_buf_release(iov[0].iov_base);
1914 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1915 cifs_buf_release(iov[0].iov_base);
1917 /* Note: On -EAGAIN error only caller can retry on handle based calls
1918 since file handle passed in no longer valid */
1925 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1928 CLOSE_REQ *pSMB = NULL;
1929 cFYI(1, ("In CIFSSMBClose"));
1931 /* do not retry on dead session on close */
1932 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1938 pSMB->FileID = (__u16) smb_file_id;
1939 pSMB->LastWriteTime = 0xFFFFFFFF;
1940 pSMB->ByteCount = 0;
1941 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1942 cifs_stats_inc(&tcon->num_closes);
1945 /* EINTR is expected when user ctl-c to kill app */
1946 cERROR(1, ("Send error in Close = %d", rc));
1950 /* Since session is dead, file will be closed on server already */
1958 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1959 const char *fromName, const char *toName,
1960 const struct nls_table *nls_codepage, int remap)
1963 RENAME_REQ *pSMB = NULL;
1964 RENAME_RSP *pSMBr = NULL;
1966 int name_len, name_len2;
1969 cFYI(1, ("In CIFSSMBRename"));
1971 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1976 pSMB->BufferFormat = 0x04;
1977 pSMB->SearchAttributes =
1978 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1981 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1983 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1984 PATH_MAX, nls_codepage, remap);
1985 name_len++; /* trailing null */
1987 pSMB->OldFileName[name_len] = 0x04; /* pad */
1988 /* protocol requires ASCII signature byte on Unicode string */
1989 pSMB->OldFileName[name_len + 1] = 0x00;
1991 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1992 toName, PATH_MAX, nls_codepage, remap);
1993 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1994 name_len2 *= 2; /* convert to bytes */
1995 } else { /* BB improve the check for buffer overruns BB */
1996 name_len = strnlen(fromName, PATH_MAX);
1997 name_len++; /* trailing null */
1998 strncpy(pSMB->OldFileName, fromName, name_len);
1999 name_len2 = strnlen(toName, PATH_MAX);
2000 name_len2++; /* trailing null */
2001 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2002 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2003 name_len2++; /* trailing null */
2004 name_len2++; /* signature byte */
2007 count = 1 /* 1st signature byte */ + name_len + name_len2;
2008 pSMB->hdr.smb_buf_length += count;
2009 pSMB->ByteCount = cpu_to_le16(count);
2011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2013 cifs_stats_inc(&tcon->num_renames);
2015 cFYI(1, ("Send error in rename = %d", rc));
2017 cifs_buf_release(pSMB);
2025 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2026 int netfid, const char *target_name,
2027 const struct nls_table *nls_codepage, int remap)
2029 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2030 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2031 struct set_file_rename *rename_info;
2033 char dummy_string[30];
2035 int bytes_returned = 0;
2037 __u16 params, param_offset, offset, count, byte_count;
2039 cFYI(1, ("Rename to File by handle"));
2040 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2046 pSMB->MaxSetupCount = 0;
2050 pSMB->Reserved2 = 0;
2051 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2052 offset = param_offset + params;
2054 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2055 rename_info = (struct set_file_rename *) data_offset;
2056 pSMB->MaxParameterCount = cpu_to_le16(2);
2057 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2058 pSMB->SetupCount = 1;
2059 pSMB->Reserved3 = 0;
2060 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2061 byte_count = 3 /* pad */ + params;
2062 pSMB->ParameterCount = cpu_to_le16(params);
2063 pSMB->TotalParameterCount = pSMB->ParameterCount;
2064 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2065 pSMB->DataOffset = cpu_to_le16(offset);
2066 /* construct random name ".cifs_tmp<inodenum><mid>" */
2067 rename_info->overwrite = cpu_to_le32(1);
2068 rename_info->root_fid = 0;
2069 /* unicode only call */
2070 if (target_name == NULL) {
2071 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2072 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2073 dummy_string, 24, nls_codepage, remap);
2075 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2076 target_name, PATH_MAX, nls_codepage,
2079 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2080 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2081 byte_count += count;
2082 pSMB->DataCount = cpu_to_le16(count);
2083 pSMB->TotalDataCount = pSMB->DataCount;
2085 pSMB->InformationLevel =
2086 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2087 pSMB->Reserved4 = 0;
2088 pSMB->hdr.smb_buf_length += byte_count;
2089 pSMB->ByteCount = cpu_to_le16(byte_count);
2090 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2091 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2092 cifs_stats_inc(&pTcon->num_t2renames);
2094 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2096 cifs_buf_release(pSMB);
2098 /* Note: On -EAGAIN error only caller can retry on handle based calls
2099 since file handle passed in no longer valid */
2105 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2106 const __u16 target_tid, const char *toName, const int flags,
2107 const struct nls_table *nls_codepage, int remap)
2110 COPY_REQ *pSMB = NULL;
2111 COPY_RSP *pSMBr = NULL;
2113 int name_len, name_len2;
2116 cFYI(1, ("In CIFSSMBCopy"));
2118 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2123 pSMB->BufferFormat = 0x04;
2124 pSMB->Tid2 = target_tid;
2126 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2128 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2129 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2130 fromName, PATH_MAX, nls_codepage,
2132 name_len++; /* trailing null */
2134 pSMB->OldFileName[name_len] = 0x04; /* pad */
2135 /* protocol requires ASCII signature byte on Unicode string */
2136 pSMB->OldFileName[name_len + 1] = 0x00;
2138 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2139 toName, PATH_MAX, nls_codepage, remap);
2140 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2141 name_len2 *= 2; /* convert to bytes */
2142 } else { /* BB improve the check for buffer overruns BB */
2143 name_len = strnlen(fromName, PATH_MAX);
2144 name_len++; /* trailing null */
2145 strncpy(pSMB->OldFileName, fromName, name_len);
2146 name_len2 = strnlen(toName, PATH_MAX);
2147 name_len2++; /* trailing null */
2148 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2149 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2150 name_len2++; /* trailing null */
2151 name_len2++; /* signature byte */
2154 count = 1 /* 1st signature byte */ + name_len + name_len2;
2155 pSMB->hdr.smb_buf_length += count;
2156 pSMB->ByteCount = cpu_to_le16(count);
2158 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2159 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2161 cFYI(1, ("Send error in copy = %d with %d files copied",
2162 rc, le16_to_cpu(pSMBr->CopyCount)));
2164 cifs_buf_release(pSMB);
2173 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2174 const char *fromName, const char *toName,
2175 const struct nls_table *nls_codepage)
2177 TRANSACTION2_SPI_REQ *pSMB = NULL;
2178 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2181 int name_len_target;
2183 int bytes_returned = 0;
2184 __u16 params, param_offset, offset, byte_count;
2186 cFYI(1, ("In Symlink Unix style"));
2188 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2193 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2195 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2196 /* find define for this maxpathcomponent */
2198 name_len++; /* trailing null */
2201 } else { /* BB improve the check for buffer overruns BB */
2202 name_len = strnlen(fromName, PATH_MAX);
2203 name_len++; /* trailing null */
2204 strncpy(pSMB->FileName, fromName, name_len);
2206 params = 6 + name_len;
2207 pSMB->MaxSetupCount = 0;
2211 pSMB->Reserved2 = 0;
2212 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2213 InformationLevel) - 4;
2214 offset = param_offset + params;
2216 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2217 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2219 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2220 /* find define for this maxpathcomponent */
2222 name_len_target++; /* trailing null */
2223 name_len_target *= 2;
2224 } else { /* BB improve the check for buffer overruns BB */
2225 name_len_target = strnlen(toName, PATH_MAX);
2226 name_len_target++; /* trailing null */
2227 strncpy(data_offset, toName, name_len_target);
2230 pSMB->MaxParameterCount = cpu_to_le16(2);
2231 /* BB find exact max on data count below from sess */
2232 pSMB->MaxDataCount = cpu_to_le16(1000);
2233 pSMB->SetupCount = 1;
2234 pSMB->Reserved3 = 0;
2235 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2236 byte_count = 3 /* pad */ + params + name_len_target;
2237 pSMB->DataCount = cpu_to_le16(name_len_target);
2238 pSMB->ParameterCount = cpu_to_le16(params);
2239 pSMB->TotalDataCount = pSMB->DataCount;
2240 pSMB->TotalParameterCount = pSMB->ParameterCount;
2241 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2242 pSMB->DataOffset = cpu_to_le16(offset);
2243 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2244 pSMB->Reserved4 = 0;
2245 pSMB->hdr.smb_buf_length += byte_count;
2246 pSMB->ByteCount = cpu_to_le16(byte_count);
2247 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2248 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2249 cifs_stats_inc(&tcon->num_symlinks);
2251 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2253 cifs_buf_release(pSMB);
2256 goto createSymLinkRetry;
2262 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2263 const char *fromName, const char *toName,
2264 const struct nls_table *nls_codepage, int remap)
2266 TRANSACTION2_SPI_REQ *pSMB = NULL;
2267 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2270 int name_len_target;
2272 int bytes_returned = 0;
2273 __u16 params, param_offset, offset, byte_count;
2275 cFYI(1, ("In Create Hard link Unix style"));
2276 createHardLinkRetry:
2277 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2282 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2283 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2284 PATH_MAX, nls_codepage, remap);
2285 name_len++; /* trailing null */
2288 } else { /* BB improve the check for buffer overruns BB */
2289 name_len = strnlen(toName, PATH_MAX);
2290 name_len++; /* trailing null */
2291 strncpy(pSMB->FileName, toName, name_len);
2293 params = 6 + name_len;
2294 pSMB->MaxSetupCount = 0;
2298 pSMB->Reserved2 = 0;
2299 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2300 InformationLevel) - 4;
2301 offset = param_offset + params;
2303 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2306 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2307 nls_codepage, remap);
2308 name_len_target++; /* trailing null */
2309 name_len_target *= 2;
2310 } else { /* BB improve the check for buffer overruns BB */
2311 name_len_target = strnlen(fromName, PATH_MAX);
2312 name_len_target++; /* trailing null */
2313 strncpy(data_offset, fromName, name_len_target);
2316 pSMB->MaxParameterCount = cpu_to_le16(2);
2317 /* BB find exact max on data count below from sess*/
2318 pSMB->MaxDataCount = cpu_to_le16(1000);
2319 pSMB->SetupCount = 1;
2320 pSMB->Reserved3 = 0;
2321 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2322 byte_count = 3 /* pad */ + params + name_len_target;
2323 pSMB->ParameterCount = cpu_to_le16(params);
2324 pSMB->TotalParameterCount = pSMB->ParameterCount;
2325 pSMB->DataCount = cpu_to_le16(name_len_target);
2326 pSMB->TotalDataCount = pSMB->DataCount;
2327 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2328 pSMB->DataOffset = cpu_to_le16(offset);
2329 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2330 pSMB->Reserved4 = 0;
2331 pSMB->hdr.smb_buf_length += byte_count;
2332 pSMB->ByteCount = cpu_to_le16(byte_count);
2333 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2334 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2335 cifs_stats_inc(&tcon->num_hardlinks);
2337 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2339 cifs_buf_release(pSMB);
2341 goto createHardLinkRetry;
2347 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2348 const char *fromName, const char *toName,
2349 const struct nls_table *nls_codepage, int remap)
2352 NT_RENAME_REQ *pSMB = NULL;
2353 RENAME_RSP *pSMBr = NULL;
2355 int name_len, name_len2;
2358 cFYI(1, ("In CIFSCreateHardLink"));
2359 winCreateHardLinkRetry:
2361 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2366 pSMB->SearchAttributes =
2367 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2369 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2370 pSMB->ClusterCount = 0;
2372 pSMB->BufferFormat = 0x04;
2374 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2376 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2377 PATH_MAX, nls_codepage, remap);
2378 name_len++; /* trailing null */
2380 pSMB->OldFileName[name_len] = 0; /* pad */
2381 pSMB->OldFileName[name_len + 1] = 0x04;
2383 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2384 toName, PATH_MAX, nls_codepage, remap);
2385 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2386 name_len2 *= 2; /* convert to bytes */
2387 } else { /* BB improve the check for buffer overruns BB */
2388 name_len = strnlen(fromName, PATH_MAX);
2389 name_len++; /* trailing null */
2390 strncpy(pSMB->OldFileName, fromName, name_len);
2391 name_len2 = strnlen(toName, PATH_MAX);
2392 name_len2++; /* trailing null */
2393 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2394 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2395 name_len2++; /* trailing null */
2396 name_len2++; /* signature byte */
2399 count = 1 /* string type byte */ + name_len + name_len2;
2400 pSMB->hdr.smb_buf_length += count;
2401 pSMB->ByteCount = cpu_to_le16(count);
2403 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2404 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2405 cifs_stats_inc(&tcon->num_hardlinks);
2407 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2409 cifs_buf_release(pSMB);
2411 goto winCreateHardLinkRetry;
2417 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2418 const unsigned char *searchName,
2419 char *symlinkinfo, const int buflen,
2420 const struct nls_table *nls_codepage)
2422 /* SMB_QUERY_FILE_UNIX_LINK */
2423 TRANSACTION2_QPI_REQ *pSMB = NULL;
2424 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2428 __u16 params, byte_count;
2430 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2433 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2438 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2440 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2441 PATH_MAX, nls_codepage);
2442 name_len++; /* trailing null */
2444 } else { /* BB improve the check for buffer overruns BB */
2445 name_len = strnlen(searchName, PATH_MAX);
2446 name_len++; /* trailing null */
2447 strncpy(pSMB->FileName, searchName, name_len);
2450 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2451 pSMB->TotalDataCount = 0;
2452 pSMB->MaxParameterCount = cpu_to_le16(2);
2453 /* BB find exact max data count below from sess structure BB */
2454 pSMB->MaxDataCount = cpu_to_le16(4000);
2455 pSMB->MaxSetupCount = 0;
2459 pSMB->Reserved2 = 0;
2460 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2461 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2462 pSMB->DataCount = 0;
2463 pSMB->DataOffset = 0;
2464 pSMB->SetupCount = 1;
2465 pSMB->Reserved3 = 0;
2466 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2467 byte_count = params + 1 /* pad */ ;
2468 pSMB->TotalParameterCount = cpu_to_le16(params);
2469 pSMB->ParameterCount = pSMB->TotalParameterCount;
2470 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2471 pSMB->Reserved4 = 0;
2472 pSMB->hdr.smb_buf_length += byte_count;
2473 pSMB->ByteCount = cpu_to_le16(byte_count);
2475 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2478 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2480 /* decode response */
2482 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2483 if (rc || (pSMBr->ByteCount < 2))
2484 /* BB also check enough total bytes returned */
2485 rc = -EIO; /* bad smb */
2487 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2488 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2490 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2491 name_len = UniStrnlen((wchar_t *) ((char *)
2492 &pSMBr->hdr.Protocol + data_offset),
2493 min_t(const int, buflen, count) / 2);
2494 /* BB FIXME investigate remapping reserved chars here */
2495 cifs_strfromUCS_le(symlinkinfo,
2496 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2498 name_len, nls_codepage);
2500 strncpy(symlinkinfo,
2501 (char *) &pSMBr->hdr.Protocol +
2503 min_t(const int, buflen, count));
2505 symlinkinfo[buflen] = 0;
2506 /* just in case so calling code does not go off the end of buffer */
2509 cifs_buf_release(pSMB);
2511 goto querySymLinkRetry;
2515 #ifdef CONFIG_CIFS_EXPERIMENTAL
2516 /* Initialize NT TRANSACT SMB into small smb request buffer.
2517 This assumes that all NT TRANSACTS that we init here have
2518 total parm and data under about 400 bytes (to fit in small cifs
2519 buffer size), which is the case so far, it easily fits. NB:
2520 Setup words themselves and ByteCount
2521 MaxSetupCount (size of returned setup area) and
2522 MaxParameterCount (returned parms size) must be set by caller */
2524 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2525 const int parm_len, struct cifsTconInfo *tcon,
2530 struct smb_com_ntransact_req *pSMB;
2532 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2536 *ret_buf = (void *)pSMB;
2538 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2539 pSMB->TotalDataCount = 0;
2540 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2541 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2542 pSMB->ParameterCount = pSMB->TotalParameterCount;
2543 pSMB->DataCount = pSMB->TotalDataCount;
2544 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2545 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2546 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2547 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2548 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2549 pSMB->SubCommand = cpu_to_le16(sub_command);
2554 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2555 __u32 *pparmlen, __u32 *pdatalen)
2558 __u32 data_count, data_offset, parm_count, parm_offset;
2559 struct smb_com_ntransact_rsp *pSMBr;
2567 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2569 /* ByteCount was converted from little endian in SendReceive */
2570 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2571 (char *)&pSMBr->ByteCount;
2573 data_offset = le32_to_cpu(pSMBr->DataOffset);
2574 data_count = le32_to_cpu(pSMBr->DataCount);
2575 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2576 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2578 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2579 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2581 /* should we also check that parm and data areas do not overlap? */
2582 if (*ppparm > end_of_smb) {
2583 cFYI(1, ("parms start after end of smb"));
2585 } else if (parm_count + *ppparm > end_of_smb) {
2586 cFYI(1, ("parm end after end of smb"));
2588 } else if (*ppdata > end_of_smb) {
2589 cFYI(1, ("data starts after end of smb"));
2591 } else if (data_count + *ppdata > end_of_smb) {
2592 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2593 *ppdata, data_count, (data_count + *ppdata),
2594 end_of_smb, pSMBr));
2596 } else if (parm_count + data_count > pSMBr->ByteCount) {
2597 cFYI(1, ("parm count and data count larger than SMB"));
2600 *pdatalen = data_count;
2601 *pparmlen = parm_count;
2604 #endif /* CIFS_EXPERIMENTAL */
2607 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2608 const unsigned char *searchName,
2609 char *symlinkinfo, const int buflen, __u16 fid,
2610 const struct nls_table *nls_codepage)
2615 struct smb_com_transaction_ioctl_req *pSMB;
2616 struct smb_com_transaction_ioctl_rsp *pSMBr;
2618 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2619 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2624 pSMB->TotalParameterCount = 0 ;
2625 pSMB->TotalDataCount = 0;
2626 pSMB->MaxParameterCount = cpu_to_le32(2);
2627 /* BB find exact data count max from sess structure BB */
2628 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2629 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2630 pSMB->MaxSetupCount = 4;
2632 pSMB->ParameterOffset = 0;
2633 pSMB->DataCount = 0;
2634 pSMB->DataOffset = 0;
2635 pSMB->SetupCount = 4;
2636 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2637 pSMB->ParameterCount = pSMB->TotalParameterCount;
2638 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2639 pSMB->IsFsctl = 1; /* FSCTL */
2640 pSMB->IsRootFlag = 0;
2641 pSMB->Fid = fid; /* file handle always le */
2642 pSMB->ByteCount = 0;
2644 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2645 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2647 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2648 } else { /* decode response */
2649 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2650 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2651 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2652 /* BB also check enough total bytes returned */
2653 rc = -EIO; /* bad smb */
2655 if (data_count && (data_count < 2048)) {
2656 char *end_of_smb = 2 /* sizeof byte count */ +
2658 (char *)&pSMBr->ByteCount;
2660 struct reparse_data *reparse_buf =
2661 (struct reparse_data *)
2662 ((char *)&pSMBr->hdr.Protocol
2664 if ((char *)reparse_buf >= end_of_smb) {
2668 if ((reparse_buf->LinkNamesBuf +
2669 reparse_buf->TargetNameOffset +
2670 reparse_buf->TargetNameLen) >
2672 cFYI(1, ("reparse buf beyond SMB"));
2677 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2678 name_len = UniStrnlen((wchar_t *)
2679 (reparse_buf->LinkNamesBuf +
2680 reparse_buf->TargetNameOffset),
2682 reparse_buf->TargetNameLen / 2));
2683 cifs_strfromUCS_le(symlinkinfo,
2684 (__le16 *) (reparse_buf->LinkNamesBuf +
2685 reparse_buf->TargetNameOffset),
2686 name_len, nls_codepage);
2687 } else { /* ASCII names */
2688 strncpy(symlinkinfo,
2689 reparse_buf->LinkNamesBuf +
2690 reparse_buf->TargetNameOffset,
2691 min_t(const int, buflen,
2692 reparse_buf->TargetNameLen));
2696 cFYI(1, ("Invalid return data count on "
2697 "get reparse info ioctl"));
2699 symlinkinfo[buflen] = 0; /* just in case so the caller
2700 does not go off the end of the buffer */
2701 cFYI(1, ("readlink result - %s", symlinkinfo));
2705 cifs_buf_release(pSMB);
2707 /* Note: On -EAGAIN error only caller can retry on handle based calls
2708 since file handle passed in no longer valid */
2713 #ifdef CONFIG_CIFS_POSIX
2715 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2716 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2717 struct cifs_posix_ace *cifs_ace)
2719 /* u8 cifs fields do not need le conversion */
2720 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2721 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2722 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2723 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2728 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2729 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2730 const int acl_type, const int size_of_data_area)
2735 struct cifs_posix_ace *pACE;
2736 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2737 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2739 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2742 if (acl_type & ACL_TYPE_ACCESS) {
2743 count = le16_to_cpu(cifs_acl->access_entry_count);
2744 pACE = &cifs_acl->ace_array[0];
2745 size = sizeof(struct cifs_posix_acl);
2746 size += sizeof(struct cifs_posix_ace) * count;
2747 /* check if we would go beyond end of SMB */
2748 if (size_of_data_area < size) {
2749 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2750 size_of_data_area, size));
2753 } else if (acl_type & ACL_TYPE_DEFAULT) {
2754 count = le16_to_cpu(cifs_acl->access_entry_count);
2755 size = sizeof(struct cifs_posix_acl);
2756 size += sizeof(struct cifs_posix_ace) * count;
2757 /* skip past access ACEs to get to default ACEs */
2758 pACE = &cifs_acl->ace_array[count];
2759 count = le16_to_cpu(cifs_acl->default_entry_count);
2760 size += sizeof(struct cifs_posix_ace) * count;
2761 /* check if we would go beyond end of SMB */
2762 if (size_of_data_area < size)
2769 size = posix_acl_xattr_size(count);
2770 if ((buflen == 0) || (local_acl == NULL)) {
2771 /* used to query ACL EA size */
2772 } else if (size > buflen) {
2774 } else /* buffer big enough */ {
2775 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2776 for (i = 0; i < count ; i++) {
2777 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2784 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2785 const posix_acl_xattr_entry *local_ace)
2787 __u16 rc = 0; /* 0 = ACL converted ok */
2789 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2790 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2791 /* BB is there a better way to handle the large uid? */
2792 if (local_ace->e_id == cpu_to_le32(-1)) {
2793 /* Probably no need to le convert -1 on any arch but can not hurt */
2794 cifs_ace->cifs_uid = cpu_to_le64(-1);
2796 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2797 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2801 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2802 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2803 const int buflen, const int acl_type)
2806 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2807 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2811 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2814 count = posix_acl_xattr_count((size_t)buflen);
2815 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2817 count, buflen, le32_to_cpu(local_acl->a_version)));
2818 if (le32_to_cpu(local_acl->a_version) != 2) {
2819 cFYI(1, ("unknown POSIX ACL version %d",
2820 le32_to_cpu(local_acl->a_version)));
2823 cifs_acl->version = cpu_to_le16(1);
2824 if (acl_type == ACL_TYPE_ACCESS)
2825 cifs_acl->access_entry_count = cpu_to_le16(count);
2826 else if (acl_type == ACL_TYPE_DEFAULT)
2827 cifs_acl->default_entry_count = cpu_to_le16(count);
2829 cFYI(1, ("unknown ACL type %d", acl_type));
2832 for (i = 0; i < count; i++) {
2833 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2834 &local_acl->a_entries[i]);
2836 /* ACE not converted */
2841 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2842 rc += sizeof(struct cifs_posix_acl);
2843 /* BB add check to make sure ACL does not overflow SMB */
2849 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2850 const unsigned char *searchName,
2851 char *acl_inf, const int buflen, const int acl_type,
2852 const struct nls_table *nls_codepage, int remap)
2854 /* SMB_QUERY_POSIX_ACL */
2855 TRANSACTION2_QPI_REQ *pSMB = NULL;
2856 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2860 __u16 params, byte_count;
2862 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2865 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2870 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2872 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2873 PATH_MAX, nls_codepage, remap);
2874 name_len++; /* trailing null */
2876 pSMB->FileName[name_len] = 0;
2877 pSMB->FileName[name_len+1] = 0;
2878 } else { /* BB improve the check for buffer overruns BB */
2879 name_len = strnlen(searchName, PATH_MAX);
2880 name_len++; /* trailing null */
2881 strncpy(pSMB->FileName, searchName, name_len);
2884 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2885 pSMB->TotalDataCount = 0;
2886 pSMB->MaxParameterCount = cpu_to_le16(2);
2887 /* BB find exact max data count below from sess structure BB */
2888 pSMB->MaxDataCount = cpu_to_le16(4000);
2889 pSMB->MaxSetupCount = 0;
2893 pSMB->Reserved2 = 0;
2894 pSMB->ParameterOffset = cpu_to_le16(
2895 offsetof(struct smb_com_transaction2_qpi_req,
2896 InformationLevel) - 4);
2897 pSMB->DataCount = 0;
2898 pSMB->DataOffset = 0;
2899 pSMB->SetupCount = 1;
2900 pSMB->Reserved3 = 0;
2901 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2902 byte_count = params + 1 /* pad */ ;
2903 pSMB->TotalParameterCount = cpu_to_le16(params);
2904 pSMB->ParameterCount = pSMB->TotalParameterCount;
2905 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2906 pSMB->Reserved4 = 0;
2907 pSMB->hdr.smb_buf_length += byte_count;
2908 pSMB->ByteCount = cpu_to_le16(byte_count);
2910 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2911 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2912 cifs_stats_inc(&tcon->num_acl_get);
2914 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2916 /* decode response */
2918 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2919 if (rc || (pSMBr->ByteCount < 2))
2920 /* BB also check enough total bytes returned */
2921 rc = -EIO; /* bad smb */
2923 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2924 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2925 rc = cifs_copy_posix_acl(acl_inf,
2926 (char *)&pSMBr->hdr.Protocol+data_offset,
2927 buflen, acl_type, count);
2930 cifs_buf_release(pSMB);
2937 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2938 const unsigned char *fileName,
2939 const char *local_acl, const int buflen,
2941 const struct nls_table *nls_codepage, int remap)
2943 struct smb_com_transaction2_spi_req *pSMB = NULL;
2944 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2948 int bytes_returned = 0;
2949 __u16 params, byte_count, data_count, param_offset, offset;
2951 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2953 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2957 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2959 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2960 PATH_MAX, nls_codepage, remap);
2961 name_len++; /* trailing null */
2963 } else { /* BB improve the check for buffer overruns BB */
2964 name_len = strnlen(fileName, PATH_MAX);
2965 name_len++; /* trailing null */
2966 strncpy(pSMB->FileName, fileName, name_len);
2968 params = 6 + name_len;
2969 pSMB->MaxParameterCount = cpu_to_le16(2);
2970 /* BB find max SMB size from sess */
2971 pSMB->MaxDataCount = cpu_to_le16(1000);
2972 pSMB->MaxSetupCount = 0;
2976 pSMB->Reserved2 = 0;
2977 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2978 InformationLevel) - 4;
2979 offset = param_offset + params;
2980 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2981 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2983 /* convert to on the wire format for POSIX ACL */
2984 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2986 if (data_count == 0) {
2988 goto setACLerrorExit;
2990 pSMB->DataOffset = cpu_to_le16(offset);
2991 pSMB->SetupCount = 1;
2992 pSMB->Reserved3 = 0;
2993 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2994 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2995 byte_count = 3 /* pad */ + params + data_count;
2996 pSMB->DataCount = cpu_to_le16(data_count);
2997 pSMB->TotalDataCount = pSMB->DataCount;
2998 pSMB->ParameterCount = cpu_to_le16(params);
2999 pSMB->TotalParameterCount = pSMB->ParameterCount;
3000 pSMB->Reserved4 = 0;
3001 pSMB->hdr.smb_buf_length += byte_count;
3002 pSMB->ByteCount = cpu_to_le16(byte_count);
3003 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3004 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3006 cFYI(1, ("Set POSIX ACL returned %d", rc));
3009 cifs_buf_release(pSMB);
3015 /* BB fix tabs in this function FIXME BB */
3017 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3018 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3021 struct smb_t2_qfi_req *pSMB = NULL;
3022 struct smb_t2_qfi_rsp *pSMBr = NULL;
3024 __u16 params, byte_count;
3026 cFYI(1, ("In GetExtAttr"));
3031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3036 params = 2 /* level */ + 2 /* fid */;
3037 pSMB->t2.TotalDataCount = 0;
3038 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3039 /* BB find exact max data count below from sess structure BB */
3040 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3041 pSMB->t2.MaxSetupCount = 0;
3042 pSMB->t2.Reserved = 0;
3044 pSMB->t2.Timeout = 0;
3045 pSMB->t2.Reserved2 = 0;
3046 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3048 pSMB->t2.DataCount = 0;
3049 pSMB->t2.DataOffset = 0;
3050 pSMB->t2.SetupCount = 1;
3051 pSMB->t2.Reserved3 = 0;
3052 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3053 byte_count = params + 1 /* pad */ ;
3054 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3055 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3056 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3059 pSMB->hdr.smb_buf_length += byte_count;
3060 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3062 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3063 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3065 cFYI(1, ("error %d in GetExtAttr", rc));
3067 /* decode response */
3068 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3069 if (rc || (pSMBr->ByteCount < 2))
3070 /* BB also check enough total bytes returned */
3071 /* If rc should we check for EOPNOSUPP and
3072 disable the srvino flag? or in caller? */
3073 rc = -EIO; /* bad smb */
3075 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3076 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3077 struct file_chattr_info *pfinfo;
3078 /* BB Do we need a cast or hash here ? */
3080 cFYI(1, ("Illegal size ret in GetExtAttr"));
3084 pfinfo = (struct file_chattr_info *)
3085 (data_offset + (char *) &pSMBr->hdr.Protocol);
3086 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3087 *pMask = le64_to_cpu(pfinfo->mask);
3091 cifs_buf_release(pSMB);
3093 goto GetExtAttrRetry;
3097 #endif /* CONFIG_POSIX */
3099 #ifdef CONFIG_CIFS_EXPERIMENTAL
3100 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3102 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3103 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3107 QUERY_SEC_DESC_REQ *pSMB;
3110 cFYI(1, ("GetCifsACL"));
3115 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3116 8 /* parm len */, tcon, (void **) &pSMB);
3120 pSMB->MaxParameterCount = cpu_to_le32(4);
3121 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3122 pSMB->MaxSetupCount = 0;
3123 pSMB->Fid = fid; /* file handle always le */
3124 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3126 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3127 pSMB->hdr.smb_buf_length += 11;
3128 iov[0].iov_base = (char *)pSMB;
3129 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3131 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3133 cifs_stats_inc(&tcon->num_acl_get);
3135 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3136 } else { /* decode response */
3140 struct smb_com_ntransact_rsp *pSMBr;
3143 /* validate_nttransact */
3144 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3145 &pdata, &parm_len, pbuflen);
3148 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3150 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3152 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3153 rc = -EIO; /* bad smb */
3158 /* BB check that data area is minimum length and as big as acl_len */
3160 acl_len = le32_to_cpu(*parm);
3161 if (acl_len != *pbuflen) {
3162 cERROR(1, ("acl length %d does not match %d",
3163 acl_len, *pbuflen));
3164 if (*pbuflen > acl_len)
3168 /* check if buffer is big enough for the acl
3169 header followed by the smallest SID */
3170 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3171 (*pbuflen >= 64 * 1024)) {
3172 cERROR(1, ("bad acl length %d", *pbuflen));
3176 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3177 if (*acl_inf == NULL) {
3181 memcpy(*acl_inf, pdata, *pbuflen);
3185 if (buf_type == CIFS_SMALL_BUFFER)
3186 cifs_small_buf_release(iov[0].iov_base);
3187 else if (buf_type == CIFS_LARGE_BUFFER)
3188 cifs_buf_release(iov[0].iov_base);
3189 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3194 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3195 struct cifs_ntsd *pntsd, __u32 acllen)
3197 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3199 int bytes_returned = 0;
3200 SET_SEC_DESC_REQ *pSMB = NULL;
3201 NTRANSACT_RSP *pSMBr = NULL;
3204 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3209 pSMB->MaxSetupCount = 0;
3213 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3214 data_count = acllen;
3215 data_offset = param_offset + param_count;
3216 byte_count = 3 /* pad */ + param_count;
3218 pSMB->DataCount = cpu_to_le32(data_count);
3219 pSMB->TotalDataCount = pSMB->DataCount;
3220 pSMB->MaxParameterCount = cpu_to_le32(4);
3221 pSMB->MaxDataCount = cpu_to_le32(16384);
3222 pSMB->ParameterCount = cpu_to_le32(param_count);
3223 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3224 pSMB->TotalParameterCount = pSMB->ParameterCount;
3225 pSMB->DataOffset = cpu_to_le32(data_offset);
3226 pSMB->SetupCount = 0;
3227 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3228 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3230 pSMB->Fid = fid; /* file handle always le */
3231 pSMB->Reserved2 = 0;
3232 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3234 if (pntsd && acllen) {
3235 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3238 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3241 pSMB->hdr.smb_buf_length += byte_count;
3243 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3244 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3246 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3248 cFYI(1, ("Set CIFS ACL returned %d", rc));
3249 cifs_buf_release(pSMB);
3252 goto setCifsAclRetry;
3257 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3259 /* Legacy Query Path Information call for lookup to old servers such
3261 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3262 const unsigned char *searchName,
3263 FILE_ALL_INFO *pFinfo,
3264 const struct nls_table *nls_codepage, int remap)
3266 QUERY_INFORMATION_REQ *pSMB;
3267 QUERY_INFORMATION_RSP *pSMBr;
3272 cFYI(1, ("In SMBQPath path %s", searchName));
3274 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3279 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3281 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3282 PATH_MAX, nls_codepage, remap);
3283 name_len++; /* trailing null */
3286 name_len = strnlen(searchName, PATH_MAX);
3287 name_len++; /* trailing null */
3288 strncpy(pSMB->FileName, searchName, name_len);
3290 pSMB->BufferFormat = 0x04;
3291 name_len++; /* account for buffer type byte */
3292 pSMB->hdr.smb_buf_length += (__u16) name_len;
3293 pSMB->ByteCount = cpu_to_le16(name_len);
3295 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3296 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3298 cFYI(1, ("Send error in QueryInfo = %d", rc));
3299 } else if (pFinfo) {
3301 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3303 /* decode response */
3304 /* BB FIXME - add time zone adjustment BB */
3305 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3308 /* decode time fields */
3309 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3310 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3311 pFinfo->LastAccessTime = 0;
3312 pFinfo->AllocationSize =
3313 cpu_to_le64(le32_to_cpu(pSMBr->size));
3314 pFinfo->EndOfFile = pFinfo->AllocationSize;
3315 pFinfo->Attributes =
3316 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3318 rc = -EIO; /* bad buffer passed in */
3320 cifs_buf_release(pSMB);
3332 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3333 const unsigned char *searchName,
3334 FILE_ALL_INFO *pFindData,
3335 int legacy /* old style infolevel */,
3336 const struct nls_table *nls_codepage, int remap)
3338 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3339 TRANSACTION2_QPI_REQ *pSMB = NULL;
3340 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3344 __u16 params, byte_count;
3346 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3348 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3353 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3355 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3356 PATH_MAX, nls_codepage, remap);
3357 name_len++; /* trailing null */
3359 } else { /* BB improve the check for buffer overruns BB */
3360 name_len = strnlen(searchName, PATH_MAX);
3361 name_len++; /* trailing null */
3362 strncpy(pSMB->FileName, searchName, name_len);
3365 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3366 pSMB->TotalDataCount = 0;
3367 pSMB->MaxParameterCount = cpu_to_le16(2);
3368 /* BB find exact max SMB PDU from sess structure BB */
3369 pSMB->MaxDataCount = cpu_to_le16(4000);
3370 pSMB->MaxSetupCount = 0;
3374 pSMB->Reserved2 = 0;
3375 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3376 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3377 pSMB->DataCount = 0;
3378 pSMB->DataOffset = 0;
3379 pSMB->SetupCount = 1;
3380 pSMB->Reserved3 = 0;
3381 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3382 byte_count = params + 1 /* pad */ ;
3383 pSMB->TotalParameterCount = cpu_to_le16(params);
3384 pSMB->ParameterCount = pSMB->TotalParameterCount;
3386 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3388 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3389 pSMB->Reserved4 = 0;
3390 pSMB->hdr.smb_buf_length += byte_count;
3391 pSMB->ByteCount = cpu_to_le16(byte_count);
3393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3396 cFYI(1, ("Send error in QPathInfo = %d", rc));
3397 } else { /* decode response */
3398 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3400 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3402 else if (!legacy && (pSMBr->ByteCount < 40))
3403 rc = -EIO; /* bad smb */
3404 else if (legacy && (pSMBr->ByteCount < 24))
3405 rc = -EIO; /* 24 or 26 expected but we do not read
3407 else if (pFindData) {
3409 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3411 /* On legacy responses we do not read the last field,
3412 EAsize, fortunately since it varies by subdialect and
3413 also note it differs on Set vs. Get, ie two bytes or 4
3414 bytes depending but we don't care here */
3416 size = sizeof(FILE_INFO_STANDARD);
3418 size = sizeof(FILE_ALL_INFO);
3419 memcpy((char *) pFindData,
3420 (char *) &pSMBr->hdr.Protocol +
3425 cifs_buf_release(pSMB);
3427 goto QPathInfoRetry;
3433 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3434 const unsigned char *searchName,
3435 FILE_UNIX_BASIC_INFO *pFindData,
3436 const struct nls_table *nls_codepage, int remap)
3438 /* SMB_QUERY_FILE_UNIX_BASIC */
3439 TRANSACTION2_QPI_REQ *pSMB = NULL;
3440 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3442 int bytes_returned = 0;
3444 __u16 params, byte_count;
3446 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3448 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3453 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3455 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3456 PATH_MAX, nls_codepage, remap);
3457 name_len++; /* trailing null */
3459 } else { /* BB improve the check for buffer overruns BB */
3460 name_len = strnlen(searchName, PATH_MAX);
3461 name_len++; /* trailing null */
3462 strncpy(pSMB->FileName, searchName, name_len);
3465 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3466 pSMB->TotalDataCount = 0;
3467 pSMB->MaxParameterCount = cpu_to_le16(2);
3468 /* BB find exact max SMB PDU from sess structure BB */
3469 pSMB->MaxDataCount = cpu_to_le16(4000);
3470 pSMB->MaxSetupCount = 0;
3474 pSMB->Reserved2 = 0;
3475 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3476 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3477 pSMB->DataCount = 0;
3478 pSMB->DataOffset = 0;
3479 pSMB->SetupCount = 1;
3480 pSMB->Reserved3 = 0;
3481 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3482 byte_count = params + 1 /* pad */ ;
3483 pSMB->TotalParameterCount = cpu_to_le16(params);
3484 pSMB->ParameterCount = pSMB->TotalParameterCount;
3485 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3486 pSMB->Reserved4 = 0;
3487 pSMB->hdr.smb_buf_length += byte_count;
3488 pSMB->ByteCount = cpu_to_le16(byte_count);
3490 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3491 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3493 cFYI(1, ("Send error in QPathInfo = %d", rc));
3494 } else { /* decode response */
3495 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3497 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3498 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3499 "Unix Extensions can be disabled on mount "
3500 "by specifying the nosfu mount option."));
3501 rc = -EIO; /* bad smb */
3503 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3504 memcpy((char *) pFindData,
3505 (char *) &pSMBr->hdr.Protocol +
3507 sizeof(FILE_UNIX_BASIC_INFO));
3510 cifs_buf_release(pSMB);
3512 goto UnixQPathInfoRetry;
3517 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3519 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3520 const char *searchName,
3521 const struct nls_table *nls_codepage,
3523 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3525 /* level 257 SMB_ */
3526 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3527 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3528 T2_FFIRST_RSP_PARMS *parms;
3530 int bytes_returned = 0;
3532 __u16 params, byte_count;
3534 cFYI(1, ("In FindFirst for %s", searchName));
3537 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3542 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3544 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3545 PATH_MAX, nls_codepage, remap);
3546 /* We can not add the asterik earlier in case
3547 it got remapped to 0xF03A as if it were part of the
3548 directory name instead of a wildcard */
3550 pSMB->FileName[name_len] = dirsep;
3551 pSMB->FileName[name_len+1] = 0;
3552 pSMB->FileName[name_len+2] = '*';
3553 pSMB->FileName[name_len+3] = 0;
3554 name_len += 4; /* now the trailing null */
3555 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3556 pSMB->FileName[name_len+1] = 0;
3558 } else { /* BB add check for overrun of SMB buf BB */
3559 name_len = strnlen(searchName, PATH_MAX);
3560 /* BB fix here and in unicode clause above ie
3561 if (name_len > buffersize-header)
3562 free buffer exit; BB */
3563 strncpy(pSMB->FileName, searchName, name_len);
3564 pSMB->FileName[name_len] = dirsep;
3565 pSMB->FileName[name_len+1] = '*';
3566 pSMB->FileName[name_len+2] = 0;
3570 params = 12 + name_len /* includes null */ ;
3571 pSMB->TotalDataCount = 0; /* no EAs */
3572 pSMB->MaxParameterCount = cpu_to_le16(10);
3573 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3574 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3575 pSMB->MaxSetupCount = 0;
3579 pSMB->Reserved2 = 0;
3580 byte_count = params + 1 /* pad */ ;
3581 pSMB->TotalParameterCount = cpu_to_le16(params);
3582 pSMB->ParameterCount = pSMB->TotalParameterCount;
3583 pSMB->ParameterOffset = cpu_to_le16(
3584 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3586 pSMB->DataCount = 0;
3587 pSMB->DataOffset = 0;
3588 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3589 pSMB->Reserved3 = 0;
3590 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3591 pSMB->SearchAttributes =
3592 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3594 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3595 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3596 CIFS_SEARCH_RETURN_RESUME);
3597 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3599 /* BB what should we set StorageType to? Does it matter? BB */
3600 pSMB->SearchStorageType = 0;
3601 pSMB->hdr.smb_buf_length += byte_count;
3602 pSMB->ByteCount = cpu_to_le16(byte_count);
3604 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3605 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3606 cifs_stats_inc(&tcon->num_ffirst);
3608 if (rc) {/* BB add logic to retry regular search if Unix search
3609 rejected unexpectedly by server */
3610 /* BB Add code to handle unsupported level rc */
3611 cFYI(1, ("Error in FindFirst = %d", rc));
3613 cifs_buf_release(pSMB);
3615 /* BB eventually could optimize out free and realloc of buf */
3618 goto findFirstRetry;
3619 } else { /* decode response */
3620 /* BB remember to free buffer if error BB */
3621 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3625 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3626 psrch_inf->unicode = true;
3628 psrch_inf->unicode = false;
3630 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3631 psrch_inf->smallBuf = 0;
3632 psrch_inf->srch_entries_start =
3633 (char *) &pSMBr->hdr.Protocol +
3634 le16_to_cpu(pSMBr->t2.DataOffset);
3635 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3636 le16_to_cpu(pSMBr->t2.ParameterOffset));
3638 if (parms->EndofSearch)
3639 psrch_inf->endOfSearch = true;
3641 psrch_inf->endOfSearch = false;
3643 psrch_inf->entries_in_buffer =
3644 le16_to_cpu(parms->SearchCount);
3645 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3646 psrch_inf->entries_in_buffer;
3647 lnoff = le16_to_cpu(parms->LastNameOffset);
3648 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3650 cERROR(1, ("ignoring corrupt resume name"));
3651 psrch_inf->last_entry = NULL;
3655 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3658 *pnetfid = parms->SearchHandle;
3660 cifs_buf_release(pSMB);
3667 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3668 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3670 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3671 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3672 T2_FNEXT_RSP_PARMS *parms;
3673 char *response_data;
3675 int bytes_returned, name_len;
3676 __u16 params, byte_count;
3678 cFYI(1, ("In FindNext"));
3680 if (psrch_inf->endOfSearch)
3683 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3688 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3690 pSMB->TotalDataCount = 0; /* no EAs */
3691 pSMB->MaxParameterCount = cpu_to_le16(8);
3692 pSMB->MaxDataCount =
3693 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3695 pSMB->MaxSetupCount = 0;
3699 pSMB->Reserved2 = 0;
3700 pSMB->ParameterOffset = cpu_to_le16(
3701 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3702 pSMB->DataCount = 0;
3703 pSMB->DataOffset = 0;
3704 pSMB->SetupCount = 1;
3705 pSMB->Reserved3 = 0;
3706 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3707 pSMB->SearchHandle = searchHandle; /* always kept as le */
3709 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3710 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3711 pSMB->ResumeKey = psrch_inf->resume_key;
3713 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3715 name_len = psrch_inf->resume_name_len;
3717 if (name_len < PATH_MAX) {
3718 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3719 byte_count += name_len;
3720 /* 14 byte parm len above enough for 2 byte null terminator */
3721 pSMB->ResumeFileName[name_len] = 0;
3722 pSMB->ResumeFileName[name_len+1] = 0;
3725 goto FNext2_err_exit;
3727 byte_count = params + 1 /* pad */ ;
3728 pSMB->TotalParameterCount = cpu_to_le16(params);
3729 pSMB->ParameterCount = pSMB->TotalParameterCount;
3730 pSMB->hdr.smb_buf_length += byte_count;
3731 pSMB->ByteCount = cpu_to_le16(byte_count);
3733 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3734 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3735 cifs_stats_inc(&tcon->num_fnext);
3738 psrch_inf->endOfSearch = true;
3739 cifs_buf_release(pSMB);
3740 rc = 0; /* search probably was closed at end of search*/
3742 cFYI(1, ("FindNext returned = %d", rc));
3743 } else { /* decode response */
3744 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3749 /* BB fixme add lock for file (srch_info) struct here */
3750 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3751 psrch_inf->unicode = true;
3753 psrch_inf->unicode = false;
3754 response_data = (char *) &pSMBr->hdr.Protocol +
3755 le16_to_cpu(pSMBr->t2.ParameterOffset);
3756 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3757 response_data = (char *)&pSMBr->hdr.Protocol +
3758 le16_to_cpu(pSMBr->t2.DataOffset);
3759 if (psrch_inf->smallBuf)
3760 cifs_small_buf_release(
3761 psrch_inf->ntwrk_buf_start);
3763 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3764 psrch_inf->srch_entries_start = response_data;
3765 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3766 psrch_inf->smallBuf = 0;
3767 if (parms->EndofSearch)
3768 psrch_inf->endOfSearch = true;
3770 psrch_inf->endOfSearch = false;
3771 psrch_inf->entries_in_buffer =
3772 le16_to_cpu(parms->SearchCount);
3773 psrch_inf->index_of_last_entry +=
3774 psrch_inf->entries_in_buffer;
3775 lnoff = le16_to_cpu(parms->LastNameOffset);
3776 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3778 cERROR(1, ("ignoring corrupt resume name"));
3779 psrch_inf->last_entry = NULL;
3782 psrch_inf->last_entry =
3783 psrch_inf->srch_entries_start + lnoff;
3785 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3786 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3788 /* BB fixme add unlock here */
3793 /* BB On error, should we leave previous search buf (and count and
3794 last entry fields) intact or free the previous one? */
3796 /* Note: On -EAGAIN error only caller can retry on handle based calls
3797 since file handle passed in no longer valid */
3800 cifs_buf_release(pSMB);
3805 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3806 const __u16 searchHandle)
3809 FINDCLOSE_REQ *pSMB = NULL;
3811 cFYI(1, ("In CIFSSMBFindClose"));
3812 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3814 /* no sense returning error if session restarted
3815 as file handle has been closed */
3821 pSMB->FileID = searchHandle;
3822 pSMB->ByteCount = 0;
3823 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3825 cERROR(1, ("Send error in FindClose = %d", rc));
3827 cifs_stats_inc(&tcon->num_fclose);
3829 /* Since session is dead, search handle closed on server already */
3837 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3838 const unsigned char *searchName,
3839 __u64 *inode_number,
3840 const struct nls_table *nls_codepage, int remap)
3843 TRANSACTION2_QPI_REQ *pSMB = NULL;
3844 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3845 int name_len, bytes_returned;
3846 __u16 params, byte_count;
3848 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3852 GetInodeNumberRetry:
3853 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3858 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3860 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3861 PATH_MAX, nls_codepage, remap);
3862 name_len++; /* trailing null */
3864 } else { /* BB improve the check for buffer overruns BB */
3865 name_len = strnlen(searchName, PATH_MAX);
3866 name_len++; /* trailing null */
3867 strncpy(pSMB->FileName, searchName, name_len);
3870 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3871 pSMB->TotalDataCount = 0;
3872 pSMB->MaxParameterCount = cpu_to_le16(2);
3873 /* BB find exact max data count below from sess structure BB */
3874 pSMB->MaxDataCount = cpu_to_le16(4000);
3875 pSMB->MaxSetupCount = 0;
3879 pSMB->Reserved2 = 0;
3880 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3881 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3882 pSMB->DataCount = 0;
3883 pSMB->DataOffset = 0;
3884 pSMB->SetupCount = 1;
3885 pSMB->Reserved3 = 0;
3886 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3887 byte_count = params + 1 /* pad */ ;
3888 pSMB->TotalParameterCount = cpu_to_le16(params);
3889 pSMB->ParameterCount = pSMB->TotalParameterCount;
3890 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3891 pSMB->Reserved4 = 0;
3892 pSMB->hdr.smb_buf_length += byte_count;
3893 pSMB->ByteCount = cpu_to_le16(byte_count);
3895 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3896 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3898 cFYI(1, ("error %d in QueryInternalInfo", rc));
3900 /* decode response */
3901 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3902 if (rc || (pSMBr->ByteCount < 2))
3903 /* BB also check enough total bytes returned */
3904 /* If rc should we check for EOPNOSUPP and
3905 disable the srvino flag? or in caller? */
3906 rc = -EIO; /* bad smb */
3908 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3909 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3910 struct file_internal_info *pfinfo;
3911 /* BB Do we need a cast or hash here ? */
3913 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3915 goto GetInodeNumOut;
3917 pfinfo = (struct file_internal_info *)
3918 (data_offset + (char *) &pSMBr->hdr.Protocol);
3919 *inode_number = pfinfo->UniqueId;
3923 cifs_buf_release(pSMB);
3925 goto GetInodeNumberRetry;
3929 /* parses DFS refferal V3 structure
3930 * caller is responsible for freeing target_nodes
3933 * on failure - errno
3936 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3937 unsigned int *num_of_nodes,
3938 struct dfs_info3_param **target_nodes,
3939 const struct nls_table *nls_codepage)
3944 struct dfs_referral_level_3 *ref;
3946 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3950 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3952 if (*num_of_nodes < 1) {
3953 cERROR(1, ("num_referrals: must be at least > 0,"
3954 "but we get num_referrals = %d\n", *num_of_nodes));
3956 goto parse_DFS_referrals_exit;
3959 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3960 if (ref->VersionNumber != cpu_to_le16(3)) {
3961 cERROR(1, ("Referrals of V%d version are not supported,"
3962 "should be V3", le16_to_cpu(ref->VersionNumber)));
3964 goto parse_DFS_referrals_exit;
3967 /* get the upper boundary of the resp buffer */
3968 data_end = (char *)(&(pSMBr->PathConsumed)) +
3969 le16_to_cpu(pSMBr->t2.DataCount);
3971 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3973 le16_to_cpu(pSMBr->DFSFlags)));
3975 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3976 *num_of_nodes, GFP_KERNEL);
3977 if (*target_nodes == NULL) {
3978 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3980 goto parse_DFS_referrals_exit;
3983 /* collect neccessary data from referrals */
3984 for (i = 0; i < *num_of_nodes; i++) {
3987 struct dfs_info3_param *node = (*target_nodes)+i;
3989 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3990 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3991 node->server_type = le16_to_cpu(ref->ServerType);
3992 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3995 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3996 max_len = data_end - temp;
3997 rc = cifs_strncpy_to_host(&(node->path_name), temp,
3998 max_len, is_unicode, nls_codepage);
4000 goto parse_DFS_referrals_exit;
4002 /* copy link target UNC */
4003 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4004 max_len = data_end - temp;
4005 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4006 max_len, is_unicode, nls_codepage);
4008 goto parse_DFS_referrals_exit;
4010 ref += le16_to_cpu(ref->Size);
4013 parse_DFS_referrals_exit:
4015 free_dfs_info_array(*target_nodes, *num_of_nodes);
4016 *target_nodes = NULL;
4023 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4024 const unsigned char *searchName,
4025 struct dfs_info3_param **target_nodes,
4026 unsigned int *num_of_nodes,
4027 const struct nls_table *nls_codepage, int remap)
4029 /* TRANS2_GET_DFS_REFERRAL */
4030 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4031 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4035 __u16 params, byte_count;
4037 *target_nodes = NULL;
4039 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4043 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4048 /* server pointer checked in called function,
4049 but should never be null here anyway */
4050 pSMB->hdr.Mid = GetNextMid(ses->server);
4051 pSMB->hdr.Tid = ses->ipc_tid;
4052 pSMB->hdr.Uid = ses->Suid;
4053 if (ses->capabilities & CAP_STATUS32)
4054 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4055 if (ses->capabilities & CAP_DFS)
4056 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4058 if (ses->capabilities & CAP_UNICODE) {
4059 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4061 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4062 searchName, PATH_MAX, nls_codepage, remap);
4063 name_len++; /* trailing null */
4065 } else { /* BB improve the check for buffer overruns BB */
4066 name_len = strnlen(searchName, PATH_MAX);
4067 name_len++; /* trailing null */
4068 strncpy(pSMB->RequestFileName, searchName, name_len);
4072 if (ses->server->secMode &
4073 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4074 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4077 pSMB->hdr.Uid = ses->Suid;
4079 params = 2 /* level */ + name_len /*includes null */ ;
4080 pSMB->TotalDataCount = 0;
4081 pSMB->DataCount = 0;
4082 pSMB->DataOffset = 0;
4083 pSMB->MaxParameterCount = 0;
4084 /* BB find exact max SMB PDU from sess structure BB */
4085 pSMB->MaxDataCount = cpu_to_le16(4000);
4086 pSMB->MaxSetupCount = 0;
4090 pSMB->Reserved2 = 0;
4091 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4092 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4093 pSMB->SetupCount = 1;
4094 pSMB->Reserved3 = 0;
4095 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4096 byte_count = params + 3 /* pad */ ;
4097 pSMB->ParameterCount = cpu_to_le16(params);
4098 pSMB->TotalParameterCount = pSMB->ParameterCount;
4099 pSMB->MaxReferralLevel = cpu_to_le16(3);
4100 pSMB->hdr.smb_buf_length += byte_count;
4101 pSMB->ByteCount = cpu_to_le16(byte_count);
4103 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4104 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4106 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4109 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4111 /* BB Also check if enough total bytes returned? */
4112 if (rc || (pSMBr->ByteCount < 17)) {
4113 rc = -EIO; /* bad smb */
4117 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4119 le16_to_cpu(pSMBr->t2.DataOffset)));
4121 /* parse returned result into more usable form */
4122 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4123 target_nodes, nls_codepage);
4126 cifs_buf_release(pSMB);
4134 /* Query File System Info such as free space to old servers such as Win 9x */
4136 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4138 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4139 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4140 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4141 FILE_SYSTEM_ALLOC_INFO *response_data;
4143 int bytes_returned = 0;
4144 __u16 params, byte_count;
4146 cFYI(1, ("OldQFSInfo"));
4148 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4153 params = 2; /* level */
4154 pSMB->TotalDataCount = 0;
4155 pSMB->MaxParameterCount = cpu_to_le16(2);
4156 pSMB->MaxDataCount = cpu_to_le16(1000);
4157 pSMB->MaxSetupCount = 0;
4161 pSMB->Reserved2 = 0;
4162 byte_count = params + 1 /* pad */ ;
4163 pSMB->TotalParameterCount = cpu_to_le16(params);
4164 pSMB->ParameterCount = pSMB->TotalParameterCount;
4165 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4166 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4167 pSMB->DataCount = 0;
4168 pSMB->DataOffset = 0;
4169 pSMB->SetupCount = 1;
4170 pSMB->Reserved3 = 0;
4171 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4172 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4173 pSMB->hdr.smb_buf_length += byte_count;
4174 pSMB->ByteCount = cpu_to_le16(byte_count);
4176 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4177 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4179 cFYI(1, ("Send error in QFSInfo = %d", rc));
4180 } else { /* decode response */
4181 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4183 if (rc || (pSMBr->ByteCount < 18))
4184 rc = -EIO; /* bad smb */
4186 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4187 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4188 pSMBr->ByteCount, data_offset));
4190 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4191 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4193 le16_to_cpu(response_data->BytesPerSector) *
4194 le32_to_cpu(response_data->
4195 SectorsPerAllocationUnit);
4197 le32_to_cpu(response_data->TotalAllocationUnits);
4198 FSData->f_bfree = FSData->f_bavail =
4199 le32_to_cpu(response_data->FreeAllocationUnits);
4201 ("Blocks: %lld Free: %lld Block size %ld",
4202 (unsigned long long)FSData->f_blocks,
4203 (unsigned long long)FSData->f_bfree,
4207 cifs_buf_release(pSMB);
4210 goto oldQFSInfoRetry;
4216 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4218 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4219 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4220 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4221 FILE_SYSTEM_INFO *response_data;
4223 int bytes_returned = 0;
4224 __u16 params, byte_count;
4226 cFYI(1, ("In QFSInfo"));
4228 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4233 params = 2; /* level */
4234 pSMB->TotalDataCount = 0;
4235 pSMB->MaxParameterCount = cpu_to_le16(2);
4236 pSMB->MaxDataCount = cpu_to_le16(1000);
4237 pSMB->MaxSetupCount = 0;
4241 pSMB->Reserved2 = 0;
4242 byte_count = params + 1 /* pad */ ;
4243 pSMB->TotalParameterCount = cpu_to_le16(params);
4244 pSMB->ParameterCount = pSMB->TotalParameterCount;
4245 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4246 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4247 pSMB->DataCount = 0;
4248 pSMB->DataOffset = 0;
4249 pSMB->SetupCount = 1;
4250 pSMB->Reserved3 = 0;
4251 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4252 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4253 pSMB->hdr.smb_buf_length += byte_count;
4254 pSMB->ByteCount = cpu_to_le16(byte_count);
4256 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4257 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4259 cFYI(1, ("Send error in QFSInfo = %d", rc));
4260 } else { /* decode response */
4261 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4263 if (rc || (pSMBr->ByteCount < 24))
4264 rc = -EIO; /* bad smb */
4266 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4270 *) (((char *) &pSMBr->hdr.Protocol) +
4273 le32_to_cpu(response_data->BytesPerSector) *
4274 le32_to_cpu(response_data->
4275 SectorsPerAllocationUnit);
4277 le64_to_cpu(response_data->TotalAllocationUnits);
4278 FSData->f_bfree = FSData->f_bavail =
4279 le64_to_cpu(response_data->FreeAllocationUnits);
4281 ("Blocks: %lld Free: %lld Block size %ld",
4282 (unsigned long long)FSData->f_blocks,
4283 (unsigned long long)FSData->f_bfree,
4287 cifs_buf_release(pSMB);
4296 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4298 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4299 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4300 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4301 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4303 int bytes_returned = 0;
4304 __u16 params, byte_count;
4306 cFYI(1, ("In QFSAttributeInfo"));
4308 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4313 params = 2; /* level */
4314 pSMB->TotalDataCount = 0;
4315 pSMB->MaxParameterCount = cpu_to_le16(2);
4316 /* BB find exact max SMB PDU from sess structure BB */
4317 pSMB->MaxDataCount = cpu_to_le16(1000);
4318 pSMB->MaxSetupCount = 0;
4322 pSMB->Reserved2 = 0;
4323 byte_count = params + 1 /* pad */ ;
4324 pSMB->TotalParameterCount = cpu_to_le16(params);
4325 pSMB->ParameterCount = pSMB->TotalParameterCount;
4326 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4327 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4328 pSMB->DataCount = 0;
4329 pSMB->DataOffset = 0;
4330 pSMB->SetupCount = 1;
4331 pSMB->Reserved3 = 0;
4332 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4333 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4334 pSMB->hdr.smb_buf_length += byte_count;
4335 pSMB->ByteCount = cpu_to_le16(byte_count);
4337 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4338 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4340 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4341 } else { /* decode response */
4342 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4344 if (rc || (pSMBr->ByteCount < 13)) {
4345 /* BB also check if enough bytes returned */
4346 rc = -EIO; /* bad smb */
4348 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4350 (FILE_SYSTEM_ATTRIBUTE_INFO
4351 *) (((char *) &pSMBr->hdr.Protocol) +
4353 memcpy(&tcon->fsAttrInfo, response_data,
4354 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4357 cifs_buf_release(pSMB);
4360 goto QFSAttributeRetry;
4366 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4368 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4369 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4370 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4371 FILE_SYSTEM_DEVICE_INFO *response_data;
4373 int bytes_returned = 0;
4374 __u16 params, byte_count;
4376 cFYI(1, ("In QFSDeviceInfo"));
4378 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4383 params = 2; /* level */
4384 pSMB->TotalDataCount = 0;
4385 pSMB->MaxParameterCount = cpu_to_le16(2);
4386 /* BB find exact max SMB PDU from sess structure BB */
4387 pSMB->MaxDataCount = cpu_to_le16(1000);
4388 pSMB->MaxSetupCount = 0;
4392 pSMB->Reserved2 = 0;
4393 byte_count = params + 1 /* pad */ ;
4394 pSMB->TotalParameterCount = cpu_to_le16(params);
4395 pSMB->ParameterCount = pSMB->TotalParameterCount;
4396 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4397 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4399 pSMB->DataCount = 0;
4400 pSMB->DataOffset = 0;
4401 pSMB->SetupCount = 1;
4402 pSMB->Reserved3 = 0;
4403 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4404 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4405 pSMB->hdr.smb_buf_length += byte_count;
4406 pSMB->ByteCount = cpu_to_le16(byte_count);
4408 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4409 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4411 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4412 } else { /* decode response */
4413 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4415 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4416 rc = -EIO; /* bad smb */
4418 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4420 (FILE_SYSTEM_DEVICE_INFO *)
4421 (((char *) &pSMBr->hdr.Protocol) +
4423 memcpy(&tcon->fsDevInfo, response_data,
4424 sizeof(FILE_SYSTEM_DEVICE_INFO));
4427 cifs_buf_release(pSMB);
4430 goto QFSDeviceRetry;
4436 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4438 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4439 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4440 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4441 FILE_SYSTEM_UNIX_INFO *response_data;
4443 int bytes_returned = 0;
4444 __u16 params, byte_count;
4446 cFYI(1, ("In QFSUnixInfo"));
4448 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4453 params = 2; /* level */
4454 pSMB->TotalDataCount = 0;
4455 pSMB->DataCount = 0;
4456 pSMB->DataOffset = 0;
4457 pSMB->MaxParameterCount = cpu_to_le16(2);
4458 /* BB find exact max SMB PDU from sess structure BB */
4459 pSMB->MaxDataCount = cpu_to_le16(100);
4460 pSMB->MaxSetupCount = 0;
4464 pSMB->Reserved2 = 0;
4465 byte_count = params + 1 /* pad */ ;
4466 pSMB->ParameterCount = cpu_to_le16(params);
4467 pSMB->TotalParameterCount = pSMB->ParameterCount;
4468 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4469 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4470 pSMB->SetupCount = 1;
4471 pSMB->Reserved3 = 0;
4472 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4473 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4474 pSMB->hdr.smb_buf_length += byte_count;
4475 pSMB->ByteCount = cpu_to_le16(byte_count);
4477 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4478 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4480 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4481 } else { /* decode response */
4482 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4484 if (rc || (pSMBr->ByteCount < 13)) {
4485 rc = -EIO; /* bad smb */
4487 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4489 (FILE_SYSTEM_UNIX_INFO
4490 *) (((char *) &pSMBr->hdr.Protocol) +
4492 memcpy(&tcon->fsUnixInfo, response_data,
4493 sizeof(FILE_SYSTEM_UNIX_INFO));
4496 cifs_buf_release(pSMB);
4506 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4508 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4509 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4510 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4512 int bytes_returned = 0;
4513 __u16 params, param_offset, offset, byte_count;
4515 cFYI(1, ("In SETFSUnixInfo"));
4517 /* BB switch to small buf init to save memory */
4518 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4523 params = 4; /* 2 bytes zero followed by info level. */
4524 pSMB->MaxSetupCount = 0;
4528 pSMB->Reserved2 = 0;
4529 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4531 offset = param_offset + params;
4533 pSMB->MaxParameterCount = cpu_to_le16(4);
4534 /* BB find exact max SMB PDU from sess structure BB */
4535 pSMB->MaxDataCount = cpu_to_le16(100);
4536 pSMB->SetupCount = 1;
4537 pSMB->Reserved3 = 0;
4538 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4539 byte_count = 1 /* pad */ + params + 12;
4541 pSMB->DataCount = cpu_to_le16(12);
4542 pSMB->ParameterCount = cpu_to_le16(params);
4543 pSMB->TotalDataCount = pSMB->DataCount;
4544 pSMB->TotalParameterCount = pSMB->ParameterCount;
4545 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4546 pSMB->DataOffset = cpu_to_le16(offset);
4550 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4553 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4554 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4555 pSMB->ClientUnixCap = cpu_to_le64(cap);
4557 pSMB->hdr.smb_buf_length += byte_count;
4558 pSMB->ByteCount = cpu_to_le16(byte_count);
4560 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4561 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4563 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4564 } else { /* decode response */
4565 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4567 rc = -EIO; /* bad smb */
4569 cifs_buf_release(pSMB);
4572 goto SETFSUnixRetry;
4580 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4581 struct kstatfs *FSData)
4583 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4584 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4585 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4586 FILE_SYSTEM_POSIX_INFO *response_data;
4588 int bytes_returned = 0;
4589 __u16 params, byte_count;
4591 cFYI(1, ("In QFSPosixInfo"));
4593 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4598 params = 2; /* level */
4599 pSMB->TotalDataCount = 0;
4600 pSMB->DataCount = 0;
4601 pSMB->DataOffset = 0;
4602 pSMB->MaxParameterCount = cpu_to_le16(2);
4603 /* BB find exact max SMB PDU from sess structure BB */
4604 pSMB->MaxDataCount = cpu_to_le16(100);
4605 pSMB->MaxSetupCount = 0;
4609 pSMB->Reserved2 = 0;
4610 byte_count = params + 1 /* pad */ ;
4611 pSMB->ParameterCount = cpu_to_le16(params);
4612 pSMB->TotalParameterCount = pSMB->ParameterCount;
4613 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4614 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4615 pSMB->SetupCount = 1;
4616 pSMB->Reserved3 = 0;
4617 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4618 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4619 pSMB->hdr.smb_buf_length += byte_count;
4620 pSMB->ByteCount = cpu_to_le16(byte_count);
4622 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4623 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4625 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4626 } else { /* decode response */
4627 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4629 if (rc || (pSMBr->ByteCount < 13)) {
4630 rc = -EIO; /* bad smb */
4632 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4634 (FILE_SYSTEM_POSIX_INFO
4635 *) (((char *) &pSMBr->hdr.Protocol) +
4638 le32_to_cpu(response_data->BlockSize);
4640 le64_to_cpu(response_data->TotalBlocks);
4642 le64_to_cpu(response_data->BlocksAvail);
4643 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4644 FSData->f_bavail = FSData->f_bfree;
4647 le64_to_cpu(response_data->UserBlocksAvail);
4649 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4651 le64_to_cpu(response_data->TotalFileNodes);
4652 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4654 le64_to_cpu(response_data->FreeFileNodes);
4657 cifs_buf_release(pSMB);
4666 /* We can not use write of zero bytes trick to
4667 set file size due to need for large file support. Also note that
4668 this SetPathInfo is preferred to SetFileInfo based method in next
4669 routine which is only needed to work around a sharing violation bug
4670 in Samba which this routine can run into */
4673 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4674 __u64 size, bool SetAllocation,
4675 const struct nls_table *nls_codepage, int remap)
4677 struct smb_com_transaction2_spi_req *pSMB = NULL;
4678 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4679 struct file_end_of_file_info *parm_data;
4682 int bytes_returned = 0;
4683 __u16 params, byte_count, data_count, param_offset, offset;
4685 cFYI(1, ("In SetEOF"));
4687 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4692 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4694 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4695 PATH_MAX, nls_codepage, remap);
4696 name_len++; /* trailing null */
4698 } else { /* BB improve the check for buffer overruns BB */
4699 name_len = strnlen(fileName, PATH_MAX);
4700 name_len++; /* trailing null */
4701 strncpy(pSMB->FileName, fileName, name_len);
4703 params = 6 + name_len;
4704 data_count = sizeof(struct file_end_of_file_info);
4705 pSMB->MaxParameterCount = cpu_to_le16(2);
4706 pSMB->MaxDataCount = cpu_to_le16(4100);
4707 pSMB->MaxSetupCount = 0;
4711 pSMB->Reserved2 = 0;
4712 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4713 InformationLevel) - 4;
4714 offset = param_offset + params;
4715 if (SetAllocation) {
4716 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4717 pSMB->InformationLevel =
4718 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4720 pSMB->InformationLevel =
4721 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4722 } else /* Set File Size */ {
4723 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4724 pSMB->InformationLevel =
4725 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4727 pSMB->InformationLevel =
4728 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4732 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4734 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4735 pSMB->DataOffset = cpu_to_le16(offset);
4736 pSMB->SetupCount = 1;
4737 pSMB->Reserved3 = 0;
4738 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4739 byte_count = 3 /* pad */ + params + data_count;
4740 pSMB->DataCount = cpu_to_le16(data_count);
4741 pSMB->TotalDataCount = pSMB->DataCount;
4742 pSMB->ParameterCount = cpu_to_le16(params);
4743 pSMB->TotalParameterCount = pSMB->ParameterCount;
4744 pSMB->Reserved4 = 0;
4745 pSMB->hdr.smb_buf_length += byte_count;
4746 parm_data->FileSize = cpu_to_le64(size);
4747 pSMB->ByteCount = cpu_to_le16(byte_count);
4748 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4749 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4751 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4753 cifs_buf_release(pSMB);
4762 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4763 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4765 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4767 struct file_end_of_file_info *parm_data;
4769 __u16 params, param_offset, offset, byte_count, count;
4771 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4773 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4778 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4779 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4782 pSMB->MaxSetupCount = 0;
4786 pSMB->Reserved2 = 0;
4787 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4788 offset = param_offset + params;
4790 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4792 count = sizeof(struct file_end_of_file_info);
4793 pSMB->MaxParameterCount = cpu_to_le16(2);
4794 /* BB find exact max SMB PDU from sess structure BB */
4795 pSMB->MaxDataCount = cpu_to_le16(1000);
4796 pSMB->SetupCount = 1;
4797 pSMB->Reserved3 = 0;
4798 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4799 byte_count = 3 /* pad */ + params + count;
4800 pSMB->DataCount = cpu_to_le16(count);
4801 pSMB->ParameterCount = cpu_to_le16(params);
4802 pSMB->TotalDataCount = pSMB->DataCount;
4803 pSMB->TotalParameterCount = pSMB->ParameterCount;
4804 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4806 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4808 pSMB->DataOffset = cpu_to_le16(offset);
4809 parm_data->FileSize = cpu_to_le64(size);
4811 if (SetAllocation) {
4812 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4813 pSMB->InformationLevel =
4814 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4816 pSMB->InformationLevel =
4817 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4818 } else /* Set File Size */ {
4819 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4820 pSMB->InformationLevel =
4821 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4823 pSMB->InformationLevel =
4824 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4826 pSMB->Reserved4 = 0;
4827 pSMB->hdr.smb_buf_length += byte_count;
4828 pSMB->ByteCount = cpu_to_le16(byte_count);
4829 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4832 ("Send error in SetFileInfo (SetFileSize) = %d",
4836 /* Note: On -EAGAIN error only caller can retry on handle based calls
4837 since file handle passed in no longer valid */
4842 /* Some legacy servers such as NT4 require that the file times be set on
4843 an open handle, rather than by pathname - this is awkward due to
4844 potential access conflicts on the open, but it is unavoidable for these
4845 old servers since the only other choice is to go from 100 nanosecond DCE
4846 time and resort to the original setpathinfo level which takes the ancient
4847 DOS time format with 2 second granularity */
4849 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4850 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4852 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4855 __u16 params, param_offset, offset, byte_count, count;
4857 cFYI(1, ("Set Times (via SetFileInfo)"));
4858 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4863 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4864 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4867 pSMB->MaxSetupCount = 0;
4871 pSMB->Reserved2 = 0;
4872 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4873 offset = param_offset + params;
4875 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4877 count = sizeof(FILE_BASIC_INFO);
4878 pSMB->MaxParameterCount = cpu_to_le16(2);
4879 /* BB find max SMB PDU from sess */
4880 pSMB->MaxDataCount = cpu_to_le16(1000);
4881 pSMB->SetupCount = 1;
4882 pSMB->Reserved3 = 0;
4883 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4884 byte_count = 3 /* pad */ + params + count;
4885 pSMB->DataCount = cpu_to_le16(count);
4886 pSMB->ParameterCount = cpu_to_le16(params);
4887 pSMB->TotalDataCount = pSMB->DataCount;
4888 pSMB->TotalParameterCount = pSMB->ParameterCount;
4889 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4890 pSMB->DataOffset = cpu_to_le16(offset);
4892 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4893 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4895 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4896 pSMB->Reserved4 = 0;
4897 pSMB->hdr.smb_buf_length += byte_count;
4898 pSMB->ByteCount = cpu_to_le16(byte_count);
4899 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4900 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4902 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4904 /* Note: On -EAGAIN error only caller can retry on handle based calls
4905 since file handle passed in no longer valid */
4911 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4912 bool delete_file, __u16 fid, __u32 pid_of_opener)
4914 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4917 __u16 params, param_offset, offset, byte_count, count;
4919 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4920 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4925 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4926 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4929 pSMB->MaxSetupCount = 0;
4933 pSMB->Reserved2 = 0;
4934 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4935 offset = param_offset + params;
4937 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4940 pSMB->MaxParameterCount = cpu_to_le16(2);
4941 /* BB find max SMB PDU from sess */
4942 pSMB->MaxDataCount = cpu_to_le16(1000);
4943 pSMB->SetupCount = 1;
4944 pSMB->Reserved3 = 0;
4945 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4946 byte_count = 3 /* pad */ + params + count;
4947 pSMB->DataCount = cpu_to_le16(count);
4948 pSMB->ParameterCount = cpu_to_le16(params);
4949 pSMB->TotalDataCount = pSMB->DataCount;
4950 pSMB->TotalParameterCount = pSMB->ParameterCount;
4951 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4952 pSMB->DataOffset = cpu_to_le16(offset);
4954 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4955 pSMB->Reserved4 = 0;
4956 pSMB->hdr.smb_buf_length += byte_count;
4957 pSMB->ByteCount = cpu_to_le16(byte_count);
4958 *data_offset = delete_file ? 1 : 0;
4959 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4961 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4967 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4968 const char *fileName, const FILE_BASIC_INFO *data,
4969 const struct nls_table *nls_codepage, int remap)
4971 TRANSACTION2_SPI_REQ *pSMB = NULL;
4972 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4975 int bytes_returned = 0;
4977 __u16 params, param_offset, offset, byte_count, count;
4979 cFYI(1, ("In SetTimes"));
4982 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4987 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4989 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4990 PATH_MAX, nls_codepage, remap);
4991 name_len++; /* trailing null */
4993 } else { /* BB improve the check for buffer overruns BB */
4994 name_len = strnlen(fileName, PATH_MAX);
4995 name_len++; /* trailing null */
4996 strncpy(pSMB->FileName, fileName, name_len);
4999 params = 6 + name_len;
5000 count = sizeof(FILE_BASIC_INFO);
5001 pSMB->MaxParameterCount = cpu_to_le16(2);
5002 /* BB find max SMB PDU from sess structure BB */
5003 pSMB->MaxDataCount = cpu_to_le16(1000);
5004 pSMB->MaxSetupCount = 0;
5008 pSMB->Reserved2 = 0;
5009 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5010 InformationLevel) - 4;
5011 offset = param_offset + params;
5012 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5013 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5014 pSMB->DataOffset = cpu_to_le16(offset);
5015 pSMB->SetupCount = 1;
5016 pSMB->Reserved3 = 0;
5017 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5018 byte_count = 3 /* pad */ + params + count;
5020 pSMB->DataCount = cpu_to_le16(count);
5021 pSMB->ParameterCount = cpu_to_le16(params);
5022 pSMB->TotalDataCount = pSMB->DataCount;
5023 pSMB->TotalParameterCount = pSMB->ParameterCount;
5024 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5025 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5027 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5028 pSMB->Reserved4 = 0;
5029 pSMB->hdr.smb_buf_length += byte_count;
5030 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5031 pSMB->ByteCount = cpu_to_le16(byte_count);
5032 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5033 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5035 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5037 cifs_buf_release(pSMB);
5045 /* Can not be used to set time stamps yet (due to old DOS time format) */
5046 /* Can be used to set attributes */
5047 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5048 handling it anyway and NT4 was what we thought it would be needed for
5049 Do not delete it until we prove whether needed for Win9x though */
5051 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5052 __u16 dos_attrs, const struct nls_table *nls_codepage)
5054 SETATTR_REQ *pSMB = NULL;
5055 SETATTR_RSP *pSMBr = NULL;
5060 cFYI(1, ("In SetAttrLegacy"));
5063 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5068 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5070 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5071 PATH_MAX, nls_codepage);
5072 name_len++; /* trailing null */
5074 } else { /* BB improve the check for buffer overruns BB */
5075 name_len = strnlen(fileName, PATH_MAX);
5076 name_len++; /* trailing null */
5077 strncpy(pSMB->fileName, fileName, name_len);
5079 pSMB->attr = cpu_to_le16(dos_attrs);
5080 pSMB->BufferFormat = 0x04;
5081 pSMB->hdr.smb_buf_length += name_len + 1;
5082 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5083 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5084 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5086 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5088 cifs_buf_release(pSMB);
5091 goto SetAttrLgcyRetry;
5095 #endif /* temporarily unneeded SetAttr legacy function */
5098 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5099 const struct cifs_unix_set_info_args *args,
5100 const struct nls_table *nls_codepage, int remap)
5102 TRANSACTION2_SPI_REQ *pSMB = NULL;
5103 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5106 int bytes_returned = 0;
5107 FILE_UNIX_BASIC_INFO *data_offset;
5108 __u16 params, param_offset, offset, count, byte_count;
5109 __u64 mode = args->mode;
5111 cFYI(1, ("In SetUID/GID/Mode"));
5113 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5118 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5120 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5121 PATH_MAX, nls_codepage, remap);
5122 name_len++; /* trailing null */
5124 } else { /* BB improve the check for buffer overruns BB */
5125 name_len = strnlen(fileName, PATH_MAX);
5126 name_len++; /* trailing null */
5127 strncpy(pSMB->FileName, fileName, name_len);
5130 params = 6 + name_len;
5131 count = sizeof(FILE_UNIX_BASIC_INFO);
5132 pSMB->MaxParameterCount = cpu_to_le16(2);
5133 /* BB find max SMB PDU from sess structure BB */
5134 pSMB->MaxDataCount = cpu_to_le16(1000);
5135 pSMB->MaxSetupCount = 0;
5139 pSMB->Reserved2 = 0;
5140 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5141 InformationLevel) - 4;
5142 offset = param_offset + params;
5144 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5146 memset(data_offset, 0, count);
5147 pSMB->DataOffset = cpu_to_le16(offset);
5148 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5149 pSMB->SetupCount = 1;
5150 pSMB->Reserved3 = 0;
5151 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5152 byte_count = 3 /* pad */ + params + count;
5153 pSMB->ParameterCount = cpu_to_le16(params);
5154 pSMB->DataCount = cpu_to_le16(count);
5155 pSMB->TotalParameterCount = pSMB->ParameterCount;
5156 pSMB->TotalDataCount = pSMB->DataCount;
5157 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5158 pSMB->Reserved4 = 0;
5159 pSMB->hdr.smb_buf_length += byte_count;
5160 /* Samba server ignores set of file size to zero due to bugs in some
5161 older clients, but we should be precise - we use SetFileSize to
5162 set file size and do not want to truncate file size to zero
5163 accidently as happened on one Samba server beta by putting
5164 zero instead of -1 here */
5165 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5166 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5167 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5168 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5169 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5170 data_offset->Uid = cpu_to_le64(args->uid);
5171 data_offset->Gid = cpu_to_le64(args->gid);
5172 /* better to leave device as zero when it is */
5173 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5174 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5175 data_offset->Permissions = cpu_to_le64(mode);
5178 data_offset->Type = cpu_to_le32(UNIX_FILE);
5179 else if (S_ISDIR(mode))
5180 data_offset->Type = cpu_to_le32(UNIX_DIR);
5181 else if (S_ISLNK(mode))
5182 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5183 else if (S_ISCHR(mode))
5184 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5185 else if (S_ISBLK(mode))
5186 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5187 else if (S_ISFIFO(mode))
5188 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5189 else if (S_ISSOCK(mode))
5190 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5193 pSMB->ByteCount = cpu_to_le16(byte_count);
5194 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5195 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5197 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5199 cifs_buf_release(pSMB);
5205 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5206 const int notify_subdirs, const __u16 netfid,
5207 __u32 filter, struct file *pfile, int multishot,
5208 const struct nls_table *nls_codepage)
5211 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5212 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5213 struct dir_notify_req *dnotify_req;
5216 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5217 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5222 pSMB->TotalParameterCount = 0 ;
5223 pSMB->TotalDataCount = 0;
5224 pSMB->MaxParameterCount = cpu_to_le32(2);
5225 /* BB find exact data count max from sess structure BB */
5226 pSMB->MaxDataCount = 0; /* same in little endian or be */
5227 /* BB VERIFY verify which is correct for above BB */
5228 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5229 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5231 pSMB->MaxSetupCount = 4;
5233 pSMB->ParameterOffset = 0;
5234 pSMB->DataCount = 0;
5235 pSMB->DataOffset = 0;
5236 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5237 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5238 pSMB->ParameterCount = pSMB->TotalParameterCount;
5240 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5241 pSMB->Reserved2 = 0;
5242 pSMB->CompletionFilter = cpu_to_le32(filter);
5243 pSMB->Fid = netfid; /* file handle always le */
5244 pSMB->ByteCount = 0;
5246 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5247 (struct smb_hdr *)pSMBr, &bytes_returned,
5250 cFYI(1, ("Error in Notify = %d", rc));
5252 /* Add file to outstanding requests */
5253 /* BB change to kmem cache alloc */
5254 dnotify_req = kmalloc(
5255 sizeof(struct dir_notify_req),
5258 dnotify_req->Pid = pSMB->hdr.Pid;
5259 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5260 dnotify_req->Mid = pSMB->hdr.Mid;
5261 dnotify_req->Tid = pSMB->hdr.Tid;
5262 dnotify_req->Uid = pSMB->hdr.Uid;
5263 dnotify_req->netfid = netfid;
5264 dnotify_req->pfile = pfile;
5265 dnotify_req->filter = filter;
5266 dnotify_req->multishot = multishot;
5267 spin_lock(&GlobalMid_Lock);
5268 list_add_tail(&dnotify_req->lhead,
5269 &GlobalDnotifyReqList);
5270 spin_unlock(&GlobalMid_Lock);
5274 cifs_buf_release(pSMB);
5277 #ifdef CONFIG_CIFS_XATTR
5279 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5280 const unsigned char *searchName,
5281 char *EAData, size_t buf_size,
5282 const struct nls_table *nls_codepage, int remap)
5284 /* BB assumes one setup word */
5285 TRANSACTION2_QPI_REQ *pSMB = NULL;
5286 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5290 struct fea *temp_fea;
5292 __u16 params, byte_count;
5294 cFYI(1, ("In Query All EAs path %s", searchName));
5296 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5301 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5303 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5304 PATH_MAX, nls_codepage, remap);
5305 name_len++; /* trailing null */
5307 } else { /* BB improve the check for buffer overruns BB */
5308 name_len = strnlen(searchName, PATH_MAX);
5309 name_len++; /* trailing null */
5310 strncpy(pSMB->FileName, searchName, name_len);
5313 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5314 pSMB->TotalDataCount = 0;
5315 pSMB->MaxParameterCount = cpu_to_le16(2);
5316 /* BB find exact max SMB PDU from sess structure BB */
5317 pSMB->MaxDataCount = cpu_to_le16(4000);
5318 pSMB->MaxSetupCount = 0;
5322 pSMB->Reserved2 = 0;
5323 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5324 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5325 pSMB->DataCount = 0;
5326 pSMB->DataOffset = 0;
5327 pSMB->SetupCount = 1;
5328 pSMB->Reserved3 = 0;
5329 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5330 byte_count = params + 1 /* pad */ ;
5331 pSMB->TotalParameterCount = cpu_to_le16(params);
5332 pSMB->ParameterCount = pSMB->TotalParameterCount;
5333 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5334 pSMB->Reserved4 = 0;
5335 pSMB->hdr.smb_buf_length += byte_count;
5336 pSMB->ByteCount = cpu_to_le16(byte_count);
5338 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5339 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5341 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5342 } else { /* decode response */
5343 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5345 /* BB also check enough total bytes returned */
5346 /* BB we need to improve the validity checking
5347 of these trans2 responses */
5348 if (rc || (pSMBr->ByteCount < 4))
5349 rc = -EIO; /* bad smb */
5350 /* else if (pFindData){
5351 memcpy((char *) pFindData,
5352 (char *) &pSMBr->hdr.Protocol +
5355 /* check that length of list is not more than bcc */
5356 /* check that each entry does not go beyond length
5358 /* check that each element of each entry does not
5359 go beyond end of list */
5360 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5361 struct fealist *ea_response_data;
5363 /* validate_trans2_offsets() */
5364 /* BB check if start of smb + data_offset > &bcc+ bcc */
5365 ea_response_data = (struct fealist *)
5366 (((char *) &pSMBr->hdr.Protocol) +
5368 name_len = le32_to_cpu(ea_response_data->list_len);
5369 cFYI(1, ("ea length %d", name_len));
5370 if (name_len <= 8) {
5371 /* returned EA size zeroed at top of function */
5372 cFYI(1, ("empty EA list returned from server"));
5374 /* account for ea list len */
5376 temp_fea = ea_response_data->list;
5377 temp_ptr = (char *)temp_fea;
5378 while (name_len > 0) {
5382 rc += temp_fea->name_len;
5383 /* account for prefix user. and trailing null */
5385 if (rc < (int)buf_size) {
5386 memcpy(EAData, "user.", 5);
5388 memcpy(EAData, temp_ptr,
5389 temp_fea->name_len);
5390 EAData += temp_fea->name_len;
5391 /* null terminate name */
5393 EAData = EAData + 1;
5394 } else if (buf_size == 0) {
5395 /* skip copy - calc size only */
5397 /* stop before overrun buffer */
5401 name_len -= temp_fea->name_len;
5402 temp_ptr += temp_fea->name_len;
5403 /* account for trailing null */
5407 le16_to_cpu(temp_fea->value_len);
5408 name_len -= value_len;
5409 temp_ptr += value_len;
5410 /* BB check that temp_ptr is still
5413 /* no trailing null to account for
5415 /* go on to next EA */
5416 temp_fea = (struct fea *)temp_ptr;
5421 cifs_buf_release(pSMB);
5428 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5429 const unsigned char *searchName, const unsigned char *ea_name,
5430 unsigned char *ea_value, size_t buf_size,
5431 const struct nls_table *nls_codepage, int remap)
5433 TRANSACTION2_QPI_REQ *pSMB = NULL;
5434 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5438 struct fea *temp_fea;
5440 __u16 params, byte_count;
5442 cFYI(1, ("In Query EA path %s", searchName));
5444 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5449 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5451 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5452 PATH_MAX, nls_codepage, remap);
5453 name_len++; /* trailing null */
5455 } else { /* BB improve the check for buffer overruns BB */
5456 name_len = strnlen(searchName, PATH_MAX);
5457 name_len++; /* trailing null */
5458 strncpy(pSMB->FileName, searchName, name_len);
5461 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5462 pSMB->TotalDataCount = 0;
5463 pSMB->MaxParameterCount = cpu_to_le16(2);
5464 /* BB find exact max SMB PDU from sess structure BB */
5465 pSMB->MaxDataCount = cpu_to_le16(4000);
5466 pSMB->MaxSetupCount = 0;
5470 pSMB->Reserved2 = 0;
5471 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5472 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5473 pSMB->DataCount = 0;
5474 pSMB->DataOffset = 0;
5475 pSMB->SetupCount = 1;
5476 pSMB->Reserved3 = 0;
5477 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5478 byte_count = params + 1 /* pad */ ;
5479 pSMB->TotalParameterCount = cpu_to_le16(params);
5480 pSMB->ParameterCount = pSMB->TotalParameterCount;
5481 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5482 pSMB->Reserved4 = 0;
5483 pSMB->hdr.smb_buf_length += byte_count;
5484 pSMB->ByteCount = cpu_to_le16(byte_count);
5486 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5487 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5489 cFYI(1, ("Send error in Query EA = %d", rc));
5490 } else { /* decode response */
5491 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5493 /* BB also check enough total bytes returned */
5494 /* BB we need to improve the validity checking
5495 of these trans2 responses */
5496 if (rc || (pSMBr->ByteCount < 4))
5497 rc = -EIO; /* bad smb */
5498 /* else if (pFindData){
5499 memcpy((char *) pFindData,
5500 (char *) &pSMBr->hdr.Protocol +
5503 /* check that length of list is not more than bcc */
5504 /* check that each entry does not go beyond length
5506 /* check that each element of each entry does not
5507 go beyond end of list */
5508 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5509 struct fealist *ea_response_data;
5511 /* validate_trans2_offsets() */
5512 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5513 ea_response_data = (struct fealist *)
5514 (((char *) &pSMBr->hdr.Protocol) +
5516 name_len = le32_to_cpu(ea_response_data->list_len);
5517 cFYI(1, ("ea length %d", name_len));
5518 if (name_len <= 8) {
5519 /* returned EA size zeroed at top of function */
5520 cFYI(1, ("empty EA list returned from server"));
5522 /* account for ea list len */
5524 temp_fea = ea_response_data->list;
5525 temp_ptr = (char *)temp_fea;
5526 /* loop through checking if we have a matching
5527 name and then return the associated value */
5528 while (name_len > 0) {
5533 le16_to_cpu(temp_fea->value_len);
5534 /* BB validate that value_len falls within SMB,
5535 even though maximum for name_len is 255 */
5536 if (memcmp(temp_fea->name, ea_name,
5537 temp_fea->name_len) == 0) {
5540 /* account for prefix user. and trailing null */
5541 if (rc <= (int)buf_size) {
5543 temp_fea->name+temp_fea->name_len+1,
5545 /* ea values, unlike ea
5548 } else if (buf_size == 0) {
5549 /* skip copy - calc size only */
5551 /* stop before overrun buffer */
5556 name_len -= temp_fea->name_len;
5557 temp_ptr += temp_fea->name_len;
5558 /* account for trailing null */
5561 name_len -= value_len;
5562 temp_ptr += value_len;
5563 /* No trailing null to account for in
5564 value_len. Go on to next EA */
5565 temp_fea = (struct fea *)temp_ptr;
5570 cifs_buf_release(pSMB);
5578 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5579 const char *ea_name, const void *ea_value,
5580 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5583 struct smb_com_transaction2_spi_req *pSMB = NULL;
5584 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5585 struct fealist *parm_data;
5588 int bytes_returned = 0;
5589 __u16 params, param_offset, byte_count, offset, count;
5591 cFYI(1, ("In SetEA"));
5593 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5598 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5600 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5601 PATH_MAX, nls_codepage, remap);
5602 name_len++; /* trailing null */
5604 } else { /* BB improve the check for buffer overruns BB */
5605 name_len = strnlen(fileName, PATH_MAX);
5606 name_len++; /* trailing null */
5607 strncpy(pSMB->FileName, fileName, name_len);
5610 params = 6 + name_len;
5612 /* done calculating parms using name_len of file name,
5613 now use name_len to calculate length of ea name
5614 we are going to create in the inode xattrs */
5615 if (ea_name == NULL)
5618 name_len = strnlen(ea_name, 255);
5620 count = sizeof(*parm_data) + ea_value_len + name_len;
5621 pSMB->MaxParameterCount = cpu_to_le16(2);
5622 /* BB find max SMB PDU from sess */
5623 pSMB->MaxDataCount = cpu_to_le16(1000);
5624 pSMB->MaxSetupCount = 0;
5628 pSMB->Reserved2 = 0;
5629 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5630 InformationLevel) - 4;
5631 offset = param_offset + params;
5632 pSMB->InformationLevel =
5633 cpu_to_le16(SMB_SET_FILE_EA);
5636 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5638 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5639 pSMB->DataOffset = cpu_to_le16(offset);
5640 pSMB->SetupCount = 1;
5641 pSMB->Reserved3 = 0;
5642 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5643 byte_count = 3 /* pad */ + params + count;
5644 pSMB->DataCount = cpu_to_le16(count);
5645 parm_data->list_len = cpu_to_le32(count);
5646 parm_data->list[0].EA_flags = 0;
5647 /* we checked above that name len is less than 255 */
5648 parm_data->list[0].name_len = (__u8)name_len;
5649 /* EA names are always ASCII */
5651 strncpy(parm_data->list[0].name, ea_name, name_len);
5652 parm_data->list[0].name[name_len] = 0;
5653 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5654 /* caller ensures that ea_value_len is less than 64K but
5655 we need to ensure that it fits within the smb */
5657 /*BB add length check to see if it would fit in
5658 negotiated SMB buffer size BB */
5659 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5661 memcpy(parm_data->list[0].name+name_len+1,
5662 ea_value, ea_value_len);
5664 pSMB->TotalDataCount = pSMB->DataCount;
5665 pSMB->ParameterCount = cpu_to_le16(params);
5666 pSMB->TotalParameterCount = pSMB->ParameterCount;
5667 pSMB->Reserved4 = 0;
5668 pSMB->hdr.smb_buf_length += byte_count;
5669 pSMB->ByteCount = cpu_to_le16(byte_count);
5670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5673 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5675 cifs_buf_release(pSMB);